clanker-wallet 0.8.0 → 0.9.0
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 +4 -4
- package/SKILL.md +4 -4
- package/dist/mcp.d.ts +6 -2
- package/dist/mcp.js +22 -13
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -179,11 +179,11 @@ Claude Desktop (`claude_desktop_config.json`), Cursor (`~/.cursor/mcp.json`), an
|
|
|
179
179
|
| Tool | Arguments | Returns |
|
|
180
180
|
|------|-----------|---------|
|
|
181
181
|
| `request_evm_tx` | `chain_id`, `to`, `value` (wei, integer string), `data` (default `0x`), `reason`, optional `urgency` / `expected_outcome` / `from` (the paired wallet to send from, needed when several wallets of the same family are paired) | `{"request_id":"req_...","status":"pending","expires_at":"..."}` |
|
|
182
|
-
| `request_transfer` | `family` (`bitcoin`), `network` (`mainnet`, `testnet`, `signet`), `to`, `amount` (sats, integer string), `reason`, optional `urgency` / `expected_outcome` / `from` (the paired wallet to send from, needed when several wallets of the same family are paired) | as above |
|
|
183
|
-
| `get_request` | `request_id`, optional `wait_seconds` (at most 50) | `status`: `pending`, `approved` (with `tx_hash
|
|
184
|
-
| `list_pairings` | none | `agent_id`, `fingerprint`, and the paired families (`evm`, `bitcoin`) with network, wallet and mode |
|
|
182
|
+
| `request_transfer` | `family` (`bitcoin` or `chia`), `network` (bitcoin: `mainnet`, `testnet`, `signet`; chia: `mainnet`, `testnet11`), `to`, `amount` (sats, integer string) or mojos for chia, `reason`, optional `fee` (chia only: mojos, default `"0"`) / `urgency` / `expected_outcome` / `from` (the paired wallet to send from, needed when several wallets of the same family are paired) | as above |
|
|
183
|
+
| `get_request` | `request_id`, optional `wait_seconds` (at most 50) | `status`: `pending`, `approved` (with `tx_hash`; a chia send may have none), `rejected`, `failed` (with `error`), `unknown` (with `error`) or `expired` |
|
|
184
|
+
| `list_pairings` | none | `agent_id`, `fingerprint`, and the paired families (`evm`, `bitcoin`, `chia`) with network, wallet and mode |
|
|
185
185
|
|
|
186
|
-
Requests are asynchronous: a request tool returns once the relay has the request, then the assistant calls `get_request` (with `wait_seconds` to wait for an answer) until the status is no longer `pending`. Invalid input or a missing pairing is a tool error, and nothing is sent. Pending requests live in the server process: after 1 h the server stops waiting and reports `expired`, and a restarted server no longer knows them (`get_request` then reports an unknown `request_id`). In both cases the human may still approve the request in their wallet, so ask them before sending it again. `unknown` means the request was delivered but the server lost its relay connection: the human may still approve it, so ask them before sending it again.
|
|
186
|
+
Requests are asynchronous: a request tool returns once the relay has the request, then the assistant calls `get_request` (with `wait_seconds` to wait for an answer) until the status is no longer `pending`. Invalid input or a missing pairing is a tool error, and nothing is sent. Pending requests live in the server process: after 1 h the server stops waiting and reports `expired`, and a restarted server no longer knows them (`get_request` then reports an unknown `request_id`). In both cases the human may still approve the request in their wallet, so ask them before sending it again. `unknown` means the request was delivered but the server lost its relay connection: the human may still approve it, so ask them before sending it again. A chia approval may have no `tx_hash`: the Sage wallet sends without reporting a transaction id, so check the recipient's balance.
|
|
187
187
|
|
|
188
188
|
---
|
|
189
189
|
|
package/SKILL.md
CHANGED
|
@@ -216,11 +216,11 @@ Claude Desktop (`claude_desktop_config.json`), Cursor (`~/.cursor/mcp.json`), an
|
|
|
216
216
|
| Tool | Arguments | Returns |
|
|
217
217
|
|------|-----------|---------|
|
|
218
218
|
| `request_evm_tx` | `chain_id`, `to`, `value` (wei, integer string), `data` (default `0x`), `reason`, optional `urgency` / `expected_outcome` / `from` (the paired wallet to send from, needed when several wallets of the same family are paired) | `{"request_id":"req_...","status":"pending","expires_at":"..."}` |
|
|
219
|
-
| `request_transfer` | `family` (`bitcoin`), `network` (`mainnet`, `testnet`, `signet`), `to`, `amount` (sats, integer string), `reason`, optional `urgency` / `expected_outcome` / `from` (the paired wallet to send from, needed when several wallets of the same family are paired) | as above |
|
|
220
|
-
| `get_request` | `request_id`, optional `wait_seconds` (at most 50) | `status`: `pending`, `approved` (with `tx_hash
|
|
221
|
-
| `list_pairings` | none | `agent_id`, `fingerprint`, and the paired families (`evm`, `bitcoin`) with network, wallet and mode |
|
|
219
|
+
| `request_transfer` | `family` (`bitcoin` or `chia`), `network` (bitcoin: `mainnet`, `testnet`, `signet`; chia: `mainnet`, `testnet11`), `to`, `amount` (sats, integer string) or mojos for chia, `reason`, optional `fee` (chia only: mojos, default `"0"`) / `urgency` / `expected_outcome` / `from` (the paired wallet to send from, needed when several wallets of the same family are paired) | as above |
|
|
220
|
+
| `get_request` | `request_id`, optional `wait_seconds` (at most 50) | `status`: `pending`, `approved` (with `tx_hash`; a chia send may have none), `rejected`, `failed` (with `error`), `unknown` (with `error`) or `expired` |
|
|
221
|
+
| `list_pairings` | none | `agent_id`, `fingerprint`, and the paired families (`evm`, `bitcoin`, `chia`) with network, wallet and mode |
|
|
222
222
|
|
|
223
|
-
Flow: call `list_pairings` to see which chains you can use, call `request_evm_tx` or `request_transfer` (same rules as `tx` / `send`: wei and
|
|
223
|
+
Flow: call `list_pairings` to see which chains you can use, call `request_evm_tx` or `request_transfer` (same rules as `tx` / `send`: wei, sats and mojos as integer strings, real addresses), tell the human a request is waiting (see "Transaction notifications"), then call `get_request` with `wait_seconds` until the status is no longer `pending`. Invalid input or a missing pairing comes back as a tool error and nothing is sent. After 1 h the server stops waiting and reports `expired`, and a restarted server no longer knows its earlier requests (`get_request` then reports an unknown `request_id`). In both cases the human may still approve the request in their wallet, so ask them before sending it again. `unknown` means the request was delivered but the server lost its relay connection: the human may still approve it, so ask them before sending it again. A chia approval may have no `tx_hash`: the Sage wallet sends without reporting a transaction id, so check the recipient's balance.
|
|
224
224
|
|
|
225
225
|
## Troubleshooting
|
|
226
226
|
|
package/dist/mcp.d.ts
CHANGED
|
@@ -17,8 +17,8 @@ export interface SavedPairing {
|
|
|
17
17
|
chain_family?: string;
|
|
18
18
|
chain_network?: string;
|
|
19
19
|
}
|
|
20
|
-
/** the families the tools request on
|
|
21
|
-
type RequestFamily = 'evm' | 'bitcoin';
|
|
20
|
+
/** the families the tools request on */
|
|
21
|
+
type RequestFamily = 'evm' | 'bitcoin' | 'chia';
|
|
22
22
|
export interface McpServerOptions {
|
|
23
23
|
/** the package version, reported in initialize */
|
|
24
24
|
version: string;
|
|
@@ -126,6 +126,10 @@ export declare const MCP_TOOLS: ({
|
|
|
126
126
|
type: string;
|
|
127
127
|
description: string;
|
|
128
128
|
};
|
|
129
|
+
fee: {
|
|
130
|
+
type: string;
|
|
131
|
+
description: string;
|
|
132
|
+
};
|
|
129
133
|
request_id?: undefined;
|
|
130
134
|
wait_seconds?: undefined;
|
|
131
135
|
};
|
package/dist/mcp.js
CHANGED
|
@@ -13,7 +13,7 @@ export const MAX_WAIT_SECONDS = 50;
|
|
|
13
13
|
const DEFAULT_REQUEST_TTL_MS = 3_600_000;
|
|
14
14
|
/** a relay that hasn't confirmed the join by then fails the request with nothing sent, inside the hosts' 60 s tool-call timeout */
|
|
15
15
|
const DEFAULT_JOIN_TIMEOUT_MS = 20_000;
|
|
16
|
-
const REQUEST_FAMILIES = ['evm', 'bitcoin'];
|
|
16
|
+
const REQUEST_FAMILIES = ['evm', 'bitcoin', 'chia'];
|
|
17
17
|
const URGENCIES = ['low', 'medium', 'high'];
|
|
18
18
|
const CONTEXT_PROPERTIES = {
|
|
19
19
|
reason: { type: 'string', description: 'why you want this, in plain words; shown to the human on the review card' },
|
|
@@ -22,7 +22,7 @@ const CONTEXT_PROPERTIES = {
|
|
|
22
22
|
};
|
|
23
23
|
/** the same on both request tools; the hosted connector copies these definitions verbatim */
|
|
24
24
|
const FROM_PROPERTY = {
|
|
25
|
-
from: { type: 'string', description: 'the paired wallet address to send from, as list_pairings shows it; needed only when several wallets of the same family (evm or
|
|
25
|
+
from: { type: 'string', description: 'the paired wallet address to send from, as list_pairings shows it; needed only when several wallets of the same family (evm, bitcoin or chia) are paired' },
|
|
26
26
|
};
|
|
27
27
|
/**
|
|
28
28
|
* MCP tool annotations: assistants (ChatGPT, dots, Claude) may skip their confirmation prompt for read-only tools.
|
|
@@ -54,17 +54,23 @@ export const MCP_TOOLS = [
|
|
|
54
54
|
},
|
|
55
55
|
{
|
|
56
56
|
name: 'request_transfer',
|
|
57
|
-
description: 'Ask the human to send bitcoin from their own wallet, which builds, signs and broadcasts it. ' +
|
|
57
|
+
description: 'Ask the human to send bitcoin or chia (XCH) from their own wallet, which builds, signs and broadcasts it. ' +
|
|
58
58
|
'Nothing is signed here: the human approves every request on their own device, or rejects it. ' +
|
|
59
59
|
'Returns { request_id } once the request is delivered; then call get_request for the outcome. ' +
|
|
60
|
-
'amount is an integer string
|
|
60
|
+
'amount is an integer string, no decimals: sats for bitcoin (1 BTC = "100000000"), where the wallet sets the fee; ' +
|
|
61
|
+
'mojos for chia (1 XCH = "1000000000000"), with an optional fee in mojos (default "0").',
|
|
61
62
|
inputSchema: {
|
|
62
63
|
type: 'object',
|
|
63
64
|
properties: {
|
|
64
|
-
family: { type: 'string', enum: ['bitcoin'], description: 'chain family' },
|
|
65
|
-
network: {
|
|
66
|
-
|
|
67
|
-
|
|
65
|
+
family: { type: 'string', enum: ['bitcoin', 'chia'], description: 'chain family' },
|
|
66
|
+
network: {
|
|
67
|
+
type: 'string',
|
|
68
|
+
enum: ['mainnet', 'testnet', 'signet', 'testnet11'],
|
|
69
|
+
description: 'bitcoin: mainnet, testnet or signet; chia: mainnet or testnet11. must match the paired wallet (see list_pairings)',
|
|
70
|
+
},
|
|
71
|
+
to: { type: 'string', description: 'address on that network: bitcoin segwit bc1... (mainnet) or tb1... (testnet, signet); chia xch1... (mainnet) or txch1... (testnet11)' },
|
|
72
|
+
amount: { type: 'string', description: 'integer string in sats (bitcoin) or mojos (chia)' },
|
|
73
|
+
fee: { type: 'string', description: 'chia only: integer string in mojos, default "0"; bitcoin takes none (the wallet sets it)' },
|
|
68
74
|
...CONTEXT_PROPERTIES,
|
|
69
75
|
...FROM_PROPERTY,
|
|
70
76
|
},
|
|
@@ -74,7 +80,7 @@ export const MCP_TOOLS = [
|
|
|
74
80
|
},
|
|
75
81
|
{
|
|
76
82
|
name: 'get_request',
|
|
77
|
-
description: 'Get the outcome of a request: pending, approved (with tx_hash), rejected, failed (with error), unknown (with error) or expired. ' +
|
|
83
|
+
description: 'Get the outcome of a request: pending, approved (with tx_hash; a chia send may have none, so check the recipient\'s balance), rejected, failed (with error), unknown (with error) or expired. ' +
|
|
78
84
|
`The human may take minutes to answer: pass wait_seconds (at most ${MAX_WAIT_SECONDS}) to wait for it, and call again while it is pending. ` +
|
|
79
85
|
'unknown means the request was delivered but this server lost its relay connection: the human may still approve it, so ask them before sending it again. ' +
|
|
80
86
|
'expired means this server stopped waiting, 1 hour after sending; after a restart it no longer knows earlier request ids. ' +
|
|
@@ -160,6 +166,7 @@ function fromMismatch(family, from, pairing) {
|
|
|
160
166
|
const NOT_PAIRED = {
|
|
161
167
|
evm: 'not paired with an evm wallet: ask the human to open https://clanker-wallet.xyz, copy the pairing JSON, and run: clanker-wallet pair \'<JSON>\'',
|
|
162
168
|
bitcoin: 'not paired with a bitcoin wallet: ask the human to open the bitcoin tab at https://clanker-wallet.xyz, copy its pairing JSON, and run: clanker-wallet pair \'<JSON>\'',
|
|
169
|
+
chia: 'not paired with a chia wallet: ask the human to open the XCH tab at https://clanker-wallet.xyz, copy its pairing JSON, and run: clanker-wallet pair \'<JSON>\'',
|
|
163
170
|
};
|
|
164
171
|
export function createMcpServer(options) {
|
|
165
172
|
const ttl = options.requestTtlMs ?? DEFAULT_REQUEST_TTL_MS;
|
|
@@ -226,13 +233,15 @@ export function createMcpServer(options) {
|
|
|
226
233
|
return submit('evm', from, cancelled, (wallet, limits) => wallet.requestTx({ chain_id, transaction, context, ...limits }));
|
|
227
234
|
}
|
|
228
235
|
async function requestTransfer(args, cancelled) {
|
|
229
|
-
|
|
230
|
-
|
|
236
|
+
const family = args.family;
|
|
237
|
+
if (family !== 'bitcoin' && family !== 'chia')
|
|
238
|
+
throw new ToolInputError(`invalid family: must be "bitcoin" or "chia", got ${JSON.stringify(family)}`);
|
|
231
239
|
const context = contextFrom(args);
|
|
232
240
|
const from = fromArg(args);
|
|
233
241
|
let request;
|
|
234
242
|
try {
|
|
235
|
-
|
|
243
|
+
const asset = family === 'bitcoin' ? 'btc' : 'xch';
|
|
244
|
+
request = validateTransfer(family, args.network, { asset, to: args.to, amount: args.amount, ...(args.fee !== undefined && { fee: args.fee }) });
|
|
236
245
|
}
|
|
237
246
|
catch (err) {
|
|
238
247
|
// the tool calls the network field `network`
|
|
@@ -241,7 +250,7 @@ export function createMcpServer(options) {
|
|
|
241
250
|
throw err;
|
|
242
251
|
}
|
|
243
252
|
const { chain_network, transfer } = request;
|
|
244
|
-
return submit(
|
|
253
|
+
return submit(family, from, cancelled, async (wallet, limits) => {
|
|
245
254
|
try {
|
|
246
255
|
return await wallet.requestTransfer({ chain_network, transfer, context, ...limits });
|
|
247
256
|
}
|