diff --git a/apps/playground-web/src/app/ai/api/chat.ts b/apps/playground-web/src/app/ai/api/chat.ts index 05515833840..d6e2cbe5954 100644 --- a/apps/playground-web/src/app/ai/api/chat.ts +++ b/apps/playground-web/src/app/ai/api/chat.ts @@ -119,7 +119,7 @@ export async function promptNebula(params: { if (data.type === "sign_transaction") { try { - const parsedTxData = JSON.parse(data.data) as NebulaTxData; + const parsedTxData = data.data as NebulaTxData; params.handleStream({ data: parsedTxData, event: "action", @@ -133,7 +133,7 @@ export async function promptNebula(params: { if (data.type === "sign_swap") { try { - const swapData = JSON.parse(data.data) as NebulaSwapData; + const swapData = data.data as NebulaSwapData; params.handleStream({ data: swapData, event: "action", diff --git a/apps/playground-web/src/app/ai/api/types.ts b/apps/playground-web/src/app/ai/api/types.ts index 3f4402cb6de..b24d3e32c39 100644 --- a/apps/playground-web/src/app/ai/api/types.ts +++ b/apps/playground-web/src/app/ai/api/types.ts @@ -22,8 +22,8 @@ export type NebulaUserMessage = { }; export type NebulaTxData = { - chainId: number; + chain_id: number; data: `0x${string}`; to: string; - value?: string; + value: string; }; diff --git a/apps/playground-web/src/app/ai/chat/page.tsx b/apps/playground-web/src/app/ai/chat/page.tsx index 479cf678b9a..49cf024e314 100644 --- a/apps/playground-web/src/app/ai/chat/page.tsx +++ b/apps/playground-web/src/app/ai/chat/page.tsx @@ -13,6 +13,6 @@ export default function ChatPage() { } export const metadata = { - title: "AI Chat API - Playground", + title: "Blockchain LLM - Playground", description: "Chat with thirdweb AI for blockchain interactions", }; diff --git a/apps/playground-web/src/app/ai/components/ChatPageContent.tsx b/apps/playground-web/src/app/ai/components/ChatPageContent.tsx index a2338ba1e50..4d9020ea211 100644 --- a/apps/playground-web/src/app/ai/components/ChatPageContent.tsx +++ b/apps/playground-web/src/app/ai/components/ChatPageContent.tsx @@ -102,7 +102,7 @@ type ChatMessage = }; type NebulaTxData = { - chainId: number; + chain_id: number; data: `0x${string}`; to: string; value?: string; @@ -703,7 +703,7 @@ function RenderMessage(props: { transaction={() => prepareTransaction({ client: THIRDWEB_CLIENT, - chain: defineChain(message.data.chainId), + chain: defineChain(message.data.chain_id), data: message.data.data, to: message.data.to, value: message.data.value @@ -719,7 +719,7 @@ function RenderMessage(props: { props.sendMessage({ content: [ { - chain_id: message.data.chainId, + chain_id: message.data.chain_id, transaction_hash: tx.transactionHash, type: "transaction", }, @@ -734,7 +734,7 @@ function RenderMessage(props: { ) : ( )} diff --git a/apps/playground-web/src/app/navLinks.ts b/apps/playground-web/src/app/navLinks.ts index d636beccb24..8f3b021bd3f 100644 --- a/apps/playground-web/src/app/navLinks.ts +++ b/apps/playground-web/src/app/navLinks.ts @@ -18,7 +18,7 @@ const ai: ShadcnSidebarLink = { links: [ { href: "/ai/chat", - label: "Chat API", + label: "Blockchain LLM", }, ], }; diff --git a/apps/portal/src/app/Header.tsx b/apps/portal/src/app/Header.tsx index 9edeb273cb3..253083bd91f 100644 --- a/apps/portal/src/app/Header.tsx +++ b/apps/portal/src/app/Header.tsx @@ -144,7 +144,7 @@ const apisLinks = [ const aiLinks = [ { href: "/ai/chat", - name: "Chat API", + name: "Blockchain LLM", }, { href: "/ai/mcp", diff --git a/apps/portal/src/app/ai/chat/execution/page.mdx b/apps/portal/src/app/ai/chat/execution/page.mdx new file mode 100644 index 00000000000..44e0bc60aba --- /dev/null +++ b/apps/portal/src/app/ai/chat/execution/page.mdx @@ -0,0 +1,59 @@ +import {OpenApiEndpoint} from "@doc"; + +# Transaction Execution + +thirdweb AI can either auto execute transactions or prepare them for signing. + +- **Auto Execute**: The API will auto execute the transaction. Requires wallet authentication. +- **Prepare for Signing**: The API will only prepare the transaction for signing. The user will need to sign the transaction manually. + +## Auto Execute + +Requirements: + +- The context object must be set with: + - `from` set to the wallet address to execute the transaction from + - `auto_execute_transaction` set to `true` + - (Optional) `chain_ids` set to the chain IDs to execute the transaction on +- The API must be called with either: + - your `x-secret-key` header for server wallet authentication + - OR a `Authorization` header with a valid wallet JWT for user wallet authentication + +Model behavior: + +If all the requirements are met, the transaction will be executed automatically and the model will return a message with the transaction ID. + +It will also include an `actions` array with a `monitor_transaction` action. This action can be used to monitor the transaction status and get the transaction receipt via the thirdweb API. + + + +## Prepare for Signing + +When the `auto_execute` parameter is set to `false` or omitted, the API will prepare the transaction for signing and return the transaction data in the `actions` array as a 'sign_transaction' action type. + + \ No newline at end of file diff --git a/apps/portal/src/app/ai/chat/page.mdx b/apps/portal/src/app/ai/chat/page.mdx index b8db4d42230..0deb32d1aef 100644 --- a/apps/portal/src/app/ai/chat/page.mdx +++ b/apps/portal/src/app/ai/chat/page.mdx @@ -1,14 +1,14 @@ import { Tabs, TabsContent, TabsList, TabsTrigger, OpenApiEndpoint } from "@doc"; -# Chat API +# Blockchain LLM -The thirdweb AI chat API is a standard OpenAI-compatible chat completion API that allows you to interact with the thirdweb AI model, optimized for blockchain interactions. +The thirdweb API exposes a standard OpenAI-compatible chat completion API that allows you to interact with the thirdweb AI model, optimized for blockchain interactions. - Query real-time data from the blockchain - Analyze transactions - Fetch token balances, prices and metadata -- Prepare any contract call or transaction for signing -- Prepare swaps from/to any token pair +- Execute or prepare any contract call or transaction +- Execute or prepare swaps from/to any token pair - Deploy contracts - Generate images - Search the web diff --git a/apps/portal/src/app/ai/chat/streaming/page.mdx b/apps/portal/src/app/ai/chat/streaming/page.mdx index 046bde4d2c4..8ba41adf01d 100644 --- a/apps/portal/src/app/ai/chat/streaming/page.mdx +++ b/apps/portal/src/app/ai/chat/streaming/page.mdx @@ -58,7 +58,12 @@ data: { "request_id": "9efc7f6a-8576-4d9c-8603-f6c72aa72164", "type": "sign_transaction", "source": "executor", - "data": "{\"chainId\": 11155111, \"to\": \"0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045\", \"data\": \"0x\", \"value\": \"0x5af3107a4000\"}" + "data": { + "chain_id": 11155111, + "to": "0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", + "data": "0x", + "value": "0x5af3107a4000" + } } ``` @@ -90,52 +95,57 @@ for await (const event of events) { if (!event.data) { continue; } + const parsedEventData = JSON.parse(event.data); switch (event.event) { case "init": { - console.log("Init event", event.data); + console.log("Init event", parsedEventData); // handle init event (session id and request id) break; } case "presence": { - console.log("Presence event", event.data); + console.log("Presence event", parsedEventData); // handle intermediate thinking steps break; } case "delta": { - console.log("Delta event", event.data); + console.log("Delta event", parsedEventData); // handle delta event (streamed output text response) break; } case "action": { - const data = JSON.parse(event.data); - // handle transaction signing - if (data.type === "sign_transaction") { - const transactionData = JSON.parse(data.data); + if (parsedEventData.type === "sign_transaction") { + const transactionData = parsedEventData.data; console.log("Sign transaction event", transactionData); } // handle swap signing - if (data.type === "sign_swap") { - const swapData = JSON.parse(data.data); + if (parsedEventData.type === "sign_swap") { + const swapData = parsedEventData.data; console.log("Sign swap event", swapData); } + // handle transaction monitoring + if (parsedEventData.type === "monitor_transaction") { + const transactionId = parsedEventData.data.transaction_id; + console.log("Monitor transaction event", transactionId); + } + break; } case "image": { - const data = JSON.parse(event.data); + const imageData = parsedEventData.data; // handle image rendering - console.log("Image data", data); + console.log("Image data", imageData); break; } case "context": { - console.log("Context event", event.data); + console.log("Context event", parsedEventData); // handle context changes (chain ids, wallet address, etc) break; } case "error": { - console.log("Error event", event.data); + console.log("Error event", parsedEventData); // handle error event (error message) break; } diff --git a/apps/portal/src/app/ai/sidebar.tsx b/apps/portal/src/app/ai/sidebar.tsx index 43c0472894b..aa6524bb16b 100644 --- a/apps/portal/src/app/ai/sidebar.tsx +++ b/apps/portal/src/app/ai/sidebar.tsx @@ -4,7 +4,7 @@ import type { SideBar } from "@/components/Layouts/DocLayout"; export const sidebar: SideBar = { links: [ { - name: "Chat API", + name: "Blockchain LLM", isCollapsible: false, links: [ { @@ -17,6 +17,10 @@ export const sidebar: SideBar = { href: "https://playground.thirdweb.com/ai/chat", icon: , }, + { + name: "Transaction Execution", + href: "/ai/chat/execution", + }, { name: "Streaming Responses", href: "/ai/chat/streaming", diff --git a/apps/portal/src/app/page.tsx b/apps/portal/src/app/page.tsx index 9b1eb52f4e3..925664fdea4 100644 --- a/apps/portal/src/app/page.tsx +++ b/apps/portal/src/app/page.tsx @@ -84,7 +84,7 @@ function AISection() { description="Integrate the most advanced blockchain model into your applications" href="/ai/chat" icon={MessageCircleIcon} - title="Chat API" + title="Blockchain LLM" />