Skip to content

Commit 3e22546

Browse files
committed
wip
1 parent 4d41377 commit 3e22546

File tree

7 files changed

+66
-74
lines changed

7 files changed

+66
-74
lines changed

apps/web/src/components/settings/billing.tsx

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,13 @@ import { getWalletAccount } from "@deco/sdk";
1515
import { useQuery } from "@tanstack/react-query";
1616

1717

18-
function AccountValue() {
18+
function AccountBalance({ workspace }: { workspace: string }) {
1919
const { data, isLoading, error } = useQuery({
2020
queryKey: ["wallet"],
21-
queryFn: () => getWalletAccount("/shared/deco.cx"),
21+
queryFn: () => getWalletAccount(workspace),
2222
});
2323

24-
if (isLoading) return <Skeleton className="w-24 h-8" />;
24+
if (isLoading) return <Skeleton className="w-32 h-12" />;
2525
if (error) return <p>Error loading wallet</p>;
2626

2727
return <p className="text-5xl font-bold">{data?.balance}</p>;
@@ -30,11 +30,10 @@ function AccountValue() {
3030
function BalanceCard() {
3131
const team = useCurrentTeam();
3232

33-
3433
return (
3534
<Card className="w-full max-w-xl p-4 flex flex-col items-center rounded-md min-h-[340px] border border-slate-200">
3635
<div className="w-full text-sm mb-8">
37-
Wallet
36+
AI Usage Wallet
3837
</div>
3938
<CardContent className="flex flex-col items-center justify-center gap-2 p-0">
4039
<div className="flex items-center gap-1 text-base mb-1">
@@ -46,7 +45,7 @@ function BalanceCard() {
4645
/>
4746
</div>
4847
<div className="mb-6">
49-
<AccountValue />
48+
<AccountBalance workspace="/shared/deco.cx" />
5049
</div>
5150
<DepositDialog />
5251
</CardContent>

apps/web/src/components/wallet/DepositDialog.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,13 +64,12 @@ export function DepositDialog() {
6464
<DialogTrigger asChild>
6565
<Button
6666
className="py-4 px-10"
67-
variant="outline"
6867
size="lg"
6968
onClick={() =>
7069
trackEvent("wallet_add_credits_click", { userId: user?.id })}
7170
>
72-
<Icon name="arrow_upward" size={16} className="mr-2" />
73-
Deposit
71+
<Icon name="add" size={16} className="mr-2" />
72+
Add credits
7473
</Button>
7574
</DialogTrigger>
7675
<DialogContent className="sm:max-w-[425px]">

packages/sdk/src/crud/wallet.ts

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
// deno-lint-ignore-file no-explicit-any
2-
import { callToolFor, fetchAPI } from "../fetcher.ts";
1+
import { MCPClient } from "../fetcher.ts";
32

43
export const getWalletAccount = async (workspace: string) => {
5-
const response = await callToolFor(workspace, "GET_WALLET_ACCOUNT", {});
6-
return response.json<any>();
4+
const { status, data, error } = await MCPClient.forWorkspace(workspace).GET_WALLET_ACCOUNT({});
5+
if (status !== 200 || error) {
6+
throw new Error(error?.message);
7+
}
8+
return data;
79
};
810

911
interface WalletStatement {
@@ -18,21 +20,22 @@ interface WalletStatement {
1820
metadata?: Record<string, string>;
1921
}
2022

21-
export const getWalletStatements = async (cursor?: string) => {
22-
const response = await fetchAPI({
23-
path: `/wallet/statements${cursor ? `?cursor=${cursor}` : ""}`,
24-
});
25-
return response.json() as Promise<{
26-
items: WalletStatement[];
27-
nextCursor: string;
28-
}>;
29-
};
23+
// export const getWalletStatements = async (cursor?: string) => {
24+
// const response = await fetchAPI({
25+
// path: `/wallet/statements${cursor ? `?cursor=${cursor}` : ""}`,
26+
// });
27+
// return response.json() as Promise<{
28+
// items: WalletStatement[];
29+
// nextCursor: string;
30+
// }>;
31+
// };
3032

3133
export const createWalletCheckoutSession = async (amountInCents: number) => {
32-
const response = await fetchAPI({
33-
segments: ["wallet", "checkout"],
34-
method: "POST",
35-
body: JSON.stringify({ amountInCents }),
36-
});
37-
return response.json() as Promise<{ checkoutUrl: string }>;
34+
// const response = await fetchAPI({
35+
// segments: ["wallet", "checkout"],
36+
// method: "POST",
37+
// body: JSON.stringify({ amountInCents }),
38+
// });
39+
// return response.json() as Promise<{ checkoutUrl: string }>;
40+
return { checkoutUrl: "https://checkout.stripe.com/c/pay/test" };
3841
};

packages/sdk/src/mcp/context.ts

Lines changed: 20 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ export interface Vars {
1919
db: Client;
2020
user: SupaUser;
2121
cf: Cloudflare;
22+
walletBinding?: { fetch: typeof fetch }
2223
immutableRes?: boolean;
2324
stub: <
2425
Constructor extends
@@ -40,6 +41,8 @@ export interface EnvVars {
4041
CF_ACCOUNT_ID: string;
4142
CF_API_TOKEN: string;
4243
CF_DISPATCH_NAMESPACE: string;
44+
WALLET_API_KEY: string;
45+
STRIPE_SECRET_KEY: string;
4346
}
4447

4548
export type AppContext = Vars & { envVars: EnvVars };
@@ -63,44 +66,28 @@ export const serializeError = (error: unknown): string => {
6366
}
6467
};
6568

66-
export const getEnv = (ctx: AppContext) => {
67-
const {
68-
CF_DISPATCH_NAMESPACE,
69-
CF_ACCOUNT_ID,
70-
CF_API_TOKEN,
71-
VITE_USE_LOCAL_BACKEND,
72-
SUPABASE_URL,
73-
SUPABASE_SERVER_TOKEN,
74-
TURSO_GROUP_DATABASE_TOKEN,
75-
TURSO_ORGANIZATION,
76-
RESEND_API_KEY,
77-
OPENROUTER_API_KEY,
78-
} = ctx.envVars;
69+
const REQUIRED_LOCAL_ENV_VARS = [
70+
"OPENROUTER_API_KEY",
71+
"CF_ACCOUNT_ID",
72+
"SUPABASE_URL",
73+
"SUPABASE_SERVER_TOKEN",
74+
"CF_API_TOKEN",
75+
"CF_DISPATCH_NAMESPACE",
76+
"TURSO_GROUP_DATABASE_TOKEN",
77+
"TURSO_ORGANIZATION",
78+
] as const;
7979

80+
export const getEnv = (ctx: AppContext) => {
8081
if (
81-
typeof OPENROUTER_API_KEY !== "string" ||
82-
typeof CF_ACCOUNT_ID !== "string" ||
83-
typeof SUPABASE_URL !== "string" ||
84-
typeof SUPABASE_SERVER_TOKEN !== "string" ||
85-
typeof CF_API_TOKEN !== "string" ||
86-
typeof CF_DISPATCH_NAMESPACE !== "string" ||
87-
typeof TURSO_GROUP_DATABASE_TOKEN !== "string" ||
88-
typeof TURSO_ORGANIZATION !== "string"
82+
!REQUIRED_LOCAL_ENV_VARS.every((v) => typeof ctx.envVars[v] === "string")
8983
) {
90-
throw new Error("Missing environment variables");
84+
const missing = REQUIRED_LOCAL_ENV_VARS.filter(
85+
(v) => typeof ctx.envVars[v] !== "string",
86+
);
87+
throw new Error(`Missing environment variables: ${missing.join(", ")}`);
9188
}
9289

93-
return {
94-
CF_ACCOUNT_ID,
95-
CF_API_TOKEN,
96-
CF_DISPATCH_NAMESPACE,
97-
VITE_USE_LOCAL_BACKEND,
98-
SUPABASE_URL,
99-
SUPABASE_SERVER_TOKEN,
100-
TURSO_GROUP_DATABASE_TOKEN,
101-
TURSO_ORGANIZATION,
102-
RESEND_API_KEY,
103-
};
90+
return ctx.envVars;
10491
};
10592

10693
export const AUTH_URL = (ctx: AppContext) =>

packages/sdk/src/mcp/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import * as profilesAPI from "./profiles/api.ts";
99
import * as teamsAPI from "./teams/api.ts";
1010
import * as threadsAPI from "./threads/api.ts";
1111
import * as triggersAPI from "./triggers/api.ts";
12+
import * as walletAPI from "./wallet/api.ts";
1213

1314
// Register tools for each API handler
1415
export const GLOBAL_TOOLS = [
@@ -57,6 +58,7 @@ export const WORKSPACE_TOOLS = [
5758
triggersAPI.createWebhookTrigger,
5859
triggersAPI.deleteTrigger,
5960
triggersAPI.getWebhookTriggerUrl,
61+
walletAPI.getWalletAccount,
6062
] as const;
6163

6264
export type WorkspaceTools = typeof WORKSPACE_TOOLS;

apps/api/src/api/wallet/api.ts renamed to packages/sdk/src/mcp/wallet/api.ts

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,13 @@
11
import { z } from "zod";
2-
import { AppContext, createApiHandler, getEnv } from "../../utils/context.ts";
2+
import { createApiHandler, getEnv } from "../context.ts";
33
import {
44
createWalletClient,
55
MicroDollar,
66
WalletAPI,
77
WellKnownWallets,
88
} from "@deco/sdk/wallet";
99
import { ClientOf } from "@deco/sdk/http";
10-
11-
function getWorkspace(c: AppContext) {
12-
const root = c.req.param("root");
13-
const wksSlug = c.req.param("slug");
14-
const workspace = `${root}/${wksSlug}`;
15-
return { root, wksSlug, workspace };
16-
}
10+
import { assertHasWorkspace } from "../assertions.ts";
1711

1812
const Account = {
1913
fetch: async (wallet: ClientOf<WalletAPI>, id: string) => {
@@ -46,13 +40,13 @@ export const getWalletAccount = createApiHandler({
4640
description: "Get the wallet account for the current tenant",
4741
schema: z.object({}),
4842
handler: async (_, c) => {
49-
const { workspace } = getWorkspace(c);
43+
assertHasWorkspace(c);
44+
5045
const envVars = getEnv(c);
51-
// @ts-expect-error todo: type the worker binding
52-
const wallet = createWalletClient(envVars.WALLET_API_KEY, c.var?.WALLET);
46+
const wallet = createWalletClient(envVars.WALLET_API_KEY, c.walletBinding);
5347

5448
const workspaceWalletId = WellKnownWallets.build(
55-
...WellKnownWallets.workspace(workspace),
49+
...WellKnownWallets.workspace(c.workspace.value),
5650
);
5751
const data = await Account.fetch(wallet, workspaceWalletId);
5852

@@ -74,7 +68,11 @@ export const createCheckoutSession = createApiHandler({
7468
description: "Create a checkout session for the current tenant's wallet",
7569
schema: z.object({}),
7670
handler: async (_, c) => {
77-
const { workspace } = getWorkspace(c);
71+
assertHasWorkspace(c);
72+
const workspace = c.workspace.value;
73+
7874
const envVars = getEnv(c);
75+
76+
7977
},
8078
});

packages/sdk/src/mcp/wallet/stripe.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
/**
2+
*
3+
*/
4+

0 commit comments

Comments
 (0)