Skip to content

Commit f392aed

Browse files
authored
Merge branch 'main' into new-engine-docs
2 parents c568671 + ec50f8c commit f392aed

File tree

30 files changed

+738
-447
lines changed

30 files changed

+738
-447
lines changed

apps/dashboard/src/app/checkout/components/client/CheckoutEmbed.client.tsx

Lines changed: 39 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,8 @@ import {
1111
} from "constants/urls";
1212
import { useV5DashboardChain } from "lib/v5-adapter";
1313
import { getVercelEnv } from "lib/vercel-utils";
14-
import { useMemo } from "react";
14+
import { useTheme } from "next-themes";
15+
import { useEffect, useMemo } from "react";
1516
import { NATIVE_TOKEN_ADDRESS, createThirdwebClient, toTokens } from "thirdweb";
1617
import { AutoConnect, PayEmbed } from "thirdweb/react";
1718
import { setThirdwebDomains } from "thirdweb/utils";
@@ -35,8 +36,17 @@ export function CheckoutEmbed({
3536
image?: string;
3637
redirectUri?: string;
3738
clientId: string;
38-
theme: "light" | "dark";
39+
theme?: "light" | "dark";
3940
}) {
41+
const { theme: browserTheme, setTheme } = useTheme();
42+
43+
// eslint-disable-next-line no-restricted-syntax
44+
useEffect(() => {
45+
if (theme) {
46+
setTheme(theme);
47+
}
48+
}, [theme, setTheme]);
49+
4050
const client = useMemo(() => {
4151
if (getVercelEnv() !== "production") {
4252
setThirdwebDomains({
@@ -59,7 +69,7 @@ export function CheckoutEmbed({
5969
<AutoConnect client={client} />
6070
<PayEmbed
6171
client={client}
62-
theme={theme === "light" ? "light" : "dark"}
72+
theme={theme ?? (browserTheme === "light" ? "light" : "dark")}
6373
payOptions={{
6474
metadata: {
6575
name,
@@ -75,17 +85,33 @@ export function CheckoutEmbed({
7585
onPurchaseSuccess: (result) => {
7686
if (!redirectUri) return;
7787
const url = new URL(redirectUri);
78-
if (result.type === "transaction") {
79-
url.searchParams.set("txHash", result.transactionHash);
80-
return window.open(url.toString());
81-
}
82-
if (result.status.status === "NOT_FOUND") {
83-
throw new Error("Transaction not found");
84-
}
85-
const txHash = result.status.source?.transactionHash;
86-
if (typeof txHash === "string") {
87-
url.searchParams.set("txHash", txHash);
88+
switch (result.type) {
89+
case "crypto": {
90+
url.searchParams.set("status", result.status.status);
91+
if (
92+
"source" in result.status &&
93+
result.status.source?.transactionHash
94+
) {
95+
url.searchParams.set(
96+
"txHash",
97+
result.status.source?.transactionHash,
98+
);
99+
}
100+
break;
101+
}
102+
case "fiat": {
103+
url.searchParams.set("status", result.status.status);
104+
if ("intentId" in result.status) {
105+
url.searchParams.set("intentId", result.status.intentId);
106+
}
107+
break;
108+
}
109+
case "transaction": {
110+
url.searchParams.set("txHash", result.transactionHash);
111+
break;
112+
}
88113
}
114+
return window.open(url.toString());
89115
},
90116
}}
91117
/>

apps/dashboard/src/app/checkout/components/client/ThemeHandler.client.tsx

Lines changed: 0 additions & 22 deletions
This file was deleted.
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
"use client";
2+
3+
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
4+
5+
export default function ErrorPage({
6+
error,
7+
}: {
8+
error: Error & { digest?: string };
9+
}) {
10+
return (
11+
<Card className="overflow-hidden text-center">
12+
<CardHeader className="border-b md:border-b-0">
13+
<CardTitle className="font-bold text-destructive text-lg">
14+
Something went wrong
15+
</CardTitle>
16+
</CardHeader>
17+
<CardContent className="text-muted-foreground">
18+
{error.message}
19+
</CardContent>
20+
</Card>
21+
);
22+
}

apps/dashboard/src/app/checkout/layout.tsx

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1+
import "../../global.css";
12
import { cn } from "@/lib/utils";
23
import { ThemeProvider } from "next-themes";
34
import { Inter } from "next/font/google";
4-
import { Suspense } from "react";
55
import { Providers } from "./components/client/Providers.client";
6-
import { ThemeHandler } from "./components/client/ThemeHandler.client";
76

87
const fontSans = Inter({
98
subsets: ["latin"],
@@ -27,14 +26,22 @@ export default async function CheckoutLayout({
2726
>
2827
<body
2928
className={cn(
30-
"bg-background font-sans antialiased",
29+
"h-screen w-screen bg-background font-sans antialiased",
3130
fontSans.variable,
3231
)}
3332
>
34-
<Suspense>
35-
<ThemeHandler />
36-
</Suspense>
37-
{children}
33+
<div className="relative mx-auto flex h-full w-full flex-col items-center justify-center overflow-hidden border py-10">
34+
<main className="container z-10 flex justify-center">
35+
{children}
36+
</main>
37+
38+
{/* eslint-disable-next-line @next/next/no-img-element */}
39+
<img
40+
alt=""
41+
src="/assets/login/background.svg"
42+
className="-bottom-12 -right-12 pointer-events-none absolute lg:right-0 lg:bottom-0"
43+
/>
44+
</div>
3845
</body>
3946
</ThemeProvider>
4047
</Providers>

apps/dashboard/src/app/checkout/page.tsx

Lines changed: 11 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import "../../global.css";
21
import { getThirdwebClient } from "@/constants/thirdweb.server";
32
import type { Metadata } from "next";
43
import { createThirdwebClient, defineChain, getContract } from "thirdweb";
@@ -71,27 +70,16 @@ export default async function RoutesPage({
7170
};
7271

7372
return (
74-
<div className="relative mx-auto flex h-screen w-screen flex-col items-center justify-center overflow-hidden border py-10">
75-
<main className="container z-10 flex justify-center">
76-
<CheckoutEmbed
77-
redirectUri={params.redirectUri}
78-
chainId={Number(params.chainId)}
79-
recipientAddress={params.recipientAddress}
80-
amount={BigInt(params.amount)}
81-
token={token}
82-
clientId={client.clientId}
83-
name={params.name}
84-
image={params.image}
85-
theme={params.theme === "light" ? "light" : "dark"}
86-
/>
87-
</main>
88-
89-
{/* eslint-disable-next-line @next/next/no-img-element */}
90-
<img
91-
alt=""
92-
src="/assets/login/background.svg"
93-
className="-bottom-12 -right-12 pointer-events-none absolute lg:right-0 lg:bottom-0"
94-
/>
95-
</div>
73+
<CheckoutEmbed
74+
redirectUri={params.redirectUri}
75+
chainId={Number(params.chainId)}
76+
recipientAddress={params.recipientAddress}
77+
amount={BigInt(params.amount)}
78+
token={token}
79+
clientId={client.clientId}
80+
name={params.name}
81+
image={params.image}
82+
theme={params.theme}
83+
/>
9684
);
9785
}

apps/dashboard/src/app/nebula-app/(app)/api/chat.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,24 @@ export async function promptNebula(params: {
9999
break;
100100
}
101101

102+
case "image": {
103+
const data = JSON.parse(event.data) as {
104+
data: {
105+
width: number;
106+
height: number;
107+
url: string;
108+
};
109+
request_id: string;
110+
};
111+
112+
params.handleStream({
113+
event: "image",
114+
data: data.data,
115+
request_id: data.request_id,
116+
});
117+
break;
118+
}
119+
102120
case "action": {
103121
const data = JSON.parse(event.data);
104122

@@ -109,6 +127,7 @@ export async function promptNebula(params: {
109127
event: "action",
110128
type: "sign_transaction",
111129
data: parsedTxData,
130+
request_id: data.request_id,
112131
});
113132
} catch (e) {
114133
console.error("failed to parse action data", e, { event });
@@ -122,6 +141,7 @@ export async function promptNebula(params: {
122141
event: "action",
123142
type: "sign_swap",
124143
data: swapData,
144+
request_id: data.request_id,
125145
});
126146
} catch (e) {
127147
console.error("failed to parse action data", e, { event });
@@ -197,11 +217,22 @@ type ChatStreamedResponse =
197217
event: "action";
198218
type: "sign_transaction";
199219
data: NebulaTxData;
220+
request_id: string;
200221
}
201222
| {
202223
event: "action";
203224
type: "sign_swap";
204225
data: NebulaSwapData;
226+
request_id: string;
227+
}
228+
| {
229+
event: "image";
230+
data: {
231+
width: number;
232+
height: number;
233+
url: string;
234+
};
235+
request_id: string;
205236
}
206237
| {
207238
event: "context";
@@ -225,6 +256,10 @@ type ChatStreamedEvent =
225256
event: "delta";
226257
data: string;
227258
}
259+
| {
260+
event: "image";
261+
data: string;
262+
}
228263
| {
229264
event: "action";
230265
type: "sign_transaction" | "sign_swap";

apps/dashboard/src/app/nebula-app/(app)/api/types.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@ type SessionContextFilter = {
33
wallet_address: string | null;
44
};
55

6+
export type NebulaSessionHistoryMessage = {
7+
role: "user" | "assistant" | "action" | "image";
8+
content: string;
9+
timestamp: number;
10+
};
11+
612
export type SessionInfo = {
713
id: string;
814
account_id: string;
@@ -11,11 +17,7 @@ export type SessionInfo = {
1117
can_execute: boolean;
1218
created_at: string;
1319
deleted_at: string | null;
14-
history: Array<{
15-
role: "user" | "assistant" | "action";
16-
content: string;
17-
timestamp: number;
18-
}> | null;
20+
history: Array<NebulaSessionHistoryMessage> | null;
1921
updated_at: string;
2022
archived_at: string | null;
2123
title: string | null;

apps/dashboard/src/app/nebula-app/(app)/components/ChatBar.tsx

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ export function ChatBar(props: {
5151
showContextSelector: boolean;
5252
client: ThirdwebClient;
5353
connectedWallets: WalletMeta[];
54-
activeAccountAddress: string | undefined;
5554
setActiveWallet: (wallet: WalletMeta) => void;
5655
isConnectingWallet: boolean;
5756
}) {
@@ -97,7 +96,7 @@ export function ChatBar(props: {
9796
<WalletSelector
9897
client={props.client}
9998
wallets={props.connectedWallets}
100-
activeAccountAddress={props.activeAccountAddress}
99+
selectedAddress={props.context?.walletAddress || undefined}
101100
onClick={(walletMeta) => {
102101
props.setActiveWallet(walletMeta);
103102
props.setContext({
@@ -242,11 +241,11 @@ function WalletSelector(props: {
242241
wallets: WalletMeta[];
243242
onClick: (wallet: WalletMeta) => void;
244243
client: ThirdwebClient;
245-
activeAccountAddress: string | undefined;
244+
selectedAddress: string | undefined;
246245
}) {
247246
const [open, setOpen] = useState(false);
248247

249-
if (!props.activeAccountAddress) {
248+
if (!props.selectedAddress) {
250249
return null;
251250
}
252251

@@ -266,7 +265,7 @@ function WalletSelector(props: {
266265
className="flex h-auto items-center gap-1 rounded-full px-2 py-1.5 text-xs"
267266
>
268267
<AccountProvider
269-
address={props.activeAccountAddress}
268+
address={props.selectedAddress}
270269
client={props.client}
271270
>
272271
<AccountAvatar
@@ -278,7 +277,7 @@ function WalletSelector(props: {
278277
<AccountBlobbie className="size-3 rounded-full" />
279278
}
280279
/>
281-
{shortenAddress(props.activeAccountAddress)}
280+
{shortenAddress(props.selectedAddress)}
282281
<ChevronDownIcon className="size-3 text-muted-foreground/70" />
283282
</AccountProvider>
284283
</Button>
@@ -301,7 +300,7 @@ function WalletSelector(props: {
301300
key={wallet.address}
302301
className={cn(
303302
"flex cursor-pointer items-center justify-between px-3 py-4 hover:bg-accent/50",
304-
props.activeAccountAddress === wallet.address && "bg-accent/50",
303+
props.selectedAddress === wallet.address && "bg-accent/50",
305304
)}
306305
onClick={() => {
307306
setOpen(false);
@@ -365,7 +364,7 @@ function WalletSelector(props: {
365364
</AccountProvider>
366365
</div>
367366

368-
{props.activeAccountAddress === wallet.address && (
367+
{props.selectedAddress === wallet.address && (
369368
<CheckIcon className="size-4 text-foreground" />
370369
)}
371370
</div>

0 commit comments

Comments
 (0)