Skip to content

Commit ba86d51

Browse files
[TOOL-2896] Portal: Add Nebula API docs (#5916)
Co-authored-by: samina <[email protected]>
1 parent 5866088 commit ba86d51

File tree

38 files changed

+1610
-645
lines changed

38 files changed

+1610
-645
lines changed

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ export async function promptNebula(params: {
3030
body.context_filter = {
3131
chain_ids: params.contextFilters.chainIds || [],
3232
contract_addresses: params.contextFilters.contractAddresses || [],
33+
wallet_addresses: params.contextFilters.walletAddresses || [],
3334
};
3435
}
3536

apps/portal/mdx-components.tsx

Lines changed: 87 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { CodeBlock, InlineCode } from "@/components/Document/Code";
1+
import { CodeBlock } from "@/components/Document/Code";
22
import { DocLink } from "@/components/Document/DocLink";
33
import { Heading } from "@/components/Document/Heading";
44
import { OrderedList, UnorderedList } from "@/components/Document/List";
@@ -8,97 +8,98 @@ import { TBody, Table, Td, Th, Tr } from "@/components/Document/Table";
88
import GithubSlugger from "github-slugger";
99
import type { MDXComponents } from "mdx/types";
1010
import type { BuiltinLanguage } from "shiki";
11+
import { InlineCode } from "./src/components/Document";
1112

1213
export function useMDXComponents(components: MDXComponents): MDXComponents {
13-
const slugger = new GithubSlugger();
14+
const slugger = new GithubSlugger();
1415

15-
function nameToLink(name: React.ReactNode) {
16-
if (typeof name !== "string") {
17-
return undefined;
18-
}
16+
function nameToLink(name: React.ReactNode) {
17+
if (typeof name !== "string") {
18+
return undefined;
19+
}
1920

20-
return slugger.slug(name);
21-
}
21+
return slugger.slug(name);
22+
}
2223

23-
function getHeading(
24-
depth: number,
25-
props: {
26-
children?: React.ReactNode;
27-
id?: string;
28-
},
29-
) {
30-
return (
31-
<Heading level={depth} id={props.id || nameToLink(props.children) || ""}>
32-
{props.children}
33-
</Heading>
34-
);
35-
}
24+
function getHeading(
25+
depth: number,
26+
props: {
27+
children?: React.ReactNode;
28+
id?: string;
29+
},
30+
) {
31+
return (
32+
<Heading level={depth} id={props.id || nameToLink(props.children) || ""}>
33+
{props.children}
34+
</Heading>
35+
);
36+
}
3637

37-
return {
38-
...components,
39-
a(props) {
40-
const { href, children } = props;
41-
return <DocLink href={href || ""}>{children}</DocLink>;
42-
},
43-
h1(props) {
44-
return getHeading(1, props);
45-
},
46-
h2(props) {
47-
return getHeading(2, props);
48-
},
49-
h3(props) {
50-
return getHeading(3, props);
51-
},
52-
h4(props) {
53-
return getHeading(4, props);
54-
},
55-
h5(props) {
56-
return getHeading(5, props);
57-
},
58-
h6(props) {
59-
return getHeading(6, props);
60-
},
61-
code(props) {
62-
const code = props.children;
63-
const lang = props.className?.replace("language-", "");
38+
return {
39+
...components,
40+
a(props) {
41+
const { href, children } = props;
42+
return <DocLink href={href || ""}>{children}</DocLink>;
43+
},
44+
h1(props) {
45+
return getHeading(1, props);
46+
},
47+
h2(props) {
48+
return getHeading(2, props);
49+
},
50+
h3(props) {
51+
return getHeading(3, props);
52+
},
53+
h4(props) {
54+
return getHeading(4, props);
55+
},
56+
h5(props) {
57+
return getHeading(5, props);
58+
},
59+
h6(props) {
60+
return getHeading(6, props);
61+
},
62+
code(props) {
63+
const code = props.children;
64+
const lang = props.className?.replace("language-", "");
6465

65-
if (!props.className) {
66-
return <InlineCode code={typeof code === "string" ? code : ""} />;
67-
}
66+
if (!props.className) {
67+
return <InlineCode code={typeof code === "string" ? code : ""} />;
68+
}
6869

69-
return (
70-
<CodeBlock
71-
lang={lang as BuiltinLanguage}
72-
code={typeof code === "string" ? code : ""}
73-
/>
74-
);
75-
},
76-
p(props) {
77-
return <Paragraph>{props.children}</Paragraph>;
78-
},
79-
ul(props) {
80-
return <UnorderedList>{props.children}</UnorderedList>;
81-
},
82-
ol(props) {
83-
return <OrderedList>{props.children}</OrderedList>;
84-
},
85-
hr() {
86-
return <Separator />;
87-
},
88-
table(props) {
89-
return <Table>{props.children}</Table>;
90-
},
91-
th(props) {
92-
return <Th>{props.children}</Th>;
93-
},
94-
td(props) {
95-
return <Td>{props.children}</Td>;
96-
},
97-
tr(props) {
98-
return <Tr>{props.children}</Tr>;
99-
},
100-
tbody(props) {
101-
return <TBody>{props.children}</TBody>;
102-
},
103-
};
70+
return (
71+
<CodeBlock
72+
lang={lang as BuiltinLanguage}
73+
code={typeof code === "string" ? code : ""}
74+
/>
75+
);
76+
},
77+
p(props) {
78+
return <Paragraph>{props.children}</Paragraph>;
79+
},
80+
ul(props) {
81+
return <UnorderedList>{props.children}</UnorderedList>;
82+
},
83+
ol(props) {
84+
return <OrderedList>{props.children}</OrderedList>;
85+
},
86+
hr() {
87+
return <Separator />;
88+
},
89+
table(props) {
90+
return <Table>{props.children}</Table>;
91+
},
92+
th(props) {
93+
return <Th>{props.children}</Th>;
94+
},
95+
td(props) {
96+
return <Td>{props.children}</Td>;
97+
},
98+
tr(props) {
99+
return <Tr>{props.children}</Tr>;
100+
},
101+
tbody(props) {
102+
return <TBody>{props.children}</TBody>;
103+
},
104+
};
104105
}

apps/portal/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"@next/mdx": "15.1.0",
2323
"@radix-ui/react-dialog": "1.1.4",
2424
"@radix-ui/react-dropdown-menu": "^2.1.3",
25+
"@radix-ui/react-select": "^2.1.3",
2526
"@radix-ui/react-slot": "^1.1.1",
2627
"@radix-ui/react-tabs": "^1.1.2",
2728
"@tanstack/react-query": "5.62.16",
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import { ApiEndpoint } from "@/components/Document/APIEndpointMeta/ApiEndpoint";
2+
import {
3+
nebulaAPI401Response,
4+
nebulaAPI422Response,
5+
nebulaContextFilterPathParameter,
6+
nebulaExecuteConfigPathParameter,
7+
nebulaSecretKeyHeaderParameter,
8+
nebulaSessionIdPathParameter,
9+
} from "../common";
10+
11+
const response200Example = `\
12+
{
13+
"message": "string",
14+
"actions": [
15+
{
16+
"session_id": "string",
17+
"request_id": "string",
18+
"type": "init",
19+
"source": "string",
20+
"data": "string"
21+
}
22+
],
23+
"session_id": "string",
24+
"request_id": "string"
25+
}`;
26+
27+
export function EndpointMetadata() {
28+
return (
29+
<ApiEndpoint
30+
metadata={{
31+
title: "Send Message",
32+
description: "Process a chat message and return the response",
33+
origin: "https://nebula-api.thirdweb.com",
34+
path: "/chat",
35+
method: "POST",
36+
request: {
37+
pathParameters: [],
38+
headers: [nebulaSecretKeyHeaderParameter],
39+
bodyParameters: [
40+
{
41+
name: "message",
42+
required: true,
43+
description: "The message to be processed.",
44+
type: "string",
45+
example: "Hello",
46+
},
47+
{
48+
name: "stream",
49+
required: false,
50+
description: "Whether to stream the response or not",
51+
type: "boolean",
52+
example: false,
53+
},
54+
{
55+
...nebulaSessionIdPathParameter,
56+
required: false,
57+
description:
58+
"The session ID to associate with the message. If not provided, a new session will be created.",
59+
},
60+
nebulaExecuteConfigPathParameter,
61+
nebulaContextFilterPathParameter,
62+
],
63+
},
64+
responseExamples: {
65+
200: response200Example,
66+
401: nebulaAPI401Response,
67+
422: nebulaAPI422Response,
68+
},
69+
}}
70+
/>
71+
);
72+
}

apps/portal/src/app/nebula/api-reference/chat/page.mdx

Lines changed: 8 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1,79 +1,6 @@
1-
### Send Message
1+
import { EndpointMetadata } from './EndpointMetadata';
22

3-
```http
4-
POST /chat
5-
```
6-
7-
**Request Body:**
8-
```json
9-
{
10-
"message": "Find the last 5 blocks",
11-
"session_id": "abc",
12-
"stream": true,
13-
"context_filter": {
14-
"chain_ids": [137],
15-
"contract_addresses": ["0x..."],
16-
"wallet_addresses": ["0x..."]
17-
},
18-
"execute_config": {
19-
"mode": "client",
20-
"signer_wallet_address": "0x..."
21-
}
22-
}
23-
```
24-
25-
**Request Parameters:**
26-
27-
- `message` (required)
28-
- Type: string
29-
- Description: The user's input message or command to be processed by Nebula
30-
31-
- `session_id` (optional)
32-
- Type: string
33-
- Description: Identifier for maintaining conversation context
34-
- Default: A new session will be created if omitted
35-
36-
- `stream` (optional)
37-
- Type: boolean
38-
- Description: Controls whether the response is streamed or returned as a single response
39-
- Default: false
40-
41-
- `context_filter` (optional)
42-
- Type: object
43-
- Description: Controls which blockchain data sources are used for context
44-
- Properties:
45-
- `chain_ids`: Array of numbers representing blockchain network IDs
46-
- `contract_addresses`: Array of strings containing contract addresses to focus on
47-
48-
- `execute_config` (optional)
49-
- Type: object
50-
- Description: Configuration for transaction execution
51-
- Properties:
52-
- `mode`: String indicating execution mode (currently only "client" is supported)
53-
- `signer_wallet_address`: String containing the wallet address that will sign transactions
54-
55-
#### Chat Messages
56-
57-
Chat messages are natural language responses from Nebula. They appear in the `message` field of the response and provide formatted information, explanations, or answers to your queries. Messages can include formatted text, blockchain data, and technical details.
58-
59-
**Example Response with Chat Message:**
60-
```json
61-
{
62-
"message": "The last block on the Arbitrum mainnet is block number **284204124**. Here are the details:\n\n- **Block Hash:** 0xf42e3d624ae1e3fd6b89d4680f39943eb1cd3b8f0606918ef818d3021b7724f1\n- **Parent Hash:** 0x4c45cd0964281833b070b633980d8f530debdd21dfbdbf6eddf96cc93cbaac8e\n- **Timestamp:** 1734063299\n- **Gas Used:** 5,064,851\n- **Gas Limit:** 1,125,899,906,842,624\n- **Base Fee per Gas:** 10,000,000\n- **Transaction Count:** 7\n- **Withdrawals Count:** 0\n\nIf you need any more information about this block or related transactions, feel free to ask!",
63-
"actions": [],
64-
"session_id": "5d579903-5a63-434f-8667-788adfae9304",
65-
"request_id": "d46cfb80-de6a-48a6-9a97-746e1708d066"
66-
}
67-
```
68-
69-
Response properties:
70-
- `message`: A formatted string containing the response, which may include:
71-
- Markdown formatting for better readability
72-
- Technical data (hashes, addresses, numbers)
73-
- Structured information about blockchain state
74-
- `actions`: Array of actions (empty when no transactions are needed)
75-
- `session_id`: Unique identifier for the current session
76-
- `request_id`: Unique identifier for the specific request
3+
<EndpointMetadata />
774

785
#### Chat Actions
796

@@ -117,11 +44,11 @@ When handling actions:
11744

11845
**Example Implementation with thirdweb SDK:**
11946
```javascript
120-
import {
121-
createThirdwebClient,
122-
prepareTransaction,
47+
import {
48+
createThirdwebClient,
49+
prepareTransaction,
12350
sendTransaction,
124-
privateKeyToAccount
51+
privateKeyToAccount
12552
} from "thirdweb";
12653

12754
// Example function to handle the API response
@@ -140,7 +67,7 @@ async function handleNebulaResponse(response) {
14067
// Check if we have any actions
14168
if (response.actions && response.actions.length > 0) {
14269
const action = response.actions[0];
143-
70+
14471
// Parse the transaction data from the action
14572
const txData = JSON.parse(action.data);
14673

@@ -159,7 +86,7 @@ async function handleNebulaResponse(response) {
15986
transaction,
16087
account
16188
});
162-
89+
16390
return result;
16491
} catch (error) {
16592
console.error("Error processing transaction:", error);

0 commit comments

Comments
 (0)