globodai-mcp-payment-manager 1.0.1

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.
Files changed (88) hide show
  1. package/.env.example +23 -0
  2. package/.github/workflows/ci.yml +26 -0
  3. package/.github/workflows/release.yml +82 -0
  4. package/LICENSE +21 -0
  5. package/README.md +362 -0
  6. package/dist/index.d.ts +31 -0
  7. package/dist/index.js +122 -0
  8. package/dist/lib/blockchain.d.ts +50 -0
  9. package/dist/lib/blockchain.js +287 -0
  10. package/dist/lib/cards.d.ts +83 -0
  11. package/dist/lib/cards.js +276 -0
  12. package/dist/lib/cli-runner.d.ts +31 -0
  13. package/dist/lib/cli-runner.js +77 -0
  14. package/dist/lib/crypto.d.ts +39 -0
  15. package/dist/lib/crypto.js +228 -0
  16. package/dist/lib/cvv-crypto.d.ts +23 -0
  17. package/dist/lib/cvv-crypto.js +67 -0
  18. package/dist/lib/mcp-core.d.ts +46 -0
  19. package/dist/lib/mcp-core.js +86 -0
  20. package/dist/lib/pin-manager.d.ts +69 -0
  21. package/dist/lib/pin-manager.js +199 -0
  22. package/dist/lib/wallets.d.ts +91 -0
  23. package/dist/lib/wallets.js +227 -0
  24. package/dist/tools/add-card.d.ts +65 -0
  25. package/dist/tools/add-card.js +97 -0
  26. package/dist/tools/add-wallet.d.ts +65 -0
  27. package/dist/tools/add-wallet.js +104 -0
  28. package/dist/tools/card-status.d.ts +20 -0
  29. package/dist/tools/card-status.js +26 -0
  30. package/dist/tools/confirm-payment.d.ts +44 -0
  31. package/dist/tools/confirm-payment.js +88 -0
  32. package/dist/tools/get-total-balance.d.ts +41 -0
  33. package/dist/tools/get-total-balance.js +98 -0
  34. package/dist/tools/get-transactions.d.ts +39 -0
  35. package/dist/tools/get-transactions.js +40 -0
  36. package/dist/tools/get-wallet-balance.d.ts +43 -0
  37. package/dist/tools/get-wallet-balance.js +69 -0
  38. package/dist/tools/list-cards.d.ts +36 -0
  39. package/dist/tools/list-cards.js +39 -0
  40. package/dist/tools/list-wallet-transactions.d.ts +63 -0
  41. package/dist/tools/list-wallet-transactions.js +76 -0
  42. package/dist/tools/list-wallets.d.ts +41 -0
  43. package/dist/tools/list-wallets.js +50 -0
  44. package/dist/tools/lock-cards.d.ts +16 -0
  45. package/dist/tools/lock-cards.js +23 -0
  46. package/dist/tools/prepare-crypto-tx.d.ts +69 -0
  47. package/dist/tools/prepare-crypto-tx.js +93 -0
  48. package/dist/tools/prepare-payment.d.ts +57 -0
  49. package/dist/tools/prepare-payment.js +93 -0
  50. package/dist/tools/remove-card.d.ts +25 -0
  51. package/dist/tools/remove-card.js +39 -0
  52. package/dist/tools/remove-wallet.d.ts +27 -0
  53. package/dist/tools/remove-wallet.js +40 -0
  54. package/dist/tools/setup-pin.d.ts +26 -0
  55. package/dist/tools/setup-pin.js +33 -0
  56. package/dist/tools/sign-crypto-tx.d.ts +42 -0
  57. package/dist/tools/sign-crypto-tx.js +75 -0
  58. package/dist/tools/unlock-cards.d.ts +35 -0
  59. package/dist/tools/unlock-cards.js +41 -0
  60. package/package.json +50 -0
  61. package/src/index.ts +139 -0
  62. package/src/lib/blockchain.ts +375 -0
  63. package/src/lib/cards.ts +372 -0
  64. package/src/lib/cli-runner.ts +113 -0
  65. package/src/lib/crypto.ts +284 -0
  66. package/src/lib/cvv-crypto.ts +81 -0
  67. package/src/lib/mcp-core.ts +127 -0
  68. package/src/lib/pin-manager.ts +252 -0
  69. package/src/lib/wallets.ts +331 -0
  70. package/src/tools/add-card.ts +108 -0
  71. package/src/tools/add-wallet.ts +114 -0
  72. package/src/tools/card-status.ts +32 -0
  73. package/src/tools/confirm-payment.ts +103 -0
  74. package/src/tools/get-total-balance.ts +123 -0
  75. package/src/tools/get-transactions.ts +49 -0
  76. package/src/tools/get-wallet-balance.ts +75 -0
  77. package/src/tools/list-cards.ts +52 -0
  78. package/src/tools/list-wallet-transactions.ts +83 -0
  79. package/src/tools/list-wallets.ts +63 -0
  80. package/src/tools/lock-cards.ts +31 -0
  81. package/src/tools/prepare-crypto-tx.ts +108 -0
  82. package/src/tools/prepare-payment.ts +108 -0
  83. package/src/tools/remove-card.ts +46 -0
  84. package/src/tools/remove-wallet.ts +47 -0
  85. package/src/tools/setup-pin.ts +39 -0
  86. package/src/tools/sign-crypto-tx.ts +90 -0
  87. package/src/tools/unlock-cards.ts +48 -0
  88. package/tsconfig.json +19 -0
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Get wallet balance via blockchain API
3
+ */
4
+ import { z } from "zod";
5
+ import { getWallet } from "../lib/wallets";
6
+ import { getWalletBalance, getUsdPrice } from "../lib/blockchain";
7
+ export const name = "get_wallet_balance";
8
+ export const description = "Get the current balance of a crypto wallet. Fetches live data from the blockchain.";
9
+ export const parameters = z.object({
10
+ wallet_id: z.string().optional().describe("Wallet ID (use list_wallets to see available wallets)"),
11
+ address: z.string().optional().describe("Wallet address (alternative to wallet_id)"),
12
+ chain: z.enum(["ethereum", "polygon", "arbitrum", "optimism", "base", "avalanche", "bsc", "bitcoin", "solana", "starknet"]).optional()
13
+ .describe("Blockchain (required if using address)"),
14
+ include_usd: z.boolean().optional().describe("Include USD value conversion (default: true)"),
15
+ });
16
+ export async function execute(args) {
17
+ let address;
18
+ let chain;
19
+ // Get wallet by ID or use provided address
20
+ if (args.wallet_id) {
21
+ const wallet = await getWallet(args.wallet_id);
22
+ if (!wallet) {
23
+ return { success: false, error: `Wallet not found: ${args.wallet_id}` };
24
+ }
25
+ address = wallet.address;
26
+ chain = wallet.chain;
27
+ }
28
+ else if (args.address && args.chain) {
29
+ address = args.address;
30
+ chain = args.chain;
31
+ }
32
+ else {
33
+ return {
34
+ success: false,
35
+ error: "Provide either wallet_id or both address and chain"
36
+ };
37
+ }
38
+ try {
39
+ const balance = await getWalletBalance(address, chain);
40
+ // Get USD price if requested
41
+ let usdValue = null;
42
+ if (args.include_usd !== false) {
43
+ const price = await getUsdPrice(balance.nativeCurrency);
44
+ if (price) {
45
+ usdValue = parseFloat(balance.nativeBalanceFormatted) * price;
46
+ }
47
+ }
48
+ return {
49
+ success: true,
50
+ wallet: {
51
+ address: `${address.slice(0, 10)}...${address.slice(-8)}`,
52
+ fullAddress: address,
53
+ chain,
54
+ },
55
+ balance: {
56
+ native: balance.nativeBalanceFormatted,
57
+ currency: balance.nativeCurrency,
58
+ raw: balance.nativeBalance,
59
+ usdValue: usdValue ? `$${usdValue.toFixed(2)}` : null,
60
+ },
61
+ };
62
+ }
63
+ catch (err) {
64
+ return {
65
+ success: false,
66
+ error: `Failed to fetch balance: ${err instanceof Error ? err.message : err}`,
67
+ };
68
+ }
69
+ }
@@ -0,0 +1,36 @@
1
+ /**
2
+ * List saved payment cards (safe view - no full card numbers)
3
+ */
4
+ import { z } from "zod";
5
+ export declare const name = "list_cards";
6
+ export declare const description = "List all saved payment cards. Shows card type, last 4 digits, nickname, and allowed usage. Does NOT show full card numbers.";
7
+ export declare const parameters: z.ZodObject<{
8
+ enabled_only: z.ZodOptional<z.ZodBoolean>;
9
+ usage_type: z.ZodOptional<z.ZodEnum<["flight", "train", "hotel", "general", "all"]>>;
10
+ }, "strip", z.ZodTypeAny, {
11
+ enabled_only?: boolean | undefined;
12
+ usage_type?: "flight" | "train" | "hotel" | "general" | "all" | undefined;
13
+ }, {
14
+ enabled_only?: boolean | undefined;
15
+ usage_type?: "flight" | "train" | "hotel" | "general" | "all" | undefined;
16
+ }>;
17
+ export declare function execute(args: z.infer<typeof parameters>): Promise<{
18
+ success: boolean;
19
+ cards: never[];
20
+ message: string;
21
+ count?: undefined;
22
+ } | {
23
+ success: boolean;
24
+ count: number;
25
+ cards: {
26
+ id: string;
27
+ nickname: string;
28
+ type: string;
29
+ lastFour: string;
30
+ cardholder: string;
31
+ usage: string;
32
+ enabled: boolean;
33
+ lastUsed: string;
34
+ }[];
35
+ message?: undefined;
36
+ }>;
@@ -0,0 +1,39 @@
1
+ /**
2
+ * List saved payment cards (safe view - no full card numbers)
3
+ */
4
+ import { z } from "zod";
5
+ import { getCardsSafe } from "../lib/cards";
6
+ export const name = "list_cards";
7
+ export const description = "List all saved payment cards. Shows card type, last 4 digits, nickname, and allowed usage. Does NOT show full card numbers.";
8
+ export const parameters = z.object({
9
+ enabled_only: z.boolean().optional().describe("Only show enabled cards"),
10
+ usage_type: z.enum(["flight", "train", "hotel", "general", "all"]).optional().describe("Filter by allowed usage type"),
11
+ });
12
+ export async function execute(args) {
13
+ const cards = await getCardsSafe();
14
+ let filtered = cards;
15
+ if (args.enabled_only) {
16
+ filtered = filtered.filter((c) => c.enabled);
17
+ }
18
+ if (args.usage_type) {
19
+ filtered = filtered.filter((c) => c.allowedUsage.includes(args.usage_type) || c.allowedUsage.includes("all"));
20
+ }
21
+ if (filtered.length === 0) {
22
+ return { success: true, cards: [], message: "No cards found" };
23
+ }
24
+ const summary = filtered.map((c) => ({
25
+ id: c.id,
26
+ nickname: c.nickname,
27
+ type: c.cardType.toUpperCase(),
28
+ lastFour: `****${c.lastFourDigits}`,
29
+ cardholder: c.cardholderName,
30
+ usage: c.allowedUsage.join(", "),
31
+ enabled: c.enabled,
32
+ lastUsed: c.lastUsedAt ?? "Never",
33
+ }));
34
+ return {
35
+ success: true,
36
+ count: summary.length,
37
+ cards: summary,
38
+ };
39
+ }
@@ -0,0 +1,63 @@
1
+ /**
2
+ * List wallet transactions from blockchain
3
+ */
4
+ import { z } from "zod";
5
+ import { type Chain } from "../lib/wallets";
6
+ export declare const name = "list_wallet_transactions";
7
+ export declare const description = "List recent transactions for a crypto wallet. Fetches live data from blockchain explorers.";
8
+ export declare const parameters: z.ZodObject<{
9
+ wallet_id: z.ZodOptional<z.ZodString>;
10
+ address: z.ZodOptional<z.ZodString>;
11
+ chain: z.ZodOptional<z.ZodEnum<["ethereum", "polygon", "arbitrum", "optimism", "base", "avalanche", "bsc", "bitcoin", "solana", "starknet"]>>;
12
+ limit: z.ZodOptional<z.ZodNumber>;
13
+ }, "strip", z.ZodTypeAny, {
14
+ address?: string | undefined;
15
+ chain?: "ethereum" | "polygon" | "arbitrum" | "optimism" | "base" | "avalanche" | "bsc" | "bitcoin" | "solana" | "starknet" | undefined;
16
+ wallet_id?: string | undefined;
17
+ limit?: number | undefined;
18
+ }, {
19
+ address?: string | undefined;
20
+ chain?: "ethereum" | "polygon" | "arbitrum" | "optimism" | "base" | "avalanche" | "bsc" | "bitcoin" | "solana" | "starknet" | undefined;
21
+ wallet_id?: string | undefined;
22
+ limit?: number | undefined;
23
+ }>;
24
+ export declare function execute(args: z.infer<typeof parameters>): Promise<{
25
+ success: boolean;
26
+ error: string;
27
+ wallet?: undefined;
28
+ transactions?: undefined;
29
+ message?: undefined;
30
+ count?: undefined;
31
+ } | {
32
+ success: boolean;
33
+ wallet: {
34
+ address: string;
35
+ chain: Chain;
36
+ fullAddress?: undefined;
37
+ };
38
+ transactions: never[];
39
+ message: string;
40
+ error?: undefined;
41
+ count?: undefined;
42
+ } | {
43
+ success: boolean;
44
+ wallet: {
45
+ address: string;
46
+ fullAddress: string;
47
+ chain: Chain;
48
+ };
49
+ count: number;
50
+ transactions: {
51
+ hash: string;
52
+ fullHash: string;
53
+ type: string;
54
+ amount: string;
55
+ from: string;
56
+ to: string;
57
+ status: "pending" | "failed" | "success";
58
+ date: string;
59
+ fee: string | null;
60
+ }[];
61
+ error?: undefined;
62
+ message?: undefined;
63
+ }>;
@@ -0,0 +1,76 @@
1
+ /**
2
+ * List wallet transactions from blockchain
3
+ */
4
+ import { z } from "zod";
5
+ import { getWallet } from "../lib/wallets";
6
+ import { getWalletTransactions } from "../lib/blockchain";
7
+ export const name = "list_wallet_transactions";
8
+ export const description = "List recent transactions for a crypto wallet. Fetches live data from blockchain explorers.";
9
+ export const parameters = z.object({
10
+ wallet_id: z.string().optional().describe("Wallet ID (use list_wallets to see available wallets)"),
11
+ address: z.string().optional().describe("Wallet address (alternative to wallet_id)"),
12
+ chain: z.enum(["ethereum", "polygon", "arbitrum", "optimism", "base", "avalanche", "bsc", "bitcoin", "solana", "starknet"]).optional()
13
+ .describe("Blockchain (required if using address)"),
14
+ limit: z.number().optional().describe("Number of transactions to return (default: 20, max: 50)"),
15
+ });
16
+ export async function execute(args) {
17
+ let address;
18
+ let chain;
19
+ // Get wallet by ID or use provided address
20
+ if (args.wallet_id) {
21
+ const wallet = await getWallet(args.wallet_id);
22
+ if (!wallet) {
23
+ return { success: false, error: `Wallet not found: ${args.wallet_id}` };
24
+ }
25
+ address = wallet.address;
26
+ chain = wallet.chain;
27
+ }
28
+ else if (args.address && args.chain) {
29
+ address = args.address;
30
+ chain = args.chain;
31
+ }
32
+ else {
33
+ return {
34
+ success: false,
35
+ error: "Provide either wallet_id or both address and chain"
36
+ };
37
+ }
38
+ const limit = Math.min(args.limit ?? 20, 50);
39
+ try {
40
+ const transactions = await getWalletTransactions(address, chain, limit);
41
+ if (transactions.length === 0) {
42
+ return {
43
+ success: true,
44
+ wallet: { address: `${address.slice(0, 10)}...${address.slice(-8)}`, chain },
45
+ transactions: [],
46
+ message: "No transactions found",
47
+ };
48
+ }
49
+ return {
50
+ success: true,
51
+ wallet: {
52
+ address: `${address.slice(0, 10)}...${address.slice(-8)}`,
53
+ fullAddress: address,
54
+ chain,
55
+ },
56
+ count: transactions.length,
57
+ transactions: transactions.map((tx) => ({
58
+ hash: `${tx.hash.slice(0, 10)}...${tx.hash.slice(-8)}`,
59
+ fullHash: tx.hash,
60
+ type: tx.isIncoming ? "RECEIVED" : "SENT",
61
+ amount: tx.valueFormatted,
62
+ from: tx.from ? `${tx.from.slice(0, 8)}...` : "N/A",
63
+ to: tx.to ? `${tx.to.slice(0, 8)}...` : "N/A",
64
+ status: tx.status,
65
+ date: new Date(tx.timestamp).toISOString(),
66
+ fee: tx.fee || null,
67
+ })),
68
+ };
69
+ }
70
+ catch (err) {
71
+ return {
72
+ success: false,
73
+ error: `Failed to fetch transactions: ${err instanceof Error ? err.message : err}`,
74
+ };
75
+ }
76
+ }
@@ -0,0 +1,41 @@
1
+ /**
2
+ * List saved crypto wallets (safe view - no private keys)
3
+ */
4
+ import { z } from "zod";
5
+ export declare const name = "list_wallets";
6
+ export declare const description = "List all saved crypto wallets. Shows address, chain, type, and allowed operations. Does NOT show private keys.";
7
+ export declare const parameters: z.ZodObject<{
8
+ chain: z.ZodOptional<z.ZodEnum<["ethereum", "polygon", "arbitrum", "optimism", "base", "avalanche", "bsc", "bitcoin", "solana", "starknet"]>>;
9
+ type: z.ZodOptional<z.ZodEnum<["hot", "watch-only", "hardware"]>>;
10
+ enabled_only: z.ZodOptional<z.ZodBoolean>;
11
+ }, "strip", z.ZodTypeAny, {
12
+ type?: "hot" | "watch-only" | "hardware" | undefined;
13
+ enabled_only?: boolean | undefined;
14
+ chain?: "ethereum" | "polygon" | "arbitrum" | "optimism" | "base" | "avalanche" | "bsc" | "bitcoin" | "solana" | "starknet" | undefined;
15
+ }, {
16
+ type?: "hot" | "watch-only" | "hardware" | undefined;
17
+ enabled_only?: boolean | undefined;
18
+ chain?: "ethereum" | "polygon" | "arbitrum" | "optimism" | "base" | "avalanche" | "bsc" | "bitcoin" | "solana" | "starknet" | undefined;
19
+ }>;
20
+ export declare function execute(args: z.infer<typeof parameters>): Promise<{
21
+ success: boolean;
22
+ wallets: never[];
23
+ message: string;
24
+ count?: undefined;
25
+ } | {
26
+ success: boolean;
27
+ count: number;
28
+ wallets: {
29
+ id: string;
30
+ nickname: string;
31
+ chain: string;
32
+ nativeCurrency: string;
33
+ address: string;
34
+ fullAddress: string;
35
+ type: import("../lib/wallets").WalletType;
36
+ operations: string;
37
+ enabled: boolean;
38
+ lastUsed: string;
39
+ }[];
40
+ message?: undefined;
41
+ }>;
@@ -0,0 +1,50 @@
1
+ /**
2
+ * List saved crypto wallets (safe view - no private keys)
3
+ */
4
+ import { z } from "zod";
5
+ import { getWalletsSafe, CHAIN_CONFIG } from "../lib/wallets";
6
+ export const name = "list_wallets";
7
+ export const description = "List all saved crypto wallets. Shows address, chain, type, and allowed operations. Does NOT show private keys.";
8
+ export const parameters = z.object({
9
+ chain: z.enum(["ethereum", "polygon", "arbitrum", "optimism", "base", "avalanche", "bsc", "bitcoin", "solana", "starknet"]).optional()
10
+ .describe("Filter by blockchain"),
11
+ type: z.enum(["hot", "watch-only", "hardware"]).optional()
12
+ .describe("Filter by wallet type"),
13
+ enabled_only: z.boolean().optional().describe("Only show enabled wallets"),
14
+ });
15
+ export async function execute(args) {
16
+ const wallets = await getWalletsSafe();
17
+ let filtered = wallets;
18
+ if (args.chain) {
19
+ filtered = filtered.filter((w) => w.chain === args.chain);
20
+ }
21
+ if (args.type) {
22
+ filtered = filtered.filter((w) => w.type === args.type);
23
+ }
24
+ if (args.enabled_only) {
25
+ filtered = filtered.filter((w) => w.enabled);
26
+ }
27
+ if (filtered.length === 0) {
28
+ return { success: true, wallets: [], message: "No wallets found" };
29
+ }
30
+ const summary = filtered.map((w) => {
31
+ const chainInfo = CHAIN_CONFIG[w.chain];
32
+ return {
33
+ id: w.id,
34
+ nickname: w.nickname,
35
+ chain: chainInfo?.name ?? w.chain,
36
+ nativeCurrency: chainInfo?.nativeCurrency ?? "?",
37
+ address: `${w.address.slice(0, 10)}...${w.address.slice(-8)}`,
38
+ fullAddress: w.address,
39
+ type: w.type,
40
+ operations: w.allowedOperations.join(", "),
41
+ enabled: w.enabled,
42
+ lastUsed: w.lastUsedAt ?? "Never",
43
+ };
44
+ });
45
+ return {
46
+ success: true,
47
+ count: summary.length,
48
+ wallets: summary,
49
+ };
50
+ }
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Lock cards (clear PIN from memory)
3
+ */
4
+ import { z } from "zod";
5
+ export declare const name = "lock_cards";
6
+ export declare const description = "Lock your cards immediately. Clears the PIN from memory. You'll need to unlock again to make payments.";
7
+ export declare const parameters: z.ZodObject<{}, "strip", z.ZodTypeAny, {}, {}>;
8
+ export declare function execute(_args: z.infer<typeof parameters>): Promise<{
9
+ success: boolean;
10
+ message: string;
11
+ note?: undefined;
12
+ } | {
13
+ success: boolean;
14
+ message: string;
15
+ note: string;
16
+ }>;
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Lock cards (clear PIN from memory)
3
+ */
4
+ import { z } from "zod";
5
+ import { lock, getStatus } from "../lib/pin-manager";
6
+ export const name = "lock_cards";
7
+ export const description = "Lock your cards immediately. Clears the PIN from memory. You'll need to unlock again to make payments.";
8
+ export const parameters = z.object({});
9
+ export async function execute(_args) {
10
+ const status = getStatus();
11
+ if (!status.unlocked) {
12
+ return {
13
+ success: true,
14
+ message: "Cards are already locked",
15
+ };
16
+ }
17
+ lock();
18
+ return {
19
+ success: true,
20
+ message: "Cards locked. PIN cleared from memory.",
21
+ note: "Use unlock_cards to unlock again when needed.",
22
+ };
23
+ }
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Prepare a crypto transaction for confirmation
3
+ *
4
+ * Creates a pending transaction that must be signed and broadcast.
5
+ * For hardware wallets, signing happens on the device.
6
+ */
7
+ import { z } from "zod";
8
+ export declare const name = "prepare_crypto_tx";
9
+ export declare const description = "Prepare a crypto transaction for signing. This creates a PENDING transaction that must be confirmed with sign_crypto_tx before broadcast.\n\nSupports:\n- Native token transfers (ETH, MATIC, etc.)\n- ERC20/token transfers\n- Contract interactions";
10
+ export declare const parameters: z.ZodObject<{
11
+ wallet_id: z.ZodString;
12
+ to: z.ZodString;
13
+ amount: z.ZodOptional<z.ZodString>;
14
+ token_address: z.ZodOptional<z.ZodString>;
15
+ token_symbol: z.ZodOptional<z.ZodString>;
16
+ data: z.ZodOptional<z.ZodString>;
17
+ gas_limit: z.ZodOptional<z.ZodString>;
18
+ max_fee_per_gas: z.ZodOptional<z.ZodString>;
19
+ max_priority_fee: z.ZodOptional<z.ZodString>;
20
+ description: z.ZodString;
21
+ }, "strip", z.ZodTypeAny, {
22
+ description: string;
23
+ to: string;
24
+ wallet_id: string;
25
+ amount?: string | undefined;
26
+ token_address?: string | undefined;
27
+ token_symbol?: string | undefined;
28
+ data?: string | undefined;
29
+ gas_limit?: string | undefined;
30
+ max_fee_per_gas?: string | undefined;
31
+ max_priority_fee?: string | undefined;
32
+ }, {
33
+ description: string;
34
+ to: string;
35
+ wallet_id: string;
36
+ amount?: string | undefined;
37
+ token_address?: string | undefined;
38
+ token_symbol?: string | undefined;
39
+ data?: string | undefined;
40
+ gas_limit?: string | undefined;
41
+ max_fee_per_gas?: string | undefined;
42
+ max_priority_fee?: string | undefined;
43
+ }>;
44
+ export declare function execute(args: z.infer<typeof parameters>): Promise<{
45
+ success: boolean;
46
+ error: string;
47
+ transaction_id?: undefined;
48
+ status?: undefined;
49
+ summary?: undefined;
50
+ wallet_type?: undefined;
51
+ next_step?: undefined;
52
+ warning?: undefined;
53
+ } | {
54
+ success: boolean;
55
+ transaction_id: `${string}-${string}-${string}-${string}-${string}`;
56
+ status: string;
57
+ summary: {
58
+ from: string;
59
+ to: string;
60
+ amount: string;
61
+ chain: string;
62
+ type: "send" | "contract";
63
+ description: string;
64
+ };
65
+ wallet_type: import("../lib/wallets").WalletType;
66
+ next_step: string;
67
+ warning: string;
68
+ error?: undefined;
69
+ }>;
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Prepare a crypto transaction for confirmation
3
+ *
4
+ * Creates a pending transaction that must be signed and broadcast.
5
+ * For hardware wallets, signing happens on the device.
6
+ */
7
+ import { z } from "zod";
8
+ import { randomUUID } from "crypto";
9
+ import { getWallet, logCryptoTransaction, CHAIN_CONFIG } from "../lib/wallets";
10
+ export const name = "prepare_crypto_tx";
11
+ export const description = `Prepare a crypto transaction for signing. This creates a PENDING transaction that must be confirmed with sign_crypto_tx before broadcast.
12
+
13
+ Supports:
14
+ - Native token transfers (ETH, MATIC, etc.)
15
+ - ERC20/token transfers
16
+ - Contract interactions`;
17
+ export const parameters = z.object({
18
+ wallet_id: z.string().describe("ID of the wallet to send from"),
19
+ to: z.string().describe("Recipient address"),
20
+ // Native or token
21
+ amount: z.string().optional().describe("Amount to send (in human readable units, e.g., '0.5' for 0.5 ETH)"),
22
+ token_address: z.string().optional().describe("Token contract address (omit for native currency)"),
23
+ token_symbol: z.string().optional().describe("Token symbol (e.g., 'USDC')"),
24
+ // Or raw contract call
25
+ data: z.string().optional().describe("Raw transaction data (hex) for contract calls"),
26
+ // Gas settings
27
+ gas_limit: z.string().optional().describe("Gas limit (default: estimated)"),
28
+ max_fee_per_gas: z.string().optional().describe("Max fee per gas in gwei"),
29
+ max_priority_fee: z.string().optional().describe("Max priority fee in gwei"),
30
+ // Description
31
+ description: z.string().describe("What this transaction is for"),
32
+ });
33
+ export async function execute(args) {
34
+ // Get wallet
35
+ const wallet = await getWallet(args.wallet_id);
36
+ if (!wallet) {
37
+ return { success: false, error: "Wallet not found" };
38
+ }
39
+ if (!wallet.enabled) {
40
+ return { success: false, error: "Wallet is disabled" };
41
+ }
42
+ if (!wallet.allowedOperations.includes("send")) {
43
+ return { success: false, error: "This wallet is not allowed to send transactions" };
44
+ }
45
+ // Validate recipient address (basic check)
46
+ const chainConfig = CHAIN_CONFIG[wallet.chain];
47
+ // Determine transaction type
48
+ let txType = "send";
49
+ if (args.data) {
50
+ txType = "contract";
51
+ }
52
+ // Create pending transaction
53
+ const txId = randomUUID();
54
+ const transaction = {
55
+ id: txId,
56
+ walletId: wallet.id,
57
+ chain: wallet.chain,
58
+ type: txType,
59
+ status: "pending",
60
+ from: wallet.address,
61
+ to: args.to,
62
+ value: args.amount,
63
+ tokenAddress: args.token_address,
64
+ tokenSymbol: args.token_symbol,
65
+ gasLimit: args.gas_limit,
66
+ maxFeePerGas: args.max_fee_per_gas,
67
+ maxPriorityFeePerGas: args.max_priority_fee,
68
+ description: args.description,
69
+ createdAt: new Date().toISOString(),
70
+ };
71
+ await logCryptoTransaction(transaction);
72
+ const amountDisplay = args.token_symbol
73
+ ? `${args.amount} ${args.token_symbol}`
74
+ : `${args.amount} ${chainConfig?.nativeCurrency ?? "tokens"}`;
75
+ return {
76
+ success: true,
77
+ transaction_id: txId,
78
+ status: "pending",
79
+ summary: {
80
+ from: `${wallet.nickname} (${wallet.address.slice(0, 10)}...)`,
81
+ to: `${args.to.slice(0, 10)}...${args.to.slice(-8)}`,
82
+ amount: amountDisplay,
83
+ chain: chainConfig?.name ?? wallet.chain,
84
+ type: txType,
85
+ description: args.description,
86
+ },
87
+ wallet_type: wallet.type,
88
+ next_step: wallet.type === "hardware"
89
+ ? "Connect your hardware wallet and call sign_crypto_tx to sign on device"
90
+ : "Call sign_crypto_tx to sign and broadcast the transaction",
91
+ warning: "NO TRANSACTION has been broadcast yet. You must sign to proceed.",
92
+ };
93
+ }
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Prepare a payment for confirmation
3
+ *
4
+ * This creates a pending transaction that must be confirmed before execution.
5
+ * Security: User must explicitly confirm with CVV before any charge.
6
+ */
7
+ import { z } from "zod";
8
+ export declare const name = "prepare_payment";
9
+ export declare const description = "Prepare a payment for a booking (flight, train, hotel, etc.). This creates a PENDING transaction that must be confirmed with confirm_payment before any charge is made.";
10
+ export declare const parameters: z.ZodObject<{
11
+ card_id: z.ZodString;
12
+ amount: z.ZodNumber;
13
+ currency: z.ZodString;
14
+ type: z.ZodEnum<["flight", "train", "hotel", "general"]>;
15
+ description: z.ZodString;
16
+ provider: z.ZodString;
17
+ details: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
18
+ }, "strip", z.ZodTypeAny, {
19
+ type: "flight" | "train" | "hotel" | "general";
20
+ amount: number;
21
+ currency: string;
22
+ description: string;
23
+ provider: string;
24
+ card_id: string;
25
+ details?: Record<string, unknown> | undefined;
26
+ }, {
27
+ type: "flight" | "train" | "hotel" | "general";
28
+ amount: number;
29
+ currency: string;
30
+ description: string;
31
+ provider: string;
32
+ card_id: string;
33
+ details?: Record<string, unknown> | undefined;
34
+ }>;
35
+ export declare function execute(args: z.infer<typeof parameters>): Promise<{
36
+ success: boolean;
37
+ error: string;
38
+ transaction_id?: undefined;
39
+ status?: undefined;
40
+ summary?: undefined;
41
+ next_step?: undefined;
42
+ warning?: undefined;
43
+ } | {
44
+ success: boolean;
45
+ transaction_id: `${string}-${string}-${string}-${string}-${string}`;
46
+ status: string;
47
+ summary: {
48
+ card: string;
49
+ amount: string;
50
+ type: "flight" | "train" | "hotel" | "general";
51
+ description: string;
52
+ provider: string;
53
+ };
54
+ next_step: string;
55
+ warning: string;
56
+ error?: undefined;
57
+ }>;