@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.
- package/LICENSE +21 -0
- package/README.md +161 -0
- package/assets/knight.png +0 -0
- package/assets/wordmark.svg +20 -0
- package/dist/api/auth.d.ts +20 -0
- package/dist/api/auth.js +92 -0
- package/dist/api/auth.js.map +1 -0
- package/dist/api/balances.d.ts +25 -0
- package/dist/api/balances.js +565 -0
- package/dist/api/balances.js.map +1 -0
- package/dist/api/http.d.ts +34 -0
- package/dist/api/http.js +277 -0
- package/dist/api/http.js.map +1 -0
- package/dist/api/relay.d.ts +49 -0
- package/dist/api/relay.js +194 -0
- package/dist/api/relay.js.map +1 -0
- package/dist/api/rpc.d.ts +10 -0
- package/dist/api/rpc.js +26 -0
- package/dist/api/rpc.js.map +1 -0
- package/dist/api/swap.d.ts +134 -0
- package/dist/api/swap.js +554 -0
- package/dist/api/swap.js.map +1 -0
- package/dist/cli.d.ts +6 -0
- package/dist/cli.js +20 -0
- package/dist/cli.js.map +1 -0
- package/dist/config.d.ts +91 -0
- package/dist/config.js +175 -0
- package/dist/config.js.map +1 -0
- package/dist/generated/env-config.d.ts +5 -0
- package/dist/generated/env-config.js +23 -0
- package/dist/generated/env-config.js.map +1 -0
- package/dist/generated/env-profile.d.ts +15 -0
- package/dist/generated/env-profile.js +2 -0
- package/dist/generated/env-profile.js.map +1 -0
- package/dist/keystore/crypto.d.ts +17 -0
- package/dist/keystore/crypto.js +57 -0
- package/dist/keystore/crypto.js.map +1 -0
- package/dist/keystore/store.d.ts +45 -0
- package/dist/keystore/store.js +224 -0
- package/dist/keystore/store.js.map +1 -0
- package/dist/keystore/types.d.ts +31 -0
- package/dist/keystore/types.js +2 -0
- package/dist/keystore/types.js.map +1 -0
- package/dist/local-secrets.d.ts +16 -0
- package/dist/local-secrets.js +73 -0
- package/dist/local-secrets.js.map +1 -0
- package/dist/log.d.ts +30 -0
- package/dist/log.js +323 -0
- package/dist/log.js.map +1 -0
- package/dist/passphrase.d.ts +6 -0
- package/dist/passphrase.js +10 -0
- package/dist/passphrase.js.map +1 -0
- package/dist/policy.d.ts +22 -0
- package/dist/policy.js +108 -0
- package/dist/policy.js.map +1 -0
- package/dist/server.d.ts +6 -0
- package/dist/server.js +38 -0
- package/dist/server.js.map +1 -0
- package/dist/signing/bitcoin.d.ts +18 -0
- package/dist/signing/bitcoin.js +84 -0
- package/dist/signing/bitcoin.js.map +1 -0
- package/dist/signing/dispatch.d.ts +7 -0
- package/dist/signing/dispatch.js +35 -0
- package/dist/signing/dispatch.js.map +1 -0
- package/dist/signing/evm.d.ts +16 -0
- package/dist/signing/evm.js +59 -0
- package/dist/signing/evm.js.map +1 -0
- package/dist/signing/index.d.ts +10 -0
- package/dist/signing/index.js +57 -0
- package/dist/signing/index.js.map +1 -0
- package/dist/signing/solana.d.ts +18 -0
- package/dist/signing/solana.js +106 -0
- package/dist/signing/solana.js.map +1 -0
- package/dist/signing/swap.d.ts +10 -0
- package/dist/signing/swap.js +114 -0
- package/dist/signing/swap.js.map +1 -0
- package/dist/signing/ton.d.ts +33 -0
- package/dist/signing/ton.js +166 -0
- package/dist/signing/ton.js.map +1 -0
- package/dist/signing/tron.d.ts +11 -0
- package/dist/signing/tron.js +39 -0
- package/dist/signing/tron.js.map +1 -0
- package/dist/signing/types.d.ts +23 -0
- package/dist/signing/types.js +2 -0
- package/dist/signing/types.js.map +1 -0
- package/dist/signing/xrp.d.ts +11 -0
- package/dist/signing/xrp.js +122 -0
- package/dist/signing/xrp.js.map +1 -0
- package/dist/tools/helpers.d.ts +42 -0
- package/dist/tools/helpers.js +80 -0
- package/dist/tools/helpers.js.map +1 -0
- package/dist/tools/index.d.ts +7 -0
- package/dist/tools/index.js +16 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/swap.d.ts +6 -0
- package/dist/tools/swap.js +343 -0
- package/dist/tools/swap.js.map +1 -0
- package/dist/tools/transfer.d.ts +6 -0
- package/dist/tools/transfer.js +284 -0
- package/dist/tools/transfer.js.map +1 -0
- package/dist/tools/wallets.d.ts +6 -0
- package/dist/tools/wallets.js +79 -0
- package/dist/tools/wallets.js.map +1 -0
- package/dist/wallet/derive.d.ts +53 -0
- package/dist/wallet/derive.js +233 -0
- package/dist/wallet/derive.js.map +1 -0
- package/dist/web/manager.d.ts +15 -0
- package/dist/web/manager.js +444 -0
- package/dist/web/manager.js.map +1 -0
- package/package.json +54 -0
package/dist/log.js
ADDED
|
@@ -0,0 +1,323 @@
|
|
|
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
|
+
import { appendFileSync, mkdirSync, existsSync } from "node:fs";
|
|
12
|
+
import { dirname, join } from "node:path";
|
|
13
|
+
import { randomUUID } from "node:crypto";
|
|
14
|
+
import { getConfig } from "./config.js";
|
|
15
|
+
const LEVEL_RANK = {
|
|
16
|
+
debug: 10,
|
|
17
|
+
info: 20,
|
|
18
|
+
warn: 30,
|
|
19
|
+
error: 40,
|
|
20
|
+
};
|
|
21
|
+
const SENSITIVE_HEADER = /^(authorization|x-api-key|cookie|set-cookie|proxy-authorization)$/i;
|
|
22
|
+
const SENSITIVE_KEY = /^(authorization|accessToken|token|password|passphrase|mnemonic|seed|privateKey|secret|x-api-key|signature|TxnSignature)$/i;
|
|
23
|
+
let resolvedPath;
|
|
24
|
+
let minLevel;
|
|
25
|
+
let bodiesEnabled;
|
|
26
|
+
let stderrMirror;
|
|
27
|
+
let warnedOnce = false;
|
|
28
|
+
function envFlag(name, fallback) {
|
|
29
|
+
const v = process.env[name];
|
|
30
|
+
if (v === undefined || v === "")
|
|
31
|
+
return fallback;
|
|
32
|
+
return !/^(0|false|off|no)$/i.test(v);
|
|
33
|
+
}
|
|
34
|
+
function resolveMinLevel() {
|
|
35
|
+
if (minLevel)
|
|
36
|
+
return minLevel;
|
|
37
|
+
const raw = (process.env.IW_LOG_LEVEL ?? "info").toLowerCase();
|
|
38
|
+
minLevel =
|
|
39
|
+
raw === "info" || raw === "warn" || raw === "error" || raw === "debug"
|
|
40
|
+
? raw
|
|
41
|
+
: "info";
|
|
42
|
+
return minLevel;
|
|
43
|
+
}
|
|
44
|
+
/** Empty string / IW_LOG_ENABLED=0 disables file logging. */
|
|
45
|
+
export function isLogEnabled() {
|
|
46
|
+
if (!envFlag("IW_LOG_ENABLED", true))
|
|
47
|
+
return false;
|
|
48
|
+
if (process.env.IW_LOG_FILE === "")
|
|
49
|
+
return false;
|
|
50
|
+
return true;
|
|
51
|
+
}
|
|
52
|
+
export function getLogFilePath() {
|
|
53
|
+
if (resolvedPath !== undefined)
|
|
54
|
+
return resolvedPath;
|
|
55
|
+
if (!isLogEnabled()) {
|
|
56
|
+
resolvedPath = null;
|
|
57
|
+
return null;
|
|
58
|
+
}
|
|
59
|
+
const override = process.env.IW_LOG_FILE?.trim();
|
|
60
|
+
if (override) {
|
|
61
|
+
resolvedPath = override;
|
|
62
|
+
return resolvedPath;
|
|
63
|
+
}
|
|
64
|
+
try {
|
|
65
|
+
const cfg = getConfig();
|
|
66
|
+
const day = new Date().toISOString().slice(0, 10); // YYYY-MM-DD
|
|
67
|
+
resolvedPath = join(cfg.keystoreDir, "logs", `iw-mcp-${day}.jsonl`);
|
|
68
|
+
}
|
|
69
|
+
catch {
|
|
70
|
+
resolvedPath = join(".", "iw-mcp-logs", `iw-mcp-${new Date().toISOString().slice(0, 10)}.jsonl`);
|
|
71
|
+
}
|
|
72
|
+
return resolvedPath;
|
|
73
|
+
}
|
|
74
|
+
function ensureDir(filePath) {
|
|
75
|
+
const dir = dirname(filePath);
|
|
76
|
+
if (!existsSync(dir))
|
|
77
|
+
mkdirSync(dir, { recursive: true });
|
|
78
|
+
}
|
|
79
|
+
export function newCorrelationId(prefix = "req") {
|
|
80
|
+
return `${prefix}_${randomUUID().replace(/-/g, "").slice(0, 16)}`;
|
|
81
|
+
}
|
|
82
|
+
/** Walk Error.cause chains (undici nests codes here). */
|
|
83
|
+
export function errorDetails(err, depth = 0) {
|
|
84
|
+
if (err == null)
|
|
85
|
+
return { value: err };
|
|
86
|
+
if (!(err instanceof Error))
|
|
87
|
+
return { value: String(err) };
|
|
88
|
+
const out = {
|
|
89
|
+
name: err.name,
|
|
90
|
+
message: err.message,
|
|
91
|
+
};
|
|
92
|
+
const any = err;
|
|
93
|
+
if (any.code)
|
|
94
|
+
out.code = any.code;
|
|
95
|
+
if (any.status != null)
|
|
96
|
+
out.status = any.status;
|
|
97
|
+
if (any.errno != null)
|
|
98
|
+
out.errno = any.errno;
|
|
99
|
+
if (any.syscall)
|
|
100
|
+
out.syscall = any.syscall;
|
|
101
|
+
if (any.address)
|
|
102
|
+
out.address = any.address;
|
|
103
|
+
if (any.port != null)
|
|
104
|
+
out.port = any.port;
|
|
105
|
+
if (typeof any.body === "string")
|
|
106
|
+
out.bodyPreview = truncate(any.body, 800);
|
|
107
|
+
if (any.cause != null && depth < 6)
|
|
108
|
+
out.cause = errorDetails(any.cause, depth + 1);
|
|
109
|
+
if (err.stack)
|
|
110
|
+
out.stack = err.stack.split("\n").slice(0, 12);
|
|
111
|
+
return out;
|
|
112
|
+
}
|
|
113
|
+
export function truncate(s, max = 2000) {
|
|
114
|
+
if (s.length <= max)
|
|
115
|
+
return s;
|
|
116
|
+
return `${s.slice(0, max)}…(+${s.length - max} chars)`;
|
|
117
|
+
}
|
|
118
|
+
export function redactHeaders(headers) {
|
|
119
|
+
if (!headers)
|
|
120
|
+
return undefined;
|
|
121
|
+
const out = {};
|
|
122
|
+
const entries = headers instanceof Headers
|
|
123
|
+
? [...headers.entries()]
|
|
124
|
+
: Array.isArray(headers)
|
|
125
|
+
? headers
|
|
126
|
+
: Object.entries(headers);
|
|
127
|
+
for (const [k, v] of entries) {
|
|
128
|
+
out[k] = SENSITIVE_HEADER.test(k) ? redactValue(String(v)) : String(v);
|
|
129
|
+
}
|
|
130
|
+
return out;
|
|
131
|
+
}
|
|
132
|
+
function redactValue(v) {
|
|
133
|
+
if (!v)
|
|
134
|
+
return "<empty>";
|
|
135
|
+
if (v.length <= 12)
|
|
136
|
+
return "<redacted>";
|
|
137
|
+
return `${v.slice(0, 6)}…${v.slice(-4)} (len=${v.length})`;
|
|
138
|
+
}
|
|
139
|
+
/** Deep-redact known secret keys; truncate long strings. */
|
|
140
|
+
export function sanitize(value, depth = 0) {
|
|
141
|
+
if (value == null)
|
|
142
|
+
return value;
|
|
143
|
+
if (depth > 8)
|
|
144
|
+
return "<max-depth>";
|
|
145
|
+
if (typeof value === "string") {
|
|
146
|
+
if (value.length > 400)
|
|
147
|
+
return truncate(value, 400);
|
|
148
|
+
return value;
|
|
149
|
+
}
|
|
150
|
+
if (typeof value === "number" || typeof value === "boolean")
|
|
151
|
+
return value;
|
|
152
|
+
if (typeof value === "bigint")
|
|
153
|
+
return value.toString();
|
|
154
|
+
if (Array.isArray(value)) {
|
|
155
|
+
if (value.length > 40) {
|
|
156
|
+
return [
|
|
157
|
+
...value.slice(0, 20).map((v) => sanitize(v, depth + 1)),
|
|
158
|
+
`<…${value.length - 20} more>`,
|
|
159
|
+
];
|
|
160
|
+
}
|
|
161
|
+
return value.map((v) => sanitize(v, depth + 1));
|
|
162
|
+
}
|
|
163
|
+
if (typeof value === "object") {
|
|
164
|
+
const out = {};
|
|
165
|
+
for (const [k, v] of Object.entries(value)) {
|
|
166
|
+
if (SENSITIVE_KEY.test(k)) {
|
|
167
|
+
out[k] =
|
|
168
|
+
typeof v === "string"
|
|
169
|
+
? redactValue(v)
|
|
170
|
+
: v == null
|
|
171
|
+
? v
|
|
172
|
+
: `<redacted ${typeof v}>`;
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
out[k] = sanitize(v, depth + 1);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
return out;
|
|
179
|
+
}
|
|
180
|
+
return String(value);
|
|
181
|
+
}
|
|
182
|
+
/** Compact summary of a JSON/text body for logs (sizes + key fields). */
|
|
183
|
+
export function summarizeBody(body) {
|
|
184
|
+
if (body == null || body === "")
|
|
185
|
+
return undefined;
|
|
186
|
+
const text = typeof body === "string" ? body : safeJson(body);
|
|
187
|
+
const out = {
|
|
188
|
+
bytes: Buffer.byteLength(text, "utf8"),
|
|
189
|
+
chars: text.length,
|
|
190
|
+
};
|
|
191
|
+
try {
|
|
192
|
+
const parsed = typeof body === "string" ? JSON.parse(body) : body;
|
|
193
|
+
if (parsed && typeof parsed === "object") {
|
|
194
|
+
out.keys = Object.keys(parsed);
|
|
195
|
+
const p = parsed;
|
|
196
|
+
if (p.fromAddress)
|
|
197
|
+
out.fromAddress = p.fromAddress;
|
|
198
|
+
if (p.toAddress)
|
|
199
|
+
out.toAddress = p.toAddress;
|
|
200
|
+
if (p.amount != null)
|
|
201
|
+
out.amount = p.amount;
|
|
202
|
+
if (p.tokenAddress)
|
|
203
|
+
out.tokenAddress = p.tokenAddress;
|
|
204
|
+
if (p.network)
|
|
205
|
+
out.network = p.network;
|
|
206
|
+
if (Array.isArray(p.signedTransactions)) {
|
|
207
|
+
out.signedTransactions = p.signedTransactions.map((t, i) => {
|
|
208
|
+
const tx = t;
|
|
209
|
+
return {
|
|
210
|
+
i,
|
|
211
|
+
transactionId: tx.transactionId,
|
|
212
|
+
txID: tx.txID,
|
|
213
|
+
signatureLen: typeof tx.signature === "string" ? tx.signature.length : undefined,
|
|
214
|
+
txDataLen: typeof tx.txData === "string" ? tx.txData.length : undefined,
|
|
215
|
+
};
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
if (p.signedEstimateResult && typeof p.signedEstimateResult === "object") {
|
|
219
|
+
const se = p.signedEstimateResult;
|
|
220
|
+
const er = se.estimateResult;
|
|
221
|
+
out.signedEstimateResult = {
|
|
222
|
+
hasSignature: typeof se.signature === "string",
|
|
223
|
+
signatureLen: typeof se.signature === "string" ? se.signature.length : undefined,
|
|
224
|
+
traceId: se.traceId,
|
|
225
|
+
amount: er?.amount,
|
|
226
|
+
coinFee: er?.coinFee,
|
|
227
|
+
tokenFee: er?.tokenFee,
|
|
228
|
+
txsToSign: Array.isArray(er?.transactionsToSign)
|
|
229
|
+
? er.transactionsToSign.length
|
|
230
|
+
: undefined,
|
|
231
|
+
timeout: er?.timeout,
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
if (p.txHash)
|
|
235
|
+
out.txHash = p.txHash;
|
|
236
|
+
if (p.operationId)
|
|
237
|
+
out.operationId = p.operationId;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
catch {
|
|
241
|
+
out.preview = truncate(text, 300);
|
|
242
|
+
}
|
|
243
|
+
if (bodiesEnabled ?? (bodiesEnabled = envFlag("IW_LOG_BODIES", false))) {
|
|
244
|
+
out.body = sanitize(typeof body === "string" ? tryParse(body) : body);
|
|
245
|
+
}
|
|
246
|
+
return out;
|
|
247
|
+
}
|
|
248
|
+
function tryParse(s) {
|
|
249
|
+
try {
|
|
250
|
+
return JSON.parse(s);
|
|
251
|
+
}
|
|
252
|
+
catch {
|
|
253
|
+
return s;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
function safeJson(v) {
|
|
257
|
+
try {
|
|
258
|
+
return JSON.stringify(v);
|
|
259
|
+
}
|
|
260
|
+
catch {
|
|
261
|
+
return String(v);
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
export function log(level, event, data) {
|
|
265
|
+
if (!isLogEnabled())
|
|
266
|
+
return;
|
|
267
|
+
if (LEVEL_RANK[level] < LEVEL_RANK[resolveMinLevel()])
|
|
268
|
+
return;
|
|
269
|
+
const file = getLogFilePath();
|
|
270
|
+
if (!file)
|
|
271
|
+
return;
|
|
272
|
+
const safeData = sanitize(data ?? {}) ?? {};
|
|
273
|
+
const line = JSON.stringify({
|
|
274
|
+
ts: new Date().toISOString(),
|
|
275
|
+
level,
|
|
276
|
+
event,
|
|
277
|
+
pid: process.pid,
|
|
278
|
+
...safeData,
|
|
279
|
+
});
|
|
280
|
+
try {
|
|
281
|
+
ensureDir(file);
|
|
282
|
+
appendFileSync(file, line + "\n", "utf8");
|
|
283
|
+
}
|
|
284
|
+
catch (e) {
|
|
285
|
+
if (!warnedOnce) {
|
|
286
|
+
warnedOnce = true;
|
|
287
|
+
process.stderr.write(`[ironwallet-mcp] failed to write log file ${file}: ${e instanceof Error ? e.message : String(e)}\n`);
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
if (stderrMirror ?? (stderrMirror = envFlag("IW_LOG_STDERR", false))) {
|
|
291
|
+
process.stderr.write(line + "\n");
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
export function logInfo(event, data) {
|
|
295
|
+
log("info", event, data);
|
|
296
|
+
}
|
|
297
|
+
export function logDebug(event, data) {
|
|
298
|
+
log("debug", event, data);
|
|
299
|
+
}
|
|
300
|
+
export function logWarn(event, data) {
|
|
301
|
+
log("warn", event, data);
|
|
302
|
+
}
|
|
303
|
+
export function logError(event, err, data) {
|
|
304
|
+
log("error", event, { ...data, error: errorDetails(err) });
|
|
305
|
+
}
|
|
306
|
+
/** One-shot banner so operators know where logs go. */
|
|
307
|
+
export function logStartupBanner(extra) {
|
|
308
|
+
const file = getLogFilePath();
|
|
309
|
+
if (!file) {
|
|
310
|
+
process.stderr.write("[ironwallet-mcp] file logging disabled\n");
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
logInfo("process.start", {
|
|
314
|
+
logFile: file,
|
|
315
|
+
logLevel: resolveMinLevel(),
|
|
316
|
+
logBodies: envFlag("IW_LOG_BODIES", false),
|
|
317
|
+
node: process.version,
|
|
318
|
+
platform: process.platform,
|
|
319
|
+
...extra,
|
|
320
|
+
});
|
|
321
|
+
process.stderr.write(`[ironwallet-mcp] logging to ${file}\n`);
|
|
322
|
+
}
|
|
323
|
+
//# sourceMappingURL=log.js.map
|
package/dist/log.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log.js","sourceRoot":"","sources":["../src/log.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Keystore wrapping secret. Generated on first use and stored under
|
|
3
|
+
* ~/.ironwallet-mcp/. IW_PASSPHRASE overrides when set to a real value.
|
|
4
|
+
*/
|
|
5
|
+
import { resolveKeystorePassphrase } from "./local-secrets.js";
|
|
6
|
+
/** Env override, else local file, else generate. */
|
|
7
|
+
export function requirePassphrase() {
|
|
8
|
+
return resolveKeystorePassphrase();
|
|
9
|
+
}
|
|
10
|
+
//# sourceMappingURL=passphrase.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"passphrase.js","sourceRoot":"","sources":["../src/passphrase.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC;AAE/D,oDAAoD;AACpD,MAAM,UAAU,iBAAiB;IAC/B,OAAO,yBAAyB,EAAE,CAAC;AACrC,CAAC"}
|
package/dist/policy.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Optional per-wallet spending policy. Disabled by default (sends autonomously).
|
|
3
|
+
* When `policy.enabled` is set, both `send_transfer` and `execute_swap` check it
|
|
4
|
+
* before signing.
|
|
5
|
+
*/
|
|
6
|
+
import type { WalletEntry } from "./keystore/types.js";
|
|
7
|
+
import type { NetworkId } from "./config.js";
|
|
8
|
+
export interface PolicyCheck {
|
|
9
|
+
kind: "transfer" | "swap";
|
|
10
|
+
network: NetworkId;
|
|
11
|
+
/** Decimal string in asset units. Required to enforce `maxPerTx`. */
|
|
12
|
+
amount?: string;
|
|
13
|
+
/** Transfer destination. Ignored for swaps. */
|
|
14
|
+
toAddress?: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Compare two non-negative decimal strings without floating point.
|
|
18
|
+
* Returns < 0 if a < b, 0 if equal, > 0 if a > b.
|
|
19
|
+
*/
|
|
20
|
+
export declare function compareDecimalAmount(a: string, b: string): number;
|
|
21
|
+
/** Throws with a clear message if the operation violates the wallet policy. */
|
|
22
|
+
export declare function enforcePolicy(entry: WalletEntry, check: PolicyCheck): void;
|
package/dist/policy.js
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Optional per-wallet spending policy. Disabled by default (sends autonomously).
|
|
3
|
+
* When `policy.enabled` is set, both `send_transfer` and `execute_swap` check it
|
|
4
|
+
* before signing.
|
|
5
|
+
*/
|
|
6
|
+
import { normalizeAddress } from "./wallet/derive.js";
|
|
7
|
+
import { logInfo, logWarn } from "./log.js";
|
|
8
|
+
/**
|
|
9
|
+
* Compare two non-negative decimal strings without floating point.
|
|
10
|
+
* Returns < 0 if a < b, 0 if equal, > 0 if a > b.
|
|
11
|
+
*/
|
|
12
|
+
export function compareDecimalAmount(a, b) {
|
|
13
|
+
const pa = parseNonNegativeDecimal(a);
|
|
14
|
+
const pb = parseNonNegativeDecimal(b);
|
|
15
|
+
if (pa.int !== pb.int)
|
|
16
|
+
return pa.int < pb.int ? -1 : 1;
|
|
17
|
+
const len = Math.max(pa.frac.length, pb.frac.length);
|
|
18
|
+
const fa = pa.frac.padEnd(len, "0");
|
|
19
|
+
const fb = pb.frac.padEnd(len, "0");
|
|
20
|
+
if (fa === fb)
|
|
21
|
+
return 0;
|
|
22
|
+
return fa < fb ? -1 : 1;
|
|
23
|
+
}
|
|
24
|
+
function parseNonNegativeDecimal(raw) {
|
|
25
|
+
const t = raw.trim();
|
|
26
|
+
if (!/^\d+(\.\d+)?$/.test(t)) {
|
|
27
|
+
throw new Error(`Invalid decimal amount "${raw}".`);
|
|
28
|
+
}
|
|
29
|
+
const [intPart, fracPart = ""] = t.split(".");
|
|
30
|
+
return { int: BigInt(intPart), frac: fracPart };
|
|
31
|
+
}
|
|
32
|
+
/** Throws with a clear message if the operation violates the wallet policy. */
|
|
33
|
+
export function enforcePolicy(entry, check) {
|
|
34
|
+
const policy = entry.policy;
|
|
35
|
+
if (!policy || !policy.enabled) {
|
|
36
|
+
logInfo("policy.skip", { wallet: entry.name, reason: "disabled_or_absent" });
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
logInfo("policy.check", {
|
|
40
|
+
wallet: entry.name,
|
|
41
|
+
kind: check.kind,
|
|
42
|
+
network: check.network,
|
|
43
|
+
toAddress: check.toAddress,
|
|
44
|
+
amount: check.amount,
|
|
45
|
+
readOnly: policy.readOnly,
|
|
46
|
+
maxPerTx: policy.maxPerTx,
|
|
47
|
+
allowedRecipients: policy.allowedRecipients?.length ?? 0,
|
|
48
|
+
});
|
|
49
|
+
if (policy.readOnly) {
|
|
50
|
+
logWarn("policy.reject", {
|
|
51
|
+
wallet: entry.name,
|
|
52
|
+
kind: check.kind,
|
|
53
|
+
reason: "read_only",
|
|
54
|
+
});
|
|
55
|
+
throw new Error(check.kind === "swap"
|
|
56
|
+
? `Wallet "${entry.name}" is read-only; swaps are disabled by policy.`
|
|
57
|
+
: `Wallet "${entry.name}" is read-only; sending is disabled by policy.`);
|
|
58
|
+
}
|
|
59
|
+
if (check.amount !== undefined && policy.maxPerTx !== undefined && policy.maxPerTx !== "") {
|
|
60
|
+
let cmp;
|
|
61
|
+
try {
|
|
62
|
+
cmp = compareDecimalAmount(check.amount, policy.maxPerTx);
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
throw new Error(`Cannot enforce maxPerTx for wallet "${entry.name}": amounts must be non-negative decimals (got amount=${check.amount}, maxPerTx=${policy.maxPerTx}).`);
|
|
66
|
+
}
|
|
67
|
+
if (cmp > 0) {
|
|
68
|
+
logWarn("policy.reject", {
|
|
69
|
+
wallet: entry.name,
|
|
70
|
+
kind: check.kind,
|
|
71
|
+
reason: "max_per_tx",
|
|
72
|
+
amount: check.amount,
|
|
73
|
+
maxPerTx: policy.maxPerTx,
|
|
74
|
+
});
|
|
75
|
+
throw new Error(`Amount ${check.amount} exceeds per-transaction limit ${policy.maxPerTx} for wallet "${entry.name}".`);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if (policy.allowedRecipients && policy.allowedRecipients.length > 0) {
|
|
79
|
+
if (check.kind === "swap") {
|
|
80
|
+
logWarn("policy.reject", {
|
|
81
|
+
wallet: entry.name,
|
|
82
|
+
kind: "swap",
|
|
83
|
+
reason: "recipient_allow_list_blocks_swap",
|
|
84
|
+
});
|
|
85
|
+
throw new Error(`Wallet "${entry.name}" has a recipient allow-list; swaps are disabled by policy because the swap router is not a whitelisted transfer recipient.`);
|
|
86
|
+
}
|
|
87
|
+
if (!check.toAddress) {
|
|
88
|
+
throw new Error(`Wallet "${entry.name}" has a recipient allow-list; a destination address is required.`);
|
|
89
|
+
}
|
|
90
|
+
const target = normalizeAddress(check.network, check.toAddress);
|
|
91
|
+
const allowed = policy.allowedRecipients.some((a) => normalizeAddress(check.network, a) === target);
|
|
92
|
+
if (!allowed) {
|
|
93
|
+
logWarn("policy.reject", {
|
|
94
|
+
wallet: entry.name,
|
|
95
|
+
kind: "transfer",
|
|
96
|
+
reason: "recipient_not_whitelisted",
|
|
97
|
+
toAddress: check.toAddress,
|
|
98
|
+
});
|
|
99
|
+
throw new Error(`Recipient ${check.toAddress} is not in the whitelist for wallet "${entry.name}".`);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
logInfo("policy.ok", {
|
|
103
|
+
wallet: entry.name,
|
|
104
|
+
kind: check.kind,
|
|
105
|
+
network: check.network,
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=policy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy.js","sourceRoot":"","sources":["../src/policy.ts"],"names":[],"mappings":"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"}
|
package/dist/server.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP stdio server. Launched by the MCP client (Cursor / Claude Desktop) per
|
|
3
|
+
* the mcp.json entry. Keystore passphrase and relay API key are created on
|
|
4
|
+
* first launch under ~/.ironwallet-mcp/ unless overridden by env.
|
|
5
|
+
*/
|
|
6
|
+
export declare function serve(): Promise<void>;
|
package/dist/server.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP stdio server. Launched by the MCP client (Cursor / Claude Desktop) per
|
|
3
|
+
* the mcp.json entry. Keystore passphrase and relay API key are created on
|
|
4
|
+
* first launch under ~/.ironwallet-mcp/ unless overridden by env.
|
|
5
|
+
*/
|
|
6
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
7
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
8
|
+
import { registerTools } from "./tools/index.js";
|
|
9
|
+
import { getConfig, packageVersion } from "./config.js";
|
|
10
|
+
import { logStartupBanner } from "./log.js";
|
|
11
|
+
export async function serve() {
|
|
12
|
+
const cfg = getConfig();
|
|
13
|
+
const server = new McpServer({
|
|
14
|
+
name: "ironwallet",
|
|
15
|
+
version: packageVersion(),
|
|
16
|
+
}, {
|
|
17
|
+
instructions: [
|
|
18
|
+
"Local Ironwallet hot wallet. Keys never leave this machine. There is no extra confirmation UI. Prefer a dedicated wallet with limited balance.",
|
|
19
|
+
"Never print, request, or invent recovery phrases or private keys. No tool accepts or returns a seed. Create/import/backup only via create_wallets backup_url or open_wallet_manager in the local browser.",
|
|
20
|
+
"If there is no wallet yet, create_wallets or open_wallet_manager first.",
|
|
21
|
+
"Transfer: list_wallets / get_balance → estimate_transfer (optional) → send_transfer. On timeout poll get_operation_status; do not resubmit blindly. send_transfer may reduce the amount so the fee fits.",
|
|
22
|
+
"Swap: list_swap_networks → list_swap_assets (copy network/symbol/address/decimals from the catalog; do not invent token addresses; omit address only for native coins) → estimate_swap or execute_swap. Quotes expire. maxMode: true sells as much as the service allows. After execute, poll get_swap_status; if execute times out, poll before retrying.",
|
|
23
|
+
].join("\n"),
|
|
24
|
+
});
|
|
25
|
+
registerTools(server);
|
|
26
|
+
// Never write logs to stdout — that stream carries the JSON-RPC protocol.
|
|
27
|
+
process.stderr.write(`[ironwallet-mcp] starting (relay=${cfg.relayUrl})\n`);
|
|
28
|
+
logStartupBanner({
|
|
29
|
+
relayUrl: cfg.relayUrl,
|
|
30
|
+
httpTimeoutMs: cfg.httpTimeoutMs,
|
|
31
|
+
httpForwardTimeoutMs: cfg.httpForwardTimeoutMs,
|
|
32
|
+
httpRetries: cfg.httpRetries,
|
|
33
|
+
keystoreDir: cfg.keystoreDir,
|
|
34
|
+
});
|
|
35
|
+
const transport = new StdioServerTransport();
|
|
36
|
+
await server.connect(transport);
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=server.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,yCAAyC,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,2CAA2C,CAAC;AACjF,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAC;AAE5C,MAAM,CAAC,KAAK,UAAU,KAAK;IACzB,MAAM,GAAG,GAAG,SAAS,EAAE,CAAC;IACxB,MAAM,MAAM,GAAG,IAAI,SAAS,CAC1B;QACE,IAAI,EAAE,YAAY;QAClB,OAAO,EAAE,cAAc,EAAE;KAC1B,EACD;QACE,YAAY,EAAE;YACZ,gJAAgJ;YAChJ,2MAA2M;YAC3M,yEAAyE;YACzE,0MAA0M;YAC1M,4VAA4V;SAC7V,CAAC,IAAI,CAAC,IAAI,CAAC;KACb,CACF,CAAC;IAEF,aAAa,CAAC,MAAM,CAAC,CAAC;IAEtB,0EAA0E;IAC1E,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,oCAAoC,GAAG,CAAC,QAAQ,KAAK,CACtD,CAAC;IACF,gBAAgB,CAAC;QACf,QAAQ,EAAE,GAAG,CAAC,QAAQ;QACtB,aAAa,EAAE,GAAG,CAAC,aAAa;QAChC,oBAAoB,EAAE,GAAG,CAAC,oBAAoB;QAC9C,WAAW,EAAE,GAAG,CAAC,WAAW;QAC5B,WAAW,EAAE,GAAG,CAAC,WAAW;KAC7B,CAAC,CAAC;IAEH,MAAM,SAAS,GAAG,IAAI,oBAAoB,EAAE,CAAC;IAC7C,MAAM,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;AAClC,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UTXO forward signing for Bitcoin / Litecoin / Dogecoin, matching the shared
|
|
3
|
+
* hd-wallet-service relay contract (and mobile BitcoinTransactionSigner):
|
|
4
|
+
*
|
|
5
|
+
* - `txData` = unsigned raw tx, lowercase hex.
|
|
6
|
+
* - `extraData` = JSON array of per-input UTXO info; utxos[0].scriptPubKey (hex)
|
|
7
|
+
* and utxos[0].value (sats / litoshis / koinu) drive the sighash.
|
|
8
|
+
* - SegWit P2WPKH (BTC BIP-84, LTC BIP-84): BIP-143 witness, SIGHASH_ALL.
|
|
9
|
+
* - Legacy P2PKH (DOGE BIP-44): classic sighash + scriptSig. Signed via
|
|
10
|
+
* `allowLegacyWitnessUtxo` using scriptPubKey+value from extraData (relay
|
|
11
|
+
* does not provide full prev txs).
|
|
12
|
+
* - Forward payload: `signature` = full signed raw tx hex, original `txData`,
|
|
13
|
+
* computed `txID`.
|
|
14
|
+
*/
|
|
15
|
+
import type { SignContext, SignedTransaction, TransactionToSign } from "./types.js";
|
|
16
|
+
export declare function signBitcoin(ctx: SignContext, txs: TransactionToSign[]): SignedTransaction[];
|
|
17
|
+
export declare function signLitecoin(ctx: SignContext, txs: TransactionToSign[]): SignedTransaction[];
|
|
18
|
+
export declare function signDoge(ctx: SignContext, txs: TransactionToSign[]): SignedTransaction[];
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* UTXO forward signing for Bitcoin / Litecoin / Dogecoin, matching the shared
|
|
3
|
+
* hd-wallet-service relay contract (and mobile BitcoinTransactionSigner):
|
|
4
|
+
*
|
|
5
|
+
* - `txData` = unsigned raw tx, lowercase hex.
|
|
6
|
+
* - `extraData` = JSON array of per-input UTXO info; utxos[0].scriptPubKey (hex)
|
|
7
|
+
* and utxos[0].value (sats / litoshis / koinu) drive the sighash.
|
|
8
|
+
* - SegWit P2WPKH (BTC BIP-84, LTC BIP-84): BIP-143 witness, SIGHASH_ALL.
|
|
9
|
+
* - Legacy P2PKH (DOGE BIP-44): classic sighash + scriptSig. Signed via
|
|
10
|
+
* `allowLegacyWitnessUtxo` using scriptPubKey+value from extraData (relay
|
|
11
|
+
* does not provide full prev txs).
|
|
12
|
+
* - Forward payload: `signature` = full signed raw tx hex, original `txData`,
|
|
13
|
+
* computed `txID`.
|
|
14
|
+
*/
|
|
15
|
+
import * as btc from "@scure/btc-signer";
|
|
16
|
+
import { hex } from "@scure/base";
|
|
17
|
+
import { logInfo } from "../log.js";
|
|
18
|
+
function hexToBytes(h) {
|
|
19
|
+
return hex.decode(h.replace(/^0x/, "").toLowerCase());
|
|
20
|
+
}
|
|
21
|
+
export function signBitcoin(ctx, txs) {
|
|
22
|
+
return signUtxo(ctx, txs, "bitcoin");
|
|
23
|
+
}
|
|
24
|
+
export function signLitecoin(ctx, txs) {
|
|
25
|
+
return signUtxo(ctx, txs, "litecoin");
|
|
26
|
+
}
|
|
27
|
+
export function signDoge(ctx, txs) {
|
|
28
|
+
return signUtxo(ctx, txs, "doge");
|
|
29
|
+
}
|
|
30
|
+
function signUtxo(ctx, txs, network) {
|
|
31
|
+
const priv = hexToBytes(ctx.privateKey);
|
|
32
|
+
const signed = [];
|
|
33
|
+
logInfo(`sign.${network}.start`, { address: ctx.address, txCount: txs.length });
|
|
34
|
+
for (const item of txs) {
|
|
35
|
+
if (!item.txData)
|
|
36
|
+
throw new Error(`${network} transactionToSign has no txData.`);
|
|
37
|
+
if (!item.extraData) {
|
|
38
|
+
throw new Error(`${network} transactionToSign has no extraData (UTXO info).`);
|
|
39
|
+
}
|
|
40
|
+
const tx = btc.Transaction.fromRaw(hexToBytes(item.txData), {
|
|
41
|
+
allowUnknownInputs: true,
|
|
42
|
+
allowUnknownOutputs: true,
|
|
43
|
+
disableScriptCheck: true,
|
|
44
|
+
// DOGE (and any legacy P2PKH input) signs from scriptPubKey+value alone.
|
|
45
|
+
allowLegacyWitnessUtxo: true,
|
|
46
|
+
lowR: true,
|
|
47
|
+
});
|
|
48
|
+
const extra = JSON.parse(item.extraData);
|
|
49
|
+
const byIndex = new Map();
|
|
50
|
+
extra.forEach((e, i) => {
|
|
51
|
+
const utxo = e.utxos?.[0];
|
|
52
|
+
if (utxo)
|
|
53
|
+
byIndex.set(e.index ?? i, utxo);
|
|
54
|
+
});
|
|
55
|
+
for (let i = 0; i < tx.inputsLength; i++) {
|
|
56
|
+
const utxo = byIndex.get(i);
|
|
57
|
+
if (!utxo)
|
|
58
|
+
throw new Error(`No UTXO info for ${network} input ${i}.`);
|
|
59
|
+
tx.updateInput(i, {
|
|
60
|
+
witnessUtxo: {
|
|
61
|
+
script: hexToBytes(utxo.scriptPubKey),
|
|
62
|
+
amount: BigInt(utxo.value),
|
|
63
|
+
},
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
tx.sign(priv);
|
|
67
|
+
tx.finalize();
|
|
68
|
+
logInfo(`sign.${network}.tx`, {
|
|
69
|
+
transactionId: item.transactionId,
|
|
70
|
+
txID: tx.id,
|
|
71
|
+
inputs: tx.inputsLength,
|
|
72
|
+
outputs: tx.outputsLength,
|
|
73
|
+
signedLen: tx.hex.length,
|
|
74
|
+
});
|
|
75
|
+
signed.push({
|
|
76
|
+
signature: tx.hex,
|
|
77
|
+
txData: item.txData,
|
|
78
|
+
txID: tx.id,
|
|
79
|
+
transactionId: item.transactionId,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
return signed;
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=bitcoin.js.map
|