@moonpay/cli 0.3.4 → 0.3.5

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.
@@ -0,0 +1,1992 @@
1
+ import { createRequire as __createRequire } from "module"; const require = __createRequire(import.meta.url);
2
+
3
+ // src/auth.ts
4
+ import { spawn } from "child_process";
5
+ import * as crypto from "crypto";
6
+ import * as fs from "fs";
7
+ import * as http from "http";
8
+ import * as os from "os";
9
+ import * as path from "path";
10
+ function escapeHtml(str) {
11
+ return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
12
+ }
13
+ function generateCodeVerifier() {
14
+ return crypto.randomBytes(32).toString("base64url");
15
+ }
16
+ function generateCodeChallenge(verifier) {
17
+ return crypto.createHash("sha256").update(verifier).digest("base64url");
18
+ }
19
+ var CONFIG_DIR = path.join(os.homedir(), ".config", "moonpay");
20
+ var CONFIG_PATH = path.join(CONFIG_DIR, "config.json");
21
+ var CREDENTIALS_PATH = path.join(CONFIG_DIR, "credentials.json");
22
+ var LOCK_PATH = path.join(CONFIG_DIR, ".credentials.lock");
23
+ var CALLBACK_PORT = 3847;
24
+ var CALLBACK_URL = `http://localhost:${CALLBACK_PORT}/callback`;
25
+ var DEFAULT_CONFIG = {
26
+ baseUrl: "https://agents.moonpay.com",
27
+ clientId: "mooniq_zin3s5jz3olzkdfxpmbeaogv"
28
+ };
29
+ function ensureConfigDir() {
30
+ if (!fs.existsSync(CONFIG_DIR)) {
31
+ fs.mkdirSync(CONFIG_DIR, { recursive: true, mode: 448 });
32
+ }
33
+ }
34
+ function atomicWriteFileSync(filePath, data, mode) {
35
+ const tmp = filePath + `.tmp.${process.pid}`;
36
+ fs.writeFileSync(tmp, data, { encoding: "utf-8", mode });
37
+ fs.renameSync(tmp, filePath);
38
+ }
39
+ var LOCK_STALE_MS = 3e4;
40
+ function acquireLock() {
41
+ ensureConfigDir();
42
+ try {
43
+ const fd = fs.openSync(LOCK_PATH, fs.constants.O_CREAT | fs.constants.O_EXCL | fs.constants.O_WRONLY, 384);
44
+ fs.writeSync(fd, JSON.stringify({ pid: process.pid, ts: Date.now() }));
45
+ fs.closeSync(fd);
46
+ } catch (err) {
47
+ if (err.code !== "EEXIST") throw err;
48
+ try {
49
+ const lockData = JSON.parse(fs.readFileSync(LOCK_PATH, "utf-8"));
50
+ if (Date.now() - lockData.ts < LOCK_STALE_MS) {
51
+ return null;
52
+ }
53
+ } catch {
54
+ }
55
+ try {
56
+ fs.unlinkSync(LOCK_PATH);
57
+ } catch {
58
+ }
59
+ try {
60
+ const fd = fs.openSync(LOCK_PATH, fs.constants.O_CREAT | fs.constants.O_EXCL | fs.constants.O_WRONLY, 384);
61
+ fs.writeSync(fd, JSON.stringify({ pid: process.pid, ts: Date.now() }));
62
+ fs.closeSync(fd);
63
+ } catch {
64
+ return null;
65
+ }
66
+ }
67
+ return () => {
68
+ try {
69
+ fs.unlinkSync(LOCK_PATH);
70
+ } catch {
71
+ }
72
+ };
73
+ }
74
+ function getConfig() {
75
+ if (!fs.existsSync(CONFIG_PATH)) {
76
+ return null;
77
+ }
78
+ try {
79
+ const data = JSON.parse(fs.readFileSync(CONFIG_PATH, "utf-8"));
80
+ if (!data.baseUrl || !data.clientId) {
81
+ return null;
82
+ }
83
+ return data;
84
+ } catch {
85
+ return null;
86
+ }
87
+ }
88
+ function getConfigOrDefault() {
89
+ const fromFile = getConfig();
90
+ if (fromFile) return fromFile;
91
+ saveConfig(DEFAULT_CONFIG);
92
+ return DEFAULT_CONFIG;
93
+ }
94
+ function getCredentials() {
95
+ if (!fs.existsSync(CREDENTIALS_PATH)) {
96
+ return null;
97
+ }
98
+ try {
99
+ const data = JSON.parse(fs.readFileSync(CREDENTIALS_PATH, "utf-8"));
100
+ if (!data.accessToken || !data.baseUrl) {
101
+ return null;
102
+ }
103
+ return data;
104
+ } catch {
105
+ return null;
106
+ }
107
+ }
108
+ function saveCredentials(creds) {
109
+ ensureConfigDir();
110
+ atomicWriteFileSync(CREDENTIALS_PATH, JSON.stringify(creds, null, 2), 384);
111
+ }
112
+ function saveConfig(config) {
113
+ ensureConfigDir();
114
+ atomicWriteFileSync(CONFIG_PATH, JSON.stringify(config, null, 2), 384);
115
+ }
116
+ function clearCredentials() {
117
+ if (fs.existsSync(CREDENTIALS_PATH)) {
118
+ fs.unlinkSync(CREDENTIALS_PATH);
119
+ }
120
+ }
121
+ function resolveBaseUrl() {
122
+ const config = getConfig();
123
+ const creds = getCredentials();
124
+ return config?.baseUrl ?? creds?.baseUrl ?? DEFAULT_CONFIG.baseUrl;
125
+ }
126
+ function openBrowser(url) {
127
+ const platform = process.platform;
128
+ const cmd = platform === "darwin" ? "open" : platform === "win32" ? "cmd" : "xdg-open";
129
+ const args = platform === "win32" ? ["/c", "start", "", url] : [url];
130
+ spawn(cmd, args, { stdio: "ignore", detached: true }).unref();
131
+ }
132
+ async function login(config) {
133
+ const state = crypto.randomUUID();
134
+ const usePkce = !config.clientSecret;
135
+ let codeVerifier;
136
+ if (usePkce) {
137
+ codeVerifier = generateCodeVerifier();
138
+ }
139
+ let resolveCallback;
140
+ const codePromise = new Promise((resolve2) => {
141
+ resolveCallback = resolve2;
142
+ });
143
+ const sockets = /* @__PURE__ */ new Set();
144
+ const server = http.createServer((req, res) => {
145
+ const url = new URL(req.url ?? "/", `http://localhost:${CALLBACK_PORT}`);
146
+ if (url.pathname === "/callback") {
147
+ const code2 = url.searchParams.get("code");
148
+ const returnedState = url.searchParams.get("state");
149
+ const error = url.searchParams.get("error");
150
+ const errorDesc = url.searchParams.get("error_description");
151
+ if (returnedState !== state) {
152
+ res.writeHead(200, { "Content-Type": "text/html" });
153
+ res.end(
154
+ `<!DOCTYPE html><html><head><meta charset="utf-8"><title>OAuth Error</title></head><body style="font-family:system-ui,sans-serif;display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:100vh;margin:0;padding:2rem;text-align:center;background:#fef2f2"><h1 style="color:#b91c1c;margin:0 0 1rem">OAuth Error</h1><p style="color:#991b1b;margin:0">State mismatch \u2014 possible CSRF attack. Please try logging in again.</p></body></html>`
155
+ );
156
+ resolveCallback("");
157
+ setTimeout(() => server.close(), 2e3);
158
+ } else if (error) {
159
+ const safeError = escapeHtml(error);
160
+ const safeDesc = escapeHtml(errorDesc ?? "Unknown error");
161
+ res.writeHead(200, { "Content-Type": "text/html" });
162
+ res.end(
163
+ `<!DOCTYPE html><html><head><meta charset="utf-8"><title>OAuth Error</title></head><body style="font-family:system-ui,sans-serif;display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:100vh;margin:0;padding:2rem;text-align:center;background:#fef2f2"><h1 style="color:#b91c1c;margin:0 0 1rem">OAuth Error</h1><p style="color:#991b1b;margin:0">${safeError}: ${safeDesc}</p></body></html>`
164
+ );
165
+ resolveCallback("");
166
+ setTimeout(() => server.close(), 2e3);
167
+ } else if (code2) {
168
+ res.writeHead(200, { "Content-Type": "text/html" });
169
+ res.end(
170
+ `<!DOCTYPE html><html><head><meta charset="utf-8"><title>MoonPay Agents</title></head><body style="font-family:system-ui,-apple-system,sans-serif;display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:100vh;margin:0;padding:2rem;text-align:center;background:#0a0a0a;color:#fafafa"><img src="https://agents.moonpay.com/logos/moonpay.jpg" alt="MoonPay" style="width:64px;height:64px;border-radius:16px;margin-bottom:1.5rem" /><h1 style="margin:0 0 0.5rem;font-size:1.5rem;font-weight:600">Your agent has money now.</h1><p style="color:#a1a1aa;margin:0;font-size:1rem">You can close this tab and return to the terminal.</p></body></html>`
171
+ );
172
+ resolveCallback(code2);
173
+ } else {
174
+ res.writeHead(200, { "Content-Type": "text/html" });
175
+ res.end(
176
+ `<!DOCTYPE html><html><head><meta charset="utf-8"><title>Error</title></head><body style="font-family:system-ui,sans-serif;display:flex;flex-direction:column;align-items:center;justify-content:center;min-height:100vh;margin:0;padding:2rem;text-align:center;background:#fef2f2"><h1 style="color:#b91c1c;margin:0 0 1rem">Error</h1><p style="color:#991b1b;margin:0">No authorization code received.</p></body></html>`
177
+ );
178
+ resolveCallback("");
179
+ setTimeout(() => server.close(), 2e3);
180
+ }
181
+ } else {
182
+ res.writeHead(204);
183
+ res.end();
184
+ }
185
+ });
186
+ await new Promise((resolve2, reject) => {
187
+ server.on("error", (err) => {
188
+ if (err.code === "EADDRINUSE") {
189
+ reject(
190
+ new Error(
191
+ `Port ${CALLBACK_PORT} is in use. Close the other process or run: lsof -i :${CALLBACK_PORT}`
192
+ )
193
+ );
194
+ } else {
195
+ reject(err);
196
+ }
197
+ });
198
+ server.on("connection", (socket) => {
199
+ sockets.add(socket);
200
+ socket.on("close", () => sockets.delete(socket));
201
+ });
202
+ server.listen(CALLBACK_PORT, "127.0.0.1", () => resolve2());
203
+ });
204
+ console.log(
205
+ `Waiting for callback at http://localhost:${CALLBACK_PORT}/callback`
206
+ );
207
+ const authorizeParams = new URLSearchParams({
208
+ client_id: config.clientId,
209
+ redirect_uri: CALLBACK_URL,
210
+ response_type: "code",
211
+ scope: "profile email",
212
+ state
213
+ });
214
+ if (usePkce && codeVerifier) {
215
+ authorizeParams.set("code_challenge", generateCodeChallenge(codeVerifier));
216
+ authorizeParams.set("code_challenge_method", "S256");
217
+ }
218
+ const authorizeUrl = `${config.baseUrl}/authorize?${authorizeParams.toString()}`;
219
+ console.log("Opening browser for authorization...");
220
+ console.log("(Make sure you're logged in to MoonPay in your browser)\n");
221
+ openBrowser(authorizeUrl);
222
+ const code = await codePromise;
223
+ if (!code) {
224
+ throw new Error("No authorization code received");
225
+ }
226
+ const tokenParams = {
227
+ grant_type: "authorization_code",
228
+ code,
229
+ client_id: config.clientId,
230
+ redirect_uri: CALLBACK_URL
231
+ };
232
+ if (config.clientSecret) {
233
+ tokenParams.client_secret = config.clientSecret;
234
+ }
235
+ if (usePkce && codeVerifier) {
236
+ tokenParams.code_verifier = codeVerifier;
237
+ }
238
+ const tokenResponse = await fetch(`${config.baseUrl}/api/oauth/token`, {
239
+ method: "POST",
240
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
241
+ body: new URLSearchParams(tokenParams)
242
+ });
243
+ if (!tokenResponse.ok) {
244
+ const err = await tokenResponse.json().catch(() => ({}));
245
+ const msg = err.error_description ?? err.error ?? tokenResponse.statusText;
246
+ throw new Error(`Token exchange failed: ${msg}`);
247
+ }
248
+ const tokens = await tokenResponse.json();
249
+ const expiresAt = Date.now() + (tokens.expires_in ?? 3600) * 1e3;
250
+ const creds = {
251
+ accessToken: tokens.access_token,
252
+ refreshToken: tokens.refresh_token ?? null,
253
+ expiresAt,
254
+ baseUrl: config.baseUrl
255
+ };
256
+ saveCredentials(creds);
257
+ await new Promise((resolve2) => setTimeout(resolve2, 1e3));
258
+ server.close();
259
+ for (const socket of sockets) {
260
+ if ("destroy" in socket && typeof socket.destroy === "function") {
261
+ socket.destroy();
262
+ }
263
+ }
264
+ sockets.clear();
265
+ return creds;
266
+ }
267
+ async function refreshCredentials(creds, config) {
268
+ if (!creds.refreshToken) {
269
+ throw new Error("No refresh token available");
270
+ }
271
+ const unlock = acquireLock();
272
+ if (!unlock) {
273
+ await new Promise((r) => setTimeout(r, 2e3));
274
+ const fresh = getCredentials();
275
+ if (fresh && fresh.expiresAt > Date.now()) {
276
+ return fresh;
277
+ }
278
+ throw new Error("Token refresh failed (concurrent refresh in progress)");
279
+ }
280
+ try {
281
+ const latest = getCredentials();
282
+ if (latest && latest.expiresAt > Date.now() + 6e4) {
283
+ return latest;
284
+ }
285
+ const refreshParams = {
286
+ grant_type: "refresh_token",
287
+ refresh_token: creds.refreshToken,
288
+ client_id: config.clientId
289
+ };
290
+ if (config.clientSecret) {
291
+ refreshParams.client_secret = config.clientSecret;
292
+ }
293
+ const tokenResponse = await fetch(`${config.baseUrl}/api/oauth/token`, {
294
+ method: "POST",
295
+ headers: { "Content-Type": "application/x-www-form-urlencoded" },
296
+ body: new URLSearchParams(refreshParams)
297
+ });
298
+ if (!tokenResponse.ok) {
299
+ throw new Error("Token refresh failed");
300
+ }
301
+ const tokens = await tokenResponse.json();
302
+ const expiresAt = Date.now() + (tokens.expires_in ?? 3600) * 1e3;
303
+ const newCreds = {
304
+ accessToken: tokens.access_token,
305
+ refreshToken: tokens.refresh_token ?? creds.refreshToken,
306
+ expiresAt,
307
+ baseUrl: config.baseUrl
308
+ };
309
+ saveCredentials(newCreds);
310
+ return newCreds;
311
+ } finally {
312
+ unlock();
313
+ }
314
+ }
315
+ var TOKEN_EXPIRY_BUFFER_MS = 5 * 60 * 1e3;
316
+ async function getValidToken() {
317
+ const creds = getCredentials();
318
+ if (!creds) return null;
319
+ const config = getConfig();
320
+ if (!config || config.baseUrl !== creds.baseUrl) return null;
321
+ if (Date.now() >= creds.expiresAt - TOKEN_EXPIRY_BUFFER_MS) {
322
+ if (creds.refreshToken) {
323
+ try {
324
+ const newCreds = await refreshCredentials(creds, config);
325
+ return newCreds.accessToken;
326
+ } catch {
327
+ return null;
328
+ }
329
+ }
330
+ return null;
331
+ }
332
+ return creds.accessToken;
333
+ }
334
+
335
+ // src/client.ts
336
+ async function callTool(baseUrl, toolName, params) {
337
+ const token = await getValidToken();
338
+ const headers = {
339
+ "Content-Type": "application/json"
340
+ };
341
+ if (token) {
342
+ headers["Authorization"] = `Bearer ${token}`;
343
+ }
344
+ let res = await fetch(`${baseUrl}/api/tools/${toolName}`, {
345
+ method: "POST",
346
+ headers,
347
+ body: JSON.stringify(params)
348
+ });
349
+ if (res.status === 401 && token) {
350
+ const creds = getCredentials();
351
+ const config = getConfig();
352
+ if (creds?.refreshToken && config && config.baseUrl === creds.baseUrl) {
353
+ try {
354
+ const newCreds = await refreshCredentials(creds, config);
355
+ res = await fetch(`${baseUrl}/api/tools/${toolName}`, {
356
+ method: "POST",
357
+ headers: {
358
+ "Content-Type": "application/json",
359
+ Authorization: `Bearer ${newCreds.accessToken}`
360
+ },
361
+ body: JSON.stringify(params)
362
+ });
363
+ } catch {
364
+ }
365
+ }
366
+ }
367
+ const data = await res.json();
368
+ if (res.status === 401) {
369
+ throw new Error("This command requires a MoonPay Agents account. Run `moonpay login` first.");
370
+ }
371
+ if (res.status < 200 || res.status >= 300) {
372
+ const err = data;
373
+ throw new Error(err?.error ?? `Tool call failed (${res.status})`);
374
+ }
375
+ return data;
376
+ }
377
+
378
+ // src/generated/schemas.json
379
+ var schemas_default = [
380
+ {
381
+ name: "buy",
382
+ description: "Buy crypto with fiat via MoonPay. Returns a checkout URL to complete the purchase.",
383
+ inputSchema: {
384
+ $ref: "#/definitions/buy_input",
385
+ definitions: {
386
+ buy_input: {
387
+ type: "object",
388
+ properties: {
389
+ token: {
390
+ type: "string",
391
+ enum: [
392
+ "sol",
393
+ "usdc",
394
+ "usdc_arbitrum",
395
+ "usdc_base",
396
+ "usdc_optimism",
397
+ "usdc_sol",
398
+ "usdc_polygon",
399
+ "eth",
400
+ "eth_polygon",
401
+ "eth_optimism",
402
+ "eth_base",
403
+ "eth_arbitrum"
404
+ ],
405
+ description: "MoonPay currency code: sol (Solana), usdc_sol (USDC on Solana), eth (Ethereum), usdc (USDC on Ethereum), usdc_base (USDC on Base), etc."
406
+ },
407
+ amount: {
408
+ type: "number",
409
+ description: "Amount of token to buy (e.g. 1.5 for 1.5 SOL)"
410
+ },
411
+ wallet: {
412
+ type: "string",
413
+ description: "Destination wallet address to receive the tokens"
414
+ },
415
+ email: {
416
+ type: [
417
+ "string",
418
+ "null"
419
+ ],
420
+ description: "Buyer email to pre-fill on the checkout page"
421
+ }
422
+ },
423
+ required: [
424
+ "token",
425
+ "amount",
426
+ "wallet",
427
+ "email"
428
+ ],
429
+ additionalProperties: false
430
+ }
431
+ },
432
+ $schema: "http://json-schema.org/draft-07/schema#"
433
+ }
434
+ },
435
+ {
436
+ name: "token_balance_list",
437
+ description: "List all token balances held in a wallet, including amount owned, current value in USD, and token details. Shows the complete token portfolio.",
438
+ inputSchema: {
439
+ $ref: "#/definitions/token_balance_list_input",
440
+ definitions: {
441
+ token_balance_list_input: {
442
+ type: "object",
443
+ properties: {
444
+ wallet: {
445
+ type: "string",
446
+ description: "Wallet address to check token balances for"
447
+ },
448
+ chain: {
449
+ type: "string",
450
+ enum: [
451
+ "solana",
452
+ "ethereum",
453
+ "base",
454
+ "polygon",
455
+ "arbitrum",
456
+ "optimism"
457
+ ],
458
+ description: "Blockchain to check balances on (e.g. 'solana', 'ethereum', 'base')"
459
+ }
460
+ },
461
+ required: [
462
+ "wallet",
463
+ "chain"
464
+ ],
465
+ additionalProperties: false
466
+ }
467
+ },
468
+ $schema: "http://json-schema.org/draft-07/schema#"
469
+ }
470
+ },
471
+ {
472
+ name: "token_retrieve",
473
+ description: "Get detailed token information including market data, price changes, volume, trades, and holder statistics by token address",
474
+ inputSchema: {
475
+ $ref: "#/definitions/token_retrieve_input",
476
+ definitions: {
477
+ token_retrieve_input: {
478
+ type: "object",
479
+ properties: {
480
+ token: {
481
+ type: "string",
482
+ description: "Address of the token to retrieve"
483
+ },
484
+ chain: {
485
+ type: "string",
486
+ enum: [
487
+ "solana",
488
+ "ethereum",
489
+ "base",
490
+ "polygon",
491
+ "arbitrum",
492
+ "optimism"
493
+ ],
494
+ description: "Blockchain network where the token exists"
495
+ }
496
+ },
497
+ required: [
498
+ "token",
499
+ "chain"
500
+ ],
501
+ additionalProperties: false
502
+ }
503
+ },
504
+ $schema: "http://json-schema.org/draft-07/schema#"
505
+ }
506
+ },
507
+ {
508
+ name: "token_search",
509
+ description: "Search for tokens by name, symbol, or address. Returns matching tokens with their market data including price, volume, and liquidity.",
510
+ inputSchema: {
511
+ $ref: "#/definitions/token_search_input",
512
+ definitions: {
513
+ token_search_input: {
514
+ type: "object",
515
+ properties: {
516
+ query: {
517
+ type: "string",
518
+ description: "Search term - can be token name (e.g. 'Bitcoin'), symbol (e.g. 'BTC'), or partial match"
519
+ },
520
+ chain: {
521
+ type: "string",
522
+ enum: [
523
+ "solana",
524
+ "ethereum",
525
+ "base",
526
+ "polygon",
527
+ "arbitrum",
528
+ "optimism"
529
+ ],
530
+ description: "Blockchain to search on (e.g. 'solana', 'ethereum', 'base')"
531
+ },
532
+ limit: {
533
+ type: [
534
+ "number",
535
+ "null"
536
+ ],
537
+ description: "Maximum number of results to return (optional, defaults to 5)"
538
+ }
539
+ },
540
+ required: [
541
+ "query",
542
+ "chain",
543
+ "limit"
544
+ ],
545
+ additionalProperties: false
546
+ }
547
+ },
548
+ $schema: "http://json-schema.org/draft-07/schema#"
549
+ }
550
+ },
551
+ {
552
+ name: "token_swap_build",
553
+ description: "Build an unsigned swap transaction. Returns a base64-encoded transaction ready for signing.",
554
+ inputSchema: {
555
+ $ref: "#/definitions/token_swap_build_input",
556
+ definitions: {
557
+ token_swap_build_input: {
558
+ type: "object",
559
+ properties: {
560
+ input: {
561
+ type: "string",
562
+ description: "Mint address of the input token"
563
+ },
564
+ output: {
565
+ type: "string",
566
+ description: "Mint address of the output token"
567
+ },
568
+ amount: {
569
+ type: "number",
570
+ description: "Amount of the input token to swap"
571
+ },
572
+ wallet: {
573
+ type: "string",
574
+ description: "Wallet address that will execute the swap"
575
+ }
576
+ },
577
+ required: [
578
+ "input",
579
+ "output",
580
+ "amount",
581
+ "wallet"
582
+ ],
583
+ additionalProperties: false
584
+ }
585
+ },
586
+ $schema: "http://json-schema.org/draft-07/schema#"
587
+ }
588
+ },
589
+ {
590
+ name: "token_swap_execute",
591
+ description: "Execute a signed swap transaction. Pass the signed transaction and requestId from token_swap_build.",
592
+ inputSchema: {
593
+ $ref: "#/definitions/token_swap_execute_input",
594
+ definitions: {
595
+ token_swap_execute_input: {
596
+ type: "object",
597
+ properties: {
598
+ transaction: {
599
+ type: "string",
600
+ description: "Base64-encoded signed transaction"
601
+ },
602
+ requestId: {
603
+ type: "string",
604
+ description: "Request ID from token_swap_build"
605
+ }
606
+ },
607
+ required: [
608
+ "transaction",
609
+ "requestId"
610
+ ],
611
+ additionalProperties: false
612
+ }
613
+ },
614
+ $schema: "http://json-schema.org/draft-07/schema#"
615
+ }
616
+ },
617
+ {
618
+ name: "token_trending_list",
619
+ description: "Get currently trending tokens on a blockchain. Perfect for discovering what's hot right now.",
620
+ inputSchema: {
621
+ $ref: "#/definitions/token_trending_list_input",
622
+ definitions: {
623
+ token_trending_list_input: {
624
+ type: "object",
625
+ properties: {
626
+ chain: {
627
+ type: "string",
628
+ enum: [
629
+ "solana",
630
+ "ethereum",
631
+ "base",
632
+ "polygon",
633
+ "arbitrum",
634
+ "optimism"
635
+ ],
636
+ description: "Blockchain to get trending tokens from (e.g. 'solana', 'ethereum', 'base')"
637
+ },
638
+ limit: {
639
+ type: "number",
640
+ description: "Number of results per page"
641
+ },
642
+ page: {
643
+ type: "number",
644
+ description: "The page number of results"
645
+ }
646
+ },
647
+ required: [
648
+ "chain",
649
+ "limit",
650
+ "page"
651
+ ],
652
+ additionalProperties: false
653
+ }
654
+ },
655
+ $schema: "http://json-schema.org/draft-07/schema#"
656
+ }
657
+ },
658
+ {
659
+ name: "transaction_send",
660
+ description: "Broadcast a signed transaction to Solana. Simulates first, then sends and confirms.",
661
+ inputSchema: {
662
+ $ref: "#/definitions/transaction_send_input",
663
+ definitions: {
664
+ transaction_send_input: {
665
+ type: "object",
666
+ properties: {
667
+ transaction: {
668
+ type: "string",
669
+ description: "Base64-encoded signed transaction"
670
+ },
671
+ message: {
672
+ type: "string",
673
+ description: "Human-readable message describing the transaction"
674
+ }
675
+ },
676
+ required: [
677
+ "transaction",
678
+ "message"
679
+ ],
680
+ additionalProperties: false
681
+ }
682
+ },
683
+ $schema: "http://json-schema.org/draft-07/schema#"
684
+ }
685
+ },
686
+ {
687
+ name: "user_retrieve",
688
+ description: "Get the currently authenticated user",
689
+ inputSchema: {
690
+ $ref: "#/definitions/user_retrieve_input",
691
+ definitions: {
692
+ user_retrieve_input: {
693
+ type: "object",
694
+ properties: {},
695
+ additionalProperties: false
696
+ }
697
+ },
698
+ $schema: "http://json-schema.org/draft-07/schema#"
699
+ }
700
+ },
701
+ {
702
+ name: "virtual-account_bank-account_delete",
703
+ description: "Delete a bank account",
704
+ inputSchema: {
705
+ $ref: "#/definitions/virtual-account_bank-account_delete_input",
706
+ definitions: {
707
+ "virtual-account_bank-account_delete_input": {
708
+ type: "object",
709
+ properties: {
710
+ bankAccountId: {
711
+ type: "string",
712
+ format: "uuid",
713
+ description: "The ID of the bank account to delete"
714
+ }
715
+ },
716
+ required: [
717
+ "bankAccountId"
718
+ ],
719
+ additionalProperties: false
720
+ }
721
+ },
722
+ $schema: "http://json-schema.org/draft-07/schema#"
723
+ }
724
+ },
725
+ {
726
+ name: "virtual-account_bank-account_eur_register",
727
+ description: "Register a EUR bank account for offramp payouts",
728
+ inputSchema: {
729
+ $ref: "#/definitions/virtual-account_bank-account_eur_register_input",
730
+ definitions: {
731
+ "virtual-account_bank-account_eur_register_input": {
732
+ type: "object",
733
+ properties: {
734
+ iban: {
735
+ type: "string",
736
+ description: "IBAN for SEPA bank account"
737
+ },
738
+ address: {
739
+ type: "object",
740
+ properties: {
741
+ street: {
742
+ type: "string",
743
+ description: "Street address"
744
+ },
745
+ city: {
746
+ type: "string",
747
+ description: "City"
748
+ },
749
+ state: {
750
+ type: "string",
751
+ description: "State or province"
752
+ },
753
+ country: {
754
+ type: "string",
755
+ enum: [
756
+ "US",
757
+ "GB",
758
+ "CA",
759
+ "AU",
760
+ "DE",
761
+ "FR",
762
+ "IT",
763
+ "ES",
764
+ "NL",
765
+ "BE",
766
+ "AT",
767
+ "CH",
768
+ "SE",
769
+ "NO",
770
+ "DK",
771
+ "FI",
772
+ "IE",
773
+ "PT",
774
+ "PL",
775
+ "CZ",
776
+ "GR",
777
+ "JP",
778
+ "KR",
779
+ "CN",
780
+ "IN",
781
+ "BR",
782
+ "MX",
783
+ "AR",
784
+ "ZA",
785
+ "NZ",
786
+ "SG",
787
+ "HK",
788
+ "AE"
789
+ ],
790
+ description: "ISO 3166-1 Alpha-2 country code"
791
+ },
792
+ postalCode: {
793
+ type: "string",
794
+ description: "Postal or ZIP code"
795
+ }
796
+ },
797
+ required: [
798
+ "street",
799
+ "city",
800
+ "state",
801
+ "country",
802
+ "postalCode"
803
+ ],
804
+ additionalProperties: false,
805
+ description: "Address of the user that owns the bank account"
806
+ },
807
+ email: {
808
+ type: "string",
809
+ description: "Email address of the user that owns the bank account"
810
+ },
811
+ phoneNumber: {
812
+ type: "string",
813
+ description: "Phone number of the user"
814
+ },
815
+ providerCountry: {
816
+ type: "string",
817
+ enum: [
818
+ "US",
819
+ "GB",
820
+ "CA",
821
+ "AU",
822
+ "DE",
823
+ "FR",
824
+ "IT",
825
+ "ES",
826
+ "NL",
827
+ "BE",
828
+ "AT",
829
+ "CH",
830
+ "SE",
831
+ "NO",
832
+ "DK",
833
+ "FI",
834
+ "IE",
835
+ "PT",
836
+ "PL",
837
+ "CZ",
838
+ "GR",
839
+ "JP",
840
+ "KR",
841
+ "CN",
842
+ "IN",
843
+ "BR",
844
+ "MX",
845
+ "AR",
846
+ "ZA",
847
+ "NZ",
848
+ "SG",
849
+ "HK",
850
+ "AE"
851
+ ],
852
+ description: "ISO 3166-1 Alpha-2 country code where the bank is located"
853
+ },
854
+ providerName: {
855
+ type: "string",
856
+ description: "Name of the bank"
857
+ },
858
+ givenName: {
859
+ type: "string",
860
+ description: "First/given name of the account holder"
861
+ },
862
+ familyName: {
863
+ type: "string",
864
+ description: "Last/family name of the account holder"
865
+ }
866
+ },
867
+ required: [
868
+ "iban",
869
+ "address",
870
+ "email",
871
+ "phoneNumber",
872
+ "providerCountry",
873
+ "providerName",
874
+ "givenName",
875
+ "familyName"
876
+ ],
877
+ additionalProperties: false
878
+ }
879
+ },
880
+ $schema: "http://json-schema.org/draft-07/schema#"
881
+ }
882
+ },
883
+ {
884
+ name: "virtual-account_bank-account_list",
885
+ description: "List registered bank accounts",
886
+ inputSchema: {
887
+ $ref: "#/definitions/virtual-account_bank-account_list_input",
888
+ definitions: {
889
+ "virtual-account_bank-account_list_input": {
890
+ type: "object",
891
+ properties: {},
892
+ additionalProperties: false
893
+ }
894
+ },
895
+ $schema: "http://json-schema.org/draft-07/schema#"
896
+ }
897
+ },
898
+ {
899
+ name: "virtual-account_bank-account_retrieve",
900
+ description: "Get a bank account by currency",
901
+ inputSchema: {
902
+ $ref: "#/definitions/virtual-account_bank-account_retrieve_input",
903
+ definitions: {
904
+ "virtual-account_bank-account_retrieve_input": {
905
+ type: "object",
906
+ properties: {
907
+ currency: {
908
+ type: "string",
909
+ enum: [
910
+ "USD",
911
+ "EUR"
912
+ ],
913
+ description: "The fiat currency code (USD or EUR)"
914
+ }
915
+ },
916
+ required: [
917
+ "currency"
918
+ ],
919
+ additionalProperties: false
920
+ }
921
+ },
922
+ $schema: "http://json-schema.org/draft-07/schema#"
923
+ }
924
+ },
925
+ {
926
+ name: "virtual-account_bank-account_usd_register",
927
+ description: "Register a USD bank account for offramp payouts",
928
+ inputSchema: {
929
+ $ref: "#/definitions/virtual-account_bank-account_usd_register_input",
930
+ definitions: {
931
+ "virtual-account_bank-account_usd_register_input": {
932
+ type: "object",
933
+ properties: {
934
+ type: {
935
+ type: "string",
936
+ enum: [
937
+ "ACH",
938
+ "Wire"
939
+ ],
940
+ description: "Type of bank account (ACH or Wire)"
941
+ },
942
+ accountNumber: {
943
+ type: "string",
944
+ description: "Account number"
945
+ },
946
+ routingNumber: {
947
+ type: "string",
948
+ description: "Routing number"
949
+ },
950
+ address: {
951
+ type: "object",
952
+ properties: {
953
+ street: {
954
+ type: "string",
955
+ description: "Street address"
956
+ },
957
+ city: {
958
+ type: "string",
959
+ description: "City"
960
+ },
961
+ state: {
962
+ type: "string",
963
+ description: "State or province"
964
+ },
965
+ country: {
966
+ type: "string",
967
+ enum: [
968
+ "US",
969
+ "GB",
970
+ "CA",
971
+ "AU",
972
+ "DE",
973
+ "FR",
974
+ "IT",
975
+ "ES",
976
+ "NL",
977
+ "BE",
978
+ "AT",
979
+ "CH",
980
+ "SE",
981
+ "NO",
982
+ "DK",
983
+ "FI",
984
+ "IE",
985
+ "PT",
986
+ "PL",
987
+ "CZ",
988
+ "GR",
989
+ "JP",
990
+ "KR",
991
+ "CN",
992
+ "IN",
993
+ "BR",
994
+ "MX",
995
+ "AR",
996
+ "ZA",
997
+ "NZ",
998
+ "SG",
999
+ "HK",
1000
+ "AE"
1001
+ ],
1002
+ description: "ISO 3166-1 Alpha-2 country code"
1003
+ },
1004
+ postalCode: {
1005
+ type: "string",
1006
+ description: "Postal or ZIP code"
1007
+ }
1008
+ },
1009
+ required: [
1010
+ "street",
1011
+ "city",
1012
+ "state",
1013
+ "country",
1014
+ "postalCode"
1015
+ ],
1016
+ additionalProperties: false,
1017
+ description: "Address of the user that owns the bank account"
1018
+ },
1019
+ email: {
1020
+ type: "string",
1021
+ description: "Email address of the user that owns the bank account"
1022
+ },
1023
+ phoneNumber: {
1024
+ type: "string",
1025
+ description: "Phone number of the user"
1026
+ },
1027
+ providerCountry: {
1028
+ type: "string",
1029
+ enum: [
1030
+ "US",
1031
+ "GB",
1032
+ "CA",
1033
+ "AU",
1034
+ "DE",
1035
+ "FR",
1036
+ "IT",
1037
+ "ES",
1038
+ "NL",
1039
+ "BE",
1040
+ "AT",
1041
+ "CH",
1042
+ "SE",
1043
+ "NO",
1044
+ "DK",
1045
+ "FI",
1046
+ "IE",
1047
+ "PT",
1048
+ "PL",
1049
+ "CZ",
1050
+ "GR",
1051
+ "JP",
1052
+ "KR",
1053
+ "CN",
1054
+ "IN",
1055
+ "BR",
1056
+ "MX",
1057
+ "AR",
1058
+ "ZA",
1059
+ "NZ",
1060
+ "SG",
1061
+ "HK",
1062
+ "AE"
1063
+ ],
1064
+ description: "ISO 3166-1 Alpha-2 country code where the bank is located"
1065
+ },
1066
+ providerName: {
1067
+ type: "string",
1068
+ description: "Name of the bank"
1069
+ },
1070
+ givenName: {
1071
+ type: "string",
1072
+ description: "First/given name of the account holder"
1073
+ },
1074
+ familyName: {
1075
+ type: "string",
1076
+ description: "Last/family name of the account holder"
1077
+ }
1078
+ },
1079
+ required: [
1080
+ "type",
1081
+ "accountNumber",
1082
+ "routingNumber",
1083
+ "address",
1084
+ "email",
1085
+ "phoneNumber",
1086
+ "providerCountry",
1087
+ "providerName",
1088
+ "givenName",
1089
+ "familyName"
1090
+ ],
1091
+ additionalProperties: false
1092
+ }
1093
+ },
1094
+ $schema: "http://json-schema.org/draft-07/schema#"
1095
+ }
1096
+ },
1097
+ {
1098
+ name: "virtual-account_create",
1099
+ description: "Create a virtual account and start KYC verification",
1100
+ inputSchema: {
1101
+ $ref: "#/definitions/virtual-account_create_input",
1102
+ definitions: {
1103
+ "virtual-account_create_input": {
1104
+ type: "object",
1105
+ properties: {},
1106
+ additionalProperties: false
1107
+ }
1108
+ },
1109
+ $schema: "http://json-schema.org/draft-07/schema#"
1110
+ }
1111
+ },
1112
+ {
1113
+ name: "virtual-account_delete",
1114
+ description: "Delete your virtual account",
1115
+ inputSchema: {
1116
+ $ref: "#/definitions/virtual-account_delete_input",
1117
+ definitions: {
1118
+ "virtual-account_delete_input": {
1119
+ type: "object",
1120
+ properties: {},
1121
+ additionalProperties: false
1122
+ }
1123
+ },
1124
+ $schema: "http://json-schema.org/draft-07/schema#"
1125
+ }
1126
+ },
1127
+ {
1128
+ name: "virtual-account_identification_create",
1129
+ description: "Create a KYC verification link to complete identity verification",
1130
+ inputSchema: {
1131
+ $ref: "#/definitions/virtual-account_identification_create_input",
1132
+ definitions: {
1133
+ "virtual-account_identification_create_input": {
1134
+ type: "object",
1135
+ properties: {},
1136
+ additionalProperties: false
1137
+ }
1138
+ },
1139
+ $schema: "http://json-schema.org/draft-07/schema#"
1140
+ }
1141
+ },
1142
+ {
1143
+ name: "virtual-account_identification_list",
1144
+ description: "List all KYC identifications",
1145
+ inputSchema: {
1146
+ $ref: "#/definitions/virtual-account_identification_list_input",
1147
+ definitions: {
1148
+ "virtual-account_identification_list_input": {
1149
+ type: "object",
1150
+ properties: {},
1151
+ additionalProperties: false
1152
+ }
1153
+ },
1154
+ $schema: "http://json-schema.org/draft-07/schema#"
1155
+ }
1156
+ },
1157
+ {
1158
+ name: "virtual-account_identification_retrieve",
1159
+ description: "Get the status of a KYC identification",
1160
+ inputSchema: {
1161
+ $ref: "#/definitions/virtual-account_identification_retrieve_input",
1162
+ definitions: {
1163
+ "virtual-account_identification_retrieve_input": {
1164
+ type: "object",
1165
+ properties: {},
1166
+ additionalProperties: false
1167
+ }
1168
+ },
1169
+ $schema: "http://json-schema.org/draft-07/schema#"
1170
+ }
1171
+ },
1172
+ {
1173
+ name: "virtual-account_offramp_create",
1174
+ description: "Create an offramp to convert stablecoin to fiat",
1175
+ inputSchema: {
1176
+ $ref: "#/definitions/virtual-account_offramp_create_input",
1177
+ definitions: {
1178
+ "virtual-account_offramp_create_input": {
1179
+ type: "object",
1180
+ properties: {
1181
+ name: {
1182
+ type: "string",
1183
+ description: "The name of the offramp"
1184
+ },
1185
+ fiat: {
1186
+ type: "string",
1187
+ enum: [
1188
+ "USD",
1189
+ "EUR"
1190
+ ],
1191
+ description: "The fiat currency to convert to"
1192
+ },
1193
+ stablecoin: {
1194
+ type: "string",
1195
+ enum: [
1196
+ "USDC",
1197
+ "USDT",
1198
+ "EURC"
1199
+ ],
1200
+ description: "The stablecoin token to convert from"
1201
+ }
1202
+ },
1203
+ required: [
1204
+ "name",
1205
+ "fiat",
1206
+ "stablecoin"
1207
+ ],
1208
+ additionalProperties: false
1209
+ }
1210
+ },
1211
+ $schema: "http://json-schema.org/draft-07/schema#"
1212
+ }
1213
+ },
1214
+ {
1215
+ name: "virtual-account_offramp_delete",
1216
+ description: "Cancel an offramp",
1217
+ inputSchema: {
1218
+ $ref: "#/definitions/virtual-account_offramp_delete_input",
1219
+ definitions: {
1220
+ "virtual-account_offramp_delete_input": {
1221
+ type: "object",
1222
+ properties: {
1223
+ offrampId: {
1224
+ type: "string",
1225
+ format: "uuid",
1226
+ description: "The ID of the offramp to cancel"
1227
+ }
1228
+ },
1229
+ required: [
1230
+ "offrampId"
1231
+ ],
1232
+ additionalProperties: false
1233
+ }
1234
+ },
1235
+ $schema: "http://json-schema.org/draft-07/schema#"
1236
+ }
1237
+ },
1238
+ {
1239
+ name: "virtual-account_offramp_initiate",
1240
+ description: "Build an unsigned transaction to send stablecoin to an offramp deposit address",
1241
+ inputSchema: {
1242
+ $ref: "#/definitions/virtual-account_offramp_initiate_input",
1243
+ definitions: {
1244
+ "virtual-account_offramp_initiate_input": {
1245
+ type: "object",
1246
+ properties: {
1247
+ wallet: {
1248
+ type: "string",
1249
+ description: "The wallet address to send from"
1250
+ },
1251
+ offrampId: {
1252
+ type: "string",
1253
+ description: "The ID of the offramp to initiate"
1254
+ },
1255
+ amount: {
1256
+ type: "number",
1257
+ minimum: 0,
1258
+ description: "The amount of stablecoin to send (in human-readable units, e.g., 100.5)"
1259
+ }
1260
+ },
1261
+ required: [
1262
+ "wallet",
1263
+ "offrampId",
1264
+ "amount"
1265
+ ],
1266
+ additionalProperties: false
1267
+ }
1268
+ },
1269
+ $schema: "http://json-schema.org/draft-07/schema#"
1270
+ }
1271
+ },
1272
+ {
1273
+ name: "virtual-account_offramp_list",
1274
+ description: "List all offramps",
1275
+ inputSchema: {
1276
+ $ref: "#/definitions/virtual-account_offramp_list_input",
1277
+ definitions: {
1278
+ "virtual-account_offramp_list_input": {
1279
+ type: "object",
1280
+ properties: {},
1281
+ additionalProperties: false
1282
+ }
1283
+ },
1284
+ $schema: "http://json-schema.org/draft-07/schema#"
1285
+ }
1286
+ },
1287
+ {
1288
+ name: "virtual-account_offramp_retrieve",
1289
+ description: "Get offramp details",
1290
+ inputSchema: {
1291
+ $ref: "#/definitions/virtual-account_offramp_retrieve_input",
1292
+ definitions: {
1293
+ "virtual-account_offramp_retrieve_input": {
1294
+ type: "object",
1295
+ properties: {
1296
+ offrampId: {
1297
+ type: "string",
1298
+ format: "uuid",
1299
+ description: "The ID of the offramp to retrieve"
1300
+ }
1301
+ },
1302
+ required: [
1303
+ "offrampId"
1304
+ ],
1305
+ additionalProperties: false
1306
+ }
1307
+ },
1308
+ $schema: "http://json-schema.org/draft-07/schema#"
1309
+ }
1310
+ },
1311
+ {
1312
+ name: "virtual-account_onramp_create",
1313
+ description: "Create an onramp to convert fiat to stablecoin",
1314
+ inputSchema: {
1315
+ $ref: "#/definitions/virtual-account_onramp_create_input",
1316
+ definitions: {
1317
+ "virtual-account_onramp_create_input": {
1318
+ type: "object",
1319
+ properties: {
1320
+ name: {
1321
+ type: "string",
1322
+ description: "The name of the onramp"
1323
+ },
1324
+ fiat: {
1325
+ type: "string",
1326
+ enum: [
1327
+ "USD",
1328
+ "EUR"
1329
+ ],
1330
+ description: "The fiat currency to convert from"
1331
+ },
1332
+ stablecoin: {
1333
+ type: "string",
1334
+ enum: [
1335
+ "USDC",
1336
+ "USDT",
1337
+ "EURC"
1338
+ ],
1339
+ description: "The stablecoin token to convert to"
1340
+ }
1341
+ },
1342
+ required: [
1343
+ "name",
1344
+ "fiat",
1345
+ "stablecoin"
1346
+ ],
1347
+ additionalProperties: false
1348
+ }
1349
+ },
1350
+ $schema: "http://json-schema.org/draft-07/schema#"
1351
+ }
1352
+ },
1353
+ {
1354
+ name: "virtual-account_onramp_delete",
1355
+ description: "Cancel an onramp",
1356
+ inputSchema: {
1357
+ $ref: "#/definitions/virtual-account_onramp_delete_input",
1358
+ definitions: {
1359
+ "virtual-account_onramp_delete_input": {
1360
+ type: "object",
1361
+ properties: {
1362
+ onrampId: {
1363
+ type: "string",
1364
+ format: "uuid",
1365
+ description: "The ID of the onramp to cancel"
1366
+ }
1367
+ },
1368
+ required: [
1369
+ "onrampId"
1370
+ ],
1371
+ additionalProperties: false
1372
+ }
1373
+ },
1374
+ $schema: "http://json-schema.org/draft-07/schema#"
1375
+ }
1376
+ },
1377
+ {
1378
+ name: "virtual-account_onramp_list",
1379
+ description: "List all onramps",
1380
+ inputSchema: {
1381
+ $ref: "#/definitions/virtual-account_onramp_list_input",
1382
+ definitions: {
1383
+ "virtual-account_onramp_list_input": {
1384
+ type: "object",
1385
+ properties: {
1386
+ status: {
1387
+ type: "string",
1388
+ enum: [
1389
+ "Created",
1390
+ "Authorized",
1391
+ "DepositAccountAdded",
1392
+ "Approved",
1393
+ "Rejected",
1394
+ "Cancelled"
1395
+ ],
1396
+ description: "Status of the onramps to get"
1397
+ }
1398
+ },
1399
+ required: [
1400
+ "status"
1401
+ ],
1402
+ additionalProperties: false
1403
+ }
1404
+ },
1405
+ $schema: "http://json-schema.org/draft-07/schema#"
1406
+ }
1407
+ },
1408
+ {
1409
+ name: "virtual-account_onramp_payment_create",
1410
+ description: "Create an open banking payment link for an onramp",
1411
+ inputSchema: {
1412
+ $ref: "#/definitions/virtual-account_onramp_payment_create_input",
1413
+ definitions: {
1414
+ "virtual-account_onramp_payment_create_input": {
1415
+ type: "object",
1416
+ properties: {
1417
+ onrampId: {
1418
+ type: "string",
1419
+ format: "uuid",
1420
+ description: "The ID of the onramp"
1421
+ },
1422
+ amount: {
1423
+ type: "string",
1424
+ description: "The amount to pay"
1425
+ },
1426
+ fiat: {
1427
+ type: "string",
1428
+ enum: [
1429
+ "USD",
1430
+ "EUR"
1431
+ ],
1432
+ description: "The fiat currency (USD or EUR)"
1433
+ }
1434
+ },
1435
+ required: [
1436
+ "onrampId",
1437
+ "amount",
1438
+ "fiat"
1439
+ ],
1440
+ additionalProperties: false
1441
+ }
1442
+ },
1443
+ $schema: "http://json-schema.org/draft-07/schema#"
1444
+ }
1445
+ },
1446
+ {
1447
+ name: "virtual-account_onramp_payment_retrieve",
1448
+ description: "Get the status of an open banking payment",
1449
+ inputSchema: {
1450
+ $ref: "#/definitions/virtual-account_onramp_payment_retrieve_input",
1451
+ definitions: {
1452
+ "virtual-account_onramp_payment_retrieve_input": {
1453
+ type: "object",
1454
+ properties: {
1455
+ onrampId: {
1456
+ type: "string",
1457
+ format: "uuid",
1458
+ description: "The ID of the onramp this payment belongs to"
1459
+ },
1460
+ paymentId: {
1461
+ type: "string",
1462
+ format: "uuid",
1463
+ description: "The ID of the payment to retrieve"
1464
+ }
1465
+ },
1466
+ required: [
1467
+ "onrampId",
1468
+ "paymentId"
1469
+ ],
1470
+ additionalProperties: false
1471
+ }
1472
+ },
1473
+ $schema: "http://json-schema.org/draft-07/schema#"
1474
+ }
1475
+ },
1476
+ {
1477
+ name: "virtual-account_onramp_retrieve",
1478
+ description: "Get onramp details and banking info",
1479
+ inputSchema: {
1480
+ $ref: "#/definitions/virtual-account_onramp_retrieve_input",
1481
+ definitions: {
1482
+ "virtual-account_onramp_retrieve_input": {
1483
+ type: "object",
1484
+ properties: {
1485
+ onrampId: {
1486
+ type: "string",
1487
+ format: "uuid",
1488
+ description: "The ID of the onramp to retrieve"
1489
+ }
1490
+ },
1491
+ required: [
1492
+ "onrampId"
1493
+ ],
1494
+ additionalProperties: false
1495
+ }
1496
+ },
1497
+ $schema: "http://json-schema.org/draft-07/schema#"
1498
+ }
1499
+ },
1500
+ {
1501
+ name: "virtual-account_retrieve",
1502
+ description: "Get your virtual account status",
1503
+ inputSchema: {
1504
+ $ref: "#/definitions/virtual-account_retrieve_input",
1505
+ definitions: {
1506
+ "virtual-account_retrieve_input": {
1507
+ type: "object",
1508
+ properties: {},
1509
+ additionalProperties: false
1510
+ }
1511
+ },
1512
+ $schema: "http://json-schema.org/draft-07/schema#"
1513
+ }
1514
+ },
1515
+ {
1516
+ name: "virtual-account_signing_create",
1517
+ description: "Sign a required document for your virtual account",
1518
+ inputSchema: {
1519
+ $ref: "#/definitions/virtual-account_signing_create_input",
1520
+ definitions: {
1521
+ "virtual-account_signing_create_input": {
1522
+ type: "object",
1523
+ properties: {
1524
+ contentId: {
1525
+ type: "string",
1526
+ description: "The unique ID of the content to sign"
1527
+ }
1528
+ },
1529
+ required: [
1530
+ "contentId"
1531
+ ],
1532
+ additionalProperties: false
1533
+ }
1534
+ },
1535
+ $schema: "http://json-schema.org/draft-07/schema#"
1536
+ }
1537
+ },
1538
+ {
1539
+ name: "virtual-account_signing_list",
1540
+ description: "List all signed documents",
1541
+ inputSchema: {
1542
+ $ref: "#/definitions/virtual-account_signing_list_input",
1543
+ definitions: {
1544
+ "virtual-account_signing_list_input": {
1545
+ type: "object",
1546
+ properties: {},
1547
+ additionalProperties: false
1548
+ }
1549
+ },
1550
+ $schema: "http://json-schema.org/draft-07/schema#"
1551
+ }
1552
+ },
1553
+ {
1554
+ name: "virtual-account_signing_required_list",
1555
+ description: "List documents that require your signature",
1556
+ inputSchema: {
1557
+ $ref: "#/definitions/virtual-account_signing_required_list_input",
1558
+ definitions: {
1559
+ "virtual-account_signing_required_list_input": {
1560
+ type: "object",
1561
+ properties: {},
1562
+ additionalProperties: false
1563
+ }
1564
+ },
1565
+ $schema: "http://json-schema.org/draft-07/schema#"
1566
+ }
1567
+ },
1568
+ {
1569
+ name: "virtual-account_transaction_list",
1570
+ description: "List virtual account transactions",
1571
+ inputSchema: {
1572
+ $ref: "#/definitions/virtual-account_transaction_list_input",
1573
+ definitions: {
1574
+ "virtual-account_transaction_list_input": {
1575
+ type: "object",
1576
+ properties: {},
1577
+ additionalProperties: false
1578
+ }
1579
+ },
1580
+ $schema: "http://json-schema.org/draft-07/schema#"
1581
+ }
1582
+ },
1583
+ {
1584
+ name: "virtual-account_wallet_list",
1585
+ description: "List registered wallets",
1586
+ inputSchema: {
1587
+ $ref: "#/definitions/virtual-account_wallet_list_input",
1588
+ definitions: {
1589
+ "virtual-account_wallet_list_input": {
1590
+ type: "object",
1591
+ properties: {},
1592
+ additionalProperties: false
1593
+ }
1594
+ },
1595
+ $schema: "http://json-schema.org/draft-07/schema#"
1596
+ }
1597
+ },
1598
+ {
1599
+ name: "virtual-account_wallet_register",
1600
+ description: "Register a wallet using a signed verification message",
1601
+ inputSchema: {
1602
+ $ref: "#/definitions/virtual-account_wallet_register_input",
1603
+ definitions: {
1604
+ "virtual-account_wallet_register_input": {
1605
+ type: "object",
1606
+ properties: {
1607
+ wallet: {
1608
+ type: "string",
1609
+ description: "The wallet address to register"
1610
+ },
1611
+ message: {
1612
+ type: "string",
1613
+ description: "The verification message (from virtual-account_wallet_registration-message_create)"
1614
+ },
1615
+ signature: {
1616
+ type: "string",
1617
+ description: "Base58-encoded signature of the message"
1618
+ }
1619
+ },
1620
+ required: [
1621
+ "wallet",
1622
+ "message",
1623
+ "signature"
1624
+ ],
1625
+ additionalProperties: false
1626
+ }
1627
+ },
1628
+ $schema: "http://json-schema.org/draft-07/schema#"
1629
+ }
1630
+ },
1631
+ {
1632
+ name: "virtual-account_wallet_registration-message_create",
1633
+ description: "Create the verification message to register a wallet",
1634
+ inputSchema: {
1635
+ $ref: "#/definitions/virtual-account_wallet_registration-message_create_input",
1636
+ definitions: {
1637
+ "virtual-account_wallet_registration-message_create_input": {
1638
+ type: "object",
1639
+ properties: {
1640
+ wallet: {
1641
+ type: "string",
1642
+ description: "The wallet address to register"
1643
+ }
1644
+ },
1645
+ required: [
1646
+ "wallet"
1647
+ ],
1648
+ additionalProperties: false
1649
+ }
1650
+ },
1651
+ $schema: "http://json-schema.org/draft-07/schema#"
1652
+ }
1653
+ }
1654
+ ];
1655
+
1656
+ // src/tools/wallet/create/tool.ts
1657
+ import { Keypair } from "@solana/web3.js";
1658
+ import bs58 from "bs58";
1659
+
1660
+ // src/tools/shared.ts
1661
+ var defineToolSchema = (config) => config;
1662
+ var createTool = (schema, handler) => ({
1663
+ schema,
1664
+ handler: async (params) => {
1665
+ const parsedInput = schema.input.parse(params);
1666
+ const result = await handler(parsedInput);
1667
+ return schema.output.parse(result);
1668
+ }
1669
+ });
1670
+
1671
+ // src/tools/wallet/server.ts
1672
+ import {
1673
+ readFileSync as readFileSync2,
1674
+ readdirSync,
1675
+ writeFileSync as writeFileSync2,
1676
+ mkdirSync as mkdirSync2,
1677
+ existsSync as existsSync2,
1678
+ renameSync as renameSync2
1679
+ } from "fs";
1680
+ import { join as join2, resolve } from "path";
1681
+ import { homedir as homedir2 } from "os";
1682
+ import { randomBytes as randomBytes2 } from "crypto";
1683
+
1684
+ // src/tools/wallet/models.ts
1685
+ import { z } from "zod";
1686
+ var walletSchema = z.object({
1687
+ name: z.string(),
1688
+ address: z.string(),
1689
+ secretKey: z.string(),
1690
+ chain: z.literal("solana"),
1691
+ createdAt: z.string()
1692
+ });
1693
+ var walletInfoSchema = walletSchema.omit({ secretKey: true });
1694
+
1695
+ // src/tools/wallet/server.ts
1696
+ var CONFIG_DIR2 = join2(homedir2(), ".config", "moonpay");
1697
+ var WALLETS_DIR = join2(CONFIG_DIR2, "wallets");
1698
+ function validateWalletName(name) {
1699
+ if (!name || /[/\\]/.test(name) || name.includes("..") || name.includes("\0")) {
1700
+ throw new Error(`Invalid wallet name: "${name}"`);
1701
+ }
1702
+ const resolved = resolve(WALLETS_DIR, `${name}.json`);
1703
+ if (!resolved.startsWith(WALLETS_DIR + "/")) {
1704
+ throw new Error(`Invalid wallet name: "${name}"`);
1705
+ }
1706
+ }
1707
+ function ensureWalletsDir() {
1708
+ mkdirSync2(WALLETS_DIR, { recursive: true, mode: 448 });
1709
+ }
1710
+ function getWalletPath(name) {
1711
+ validateWalletName(name);
1712
+ return join2(WALLETS_DIR, `${name}.json`);
1713
+ }
1714
+ function getWalletsDir() {
1715
+ return WALLETS_DIR;
1716
+ }
1717
+ function saveWallet(wallet) {
1718
+ ensureWalletsDir();
1719
+ const filePath = getWalletPath(wallet.name);
1720
+ if (existsSync2(filePath)) {
1721
+ throw new Error(`Wallet "${wallet.name}" already exists`);
1722
+ }
1723
+ const safeName = wallet.name.replace(/[^a-zA-Z0-9_-]/g, "_");
1724
+ const tmpPath = join2(
1725
+ WALLETS_DIR,
1726
+ `.${safeName}.${randomBytes2(4).toString("hex")}.tmp`
1727
+ );
1728
+ writeFileSync2(tmpPath, JSON.stringify(wallet, null, 2), { mode: 384 });
1729
+ renameSync2(tmpPath, filePath);
1730
+ }
1731
+ function loadWallet(nameOrAddress) {
1732
+ ensureWalletsDir();
1733
+ const files = readdirSync(WALLETS_DIR).filter((f) => f.endsWith(".json"));
1734
+ for (const file of files) {
1735
+ const raw = JSON.parse(readFileSync2(join2(WALLETS_DIR, file), "utf-8"));
1736
+ const result = walletSchema.safeParse(raw);
1737
+ if (!result.success) continue;
1738
+ const wallet = result.data;
1739
+ if (wallet.name === nameOrAddress || wallet.address === nameOrAddress)
1740
+ return wallet;
1741
+ }
1742
+ throw new Error(`Wallet "${nameOrAddress}" not found`);
1743
+ }
1744
+
1745
+ // src/tools/wallet/create/schema.ts
1746
+ import { z as z2 } from "zod";
1747
+ var walletCreateSchema = defineToolSchema({
1748
+ name: "wallet_create",
1749
+ description: "Generate a new Solana keypair and store it locally",
1750
+ input: z2.object({
1751
+ name: z2.string().describe("Wallet name")
1752
+ }),
1753
+ output: z2.object({
1754
+ name: z2.string().describe("Wallet name"),
1755
+ address: z2.string().describe("Solana wallet address (base58)")
1756
+ })
1757
+ });
1758
+
1759
+ // src/tools/wallet/create/tool.ts
1760
+ var walletCreate = createTool(walletCreateSchema, async (params) => {
1761
+ const keypair = Keypair.generate();
1762
+ const wallet = {
1763
+ name: params.name,
1764
+ address: keypair.publicKey.toBase58(),
1765
+ secretKey: bs58.encode(keypair.secretKey),
1766
+ chain: "solana",
1767
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
1768
+ };
1769
+ saveWallet(wallet);
1770
+ return { name: wallet.name, address: wallet.address };
1771
+ });
1772
+
1773
+ // src/tools/wallet/import/tool.ts
1774
+ import { Keypair as Keypair2 } from "@solana/web3.js";
1775
+ import bs582 from "bs58";
1776
+ import { createInterface } from "readline";
1777
+
1778
+ // src/tools/wallet/import/schema.ts
1779
+ import { z as z3 } from "zod";
1780
+ var walletImportSchema = defineToolSchema({
1781
+ name: "wallet_import",
1782
+ description: "Import a Solana wallet from a base58 private key",
1783
+ input: z3.object({
1784
+ name: z3.string().describe("Wallet name"),
1785
+ key: z3.string().nullable().describe("Base58-encoded private key (prompted interactively if not provided)")
1786
+ }),
1787
+ output: z3.object({
1788
+ name: z3.string().describe("Wallet name"),
1789
+ address: z3.string().describe("Solana wallet address (base58)")
1790
+ })
1791
+ });
1792
+
1793
+ // src/tools/wallet/import/tool.ts
1794
+ async function promptSecret(prompt) {
1795
+ const rl = createInterface({ input: process.stdin, output: process.stderr });
1796
+ return new Promise((resolve2) => {
1797
+ rl.question(prompt, (answer) => {
1798
+ rl.close();
1799
+ resolve2(answer.trim());
1800
+ });
1801
+ });
1802
+ }
1803
+ var walletImport = createTool(walletImportSchema, async (params) => {
1804
+ const secretKeyBase58 = params.key !== null ? params.key : await promptSecret("Enter private key (base58): ");
1805
+ let keypair;
1806
+ try {
1807
+ const secretKeyBytes = bs582.decode(secretKeyBase58);
1808
+ keypair = Keypair2.fromSecretKey(secretKeyBytes);
1809
+ } catch {
1810
+ throw new Error(
1811
+ "Invalid private key. Expected a base58-encoded Solana secret key."
1812
+ );
1813
+ }
1814
+ const wallet = {
1815
+ name: params.name,
1816
+ address: keypair.publicKey.toBase58(),
1817
+ secretKey: secretKeyBase58,
1818
+ chain: "solana",
1819
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
1820
+ };
1821
+ saveWallet(wallet);
1822
+ return { name: wallet.name, address: wallet.address };
1823
+ });
1824
+
1825
+ // src/tools/wallet/list/tool.ts
1826
+ import { readFileSync as readFileSync3, readdirSync as readdirSync2 } from "fs";
1827
+ import { join as join3 } from "path";
1828
+
1829
+ // src/tools/wallet/list/schema.ts
1830
+ import { z as z4 } from "zod";
1831
+ var walletListSchema = defineToolSchema({
1832
+ name: "wallet_list",
1833
+ description: "List all local wallets",
1834
+ input: z4.object({}),
1835
+ output: z4.array(walletInfoSchema)
1836
+ });
1837
+
1838
+ // src/tools/wallet/list/tool.ts
1839
+ var walletList = createTool(walletListSchema, async () => {
1840
+ ensureWalletsDir();
1841
+ const dir = getWalletsDir();
1842
+ const files = readdirSync2(dir).filter(
1843
+ (f) => f.endsWith(".json") && !f.startsWith(".")
1844
+ );
1845
+ return files.map((f) => {
1846
+ const wallet = JSON.parse(readFileSync3(join3(dir, f), "utf-8"));
1847
+ return {
1848
+ name: wallet.name,
1849
+ address: wallet.address,
1850
+ chain: wallet.chain,
1851
+ createdAt: wallet.createdAt
1852
+ };
1853
+ });
1854
+ });
1855
+
1856
+ // src/tools/wallet/retrieve/schema.ts
1857
+ import { z as z5 } from "zod";
1858
+ var walletRetrieveSchema = defineToolSchema({
1859
+ name: "wallet_retrieve",
1860
+ description: "Get details of a specific wallet",
1861
+ input: z5.object({
1862
+ wallet: z5.string().describe("Wallet name or address")
1863
+ }),
1864
+ output: walletInfoSchema
1865
+ });
1866
+
1867
+ // src/tools/wallet/retrieve/tool.ts
1868
+ var walletRetrieve = createTool(
1869
+ walletRetrieveSchema,
1870
+ async (params) => {
1871
+ const wallet = loadWallet(params.wallet);
1872
+ return {
1873
+ name: wallet.name,
1874
+ address: wallet.address,
1875
+ chain: wallet.chain,
1876
+ createdAt: wallet.createdAt
1877
+ };
1878
+ }
1879
+ );
1880
+
1881
+ // src/tools/wallet/delete/tool.ts
1882
+ import { unlinkSync as unlinkSync2 } from "fs";
1883
+
1884
+ // src/tools/wallet/delete/schema.ts
1885
+ import { z as z6 } from "zod";
1886
+ var walletDeleteSchema = defineToolSchema({
1887
+ name: "wallet_delete",
1888
+ description: "Permanently delete a local wallet. This removes the private key file and cannot be undone.",
1889
+ input: z6.object({
1890
+ wallet: z6.string().describe("Name or address of the wallet to delete"),
1891
+ confirm: z6.boolean().describe("Must be true to confirm deletion")
1892
+ }),
1893
+ output: z6.object({
1894
+ name: z6.string().describe("Name of the deleted wallet"),
1895
+ deleted: z6.literal(true)
1896
+ })
1897
+ });
1898
+
1899
+ // src/tools/wallet/delete/tool.ts
1900
+ var walletDelete = createTool(walletDeleteSchema, async (params) => {
1901
+ if (!params.confirm) {
1902
+ throw new Error(
1903
+ "Deletion not confirmed. Pass --confirm to permanently delete this wallet."
1904
+ );
1905
+ }
1906
+ const wallet = await walletRetrieve.handler({ wallet: params.wallet });
1907
+ unlinkSync2(getWalletPath(wallet.name));
1908
+ return { name: wallet.name, deleted: true };
1909
+ });
1910
+
1911
+ // src/tools/transaction/sign/tool.ts
1912
+ import { Keypair as Keypair3, VersionedTransaction } from "@solana/web3.js";
1913
+ import bs583 from "bs58";
1914
+
1915
+ // src/tools/transaction/sign/schema.ts
1916
+ import { z as z7 } from "zod";
1917
+ var transactionSignSchema = defineToolSchema({
1918
+ name: "transaction_sign",
1919
+ description: "Sign a base64-encoded Solana transaction with a local wallet",
1920
+ input: z7.object({
1921
+ wallet: z7.string().describe("Wallet address"),
1922
+ transaction: z7.string().describe("Base64-encoded unsigned transaction")
1923
+ }),
1924
+ output: z7.object({
1925
+ transaction: z7.string().describe("Base64-encoded signed transaction")
1926
+ })
1927
+ });
1928
+
1929
+ // src/tools/transaction/sign/tool.ts
1930
+ var transactionSign = createTool(
1931
+ transactionSignSchema,
1932
+ async (params) => {
1933
+ const storedWallet = loadWallet(params.wallet);
1934
+ const txBytes = Buffer.from(params.transaction.trim(), "base64");
1935
+ const tx = VersionedTransaction.deserialize(txBytes);
1936
+ const secretKeyBytes = bs583.decode(storedWallet.secretKey);
1937
+ const keypair = Keypair3.fromSecretKey(secretKeyBytes);
1938
+ tx.sign([keypair]);
1939
+ return {
1940
+ transaction: Buffer.from(tx.serialize()).toString("base64")
1941
+ };
1942
+ }
1943
+ );
1944
+
1945
+ // src/tools/message/sign/tool.ts
1946
+ import { Keypair as Keypair4 } from "@solana/web3.js";
1947
+ import bs584 from "bs58";
1948
+ import nacl from "tweetnacl";
1949
+
1950
+ // src/tools/message/sign/schema.ts
1951
+ import { z as z8 } from "zod";
1952
+ var messageSignSchema = defineToolSchema({
1953
+ name: "message_sign",
1954
+ description: "Sign a message with a local wallet. Produces a base58-encoded ed25519 signature compatible with Solana's signMessage.",
1955
+ input: z8.object({
1956
+ wallet: z8.string().describe("Wallet address to sign with"),
1957
+ message: z8.string().describe("Message text to sign")
1958
+ }),
1959
+ output: z8.object({
1960
+ signature: z8.string().describe("Base58-encoded ed25519 signature")
1961
+ })
1962
+ });
1963
+
1964
+ // src/tools/message/sign/tool.ts
1965
+ var messageSign = createTool(messageSignSchema, async (params) => {
1966
+ const storedWallet = loadWallet(params.wallet);
1967
+ const secretKeyBytes = bs584.decode(storedWallet.secretKey);
1968
+ const keypair = Keypair4.fromSecretKey(secretKeyBytes);
1969
+ const messageBytes = Buffer.from(params.message, "utf8");
1970
+ const signatureBytes = nacl.sign.detached(messageBytes, keypair.secretKey);
1971
+ return { signature: bs584.encode(signatureBytes) };
1972
+ });
1973
+
1974
+ export {
1975
+ getConfigOrDefault,
1976
+ clearCredentials,
1977
+ resolveBaseUrl,
1978
+ login,
1979
+ callTool,
1980
+ schemas_default,
1981
+ defineToolSchema,
1982
+ createTool,
1983
+ loadWallet,
1984
+ walletCreate,
1985
+ walletImport,
1986
+ walletList,
1987
+ walletRetrieve,
1988
+ walletDelete,
1989
+ transactionSign,
1990
+ messageSign
1991
+ };
1992
+ //# sourceMappingURL=chunk-SQTD2GMD.js.map