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 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`), `rejected`, `failed` (with `error`), `unknown` (with `error`) or `expired` |
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. Chia is not offered over MCP yet.
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`), `rejected`, `failed` (with `error`), `unknown` (with `error`) or `expired` |
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 sats 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. Chia is not offered over MCP yet.
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; chia waits until the web app shows it again */
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 bitcoin) are paired' },
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 in sats (1 BTC = "100000000"), no decimals; the wallet sets the fee.',
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: { type: 'string', enum: ['mainnet', 'testnet', 'signet'], description: 'must match the paired wallet (see list_pairings)' },
66
- to: { type: 'string', description: 'segwit address on that network: bc1... on mainnet, tb1... on testnet and signet' },
67
- amount: { type: 'string', description: 'integer string in sats' },
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
- if (args.family !== 'bitcoin')
230
- throw new ToolInputError(`invalid family: must be "bitcoin", got ${JSON.stringify(args.family)}`);
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
- request = validateTransfer('bitcoin', args.network, { asset: 'btc', to: args.to, amount: args.amount });
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('bitcoin', from, cancelled, async (wallet, limits) => {
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
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clanker-wallet",
3
- "version": "0.8.0",
3
+ "version": "0.9.0",
4
4
  "type": "module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",