Skip to content

Commit

Permalink
feat(node): support deposit for stub settlement module
Browse files Browse the repository at this point in the history
  • Loading branch information
justmoon committed Nov 27, 2023
1 parent f9dac14 commit beceaf5
Show file tree
Hide file tree
Showing 9 changed files with 186 additions and 4 deletions.
14 changes: 13 additions & 1 deletion packages/app-node/src/backend/settlement-schemes/modules/stub.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,11 @@ const stub = {
behavior: ({ host }) => {
let balance = INITIAL_BALANCE

host.reportOnLedgerBalance({ ledgerId: ledger.id, balance })
const reportBalance = () => {
host.reportOnLedgerBalance({ ledgerId: ledger.id, balance })
}

reportBalance()

return {
getPeeringInfo: () => {
Expand Down Expand Up @@ -63,6 +67,7 @@ const stub = {
logger.info(`Sending settlement for ${amount} units to ${peerId}`)

balance -= amount
reportBalance()

return {
proof: new Uint8Array(),
Expand All @@ -72,6 +77,7 @@ const stub = {
logger.info(`Received settlement for ${amount} units from ${peerId}`)

balance += amount
reportBalance()

return {
result: "accept" as const,
Expand All @@ -80,6 +86,12 @@ const stub = {
handleMessage: () => {
// no-op
},
handleDeposit: ({ amount }) => {
logger.info(`Received deposit for ${amount} units`)

balance += amount
reportBalance()
},
}
},
} satisfies SettlementSchemeModule<object>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,9 @@ const xrplTestnet = {
handleMessage: () => {
// no-op
},
handleDeposit: () => {
throw new Error("not implemented")
},
}
},
} satisfies SettlementSchemeModule<XrplPeerState>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { z } from "zod"

import { trpc } from "../../local-ipc-server/trpc-context"
import { SettlementSchemeId } from "../../peer-protocol/types/settlement-scheme-id"
import { protectedProcedure } from "../../trpc-server/middlewares/auth"
import { ManageSettlementSchemeInstancesActor } from "../manage-settlement-scheme-instances"

export const settlementRouter = trpc.router({
stubDeposit: protectedProcedure
.input(z.string())
.mutation(async ({ input: amount, ctx: { sig } }) => {
const manageSettlementSchemeInstancesActor = sig.reactor.use(
ManageSettlementSchemeInstancesActor,
)

const stubActor = manageSettlementSchemeInstancesActor.get(
"stub" as SettlementSchemeId,
)

if (!stubActor) {
throw new Error("Stub settlement scheme is not enabled")
}

await stubActor.api.handleDeposit.ask({ amount: BigInt(amount) })

return true
}),
})
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,11 @@ export interface SettlementSchemeActorMethods<
peerId: NodeId
message: Uint8Array
}) => Promisable<void>

/**
* Process an incoming deposit by the owner.
*/
handleDeposit: (parameters: { amount: bigint }) => Promisable<void>
}

export interface SettlementSchemeBehaviorParameters {
Expand Down
2 changes: 2 additions & 0 deletions packages/app-node/src/backend/trpc-server/app-router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { acmeRouter } from "../acme-certificate-manager/trpc-routers/acme"
import { apiKeysRouter } from "../api-keys/trpc-routers/api-keys"
import { configAdminRouter } from "../config/trpc-routers/config-admin"
import { tlsAdminRouter } from "../http-server/trpc-routers/tls-admin"
import { settlementRouter } from "../settlement-schemes/trpc-routers/settlement"
import { debugRouter } from "./routers/debug"
import { generalRouter } from "./routers/general"
import { paymentRouter } from "./routers/payment"
Expand All @@ -15,6 +16,7 @@ export const appRouter = trpc.router({
tls: tlsAdminRouter,
config: configAdminRouter,
apiKeys: apiKeysRouter,
settlement: settlementRouter,
})

export type AppRouter = typeof appRouter
2 changes: 2 additions & 0 deletions packages/app-node/src/frontend/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { Routing } from "./pages/debug/routing/routing"
import { State } from "./pages/debug/state/state"
import { LoginPage } from "./pages/login/login"
import { PaymentStatus } from "./pages/payment-status/payment-status"
import { ReceivePage } from "./pages/receive/receive"
import { Send } from "./pages/send/send"
import { Settings } from "./pages/settings/settings"
import { Setup } from "./pages/setup/setup"
Expand Down Expand Up @@ -45,6 +46,7 @@ const App = () => {
<MainNavigation />
<Switch>
<Route path="/send" component={Send} />
<Route path="/receive" component={ReceivePage} />
<Route path="/payments/:paymentId" component={PaymentStatus} />
<Route path="/debug/ledger" component={Ledger} />
<Route path="/debug/nodes" component={Nodes} />
Expand Down
17 changes: 14 additions & 3 deletions packages/app-node/src/frontend/pages/account/account.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { DownloadIcon, UploadIcon } from "lucide-react"
import { Link } from "wouter"

import { Amount } from "../../components/amount/amount"
Expand Down Expand Up @@ -35,9 +36,19 @@ export const Account = () => {
</div>
</CardContent>
</Card>
<Link href="/send">
<Button>Send</Button>
</Link>
<div className="flex flex-row space-x-2">
<Link href="/send">
<Button>
<UploadIcon className="h-4 w-4 mr-2" />
Send
</Button>
</Link>
<Link href="/receive">
<Button>
<DownloadIcon className="h-4 w-4 mr-2" /> Receive
</Button>
</Link>
</div>
</div>
)
}
91 changes: 91 additions & 0 deletions packages/app-node/src/frontend/pages/receive/receive.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import { ComponentType, LazyExoticComponent, Suspense, lazy } from "react"
import { Link } from "wouter"

import { SettlementSchemeId } from "../../../backend/peer-protocol/types/settlement-scheme-id"
import { Button } from "../../components/ui/button"
import {
Card,
CardContent,
CardFooter,
CardHeader,
CardTitle,
} from "../../components/ui/card"
import {
Tabs,
TabsContent,
TabsList,
TabsTrigger,
} from "../../components/ui/tabs"
import { trpc } from "../../utils/trpc"

const SCHEME_DEPOSIT_NAME_MAP: Record<SettlementSchemeId, string> = {
["stub" as SettlementSchemeId]: "Stub",
}

const SCHEME_DEPOSIT_UI_MAP: Record<
SettlementSchemeId,
LazyExoticComponent<ComponentType>
> = {
["stub" as SettlementSchemeId]: lazy(
() => import("./settlement-schemes/stub"),
),
}

export function ReceivePage() {
const basicState = trpc.general.getBasicState.useQuery()

const activeSettlementSchemes = basicState.data?.activeSettlementSchemes ?? []

return (
<div className="flex h-full items-center justify-center">
<Card>
<CardHeader>
<CardTitle className="flex-grow flex-shrink-0 basis-auto font-bold text-lg md:text-xl">
Receive
</CardTitle>
</CardHeader>
<CardContent>
<Tabs defaultValue="interledger">
<TabsList>
<TabsTrigger value="interledger">Interledger</TabsTrigger>
{activeSettlementSchemes.map((schemeId) =>
SCHEME_DEPOSIT_NAME_MAP[schemeId] ? (
<TabsTrigger key={schemeId} value={schemeId}>
{SCHEME_DEPOSIT_NAME_MAP[schemeId]}
</TabsTrigger>
) : null,
)}
</TabsList>
<TabsContent value="interledger">
<p>Send money to the following payment pointer:</p>
<div className="text-lg font-bold border rounded-lg p-4 mt-4">
{basicState.data ? `$${basicState.data.hostname}` : "???"}
</div>
</TabsContent>

{activeSettlementSchemes.map((schemeId) => {
const Component = SCHEME_DEPOSIT_UI_MAP[schemeId]

if (!Component) {
return null
}

return (
<TabsContent key={schemeId} value={schemeId}>
<Suspense fallback={<div>Loading...</div>}>
<Component />
</Suspense>
</TabsContent>
)
})}
</Tabs>
</CardContent>
<CardFooter>
<Link href="/">
<Button variant="ghost">Back</Button>
</Link>
</CardFooter>
</Card>
</div>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { useLocation } from "wouter"

import { Button } from "../../../components/ui/button"
import { trpc } from "../../../utils/trpc"

export default function StubDeposit() {
const stubDepositMutation = trpc.settlement.stubDeposit.useMutation()
const [, setLocation] = useLocation()

return (
<div>
<p>
The &quot;stub&quot; settlement method only simulates a ledger rather
than using a real one. You can click the button below to simulate
receiving funds on the underlying ledger.
</p>
<Button
className="mt-4"
onClick={() => {
stubDepositMutation.mutate("100000000000")
setLocation("/")
}}
>
Receive $100
</Button>
</div>
)
}

0 comments on commit beceaf5

Please sign in to comment.