keyring-chatbot-agent-sdk-test 1.0.25 → 1.0.27
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +340 -580
- package/dist/chat-widget.es.js +76 -60
- package/dist/chat-widget.umd.js +2 -2
- package/dist/lib.d.ts +417 -56
- package/package.json +15 -30
- package/.vscode/extensions.json +0 -6
- package/dist/chat-widget-wc.es.js +0 -63
- package/dist/chat-widget-wc.umd.js +0 -2
package/README.md
CHANGED
|
@@ -1,679 +1,439 @@
|
|
|
1
|
-
#
|
|
1
|
+
# keyring-chatbot-agent
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
React chat widget — drops a floating chat button + modal into any React dApp.
|
|
4
|
+
The widget answers questions and handles wallet / token / NFT lookups in the
|
|
5
|
+
browser. When it proposes an on-chain action (send / approve / wrap / unwrap /
|
|
6
|
+
send NFT / swap), it renders a confirmation form and hands the host an unsigned
|
|
7
|
+
transaction to sign and broadcast.
|
|
4
8
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
## Features
|
|
8
|
-
|
|
9
|
-
- **Natural language AI chat** — Understands user intent, distinguishes general questions from on-chain tasks
|
|
10
|
-
- **Token swaps** — Best-price routing via deBridge, automatic ERC-20 approval when needed
|
|
11
|
-
- **Send tokens** — ERC-20 and native tokens, supports "max", "50%", "$5" amount expressions
|
|
12
|
-
- **Send NFTs** — ERC-721 and ERC-1155, resolves NFT by name or token ID from the user's wallet
|
|
13
|
-
- **View balances** — Token list with USD values
|
|
14
|
-
- **Trending tokens** — Per-chain trending data with quick-buy buttons
|
|
15
|
-
- **Wrap / Unwrap** — ETH ↔ WETH and equivalents on each chain
|
|
16
|
-
- **Approve token** — ERC-20 spending allowance
|
|
17
|
-
- **Custom chat UI** — Custom title, welcome message, floating button icon, header icon, suggestion buttons, and fully custom chat button
|
|
18
|
-
- **Multi-language** — English, Japanese, Chinese UI
|
|
19
|
-
- **Multi-chain** — Ethereum, Optimism, BNB Chain, Polygon, Base, Arbitrum, Avalanche, Linea
|
|
20
|
-
- **Full TypeScript** — Complete type declarations included
|
|
21
|
-
|
|
22
|
-
---
|
|
23
|
-
|
|
24
|
-
## Installation
|
|
25
|
-
|
|
26
|
-
```bash
|
|
27
|
-
npm install keyring-chatbot-agent-sdk-test
|
|
28
|
-
# or
|
|
29
|
-
yarn add keyring-chatbot-agent-sdk-test
|
|
30
|
-
```
|
|
31
|
-
|
|
32
|
-
**Peer dependencies** (React 17, 18, or 19):
|
|
9
|
+
## Install
|
|
33
10
|
|
|
34
11
|
```bash
|
|
35
|
-
|
|
12
|
+
yarn add keyring-chatbot-agent
|
|
13
|
+
# peer deps
|
|
14
|
+
yarn add react react-dom
|
|
36
15
|
```
|
|
37
16
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
## React Usage
|
|
17
|
+
Peer deps: `react` / `react-dom` (17, 18 or 19).
|
|
41
18
|
|
|
42
|
-
|
|
19
|
+
## Quick start
|
|
43
20
|
|
|
44
21
|
```tsx
|
|
45
|
-
import { ChatWidget } from 'keyring-chatbot-agent
|
|
46
|
-
import type {
|
|
47
|
-
Transaction,
|
|
48
|
-
TransactionResult,
|
|
49
|
-
} from 'keyring-chatbot-agent-sdk-test';
|
|
22
|
+
import { ChatWidget } from 'keyring-chatbot-agent';
|
|
23
|
+
import type { Transaction, TransactionResult } from 'keyring-chatbot-agent';
|
|
50
24
|
|
|
51
|
-
function App() {
|
|
25
|
+
export function App() {
|
|
26
|
+
// Sign + broadcast with your own wallet/provider, then report the result.
|
|
52
27
|
const handleTransaction = async (
|
|
53
28
|
tx: Transaction
|
|
54
29
|
): Promise<TransactionResult> => {
|
|
55
30
|
try {
|
|
56
|
-
const hash = await
|
|
31
|
+
const hash = await wallet.sendTransaction({
|
|
32
|
+
from: tx.from,
|
|
33
|
+
to: tx.to,
|
|
34
|
+
data: tx.data,
|
|
35
|
+
value: tx.value, // wei, decimal string
|
|
36
|
+
chainId: tx.chainId,
|
|
37
|
+
});
|
|
57
38
|
return { status: 'success', transactionHash: hash };
|
|
58
|
-
} catch (err
|
|
39
|
+
} catch (err) {
|
|
59
40
|
return { status: 'fail', error: (err as Error).message };
|
|
60
41
|
}
|
|
61
42
|
};
|
|
62
43
|
|
|
63
44
|
return (
|
|
64
45
|
<ChatWidget
|
|
65
|
-
account={{ address: '0x
|
|
46
|
+
account={{ address: '0x…', chainId: 8453 }}
|
|
47
|
+
language="en"
|
|
48
|
+
position="bottom-right"
|
|
49
|
+
theme={{ buttonSize: 56 }}
|
|
66
50
|
onTransaction={handleTransaction}
|
|
67
51
|
/>
|
|
68
52
|
);
|
|
69
53
|
}
|
|
70
54
|
```
|
|
71
55
|
|
|
72
|
-
|
|
56
|
+
The widget creates **one chat session per mount**, persists history in
|
|
57
|
+
`localStorage`, and forwards the connected wallet address + chain so wallet /
|
|
58
|
+
token / NFT lookups have the context they need.
|
|
73
59
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
TransactionResult,
|
|
79
|
-
} from 'keyring-chatbot-agent-sdk-test';
|
|
60
|
+
> The session is built once on mount. Changing `account`'s address/chain after
|
|
61
|
+
> mount does not rebuild it — remount the widget with a new React `key` (e.g.
|
|
62
|
+
> ``key={`${address}-${chainId}`}``) when you want a fresh session on account
|
|
63
|
+
> switch.
|
|
80
64
|
|
|
81
|
-
|
|
82
|
-
const handleTransaction = async (
|
|
83
|
-
tx: Transaction
|
|
84
|
-
): Promise<TransactionResult> => {
|
|
85
|
-
try {
|
|
86
|
-
const hash = await walletClient.sendTransaction(tx);
|
|
87
|
-
return { status: 'success', transactionHash: hash };
|
|
88
|
-
} catch (err: unknown) {
|
|
89
|
-
return { status: 'fail', error: (err as Error).message };
|
|
90
|
-
}
|
|
91
|
-
};
|
|
65
|
+
## When the widget renders
|
|
92
66
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
onClose={() => console.log('Chat closed')}
|
|
128
|
-
/>
|
|
129
|
-
);
|
|
130
|
-
}
|
|
67
|
+
`<ChatWidget>` returns `null` (renders nothing) unless **both**:
|
|
68
|
+
|
|
69
|
+
1. `account.address` is a valid address and `account.chainId` is set, and
|
|
70
|
+
2. the current `window.location.origin` is allowed.
|
|
71
|
+
|
|
72
|
+
Origins are gated by `WHITELIST_ORIGIN` in `src/shared/app.ts`. `localhost`
|
|
73
|
+
always passes for local dev; an empty whitelist disables the gate.
|
|
74
|
+
|
|
75
|
+
## `onTransaction`
|
|
76
|
+
|
|
77
|
+
Invoked when the user confirms an action form (`send` / `approve` / `wrap` /
|
|
78
|
+
`unwrap` / `send_nft`) or a buy/swap confirmation. The widget passes an unsigned
|
|
79
|
+
transaction; the host signs, broadcasts, and returns the result. **Required**
|
|
80
|
+
for any on-chain action — without it the widget can only answer questions.
|
|
81
|
+
|
|
82
|
+
```ts
|
|
83
|
+
type Transaction = {
|
|
84
|
+
from: string;
|
|
85
|
+
to: string;
|
|
86
|
+
data: string;
|
|
87
|
+
value: string; // wei, decimal string
|
|
88
|
+
chainId?: number | string;
|
|
89
|
+
gasLimit?: string;
|
|
90
|
+
gasPrice?: string;
|
|
91
|
+
maxFeePerGas?: string;
|
|
92
|
+
maxPriorityFeePerGas?: string;
|
|
93
|
+
nonce?: number;
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
type TransactionResult = {
|
|
97
|
+
status: 'success' | 'fail';
|
|
98
|
+
transactionHash?: string;
|
|
99
|
+
error?: string;
|
|
100
|
+
};
|
|
131
101
|
```
|
|
132
102
|
|
|
133
|
-
|
|
103
|
+
Before signing, the widget pre-flights the tx against the wallet's native
|
|
104
|
+
balance (gas + value). If it can't cover it, the widget posts an
|
|
105
|
+
"insufficient gas" message in the user's language and never calls
|
|
106
|
+
`onTransaction`. A flaky RPC fails open — the wallet stays the final gatekeeper.
|
|
107
|
+
|
|
108
|
+
## Props
|
|
109
|
+
|
|
110
|
+
| Prop | Type | Default | Notes |
|
|
111
|
+
| ----------------------- | ----------------------------------------------- | ---------------- | --------------------------------------------------------------------- |
|
|
112
|
+
| `account` | `{ address: string; chainId: number \| string }`| — | Connected wallet. Required for the widget to render. |
|
|
113
|
+
| `onTransaction` | `(tx) => Promise<TransactionResult>` | — | Sign + broadcast handler. Required for on-chain actions. |
|
|
114
|
+
| `language` | `'en' \| 'ja' \| 'cn'` | `'en'` | UI language. Per-message language from the agent is honored too. |
|
|
115
|
+
| `rpcUrls` | `Record<number, string>` | built-in | RPC per **numeric** chainId. Merged over the built-in defaults. |
|
|
116
|
+
| `position` | `'bottom-right' \| 'bottom-left'` | `'bottom-right'` | Anchor of the floating button + modal. |
|
|
117
|
+
| `theme` | `ChatWidgetTheme` | `{}` | `primaryColor`, `buttonSize`, `zIndex`, `modalChatStyle`, `offset`. |
|
|
118
|
+
| `defaultOpen` | `boolean` | `false` | Open the modal on mount. |
|
|
119
|
+
| `onOpen` / `onClose` | `() => void` | — | Fired when the modal opens / closes. |
|
|
120
|
+
| `chatTitle` | `string` | built-in | Header title. |
|
|
121
|
+
| `welcomeMessage` | `string` | localized | First bot bubble. |
|
|
122
|
+
| `customSuggestions` | `SuggestionButtonConfig[]` | built-in chips | Replace the default suggestion chips. |
|
|
123
|
+
| `additionalSuggestions` | `SuggestionButtonConfig[]` | — | Append extra chips after the base set. |
|
|
124
|
+
| `buttonIcon` | `string` | — | Custom floating-button icon. |
|
|
125
|
+
| `chatIcon` | `string` | built-in | Header / avatar icon. |
|
|
126
|
+
| `customChatButton` | `ReactNode` | — | Replace the floating button entirely. |
|
|
127
|
+
| `styleButtonChat` | `CSSProperties` | — | Extra styles on the floating container. |
|
|
128
|
+
| `modalConfig` | `{ isShowIcon?: boolean }` | `{}` | Modal-level toggles. |
|
|
129
|
+
|
|
130
|
+
`SuggestionButtonConfig` is `{ icon?: string; text: string }`.
|
|
131
|
+
|
|
132
|
+
> Agent behavior (model, subagents, storage key, data sources, …) is **not** a
|
|
133
|
+
> prop — it's fixed by the package descriptor in `src/shared/app.ts`. The only
|
|
134
|
+
> agent-related prop is `rpcUrls`.
|
|
135
|
+
|
|
136
|
+
### Prop details & examples
|
|
137
|
+
|
|
138
|
+
#### `account` (required to render)
|
|
139
|
+
|
|
140
|
+
The connected wallet. Pass `undefined` while disconnected — the widget then
|
|
141
|
+
renders nothing. `chainId` may be a number (`8453`) or hex string (`"0x2105"`).
|
|
134
142
|
|
|
135
143
|
```tsx
|
|
136
|
-
|
|
137
|
-
import { ChatWidget } from 'keyring-chatbot-agent-sdk-test';
|
|
138
|
-
import type {
|
|
139
|
-
Transaction,
|
|
140
|
-
TransactionResult,
|
|
141
|
-
} from 'keyring-chatbot-agent-sdk-test';
|
|
144
|
+
<ChatWidget account={{ address: '0xAbc…123', chainId: 8453 }} />
|
|
142
145
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
+
// Disconnected → widget renders null:
|
|
147
|
+
<ChatWidget account={connected ? { address, chainId } : undefined} />
|
|
148
|
+
```
|
|
146
149
|
|
|
147
|
-
|
|
148
|
-
tx: Transaction
|
|
149
|
-
): Promise<TransactionResult> => {
|
|
150
|
-
try {
|
|
151
|
-
const hash = await sendTransactionAsync({
|
|
152
|
-
to: tx.to as `0x${string}`,
|
|
153
|
-
data: tx.data as `0x${string}`,
|
|
154
|
-
value: BigInt(tx.value || '0'),
|
|
155
|
-
});
|
|
156
|
-
return { status: 'success', transactionHash: hash };
|
|
157
|
-
} catch (err: unknown) {
|
|
158
|
-
return { status: 'fail', error: (err as Error).message };
|
|
159
|
-
}
|
|
160
|
-
};
|
|
150
|
+
Remount on identity change to start a fresh session:
|
|
161
151
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
account={address ? { address, chainId: chainId ?? 1 } : undefined}
|
|
165
|
-
onTransaction={handleTransaction}
|
|
166
|
-
/>
|
|
167
|
-
);
|
|
168
|
-
}
|
|
152
|
+
```tsx
|
|
153
|
+
<ChatWidget key={`${address}-${chainId}`} account={{ address, chainId }} />
|
|
169
154
|
```
|
|
170
155
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
| `onTransaction` | `(tx: Transaction) => Promise<TransactionResult>` | `undefined` | \* | Called when the chatbot needs to sign/send a transaction. |
|
|
177
|
-
| `position` | `'bottom-right'` \| `'bottom-left'` | `'bottom-right'` | No | Corner where the floating button appears. |
|
|
178
|
-
| `language` | `'en'` \| `'ja'` \| `'cn'` | `'en'` | No | UI language. |
|
|
179
|
-
| `theme` | `ChatWidgetTheme` | `{}` | No | Visual customization (color, size, z-index). |
|
|
180
|
-
| `defaultOpen` | `boolean` | `false` | No | Open the chat modal on first render. |
|
|
181
|
-
| `rpcUrls` | `Record<number, string>` | — | No | Per-chain RPC URL overrides. Takes priority over built-in defaults for balance queries and gas estimation. |
|
|
182
|
-
| `onOpen` | `() => void` | — | No | Callback fired when the modal opens. |
|
|
183
|
-
| `onClose` | `() => void` | — | No | Callback fired when the modal closes. |
|
|
184
|
-
| `chatTitle` | `string` | built-in title | No | Override the title shown in the modal header. |
|
|
185
|
-
| `welcomeMessage` | `string` | built-in message | No | Override the first assistant message shown in the conversation. |
|
|
186
|
-
| `customSuggestions` | `SuggestionButtonConfig[]` | built-in list | No | Replace the default quick suggestion buttons. Each item needs `text`; `icon` is optional. |
|
|
187
|
-
| `buttonIcon` | `string` | built-in icon | No | Custom image URL for the floating chat button icon. |
|
|
188
|
-
| `chatIcon` | `string` | built-in logo | No | Custom image URL for the modal header logo. |
|
|
189
|
-
| `customChatButton` | `React.ReactNode` | `undefined` | No | Fully custom React element to replace the default floating chat button. Click handling is applied automatically. |
|
|
190
|
-
| `styleButtonChat` | `React.CSSProperties` | `undefined` | No | Custom CSS styles applied to the floating chat button container. |
|
|
191
|
-
|
|
192
|
-
> \* `onTransaction` is required to execute on-chain actions (swap, send, approve, etc.). Without it, the AI can still answer questions and display information.
|
|
193
|
-
|
|
194
|
-
### Chat UI customization
|
|
156
|
+
#### `onTransaction` (required for on-chain actions)
|
|
157
|
+
|
|
158
|
+
Called when the user confirms a wallet action. Sign + broadcast, then return the
|
|
159
|
+
result. See [`onTransaction`](#ontransaction) for the full `Transaction` /
|
|
160
|
+
`TransactionResult` shapes.
|
|
195
161
|
|
|
196
162
|
```tsx
|
|
197
163
|
<ChatWidget
|
|
198
|
-
account={{ address
|
|
199
|
-
onTransaction={
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
padding: 12,
|
|
208
|
-
background: '#5B7FFF',
|
|
209
|
-
borderRadius: 16,
|
|
210
|
-
color: '#fff',
|
|
211
|
-
}}
|
|
212
|
-
>
|
|
213
|
-
💬 Chat with AI
|
|
214
|
-
</div>
|
|
215
|
-
}
|
|
216
|
-
customSuggestions={[
|
|
217
|
-
{ text: 'Check my portfolio', icon: '📊' },
|
|
218
|
-
{ text: 'Swap ETH to USDC', icon: '🔄' },
|
|
219
|
-
{ text: 'Show trending tokens' },
|
|
220
|
-
]}
|
|
221
|
-
styleButtonChat={{ bottom: 100, right: 30 }}
|
|
164
|
+
account={{ address, chainId }}
|
|
165
|
+
onTransaction={async (tx) => {
|
|
166
|
+
try {
|
|
167
|
+
const hash = await wallet.sendTransaction(tx);
|
|
168
|
+
return { status: 'success', transactionHash: hash };
|
|
169
|
+
} catch (e) {
|
|
170
|
+
return { status: 'fail', error: (e as Error).message };
|
|
171
|
+
}
|
|
172
|
+
}}
|
|
222
173
|
/>
|
|
223
174
|
```
|
|
224
175
|
|
|
225
|
-
`
|
|
176
|
+
#### `language`
|
|
226
177
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
}
|
|
178
|
+
UI language for the widget's own strings: `'en'` | `'ja'` | `'cn'`. The agent
|
|
179
|
+
also tags each reply with a language, which is honored per-message.
|
|
180
|
+
|
|
181
|
+
```tsx
|
|
182
|
+
<ChatWidget account={acct} language="ja" />
|
|
232
183
|
```
|
|
233
184
|
|
|
234
|
-
|
|
185
|
+
#### `rpcUrls`
|
|
235
186
|
|
|
236
|
-
|
|
187
|
+
Override RPC endpoints, keyed by **numeric** chainId. Merged over the built-in
|
|
188
|
+
defaults, so you only list the chains you want to change.
|
|
237
189
|
|
|
238
190
|
```tsx
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
account={{ address: userAddress, chainId: 10 }}
|
|
247
|
-
onTransaction={handleTransaction}
|
|
248
|
-
/>
|
|
249
|
-
</>
|
|
250
|
-
);
|
|
251
|
-
}
|
|
191
|
+
<ChatWidget
|
|
192
|
+
account={acct}
|
|
193
|
+
rpcUrls={{
|
|
194
|
+
1: 'https://my-eth-rpc.example',
|
|
195
|
+
8453: 'https://my-base-rpc.example',
|
|
196
|
+
}}
|
|
197
|
+
/>
|
|
252
198
|
```
|
|
253
199
|
|
|
254
|
-
|
|
200
|
+
#### `position`
|
|
255
201
|
|
|
256
|
-
|
|
202
|
+
Which corner the floating button + modal anchor to: `'bottom-right'` (default)
|
|
203
|
+
or `'bottom-left'`.
|
|
257
204
|
|
|
258
|
-
|
|
205
|
+
```tsx
|
|
206
|
+
<ChatWidget account={acct} position="bottom-left" />
|
|
207
|
+
```
|
|
259
208
|
|
|
260
|
-
|
|
209
|
+
#### `theme`
|
|
261
210
|
|
|
262
|
-
|
|
211
|
+
```ts
|
|
212
|
+
type ChatWidgetTheme = {
|
|
213
|
+
primaryColor?: string;
|
|
214
|
+
buttonSize?: number; // px
|
|
215
|
+
zIndex?: number;
|
|
216
|
+
modalChatStyle?: React.CSSProperties; // styles on the modal surface
|
|
217
|
+
offset?: { x: number; y: number }; // px from the anchored corner
|
|
218
|
+
};
|
|
219
|
+
```
|
|
263
220
|
|
|
264
|
-
|
|
221
|
+
```tsx
|
|
222
|
+
<ChatWidget
|
|
223
|
+
account={acct}
|
|
224
|
+
theme={{
|
|
225
|
+
primaryColor: '#0b3988',
|
|
226
|
+
buttonSize: 56,
|
|
227
|
+
zIndex: 9999,
|
|
228
|
+
offset: { x: 24, y: 24 },
|
|
229
|
+
modalChatStyle: { width: 420, maxHeight: '70vh' },
|
|
230
|
+
}}
|
|
231
|
+
/>
|
|
232
|
+
```
|
|
265
233
|
|
|
266
|
-
|
|
234
|
+
#### `defaultOpen`, `onOpen`, `onClose`
|
|
267
235
|
|
|
268
|
-
|
|
269
|
-
| --------------- | --------- | ---------------- | ------------------------------------------------ |
|
|
270
|
-
| `position` | `string` | `'bottom-right'` | `'bottom-right'` or `'bottom-left'` |
|
|
271
|
-
| `primary-color` | `string` | `'#007bff'` | Widget accent color (hex or any CSS color value) |
|
|
272
|
-
| `button-size` | `number` | `60` | Floating button diameter in pixels |
|
|
273
|
-
| `z-index` | `number` | `9999` | CSS `z-index` of the widget |
|
|
274
|
-
| `default-open` | `boolean` | `false` | Set to `"true"` to open the chat on page load |
|
|
275
|
-
| `language` | `string` | `'en'` | UI language: `'en'`, `'ja'`, or `'cn'` |
|
|
236
|
+
Open on mount and observe open/close.
|
|
276
237
|
|
|
277
|
-
|
|
238
|
+
```tsx
|
|
239
|
+
<ChatWidget
|
|
240
|
+
account={acct}
|
|
241
|
+
defaultOpen
|
|
242
|
+
onOpen={() => analytics.track('chat_open')}
|
|
243
|
+
onClose={() => analytics.track('chat_close')}
|
|
244
|
+
/>
|
|
245
|
+
```
|
|
278
246
|
|
|
279
|
-
|
|
247
|
+
#### `chatTitle`, `welcomeMessage`
|
|
280
248
|
|
|
281
|
-
|
|
282
|
-
| ------------------- | ------------------------------------------------- | ---------------------------------------------------------- |
|
|
283
|
-
| `account` | `{ address: string; chainId: number }` | Connected wallet info |
|
|
284
|
-
| `onTransaction` | `(tx: Transaction) => Promise<TransactionResult>` | Transaction signing / sending handler |
|
|
285
|
-
| `rpcUrls` | `Record<number, string>` | Per-chain RPC URL overrides |
|
|
286
|
-
| `onOpen` | `() => void` | Callback fired when the modal opens |
|
|
287
|
-
| `onClose` | `() => void` | Callback fired when the modal closes |
|
|
288
|
-
| `chatTitle` | `string` | Custom modal header title |
|
|
289
|
-
| `welcomeMessage` | `string` | Custom first assistant message |
|
|
290
|
-
| `customSuggestions` | `{ text: string; icon?: string }[]` | Custom quick suggestion buttons |
|
|
291
|
-
| `buttonIcon` | `string` | Custom floating button icon URL |
|
|
292
|
-
| `chatIcon` | `string` | Custom modal header logo URL |
|
|
293
|
-
| `customChatButton` | `React.ReactNode` | Fully custom element replacing the default floating button |
|
|
294
|
-
| `styleButtonChat` | `React.CSSProperties` | Custom CSS styles for the floating button container |
|
|
249
|
+
Header title and the first bot bubble.
|
|
295
250
|
|
|
296
|
-
|
|
251
|
+
```tsx
|
|
252
|
+
<ChatWidget
|
|
253
|
+
account={acct}
|
|
254
|
+
chatTitle="Ask Keyring"
|
|
255
|
+
welcomeMessage="Hi! Ask me about your wallet, tokens, or NFTs."
|
|
256
|
+
/>
|
|
257
|
+
```
|
|
297
258
|
|
|
298
|
-
|
|
299
|
-
| ------------- | -------------------------- |
|
|
300
|
-
| `clearChat()` | Clear current chat history |
|
|
259
|
+
#### `customSuggestions` vs `additionalSuggestions`
|
|
301
260
|
|
|
302
|
-
|
|
261
|
+
Suggestion chips above the input. `customSuggestions` **replaces** the built-in
|
|
262
|
+
set; `additionalSuggestions` **appends** after the base set. Each chip is
|
|
263
|
+
`{ icon?: string; text: string }` — `text` is sent as the prompt when tapped.
|
|
303
264
|
|
|
304
|
-
```
|
|
305
|
-
|
|
306
|
-
<
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
<script src="https://unpkg.com/keyring-chatbot-agent-sdk-test/dist/chat-widget-wc.umd.js"></script>
|
|
265
|
+
```tsx
|
|
266
|
+
// Replace the defaults entirely:
|
|
267
|
+
<ChatWidget
|
|
268
|
+
account={acct}
|
|
269
|
+
customSuggestions={[
|
|
270
|
+
{ icon: '💸', text: 'Send 0.01 ETH' },
|
|
271
|
+
{ icon: '📈', text: 'Show my token balances' },
|
|
272
|
+
]}
|
|
273
|
+
/>
|
|
314
274
|
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
button-size="60"
|
|
321
|
-
z-index="9999"
|
|
322
|
-
language="en"
|
|
323
|
-
></chat-widget>
|
|
324
|
-
|
|
325
|
-
<!-- 3. Assign account and onTransaction via JavaScript -->
|
|
326
|
-
<script>
|
|
327
|
-
const widget = document.getElementById('my-chat');
|
|
328
|
-
|
|
329
|
-
// Set wallet info (reassign whenever the wallet changes)
|
|
330
|
-
widget.account = { address: '0xYourWalletAddress', chainId: 10 };
|
|
331
|
-
|
|
332
|
-
// Set the transaction handler
|
|
333
|
-
widget.onTransaction = async function (tx) {
|
|
334
|
-
try {
|
|
335
|
-
// Works with any provider: ethers.js, viem, MetaMask, etc.
|
|
336
|
-
const provider = new ethers.BrowserProvider(window.ethereum);
|
|
337
|
-
const signer = await provider.getSigner();
|
|
338
|
-
const txResponse = await signer.sendTransaction({
|
|
339
|
-
to: tx.to,
|
|
340
|
-
data: tx.data,
|
|
341
|
-
value: BigInt(tx.value || '0'),
|
|
342
|
-
});
|
|
343
|
-
const receipt = await txResponse.wait();
|
|
344
|
-
return { status: 'success', transactionHash: receipt.hash };
|
|
345
|
-
} catch (err) {
|
|
346
|
-
return { status: 'fail', error: err.message };
|
|
347
|
-
}
|
|
348
|
-
};
|
|
349
|
-
|
|
350
|
-
// Optional: override RPC URLs
|
|
351
|
-
widget.rpcUrls = {
|
|
352
|
-
10: 'https://optimism-mainnet.infura.io/v3/YOUR_KEY',
|
|
353
|
-
8453: 'https://mainnet.base.org',
|
|
354
|
-
};
|
|
355
|
-
|
|
356
|
-
widget.chatTitle = 'Keyring Assistant';
|
|
357
|
-
widget.welcomeMessage = 'How can I help you today?';
|
|
358
|
-
widget.buttonIcon = 'https://your-cdn.com/chat-button.svg';
|
|
359
|
-
widget.chatIcon = 'https://your-cdn.com/chat-header-logo.svg';
|
|
360
|
-
widget.customSuggestions = [
|
|
361
|
-
{ text: 'Show my balance', icon: '💼' },
|
|
362
|
-
{ text: 'Swap ETH to USDC', icon: '🔄' },
|
|
363
|
-
{ text: 'Show trending tokens' },
|
|
364
|
-
];
|
|
365
|
-
|
|
366
|
-
// Optional: use a fully custom chat button (React.ReactNode)
|
|
367
|
-
// widget.customChatButton = yourCustomElement;
|
|
368
|
-
|
|
369
|
-
// Optional: custom style for the chat button container
|
|
370
|
-
// widget.styleButtonChat = { bottom: '100px', right: '30px' };
|
|
371
|
-
|
|
372
|
-
// Clear chat history when needed
|
|
373
|
-
widget.clearChat();
|
|
374
|
-
</script>
|
|
375
|
-
</body>
|
|
376
|
-
</html>
|
|
275
|
+
// Keep the defaults, add two more:
|
|
276
|
+
<ChatWidget
|
|
277
|
+
account={acct}
|
|
278
|
+
additionalSuggestions={[{ icon: '🖼️', text: 'List my NFTs' }]}
|
|
279
|
+
/>
|
|
377
280
|
```
|
|
378
281
|
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
```html
|
|
382
|
-
<!DOCTYPE html>
|
|
383
|
-
<html lang="en">
|
|
384
|
-
<head>
|
|
385
|
-
<meta charset="UTF-8" />
|
|
386
|
-
<title>My dApp</title>
|
|
387
|
-
</head>
|
|
388
|
-
<body>
|
|
389
|
-
<chat-widget
|
|
390
|
-
id="my-chat"
|
|
391
|
-
position="bottom-right"
|
|
392
|
-
language="en"
|
|
393
|
-
></chat-widget>
|
|
282
|
+
#### `buttonIcon`, `chatIcon`
|
|
394
283
|
|
|
395
|
-
|
|
396
|
-
|
|
284
|
+
Image URLs. `buttonIcon` is the floating button; `chatIcon` is the header /
|
|
285
|
+
avatar icon.
|
|
397
286
|
|
|
398
|
-
|
|
287
|
+
```tsx
|
|
288
|
+
<ChatWidget
|
|
289
|
+
account={acct}
|
|
290
|
+
buttonIcon="https://cdn.example/chat.png"
|
|
291
|
+
chatIcon="https://cdn.example/avatar.png"
|
|
292
|
+
/>
|
|
293
|
+
```
|
|
399
294
|
|
|
400
|
-
|
|
295
|
+
#### `customChatButton`
|
|
401
296
|
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
};
|
|
405
|
-
</script>
|
|
406
|
-
</body>
|
|
407
|
-
</html>
|
|
408
|
-
```
|
|
297
|
+
Replace the floating button with your own node. The widget still owns the
|
|
298
|
+
open/close behavior, so render a presentational element (no `onClick` needed).
|
|
409
299
|
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
<
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
<script src="https://unpkg.com/keyring-chatbot-agent-sdk-test/dist/chat-widget-wc.umd.js"></script>
|
|
420
|
-
</head>
|
|
421
|
-
<body>
|
|
422
|
-
<button id="connect-btn">Connect Wallet</button>
|
|
423
|
-
<chat-widget
|
|
424
|
-
id="my-chat"
|
|
425
|
-
position="bottom-right"
|
|
426
|
-
language="en"
|
|
427
|
-
></chat-widget>
|
|
428
|
-
|
|
429
|
-
<script>
|
|
430
|
-
const widget = document.getElementById('my-chat');
|
|
431
|
-
|
|
432
|
-
widget.onTransaction = async function (tx) {
|
|
433
|
-
try {
|
|
434
|
-
const provider = new ethers.BrowserProvider(window.ethereum);
|
|
435
|
-
const signer = await provider.getSigner();
|
|
436
|
-
const txResponse = await signer.sendTransaction({
|
|
437
|
-
to: tx.to,
|
|
438
|
-
data: tx.data,
|
|
439
|
-
value: BigInt(tx.value || '0'),
|
|
440
|
-
});
|
|
441
|
-
const receipt = await txResponse.wait();
|
|
442
|
-
return { status: 'success', transactionHash: receipt.hash };
|
|
443
|
-
} catch (err) {
|
|
444
|
-
return { status: 'fail', error: err.message };
|
|
445
|
-
}
|
|
446
|
-
};
|
|
447
|
-
|
|
448
|
-
document.getElementById('connect-btn').onclick = async function () {
|
|
449
|
-
if (!window.ethereum) return alert('Please install MetaMask!');
|
|
450
|
-
const provider = new ethers.BrowserProvider(window.ethereum);
|
|
451
|
-
const accounts = await provider.send('eth_requestAccounts', []);
|
|
452
|
-
const network = await provider.getNetwork();
|
|
453
|
-
widget.account = {
|
|
454
|
-
address: accounts[0],
|
|
455
|
-
chainId: Number(network.chainId),
|
|
456
|
-
};
|
|
457
|
-
};
|
|
458
|
-
|
|
459
|
-
// React to wallet / chain changes
|
|
460
|
-
if (window.ethereum) {
|
|
461
|
-
window.ethereum.on('accountsChanged', async (accounts) => {
|
|
462
|
-
if (accounts.length === 0) {
|
|
463
|
-
widget.account = undefined;
|
|
464
|
-
} else {
|
|
465
|
-
const provider = new ethers.BrowserProvider(window.ethereum);
|
|
466
|
-
const network = await provider.getNetwork();
|
|
467
|
-
widget.account = {
|
|
468
|
-
address: accounts[0],
|
|
469
|
-
chainId: Number(network.chainId),
|
|
470
|
-
};
|
|
471
|
-
}
|
|
472
|
-
});
|
|
473
|
-
window.ethereum.on('chainChanged', async () => {
|
|
474
|
-
const provider = new ethers.BrowserProvider(window.ethereum);
|
|
475
|
-
const network = await provider.getNetwork();
|
|
476
|
-
const accounts = await provider.listAccounts();
|
|
477
|
-
if (accounts.length > 0) {
|
|
478
|
-
widget.account = {
|
|
479
|
-
address: accounts[0].address,
|
|
480
|
-
chainId: Number(network.chainId),
|
|
481
|
-
};
|
|
482
|
-
}
|
|
483
|
-
});
|
|
484
|
-
}
|
|
485
|
-
</script>
|
|
486
|
-
</body>
|
|
487
|
-
</html>
|
|
300
|
+
```tsx
|
|
301
|
+
<ChatWidget
|
|
302
|
+
account={acct}
|
|
303
|
+
customChatButton={
|
|
304
|
+
<div className="my-fab">
|
|
305
|
+
<img src="/chat.svg" alt="" /> Chat
|
|
306
|
+
</div>
|
|
307
|
+
}
|
|
308
|
+
/>
|
|
488
309
|
```
|
|
489
310
|
|
|
490
|
-
|
|
311
|
+
#### `styleButtonChat`
|
|
491
312
|
|
|
492
|
-
|
|
313
|
+
Extra inline styles applied to the floating container (merged over the
|
|
314
|
+
position/offset styles).
|
|
493
315
|
|
|
494
|
-
```
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
chainId: number | string; // EIP-155 chain ID
|
|
498
|
-
}
|
|
316
|
+
```tsx
|
|
317
|
+
<ChatWidget account={acct} styleButtonChat={{ bottom: 96, right: 32 }} />
|
|
318
|
+
```
|
|
499
319
|
|
|
500
|
-
|
|
501
|
-
from: string;
|
|
502
|
-
to: string;
|
|
503
|
-
data: string; // ABI-encoded calldata (hex)
|
|
504
|
-
value: string; // Native token amount in wei
|
|
505
|
-
gasLimit?: string;
|
|
506
|
-
gasPrice?: string;
|
|
507
|
-
maxFeePerGas?: string;
|
|
508
|
-
maxPriorityFeePerGas?: string;
|
|
509
|
-
nonce?: number;
|
|
510
|
-
chainId?: number | string;
|
|
511
|
-
}
|
|
320
|
+
#### `modalConfig`
|
|
512
321
|
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
transactionHash?: string; // Present on success
|
|
516
|
-
error?: string; // Present on failure
|
|
517
|
-
}
|
|
322
|
+
Modal-level toggles. Currently `{ isShowIcon?: boolean }` (default `true`) —
|
|
323
|
+
set `false` to hide the header icon.
|
|
518
324
|
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
zIndex?: number; // CSS z-index
|
|
523
|
-
}
|
|
325
|
+
```tsx
|
|
326
|
+
<ChatWidget account={acct} modalConfig={{ isShowIcon: false }} />
|
|
327
|
+
```
|
|
524
328
|
|
|
525
|
-
|
|
526
|
-
text: string;
|
|
527
|
-
icon?: string;
|
|
528
|
-
}
|
|
329
|
+
### A fuller example
|
|
529
330
|
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
suggestions?: SuggestionButtonConfig[];
|
|
534
|
-
buttonIcon?: string;
|
|
535
|
-
chatIcon?: string;
|
|
536
|
-
}
|
|
331
|
+
```tsx
|
|
332
|
+
import { ChatWidget } from 'keyring-chatbot-agent';
|
|
333
|
+
import type { Transaction, TransactionResult } from 'keyring-chatbot-agent';
|
|
537
334
|
|
|
538
|
-
|
|
539
|
-
|
|
335
|
+
export function Chat({ address, chainId, connected }) {
|
|
336
|
+
const onTransaction = async (tx: Transaction): Promise<TransactionResult> => {
|
|
337
|
+
try {
|
|
338
|
+
const hash = await wallet.sendTransaction(tx);
|
|
339
|
+
return { status: 'success', transactionHash: hash };
|
|
340
|
+
} catch (e) {
|
|
341
|
+
return { status: 'fail', error: (e as Error).message };
|
|
342
|
+
}
|
|
343
|
+
};
|
|
540
344
|
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
---
|
|
557
|
-
|
|
558
|
-
## AI Capabilities
|
|
559
|
-
|
|
560
|
-
The embedded AI (GPT-4.1-mini via Moralis Cortex) understands natural language and automatically routes to on-chain actions:
|
|
561
|
-
|
|
562
|
-
| What the user says | Action performed |
|
|
563
|
-
| ---------------------------------- | ------------------------------------ |
|
|
564
|
-
| "Swap 1 ETH to USDC" | Token swap via deBridge |
|
|
565
|
-
| "Swap max USDT to ETH" | Swap with full-balance resolution |
|
|
566
|
-
| "Buy WBTC" | Trending token list for selection |
|
|
567
|
-
| "Send 10 USDC to 0x..." | ERC-20 transfer |
|
|
568
|
-
| "Send 0.05 ETH to 0x..." | Native token transfer |
|
|
569
|
-
| "Wrap 1 ETH" / "Unwrap 0.5 WETH" | Wrap / unwrap native token |
|
|
570
|
-
| "Show my NFTs" | Link to NFT gallery |
|
|
571
|
-
| "Send my Bored Ape #1234 to 0x..." | ERC-721 / ERC-1155 transfer |
|
|
572
|
-
| "What is the current gas fee?" | General blockchain Q&A |
|
|
573
|
-
| "What tokens are trending?" | Trending list with quick-buy buttons |
|
|
574
|
-
| "What is my balance?" | Token list with USD values |
|
|
575
|
-
|
|
576
|
-
### Smart swap flow
|
|
577
|
-
|
|
578
|
-
The AI handles missing parameters gracefully:
|
|
579
|
-
|
|
580
|
-
| Available information | Behaviour |
|
|
581
|
-
| -------------------------------- | --------------------------------------------- |
|
|
582
|
-
| token_in + token_out + amount | Full auto-swap: estimate → confirm → execute |
|
|
583
|
-
| token_in + token_out (no amount) | Shows 25 / 50 / 75 / 100 % amount selector |
|
|
584
|
-
| token_out only | Shows wallet balances to choose source token |
|
|
585
|
-
| token_in only | Shows trending tokens to choose destination |
|
|
586
|
-
| Neither token specified | Asks the user to specify both tokens |
|
|
587
|
-
| ERC-20 needs approval | Prompts Approve step before swap |
|
|
588
|
-
| Insufficient balance or fee | Warning message, no confirmation button shown |
|
|
589
|
-
|
|
590
|
-
---
|
|
591
|
-
|
|
592
|
-
## Build Outputs
|
|
593
|
-
|
|
594
|
-
| File | Format | Use case |
|
|
595
|
-
| ---------------------------- | ------ | ------------------------------------------ |
|
|
596
|
-
| `dist/chat-widget.es.js` | ESM | React / Vite / bundler |
|
|
597
|
-
| `dist/chat-widget.umd.js` | UMD | CommonJS / `require` |
|
|
598
|
-
| `dist/chat-widget-wc.es.js` | ESM | Web Component via `<script type="module">` |
|
|
599
|
-
| `dist/chat-widget-wc.umd.js` | UMD | Web Component via `<script src>` / CDN |
|
|
600
|
-
| `dist/lib.d.ts` | Types | TypeScript declarations |
|
|
601
|
-
|
|
602
|
-
### Package exports map
|
|
603
|
-
|
|
604
|
-
```json
|
|
605
|
-
{
|
|
606
|
-
".": {
|
|
607
|
-
"import": "dist/chat-widget.es.js",
|
|
608
|
-
"require": "dist/chat-widget.umd.js",
|
|
609
|
-
"types": "dist/lib.d.ts"
|
|
610
|
-
},
|
|
611
|
-
"./web-component": {
|
|
612
|
-
"import": "dist/chat-widget-wc.es.js",
|
|
613
|
-
"require": "dist/chat-widget-wc.umd.js"
|
|
614
|
-
}
|
|
345
|
+
return (
|
|
346
|
+
<ChatWidget
|
|
347
|
+
key={`${address}-${chainId}`}
|
|
348
|
+
account={connected ? { address, chainId } : undefined}
|
|
349
|
+
onTransaction={onTransaction}
|
|
350
|
+
language="en"
|
|
351
|
+
position="bottom-right"
|
|
352
|
+
theme={{ primaryColor: '#0b3988', buttonSize: 56, offset: { x: 24, y: 24 } }}
|
|
353
|
+
chatTitle="Ask Keyring"
|
|
354
|
+
welcomeMessage="Hi! Ask me about your wallet, tokens, or NFTs."
|
|
355
|
+
additionalSuggestions={[{ icon: '🖼️', text: 'List my NFTs' }]}
|
|
356
|
+
rpcUrls={{ 8453: 'https://my-base-rpc.example' }}
|
|
357
|
+
onOpen={() => console.log('opened')}
|
|
358
|
+
/>
|
|
359
|
+
);
|
|
615
360
|
}
|
|
616
361
|
```
|
|
617
362
|
|
|
618
|
-
##
|
|
363
|
+
## Clearing history
|
|
619
364
|
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
├── components/
|
|
623
|
-
│ ├── ActionForm.tsx # Inline transaction forms (send, approve, ...)
|
|
624
|
-
│ ├── ChatButton.tsx # Floating action button
|
|
625
|
-
│ ├── ChatModal.tsx # Chat UI + all AI and on-chain logic
|
|
626
|
-
│ ├── ChatWidget.tsx # Root component — public API entry point
|
|
627
|
-
│ ├── MessageContent.tsx # Markdown message renderer
|
|
628
|
-
│ ├── ScrollToBottomButton.tsx
|
|
629
|
-
│ └── WalletUserInfo.tsx
|
|
630
|
-
├── constants/
|
|
631
|
-
│ ├── agentActions.ts # AgentActionType definitions + form schemas
|
|
632
|
-
│ ├── chains.ts # Supported chain configs
|
|
633
|
-
│ ├── storage.ts # localStorage key constants
|
|
634
|
-
│ └── systemPrompt.ts # AI system prompt builder
|
|
635
|
-
├── contexts/
|
|
636
|
-
│ ├── ConfigContext.tsx # RPC URLs + theme config context
|
|
637
|
-
│ ├── ConnectContext.tsx # Wallet account context
|
|
638
|
-
│ └── LanguageContext.tsx # i18n language context
|
|
639
|
-
├── hooks/
|
|
640
|
-
│ └── useChatMessages.ts # Chat message state management
|
|
641
|
-
├── services/
|
|
642
|
-
│ ├── BaseApi.ts # Base HTTP client
|
|
643
|
-
│ ├── deBridge.ts # deBridge swap quote + transaction API
|
|
644
|
-
│ ├── gemini.ts # Gemini AI: question classification, general chat
|
|
645
|
-
│ ├── moralis.ts # Moralis AI chat, wallet balances, NFTs, metadata
|
|
646
|
-
│ ├── token.ts # Token info + trending data
|
|
647
|
-
│ └── web3.ts # Transaction builder, fee estimation, allowance check
|
|
648
|
-
├── types/
|
|
649
|
-
│ └── index.ts # All public TypeScript interfaces
|
|
650
|
-
├── lib.tsx # React library entry point
|
|
651
|
-
└── web-component.tsx # Web Component entry point
|
|
652
|
-
```
|
|
365
|
+
Reset the active widget's chat history imperatively — e.g. on logout — without
|
|
366
|
+
holding a ref:
|
|
653
367
|
|
|
654
|
-
|
|
368
|
+
```ts
|
|
369
|
+
import { clearChat } from 'keyring-chatbot-agent';
|
|
655
370
|
|
|
656
|
-
|
|
371
|
+
function onLogout() {
|
|
372
|
+
clearChat(); // clears in-memory + localStorage history and re-shows suggestions
|
|
373
|
+
}
|
|
374
|
+
```
|
|
657
375
|
|
|
658
|
-
|
|
659
|
-
# Build a specific package name and update README/.env/package.json accordingly
|
|
660
|
-
yarn build:package keyring-chatbot-agent-sdk-test
|
|
376
|
+
## Compose your own UI
|
|
661
377
|
|
|
662
|
-
|
|
663
|
-
|
|
378
|
+
For a custom layout that reuses the same wiring, skip `<ChatWidget>` and compose
|
|
379
|
+
the providers + hooks yourself:
|
|
664
380
|
|
|
665
|
-
|
|
666
|
-
|
|
381
|
+
```tsx
|
|
382
|
+
import {
|
|
383
|
+
ConfigProvider,
|
|
384
|
+
ConnectProvider,
|
|
385
|
+
LanguageProvider,
|
|
386
|
+
useAgent,
|
|
387
|
+
useAgentChat,
|
|
388
|
+
ActionForm,
|
|
389
|
+
} from 'keyring-chatbot-agent';
|
|
667
390
|
```
|
|
668
391
|
|
|
669
|
-
|
|
670
|
-
|
|
671
|
-
- `
|
|
672
|
-
- `publish:package` publishes the current package, creates a git commit, and creates a git tag in the form `<package>@<version>`.
|
|
673
|
-
- `publish:all` loops through all package names from `SDK_PACKAGE_DATA`, builds and publishes them one by one, then pushes commits and tags.
|
|
674
|
-
|
|
675
|
-
---
|
|
392
|
+
- `useAgent()` — builds the per-session chat agent (config-driven; takes no args).
|
|
393
|
+
- `useAgentChat({ agent, addMessage })` — `send(text)` → reply + wallet actions.
|
|
394
|
+
- `ActionForm` — the confirmation form primitive for a wallet action.
|
|
676
395
|
|
|
677
|
-
##
|
|
396
|
+
## Exports
|
|
678
397
|
|
|
679
|
-
|
|
398
|
+
```ts
|
|
399
|
+
// Widget
|
|
400
|
+
import { ChatWidget, type ChatWidgetProps } from 'keyring-chatbot-agent';
|
|
401
|
+
|
|
402
|
+
// Imperative
|
|
403
|
+
import { clearChat } from 'keyring-chatbot-agent';
|
|
404
|
+
|
|
405
|
+
// Compose-your-own
|
|
406
|
+
import {
|
|
407
|
+
ConfigProvider,
|
|
408
|
+
useConfig,
|
|
409
|
+
ConnectProvider,
|
|
410
|
+
useConnect,
|
|
411
|
+
LanguageProvider,
|
|
412
|
+
useLanguage,
|
|
413
|
+
useAgent,
|
|
414
|
+
useAgentChat,
|
|
415
|
+
ActionForm,
|
|
416
|
+
} from 'keyring-chatbot-agent';
|
|
417
|
+
|
|
418
|
+
// Types
|
|
419
|
+
import type {
|
|
420
|
+
Account,
|
|
421
|
+
ChatWidgetTheme,
|
|
422
|
+
Config,
|
|
423
|
+
Language,
|
|
424
|
+
ChatWidgetLanguage,
|
|
425
|
+
Message,
|
|
426
|
+
MessageButton,
|
|
427
|
+
MessageActionButton,
|
|
428
|
+
MessageWalletAction,
|
|
429
|
+
MessageTokenInfo,
|
|
430
|
+
MessageNftInfo,
|
|
431
|
+
WalletActionStatus,
|
|
432
|
+
SuggestionButtonConfig,
|
|
433
|
+
ChatUICustomization,
|
|
434
|
+
AgentActionType,
|
|
435
|
+
Transaction,
|
|
436
|
+
TransactionStatus,
|
|
437
|
+
TransactionResult,
|
|
438
|
+
} from 'keyring-chatbot-agent';
|
|
439
|
+
```
|