From 59bda84986b606f8c554b10ad33fbc1c06f61bab Mon Sep 17 00:00:00 2001 From: Nicolas Burtey Date: Thu, 21 Sep 2023 21:20:35 +0100 Subject: [PATCH] chore: expose basic webpage for card --- apps/boltcard/TODO.txt | 2 + apps/boltcard/app/api/card/id/[id]/route.ts | 4 +- .../api/card/id/[id]/transactions/route.ts | 2 +- apps/boltcard/app/api/card/uid/[uid]/route.ts | 4 +- apps/boltcard/app/api/createboltcard/route.ts | 4 +- apps/boltcard/app/api/ln/route.ts | 176 ++++++++++-------- apps/boltcard/app/api/new/route.ts | 4 +- apps/boltcard/app/card/[id]/page.tsx | 68 ++++++- apps/boltcard/bun.lockb | Bin 298285 -> 298609 bytes apps/boltcard/package.json | 2 +- apps/boltcard/services/config.ts | 2 +- apps/boltcard/services/db/card.ts | 16 ++ 12 files changed, 191 insertions(+), 93 deletions(-) diff --git a/apps/boltcard/TODO.txt b/apps/boltcard/TODO.txt index a3d2c79c2dc..df0c3c92990 100644 --- a/apps/boltcard/TODO.txt +++ b/apps/boltcard/TODO.txt @@ -4,3 +4,5 @@ - Tilt setup - verify writing card do the callback/creation of Card entity - open telemetry + +- add lnurl / lightning address / invoice diff --git a/apps/boltcard/app/api/card/id/[id]/route.ts b/apps/boltcard/app/api/card/id/[id]/route.ts index 427fba6bf85..0a3e249c3ad 100644 --- a/apps/boltcard/app/api/card/id/[id]/route.ts +++ b/apps/boltcard/app/api/card/id/[id]/route.ts @@ -1,10 +1,10 @@ import { NextRequest, NextResponse } from "next/server" -import { fetchByCardId } from "@/services/db/card" +import { fetchPublicByCardId } from "@/services/db/card" export async function GET(req: NextRequest, { params }: { params: { id: string } }) { const id = params.id - const card = await fetchByCardId(id) + const card = await fetchPublicByCardId(id) if (!card) { return NextResponse.json( { status: "ERROR", reason: "card not found" }, diff --git a/apps/boltcard/app/api/card/id/[id]/transactions/route.ts b/apps/boltcard/app/api/card/id/[id]/transactions/route.ts index f91fb31c370..f530e7d582c 100644 --- a/apps/boltcard/app/api/card/id/[id]/transactions/route.ts +++ b/apps/boltcard/app/api/card/id/[id]/transactions/route.ts @@ -2,9 +2,9 @@ import { NextRequest, NextResponse } from "next/server" import { gql } from "@apollo/client" -import { fetchByCardId } from "@/services/db/card" import { apollo } from "@/services/core" import { TransactionsDocument, TransactionsQuery } from "@/services/core/generated" +import { fetchByCardId } from "@/services/db/card" gql` query transactions($first: Int, $after: String) { diff --git a/apps/boltcard/app/api/card/uid/[uid]/route.ts b/apps/boltcard/app/api/card/uid/[uid]/route.ts index 629ab550513..f66bfc297e5 100644 --- a/apps/boltcard/app/api/card/uid/[uid]/route.ts +++ b/apps/boltcard/app/api/card/uid/[uid]/route.ts @@ -1,10 +1,10 @@ import { NextRequest, NextResponse } from "next/server" -import { fetchByUid } from "@/services/db/card" +import { fetchPublicByCardUid } from "@/services/db/card" export async function GET(req: NextRequest, { params }: { params: { uid: string } }) { const uid = params.uid - const card = await fetchByUid(uid) + const card = await fetchPublicByCardUid(uid) if (!card) { return NextResponse.json( { status: "ERROR", reason: "card not found" }, diff --git a/apps/boltcard/app/api/createboltcard/route.ts b/apps/boltcard/app/api/createboltcard/route.ts index 58eaa32b89d..42952a571dc 100644 --- a/apps/boltcard/app/api/createboltcard/route.ts +++ b/apps/boltcard/app/api/createboltcard/route.ts @@ -3,7 +3,7 @@ import { randomBytes } from "crypto" import { NextRequest, NextResponse } from "next/server" import { createCardInit } from "@/services/db/card-init" -import { serverUrl } from "@/services/config" +import { serverApi } from "@/services/config" const randomHex = (): string => randomBytes(16).toString("hex") @@ -45,7 +45,7 @@ export async function GET(req: NextRequest) { ) } - const url = `${serverUrl}/new?a=${oneTimeCode}` + const url = `${serverApi}/new?a=${oneTimeCode}` return NextResponse.json({ status: "OK", url, diff --git a/apps/boltcard/app/api/ln/route.ts b/apps/boltcard/app/api/ln/route.ts index 51888955bf0..881fe278b2b 100644 --- a/apps/boltcard/app/api/ln/route.ts +++ b/apps/boltcard/app/api/ln/route.ts @@ -4,7 +4,7 @@ import { NextRequest, NextResponse } from "next/server" import { ApolloQueryResult, gql } from "@apollo/client" -import { aesDecryptKey, serverUrl } from "@/services/config" +import { aesDecryptKey, serverApi } from "@/services/config" import { aesDecrypt, checkSignature } from "@/services/crypto/aes" import { decodePToUidCtr } from "@/services/crypto/decoder" import { createCard, fetchByUid } from "@/services/db/card" @@ -98,6 +98,96 @@ const maybeSetupCard = async ({ return null } +const setupCard = async ({ + cardInit, + uid, + ctr, +}: { + cardInit: CardInitInput + uid: string + ctr: number +}): Promise => { + const { k0AuthKey, k2CmacKey, k3, k4, token } = cardInit + + const client = apollo(token).getClient() + + let data: ApolloQueryResult + try { + data = await client.query({ + query: GetUsdWalletIdDocument, + }) + } catch (error) { + console.error(error) + return NextResponse.json( + { status: "ERROR", reason: "issue fetching walletId" }, + { status: 400 }, + ) + } + + const accountId = data.data?.me?.defaultAccount?.id + if (!accountId) { + return NextResponse.json( + { status: "ERROR", reason: "no accountId found" }, + { status: 400 }, + ) + } + + const wallets = data.data?.me?.defaultAccount.wallets + + if (!wallets) { + return NextResponse.json( + { status: "ERROR", reason: "no wallets found" }, + { status: 400 }, + ) + } + + const usdWallet = wallets.find((wallet) => wallet.walletCurrency === "USD") + const walletId = usdWallet?.id + + console.log({ usdWallet, wallets }) + + if (!walletId) { + return NextResponse.json( + { status: "ERROR", reason: "no usd wallet found" }, + { status: 400 }, + ) + } + + const dataOnchain = await client.mutate({ + mutation: OnChainAddressCurrentDocument, + variables: { input: { walletId } }, + }) + const onchainAddress = dataOnchain.data?.onChainAddressCurrent?.address + if (!onchainAddress) { + console.log(dataOnchain.data?.onChainAddressCurrent, "dataOnchain") + return NextResponse.json( + { status: "ERROR", reason: `onchain address not found` }, + { status: 400 }, + ) + } + + const id = generateReadableCode(12) + console.log({ id, onchainAddress }, "new card id") + + await markCardInitAsUsed(k2CmacKey) + + const card = await createCard({ + id, + uid, + k0AuthKey, + k2CmacKey, + k3, + k4, + ctr, + token, + accountId, + onchainAddress, + walletId, + }) + + return card +} + gql` query getUsdWalletId { me { @@ -159,86 +249,14 @@ export async function GET(req: NextRequest) { let card = await fetchByUid(uid) if (!card) { - const result = await maybeSetupCard({ uidRaw, ctrRawInverseBytes, ba_c }) - - if (result) { - const { k0AuthKey, k2CmacKey, k3, k4, token } = result - - const client = apollo(token).getClient() - - let data: ApolloQueryResult - try { - data = await client.query({ - query: GetUsdWalletIdDocument, - }) - } catch (error) { - console.error(error) - return NextResponse.json( - { status: "ERROR", reason: "issue fetching walletId" }, - { status: 400 }, - ) - } - - const accountId = data.data?.me?.defaultAccount?.id - if (!accountId) { - return NextResponse.json( - { status: "ERROR", reason: "no accountId found" }, - { status: 400 }, - ) - } + const cardInit = await maybeSetupCard({ uidRaw, ctrRawInverseBytes, ba_c }) - const wallets = data.data?.me?.defaultAccount.wallets + if (cardInit) { + card = await setupCard({ cardInit, uid, ctr }) - if (!wallets) { - return NextResponse.json( - { status: "ERROR", reason: "no wallets found" }, - { status: 400 }, - ) + if (card instanceof NextResponse) { + return card } - - const usdWallet = wallets.find((wallet) => wallet.walletCurrency === "USD") - const walletId = usdWallet?.id - - console.log({ usdWallet, wallets }) - - if (!walletId) { - return NextResponse.json( - { status: "ERROR", reason: "no usd wallet found" }, - { status: 400 }, - ) - } - - const dataOnchain = await client.mutate({ - mutation: OnChainAddressCurrentDocument, - variables: { input: { walletId } }, - }) - const onchainAddress = dataOnchain.data?.onChainAddressCurrent?.address - if (!onchainAddress) { - console.log(dataOnchain.data?.onChainAddressCurrent, "dataOnchain") - return NextResponse.json( - { status: "ERROR", reason: `onchain address not found` }, - { status: 400 }, - ) - } - - const id = generateReadableCode(12) - console.log({ id, onchainAddress }, "new card id") - - await markCardInitAsUsed(k2CmacKey) - - card = await createCard({ - id, - uid, - k0AuthKey, - k2CmacKey, - k3, - k4, - ctr, - token, - accountId, - onchainAddress, - walletId, - }) } else { return NextResponse.json( { status: "ERROR", reason: "card not found" }, @@ -270,7 +288,7 @@ export async function GET(req: NextRequest) { return NextResponse.json({ tag: "withdrawRequest", - callback: serverUrl + "/callback", + callback: serverApi + "/callback", k1, defaultDescription: "payment for a blink card", minWithdrawable: 1000, diff --git a/apps/boltcard/app/api/new/route.ts b/apps/boltcard/app/api/new/route.ts index ce619b697e8..d5e02b2ae47 100644 --- a/apps/boltcard/app/api/new/route.ts +++ b/apps/boltcard/app/api/new/route.ts @@ -1,6 +1,6 @@ import { NextRequest, NextResponse } from "next/server" -import { aesDecryptKey, serverUrl } from "@/services/config" +import { aesDecryptKey, serverApi } from "@/services/config" import { fetchByOneTimeCode } from "@/services/db/card-init" interface NewCardResponse { @@ -43,7 +43,7 @@ export async function GET(req: NextRequest) { ) } - const lnurlwBase = `${serverUrl}/ln` + const lnurlwBase = `${serverApi}/ln` .replace("http://", "lnurlw://") .replace("https://", "lnurlw://") diff --git a/apps/boltcard/app/card/[id]/page.tsx b/apps/boltcard/app/card/[id]/page.tsx index 403f3bbc489..3e10d3611a1 100644 --- a/apps/boltcard/app/card/[id]/page.tsx +++ b/apps/boltcard/app/card/[id]/page.tsx @@ -1,9 +1,71 @@ -export default function Home({ params }: { params: { id: string } }) { +import { serverApi } from "@/services/config" + +export default async function Home({ params }: { params: { id: string } }) { const { id } = params + const cardApi = `${serverApi}/card/id/${id}` + const cardResult = await fetch(cardApi, { cache: "no-store" }) + const cardInfo = await cardResult.json() + + const transactionsApi = `${serverApi}/card/id/${id}/transactions` + const transactionsResult = await fetch(transactionsApi) + const transactionInfo = await transactionsResult.json() + return ( -
-

cardId: {id}

+
+

boltcard

+ +
+

Card Information:

+
    +
  • + ID: {cardInfo.id} +
  • +
  • + UID: {cardInfo.uid} +
  • +
  • + Onchain Address: {cardInfo.onchainAddress} +
  • +
  • + Enabled: {cardInfo.enabled ? "Yes" : "No"} +
  • +
+
+ +
+

Transactions:

+
    + {transactionInfo.map((tx, index) => ( +
  • + Transaction {index + 1}: +
      +
    • + ID: {tx.id} +
    • +
    • + Status: {tx.status} +
    • +
    • + Direction: {tx.direction} +
    • +
    • + Memo: {tx.memo} +
    • +
    • + Amount: {tx.settlementDisplayAmount}{" "} + {tx.settlementDisplayCurrency} +
    • +
    • + Fee: {tx.settlementDisplayFee}{" "} + {tx.settlementDisplayCurrency} +
    • + {/* Add more fields as required */} +
    +
  • + ))} +
+
) } diff --git a/apps/boltcard/bun.lockb b/apps/boltcard/bun.lockb index 960489c7199d545a9ecba3be05cb0847fc94ddff..8a22306985136cfaf8d1b5e681ec1614d6d20fe1 100755 GIT binary patch delta 38986 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 delta 38403 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 Pn0vKLTj^|fHunDm!v)|R diff --git a/apps/boltcard/package.json b/apps/boltcard/package.json index 3eccde4c6c8..f921d43f195 100644 --- a/apps/boltcard/package.json +++ b/apps/boltcard/package.json @@ -22,7 +22,7 @@ "eslint-config-next": "13.4.19", "graphql": "^16.8.0", "knex": "^2.5.1", - "next": "13.4.19", + "next": "latest", "node-aes-cmac": "^0.1.1", "pg": "^8.11.3", "postcss": "8.4.29", diff --git a/apps/boltcard/services/config.ts b/apps/boltcard/services/config.ts index d2bb3f76fb2..a2b9a7b8404 100644 --- a/apps/boltcard/services/config.ts +++ b/apps/boltcard/services/config.ts @@ -1,4 +1,4 @@ -export const serverUrl = process.env.SERVER_URL ?? "http://localhost:3000/api" +export const serverApi = process.env.SERVER_URL ?? "http://localhost:3000/api" export const coreUrl = process.env.CORE_URL ?? "http://localhost:4002/graphql" diff --git a/apps/boltcard/services/db/card.ts b/apps/boltcard/services/db/card.ts index fbfafc3b442..f8854a82000 100644 --- a/apps/boltcard/services/db/card.ts +++ b/apps/boltcard/services/db/card.ts @@ -10,6 +10,22 @@ export async function fetchByCardId(cardId: string) { return result } +export async function fetchPublicByCardUid(uid: string) { + const result = await knex("Card") + .where("uid", uid) + .select("id", "uid", "onchainAddress", "enabled") + .first() + return result +} + +export async function fetchPublicByCardId(cardId: string) { + const result = await knex("Card") + .where("id", cardId) + .select("id", "uid", "onchainAddress", "enabled") + .first() + return result +} + interface CardInput { id: string uid: string