@ironwallet/mcp-server 1.0.0-preprod.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.
Files changed (110) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +161 -0
  3. package/assets/knight.png +0 -0
  4. package/assets/wordmark.svg +20 -0
  5. package/dist/api/auth.d.ts +20 -0
  6. package/dist/api/auth.js +92 -0
  7. package/dist/api/auth.js.map +1 -0
  8. package/dist/api/balances.d.ts +25 -0
  9. package/dist/api/balances.js +565 -0
  10. package/dist/api/balances.js.map +1 -0
  11. package/dist/api/http.d.ts +34 -0
  12. package/dist/api/http.js +277 -0
  13. package/dist/api/http.js.map +1 -0
  14. package/dist/api/relay.d.ts +49 -0
  15. package/dist/api/relay.js +194 -0
  16. package/dist/api/relay.js.map +1 -0
  17. package/dist/api/rpc.d.ts +10 -0
  18. package/dist/api/rpc.js +26 -0
  19. package/dist/api/rpc.js.map +1 -0
  20. package/dist/api/swap.d.ts +134 -0
  21. package/dist/api/swap.js +554 -0
  22. package/dist/api/swap.js.map +1 -0
  23. package/dist/cli.d.ts +6 -0
  24. package/dist/cli.js +20 -0
  25. package/dist/cli.js.map +1 -0
  26. package/dist/config.d.ts +91 -0
  27. package/dist/config.js +175 -0
  28. package/dist/config.js.map +1 -0
  29. package/dist/generated/env-config.d.ts +5 -0
  30. package/dist/generated/env-config.js +23 -0
  31. package/dist/generated/env-config.js.map +1 -0
  32. package/dist/generated/env-profile.d.ts +15 -0
  33. package/dist/generated/env-profile.js +2 -0
  34. package/dist/generated/env-profile.js.map +1 -0
  35. package/dist/keystore/crypto.d.ts +17 -0
  36. package/dist/keystore/crypto.js +57 -0
  37. package/dist/keystore/crypto.js.map +1 -0
  38. package/dist/keystore/store.d.ts +45 -0
  39. package/dist/keystore/store.js +224 -0
  40. package/dist/keystore/store.js.map +1 -0
  41. package/dist/keystore/types.d.ts +31 -0
  42. package/dist/keystore/types.js +2 -0
  43. package/dist/keystore/types.js.map +1 -0
  44. package/dist/local-secrets.d.ts +16 -0
  45. package/dist/local-secrets.js +73 -0
  46. package/dist/local-secrets.js.map +1 -0
  47. package/dist/log.d.ts +30 -0
  48. package/dist/log.js +323 -0
  49. package/dist/log.js.map +1 -0
  50. package/dist/passphrase.d.ts +6 -0
  51. package/dist/passphrase.js +10 -0
  52. package/dist/passphrase.js.map +1 -0
  53. package/dist/policy.d.ts +22 -0
  54. package/dist/policy.js +108 -0
  55. package/dist/policy.js.map +1 -0
  56. package/dist/server.d.ts +6 -0
  57. package/dist/server.js +38 -0
  58. package/dist/server.js.map +1 -0
  59. package/dist/signing/bitcoin.d.ts +18 -0
  60. package/dist/signing/bitcoin.js +84 -0
  61. package/dist/signing/bitcoin.js.map +1 -0
  62. package/dist/signing/dispatch.d.ts +7 -0
  63. package/dist/signing/dispatch.js +35 -0
  64. package/dist/signing/dispatch.js.map +1 -0
  65. package/dist/signing/evm.d.ts +16 -0
  66. package/dist/signing/evm.js +59 -0
  67. package/dist/signing/evm.js.map +1 -0
  68. package/dist/signing/index.d.ts +10 -0
  69. package/dist/signing/index.js +57 -0
  70. package/dist/signing/index.js.map +1 -0
  71. package/dist/signing/solana.d.ts +18 -0
  72. package/dist/signing/solana.js +106 -0
  73. package/dist/signing/solana.js.map +1 -0
  74. package/dist/signing/swap.d.ts +10 -0
  75. package/dist/signing/swap.js +114 -0
  76. package/dist/signing/swap.js.map +1 -0
  77. package/dist/signing/ton.d.ts +33 -0
  78. package/dist/signing/ton.js +166 -0
  79. package/dist/signing/ton.js.map +1 -0
  80. package/dist/signing/tron.d.ts +11 -0
  81. package/dist/signing/tron.js +39 -0
  82. package/dist/signing/tron.js.map +1 -0
  83. package/dist/signing/types.d.ts +23 -0
  84. package/dist/signing/types.js +2 -0
  85. package/dist/signing/types.js.map +1 -0
  86. package/dist/signing/xrp.d.ts +11 -0
  87. package/dist/signing/xrp.js +122 -0
  88. package/dist/signing/xrp.js.map +1 -0
  89. package/dist/tools/helpers.d.ts +42 -0
  90. package/dist/tools/helpers.js +80 -0
  91. package/dist/tools/helpers.js.map +1 -0
  92. package/dist/tools/index.d.ts +7 -0
  93. package/dist/tools/index.js +16 -0
  94. package/dist/tools/index.js.map +1 -0
  95. package/dist/tools/swap.d.ts +6 -0
  96. package/dist/tools/swap.js +343 -0
  97. package/dist/tools/swap.js.map +1 -0
  98. package/dist/tools/transfer.d.ts +6 -0
  99. package/dist/tools/transfer.js +284 -0
  100. package/dist/tools/transfer.js.map +1 -0
  101. package/dist/tools/wallets.d.ts +6 -0
  102. package/dist/tools/wallets.js +79 -0
  103. package/dist/tools/wallets.js.map +1 -0
  104. package/dist/wallet/derive.d.ts +53 -0
  105. package/dist/wallet/derive.js +233 -0
  106. package/dist/wallet/derive.js.map +1 -0
  107. package/dist/web/manager.d.ts +15 -0
  108. package/dist/web/manager.js +444 -0
  109. package/dist/web/manager.js.map +1 -0
  110. package/package.json +54 -0
@@ -0,0 +1,224 @@
1
+ /**
2
+ * Keystore persistence: reads/writes the encrypted keystore file and provides
3
+ * seed generation/import. Mnemonics are held in memory only transiently during
4
+ * signing; they are never returned to callers of these functions except the
5
+ * local browser wallet manager.
6
+ */
7
+ import { mkdirSync, readFileSync, writeFileSync, existsSync, chmodSync, } from "node:fs";
8
+ import { join } from "node:path";
9
+ import { getConfig } from "../config.js";
10
+ import { encryptSecret, decryptSecret } from "./crypto.js";
11
+ import { deriveAddresses, newMnemonic, isValidMnemonic, } from "../wallet/derive.js";
12
+ import { logDebug, logError, logInfo } from "../log.js";
13
+ function keystorePath() {
14
+ return join(getConfig().keystoreDir, "keystore.json");
15
+ }
16
+ function ensureDir() {
17
+ const dir = getConfig().keystoreDir;
18
+ if (!existsSync(dir))
19
+ mkdirSync(dir, { recursive: true });
20
+ }
21
+ export function loadKeystore() {
22
+ const path = keystorePath();
23
+ if (!existsSync(path)) {
24
+ logDebug("keystore.load", { path, exists: false, walletCount: 0 });
25
+ return { version: 1, wallets: [] };
26
+ }
27
+ const raw = readFileSync(path, "utf8");
28
+ const parsed = JSON.parse(raw);
29
+ if (parsed.version !== 1) {
30
+ throw new Error(`Unsupported keystore version: ${parsed.version}`);
31
+ }
32
+ logDebug("keystore.load", {
33
+ path,
34
+ exists: true,
35
+ walletCount: parsed.wallets.length,
36
+ names: parsed.wallets.map((w) => w.name),
37
+ });
38
+ return parsed;
39
+ }
40
+ function saveKeystore(ks) {
41
+ ensureDir();
42
+ const path = keystorePath();
43
+ writeFileSync(path, JSON.stringify(ks, null, 2), { mode: 0o600 });
44
+ try {
45
+ chmodSync(path, 0o600);
46
+ }
47
+ catch {
48
+ // best effort on platforms without POSIX perms
49
+ }
50
+ logInfo("keystore.save", {
51
+ path,
52
+ walletCount: ks.wallets.length,
53
+ names: ks.wallets.map((w) => w.name),
54
+ });
55
+ }
56
+ export function walletNames() {
57
+ return loadKeystore().wallets.map((w) => w.name);
58
+ }
59
+ export function getEntry(name) {
60
+ return loadKeystore().wallets.find((w) => w.name === name);
61
+ }
62
+ /**
63
+ * Resolve which wallet to use. If `name` is given it must exist. If omitted and
64
+ * exactly one wallet exists, that one is used. Otherwise an error is thrown.
65
+ */
66
+ export function resolveEntry(name) {
67
+ const ks = loadKeystore();
68
+ if (name) {
69
+ const found = ks.wallets.find((w) => w.name === name);
70
+ if (!found)
71
+ throw new Error(`Wallet "${name}" not found.`);
72
+ return found;
73
+ }
74
+ if (ks.wallets.length === 1)
75
+ return ks.wallets[0];
76
+ if (ks.wallets.length === 0) {
77
+ throw new Error("No wallets found. Create one with the create_wallets tool or open_wallet_manager.");
78
+ }
79
+ throw new Error(`Multiple wallets exist (${ks.wallets
80
+ .map((w) => w.name)
81
+ .join(", ")}). Specify which one with the "wallet" parameter.`);
82
+ }
83
+ function uniqueName(base, existing) {
84
+ if (!existing.has(base))
85
+ return base;
86
+ let i = 2;
87
+ while (existing.has(`${base}-${i}`))
88
+ i++;
89
+ return `${base}-${i}`;
90
+ }
91
+ /**
92
+ * Create N brand-new wallets. Returns names + addresses. The mnemonic is only
93
+ * echoed back when `revealMnemonic` is true (wallet manager), never for the
94
+ * MCP tool path.
95
+ */
96
+ export function createWallets(count, passphrase, opts = {}) {
97
+ if (count < 1 || count > 50) {
98
+ throw new Error("count must be between 1 and 50.");
99
+ }
100
+ logInfo("keystore.create_wallets.start", {
101
+ count,
102
+ namePrefix: opts.namePrefix,
103
+ revealMnemonic: Boolean(opts.revealMnemonic),
104
+ });
105
+ const ks = loadKeystore();
106
+ const existing = new Set(ks.wallets.map((w) => w.name));
107
+ const prefix = opts.namePrefix ?? "wallet";
108
+ const created = [];
109
+ for (let i = 0; i < count; i++) {
110
+ const mnemonic = newMnemonic(12);
111
+ const addresses = deriveAddresses(mnemonic);
112
+ const name = uniqueName(count === 1 && opts.namePrefix ? prefix : `${prefix}-${existing.size + 1}`, existing);
113
+ existing.add(name);
114
+ const entry = {
115
+ name,
116
+ encSeed: encryptSecret(mnemonic, passphrase),
117
+ addresses,
118
+ backedUp: false,
119
+ createdAt: new Date().toISOString(),
120
+ };
121
+ ks.wallets.push(entry);
122
+ created.push({
123
+ name,
124
+ addresses,
125
+ mnemonic: opts.revealMnemonic ? mnemonic : undefined,
126
+ });
127
+ }
128
+ saveKeystore(ks);
129
+ logInfo("keystore.create_wallets.ok", {
130
+ created: created.map((c) => ({ name: c.name, addresses: c.addresses })),
131
+ });
132
+ return created;
133
+ }
134
+ /** Import an existing mnemonic under a name. */
135
+ export function importWallet(mnemonic, passphrase, name) {
136
+ const trimmed = mnemonic.trim();
137
+ if (!isValidMnemonic(trimmed)) {
138
+ logError("keystore.import.fail", new Error("Invalid BIP-39 mnemonic."), {
139
+ requestedName: name,
140
+ });
141
+ throw new Error("Invalid BIP-39 mnemonic.");
142
+ }
143
+ const ks = loadKeystore();
144
+ const existing = new Set(ks.wallets.map((w) => w.name));
145
+ const finalName = uniqueName(name ?? "imported", existing);
146
+ const addresses = deriveAddresses(trimmed);
147
+ const entry = {
148
+ name: finalName,
149
+ encSeed: encryptSecret(trimmed, passphrase),
150
+ addresses,
151
+ backedUp: true, // user already has these words
152
+ createdAt: new Date().toISOString(),
153
+ };
154
+ ks.wallets.push(entry);
155
+ saveKeystore(ks);
156
+ logInfo("keystore.import.ok", { name: finalName, addresses });
157
+ return { name: finalName, addresses };
158
+ }
159
+ /** Decrypt and return a wallet's mnemonic. CLI/backup use only. */
160
+ export function revealMnemonic(name, passphrase) {
161
+ const entry = getEntry(name);
162
+ if (!entry)
163
+ throw new Error(`Wallet "${name}" not found.`);
164
+ return decryptSecret(entry.encSeed, passphrase);
165
+ }
166
+ /** Decrypt a wallet's mnemonic for internal signing. Never expose the result. */
167
+ export function unlockMnemonic(entry, passphrase) {
168
+ return decryptSecret(entry.encSeed, passphrase);
169
+ }
170
+ /**
171
+ * Fill in any newly supported network addresses missing from an older keystore
172
+ * entry (e.g. litecoin/doge added after the wallet was created). Persists when
173
+ * something was missing.
174
+ */
175
+ export function syncAddresses(entry, mnemonic) {
176
+ const fresh = deriveAddresses(mnemonic);
177
+ let changed = false;
178
+ const merged = { ...entry.addresses };
179
+ for (const [net, addr] of Object.entries(fresh)) {
180
+ if (!merged[net]) {
181
+ merged[net] = addr;
182
+ changed = true;
183
+ }
184
+ }
185
+ if (!changed)
186
+ return entry;
187
+ const ks = loadKeystore();
188
+ const stored = ks.wallets.find((w) => w.name === entry.name);
189
+ if (!stored)
190
+ return { ...entry, addresses: merged };
191
+ stored.addresses = merged;
192
+ saveKeystore(ks);
193
+ logInfo("keystore.sync_addresses", {
194
+ name: entry.name,
195
+ added: Object.keys(fresh).filter((n) => !entry.addresses[n]),
196
+ });
197
+ return { ...entry, addresses: merged };
198
+ }
199
+ export function markBackedUp(name) {
200
+ const ks = loadKeystore();
201
+ const entry = ks.wallets.find((w) => w.name === name);
202
+ if (!entry)
203
+ throw new Error(`Wallet "${name}" not found.`);
204
+ entry.backedUp = true;
205
+ saveKeystore(ks);
206
+ }
207
+ export function removeWallet(name) {
208
+ const ks = loadKeystore();
209
+ const before = ks.wallets.length;
210
+ ks.wallets = ks.wallets.filter((w) => w.name !== name);
211
+ if (ks.wallets.length === before)
212
+ throw new Error(`Wallet "${name}" not found.`);
213
+ saveKeystore(ks);
214
+ logInfo("keystore.remove.ok", { name, remaining: ks.wallets.length });
215
+ }
216
+ export function setPolicy(name, policy) {
217
+ const ks = loadKeystore();
218
+ const entry = ks.wallets.find((w) => w.name === name);
219
+ if (!entry)
220
+ throw new Error(`Wallet "${name}" not found.`);
221
+ entry.policy = policy;
222
+ saveKeystore(ks);
223
+ }
224
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/keystore/store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,31 @@
1
+ import type { NetworkId } from "../config.js";
2
+ /** Per-wallet spending policy. Enforced only when `enabled` is true. */
3
+ export interface WalletPolicy {
4
+ enabled: boolean;
5
+ /** If true, send_transfer and execute_swap are rejected. */
6
+ readOnly?: boolean;
7
+ /** Max amount per send_transfer or execute_swap (decimal string, asset units). */
8
+ maxPerTx?: string;
9
+ /**
10
+ * Allowed transfer destinations. Empty/undefined = no whitelist.
11
+ * When set, execute_swap is rejected (swap routers are not on this list).
12
+ */
13
+ allowedRecipients?: string[];
14
+ }
15
+ /** An encrypted seed record. The mnemonic is never stored in clear text. */
16
+ export interface WalletEntry {
17
+ name: string;
18
+ /** Encrypted mnemonic blob (see keystore/crypto.ts EncryptedBlob JSON). */
19
+ encSeed: string;
20
+ /** Public addresses per network. Safe to read without the passphrase. */
21
+ addresses: Record<string, string>;
22
+ /** Whether the user confirmed they backed up the mnemonic. */
23
+ backedUp: boolean;
24
+ createdAt: string;
25
+ policy?: WalletPolicy;
26
+ }
27
+ export interface KeystoreFile {
28
+ version: 1;
29
+ wallets: WalletEntry[];
30
+ }
31
+ export type { NetworkId };
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/keystore/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Machine-local secrets and install identity. Generated on first use and stored
3
+ * under the keystore directory (0600). Not written to User env, mcp.json, or
4
+ * the plugin dashboard.
5
+ *
6
+ * Env vars still win when set to a real value. Unexpanded `${VAR}` placeholders
7
+ * (Claude Code when the shell var is missing) are treated as unset.
8
+ */
9
+ export declare function resolveKeystoreDir(): string;
10
+ export declare function isUnsetSecret(value: string | undefined): boolean;
11
+ /** x-api-key for Relay / Swap Proxy. UUID, stable per machine directory. */
12
+ export declare function resolveRelayApiKey(): string;
13
+ /** Keystore wrapping secret. Not the recovery phrase. */
14
+ export declare function resolveKeystorePassphrase(): string;
15
+ /** X-Device-Id. UUID, stable per keystore directory. */
16
+ export declare function resolveDeviceId(): string;
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Machine-local secrets and install identity. Generated on first use and stored
3
+ * under the keystore directory (0600). Not written to User env, mcp.json, or
4
+ * the plugin dashboard.
5
+ *
6
+ * Env vars still win when set to a real value. Unexpanded `${VAR}` placeholders
7
+ * (Claude Code when the shell var is missing) are treated as unset.
8
+ */
9
+ import { chmodSync, existsSync, mkdirSync, readFileSync, writeFileSync, } from "node:fs";
10
+ import { join } from "node:path";
11
+ import { randomBytes, randomUUID } from "node:crypto";
12
+ const RELAY_KEY_FILE = "relay-api-key";
13
+ const PASSPHRASE_FILE = "keystore-passphrase";
14
+ const DEVICE_ID_FILE = "device-id";
15
+ export function resolveKeystoreDir() {
16
+ if (process.env.IW_KEYSTORE_DIR)
17
+ return process.env.IW_KEYSTORE_DIR;
18
+ const home = process.env.HOME ??
19
+ process.env.USERPROFILE ??
20
+ process.env.HOMEPATH ??
21
+ ".";
22
+ return `${home}/.ironwallet-mcp`;
23
+ }
24
+ export function isUnsetSecret(value) {
25
+ if (!value)
26
+ return true;
27
+ const trimmed = value.trim();
28
+ if (trimmed.length === 0)
29
+ return true;
30
+ return /^\$\{[A-Za-z_][A-Za-z0-9_]*\}$/.test(trimmed);
31
+ }
32
+ function readOrCreate(filename, generate) {
33
+ const dir = resolveKeystoreDir();
34
+ if (!existsSync(dir))
35
+ mkdirSync(dir, { recursive: true });
36
+ const path = join(dir, filename);
37
+ if (existsSync(path)) {
38
+ const existing = readFileSync(path, "utf8").trim();
39
+ if (existing.length > 0 && !isUnsetSecret(existing))
40
+ return existing;
41
+ }
42
+ const value = generate();
43
+ writeFileSync(path, `${value}\n`, { mode: 0o600 });
44
+ try {
45
+ chmodSync(path, 0o600);
46
+ }
47
+ catch {
48
+ // best effort on platforms without POSIX perms
49
+ }
50
+ return value;
51
+ }
52
+ /** x-api-key for Relay / Swap Proxy. UUID, stable per machine directory. */
53
+ export function resolveRelayApiKey() {
54
+ const fromEnv = process.env.IW_RELAY_API_KEY;
55
+ if (!isUnsetSecret(fromEnv))
56
+ return fromEnv.trim();
57
+ return readOrCreate(RELAY_KEY_FILE, () => randomUUID());
58
+ }
59
+ /** Keystore wrapping secret. Not the recovery phrase. */
60
+ export function resolveKeystorePassphrase() {
61
+ const fromEnv = process.env.IW_PASSPHRASE;
62
+ if (!isUnsetSecret(fromEnv))
63
+ return fromEnv.trim();
64
+ return readOrCreate(PASSPHRASE_FILE, () => randomBytes(24).toString("base64url"));
65
+ }
66
+ /** X-Device-Id. UUID, stable per keystore directory. */
67
+ export function resolveDeviceId() {
68
+ const fromEnv = process.env.IW_DEVICE_ID;
69
+ if (!isUnsetSecret(fromEnv))
70
+ return fromEnv.trim();
71
+ return readOrCreate(DEVICE_ID_FILE, () => randomUUID());
72
+ }
73
+ //# sourceMappingURL=local-secrets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"local-secrets.js","sourceRoot":"","sources":["../src/local-secrets.ts"],"names":[],"mappings":"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"}
package/dist/log.d.ts ADDED
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Append-only JSONL file logger for diagnosing relay/network instability.
3
+ *
4
+ * Writes ONLY to a file (never stdout — that carries MCP JSON-RPC). Optionally
5
+ * mirrors to stderr when IW_LOG_STDERR=1.
6
+ *
7
+ * Secrets (Authorization, x-api-key, mnemonics, private keys, full signatures)
8
+ * are redacted. Bodies are summarized by default; set IW_LOG_BODIES=1 to include
9
+ * truncated request/response bodies (still redacted for known secret fields).
10
+ */
11
+ export type LogLevel = "debug" | "info" | "warn" | "error";
12
+ /** Empty string / IW_LOG_ENABLED=0 disables file logging. */
13
+ export declare function isLogEnabled(): boolean;
14
+ export declare function getLogFilePath(): string | null;
15
+ export declare function newCorrelationId(prefix?: string): string;
16
+ /** Walk Error.cause chains (undici nests codes here). */
17
+ export declare function errorDetails(err: unknown, depth?: number): Record<string, unknown>;
18
+ export declare function truncate(s: string, max?: number): string;
19
+ export declare function redactHeaders(headers?: Headers | Record<string, string> | [string, string][]): Record<string, string> | undefined;
20
+ /** Deep-redact known secret keys; truncate long strings. */
21
+ export declare function sanitize(value: unknown, depth?: number): unknown;
22
+ /** Compact summary of a JSON/text body for logs (sizes + key fields). */
23
+ export declare function summarizeBody(body: unknown): Record<string, unknown> | undefined;
24
+ export declare function log(level: LogLevel, event: string, data?: Record<string, unknown>): void;
25
+ export declare function logInfo(event: string, data?: Record<string, unknown>): void;
26
+ export declare function logDebug(event: string, data?: Record<string, unknown>): void;
27
+ export declare function logWarn(event: string, data?: Record<string, unknown>): void;
28
+ export declare function logError(event: string, err: unknown, data?: Record<string, unknown>): void;
29
+ /** One-shot banner so operators know where logs go. */
30
+ export declare function logStartupBanner(extra?: Record<string, unknown>): void;