chainlesschain 0.47.9 → 0.51.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/bin/chainlesschain.js +0 -0
- package/package.json +1 -1
- package/src/assets/web-panel/.build-hash +1 -1
- package/src/assets/web-panel/assets/{AppLayout-6SPt_8Y_.js → AppLayout-Rvi759IS.js} +1 -1
- package/src/assets/web-panel/assets/Dashboard-BS-tzGNj.css +1 -0
- package/src/assets/web-panel/assets/{Dashboard-Br7kCwKJ.js → Dashboard-DBhFxXYQ.js} +2 -2
- package/src/assets/web-panel/assets/{index-tN-8TosE.js → index-uL0cZ8N_.js} +2 -2
- package/src/assets/web-panel/index.html +2 -2
- package/src/commands/codegen.js +303 -0
- package/src/commands/collab.js +482 -0
- package/src/commands/crosschain.js +382 -0
- package/src/commands/dbevo.js +388 -0
- package/src/commands/dev.js +411 -0
- package/src/commands/federation.js +427 -0
- package/src/commands/fusion.js +332 -0
- package/src/commands/governance.js +505 -0
- package/src/commands/hardening.js +110 -0
- package/src/commands/incentive.js +373 -0
- package/src/commands/inference.js +304 -0
- package/src/commands/infra.js +361 -0
- package/src/commands/ipfs.js +392 -0
- package/src/commands/kg.js +371 -0
- package/src/commands/marketplace.js +326 -0
- package/src/commands/mcp.js +97 -18
- package/src/commands/multimodal.js +404 -0
- package/src/commands/nlprog.js +329 -0
- package/src/commands/ops.js +408 -0
- package/src/commands/perception.js +385 -0
- package/src/commands/pqc.js +34 -0
- package/src/commands/privacy.js +345 -0
- package/src/commands/quantization.js +280 -0
- package/src/commands/recommend.js +336 -0
- package/src/commands/reputation.js +349 -0
- package/src/commands/runtime.js +500 -0
- package/src/commands/sla.js +352 -0
- package/src/commands/stress.js +252 -0
- package/src/commands/tech.js +268 -0
- package/src/commands/tenant.js +576 -0
- package/src/commands/trust.js +366 -0
- package/src/harness/mcp-client.js +330 -54
- package/src/index.js +118 -0
- package/src/lib/aiops.js +523 -0
- package/src/lib/autonomous-developer.js +524 -0
- package/src/lib/code-agent.js +442 -0
- package/src/lib/collaboration-governance.js +556 -0
- package/src/lib/community-governance.js +649 -0
- package/src/lib/content-recommendation.js +600 -0
- package/src/lib/cross-chain.js +669 -0
- package/src/lib/dbevo.js +669 -0
- package/src/lib/decentral-infra.js +445 -0
- package/src/lib/federation-hardening.js +587 -0
- package/src/lib/hardening-manager.js +409 -0
- package/src/lib/inference-network.js +407 -0
- package/src/lib/ipfs-storage.js +575 -0
- package/src/lib/knowledge-graph.js +530 -0
- package/src/lib/mcp-client.js +3 -0
- package/src/lib/multimodal.js +725 -0
- package/src/lib/nl-programming.js +595 -0
- package/src/lib/perception.js +500 -0
- package/src/lib/pqc-manager.js +141 -9
- package/src/lib/privacy-computing.js +575 -0
- package/src/lib/protocol-fusion.js +535 -0
- package/src/lib/quantization.js +362 -0
- package/src/lib/reputation-optimizer.js +509 -0
- package/src/lib/skill-marketplace.js +397 -0
- package/src/lib/sla-manager.js +484 -0
- package/src/lib/stress-tester.js +383 -0
- package/src/lib/tech-learning-engine.js +651 -0
- package/src/lib/tenant-saas.js +831 -0
- package/src/lib/token-incentive.js +513 -0
- package/src/lib/trust-security.js +473 -0
- package/src/lib/universal-runtime.js +771 -0
- package/src/assets/web-panel/assets/Dashboard-CKeMmCoT.css +0 -1
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `cc crosschain` — CLI surface for Phase 89 Cross-Chain Interoperability.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { Command } from "commander";
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
SUPPORTED_CHAINS,
|
|
9
|
+
BRIDGE_STATUS,
|
|
10
|
+
SWAP_STATUS,
|
|
11
|
+
MESSAGE_STATUS,
|
|
12
|
+
DEFAULT_CONFIG,
|
|
13
|
+
ensureCrossChainTables,
|
|
14
|
+
bridgeAsset,
|
|
15
|
+
updateBridgeStatus,
|
|
16
|
+
getBridge,
|
|
17
|
+
listBridges,
|
|
18
|
+
initiateSwap,
|
|
19
|
+
claimSwap,
|
|
20
|
+
refundSwap,
|
|
21
|
+
getSwap,
|
|
22
|
+
revealSecret,
|
|
23
|
+
listSwaps,
|
|
24
|
+
sendMessage,
|
|
25
|
+
updateMessageStatus,
|
|
26
|
+
getMessage,
|
|
27
|
+
listMessages,
|
|
28
|
+
estimateFee,
|
|
29
|
+
getCrossChainStats,
|
|
30
|
+
} from "../lib/cross-chain.js";
|
|
31
|
+
|
|
32
|
+
function _dbFromCtx(cmd) {
|
|
33
|
+
const root = cmd?.parent?.parent ?? cmd?.parent;
|
|
34
|
+
return root?._db;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function registerCrossChainCommand(program) {
|
|
38
|
+
const cc = new Command("crosschain")
|
|
39
|
+
.description("Cross-chain interoperability (Phase 89)")
|
|
40
|
+
.hook("preAction", (thisCmd) => {
|
|
41
|
+
const db = _dbFromCtx(thisCmd);
|
|
42
|
+
if (db) ensureCrossChainTables(db);
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
/* ── Catalogs ────────────────────────────────────── */
|
|
46
|
+
|
|
47
|
+
cc.command("chains")
|
|
48
|
+
.description("List supported chains")
|
|
49
|
+
.option("--json", "JSON output")
|
|
50
|
+
.action((opts) => {
|
|
51
|
+
const chains = Object.values(SUPPORTED_CHAINS);
|
|
52
|
+
if (opts.json) return console.log(JSON.stringify(chains, null, 2));
|
|
53
|
+
for (const c of chains)
|
|
54
|
+
console.log(
|
|
55
|
+
` ${c.id.padEnd(12)} ${c.name.padEnd(18)} ${c.symbol} chainId=${c.chainId}`,
|
|
56
|
+
);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
cc.command("bridge-statuses")
|
|
60
|
+
.description("List bridge statuses")
|
|
61
|
+
.option("--json", "JSON output")
|
|
62
|
+
.action((opts) => {
|
|
63
|
+
const statuses = Object.values(BRIDGE_STATUS);
|
|
64
|
+
if (opts.json) return console.log(JSON.stringify(statuses, null, 2));
|
|
65
|
+
for (const s of statuses) console.log(` ${s}`);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
cc.command("swap-statuses")
|
|
69
|
+
.description("List swap statuses")
|
|
70
|
+
.option("--json", "JSON output")
|
|
71
|
+
.action((opts) => {
|
|
72
|
+
const statuses = Object.values(SWAP_STATUS);
|
|
73
|
+
if (opts.json) return console.log(JSON.stringify(statuses, null, 2));
|
|
74
|
+
for (const s of statuses) console.log(` ${s}`);
|
|
75
|
+
});
|
|
76
|
+
|
|
77
|
+
/* ── Asset Bridge ────────────────────────────────── */
|
|
78
|
+
|
|
79
|
+
cc.command("bridge <from-chain> <to-chain> <amount>")
|
|
80
|
+
.description("Bridge asset between chains")
|
|
81
|
+
.option("-a, --asset <asset>", "Asset name", "native")
|
|
82
|
+
.option("-s, --sender <address>", "Sender address")
|
|
83
|
+
.option("-r, --recipient <address>", "Recipient address")
|
|
84
|
+
.option("--json", "JSON output")
|
|
85
|
+
.action((fromChain, toChain, amount, opts) => {
|
|
86
|
+
const db = _dbFromCtx(cc);
|
|
87
|
+
const result = bridgeAsset(db, {
|
|
88
|
+
fromChain,
|
|
89
|
+
toChain,
|
|
90
|
+
asset: opts.asset,
|
|
91
|
+
amount: parseFloat(amount),
|
|
92
|
+
senderAddress: opts.sender,
|
|
93
|
+
recipientAddress: opts.recipient,
|
|
94
|
+
});
|
|
95
|
+
if (opts.json) return console.log(JSON.stringify(result, null, 2));
|
|
96
|
+
if (result.bridgeId)
|
|
97
|
+
console.log(`Bridge created: ${result.bridgeId} (fee: ${result.fee})`);
|
|
98
|
+
else console.log(`Failed: ${result.reason}`);
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
cc.command("bridge-status <bridge-id> <status>")
|
|
102
|
+
.description("Update bridge status")
|
|
103
|
+
.option("-t, --tx-hash <hash>", "Transaction hash")
|
|
104
|
+
.option("-e, --error <message>", "Error message")
|
|
105
|
+
.option("--json", "JSON output")
|
|
106
|
+
.action((bridgeId, status, opts) => {
|
|
107
|
+
const db = _dbFromCtx(cc);
|
|
108
|
+
const result = updateBridgeStatus(db, bridgeId, status, {
|
|
109
|
+
txHash: opts.txHash,
|
|
110
|
+
errorMessage: opts.error,
|
|
111
|
+
});
|
|
112
|
+
if (opts.json) return console.log(JSON.stringify(result, null, 2));
|
|
113
|
+
console.log(
|
|
114
|
+
result.updated ? "Bridge status updated." : `Failed: ${result.reason}`,
|
|
115
|
+
);
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
cc.command("bridge-show <bridge-id>")
|
|
119
|
+
.description("Show bridge details")
|
|
120
|
+
.option("--json", "JSON output")
|
|
121
|
+
.action((bridgeId, opts) => {
|
|
122
|
+
const db = _dbFromCtx(cc);
|
|
123
|
+
const b = getBridge(db, bridgeId);
|
|
124
|
+
if (!b) return console.log("Bridge not found.");
|
|
125
|
+
if (opts.json) return console.log(JSON.stringify(b, null, 2));
|
|
126
|
+
console.log(`ID: ${b.id}`);
|
|
127
|
+
console.log(`Route: ${b.from_chain} → ${b.to_chain}`);
|
|
128
|
+
console.log(`Asset: ${b.asset}`);
|
|
129
|
+
console.log(`Amount: ${b.amount}`);
|
|
130
|
+
console.log(`Fee: ${b.fee_amount}`);
|
|
131
|
+
console.log(`Status: ${b.status}`);
|
|
132
|
+
if (b.lock_tx_hash) console.log(`Lock TX: ${b.lock_tx_hash}`);
|
|
133
|
+
if (b.mint_tx_hash) console.log(`Mint TX: ${b.mint_tx_hash}`);
|
|
134
|
+
if (b.error_message) console.log(`Error: ${b.error_message}`);
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
cc.command("bridges")
|
|
138
|
+
.description("List bridge transactions")
|
|
139
|
+
.option("-f, --from <chain>", "Filter by source chain")
|
|
140
|
+
.option("-t, --to <chain>", "Filter by destination chain")
|
|
141
|
+
.option("-s, --status <status>", "Filter by status")
|
|
142
|
+
.option("--limit <n>", "Max results", parseInt)
|
|
143
|
+
.option("--json", "JSON output")
|
|
144
|
+
.action((opts) => {
|
|
145
|
+
const db = _dbFromCtx(cc);
|
|
146
|
+
const bridges = listBridges(db, {
|
|
147
|
+
fromChain: opts.from,
|
|
148
|
+
toChain: opts.to,
|
|
149
|
+
status: opts.status,
|
|
150
|
+
limit: opts.limit,
|
|
151
|
+
});
|
|
152
|
+
if (opts.json) return console.log(JSON.stringify(bridges, null, 2));
|
|
153
|
+
if (bridges.length === 0) return console.log("No bridges.");
|
|
154
|
+
for (const b of bridges) {
|
|
155
|
+
console.log(
|
|
156
|
+
` ${b.status.padEnd(12)} ${b.from_chain}→${b.to_chain} ${b.amount} ${b.asset} ${b.id.slice(0, 8)}`,
|
|
157
|
+
);
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
|
|
161
|
+
/* ── HTLC Atomic Swap ────────────────────────────── */
|
|
162
|
+
|
|
163
|
+
cc.command("swap <from-chain> <to-chain> <amount>")
|
|
164
|
+
.description("Initiate HTLC atomic swap")
|
|
165
|
+
.option("-a, --from-asset <asset>", "Source asset", "native")
|
|
166
|
+
.option("-b, --to-asset <asset>", "Target asset", "native")
|
|
167
|
+
.option("-c, --counterparty <address>", "Counterparty address")
|
|
168
|
+
.option("-t, --timeout <ms>", "Timeout in ms", parseInt)
|
|
169
|
+
.option("--json", "JSON output")
|
|
170
|
+
.action((fromChain, toChain, amount, opts) => {
|
|
171
|
+
const db = _dbFromCtx(cc);
|
|
172
|
+
const result = initiateSwap(db, {
|
|
173
|
+
fromChain,
|
|
174
|
+
toChain,
|
|
175
|
+
fromAsset: opts.fromAsset,
|
|
176
|
+
toAsset: opts.toAsset,
|
|
177
|
+
amount: parseFloat(amount),
|
|
178
|
+
counterpartyAddress: opts.counterparty,
|
|
179
|
+
timeoutMs: opts.timeout,
|
|
180
|
+
});
|
|
181
|
+
if (opts.json) return console.log(JSON.stringify(result, null, 2));
|
|
182
|
+
if (result.swapId) {
|
|
183
|
+
console.log(`Swap initiated: ${result.swapId}`);
|
|
184
|
+
console.log(`Hash lock: ${result.hashLock}`);
|
|
185
|
+
console.log(`Expires: ${new Date(result.expiresAt).toISOString()}`);
|
|
186
|
+
} else console.log(`Failed: ${result.reason}`);
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
cc.command("swap-claim <swap-id>")
|
|
190
|
+
.description("Claim a swap with secret")
|
|
191
|
+
.option("-s, --secret <hex>", "HTLC secret")
|
|
192
|
+
.option("-t, --tx-hash <hash>", "Claim transaction hash")
|
|
193
|
+
.option("--json", "JSON output")
|
|
194
|
+
.action((swapId, opts) => {
|
|
195
|
+
const db = _dbFromCtx(cc);
|
|
196
|
+
const result = claimSwap(db, swapId, {
|
|
197
|
+
secret: opts.secret,
|
|
198
|
+
txHash: opts.txHash,
|
|
199
|
+
});
|
|
200
|
+
if (opts.json) return console.log(JSON.stringify(result, null, 2));
|
|
201
|
+
console.log(
|
|
202
|
+
result.claimed ? "Swap claimed." : `Failed: ${result.reason}`,
|
|
203
|
+
);
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
cc.command("swap-refund <swap-id>")
|
|
207
|
+
.description("Refund a swap")
|
|
208
|
+
.option("-t, --tx-hash <hash>", "Refund transaction hash")
|
|
209
|
+
.option("--json", "JSON output")
|
|
210
|
+
.action((swapId, opts) => {
|
|
211
|
+
const db = _dbFromCtx(cc);
|
|
212
|
+
const result = refundSwap(db, swapId, { txHash: opts.txHash });
|
|
213
|
+
if (opts.json) return console.log(JSON.stringify(result, null, 2));
|
|
214
|
+
console.log(
|
|
215
|
+
result.refunded ? "Swap refunded." : `Failed: ${result.reason}`,
|
|
216
|
+
);
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
cc.command("swap-show <swap-id>")
|
|
220
|
+
.description("Show swap details")
|
|
221
|
+
.option("--json", "JSON output")
|
|
222
|
+
.action((swapId, opts) => {
|
|
223
|
+
const db = _dbFromCtx(cc);
|
|
224
|
+
const s = getSwap(db, swapId);
|
|
225
|
+
if (!s) return console.log("Swap not found.");
|
|
226
|
+
if (opts.json) return console.log(JSON.stringify(s, null, 2));
|
|
227
|
+
console.log(`ID: ${s.id}`);
|
|
228
|
+
console.log(`Route: ${s.from_chain} → ${s.to_chain}`);
|
|
229
|
+
console.log(`Assets: ${s.from_asset} → ${s.to_asset}`);
|
|
230
|
+
console.log(`Amount: ${s.amount}`);
|
|
231
|
+
console.log(`Hash lock: ${s.hash_lock}`);
|
|
232
|
+
console.log(`Status: ${s.status}`);
|
|
233
|
+
console.log(`Expires: ${new Date(s.expires_at).toISOString()}`);
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
cc.command("swap-secret <swap-id>")
|
|
237
|
+
.description("Reveal swap secret (only after claim)")
|
|
238
|
+
.option("--json", "JSON output")
|
|
239
|
+
.action((swapId, opts) => {
|
|
240
|
+
const db = _dbFromCtx(cc);
|
|
241
|
+
const result = revealSecret(db, swapId);
|
|
242
|
+
if (!result)
|
|
243
|
+
return console.log("Secret unavailable (swap must be claimed).");
|
|
244
|
+
if (opts.json) return console.log(JSON.stringify(result, null, 2));
|
|
245
|
+
console.log(`Secret: ${result.secret}`);
|
|
246
|
+
console.log(`Hash lock: ${result.hashLock}`);
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
cc.command("swaps")
|
|
250
|
+
.description("List swaps")
|
|
251
|
+
.option("-f, --from <chain>", "Filter by source chain")
|
|
252
|
+
.option("-s, --status <status>", "Filter by status")
|
|
253
|
+
.option("--limit <n>", "Max results", parseInt)
|
|
254
|
+
.option("--json", "JSON output")
|
|
255
|
+
.action((opts) => {
|
|
256
|
+
const db = _dbFromCtx(cc);
|
|
257
|
+
const swaps = listSwaps(db, {
|
|
258
|
+
fromChain: opts.from,
|
|
259
|
+
status: opts.status,
|
|
260
|
+
limit: opts.limit,
|
|
261
|
+
});
|
|
262
|
+
if (opts.json) return console.log(JSON.stringify(swaps, null, 2));
|
|
263
|
+
if (swaps.length === 0) return console.log("No swaps.");
|
|
264
|
+
for (const s of swaps) {
|
|
265
|
+
console.log(
|
|
266
|
+
` ${s.status.padEnd(14)} ${s.from_chain}→${s.to_chain} ${s.amount} ${s.from_asset}→${s.to_asset} ${s.id.slice(0, 8)}`,
|
|
267
|
+
);
|
|
268
|
+
}
|
|
269
|
+
});
|
|
270
|
+
|
|
271
|
+
/* ── Cross-Chain Messages ────────────────────────── */
|
|
272
|
+
|
|
273
|
+
cc.command("send <from-chain> <to-chain>")
|
|
274
|
+
.description("Send cross-chain message")
|
|
275
|
+
.option("-p, --payload <text>", "Message payload")
|
|
276
|
+
.option("-c, --contract <address>", "Target contract address")
|
|
277
|
+
.option("--json", "JSON output")
|
|
278
|
+
.action((fromChain, toChain, opts) => {
|
|
279
|
+
const db = _dbFromCtx(cc);
|
|
280
|
+
const result = sendMessage(db, {
|
|
281
|
+
fromChain,
|
|
282
|
+
toChain,
|
|
283
|
+
payload: opts.payload,
|
|
284
|
+
targetContract: opts.contract,
|
|
285
|
+
});
|
|
286
|
+
if (opts.json) return console.log(JSON.stringify(result, null, 2));
|
|
287
|
+
if (result.messageId) console.log(`Message sent: ${result.messageId}`);
|
|
288
|
+
else console.log(`Failed: ${result.reason}`);
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
cc.command("msg-status <message-id> <status>")
|
|
292
|
+
.description("Update message status")
|
|
293
|
+
.option("-t, --tx-hash <hash>", "Transaction hash")
|
|
294
|
+
.option("--json", "JSON output")
|
|
295
|
+
.action((messageId, status, opts) => {
|
|
296
|
+
const db = _dbFromCtx(cc);
|
|
297
|
+
const result = updateMessageStatus(db, messageId, status, {
|
|
298
|
+
txHash: opts.txHash,
|
|
299
|
+
});
|
|
300
|
+
if (opts.json) return console.log(JSON.stringify(result, null, 2));
|
|
301
|
+
console.log(
|
|
302
|
+
result.updated ? "Message status updated." : `Failed: ${result.reason}`,
|
|
303
|
+
);
|
|
304
|
+
});
|
|
305
|
+
|
|
306
|
+
cc.command("msg-show <message-id>")
|
|
307
|
+
.description("Show message details")
|
|
308
|
+
.option("--json", "JSON output")
|
|
309
|
+
.action((messageId, opts) => {
|
|
310
|
+
const db = _dbFromCtx(cc);
|
|
311
|
+
const m = getMessage(db, messageId);
|
|
312
|
+
if (!m) return console.log("Message not found.");
|
|
313
|
+
if (opts.json) return console.log(JSON.stringify(m, null, 2));
|
|
314
|
+
console.log(`ID: ${m.id}`);
|
|
315
|
+
console.log(`Route: ${m.from_chain} → ${m.to_chain}`);
|
|
316
|
+
console.log(`Payload: ${m.payload}`);
|
|
317
|
+
console.log(`Status: ${m.status}`);
|
|
318
|
+
console.log(`Retries: ${m.retries}`);
|
|
319
|
+
if (m.target_contract) console.log(`Contract: ${m.target_contract}`);
|
|
320
|
+
});
|
|
321
|
+
|
|
322
|
+
cc.command("messages")
|
|
323
|
+
.description("List cross-chain messages")
|
|
324
|
+
.option("-f, --from <chain>", "Filter by source chain")
|
|
325
|
+
.option("-t, --to <chain>", "Filter by destination chain")
|
|
326
|
+
.option("-s, --status <status>", "Filter by status")
|
|
327
|
+
.option("--limit <n>", "Max results", parseInt)
|
|
328
|
+
.option("--json", "JSON output")
|
|
329
|
+
.action((opts) => {
|
|
330
|
+
const db = _dbFromCtx(cc);
|
|
331
|
+
const msgs = listMessages(db, {
|
|
332
|
+
fromChain: opts.from,
|
|
333
|
+
toChain: opts.to,
|
|
334
|
+
status: opts.status,
|
|
335
|
+
limit: opts.limit,
|
|
336
|
+
});
|
|
337
|
+
if (opts.json) return console.log(JSON.stringify(msgs, null, 2));
|
|
338
|
+
if (msgs.length === 0) return console.log("No messages.");
|
|
339
|
+
for (const m of msgs) {
|
|
340
|
+
console.log(
|
|
341
|
+
` ${m.status.padEnd(12)} ${m.from_chain}→${m.to_chain} ${m.id.slice(0, 8)}`,
|
|
342
|
+
);
|
|
343
|
+
}
|
|
344
|
+
});
|
|
345
|
+
|
|
346
|
+
/* ── Fee Estimation ──────────────────────────────── */
|
|
347
|
+
|
|
348
|
+
cc.command("estimate-fee <from-chain> <to-chain> <amount>")
|
|
349
|
+
.description("Estimate cross-chain bridge fee")
|
|
350
|
+
.option("--json", "JSON output")
|
|
351
|
+
.action((fromChain, toChain, amount, opts) => {
|
|
352
|
+
const result = estimateFee({
|
|
353
|
+
fromChain,
|
|
354
|
+
toChain,
|
|
355
|
+
amount: parseFloat(amount),
|
|
356
|
+
});
|
|
357
|
+
if (opts.json) return console.log(JSON.stringify(result, null, 2));
|
|
358
|
+
if (result.fee === null) return console.log(`Failed: ${result.reason}`);
|
|
359
|
+
console.log(`Estimated fee: $${result.fee} USD`);
|
|
360
|
+
console.log(` Source chain: $${result.breakdown.sourceFee}`);
|
|
361
|
+
console.log(` Dest chain: $${result.breakdown.destFee}`);
|
|
362
|
+
console.log(` Bridge fee: $${result.breakdown.bridgeFee}`);
|
|
363
|
+
});
|
|
364
|
+
|
|
365
|
+
/* ── Stats ───────────────────────────────────────── */
|
|
366
|
+
|
|
367
|
+
cc.command("stats")
|
|
368
|
+
.description("Cross-chain statistics")
|
|
369
|
+
.option("--json", "JSON output")
|
|
370
|
+
.action((opts) => {
|
|
371
|
+
const db = _dbFromCtx(cc);
|
|
372
|
+
const stats = getCrossChainStats(db);
|
|
373
|
+
if (opts.json) return console.log(JSON.stringify(stats, null, 2));
|
|
374
|
+
console.log(
|
|
375
|
+
`Bridges: ${stats.bridges.total} (volume: ${stats.bridges.totalVolume}, fees: ${stats.bridges.totalFees})`,
|
|
376
|
+
);
|
|
377
|
+
console.log(`Swaps: ${stats.swaps.total}`);
|
|
378
|
+
console.log(`Messages: ${stats.messages.total}`);
|
|
379
|
+
});
|
|
380
|
+
|
|
381
|
+
program.addCommand(cc);
|
|
382
|
+
}
|