@moonpay/cli 0.4.2 → 0.5.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.
@@ -1,2444 +0,0 @@
1
- import { createRequire as __createRequire } from "module"; const require = __createRequire(import.meta.url);
2
- import {
3
- KEY_CHAIN_MAP,
4
- chainSchema,
5
- deleteWalletFile,
6
- keyChainSchema,
7
- loadAllWallets,
8
- loadWallet,
9
- lockedVaultDataSchema,
10
- saveWalletMetadata,
11
- vaultDataSchema,
12
- walletInfoSchema
13
- } from "./chunk-AGDVU2O5.js";
14
- import {
15
- deriveAllAddresses,
16
- deriveKeyForChain
17
- } from "./chunk-Z33PSOPD.js";
18
- import {
19
- __require
20
- } from "./chunk-EEBB5MQP.js";
21
-
22
- // src/auth.ts
23
- import { spawn } from "child_process";
24
- import * as crypto from "crypto";
25
- import * as fs from "fs";
26
- import * as os from "os";
27
- import * as path from "path";
28
- import { createInterface } from "readline";
29
- function generateCodeVerifier() {
30
- return crypto.randomBytes(32).toString("base64url");
31
- }
32
- function generateCodeChallenge(verifier) {
33
- return crypto.createHash("sha256").update(verifier).digest("base64url");
34
- }
35
- var CONFIG_DIR = path.join(os.homedir(), ".config", "moonpay");
36
- var CONFIG_PATH = path.join(CONFIG_DIR, "config.json");
37
- var CREDENTIALS_PATH = path.join(CONFIG_DIR, "credentials.json");
38
- var LOCK_PATH = path.join(CONFIG_DIR, ".credentials.lock");
39
- var DEFAULT_CONFIG = {
40
- baseUrl: "https://agents.moonpay.com",
41
- clientId: "mooniq_zin3s5jz3olzkdfxpmbeaogv"
42
- };
43
- function ensureConfigDir() {
44
- if (!fs.existsSync(CONFIG_DIR)) {
45
- fs.mkdirSync(CONFIG_DIR, { recursive: true, mode: 448 });
46
- }
47
- }
48
- function atomicWriteFileSync(filePath, data, mode) {
49
- const tmp = filePath + `.tmp.${process.pid}`;
50
- fs.writeFileSync(tmp, data, { encoding: "utf-8", mode });
51
- fs.renameSync(tmp, filePath);
52
- }
53
- var LOCK_STALE_MS = 3e4;
54
- function acquireLock() {
55
- ensureConfigDir();
56
- try {
57
- const fd = fs.openSync(LOCK_PATH, fs.constants.O_CREAT | fs.constants.O_EXCL | fs.constants.O_WRONLY, 384);
58
- fs.writeSync(fd, JSON.stringify({ pid: process.pid, ts: Date.now() }));
59
- fs.closeSync(fd);
60
- } catch (err) {
61
- if (err.code !== "EEXIST") throw err;
62
- try {
63
- const lockData = JSON.parse(fs.readFileSync(LOCK_PATH, "utf-8"));
64
- if (Date.now() - lockData.ts < LOCK_STALE_MS) {
65
- return null;
66
- }
67
- } catch {
68
- }
69
- try {
70
- fs.unlinkSync(LOCK_PATH);
71
- } catch {
72
- }
73
- try {
74
- const fd = fs.openSync(LOCK_PATH, fs.constants.O_CREAT | fs.constants.O_EXCL | fs.constants.O_WRONLY, 384);
75
- fs.writeSync(fd, JSON.stringify({ pid: process.pid, ts: Date.now() }));
76
- fs.closeSync(fd);
77
- } catch {
78
- return null;
79
- }
80
- }
81
- return () => {
82
- try {
83
- fs.unlinkSync(LOCK_PATH);
84
- } catch {
85
- }
86
- };
87
- }
88
- function getConfig() {
89
- if (!fs.existsSync(CONFIG_PATH)) return null;
90
- try {
91
- const data = JSON.parse(fs.readFileSync(CONFIG_PATH, "utf-8"));
92
- if (!data.baseUrl || !data.clientId) return null;
93
- return data;
94
- } catch {
95
- return null;
96
- }
97
- }
98
- function getConfigOrDefault() {
99
- const fromFile = getConfig();
100
- if (fromFile) return fromFile;
101
- saveConfig(DEFAULT_CONFIG);
102
- return DEFAULT_CONFIG;
103
- }
104
- function getCredentials() {
105
- if (!fs.existsSync(CREDENTIALS_PATH)) return null;
106
- try {
107
- const data = JSON.parse(fs.readFileSync(CREDENTIALS_PATH, "utf-8"));
108
- if (!data.accessToken || !data.baseUrl) return null;
109
- return data;
110
- } catch {
111
- return null;
112
- }
113
- }
114
- function saveCredentials(creds) {
115
- ensureConfigDir();
116
- atomicWriteFileSync(CREDENTIALS_PATH, JSON.stringify(creds, null, 2), 384);
117
- }
118
- function saveConfig(config) {
119
- ensureConfigDir();
120
- atomicWriteFileSync(CONFIG_PATH, JSON.stringify(config, null, 2), 384);
121
- }
122
- function clearCredentials() {
123
- if (fs.existsSync(CREDENTIALS_PATH)) {
124
- fs.unlinkSync(CREDENTIALS_PATH);
125
- }
126
- }
127
- function resolveBaseUrl() {
128
- const config = getConfig();
129
- const creds = getCredentials();
130
- return config?.baseUrl ?? creds?.baseUrl ?? DEFAULT_CONFIG.baseUrl;
131
- }
132
- function openBrowser(url) {
133
- const platform = process.platform;
134
- const cmd = platform === "darwin" ? "open" : platform === "win32" ? "cmd" : "xdg-open";
135
- const args = platform === "win32" ? ["/c", "start", "", url] : [url];
136
- try {
137
- spawn(cmd, args, { stdio: "ignore", detached: true }).unref();
138
- return true;
139
- } catch {
140
- return false;
141
- }
142
- }
143
- function promptLine(prompt) {
144
- const rl = createInterface({ input: process.stdin, output: process.stderr });
145
- return new Promise((resolve) => {
146
- rl.question(prompt, (answer) => {
147
- rl.close();
148
- resolve(answer.trim());
149
- });
150
- });
151
- }
152
- var LOGIN_STATE_PATH = path.join(CONFIG_DIR, ".login-state.json");
153
- async function login(config, options = {}) {
154
- const callbackUrl = `${config.baseUrl}/callback`;
155
- if (options.code) {
156
- const stateData = loadLoginState();
157
- if (!stateData) {
158
- throw new Error("No pending login found. Run `mp login --no-browser` first.");
159
- }
160
- return exchangeCode(config, options.code, callbackUrl, stateData.codeVerifier);
161
- }
162
- const state = crypto.randomUUID();
163
- const usePkce = !config.clientSecret;
164
- let codeVerifier;
165
- if (usePkce) {
166
- codeVerifier = generateCodeVerifier();
167
- }
168
- const authorizeParams = new URLSearchParams({
169
- client_id: config.clientId,
170
- redirect_uri: callbackUrl,
171
- response_type: "code",
172
- scope: "profile email",
173
- state
174
- });
175
- if (usePkce && codeVerifier) {
176
- authorizeParams.set("code_challenge", generateCodeChallenge(codeVerifier));
177
- authorizeParams.set("code_challenge_method", "S256");
178
- }
179
- const authorizeUrl = `${config.baseUrl}/authorize?${authorizeParams.toString()}`;
180
- saveLoginState({ state, codeVerifier: codeVerifier ?? null });
181
- const opened = options.noBrowser ? false : openBrowser(authorizeUrl);
182
- console.log("Open this URL in your browser to log in:\n");
183
- console.log(` ${authorizeUrl}
184
- `);
185
- if (options.noBrowser) {
186
- console.log("Tip: you can run `open <url>` to open it directly.");
187
- console.log("After authorizing, copy the code and run:\n");
188
- console.log(" mp login --code <paste-code-here>\n");
189
- process.exit(0);
190
- }
191
- const code = await promptLine("Paste code: ");
192
- if (!code) {
193
- throw new Error("No authorization code provided.");
194
- }
195
- return exchangeCode(config, code, callbackUrl, codeVerifier ?? null);
196
- }
197
- function saveLoginState(state) {
198
- ensureConfigDir();
199
- atomicWriteFileSync(LOGIN_STATE_PATH, JSON.stringify(state), 384);
200
- }
201
- function loadLoginState() {
202
- if (!fs.existsSync(LOGIN_STATE_PATH)) return null;
203
- try {
204
- const data = JSON.parse(fs.readFileSync(LOGIN_STATE_PATH, "utf-8"));
205
- fs.unlinkSync(LOGIN_STATE_PATH);
206
- return data;
207
- } catch {
208
- return null;
209
- }
210
- }
211
- async function exchangeCode(config, code, callbackUrl, codeVerifier) {
212
- const tokenParams = {
213
- grant_type: "authorization_code",
214
- code,
215
- client_id: config.clientId,
216
- redirect_uri: callbackUrl
217
- };
218
- if (config.clientSecret) {
219
- tokenParams.client_secret = config.clientSecret;
220
- }
221
- if (codeVerifier) {
222
- tokenParams.code_verifier = codeVerifier;
223
- }
224
- const tokenResponse = await fetch(`${config.baseUrl}/api/oauth/token`, {
225
- method: "POST",
226
- headers: { "Content-Type": "application/x-www-form-urlencoded" },
227
- body: new URLSearchParams(tokenParams)
228
- });
229
- if (!tokenResponse.ok) {
230
- const err = await tokenResponse.json().catch(() => ({}));
231
- const msg = err.error_description ?? err.error ?? tokenResponse.statusText;
232
- throw new Error(`Token exchange failed: ${msg}`);
233
- }
234
- const tokens = await tokenResponse.json();
235
- const expiresAt = Date.now() + (tokens.expires_in ?? 3600) * 1e3;
236
- const creds = {
237
- accessToken: tokens.access_token,
238
- refreshToken: tokens.refresh_token ?? null,
239
- expiresAt,
240
- baseUrl: config.baseUrl
241
- };
242
- saveCredentials(creds);
243
- return creds;
244
- }
245
- async function refreshCredentials(creds, config) {
246
- if (!creds.refreshToken) {
247
- throw new Error("No refresh token available");
248
- }
249
- const unlock = acquireLock();
250
- if (!unlock) {
251
- await new Promise((r) => setTimeout(r, 2e3));
252
- const fresh = getCredentials();
253
- if (fresh && fresh.expiresAt > Date.now()) {
254
- return fresh;
255
- }
256
- throw new Error("Token refresh failed (concurrent refresh in progress)");
257
- }
258
- try {
259
- const latest = getCredentials();
260
- if (latest && latest.expiresAt > Date.now() + 6e4) {
261
- return latest;
262
- }
263
- const refreshParams = {
264
- grant_type: "refresh_token",
265
- refresh_token: creds.refreshToken,
266
- client_id: config.clientId
267
- };
268
- if (config.clientSecret) {
269
- refreshParams.client_secret = config.clientSecret;
270
- }
271
- const tokenResponse = await fetch(`${config.baseUrl}/api/oauth/token`, {
272
- method: "POST",
273
- headers: { "Content-Type": "application/x-www-form-urlencoded" },
274
- body: new URLSearchParams(refreshParams)
275
- });
276
- if (!tokenResponse.ok) {
277
- throw new Error("Token refresh failed");
278
- }
279
- const tokens = await tokenResponse.json();
280
- const expiresAt = Date.now() + (tokens.expires_in ?? 3600) * 1e3;
281
- const newCreds = {
282
- accessToken: tokens.access_token,
283
- refreshToken: tokens.refresh_token ?? creds.refreshToken,
284
- expiresAt,
285
- baseUrl: config.baseUrl
286
- };
287
- saveCredentials(newCreds);
288
- return newCreds;
289
- } finally {
290
- unlock();
291
- }
292
- }
293
- var TOKEN_EXPIRY_BUFFER_MS = 5 * 60 * 1e3;
294
- async function getValidToken() {
295
- const creds = getCredentials();
296
- if (!creds) return null;
297
- const config = getConfig();
298
- if (!config || config.baseUrl !== creds.baseUrl) return null;
299
- if (Date.now() >= creds.expiresAt - TOKEN_EXPIRY_BUFFER_MS) {
300
- if (creds.refreshToken) {
301
- try {
302
- const newCreds = await refreshCredentials(creds, config);
303
- return newCreds.accessToken;
304
- } catch {
305
- return null;
306
- }
307
- }
308
- return null;
309
- }
310
- return creds.accessToken;
311
- }
312
-
313
- // src/client.ts
314
- async function callTool(baseUrl, toolName, params) {
315
- const token = await getValidToken();
316
- const headers = {
317
- "Content-Type": "application/json"
318
- };
319
- if (token) {
320
- headers["Authorization"] = `Bearer ${token}`;
321
- }
322
- let res = await fetch(`${baseUrl}/api/tools/${toolName}`, {
323
- method: "POST",
324
- headers,
325
- body: JSON.stringify(params)
326
- });
327
- if (res.status === 401 && token) {
328
- const creds = getCredentials();
329
- const config = getConfig();
330
- if (creds?.refreshToken && config && config.baseUrl === creds.baseUrl) {
331
- try {
332
- const newCreds = await refreshCredentials(creds, config);
333
- res = await fetch(`${baseUrl}/api/tools/${toolName}`, {
334
- method: "POST",
335
- headers: {
336
- "Content-Type": "application/json",
337
- Authorization: `Bearer ${newCreds.accessToken}`
338
- },
339
- body: JSON.stringify(params)
340
- });
341
- } catch {
342
- }
343
- }
344
- }
345
- const data = await res.json();
346
- if (res.status === 401) {
347
- throw new Error("This command requires a MoonPay Agents account. Run `moonpay login` first.");
348
- }
349
- if (res.status < 200 || res.status >= 300) {
350
- const err = data;
351
- throw new Error(err?.error ?? `Tool call failed (${res.status})`);
352
- }
353
- return data;
354
- }
355
-
356
- // src/generated/schemas.json
357
- var schemas_default = [
358
- {
359
- name: "buy",
360
- description: "Buy crypto with fiat via MoonPay. Returns a checkout URL to complete the purchase.",
361
- inputSchema: {
362
- $ref: "#/definitions/buy_input",
363
- definitions: {
364
- buy_input: {
365
- type: "object",
366
- properties: {
367
- token: {
368
- type: "string",
369
- enum: [
370
- "sol",
371
- "usdc",
372
- "usdc_arbitrum",
373
- "usdc_base",
374
- "usdc_optimism",
375
- "usdc_sol",
376
- "usdc_polygon",
377
- "eth",
378
- "eth_polygon",
379
- "eth_optimism",
380
- "eth_base",
381
- "eth_arbitrum"
382
- ],
383
- description: "MoonPay currency code: sol (Solana), usdc_sol (USDC on Solana), eth (Ethereum), usdc (USDC on Ethereum), usdc_base (USDC on Base), etc."
384
- },
385
- amount: {
386
- type: "number",
387
- description: "Amount of the token to buy, in token units \u2014 not fiat. For example, 1.5 means 1.5 SOL, not $1.50."
388
- },
389
- wallet: {
390
- type: "string",
391
- description: "Destination wallet address to receive the tokens"
392
- },
393
- email: {
394
- type: [
395
- "string",
396
- "null"
397
- ],
398
- description: "Buyer email to pre-fill on the checkout page"
399
- }
400
- },
401
- required: [
402
- "token",
403
- "amount",
404
- "wallet",
405
- "email"
406
- ],
407
- additionalProperties: false
408
- }
409
- },
410
- $schema: "http://json-schema.org/draft-07/schema#"
411
- }
412
- },
413
- {
414
- name: "token_balance_list",
415
- description: "List all token balances held in a wallet, including amount owned, current value in USD, and token details. Shows the complete token portfolio.",
416
- inputSchema: {
417
- $ref: "#/definitions/token_balance_list_input",
418
- definitions: {
419
- token_balance_list_input: {
420
- type: "object",
421
- properties: {
422
- wallet: {
423
- type: "string",
424
- description: "Wallet address to check token balances for"
425
- },
426
- chain: {
427
- type: "string",
428
- enum: [
429
- "solana",
430
- "ethereum",
431
- "base",
432
- "polygon",
433
- "arbitrum",
434
- "optimism"
435
- ],
436
- description: "Blockchain to check balances on (e.g. 'solana', 'ethereum', 'base')"
437
- }
438
- },
439
- required: [
440
- "wallet",
441
- "chain"
442
- ],
443
- additionalProperties: false
444
- }
445
- },
446
- $schema: "http://json-schema.org/draft-07/schema#"
447
- }
448
- },
449
- {
450
- name: "token_retrieve",
451
- description: "Get detailed token information including market data, price changes, volume, trades, and holder statistics by token address",
452
- inputSchema: {
453
- $ref: "#/definitions/token_retrieve_input",
454
- definitions: {
455
- token_retrieve_input: {
456
- type: "object",
457
- properties: {
458
- token: {
459
- type: "string",
460
- description: "Address of the token to retrieve"
461
- },
462
- chain: {
463
- type: "string",
464
- enum: [
465
- "solana",
466
- "ethereum",
467
- "base",
468
- "polygon",
469
- "arbitrum",
470
- "optimism"
471
- ],
472
- description: "Blockchain network where the token exists"
473
- }
474
- },
475
- required: [
476
- "token",
477
- "chain"
478
- ],
479
- additionalProperties: false
480
- }
481
- },
482
- $schema: "http://json-schema.org/draft-07/schema#"
483
- }
484
- },
485
- {
486
- name: "token_search",
487
- description: "Search for tokens by name, symbol, or address. Returns matching tokens with their market data including price, volume, and liquidity.",
488
- inputSchema: {
489
- $ref: "#/definitions/token_search_input",
490
- definitions: {
491
- token_search_input: {
492
- type: "object",
493
- properties: {
494
- query: {
495
- type: "string",
496
- description: "Search term - can be token name (e.g. 'Bitcoin'), symbol (e.g. 'BTC'), or partial match"
497
- },
498
- chain: {
499
- type: "string",
500
- enum: [
501
- "solana",
502
- "ethereum",
503
- "base",
504
- "polygon",
505
- "arbitrum",
506
- "optimism"
507
- ],
508
- description: "Blockchain to search on (e.g. 'solana', 'ethereum', 'base')"
509
- },
510
- limit: {
511
- type: [
512
- "number",
513
- "null"
514
- ],
515
- description: "Maximum number of results to return (optional, defaults to 5)"
516
- }
517
- },
518
- required: [
519
- "query",
520
- "chain",
521
- "limit"
522
- ],
523
- additionalProperties: false
524
- }
525
- },
526
- $schema: "http://json-schema.org/draft-07/schema#"
527
- }
528
- },
529
- {
530
- name: "token_swap_build",
531
- description: "Build an unsigned swap transaction. Returns a base64-encoded transaction ready for signing.",
532
- inputSchema: {
533
- $ref: "#/definitions/token_swap_build_input",
534
- definitions: {
535
- token_swap_build_input: {
536
- type: "object",
537
- properties: {
538
- input: {
539
- type: "string",
540
- description: "Mint address of the input token"
541
- },
542
- output: {
543
- type: "string",
544
- description: "Mint address of the output token"
545
- },
546
- amount: {
547
- type: "number",
548
- description: "Amount of the input token to swap"
549
- },
550
- wallet: {
551
- type: "string",
552
- description: "Wallet address that will execute the swap"
553
- }
554
- },
555
- required: [
556
- "input",
557
- "output",
558
- "amount",
559
- "wallet"
560
- ],
561
- additionalProperties: false
562
- }
563
- },
564
- $schema: "http://json-schema.org/draft-07/schema#"
565
- }
566
- },
567
- {
568
- name: "token_swap_execute",
569
- description: "Execute a signed swap transaction. Pass the signed transaction and requestId from token_swap_build.",
570
- inputSchema: {
571
- $ref: "#/definitions/token_swap_execute_input",
572
- definitions: {
573
- token_swap_execute_input: {
574
- type: "object",
575
- properties: {
576
- transaction: {
577
- type: "string",
578
- description: "Base64-encoded signed transaction"
579
- },
580
- requestId: {
581
- type: "string",
582
- description: "Request ID from token_swap_build"
583
- }
584
- },
585
- required: [
586
- "transaction",
587
- "requestId"
588
- ],
589
- additionalProperties: false
590
- }
591
- },
592
- $schema: "http://json-schema.org/draft-07/schema#"
593
- }
594
- },
595
- {
596
- name: "token_transfer_build",
597
- description: "Build an unsigned transfer transaction. Returns a base64-encoded transaction ready for signing. Handles both native SOL and SPL tokens.",
598
- inputSchema: {
599
- $ref: "#/definitions/token_transfer_build_input",
600
- definitions: {
601
- token_transfer_build_input: {
602
- type: "object",
603
- properties: {
604
- wallet: {
605
- type: "string",
606
- description: "Wallet address to transfer from"
607
- },
608
- token: {
609
- type: "string",
610
- description: "Mint address of the token to transfer"
611
- },
612
- to: {
613
- type: "string",
614
- description: "Recipient wallet address"
615
- },
616
- amount: {
617
- type: "number",
618
- description: "Amount to transfer in human-readable units (e.g. 1.5)"
619
- }
620
- },
621
- required: [
622
- "wallet",
623
- "token",
624
- "to",
625
- "amount"
626
- ],
627
- additionalProperties: false
628
- }
629
- },
630
- $schema: "http://json-schema.org/draft-07/schema#"
631
- }
632
- },
633
- {
634
- name: "token_trending_list",
635
- description: "Get currently trending tokens on a blockchain. Perfect for discovering what's hot right now.",
636
- inputSchema: {
637
- $ref: "#/definitions/token_trending_list_input",
638
- definitions: {
639
- token_trending_list_input: {
640
- type: "object",
641
- properties: {
642
- chain: {
643
- type: "string",
644
- enum: [
645
- "solana",
646
- "ethereum",
647
- "base",
648
- "polygon",
649
- "arbitrum",
650
- "optimism"
651
- ],
652
- description: "Blockchain to get trending tokens from (e.g. 'solana', 'ethereum', 'base')"
653
- },
654
- limit: {
655
- type: "number",
656
- description: "Number of results per page"
657
- },
658
- page: {
659
- type: "number",
660
- description: "The page number of results"
661
- }
662
- },
663
- required: [
664
- "chain",
665
- "limit",
666
- "page"
667
- ],
668
- additionalProperties: false
669
- }
670
- },
671
- $schema: "http://json-schema.org/draft-07/schema#"
672
- }
673
- },
674
- {
675
- name: "transaction_send",
676
- description: "Broadcast a signed transaction to Solana. Simulates first, then sends and confirms.",
677
- inputSchema: {
678
- $ref: "#/definitions/transaction_send_input",
679
- definitions: {
680
- transaction_send_input: {
681
- type: "object",
682
- properties: {
683
- transaction: {
684
- type: "string",
685
- description: "Base64-encoded signed transaction"
686
- },
687
- message: {
688
- type: "string",
689
- description: "Human-readable message describing the transaction"
690
- }
691
- },
692
- required: [
693
- "transaction",
694
- "message"
695
- ],
696
- additionalProperties: false
697
- }
698
- },
699
- $schema: "http://json-schema.org/draft-07/schema#"
700
- }
701
- },
702
- {
703
- name: "user_retrieve",
704
- description: "Get the currently authenticated user",
705
- inputSchema: {
706
- $ref: "#/definitions/user_retrieve_input",
707
- definitions: {
708
- user_retrieve_input: {
709
- type: "object",
710
- properties: {},
711
- additionalProperties: false
712
- }
713
- },
714
- $schema: "http://json-schema.org/draft-07/schema#"
715
- }
716
- },
717
- {
718
- name: "virtual-account_bank-account_delete",
719
- description: "Delete a bank account",
720
- inputSchema: {
721
- $ref: "#/definitions/virtual-account_bank-account_delete_input",
722
- definitions: {
723
- "virtual-account_bank-account_delete_input": {
724
- type: "object",
725
- properties: {
726
- bankAccountId: {
727
- type: "string",
728
- format: "uuid",
729
- description: "The ID of the bank account to delete"
730
- }
731
- },
732
- required: [
733
- "bankAccountId"
734
- ],
735
- additionalProperties: false
736
- }
737
- },
738
- $schema: "http://json-schema.org/draft-07/schema#"
739
- }
740
- },
741
- {
742
- name: "virtual-account_bank-account_eur_register",
743
- description: "Register a EUR bank account for offramp payouts",
744
- inputSchema: {
745
- $ref: "#/definitions/virtual-account_bank-account_eur_register_input",
746
- definitions: {
747
- "virtual-account_bank-account_eur_register_input": {
748
- type: "object",
749
- properties: {
750
- iban: {
751
- type: "string",
752
- description: "IBAN for SEPA bank account"
753
- },
754
- address: {
755
- type: "object",
756
- properties: {
757
- street: {
758
- type: "string",
759
- description: "Street address"
760
- },
761
- city: {
762
- type: "string",
763
- description: "City"
764
- },
765
- state: {
766
- type: "string",
767
- description: "State or province"
768
- },
769
- country: {
770
- type: "string",
771
- enum: [
772
- "US",
773
- "GB",
774
- "CA",
775
- "AU",
776
- "DE",
777
- "FR",
778
- "IT",
779
- "ES",
780
- "NL",
781
- "BE",
782
- "AT",
783
- "CH",
784
- "SE",
785
- "NO",
786
- "DK",
787
- "FI",
788
- "IE",
789
- "PT",
790
- "PL",
791
- "CZ",
792
- "GR",
793
- "JP",
794
- "KR",
795
- "CN",
796
- "IN",
797
- "BR",
798
- "MX",
799
- "AR",
800
- "ZA",
801
- "NZ",
802
- "SG",
803
- "HK",
804
- "AE"
805
- ],
806
- description: "ISO 3166-1 Alpha-2 country code"
807
- },
808
- postalCode: {
809
- type: "string",
810
- description: "Postal or ZIP code"
811
- }
812
- },
813
- required: [
814
- "street",
815
- "city",
816
- "state",
817
- "country",
818
- "postalCode"
819
- ],
820
- additionalProperties: false,
821
- description: "Address of the user that owns the bank account"
822
- },
823
- email: {
824
- type: "string",
825
- description: "Email address of the user that owns the bank account"
826
- },
827
- phoneNumber: {
828
- type: "string",
829
- description: "Phone number of the user"
830
- },
831
- providerCountry: {
832
- type: "string",
833
- enum: [
834
- "US",
835
- "GB",
836
- "CA",
837
- "AU",
838
- "DE",
839
- "FR",
840
- "IT",
841
- "ES",
842
- "NL",
843
- "BE",
844
- "AT",
845
- "CH",
846
- "SE",
847
- "NO",
848
- "DK",
849
- "FI",
850
- "IE",
851
- "PT",
852
- "PL",
853
- "CZ",
854
- "GR",
855
- "JP",
856
- "KR",
857
- "CN",
858
- "IN",
859
- "BR",
860
- "MX",
861
- "AR",
862
- "ZA",
863
- "NZ",
864
- "SG",
865
- "HK",
866
- "AE"
867
- ],
868
- description: "ISO 3166-1 Alpha-2 country code where the bank is located"
869
- },
870
- providerName: {
871
- type: "string",
872
- description: "Name of the bank"
873
- },
874
- givenName: {
875
- type: "string",
876
- description: "First/given name of the account holder"
877
- },
878
- familyName: {
879
- type: "string",
880
- description: "Last/family name of the account holder"
881
- }
882
- },
883
- required: [
884
- "iban",
885
- "address",
886
- "email",
887
- "phoneNumber",
888
- "providerCountry",
889
- "providerName",
890
- "givenName",
891
- "familyName"
892
- ],
893
- additionalProperties: false
894
- }
895
- },
896
- $schema: "http://json-schema.org/draft-07/schema#"
897
- }
898
- },
899
- {
900
- name: "virtual-account_bank-account_list",
901
- description: "List registered bank accounts",
902
- inputSchema: {
903
- $ref: "#/definitions/virtual-account_bank-account_list_input",
904
- definitions: {
905
- "virtual-account_bank-account_list_input": {
906
- type: "object",
907
- properties: {},
908
- additionalProperties: false
909
- }
910
- },
911
- $schema: "http://json-schema.org/draft-07/schema#"
912
- }
913
- },
914
- {
915
- name: "virtual-account_bank-account_retrieve",
916
- description: "Get a bank account by currency",
917
- inputSchema: {
918
- $ref: "#/definitions/virtual-account_bank-account_retrieve_input",
919
- definitions: {
920
- "virtual-account_bank-account_retrieve_input": {
921
- type: "object",
922
- properties: {
923
- currency: {
924
- type: "string",
925
- enum: [
926
- "USD",
927
- "EUR"
928
- ],
929
- description: "The fiat currency code (USD or EUR)"
930
- }
931
- },
932
- required: [
933
- "currency"
934
- ],
935
- additionalProperties: false
936
- }
937
- },
938
- $schema: "http://json-schema.org/draft-07/schema#"
939
- }
940
- },
941
- {
942
- name: "virtual-account_bank-account_usd_register",
943
- description: "Register a USD bank account for offramp payouts",
944
- inputSchema: {
945
- $ref: "#/definitions/virtual-account_bank-account_usd_register_input",
946
- definitions: {
947
- "virtual-account_bank-account_usd_register_input": {
948
- type: "object",
949
- properties: {
950
- type: {
951
- type: "string",
952
- enum: [
953
- "ACH",
954
- "Wire"
955
- ],
956
- description: "Type of bank account (ACH or Wire)"
957
- },
958
- accountNumber: {
959
- type: "string",
960
- description: "Account number"
961
- },
962
- routingNumber: {
963
- type: "string",
964
- description: "Routing number"
965
- },
966
- address: {
967
- type: "object",
968
- properties: {
969
- street: {
970
- type: "string",
971
- description: "Street address"
972
- },
973
- city: {
974
- type: "string",
975
- description: "City"
976
- },
977
- state: {
978
- type: "string",
979
- description: "State or province"
980
- },
981
- country: {
982
- type: "string",
983
- enum: [
984
- "US",
985
- "GB",
986
- "CA",
987
- "AU",
988
- "DE",
989
- "FR",
990
- "IT",
991
- "ES",
992
- "NL",
993
- "BE",
994
- "AT",
995
- "CH",
996
- "SE",
997
- "NO",
998
- "DK",
999
- "FI",
1000
- "IE",
1001
- "PT",
1002
- "PL",
1003
- "CZ",
1004
- "GR",
1005
- "JP",
1006
- "KR",
1007
- "CN",
1008
- "IN",
1009
- "BR",
1010
- "MX",
1011
- "AR",
1012
- "ZA",
1013
- "NZ",
1014
- "SG",
1015
- "HK",
1016
- "AE"
1017
- ],
1018
- description: "ISO 3166-1 Alpha-2 country code"
1019
- },
1020
- postalCode: {
1021
- type: "string",
1022
- description: "Postal or ZIP code"
1023
- }
1024
- },
1025
- required: [
1026
- "street",
1027
- "city",
1028
- "state",
1029
- "country",
1030
- "postalCode"
1031
- ],
1032
- additionalProperties: false,
1033
- description: "Address of the user that owns the bank account"
1034
- },
1035
- email: {
1036
- type: "string",
1037
- description: "Email address of the user that owns the bank account"
1038
- },
1039
- phoneNumber: {
1040
- type: "string",
1041
- description: "Phone number of the user"
1042
- },
1043
- providerCountry: {
1044
- type: "string",
1045
- enum: [
1046
- "US",
1047
- "GB",
1048
- "CA",
1049
- "AU",
1050
- "DE",
1051
- "FR",
1052
- "IT",
1053
- "ES",
1054
- "NL",
1055
- "BE",
1056
- "AT",
1057
- "CH",
1058
- "SE",
1059
- "NO",
1060
- "DK",
1061
- "FI",
1062
- "IE",
1063
- "PT",
1064
- "PL",
1065
- "CZ",
1066
- "GR",
1067
- "JP",
1068
- "KR",
1069
- "CN",
1070
- "IN",
1071
- "BR",
1072
- "MX",
1073
- "AR",
1074
- "ZA",
1075
- "NZ",
1076
- "SG",
1077
- "HK",
1078
- "AE"
1079
- ],
1080
- description: "ISO 3166-1 Alpha-2 country code where the bank is located"
1081
- },
1082
- providerName: {
1083
- type: "string",
1084
- description: "Name of the bank"
1085
- },
1086
- givenName: {
1087
- type: "string",
1088
- description: "First/given name of the account holder"
1089
- },
1090
- familyName: {
1091
- type: "string",
1092
- description: "Last/family name of the account holder"
1093
- }
1094
- },
1095
- required: [
1096
- "type",
1097
- "accountNumber",
1098
- "routingNumber",
1099
- "address",
1100
- "email",
1101
- "phoneNumber",
1102
- "providerCountry",
1103
- "providerName",
1104
- "givenName",
1105
- "familyName"
1106
- ],
1107
- additionalProperties: false
1108
- }
1109
- },
1110
- $schema: "http://json-schema.org/draft-07/schema#"
1111
- }
1112
- },
1113
- {
1114
- name: "virtual-account_create",
1115
- description: "Create a virtual account and start KYC verification",
1116
- inputSchema: {
1117
- $ref: "#/definitions/virtual-account_create_input",
1118
- definitions: {
1119
- "virtual-account_create_input": {
1120
- type: "object",
1121
- properties: {},
1122
- additionalProperties: false
1123
- }
1124
- },
1125
- $schema: "http://json-schema.org/draft-07/schema#"
1126
- }
1127
- },
1128
- {
1129
- name: "virtual-account_delete",
1130
- description: "Delete your virtual account",
1131
- inputSchema: {
1132
- $ref: "#/definitions/virtual-account_delete_input",
1133
- definitions: {
1134
- "virtual-account_delete_input": {
1135
- type: "object",
1136
- properties: {},
1137
- additionalProperties: false
1138
- }
1139
- },
1140
- $schema: "http://json-schema.org/draft-07/schema#"
1141
- }
1142
- },
1143
- {
1144
- name: "virtual-account_identification_create",
1145
- description: "Create a KYC verification link to complete identity verification",
1146
- inputSchema: {
1147
- $ref: "#/definitions/virtual-account_identification_create_input",
1148
- definitions: {
1149
- "virtual-account_identification_create_input": {
1150
- type: "object",
1151
- properties: {},
1152
- additionalProperties: false
1153
- }
1154
- },
1155
- $schema: "http://json-schema.org/draft-07/schema#"
1156
- }
1157
- },
1158
- {
1159
- name: "virtual-account_identification_list",
1160
- description: "List all KYC identifications",
1161
- inputSchema: {
1162
- $ref: "#/definitions/virtual-account_identification_list_input",
1163
- definitions: {
1164
- "virtual-account_identification_list_input": {
1165
- type: "object",
1166
- properties: {},
1167
- additionalProperties: false
1168
- }
1169
- },
1170
- $schema: "http://json-schema.org/draft-07/schema#"
1171
- }
1172
- },
1173
- {
1174
- name: "virtual-account_identification_retrieve",
1175
- description: "Get the status of a KYC identification",
1176
- inputSchema: {
1177
- $ref: "#/definitions/virtual-account_identification_retrieve_input",
1178
- definitions: {
1179
- "virtual-account_identification_retrieve_input": {
1180
- type: "object",
1181
- properties: {},
1182
- additionalProperties: false
1183
- }
1184
- },
1185
- $schema: "http://json-schema.org/draft-07/schema#"
1186
- }
1187
- },
1188
- {
1189
- name: "virtual-account_offramp_create",
1190
- description: "Create an offramp to convert stablecoin to fiat",
1191
- inputSchema: {
1192
- $ref: "#/definitions/virtual-account_offramp_create_input",
1193
- definitions: {
1194
- "virtual-account_offramp_create_input": {
1195
- type: "object",
1196
- properties: {
1197
- name: {
1198
- type: "string",
1199
- description: "The name of the offramp"
1200
- },
1201
- fiat: {
1202
- type: "string",
1203
- enum: [
1204
- "USD",
1205
- "EUR"
1206
- ],
1207
- description: "The fiat currency to convert to"
1208
- },
1209
- stablecoin: {
1210
- type: "string",
1211
- enum: [
1212
- "USDC",
1213
- "USDT",
1214
- "EURC"
1215
- ],
1216
- description: "The stablecoin token to convert from"
1217
- }
1218
- },
1219
- required: [
1220
- "name",
1221
- "fiat",
1222
- "stablecoin"
1223
- ],
1224
- additionalProperties: false
1225
- }
1226
- },
1227
- $schema: "http://json-schema.org/draft-07/schema#"
1228
- }
1229
- },
1230
- {
1231
- name: "virtual-account_offramp_delete",
1232
- description: "Cancel an offramp",
1233
- inputSchema: {
1234
- $ref: "#/definitions/virtual-account_offramp_delete_input",
1235
- definitions: {
1236
- "virtual-account_offramp_delete_input": {
1237
- type: "object",
1238
- properties: {
1239
- offrampId: {
1240
- type: "string",
1241
- format: "uuid",
1242
- description: "The ID of the offramp to cancel"
1243
- }
1244
- },
1245
- required: [
1246
- "offrampId"
1247
- ],
1248
- additionalProperties: false
1249
- }
1250
- },
1251
- $schema: "http://json-schema.org/draft-07/schema#"
1252
- }
1253
- },
1254
- {
1255
- name: "virtual-account_offramp_initiate",
1256
- description: "Build an unsigned transaction to send stablecoin to an offramp deposit address",
1257
- inputSchema: {
1258
- $ref: "#/definitions/virtual-account_offramp_initiate_input",
1259
- definitions: {
1260
- "virtual-account_offramp_initiate_input": {
1261
- type: "object",
1262
- properties: {
1263
- wallet: {
1264
- type: "string",
1265
- description: "The wallet address to send from"
1266
- },
1267
- offrampId: {
1268
- type: "string",
1269
- description: "The ID of the offramp to initiate"
1270
- },
1271
- amount: {
1272
- type: "number",
1273
- minimum: 0,
1274
- description: "The amount of stablecoin to send (in human-readable units, e.g., 100.5)"
1275
- }
1276
- },
1277
- required: [
1278
- "wallet",
1279
- "offrampId",
1280
- "amount"
1281
- ],
1282
- additionalProperties: false
1283
- }
1284
- },
1285
- $schema: "http://json-schema.org/draft-07/schema#"
1286
- }
1287
- },
1288
- {
1289
- name: "virtual-account_offramp_list",
1290
- description: "List all offramps",
1291
- inputSchema: {
1292
- $ref: "#/definitions/virtual-account_offramp_list_input",
1293
- definitions: {
1294
- "virtual-account_offramp_list_input": {
1295
- type: "object",
1296
- properties: {},
1297
- additionalProperties: false
1298
- }
1299
- },
1300
- $schema: "http://json-schema.org/draft-07/schema#"
1301
- }
1302
- },
1303
- {
1304
- name: "virtual-account_offramp_retrieve",
1305
- description: "Get offramp details",
1306
- inputSchema: {
1307
- $ref: "#/definitions/virtual-account_offramp_retrieve_input",
1308
- definitions: {
1309
- "virtual-account_offramp_retrieve_input": {
1310
- type: "object",
1311
- properties: {
1312
- offrampId: {
1313
- type: "string",
1314
- format: "uuid",
1315
- description: "The ID of the offramp to retrieve"
1316
- }
1317
- },
1318
- required: [
1319
- "offrampId"
1320
- ],
1321
- additionalProperties: false
1322
- }
1323
- },
1324
- $schema: "http://json-schema.org/draft-07/schema#"
1325
- }
1326
- },
1327
- {
1328
- name: "virtual-account_onramp_create",
1329
- description: "Create an onramp to convert fiat to stablecoin",
1330
- inputSchema: {
1331
- $ref: "#/definitions/virtual-account_onramp_create_input",
1332
- definitions: {
1333
- "virtual-account_onramp_create_input": {
1334
- type: "object",
1335
- properties: {
1336
- name: {
1337
- type: "string",
1338
- description: "The name of the onramp"
1339
- },
1340
- fiat: {
1341
- type: "string",
1342
- enum: [
1343
- "USD",
1344
- "EUR"
1345
- ],
1346
- description: "The fiat currency to convert from"
1347
- },
1348
- stablecoin: {
1349
- type: "string",
1350
- enum: [
1351
- "USDC",
1352
- "USDT",
1353
- "EURC"
1354
- ],
1355
- description: "The stablecoin token to convert to"
1356
- }
1357
- },
1358
- required: [
1359
- "name",
1360
- "fiat",
1361
- "stablecoin"
1362
- ],
1363
- additionalProperties: false
1364
- }
1365
- },
1366
- $schema: "http://json-schema.org/draft-07/schema#"
1367
- }
1368
- },
1369
- {
1370
- name: "virtual-account_onramp_delete",
1371
- description: "Cancel an onramp",
1372
- inputSchema: {
1373
- $ref: "#/definitions/virtual-account_onramp_delete_input",
1374
- definitions: {
1375
- "virtual-account_onramp_delete_input": {
1376
- type: "object",
1377
- properties: {
1378
- onrampId: {
1379
- type: "string",
1380
- format: "uuid",
1381
- description: "The ID of the onramp to cancel"
1382
- }
1383
- },
1384
- required: [
1385
- "onrampId"
1386
- ],
1387
- additionalProperties: false
1388
- }
1389
- },
1390
- $schema: "http://json-schema.org/draft-07/schema#"
1391
- }
1392
- },
1393
- {
1394
- name: "virtual-account_onramp_list",
1395
- description: "List all onramps",
1396
- inputSchema: {
1397
- $ref: "#/definitions/virtual-account_onramp_list_input",
1398
- definitions: {
1399
- "virtual-account_onramp_list_input": {
1400
- type: "object",
1401
- properties: {
1402
- status: {
1403
- type: "string",
1404
- enum: [
1405
- "Created",
1406
- "Authorized",
1407
- "DepositAccountAdded",
1408
- "Approved",
1409
- "Rejected",
1410
- "Cancelled"
1411
- ],
1412
- description: "Status of the onramps to get"
1413
- }
1414
- },
1415
- required: [
1416
- "status"
1417
- ],
1418
- additionalProperties: false
1419
- }
1420
- },
1421
- $schema: "http://json-schema.org/draft-07/schema#"
1422
- }
1423
- },
1424
- {
1425
- name: "virtual-account_onramp_payment_create",
1426
- description: "Create an open banking payment link for an onramp",
1427
- inputSchema: {
1428
- $ref: "#/definitions/virtual-account_onramp_payment_create_input",
1429
- definitions: {
1430
- "virtual-account_onramp_payment_create_input": {
1431
- type: "object",
1432
- properties: {
1433
- onrampId: {
1434
- type: "string",
1435
- format: "uuid",
1436
- description: "The ID of the onramp"
1437
- },
1438
- amount: {
1439
- type: "string",
1440
- description: "The amount to pay"
1441
- },
1442
- fiat: {
1443
- type: "string",
1444
- enum: [
1445
- "USD",
1446
- "EUR"
1447
- ],
1448
- description: "The fiat currency (USD or EUR)"
1449
- }
1450
- },
1451
- required: [
1452
- "onrampId",
1453
- "amount",
1454
- "fiat"
1455
- ],
1456
- additionalProperties: false
1457
- }
1458
- },
1459
- $schema: "http://json-schema.org/draft-07/schema#"
1460
- }
1461
- },
1462
- {
1463
- name: "virtual-account_onramp_payment_retrieve",
1464
- description: "Get the status of an open banking payment",
1465
- inputSchema: {
1466
- $ref: "#/definitions/virtual-account_onramp_payment_retrieve_input",
1467
- definitions: {
1468
- "virtual-account_onramp_payment_retrieve_input": {
1469
- type: "object",
1470
- properties: {
1471
- onrampId: {
1472
- type: "string",
1473
- format: "uuid",
1474
- description: "The ID of the onramp this payment belongs to"
1475
- },
1476
- paymentId: {
1477
- type: "string",
1478
- format: "uuid",
1479
- description: "The ID of the payment to retrieve"
1480
- }
1481
- },
1482
- required: [
1483
- "onrampId",
1484
- "paymentId"
1485
- ],
1486
- additionalProperties: false
1487
- }
1488
- },
1489
- $schema: "http://json-schema.org/draft-07/schema#"
1490
- }
1491
- },
1492
- {
1493
- name: "virtual-account_onramp_retrieve",
1494
- description: "Get onramp details and banking info",
1495
- inputSchema: {
1496
- $ref: "#/definitions/virtual-account_onramp_retrieve_input",
1497
- definitions: {
1498
- "virtual-account_onramp_retrieve_input": {
1499
- type: "object",
1500
- properties: {
1501
- onrampId: {
1502
- type: "string",
1503
- format: "uuid",
1504
- description: "The ID of the onramp to retrieve"
1505
- }
1506
- },
1507
- required: [
1508
- "onrampId"
1509
- ],
1510
- additionalProperties: false
1511
- }
1512
- },
1513
- $schema: "http://json-schema.org/draft-07/schema#"
1514
- }
1515
- },
1516
- {
1517
- name: "virtual-account_retrieve",
1518
- description: "Get your virtual account status",
1519
- inputSchema: {
1520
- $ref: "#/definitions/virtual-account_retrieve_input",
1521
- definitions: {
1522
- "virtual-account_retrieve_input": {
1523
- type: "object",
1524
- properties: {},
1525
- additionalProperties: false
1526
- }
1527
- },
1528
- $schema: "http://json-schema.org/draft-07/schema#"
1529
- }
1530
- },
1531
- {
1532
- name: "virtual-account_signing_create",
1533
- description: "Sign a required document for your virtual account",
1534
- inputSchema: {
1535
- $ref: "#/definitions/virtual-account_signing_create_input",
1536
- definitions: {
1537
- "virtual-account_signing_create_input": {
1538
- type: "object",
1539
- properties: {
1540
- contentId: {
1541
- type: "string",
1542
- description: "The unique ID of the content to sign"
1543
- }
1544
- },
1545
- required: [
1546
- "contentId"
1547
- ],
1548
- additionalProperties: false
1549
- }
1550
- },
1551
- $schema: "http://json-schema.org/draft-07/schema#"
1552
- }
1553
- },
1554
- {
1555
- name: "virtual-account_signing_list",
1556
- description: "List all signed documents",
1557
- inputSchema: {
1558
- $ref: "#/definitions/virtual-account_signing_list_input",
1559
- definitions: {
1560
- "virtual-account_signing_list_input": {
1561
- type: "object",
1562
- properties: {},
1563
- additionalProperties: false
1564
- }
1565
- },
1566
- $schema: "http://json-schema.org/draft-07/schema#"
1567
- }
1568
- },
1569
- {
1570
- name: "virtual-account_signing_required_list",
1571
- description: "List documents that require your signature",
1572
- inputSchema: {
1573
- $ref: "#/definitions/virtual-account_signing_required_list_input",
1574
- definitions: {
1575
- "virtual-account_signing_required_list_input": {
1576
- type: "object",
1577
- properties: {},
1578
- additionalProperties: false
1579
- }
1580
- },
1581
- $schema: "http://json-schema.org/draft-07/schema#"
1582
- }
1583
- },
1584
- {
1585
- name: "virtual-account_transaction_list",
1586
- description: "List virtual account transactions",
1587
- inputSchema: {
1588
- $ref: "#/definitions/virtual-account_transaction_list_input",
1589
- definitions: {
1590
- "virtual-account_transaction_list_input": {
1591
- type: "object",
1592
- properties: {},
1593
- additionalProperties: false
1594
- }
1595
- },
1596
- $schema: "http://json-schema.org/draft-07/schema#"
1597
- }
1598
- },
1599
- {
1600
- name: "virtual-account_wallet_list",
1601
- description: "List registered wallets",
1602
- inputSchema: {
1603
- $ref: "#/definitions/virtual-account_wallet_list_input",
1604
- definitions: {
1605
- "virtual-account_wallet_list_input": {
1606
- type: "object",
1607
- properties: {},
1608
- additionalProperties: false
1609
- }
1610
- },
1611
- $schema: "http://json-schema.org/draft-07/schema#"
1612
- }
1613
- },
1614
- {
1615
- name: "virtual-account_wallet_register",
1616
- description: "Register a wallet using a signed verification message",
1617
- inputSchema: {
1618
- $ref: "#/definitions/virtual-account_wallet_register_input",
1619
- definitions: {
1620
- "virtual-account_wallet_register_input": {
1621
- type: "object",
1622
- properties: {
1623
- wallet: {
1624
- type: "string",
1625
- description: "The wallet address to register"
1626
- },
1627
- message: {
1628
- type: "string",
1629
- description: "The verification message (from virtual-account_wallet_registration-message_create)"
1630
- },
1631
- signature: {
1632
- type: "string",
1633
- description: "Base58-encoded signature of the message"
1634
- }
1635
- },
1636
- required: [
1637
- "wallet",
1638
- "message",
1639
- "signature"
1640
- ],
1641
- additionalProperties: false
1642
- }
1643
- },
1644
- $schema: "http://json-schema.org/draft-07/schema#"
1645
- }
1646
- },
1647
- {
1648
- name: "virtual-account_wallet_registration-message_create",
1649
- description: "Create the verification message to register a wallet",
1650
- inputSchema: {
1651
- $ref: "#/definitions/virtual-account_wallet_registration-message_create_input",
1652
- definitions: {
1653
- "virtual-account_wallet_registration-message_create_input": {
1654
- type: "object",
1655
- properties: {
1656
- wallet: {
1657
- type: "string",
1658
- description: "The wallet address to register"
1659
- }
1660
- },
1661
- required: [
1662
- "wallet"
1663
- ],
1664
- additionalProperties: false
1665
- }
1666
- },
1667
- $schema: "http://json-schema.org/draft-07/schema#"
1668
- }
1669
- }
1670
- ];
1671
-
1672
- // src/tools/wallet/create/tool.ts
1673
- import { writeFileSync as writeFileSync3, mkdirSync as mkdirSync3 } from "fs";
1674
- import { join as join3 } from "path";
1675
- import { homedir as homedir3 } from "os";
1676
- import { generateMnemonic } from "@scure/bip39";
1677
- import { wordlist as english } from "@scure/bip39/wordlists/english";
1678
-
1679
- // src/tools/shared.ts
1680
- var defineToolSchema = (config) => config;
1681
- var createTool = (schema, handler) => ({
1682
- schema,
1683
- handler: async (params) => {
1684
- const parsedInput = schema.input.parse(params);
1685
- const result = await handler(parsedInput);
1686
- return schema.output.parse(result);
1687
- }
1688
- });
1689
-
1690
- // src/tools/wallet/vault.ts
1691
- import {
1692
- readFileSync as readFileSync2,
1693
- writeFileSync as writeFileSync2,
1694
- existsSync as existsSync2,
1695
- renameSync as renameSync2,
1696
- mkdirSync as mkdirSync2
1697
- } from "fs";
1698
- import { join as join2 } from "path";
1699
- import { homedir as homedir2 } from "os";
1700
- import {
1701
- randomBytes as randomBytes2,
1702
- randomUUID as randomUUID2,
1703
- scryptSync,
1704
- createCipheriv,
1705
- createDecipheriv
1706
- } from "crypto";
1707
- var CONFIG_DIR2 = join2(homedir2(), ".config", "moonpay");
1708
- var VAULT_PATH = join2(CONFIG_DIR2, "vault.json");
1709
- function ensureConfigDir2() {
1710
- mkdirSync2(CONFIG_DIR2, { recursive: true, mode: 448 });
1711
- }
1712
- function loadVault() {
1713
- if (!existsSync2(VAULT_PATH)) {
1714
- const empty = { version: 1, entries: {} };
1715
- saveVault(empty);
1716
- return empty;
1717
- }
1718
- const raw = JSON.parse(readFileSync2(VAULT_PATH, "utf-8"));
1719
- const locked = lockedVaultDataSchema.safeParse(raw);
1720
- if (locked.success) {
1721
- throw new Error(
1722
- "Vault is locked. Run `mp wallet unlock` to decrypt it first."
1723
- );
1724
- }
1725
- const result = vaultDataSchema.safeParse(raw);
1726
- if (!result.success) {
1727
- throw new Error("Vault file is corrupted or has an unknown format.");
1728
- }
1729
- return result.data;
1730
- }
1731
- function saveVault(vault) {
1732
- ensureConfigDir2();
1733
- const tmpPath = join2(
1734
- CONFIG_DIR2,
1735
- `.vault.${randomBytes2(4).toString("hex")}.tmp`
1736
- );
1737
- writeFileSync2(tmpPath, JSON.stringify(vault, null, 2), { mode: 384 });
1738
- renameSync2(tmpPath, VAULT_PATH);
1739
- }
1740
- function isVaultLocked() {
1741
- if (!existsSync2(VAULT_PATH)) return false;
1742
- const raw = JSON.parse(readFileSync2(VAULT_PATH, "utf-8"));
1743
- return lockedVaultDataSchema.safeParse(raw).success;
1744
- }
1745
- function addHdEntry(mnemonic) {
1746
- const vault = loadVault();
1747
- const id = randomUUID2();
1748
- const entry = { id, type: "hd", mnemonic };
1749
- vault.entries[id] = entry;
1750
- saveVault(vault);
1751
- return id;
1752
- }
1753
- function addImportedEntry(chain, privateKey) {
1754
- const vault = loadVault();
1755
- const id = randomUUID2();
1756
- const entry = { id, type: "imported", chain, privateKey };
1757
- vault.entries[id] = entry;
1758
- saveVault(vault);
1759
- return id;
1760
- }
1761
- function removeVaultEntry(id) {
1762
- const vault = loadVault();
1763
- delete vault.entries[id];
1764
- saveVault(vault);
1765
- }
1766
- function resolveSigningKey(wallet, chain) {
1767
- const vault = loadVault();
1768
- const entry = vault.entries[wallet.vaultRef];
1769
- if (!entry) {
1770
- throw new Error(
1771
- `Vault entry not found for wallet "${wallet.name}". The vault may be out of sync.`
1772
- );
1773
- }
1774
- const keyChain = KEY_CHAIN_MAP[chain];
1775
- if (entry.type === "imported") {
1776
- if (entry.chain !== keyChain) {
1777
- throw new Error(
1778
- `Wallet "${wallet.name}" was imported for ${entry.chain}, cannot sign for ${chain}.`
1779
- );
1780
- }
1781
- return {
1782
- privateKey: decodePrivateKey(entry.privateKey, keyChain),
1783
- address: wallet.addresses[keyChain]
1784
- };
1785
- }
1786
- const derived = deriveKeyForChain(entry.mnemonic, keyChain, wallet.account ?? 0);
1787
- return {
1788
- privateKey: derived.privateKey,
1789
- address: derived.address
1790
- };
1791
- }
1792
- function decodePrivateKey(key, chain) {
1793
- if (chain === "solana") {
1794
- const bs583 = __require("bs58");
1795
- return bs583.default.decode(key);
1796
- }
1797
- return Uint8Array.from(Buffer.from(key, "hex"));
1798
- }
1799
- var SCRYPT_N = 2 ** 14;
1800
- var SCRYPT_R = 8;
1801
- var SCRYPT_P = 1;
1802
- var KEY_LENGTH = 32;
1803
- function deriveEncryptionKey(password, salt) {
1804
- return scryptSync(password, salt, KEY_LENGTH, {
1805
- N: SCRYPT_N,
1806
- r: SCRYPT_R,
1807
- p: SCRYPT_P
1808
- });
1809
- }
1810
- function lockVault(password) {
1811
- const vault = loadVault();
1812
- const salt = randomBytes2(32);
1813
- const key = deriveEncryptionKey(password, salt);
1814
- const iv = randomBytes2(12);
1815
- const cipher = createCipheriv("aes-256-gcm", key, iv);
1816
- const plaintext = JSON.stringify(vault);
1817
- const encrypted = Buffer.concat([
1818
- cipher.update(plaintext, "utf8"),
1819
- cipher.final()
1820
- ]);
1821
- const tag = cipher.getAuthTag();
1822
- const locked = {
1823
- version: 1,
1824
- locked: true,
1825
- ciphertext: encrypted.toString("base64"),
1826
- iv: iv.toString("base64"),
1827
- salt: salt.toString("base64"),
1828
- tag: tag.toString("base64")
1829
- };
1830
- ensureConfigDir2();
1831
- const tmpPath = join2(
1832
- CONFIG_DIR2,
1833
- `.vault.${randomBytes2(4).toString("hex")}.tmp`
1834
- );
1835
- writeFileSync2(tmpPath, JSON.stringify(locked, null, 2), { mode: 384 });
1836
- renameSync2(tmpPath, VAULT_PATH);
1837
- }
1838
- function unlockVault(password) {
1839
- if (!existsSync2(VAULT_PATH)) {
1840
- throw new Error("No vault found. Create a wallet first.");
1841
- }
1842
- const raw = JSON.parse(readFileSync2(VAULT_PATH, "utf-8"));
1843
- const locked = lockedVaultDataSchema.safeParse(raw);
1844
- if (!locked.success) {
1845
- throw new Error("Vault is not locked.");
1846
- }
1847
- const { ciphertext, iv, salt, tag } = locked.data;
1848
- const saltBuf = Buffer.from(salt, "base64");
1849
- const key = deriveEncryptionKey(password, saltBuf);
1850
- const ivBuf = Buffer.from(iv, "base64");
1851
- const tagBuf = Buffer.from(tag, "base64");
1852
- const ciphertextBuf = Buffer.from(ciphertext, "base64");
1853
- const decipher = createDecipheriv("aes-256-gcm", key, ivBuf, { authTagLength: 16 });
1854
- decipher.setAuthTag(tagBuf);
1855
- let decrypted;
1856
- try {
1857
- decrypted = Buffer.concat([
1858
- decipher.update(ciphertextBuf),
1859
- decipher.final()
1860
- ]);
1861
- } catch {
1862
- throw new Error("Wrong password.");
1863
- }
1864
- const vault = vaultDataSchema.parse(JSON.parse(decrypted.toString("utf8")));
1865
- saveVault(vault);
1866
- }
1867
-
1868
- // src/tools/wallet/create/schema.ts
1869
- import { z } from "zod";
1870
- var walletCreateSchema = defineToolSchema({
1871
- name: "wallet_create",
1872
- description: "Create a new multi-chain HD wallet. Generates a BIP39 mnemonic seed phrase and derives addresses for Solana, Ethereum (shared by Base, Arbitrum, Polygon, Optimism, BNB, Avalanche), Bitcoin, and Tron. The mnemonic is saved to a local backup file (path returned in output) \u2014 it is never printed or returned in the response. To derive additional accounts from the same mnemonic, pass --from with an existing wallet name and --account with the desired index.",
1873
- input: z.object({
1874
- name: z.string().describe("Wallet name"),
1875
- from: z.string().nullable().describe("Name of an existing HD wallet to derive from. Uses the same mnemonic but a different account index. Omit to generate a new mnemonic."),
1876
- account: z.number().int().min(0).nullable().describe("BIP44 account index (0, 1, 2, ...). Required when using --from. Omit for new wallets (defaults to 0).")
1877
- }),
1878
- output: z.object({
1879
- name: z.string().describe("Wallet name"),
1880
- account: z.number().describe("BIP44 account index used for derivation"),
1881
- addresses: z.record(keyChainSchema, z.string()).describe("Derived addresses per chain (solana, ethereum, bitcoin, tron)"),
1882
- backupPath: z.string().nullable().describe("Path to the mnemonic backup file (0o600 permissions). Null when derived from an existing wallet.")
1883
- })
1884
- });
1885
-
1886
- // src/tools/wallet/create/tool.ts
1887
- var walletCreate = createTool(walletCreateSchema, async (params) => {
1888
- if (params.from) {
1889
- if (params.account === null) {
1890
- throw new Error("--account is required when using --from.");
1891
- }
1892
- return deriveFromExisting(params.name, params.from, params.account);
1893
- }
1894
- return createNew(params.name);
1895
- });
1896
- function createNew(name) {
1897
- const mnemonic = generateMnemonic(english, 128);
1898
- const addresses = deriveAllAddresses(mnemonic);
1899
- const vaultRef = addHdEntry(mnemonic);
1900
- const metadata = {
1901
- name,
1902
- type: "hd",
1903
- vaultRef,
1904
- account: 0,
1905
- addresses,
1906
- createdAt: (/* @__PURE__ */ new Date()).toISOString()
1907
- };
1908
- saveWalletMetadata(metadata);
1909
- const backupDir = join3(homedir3(), ".config", "moonpay", "backups");
1910
- mkdirSync3(backupDir, { recursive: true, mode: 448 });
1911
- const backupPath = join3(backupDir, `${name}.mnemonic`);
1912
- writeFileSync3(backupPath, mnemonic + "\n", { mode: 384 });
1913
- return { name, account: 0, addresses, backupPath };
1914
- }
1915
- function deriveFromExisting(name, from, account) {
1916
- const source = loadWallet(from);
1917
- if (source.type !== "hd") {
1918
- throw new Error(
1919
- `Wallet "${from}" is an imported single-key wallet. Only HD wallets support account derivation.`
1920
- );
1921
- }
1922
- const vault = loadVault();
1923
- const entry = vault.entries[source.vaultRef];
1924
- if (!entry || entry.type !== "hd") {
1925
- throw new Error(`Vault entry for wallet "${from}" not found or is not HD.`);
1926
- }
1927
- const addresses = deriveAllAddresses(entry.mnemonic, account);
1928
- const metadata = {
1929
- name,
1930
- type: "hd",
1931
- vaultRef: source.vaultRef,
1932
- account,
1933
- addresses,
1934
- createdAt: (/* @__PURE__ */ new Date()).toISOString()
1935
- };
1936
- saveWalletMetadata(metadata);
1937
- return { name, account, addresses, backupPath: null };
1938
- }
1939
-
1940
- // src/tools/wallet/import/tool.ts
1941
- import { validateMnemonic } from "@scure/bip39";
1942
- import { wordlist as english2 } from "@scure/bip39/wordlists/english";
1943
- import { Keypair } from "@solana/web3.js";
1944
- import bs58 from "bs58";
1945
- import { createInterface as createInterface2 } from "readline";
1946
-
1947
- // src/tools/wallet/import/schema.ts
1948
- import { z as z2 } from "zod";
1949
- var walletImportSchema = defineToolSchema({
1950
- name: "wallet_import",
1951
- description: "Import a wallet from a BIP39 mnemonic (HD, all chains) or a single private key (one chain). Provide either --mnemonic or --key, not both.",
1952
- input: z2.object({
1953
- name: z2.string().describe("Wallet name"),
1954
- mnemonic: z2.string().nullable().describe("BIP39 mnemonic seed phrase (for HD wallet import)"),
1955
- key: z2.string().nullable().describe(
1956
- "Private key: base58 for Solana, hex for EVM/Bitcoin (for single-chain import)"
1957
- ),
1958
- chain: chainSchema.nullable().describe(
1959
- "Chain for single-key import: solana, ethereum, base, arbitrum, or bitcoin (default solana)"
1960
- )
1961
- }),
1962
- output: z2.object({
1963
- name: z2.string().describe("Wallet name"),
1964
- type: z2.enum(["hd", "imported"]).describe("Wallet type"),
1965
- addresses: z2.record(keyChainSchema, z2.string()).describe("Wallet addresses per chain")
1966
- })
1967
- });
1968
-
1969
- // src/tools/wallet/import/tool.ts
1970
- async function promptSecret(prompt) {
1971
- const rl = createInterface2({ input: process.stdin, output: process.stderr });
1972
- return new Promise((resolve) => {
1973
- rl.question(prompt, (answer) => {
1974
- rl.close();
1975
- resolve(answer.trim());
1976
- });
1977
- });
1978
- }
1979
- var walletImport = createTool(walletImportSchema, async (params) => {
1980
- if (params.mnemonic && params.key) {
1981
- throw new Error("Provide either --mnemonic or --key, not both.");
1982
- }
1983
- if (params.mnemonic) {
1984
- return importMnemonic(params.name, params.mnemonic);
1985
- }
1986
- const chain = params.chain ? KEY_CHAIN_MAP[params.chain] : "solana";
1987
- const key = params.key !== null ? params.key : await promptSecret("Enter private key: ");
1988
- return importKey(params.name, chain, key);
1989
- });
1990
- async function importMnemonic(name, mnemonic) {
1991
- const trimmed = mnemonic.trim().toLowerCase();
1992
- if (!validateMnemonic(trimmed, english2)) {
1993
- throw new Error("Invalid BIP39 mnemonic.");
1994
- }
1995
- const addresses = deriveAllAddresses(trimmed);
1996
- const vaultRef = addHdEntry(trimmed);
1997
- const metadata = {
1998
- name,
1999
- type: "hd",
2000
- vaultRef,
2001
- account: 0,
2002
- addresses,
2003
- createdAt: (/* @__PURE__ */ new Date()).toISOString()
2004
- };
2005
- saveWalletMetadata(metadata);
2006
- return { name, type: "hd", addresses };
2007
- }
2008
- async function importKey(name, chain, key) {
2009
- let address;
2010
- if (chain === "solana") {
2011
- try {
2012
- const secretKeyBytes = bs58.decode(key);
2013
- const keypair = Keypair.fromSecretKey(secretKeyBytes);
2014
- address = keypair.publicKey.toBase58();
2015
- } catch {
2016
- throw new Error(
2017
- "Invalid private key. Expected a base58-encoded Solana secret key."
2018
- );
2019
- }
2020
- } else if (chain === "ethereum") {
2021
- const cleanKey = key.startsWith("0x") ? key.slice(2) : key;
2022
- if (!/^[0-9a-fA-F]{64}$/.test(cleanKey)) {
2023
- throw new Error(
2024
- "Invalid private key. Expected a 64-character hex string for EVM."
2025
- );
2026
- }
2027
- const { deriveKeyForChain: deriveKeyForChain2 } = await import("./chains-R754DQM5.js");
2028
- const { HDKey } = await import("@scure/bip32");
2029
- const ecc2 = await import("tiny-secp256k1");
2030
- const { createHash: createHash3 } = await import("crypto");
2031
- const privKeyBytes = Buffer.from(cleanKey, "hex");
2032
- const pubKey = ecc2.pointFromScalar(privKeyBytes);
2033
- if (!pubKey) throw new Error("Invalid private key.");
2034
- const uncompressed = ecc2.pointCompress(pubKey, false);
2035
- const hash = createHash3("sha3-256").update(uncompressed.slice(1)).digest();
2036
- address = "0x" + hash.slice(-20).toString("hex");
2037
- key = cleanKey;
2038
- } else {
2039
- const cleanKey = key.startsWith("0x") ? key.slice(2) : key;
2040
- if (!/^[0-9a-fA-F]{64}$/.test(cleanKey)) {
2041
- throw new Error(
2042
- "Invalid private key. Expected a 64-character hex string for Bitcoin."
2043
- );
2044
- }
2045
- const bitcoin = await import("bitcoinjs-lib");
2046
- const ECPairFactory = (await import("ecpair")).default;
2047
- const ecc2 = await import("tiny-secp256k1");
2048
- const ECPair = ECPairFactory(ecc2);
2049
- const keyPair = ECPair.fromPrivateKey(Buffer.from(cleanKey, "hex"));
2050
- const { address: btcAddress } = bitcoin.payments.p2wpkh({
2051
- pubkey: Buffer.from(keyPair.publicKey)
2052
- });
2053
- if (!btcAddress) throw new Error("Failed to derive Bitcoin address.");
2054
- address = btcAddress;
2055
- key = cleanKey;
2056
- }
2057
- const vaultRef = addImportedEntry(chain, key);
2058
- const metadata = {
2059
- name,
2060
- type: "imported",
2061
- vaultRef,
2062
- account: 0,
2063
- addresses: { [chain]: address },
2064
- createdAt: (/* @__PURE__ */ new Date()).toISOString()
2065
- };
2066
- saveWalletMetadata(metadata);
2067
- return { name, type: "imported", addresses: { [chain]: address } };
2068
- }
2069
-
2070
- // src/tools/wallet/list/schema.ts
2071
- import { z as z3 } from "zod";
2072
- var walletListSchema = defineToolSchema({
2073
- name: "wallet_list",
2074
- description: "List all local wallets",
2075
- input: z3.object({}),
2076
- output: z3.array(walletInfoSchema)
2077
- });
2078
-
2079
- // src/tools/wallet/list/tool.ts
2080
- var walletList = createTool(walletListSchema, async () => {
2081
- return loadAllWallets();
2082
- });
2083
-
2084
- // src/tools/wallet/retrieve/schema.ts
2085
- import { z as z4 } from "zod";
2086
- var walletRetrieveSchema = defineToolSchema({
2087
- name: "wallet_retrieve",
2088
- description: "Get details of a specific wallet",
2089
- input: z4.object({
2090
- wallet: z4.string().describe("Wallet name or address")
2091
- }),
2092
- output: walletInfoSchema
2093
- });
2094
-
2095
- // src/tools/wallet/retrieve/tool.ts
2096
- var walletRetrieve = createTool(
2097
- walletRetrieveSchema,
2098
- async (params) => {
2099
- return loadWallet(params.wallet);
2100
- }
2101
- );
2102
-
2103
- // src/tools/wallet/delete/schema.ts
2104
- import { z as z5 } from "zod";
2105
- var walletDeleteSchema = defineToolSchema({
2106
- name: "wallet_delete",
2107
- description: "Permanently delete a local wallet. This removes the private key file and cannot be undone.",
2108
- input: z5.object({
2109
- wallet: z5.string().describe("Name or address of the wallet to delete"),
2110
- confirm: z5.boolean().describe("Must be true to confirm deletion")
2111
- }),
2112
- output: z5.object({
2113
- name: z5.string().describe("Name of the deleted wallet"),
2114
- deleted: z5.literal(true)
2115
- })
2116
- });
2117
-
2118
- // src/tools/wallet/delete/tool.ts
2119
- var walletDelete = createTool(walletDeleteSchema, async (params) => {
2120
- if (!params.confirm) {
2121
- throw new Error(
2122
- "Deletion not confirmed. Pass --confirm to permanently delete this wallet."
2123
- );
2124
- }
2125
- const wallet = loadWallet(params.wallet);
2126
- removeVaultEntry(wallet.vaultRef);
2127
- deleteWalletFile(wallet.name);
2128
- return { name: wallet.name, deleted: true };
2129
- });
2130
-
2131
- // src/tools/transaction/sign/tool.ts
2132
- import { Keypair as Keypair2, VersionedTransaction } from "@solana/web3.js";
2133
-
2134
- // src/tools/transaction/sign/schema.ts
2135
- import { z as z6 } from "zod";
2136
- var transactionSignSchema = defineToolSchema({
2137
- name: "transaction_sign",
2138
- description: "Sign a transaction with a local wallet. Supports Solana (VersionedTransaction), EVM (RLP-encoded), and Bitcoin (PSBT) transactions.",
2139
- input: z6.object({
2140
- wallet: z6.string().describe("Wallet name or address"),
2141
- chain: chainSchema.describe(
2142
- "Chain: solana, ethereum, base, arbitrum, or bitcoin"
2143
- ),
2144
- transaction: z6.string().describe("Base64-encoded unsigned transaction")
2145
- }),
2146
- output: z6.object({
2147
- transaction: z6.string().describe("Base64-encoded signed transaction")
2148
- })
2149
- });
2150
-
2151
- // src/tools/transaction/sign/tool.ts
2152
- var transactionSign = createTool(
2153
- transactionSignSchema,
2154
- async (params) => {
2155
- const wallet = loadWallet(params.wallet);
2156
- const chain = params.chain;
2157
- const keyChain = KEY_CHAIN_MAP[chain];
2158
- const { privateKey } = resolveSigningKey(wallet, chain);
2159
- const txBytes = Buffer.from(params.transaction.trim(), "base64");
2160
- switch (keyChain) {
2161
- case "solana":
2162
- return signSolana(privateKey, txBytes);
2163
- case "ethereum":
2164
- return signEvm(privateKey, txBytes);
2165
- case "bitcoin":
2166
- return signBitcoin(privateKey, txBytes);
2167
- case "tron":
2168
- return signEvm(privateKey, txBytes);
2169
- }
2170
- }
2171
- );
2172
- function signSolana(privateKey, txBytes) {
2173
- const tx = VersionedTransaction.deserialize(txBytes);
2174
- const keypair = Keypair2.fromSecretKey(privateKey);
2175
- tx.sign([keypair]);
2176
- return { transaction: Buffer.from(tx.serialize()).toString("base64") };
2177
- }
2178
- async function signEvm(privateKey, txBytes) {
2179
- const { createHash: createHash3 } = await import("crypto");
2180
- const ecc2 = await import("tiny-secp256k1");
2181
- const hash = createHash3("sha3-256").update(txBytes).digest();
2182
- const sig = ecc2.sign(hash, privateKey);
2183
- if (!sig) throw new Error("EVM signing failed");
2184
- const signed = Buffer.concat([txBytes, Buffer.from(sig)]);
2185
- return { transaction: signed.toString("base64") };
2186
- }
2187
- async function signBitcoin(privateKey, txBytes) {
2188
- const bitcoin = await import("bitcoinjs-lib");
2189
- const ECPairFactory = (await import("ecpair")).default;
2190
- const ecc2 = await import("tiny-secp256k1");
2191
- const ECPair = ECPairFactory(ecc2);
2192
- const keyPair = ECPair.fromPrivateKey(Buffer.from(privateKey));
2193
- const psbt = bitcoin.Psbt.fromBase64(txBytes.toString("base64"));
2194
- psbt.signAllInputs(keyPair);
2195
- return { transaction: psbt.toBase64() };
2196
- }
2197
-
2198
- // src/tools/message/sign/tool.ts
2199
- import { createHash as createHash2 } from "crypto";
2200
- import { Keypair as Keypair3 } from "@solana/web3.js";
2201
- import bs582 from "bs58";
2202
- import nacl from "tweetnacl";
2203
- import * as ecc from "tiny-secp256k1";
2204
-
2205
- // src/tools/message/sign/schema.ts
2206
- import { z as z7 } from "zod";
2207
- var messageSignSchema = defineToolSchema({
2208
- name: "message_sign",
2209
- description: "Sign a message with a local wallet. Supports Solana (ed25519), EVM (EIP-191 personal sign), and Bitcoin (secp256k1 ECDSA).",
2210
- input: z7.object({
2211
- wallet: z7.string().describe("Wallet address or name to sign with"),
2212
- chain: chainSchema.describe(
2213
- "Chain: solana, ethereum, base, arbitrum, or bitcoin"
2214
- ),
2215
- message: z7.string().describe("Message text to sign")
2216
- }),
2217
- output: z7.object({
2218
- signature: z7.string().describe(
2219
- "Signature: base58 for Solana, hex (0x-prefixed) for EVM/Bitcoin"
2220
- )
2221
- })
2222
- });
2223
-
2224
- // src/tools/message/sign/tool.ts
2225
- var messageSign = createTool(messageSignSchema, async (params) => {
2226
- const wallet = loadWallet(params.wallet);
2227
- const chain = params.chain;
2228
- const keyChain = KEY_CHAIN_MAP[chain];
2229
- const { privateKey } = resolveSigningKey(wallet, chain);
2230
- const messageBytes = Buffer.from(params.message, "utf8");
2231
- switch (keyChain) {
2232
- case "solana":
2233
- return signSolana2(privateKey, messageBytes);
2234
- case "ethereum":
2235
- return signEvm2(privateKey, messageBytes);
2236
- case "bitcoin":
2237
- return signBitcoin2(privateKey, messageBytes);
2238
- case "tron":
2239
- return signEvm2(privateKey, messageBytes);
2240
- }
2241
- });
2242
- function signSolana2(privateKey, messageBytes) {
2243
- const keypair = Keypair3.fromSecretKey(privateKey);
2244
- const signatureBytes = nacl.sign.detached(messageBytes, keypair.secretKey);
2245
- return { signature: bs582.encode(signatureBytes) };
2246
- }
2247
- function signEvm2(privateKey, messageBytes) {
2248
- const prefix = Buffer.from(
2249
- `Ethereum Signed Message:
2250
- ${messageBytes.length}`,
2251
- "utf8"
2252
- );
2253
- const prefixed = Buffer.concat([prefix, messageBytes]);
2254
- const hash = createHash2("sha3-256").update(prefixed).digest();
2255
- const sig = ecc.sign(hash, privateKey);
2256
- if (!sig) throw new Error("EVM message signing failed");
2257
- return { signature: "0x" + Buffer.from(sig).toString("hex") };
2258
- }
2259
- function signBitcoin2(privateKey, messageBytes) {
2260
- const hash1 = createHash2("sha256").update(messageBytes).digest();
2261
- const hash2 = createHash2("sha256").update(hash1).digest();
2262
- const sig = ecc.sign(hash2, privateKey);
2263
- if (!sig) throw new Error("Bitcoin message signing failed");
2264
- return { signature: "0x" + Buffer.from(sig).toString("hex") };
2265
- }
2266
-
2267
- // src/tools/wallet/lock/tool.ts
2268
- import { createInterface as createInterface3 } from "readline";
2269
-
2270
- // src/tools/wallet/lock/schema.ts
2271
- import { z as z8 } from "zod";
2272
- var walletLockSchema = defineToolSchema({
2273
- name: "wallet_lock",
2274
- description: "Encrypt the vault with a password. All signing operations will fail until `wallet unlock` is called. Password is prompted interactively.",
2275
- input: z8.object({}),
2276
- output: z8.object({
2277
- locked: z8.literal(true)
2278
- })
2279
- });
2280
-
2281
- // src/tools/wallet/lock/tool.ts
2282
- async function promptPassword(prompt) {
2283
- const rl = createInterface3({ input: process.stdin, output: process.stderr });
2284
- return new Promise((resolve) => {
2285
- rl.question(prompt, (answer) => {
2286
- rl.close();
2287
- resolve(answer);
2288
- });
2289
- });
2290
- }
2291
- var walletLock = createTool(walletLockSchema, async () => {
2292
- if (isVaultLocked()) {
2293
- throw new Error("Vault is already locked.");
2294
- }
2295
- const password = await promptPassword("Enter password to encrypt vault: ");
2296
- if (!password) {
2297
- throw new Error("Password cannot be empty.");
2298
- }
2299
- const confirm = await promptPassword("Confirm password: ");
2300
- if (password !== confirm) {
2301
- throw new Error("Passwords do not match.");
2302
- }
2303
- lockVault(password);
2304
- return { locked: true };
2305
- });
2306
-
2307
- // src/tools/wallet/unlock/tool.ts
2308
- import { createInterface as createInterface4 } from "readline";
2309
-
2310
- // src/tools/wallet/unlock/schema.ts
2311
- import { z as z9 } from "zod";
2312
- var walletUnlockSchema = defineToolSchema({
2313
- name: "wallet_unlock",
2314
- description: "Decrypt the vault with a password. Restores access to all signing operations. Password is prompted interactively.",
2315
- input: z9.object({}),
2316
- output: z9.object({
2317
- unlocked: z9.literal(true)
2318
- })
2319
- });
2320
-
2321
- // src/tools/wallet/unlock/tool.ts
2322
- async function promptPassword2(prompt) {
2323
- const rl = createInterface4({ input: process.stdin, output: process.stderr });
2324
- return new Promise((resolve) => {
2325
- rl.question(prompt, (answer) => {
2326
- rl.close();
2327
- resolve(answer);
2328
- });
2329
- });
2330
- }
2331
- var walletUnlock = createTool(walletUnlockSchema, async () => {
2332
- if (!isVaultLocked()) {
2333
- throw new Error("Vault is not locked.");
2334
- }
2335
- const password = await promptPassword2("Enter password to decrypt vault: ");
2336
- unlockVault(password);
2337
- return { unlocked: true };
2338
- });
2339
-
2340
- // src/tools/bitcoin/balance/tool.ts
2341
- import https from "https";
2342
-
2343
- // src/tools/bitcoin/balance/schema.ts
2344
- import { z as z10 } from "zod";
2345
- var bitcoinBalanceRetrieveSchema = defineToolSchema({
2346
- name: "bitcoin_balance_retrieve",
2347
- description: "Get the BTC balance of a Bitcoin address. Returns confirmed and unconfirmed balances in BTC and satoshis.",
2348
- input: z10.object({
2349
- wallet: z10.string().describe("Bitcoin address (bc1...) or wallet name")
2350
- }),
2351
- output: z10.object({
2352
- address: z10.string().describe("Bitcoin address"),
2353
- confirmed: z10.object({
2354
- btc: z10.string().describe("Confirmed balance in BTC"),
2355
- sats: z10.number().describe("Confirmed balance in satoshis")
2356
- }),
2357
- unconfirmed: z10.object({
2358
- btc: z10.string().describe("Unconfirmed (pending) balance in BTC"),
2359
- sats: z10.number().describe("Unconfirmed (pending) balance in satoshis")
2360
- }),
2361
- total: z10.object({
2362
- btc: z10.string().describe("Total balance in BTC"),
2363
- sats: z10.number().describe("Total balance in satoshis")
2364
- })
2365
- })
2366
- });
2367
-
2368
- // src/tools/bitcoin/balance/tool.ts
2369
- var SATS_PER_BTC = 1e8;
2370
- function satsToBtc(sats) {
2371
- return (sats / SATS_PER_BTC).toFixed(8);
2372
- }
2373
- function fetchJson(url) {
2374
- return new Promise((resolve, reject) => {
2375
- https.get(url, { headers: { "User-Agent": "moonpay-cli" } }, (res) => {
2376
- if (res.statusCode !== 200) {
2377
- reject(new Error(`HTTP ${res.statusCode} from ${url}`));
2378
- res.resume();
2379
- return;
2380
- }
2381
- let data = "";
2382
- res.on("data", (chunk) => data += chunk);
2383
- res.on("end", () => {
2384
- try {
2385
- resolve(JSON.parse(data));
2386
- } catch {
2387
- reject(new Error("Invalid JSON response"));
2388
- }
2389
- });
2390
- }).on("error", reject);
2391
- });
2392
- }
2393
- var bitcoinBalanceRetrieve = createTool(
2394
- bitcoinBalanceRetrieveSchema,
2395
- async (params) => {
2396
- let address = params.wallet;
2397
- if (!address.startsWith("bc1") && !address.startsWith("1") && !address.startsWith("3")) {
2398
- const { loadWallet: loadWallet2 } = await import("./server-IUOCZFT7.js");
2399
- const wallet = loadWallet2(address);
2400
- const btcAddress = wallet.addresses.bitcoin;
2401
- if (!btcAddress) {
2402
- throw new Error(
2403
- `Wallet "${address}" has no Bitcoin address. It may be an imported single-chain wallet.`
2404
- );
2405
- }
2406
- address = btcAddress;
2407
- }
2408
- const data = await fetchJson(
2409
- `https://mempool.space/api/address/${address}`
2410
- );
2411
- const confirmedSats = data.chain_stats.funded_txo_sum - data.chain_stats.spent_txo_sum;
2412
- const unconfirmedSats = data.mempool_stats.funded_txo_sum - data.mempool_stats.spent_txo_sum;
2413
- const totalSats = confirmedSats + unconfirmedSats;
2414
- return {
2415
- address,
2416
- confirmed: { btc: satsToBtc(confirmedSats), sats: confirmedSats },
2417
- unconfirmed: { btc: satsToBtc(unconfirmedSats), sats: unconfirmedSats },
2418
- total: { btc: satsToBtc(totalSats), sats: totalSats }
2419
- };
2420
- }
2421
- );
2422
-
2423
- export {
2424
- getConfigOrDefault,
2425
- clearCredentials,
2426
- resolveBaseUrl,
2427
- login,
2428
- callTool,
2429
- schemas_default,
2430
- defineToolSchema,
2431
- createTool,
2432
- resolveSigningKey,
2433
- walletCreate,
2434
- walletImport,
2435
- walletList,
2436
- walletRetrieve,
2437
- walletDelete,
2438
- transactionSign,
2439
- messageSign,
2440
- walletLock,
2441
- walletUnlock,
2442
- bitcoinBalanceRetrieve
2443
- };
2444
- //# sourceMappingURL=chunk-DAQDHLPY.js.map