chain-insights 0.28.0 → 0.35.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.
- package/README.md +11 -6
- package/dist/cli.cjs +108 -6
- package/dist/cli.mjs +108 -6
- package/dist/cli.mjs.map +1 -1
- package/dist/index.cjs +0 -2
- package/dist/index.d.cts +25 -71
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +25 -71
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -2
- package/dist/mcp-proxy.cjs +87 -15
- package/dist/mcp-proxy.d.cts +4 -5
- package/dist/mcp-proxy.d.cts.map +1 -1
- package/dist/mcp-proxy.d.mts +4 -5
- package/dist/mcp-proxy.d.mts.map +1 -1
- package/dist/mcp-proxy.mjs +87 -15
- package/dist/mcp-proxy.mjs.map +1 -1
- package/dist/{public-tools-DDGHRazh.cjs → public-tools-CZTDEjqJ.cjs} +22 -179
- package/dist/{public-tools-CMI_0y87.mjs → public-tools-CsBmOyeQ.mjs} +23 -180
- package/dist/public-tools-CsBmOyeQ.mjs.map +1 -0
- package/dist/subscription-status-Cm7LqY_h.cjs +150 -0
- package/dist/subscription-status-MyeqOmbA.mjs +142 -0
- package/dist/subscription-status-MyeqOmbA.mjs.map +1 -0
- package/dist/{tool-visibility-CJqjmDF5.mjs → tool-visibility-CJV9HezW.mjs} +3 -2
- package/dist/tool-visibility-CJV9HezW.mjs.map +1 -0
- package/dist/{tool-visibility-BBEbpKt4.cjs → tool-visibility-CyZqYnQA.cjs} +2 -1
- package/dist/transport-error-CSEb6sPr.mjs +58 -0
- package/dist/transport-error-CSEb6sPr.mjs.map +1 -0
- package/dist/transport-error-DmC9WLTW.cjs +56 -0
- package/docs/graph-query-compatibility.md +74 -67
- package/docs/graph-tools.md +143 -6
- package/package.json +4 -5
- package/skills/chain-insights-cypher/SKILL.md +136 -25
- package/skills/chain-insights-cypher/agents/openai.yaml +2 -2
- package/skills/chain-insights-schema-evm/SKILL.md +222 -15
- package/dist/merge-BZw-pMPN.mjs +0 -199
- package/dist/merge-BZw-pMPN.mjs.map +0 -1
- package/dist/merge-C52eaAGU.cjs +0 -202
- package/dist/public-tools-CMI_0y87.mjs.map +0 -1
- package/dist/tool-visibility-CJqjmDF5.mjs.map +0 -1
package/README.md
CHANGED
|
@@ -1,11 +1,17 @@
|
|
|
1
1
|
# Chain Insights
|
|
2
2
|
|
|
3
|
+
<div align="center">
|
|
4
|
+
<img src=".github/assets/chain-insights-github-crime-scene.png" width="100%" alt="Chain Insights: the agency cast around a crime-scene table tracing a glowing fund-flow trail while the scammer flees with the coin" />
|
|
5
|
+
|
|
3
6
|
[](https://www.npmjs.com/package/chain-insights)
|
|
4
7
|
[](https://github.com/chainswarm/chain-insights/actions/workflows/verify.yml)
|
|
5
8
|
[](https://securityscorecards.dev/viewer/?uri=github.com/chainswarm/chain-insights)
|
|
6
9
|
[](https://github.com/chainswarm/chain-insights/blob/main/LICENSE)
|
|
7
10
|
|
|
8
|
-
|
|
11
|
+
*Follow the funds. Find the obvious.*
|
|
12
|
+
|
|
13
|
+
[Website](https://chain-insights.ai) | [npm](https://www.npmjs.com/package/chain-insights) | [Quickstart](#quickstart)
|
|
14
|
+
</div>
|
|
9
15
|
|
|
10
16
|
Chain Insights is open-source AML and forensics infrastructure for AI agents
|
|
11
17
|
and analysts: a hosted Chain Insights Graph you reach over MCP, screened
|
|
@@ -124,7 +130,6 @@ Source modules (hand-maintained):
|
|
|
124
130
|
| Module | Entrypoint | Component doc |
|
|
125
131
|
| --------------- | ------------------- | ---------------------------------------------------------------------------- |
|
|
126
132
|
| `config` | `src/config` | [components/config.md](docs/architecture/components/config.md) |
|
|
127
|
-
| `federation` | `src/federation` | [components/federation.md](docs/architecture/components/federation.md) |
|
|
128
133
|
| `investigation` | `src/investigation` | [components/investigation.md](docs/architecture/components/investigation.md) |
|
|
129
134
|
| `mcp` | `src/mcp` | [components/mcp.md](docs/architecture/components/mcp.md) |
|
|
130
135
|
| `wallet` | `src/wallet` | [components/wallet.md](docs/architecture/components/wallet.md) |
|
|
@@ -144,10 +149,10 @@ and [operating rules](docs/architecture/operating-rules.md).
|
|
|
144
149
|
|
|
145
150
|
Graph queries choose the read graph explicitly:
|
|
146
151
|
|
|
147
|
-
| Graph | Use it for
|
|
148
|
-
| ---------- |
|
|
149
|
-
| `topology` | The unified address / FLOWS_TO / OPERATED_BY / LINKED graph — recent and full historical fund-flow traversal,
|
|
150
|
-
| `facts` | Bounded individual `TRANSFER` rows with amount, `amount_usd`, asset, transaction, and block facts
|
|
152
|
+
| Graph | Use it for |
|
|
153
|
+
| ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
154
|
+
| `topology` | The unified address / FLOWS_TO / OPERATED_BY / LINKED graph — recent and full historical fund-flow traversal, the node `risk_score`/`risk_level` verdict, and swap, liquidity-pool and bridge totals (see [Graph tools](docs/graph-tools.md#swaps-liquidity-pools-and-bridges)) |
|
|
155
|
+
| `facts` | Bounded individual `TRANSFER` rows with amount, `amount_usd`, asset, transaction, and block facts, plus single `SWAP`, `LIQUIDITY_ADD`, `LIQUIDITY_REMOVE` and `BRIDGE_CROSSING` rows |
|
|
151
156
|
|
|
152
157
|
One rule is worth reading before writing a query by hand: the `network`
|
|
153
158
|
argument selects the graph, not the addresses inside it. The address-space
|
package/dist/cli.cjs
CHANGED
|
@@ -187,6 +187,8 @@ async function withGraphMcpClient(name, fn) {
|
|
|
187
187
|
const { loadConfig } = await Promise.resolve().then(() => require("./config-B542AM4w.cjs")).then((n) => n.config_exports);
|
|
188
188
|
const config = await loadConfig();
|
|
189
189
|
const { createConfiguredGraphMcpFetch, resolveGraphMcpEndpoint } = await Promise.resolve().then(() => require("./client-Ypw9BNbn.cjs")).then((n) => n.client_exports);
|
|
190
|
+
const { toGraphMcpEndpointError } = await Promise.resolve().then(() => require("./transport-error-DmC9WLTW.cjs"));
|
|
191
|
+
const endpoint = resolveGraphMcpEndpoint(config);
|
|
190
192
|
const paymentFetch = await createConfiguredGraphMcpFetch(config);
|
|
191
193
|
const { Client } = await import("@modelcontextprotocol/sdk/client/index.js");
|
|
192
194
|
const { StreamableHTTPClientTransport } = await import("@modelcontextprotocol/sdk/client/streamableHttp.js");
|
|
@@ -194,11 +196,17 @@ async function withGraphMcpClient(name, fn) {
|
|
|
194
196
|
name,
|
|
195
197
|
version: require_version.PACKAGE_VERSION
|
|
196
198
|
});
|
|
197
|
-
|
|
199
|
+
try {
|
|
200
|
+
await client.connect(new StreamableHTTPClientTransport(new URL(endpoint), { fetch: paymentFetch }));
|
|
201
|
+
} catch (err) {
|
|
202
|
+
throw toGraphMcpEndpointError(err, endpoint);
|
|
203
|
+
}
|
|
198
204
|
const { installActionLogging } = await Promise.resolve().then(() => require("./action-log-HniMMF7f.cjs")).then((n) => n.action_log_exports);
|
|
199
205
|
installActionLogging(client);
|
|
200
206
|
try {
|
|
201
207
|
return await fn(client, config);
|
|
208
|
+
} catch (err) {
|
|
209
|
+
throw toGraphMcpEndpointError(err, endpoint);
|
|
202
210
|
} finally {
|
|
203
211
|
await client.close();
|
|
204
212
|
}
|
|
@@ -230,14 +238,74 @@ async function printNetworkCapability(name, opts) {
|
|
|
230
238
|
if (opts.json) console.log(JSON.stringify(network, null, 2));
|
|
231
239
|
else console.log(formatNetworkCapability(network));
|
|
232
240
|
}
|
|
241
|
+
/**
|
|
242
|
+
* Fetches the caller's subscription facts for the deposit pre-sign guard.
|
|
243
|
+
* The extension math is server-authoritative: the printed values come from
|
|
244
|
+
* `subscription_status`. Any failure (no wallet, unreachable endpoint,
|
|
245
|
+
* missing tool, error result) degrades to an unavailable lookup — the guard
|
|
246
|
+
* must never block the flow on a server that lacks the tool.
|
|
247
|
+
*/
|
|
248
|
+
async function fetchSubscriptionStatusForCli() {
|
|
249
|
+
try {
|
|
250
|
+
const { getWalletAccount } = await Promise.resolve().then(() => require("./tools-BHfphgy9.cjs")).then((n) => n.tools_exports);
|
|
251
|
+
const account = await getWalletAccount();
|
|
252
|
+
return await withGraphMcpClient("chain-insights-cli-subscription-status", async (client) => {
|
|
253
|
+
const result = await client.callTool({
|
|
254
|
+
name: "subscription_status",
|
|
255
|
+
arguments: { wallet: account.address }
|
|
256
|
+
});
|
|
257
|
+
const { parseSubscriptionStatusToolResult } = await Promise.resolve().then(() => require("./subscription-status-Cm7LqY_h.cjs")).then((n) => n.subscription_status_exports);
|
|
258
|
+
const facts = parseSubscriptionStatusToolResult(result);
|
|
259
|
+
if (!facts) return {
|
|
260
|
+
kind: "unavailable",
|
|
261
|
+
reason: "the graph endpoint returned no subscription facts"
|
|
262
|
+
};
|
|
263
|
+
return {
|
|
264
|
+
kind: "available",
|
|
265
|
+
facts
|
|
266
|
+
};
|
|
267
|
+
});
|
|
268
|
+
} catch (err) {
|
|
269
|
+
return {
|
|
270
|
+
kind: "unavailable",
|
|
271
|
+
reason: err.message
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
async function printSubscriptionPassGuidance(pass) {
|
|
276
|
+
const { formatDepositGuardLine, formatDepositIrreversibilityWarning, formatSubscriptionPassHint, isDepositConfirmed, resolveSubscriptionMonthUsd } = await Promise.resolve().then(() => require("./subscription-status-Cm7LqY_h.cjs")).then((n) => n.subscription_status_exports);
|
|
277
|
+
const hint = formatSubscriptionPassHint(pass, resolveSubscriptionMonthUsd());
|
|
278
|
+
const status = await fetchSubscriptionStatusForCli();
|
|
279
|
+
if (status.kind === "available") {
|
|
280
|
+
process.stderr.write(`${formatDepositGuardLine(status.facts, pass)}\n`);
|
|
281
|
+
process.stderr.write("The no-admin subscription sink cannot refund deposits. Type DEPOSIT to continue:\n");
|
|
282
|
+
const { createInterface } = await import("node:readline/promises");
|
|
283
|
+
const prompt = createInterface({
|
|
284
|
+
input: process.stdin,
|
|
285
|
+
output: process.stderr
|
|
286
|
+
});
|
|
287
|
+
let answer;
|
|
288
|
+
try {
|
|
289
|
+
answer = await prompt.question("> ");
|
|
290
|
+
} finally {
|
|
291
|
+
prompt.close();
|
|
292
|
+
}
|
|
293
|
+
process.stderr.write("\n");
|
|
294
|
+
if (!isDepositConfirmed(answer)) throw new Error("Deposit cancelled. No deposit was made.");
|
|
295
|
+
console.log(hint);
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
process.stderr.write(`${formatDepositIrreversibilityWarning(status.reason)}\n`);
|
|
299
|
+
console.log(hint);
|
|
300
|
+
}
|
|
233
301
|
function addAmlAddressRiskCommand(parent, networksCommand) {
|
|
234
302
|
parent.addCommand(createCliCommand("aml-address-risk").description("CIA workflow: screen an address for AML risk, exchange behavior, and optional comparison with another address").requiredOption("--address <address>", "Full blockchain address to screen").requiredOption("--network <network>", `Network to query. Run \`${networksCommand}\` for supported networks.`).option("--compare-address <address>", "Optional second address to compare against the screened address").option("--json", "Print machine-readable JSON output").option("--version <version>", "AML tool contract version. Omit to use the latest version (currently v1)").addOption(new commander.Option("--tool-version <version>", "Internal alias for the AML tool version").hideHelp()).action(async (opts) => {
|
|
235
303
|
try {
|
|
236
|
-
const { resolveAmlAddressRiskVersion } = await Promise.resolve().then(() => require("./public-tools-
|
|
304
|
+
const { resolveAmlAddressRiskVersion } = await Promise.resolve().then(() => require("./public-tools-CZTDEjqJ.cjs"));
|
|
237
305
|
const requestedVersion = opts.toolVersion ?? opts.version;
|
|
238
306
|
resolveAmlAddressRiskVersion(requestedVersion);
|
|
239
307
|
await withGraphMcpClient("chain-insights-cli-aml-address-risk", async (client) => {
|
|
240
|
-
const { runAmlAddressRisk } = await Promise.resolve().then(() => require("./public-tools-
|
|
308
|
+
const { runAmlAddressRisk } = await Promise.resolve().then(() => require("./public-tools-CZTDEjqJ.cjs"));
|
|
241
309
|
const result = await runAmlAddressRisk(client, {
|
|
242
310
|
address: opts.address,
|
|
243
311
|
network: opts.network,
|
|
@@ -534,6 +602,21 @@ program.command("wallet").description("Manage the local Base USDC payment wallet
|
|
|
534
602
|
process.exit(1);
|
|
535
603
|
}
|
|
536
604
|
}));
|
|
605
|
+
program.command("buy").description("Show CIA subscription pass deposit guidance (the sink cannot refund deposits)").addCommand(createCliCommand("day").description("Show day-pass deposit guidance (SUBSCRIPTION_MONTH_USD / 30)").action(async () => {
|
|
606
|
+
try {
|
|
607
|
+
await printSubscriptionPassGuidance("day");
|
|
608
|
+
} catch (err) {
|
|
609
|
+
console.error(err.message);
|
|
610
|
+
process.exit(1);
|
|
611
|
+
}
|
|
612
|
+
})).addCommand(createCliCommand("month").description("Show month-pass deposit guidance at the list price").action(async () => {
|
|
613
|
+
try {
|
|
614
|
+
await printSubscriptionPassGuidance("month");
|
|
615
|
+
} catch (err) {
|
|
616
|
+
console.error(err.message);
|
|
617
|
+
process.exit(1);
|
|
618
|
+
}
|
|
619
|
+
}));
|
|
537
620
|
program.command("mcp").description("Low-level access to the Chain Insights MCP endpoint").allowExcessArguments(false).addCommand(createCliCommand("networks").description("List the detailed Chain Insights capability matrix and tool support").option("--json", "Print raw capability JSON").action(async (opts) => {
|
|
538
621
|
try {
|
|
539
622
|
await printNetworkCapabilities(opts);
|
|
@@ -545,7 +628,7 @@ program.command("mcp").description("Low-level access to the Chain Insights MCP e
|
|
|
545
628
|
try {
|
|
546
629
|
const { loadSchema, saveSchema } = await Promise.resolve().then(() => require("./schema-cache-n7Gbhvsj.cjs"));
|
|
547
630
|
const { formatToolsTable } = await Promise.resolve().then(() => require("./format-BjZuYDr8.cjs"));
|
|
548
|
-
const { visibleRemoteTools } = await Promise.resolve().then(() => require("./tool-visibility-
|
|
631
|
+
const { visibleRemoteTools } = await Promise.resolve().then(() => require("./tool-visibility-CyZqYnQA.cjs")).then((n) => n.tool_visibility_exports);
|
|
549
632
|
const { loadConfig } = await Promise.resolve().then(() => require("./config-B542AM4w.cjs")).then((n) => n.config_exports);
|
|
550
633
|
const { createConfiguredGraphMcpFetch, resolveGraphMcpEndpoint } = await Promise.resolve().then(() => require("./client-Ypw9BNbn.cjs")).then((n) => n.client_exports);
|
|
551
634
|
const config = await loadConfig();
|
|
@@ -575,7 +658,7 @@ program.command("mcp").description("Low-level access to the Chain Insights MCP e
|
|
|
575
658
|
})).addCommand(createCliCommand("call").description("Call a low-level MCP tool directly (advanced)").option("--json", "Print machine-readable JSON output").argument("<tool>", "Tool name to call").argument("[args...]", "Key=value arguments (e.g. address=0x1234... network=robinhood)").action(async (tool, rawArgs, opts) => {
|
|
576
659
|
try {
|
|
577
660
|
const { parseMcpCallArgs } = await Promise.resolve().then(() => require("./call-args-DAiQSDmD.cjs"));
|
|
578
|
-
const { assertPublicMcpToolName, validatePublicMcpToolArguments } = await Promise.resolve().then(() => require("./tool-visibility-
|
|
661
|
+
const { assertPublicMcpToolName, validatePublicMcpToolArguments } = await Promise.resolve().then(() => require("./tool-visibility-CyZqYnQA.cjs")).then((n) => n.tool_visibility_exports);
|
|
579
662
|
const args = parseMcpCallArgs(rawArgs);
|
|
580
663
|
assertPublicMcpToolName(tool);
|
|
581
664
|
if (tool === "aml_address_risk") throw new Error("aml_address_risk is a CIA workflow. Run `cia workflow aml-address-risk` instead.");
|
|
@@ -611,6 +694,25 @@ program.command("mcp").description("Low-level access to the Chain Insights MCP e
|
|
|
611
694
|
}
|
|
612
695
|
return;
|
|
613
696
|
}
|
|
697
|
+
if (tool === "meta_subscription_status") {
|
|
698
|
+
try {
|
|
699
|
+
const { getWalletAccount } = await Promise.resolve().then(() => require("./tools-BHfphgy9.cjs")).then((n) => n.tools_exports);
|
|
700
|
+
const account = await getWalletAccount();
|
|
701
|
+
printMcpTextContent(await client.callTool({
|
|
702
|
+
name: "subscription_status",
|
|
703
|
+
arguments: { wallet: account.address }
|
|
704
|
+
}), {
|
|
705
|
+
tool,
|
|
706
|
+
json: opts.json
|
|
707
|
+
});
|
|
708
|
+
} catch (err) {
|
|
709
|
+
const { isMissingSubscriptionStatusToolError, unavailableSubscriptionStatus, subscriptionStatusText } = await Promise.resolve().then(() => require("./subscription-status-Cm7LqY_h.cjs")).then((n) => n.subscription_status_exports);
|
|
710
|
+
if (!isMissingSubscriptionStatusToolError(err)) throw err;
|
|
711
|
+
const { resolveGraphMcpEndpoint } = await Promise.resolve().then(() => require("./client-Ypw9BNbn.cjs")).then((n) => n.client_exports);
|
|
712
|
+
console.log(subscriptionStatusText(unavailableSubscriptionStatus(resolveGraphMcpEndpoint(config), `subscription_status failed: ${err.message}`)));
|
|
713
|
+
}
|
|
714
|
+
return;
|
|
715
|
+
}
|
|
614
716
|
printMcpTextContent(await client.callTool({
|
|
615
717
|
name: tool,
|
|
616
718
|
arguments: args
|
|
@@ -620,7 +722,7 @@ program.command("mcp").description("Low-level access to the Chain Insights MCP e
|
|
|
620
722
|
});
|
|
621
723
|
});
|
|
622
724
|
} catch (err) {
|
|
623
|
-
const { formatMcpCallError } = await Promise.resolve().then(() => require("./tool-visibility-
|
|
725
|
+
const { formatMcpCallError } = await Promise.resolve().then(() => require("./tool-visibility-CyZqYnQA.cjs")).then((n) => n.tool_visibility_exports);
|
|
624
726
|
console.error(formatMcpCallError(tool, err));
|
|
625
727
|
process.exit(1);
|
|
626
728
|
}
|
package/dist/cli.mjs
CHANGED
|
@@ -185,6 +185,8 @@ async function withGraphMcpClient(name, fn) {
|
|
|
185
185
|
const { loadConfig } = await import("./config-DbbPiGk0.mjs").then((n) => n.t);
|
|
186
186
|
const config = await loadConfig();
|
|
187
187
|
const { createConfiguredGraphMcpFetch, resolveGraphMcpEndpoint } = await import("./client-CHYskPnG.mjs").then((n) => n.r);
|
|
188
|
+
const { toGraphMcpEndpointError } = await import("./transport-error-CSEb6sPr.mjs");
|
|
189
|
+
const endpoint = resolveGraphMcpEndpoint(config);
|
|
188
190
|
const paymentFetch = await createConfiguredGraphMcpFetch(config);
|
|
189
191
|
const { Client } = await import("@modelcontextprotocol/sdk/client/index.js");
|
|
190
192
|
const { StreamableHTTPClientTransport } = await import("@modelcontextprotocol/sdk/client/streamableHttp.js");
|
|
@@ -192,11 +194,17 @@ async function withGraphMcpClient(name, fn) {
|
|
|
192
194
|
name,
|
|
193
195
|
version: PACKAGE_VERSION
|
|
194
196
|
});
|
|
195
|
-
|
|
197
|
+
try {
|
|
198
|
+
await client.connect(new StreamableHTTPClientTransport(new URL(endpoint), { fetch: paymentFetch }));
|
|
199
|
+
} catch (err) {
|
|
200
|
+
throw toGraphMcpEndpointError(err, endpoint);
|
|
201
|
+
}
|
|
196
202
|
const { installActionLogging } = await import("./action-log-diTHyMbV.mjs").then((n) => n.n);
|
|
197
203
|
installActionLogging(client);
|
|
198
204
|
try {
|
|
199
205
|
return await fn(client, config);
|
|
206
|
+
} catch (err) {
|
|
207
|
+
throw toGraphMcpEndpointError(err, endpoint);
|
|
200
208
|
} finally {
|
|
201
209
|
await client.close();
|
|
202
210
|
}
|
|
@@ -228,14 +236,74 @@ async function printNetworkCapability(name, opts) {
|
|
|
228
236
|
if (opts.json) console.log(JSON.stringify(network, null, 2));
|
|
229
237
|
else console.log(formatNetworkCapability(network));
|
|
230
238
|
}
|
|
239
|
+
/**
|
|
240
|
+
* Fetches the caller's subscription facts for the deposit pre-sign guard.
|
|
241
|
+
* The extension math is server-authoritative: the printed values come from
|
|
242
|
+
* `subscription_status`. Any failure (no wallet, unreachable endpoint,
|
|
243
|
+
* missing tool, error result) degrades to an unavailable lookup — the guard
|
|
244
|
+
* must never block the flow on a server that lacks the tool.
|
|
245
|
+
*/
|
|
246
|
+
async function fetchSubscriptionStatusForCli() {
|
|
247
|
+
try {
|
|
248
|
+
const { getWalletAccount } = await import("./tools-BRQAPF2R.mjs").then((n) => n.p);
|
|
249
|
+
const account = await getWalletAccount();
|
|
250
|
+
return await withGraphMcpClient("chain-insights-cli-subscription-status", async (client) => {
|
|
251
|
+
const result = await client.callTool({
|
|
252
|
+
name: "subscription_status",
|
|
253
|
+
arguments: { wallet: account.address }
|
|
254
|
+
});
|
|
255
|
+
const { parseSubscriptionStatusToolResult } = await import("./subscription-status-MyeqOmbA.mjs").then((n) => n.t);
|
|
256
|
+
const facts = parseSubscriptionStatusToolResult(result);
|
|
257
|
+
if (!facts) return {
|
|
258
|
+
kind: "unavailable",
|
|
259
|
+
reason: "the graph endpoint returned no subscription facts"
|
|
260
|
+
};
|
|
261
|
+
return {
|
|
262
|
+
kind: "available",
|
|
263
|
+
facts
|
|
264
|
+
};
|
|
265
|
+
});
|
|
266
|
+
} catch (err) {
|
|
267
|
+
return {
|
|
268
|
+
kind: "unavailable",
|
|
269
|
+
reason: err.message
|
|
270
|
+
};
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
async function printSubscriptionPassGuidance(pass) {
|
|
274
|
+
const { formatDepositGuardLine, formatDepositIrreversibilityWarning, formatSubscriptionPassHint, isDepositConfirmed, resolveSubscriptionMonthUsd } = await import("./subscription-status-MyeqOmbA.mjs").then((n) => n.t);
|
|
275
|
+
const hint = formatSubscriptionPassHint(pass, resolveSubscriptionMonthUsd());
|
|
276
|
+
const status = await fetchSubscriptionStatusForCli();
|
|
277
|
+
if (status.kind === "available") {
|
|
278
|
+
process.stderr.write(`${formatDepositGuardLine(status.facts, pass)}\n`);
|
|
279
|
+
process.stderr.write("The no-admin subscription sink cannot refund deposits. Type DEPOSIT to continue:\n");
|
|
280
|
+
const { createInterface } = await import("node:readline/promises");
|
|
281
|
+
const prompt = createInterface({
|
|
282
|
+
input: process.stdin,
|
|
283
|
+
output: process.stderr
|
|
284
|
+
});
|
|
285
|
+
let answer;
|
|
286
|
+
try {
|
|
287
|
+
answer = await prompt.question("> ");
|
|
288
|
+
} finally {
|
|
289
|
+
prompt.close();
|
|
290
|
+
}
|
|
291
|
+
process.stderr.write("\n");
|
|
292
|
+
if (!isDepositConfirmed(answer)) throw new Error("Deposit cancelled. No deposit was made.");
|
|
293
|
+
console.log(hint);
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
process.stderr.write(`${formatDepositIrreversibilityWarning(status.reason)}\n`);
|
|
297
|
+
console.log(hint);
|
|
298
|
+
}
|
|
231
299
|
function addAmlAddressRiskCommand(parent, networksCommand) {
|
|
232
300
|
parent.addCommand(createCliCommand("aml-address-risk").description("CIA workflow: screen an address for AML risk, exchange behavior, and optional comparison with another address").requiredOption("--address <address>", "Full blockchain address to screen").requiredOption("--network <network>", `Network to query. Run \`${networksCommand}\` for supported networks.`).option("--compare-address <address>", "Optional second address to compare against the screened address").option("--json", "Print machine-readable JSON output").option("--version <version>", "AML tool contract version. Omit to use the latest version (currently v1)").addOption(new Option("--tool-version <version>", "Internal alias for the AML tool version").hideHelp()).action(async (opts) => {
|
|
233
301
|
try {
|
|
234
|
-
const { resolveAmlAddressRiskVersion } = await import("./public-tools-
|
|
302
|
+
const { resolveAmlAddressRiskVersion } = await import("./public-tools-CsBmOyeQ.mjs");
|
|
235
303
|
const requestedVersion = opts.toolVersion ?? opts.version;
|
|
236
304
|
resolveAmlAddressRiskVersion(requestedVersion);
|
|
237
305
|
await withGraphMcpClient("chain-insights-cli-aml-address-risk", async (client) => {
|
|
238
|
-
const { runAmlAddressRisk } = await import("./public-tools-
|
|
306
|
+
const { runAmlAddressRisk } = await import("./public-tools-CsBmOyeQ.mjs");
|
|
239
307
|
const result = await runAmlAddressRisk(client, {
|
|
240
308
|
address: opts.address,
|
|
241
309
|
network: opts.network,
|
|
@@ -532,6 +600,21 @@ program.command("wallet").description("Manage the local Base USDC payment wallet
|
|
|
532
600
|
process.exit(1);
|
|
533
601
|
}
|
|
534
602
|
}));
|
|
603
|
+
program.command("buy").description("Show CIA subscription pass deposit guidance (the sink cannot refund deposits)").addCommand(createCliCommand("day").description("Show day-pass deposit guidance (SUBSCRIPTION_MONTH_USD / 30)").action(async () => {
|
|
604
|
+
try {
|
|
605
|
+
await printSubscriptionPassGuidance("day");
|
|
606
|
+
} catch (err) {
|
|
607
|
+
console.error(err.message);
|
|
608
|
+
process.exit(1);
|
|
609
|
+
}
|
|
610
|
+
})).addCommand(createCliCommand("month").description("Show month-pass deposit guidance at the list price").action(async () => {
|
|
611
|
+
try {
|
|
612
|
+
await printSubscriptionPassGuidance("month");
|
|
613
|
+
} catch (err) {
|
|
614
|
+
console.error(err.message);
|
|
615
|
+
process.exit(1);
|
|
616
|
+
}
|
|
617
|
+
}));
|
|
535
618
|
program.command("mcp").description("Low-level access to the Chain Insights MCP endpoint").allowExcessArguments(false).addCommand(createCliCommand("networks").description("List the detailed Chain Insights capability matrix and tool support").option("--json", "Print raw capability JSON").action(async (opts) => {
|
|
536
619
|
try {
|
|
537
620
|
await printNetworkCapabilities(opts);
|
|
@@ -543,7 +626,7 @@ program.command("mcp").description("Low-level access to the Chain Insights MCP e
|
|
|
543
626
|
try {
|
|
544
627
|
const { loadSchema, saveSchema } = await import("./schema-cache-DJdU4MIP.mjs");
|
|
545
628
|
const { formatToolsTable } = await import("./format-DB2IH2U5.mjs");
|
|
546
|
-
const { visibleRemoteTools } = await import("./tool-visibility-
|
|
629
|
+
const { visibleRemoteTools } = await import("./tool-visibility-CJV9HezW.mjs").then((n) => n.i);
|
|
547
630
|
const { loadConfig } = await import("./config-DbbPiGk0.mjs").then((n) => n.t);
|
|
548
631
|
const { createConfiguredGraphMcpFetch, resolveGraphMcpEndpoint } = await import("./client-CHYskPnG.mjs").then((n) => n.r);
|
|
549
632
|
const config = await loadConfig();
|
|
@@ -573,7 +656,7 @@ program.command("mcp").description("Low-level access to the Chain Insights MCP e
|
|
|
573
656
|
})).addCommand(createCliCommand("call").description("Call a low-level MCP tool directly (advanced)").option("--json", "Print machine-readable JSON output").argument("<tool>", "Tool name to call").argument("[args...]", "Key=value arguments (e.g. address=0x1234... network=robinhood)").action(async (tool, rawArgs, opts) => {
|
|
574
657
|
try {
|
|
575
658
|
const { parseMcpCallArgs } = await import("./call-args-ysbB_xdA.mjs");
|
|
576
|
-
const { assertPublicMcpToolName, validatePublicMcpToolArguments } = await import("./tool-visibility-
|
|
659
|
+
const { assertPublicMcpToolName, validatePublicMcpToolArguments } = await import("./tool-visibility-CJV9HezW.mjs").then((n) => n.i);
|
|
577
660
|
const args = parseMcpCallArgs(rawArgs);
|
|
578
661
|
assertPublicMcpToolName(tool);
|
|
579
662
|
if (tool === "aml_address_risk") throw new Error("aml_address_risk is a CIA workflow. Run `cia workflow aml-address-risk` instead.");
|
|
@@ -609,6 +692,25 @@ program.command("mcp").description("Low-level access to the Chain Insights MCP e
|
|
|
609
692
|
}
|
|
610
693
|
return;
|
|
611
694
|
}
|
|
695
|
+
if (tool === "meta_subscription_status") {
|
|
696
|
+
try {
|
|
697
|
+
const { getWalletAccount } = await import("./tools-BRQAPF2R.mjs").then((n) => n.p);
|
|
698
|
+
const account = await getWalletAccount();
|
|
699
|
+
printMcpTextContent(await client.callTool({
|
|
700
|
+
name: "subscription_status",
|
|
701
|
+
arguments: { wallet: account.address }
|
|
702
|
+
}), {
|
|
703
|
+
tool,
|
|
704
|
+
json: opts.json
|
|
705
|
+
});
|
|
706
|
+
} catch (err) {
|
|
707
|
+
const { isMissingSubscriptionStatusToolError, unavailableSubscriptionStatus, subscriptionStatusText } = await import("./subscription-status-MyeqOmbA.mjs").then((n) => n.t);
|
|
708
|
+
if (!isMissingSubscriptionStatusToolError(err)) throw err;
|
|
709
|
+
const { resolveGraphMcpEndpoint } = await import("./client-CHYskPnG.mjs").then((n) => n.r);
|
|
710
|
+
console.log(subscriptionStatusText(unavailableSubscriptionStatus(resolveGraphMcpEndpoint(config), `subscription_status failed: ${err.message}`)));
|
|
711
|
+
}
|
|
712
|
+
return;
|
|
713
|
+
}
|
|
612
714
|
printMcpTextContent(await client.callTool({
|
|
613
715
|
name: tool,
|
|
614
716
|
arguments: args
|
|
@@ -618,7 +720,7 @@ program.command("mcp").description("Low-level access to the Chain Insights MCP e
|
|
|
618
720
|
});
|
|
619
721
|
});
|
|
620
722
|
} catch (err) {
|
|
621
|
-
const { formatMcpCallError } = await import("./tool-visibility-
|
|
723
|
+
const { formatMcpCallError } = await import("./tool-visibility-CJV9HezW.mjs").then((n) => n.i);
|
|
622
724
|
console.error(formatMcpCallError(tool, err));
|
|
623
725
|
process.exit(1);
|
|
624
726
|
}
|