add address fetching

This commit is contained in:
Paul Miller
2023-04-06 11:21:58 -05:00
parent d5c7f2a0d6
commit 3291885a5a
9 changed files with 98 additions and 39 deletions

View File

@@ -1,7 +1,9 @@
import { Motion, Presence } from "@motionone/solid"; import { Motion, Presence } from "@motionone/solid";
import { MutinyBalance } from "@mutinywallet/node-manager"; import { MutinyBalance } from "@mutinywallet/node-manager";
import { createResource, Show } from "solid-js";
import { useNodeManager } from "~/state/nodeManagerState"; import { useNodeManager } from "~/state/nodeManagerState";
import { ButtonLink } from "./Button";
function prettyPrintAmount(n?: number | bigint): string { function prettyPrintAmount(n?: number | bigint): string {
if (!n || n.valueOf() === 0) { if (!n || n.valueOf() === 0) {
@@ -15,7 +17,15 @@ function prettyPrintBalance(b: MutinyBalance): string {
} }
export default function BalanceBox() { export default function BalanceBox() {
const { balance, refetchBalance } = useNodeManager(); const { nodeManager } = useNodeManager();
const fetchBalance = async () => {
console.log("Refetching balance");
const balance = await nodeManager()?.get_balance();
return balance
};
const [balance, { refetch: refetchBalance }] = createResource(nodeManager, fetchBalance);
return ( return (
<Presence> <Presence>
@@ -31,12 +41,15 @@ export default function BalanceBox() {
</header> </header>
<div onClick={refetchBalance}> <div onClick={refetchBalance}>
<h1 class='text-4xl font-light'> <h1 class='text-4xl font-light'>
{balance() && prettyPrintBalance(balance())} <span class='text-xl'>SAT</span> <Show when={balance()}>
{/* TODO: no-non-null-asssertion but type narrowing just isn't working */}
{prettyPrintBalance(balance()!)} <span class='text-xl'>SAT</span>
</Show>
</h1> </h1>
</div> </div>
<div class="flex gap-2 py-4"> <div class="flex gap-2 py-4">
<button class='bg-[#1EA67F] p-4 flex-1 rounded-xl text-xl font-semibold '><span class="drop-shadow-sm shadow-black">Send</span></button> <ButtonLink href="/scanner" intent="green">Send</ButtonLink>
<button class='bg-[#3B6CCC] p-4 flex-1 rounded-xl text-xl font-semibold '><span class="drop-shadow-sm shadow-black">Receive</span></button> <ButtonLink href="/receive" intent="blue">Receive</ButtonLink>
</div> </div>
</div> </div>
</Motion> </Motion>

View File

@@ -1,5 +1,6 @@
import { cva, VariantProps } from "class-variance-authority"; import { cva, VariantProps } from "class-variance-authority";
import { children, JSX, ParentComponent, splitProps } from "solid-js"; import { children, JSX, ParentComponent, splitProps } from "solid-js";
import { A } from "solid-start";
const button = cva(["p-4", "rounded-xl", "text-xl", "font-semibold"], { const button = cva(["p-4", "rounded-xl", "text-xl", "font-semibold"], {
variants: { variants: {
@@ -7,7 +8,8 @@ const button = cva(["p-4", "rounded-xl", "text-xl", "font-semibold"], {
active: "bg-white text-black", active: "bg-white text-black",
inactive: "bg-black text-white border border-white", inactive: "bg-black text-white border border-white",
blue: "bg-[#3B6CCC] text-white", blue: "bg-[#3B6CCC] text-white",
red: "bg-[#F61D5B] text-white" red: "bg-[#F61D5B] text-white",
green: "bg-[#1EA67F] text-white",
}, },
layout: { layout: {
flex: "flex-1", flex: "flex-1",
@@ -43,4 +45,27 @@ export const Button: ParentComponent<ButtonProps> = props => {
{slot()} {slot()}
</button> </button>
) )
}
interface ButtonLinkProps extends JSX.ButtonHTMLAttributes<HTMLAnchorElement>, StyleProps {
href: string
}
export const ButtonLink: ParentComponent<ButtonLinkProps> = props => {
const slot = children(() => props.children)
const [local, attrs] = splitProps(props, ['children', 'intent', 'layout', 'class', 'href'])
return (
<A
href={local.href}
{...attrs}
class={button({
class: local.class || "",
intent: local.intent,
layout: local.layout,
})}
>
{slot()}
</A>
)
} }

View File

@@ -4,14 +4,16 @@ import settings from '~/assets/icons/settings.svg';
import { A } from "solid-start"; import { A } from "solid-start";
type ActiveTab = 'home' | 'scan' | 'settings'; type ActiveTab = 'home' | 'scan' | 'settings' | 'none';
export default function NavBar(props: { activeTab: ActiveTab }) { export default function NavBar(props: { activeTab: ActiveTab }) {
const activeStyle = 'h-full border-t-2 border-b-2 border-b-black flex flex-col justify-center' const activeStyle = 'h-full border-t-2 border-b-2 border-b-black flex flex-col justify-center'
return (<nav class='bg-black fixed bottom-0 shadow-lg z-40 w-full safe-bottom'> return (<nav class='bg-black fixed bottom-0 shadow-lg z-40 w-full safe-bottom'>
<ul class='h-16 flex justify-between px-16 items-center'> <ul class='h-16 flex justify-between px-16 items-center'>
<li class={props.activeTab === "home" ? activeStyle : ""}> <li class={props.activeTab === "home" ? activeStyle : ""}>
<img src={mutiny_m} alt="home" /> <A href="/">
<img src={mutiny_m} alt="home" />
</A>
</li> </li>
<li class={props.activeTab === "scan" ? activeStyle : ""}> <li class={props.activeTab === "scan" ? activeStyle : ""}>
<A href="/scanner"> <A href="/scanner">

View File

@@ -52,12 +52,12 @@ export async function checkForWasm() {
} }
} }
export async function setupNodeManager(settings?: NodeManagerSettingStrings): Promise<NodeManager> { export async function setupNodeManager(): Promise<NodeManager> {
const _ = await init(); const _ = await init();
console.time("Setup"); console.time("Setup");
console.log("Starting setup...") console.log("Starting setup...")
const { network, proxy, esplora } = await setAndGetMutinySettings(settings) const { network, proxy, esplora } = await setAndGetMutinySettings()
console.log("Initializing Node Manager") console.log("Initializing Node Manager")
console.log("Using network", network); console.log("Using network", network);
console.log("Using proxy", proxy); console.log("Using proxy", proxy);

View File

@@ -13,6 +13,7 @@ import {
Title, Title,
} from "solid-start"; } from "solid-start";
import "./root.css"; import "./root.css";
import { NodeManagerProvider } from "./state/nodeManagerState";
export default function Root() { export default function Root() {
return ( return (
@@ -34,9 +35,11 @@ export default function Root() {
<Body> <Body>
<Suspense> <Suspense>
<ErrorBoundary> <ErrorBoundary>
<Routes> <NodeManagerProvider>
<FileRoutes /> <Routes>
</Routes> <FileRoutes />
</Routes>
</NodeManagerProvider>
</ErrorBoundary> </ErrorBoundary>
</Suspense> </Suspense>
<Scripts /> <Scripts />

31
src/routes/Receive.tsx Normal file
View File

@@ -0,0 +1,31 @@
import { createResource, Show } from "solid-js";
import { Button } from "~/components/Button";
import NavBar from "~/components/NavBar";
import SafeArea from "~/components/SafeArea";
import { useNodeManager } from "~/state/nodeManagerState";
export default function Receive() {
const { nodeManager } = useNodeManager();
// TODO: would be nice if this was just newest unused address
const getNewAddress = async () => {
console.log("Getting new address");
const address = await nodeManager()?.get_new_address();
return address
};
const [address, { refetch: refetchAddress }] = createResource(nodeManager, getNewAddress);
return (
<SafeArea>
<main class='flex flex-col gap-4 py-8 px-4'>
<Show when={address()}>
<h1>{address()}</h1>
<Button onClick={refetchAddress}>Get new address</Button>
</Show>
</main>
<NavBar activeTab="none" />
</SafeArea>
)
}

View File

@@ -35,9 +35,7 @@ export default function Home() {
<ReloadPrompt /> <ReloadPrompt />
<Switch fallback={<>Loading...</>} > <Switch fallback={<>Loading...</>} >
<Match when={waitlistData() && waitlistData().approval_date}> <Match when={waitlistData() && waitlistData().approval_date}>
<NodeManagerProvider> <App />
<App />
</NodeManagerProvider>
</Match> </Match>
<Match when={waitlistData() && waitlistData().date}> <Match when={waitlistData() && waitlistData().date}>
<WaitlistAlreadyIn /> <WaitlistAlreadyIn />

View File

@@ -1,10 +0,0 @@
import { Outlet } from "solid-start";
export default function UsersLayout() {
return (
<div>
<h1>Users</h1>
<Outlet />
</div>
);
}

View File

@@ -1,24 +1,14 @@
import { NodeManager } from "@mutinywallet/node-manager"; import { NodeManager } from "@mutinywallet/node-manager";
import { createContext, JSX, useContext, createResource } from "solid-js"; import { createContext, JSX, useContext, createResource, Resource } from "solid-js";
import { setupNodeManager } from "~/logic/nodeManagerSetup"; import { setupNodeManager } from "~/logic/nodeManagerSetup";
const NodeManagerContext = createContext(); const NodeManagerContext = createContext<{ nodeManager: Resource<NodeManager> }>();
export function NodeManagerProvider(props: { children: JSX.Element }) { export function NodeManagerProvider(props: { children: JSX.Element }) {
const [nodeManager] = createResource({}, setupNodeManager); const [nodeManager] = createResource(setupNodeManager);
const fetchBalance = async (nm: NodeManager) => {
console.log("refetching balance");
const balance = await nm.get_balance();
return balance
};
const [balance, { refetch }] = createResource(nodeManager, fetchBalance);
const value = { const value = {
nodeManager, nodeManager,
balance,
refetchBalance: refetch
}; };
return ( return (
@@ -28,4 +18,11 @@ export function NodeManagerProvider(props: { children: JSX.Element }) {
) )
} }
export function useNodeManager() { return useContext(NodeManagerContext); } export function useNodeManager() {
// This is a trick to narrow the typescript types: https://docs.solidjs.com/references/api-reference/component-apis/createContext
const context = useContext(NodeManagerContext);
if (!context) {
throw new Error("useNodeManager: cannot find a NodeManagerContext")
}
return context;
}