chain-insights 0.3.19 → 0.8.22
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 +1 -1
- package/README.md +54 -36
- package/bin/install.cjs +5 -9
- package/dist/active-BQopLul8.mjs.map +1 -1
- package/dist/{active-XWv72R1X.cjs → active-Bj6dohpc.cjs} +5 -5
- package/dist/{app-DBrqk_iP.cjs → app-BNrqZ_LR.cjs} +6 -6
- package/dist/{app-DXwILI_a.mjs → app-CCXmYEV1.mjs} +2 -2
- package/dist/{app-DXwILI_a.mjs.map → app-CCXmYEV1.mjs.map} +1 -1
- package/dist/{artifact-server-v0WgTPFT.cjs → artifact-server-B4YVpWK2.cjs} +1 -1
- package/dist/{artifact-server-CcmLBv1j.mjs → artifact-server-DR13HEei.mjs} +2 -2
- package/dist/{artifact-server-CcmLBv1j.mjs.map → artifact-server-DR13HEei.mjs.map} +1 -1
- package/dist/{call-args-DPXdX3_D.mjs → call-args-D3UajHDq.mjs} +3 -5
- package/dist/call-args-D3UajHDq.mjs.map +1 -0
- package/dist/{call-args-CcUV6gFS.cjs → call-args-DyU9d6tT.cjs} +2 -4
- package/dist/capabilities-CjIcF3da.cjs +136 -0
- package/dist/capabilities-GuF58uDa.mjs +137 -0
- package/dist/capabilities-GuF58uDa.mjs.map +1 -0
- package/dist/cli.cjs +173 -252
- package/dist/cli.mjs +164 -243
- package/dist/cli.mjs.map +1 -1
- package/dist/{client-ytTO0mcZ.mjs → client-C_HEuq0f.mjs} +9 -8
- package/dist/client-C_HEuq0f.mjs.map +1 -0
- package/dist/{client-BY-56ojr.cjs → client-rVqMG2j9.cjs} +10 -9
- package/dist/{config-CkW404Cs.cjs → config-B8Hk-G1y.cjs} +6 -6
- package/dist/{config-C6zM8Xir.mjs → config-BFi5yBMm.mjs} +3 -3
- package/dist/{config-C6zM8Xir.mjs.map → config-BFi5yBMm.mjs.map} +1 -1
- package/dist/format-Bq94jSyw.mjs.map +1 -1
- package/dist/{graph-normalizer-DbjlbMpz.cjs → graph-normalizer-B2Q2lgVy.cjs} +2 -5
- package/dist/{graph-normalizer-CXP06jKh.mjs → graph-normalizer-BA3Rbd6l.mjs} +3 -6
- package/dist/graph-normalizer-BA3Rbd6l.mjs.map +1 -0
- package/dist/{graph-reports-CEq-Mvx0.mjs → graph-reports-B6yoYbPq.mjs} +2 -2
- package/dist/{graph-reports-CEq-Mvx0.mjs.map → graph-reports-B6yoYbPq.mjs.map} +1 -1
- package/dist/{graph-reports-CkglRtg4.cjs → graph-reports-DSHSp5HL.cjs} +5 -5
- package/dist/{html-generator-BFKafL8y.cjs → html-generator-DF0F6nUI.cjs} +5 -5
- package/dist/{html-generator-D4fX71hI.mjs → html-generator-DjWagEB5.mjs} +2 -2
- package/dist/html-generator-DjWagEB5.mjs.map +1 -0
- package/dist/index.cjs +10 -8
- package/dist/index.d.cts +34 -4
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +34 -4
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +8 -8
- package/dist/{init-BGDvGreX.mjs → init-BWFFHDtL.mjs} +74 -12
- package/dist/init-BWFFHDtL.mjs.map +1 -0
- package/dist/{init-Cuw9TznI.cjs → init-s0SU97fS.cjs} +75 -13
- package/dist/{mcp-endpoint-cQIZSjkK.cjs → mcp-endpoint-BIWrUOFG.cjs} +1 -8
- package/dist/{mcp-endpoint-QQ5Lbqc2.mjs → mcp-endpoint-DbWtLcba.mjs} +3 -4
- package/dist/mcp-endpoint-DbWtLcba.mjs.map +1 -0
- package/dist/mcp-proxy.cjs +711 -892
- package/dist/mcp-proxy.d.cts.map +1 -1
- package/dist/mcp-proxy.d.mts.map +1 -1
- package/dist/mcp-proxy.mjs +707 -888
- package/dist/mcp-proxy.mjs.map +1 -1
- package/dist/{output-root-DI0tzA0X.cjs → output-root-C1PFNCqb.cjs} +4 -4
- package/dist/{public-tools-BREojpU7.cjs → public-tools-CXD65Dfk.cjs} +923 -1495
- package/dist/{public-tools-brHmHGYm.mjs → public-tools-DScJ1mRk.mjs} +922 -1487
- package/dist/public-tools-DScJ1mRk.mjs.map +1 -0
- package/dist/resolve-port-CbaEoODz.cjs +18 -0
- package/dist/resolve-port-DxPK7Ipx.mjs +20 -0
- package/dist/resolve-port-DxPK7Ipx.mjs.map +1 -0
- package/dist/{schema-Dr6JXSOF.cjs → schema-Dj2mqv1g.cjs} +6 -10
- package/dist/{schema-cache-CJk1EL3L.cjs → schema-cache-CX0r2UQp.cjs} +3 -3
- package/dist/{schema-D_qwaQA5.mjs → schema-zWbVYCQW.mjs} +2 -6
- package/dist/schema-zWbVYCQW.mjs.map +1 -0
- package/dist/{server-ColyTG1t.cjs → server-BkljWFmU.cjs} +3 -3
- package/dist/{server-BK4bfOiv.mjs → server-CGGSh1TZ.mjs} +2 -2
- package/dist/{server-BK4bfOiv.mjs.map → server-CGGSh1TZ.mjs.map} +1 -1
- package/dist/templates/graph.html +11 -10
- package/dist/tool-visibility-9-rvB91K.mjs +98 -0
- package/dist/tool-visibility-9-rvB91K.mjs.map +1 -0
- package/dist/tool-visibility-Cl2p7Ghx.cjs +118 -0
- package/dist/{tools-v6kcdojg.mjs → tools-B4rwKdvU.mjs} +53 -13
- package/dist/tools-B4rwKdvU.mjs.map +1 -0
- package/dist/{tools-BhTI3Lmg.cjs → tools-e87fylVa.cjs} +71 -13
- package/dist/{topup-server-DhYlOOBM.cjs → topup-server-B8anfXcq.cjs} +2 -2
- package/dist/topup-server-R3dNp-p8.mjs.map +1 -1
- package/dist/update-CJUfGCxs.mjs.map +1 -1
- package/dist/usage-status-D2uosC7s.mjs +36 -0
- package/dist/usage-status-D2uosC7s.mjs.map +1 -0
- package/dist/usage-status-H1xgCu99.cjs +44 -0
- package/dist/{viz-BBvY-wXz.cjs → viz-C9m5OuQT.cjs} +9 -8
- package/dist/{viz-D8umSF-t.mjs → viz-Cvb81rMm.mjs} +5 -4
- package/dist/viz-Cvb81rMm.mjs.map +1 -0
- package/dist/{wallet-BL0fJC29.mjs → wallet-BrTTnf7w.mjs} +43 -2
- package/dist/wallet-BrTTnf7w.mjs.map +1 -0
- package/dist/{wallet-gC2jxh7j.cjs → wallet-C2yVjcSY.cjs} +47 -6
- package/docs/architecture.md +10 -12
- package/docs/contributing.md +2 -9
- package/docs/debugging.md +33 -17
- package/docs/development.md +27 -0
- package/docs/graph-tools.md +33 -119
- package/docs/investigation-workspaces.md +1 -1
- package/docs/mcp-proxy.md +69 -52
- package/package.json +17 -13
- package/skills/chain-insights-address-risk/SKILL.md +1 -1
- package/skills/chain-insights-bittensor-cypher/SKILL.md +61 -52
- package/skills/chain-insights-cypher/SKILL.md +44 -23
- package/skills/chain-insights-cypher/agents/openai.yaml +1 -1
- package/skills/chain-insights-cypher/references/memgraph-examples.md +40 -34
- package/skills/chain-insights-developer-experience/SKILL.md +8 -8
- package/skills/chain-insights-investigation/SKILL.md +9 -9
- package/skills/chain-insights-investigation/scripts/run-target-uat.sh +12 -12
- package/skills/chain-insights-trace-funds/SKILL.md +13 -10
- package/skills/test-chain-insights-graph/SKILL.md +81 -0
- package/skills/test-chain-insights-graph/agents/openai.yaml +4 -0
- package/skills/{test-chain-insights-graphrag-mcp → test-chain-insights-graph}/scripts/run-uat.sh +260 -256
- package/dist/call-args-DPXdX3_D.mjs.map +0 -1
- package/dist/capabilities-CM72SErE.mjs +0 -81
- package/dist/capabilities-CM72SErE.mjs.map +0 -1
- package/dist/capabilities-DGeF-oHc.cjs +0 -80
- package/dist/client-ytTO0mcZ.mjs.map +0 -1
- package/dist/graph-normalizer-CXP06jKh.mjs.map +0 -1
- package/dist/html-generator-D4fX71hI.mjs.map +0 -1
- package/dist/init-BGDvGreX.mjs.map +0 -1
- package/dist/mcp-endpoint-QQ5Lbqc2.mjs.map +0 -1
- package/dist/public-tools-brHmHGYm.mjs.map +0 -1
- package/dist/schema-D_qwaQA5.mjs.map +0 -1
- package/dist/setup-CDha4B9s.cjs +0 -81
- package/dist/setup-yXK8agdn.mjs +0 -80
- package/dist/setup-yXK8agdn.mjs.map +0 -1
- package/dist/tool-visibility--QPgrRE5.cjs +0 -42
- package/dist/tool-visibility-nr6XqO1F.mjs +0 -34
- package/dist/tool-visibility-nr6XqO1F.mjs.map +0 -1
- package/dist/tools-v6kcdojg.mjs.map +0 -1
- package/dist/viz-D8umSF-t.mjs.map +0 -1
- package/dist/wallet-BL0fJC29.mjs.map +0 -1
- package/skills/chain-insights-exposure-analysis/SKILL.md +0 -83
- package/skills/test-chain-insights-graphrag-mcp/SKILL.md +0 -75
- package/skills/test-chain-insights-graphrag-mcp/agents/openai.yaml +0 -4
- /package/dist/{chunk-DakpK96I.cjs → rolldown-runtime-DakpK96I.cjs} +0 -0
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import { a as resolveGraphMcpEndpoint, n as applyMcpAuthHeaders } from "./client-C_HEuq0f.mjs";
|
|
2
|
+
//#region src/mcp/capabilities.ts
|
|
3
|
+
const BITTENSOR_SEMANTIC_NETWORKS = /* @__PURE__ */ new Set([
|
|
4
|
+
"bittensor",
|
|
5
|
+
"bittensor_evm",
|
|
6
|
+
"bittensor_semantic"
|
|
7
|
+
]);
|
|
8
|
+
const PUBLIC_CHAIN_INSIGHTS_TOOL_STATUS = {
|
|
9
|
+
aml_address_risk: "available",
|
|
10
|
+
aml_trace_victim_funds: "available",
|
|
11
|
+
aml_trace_deposit_sources: "available",
|
|
12
|
+
aml_trace_suspect_funds: "available",
|
|
13
|
+
graph_query: "available",
|
|
14
|
+
graph_query_batch: "available",
|
|
15
|
+
meta_network_capabilities: "available",
|
|
16
|
+
meta_usage_status: "available",
|
|
17
|
+
wallet_balance: "available"
|
|
18
|
+
};
|
|
19
|
+
const AVAILABLE_TOOLS_PER_LINE = 3;
|
|
20
|
+
function publicNetworkCapabilities(document) {
|
|
21
|
+
const source = document.networks.find((network) => BITTENSOR_SEMANTIC_NETWORKS.has(network.network));
|
|
22
|
+
return {
|
|
23
|
+
schema: "chain-insights.network-capabilities.v1",
|
|
24
|
+
networks: source ? [{
|
|
25
|
+
network: "bittensor",
|
|
26
|
+
display_name: "Bittensor",
|
|
27
|
+
status: source.status || "live",
|
|
28
|
+
default: source.default !== false,
|
|
29
|
+
layers: {
|
|
30
|
+
facts: { enabled: source.layers.facts?.enabled === true },
|
|
31
|
+
risk: { enabled: source.layers.risk?.enabled === true },
|
|
32
|
+
topology: {
|
|
33
|
+
enabled: source.layers.topology?.enabled === true,
|
|
34
|
+
...source.layers.topology?.live ? { live: source.layers.topology.live } : {},
|
|
35
|
+
...source.layers.topology?.archive ? { archive: source.layers.topology.archive } : {}
|
|
36
|
+
}
|
|
37
|
+
},
|
|
38
|
+
...source.coverage ? { coverage: source.coverage } : {},
|
|
39
|
+
...source.freshness ? { freshness: source.freshness } : {},
|
|
40
|
+
tools: PUBLIC_CHAIN_INSIGHTS_TOOL_STATUS
|
|
41
|
+
}] : []
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
function metadataNetworksUrl(endpoint) {
|
|
45
|
+
const url = new URL(endpoint);
|
|
46
|
+
url.pathname = "/metadata/networks";
|
|
47
|
+
url.search = "";
|
|
48
|
+
url.hash = "";
|
|
49
|
+
return url;
|
|
50
|
+
}
|
|
51
|
+
async function fetchNetworkCapabilities(config) {
|
|
52
|
+
const request = metadataNetworksUrl(resolveGraphMcpEndpoint(config));
|
|
53
|
+
const headers = new Headers();
|
|
54
|
+
const token = config.graphMcpAuthToken?.trim();
|
|
55
|
+
if (token) applyMcpAuthHeaders(headers, token);
|
|
56
|
+
let response;
|
|
57
|
+
try {
|
|
58
|
+
response = await fetch(request, { headers });
|
|
59
|
+
} catch (err) {
|
|
60
|
+
throw new Error(`network capabilities unavailable at ${request}: ${err.message}`);
|
|
61
|
+
}
|
|
62
|
+
if (!response.ok) throw new Error(`network capabilities unavailable at ${request}: HTTP ${response.status}`);
|
|
63
|
+
const parsed = await response.json();
|
|
64
|
+
if (parsed.schema !== "chain-insights.network-capabilities.v1" || !Array.isArray(parsed.networks)) throw new Error("network capabilities response has unsupported schema");
|
|
65
|
+
return publicNetworkCapabilities(parsed);
|
|
66
|
+
}
|
|
67
|
+
function layerValue(network, layer) {
|
|
68
|
+
if (!network.layers[layer]?.enabled) return "no";
|
|
69
|
+
return "yes";
|
|
70
|
+
}
|
|
71
|
+
function availableTools(network) {
|
|
72
|
+
const effectiveTools = BITTENSOR_SEMANTIC_NETWORKS.has(network.network) && network.layers.topology?.enabled === true ? {
|
|
73
|
+
...network.tools ?? {},
|
|
74
|
+
...PUBLIC_CHAIN_INSIGHTS_TOOL_STATUS
|
|
75
|
+
} : network.tools ?? {};
|
|
76
|
+
return Object.entries(effectiveTools).filter(([, status]) => status === "available").map(([name]) => name).sort();
|
|
77
|
+
}
|
|
78
|
+
function availableToolLines(network) {
|
|
79
|
+
const tools = availableTools(network);
|
|
80
|
+
if (tools.length === 0) return ["none"];
|
|
81
|
+
const lines = [];
|
|
82
|
+
for (let index = 0; index < tools.length; index += AVAILABLE_TOOLS_PER_LINE) lines.push(tools.slice(index, index + AVAILABLE_TOOLS_PER_LINE).join(", "));
|
|
83
|
+
return lines;
|
|
84
|
+
}
|
|
85
|
+
function shortDate(value) {
|
|
86
|
+
if (!value) return "";
|
|
87
|
+
return value.slice(0, 10);
|
|
88
|
+
}
|
|
89
|
+
function datasetLabel(network) {
|
|
90
|
+
const coverage = network.coverage;
|
|
91
|
+
if (!coverage) return "unknown";
|
|
92
|
+
const blockRange = coverage.from_block !== void 0 && coverage.to_block !== void 0 ? `${coverage.from_block}..${coverage.to_block}` : "blocks unknown";
|
|
93
|
+
const dateRange = coverage.from_timestamp && coverage.to_timestamp ? `${shortDate(coverage.from_timestamp)}..${shortDate(coverage.to_timestamp)}` : "";
|
|
94
|
+
if (blockRange === "blocks unknown" && dateRange === "") return "unknown";
|
|
95
|
+
if (blockRange === "blocks unknown") return dateRange;
|
|
96
|
+
if (dateRange === "") return blockRange;
|
|
97
|
+
return `${blockRange} / ${dateRange}`;
|
|
98
|
+
}
|
|
99
|
+
function formatNetworkCapabilities(document) {
|
|
100
|
+
if (document.networks.length === 0) return "No supported networks advertised.";
|
|
101
|
+
const headers = [
|
|
102
|
+
"Network",
|
|
103
|
+
"Topology",
|
|
104
|
+
"Facts",
|
|
105
|
+
"Risk",
|
|
106
|
+
"Dataset",
|
|
107
|
+
"Available tools"
|
|
108
|
+
];
|
|
109
|
+
const widths = [
|
|
110
|
+
14,
|
|
111
|
+
10,
|
|
112
|
+
8,
|
|
113
|
+
8,
|
|
114
|
+
38,
|
|
115
|
+
64
|
|
116
|
+
];
|
|
117
|
+
const row = (values) => values.map((value, index) => value.padEnd(widths[index])).join(" ");
|
|
118
|
+
const networkRows = document.networks.flatMap((network) => {
|
|
119
|
+
return availableToolLines(network).map((toolLine, index) => row([
|
|
120
|
+
index === 0 ? network.display_name || network.network : "",
|
|
121
|
+
index === 0 ? layerValue(network, "topology") : "",
|
|
122
|
+
index === 0 ? layerValue(network, "facts") : "",
|
|
123
|
+
index === 0 ? layerValue(network, "risk") : "",
|
|
124
|
+
index === 0 ? datasetLabel(network) : "",
|
|
125
|
+
toolLine
|
|
126
|
+
]));
|
|
127
|
+
});
|
|
128
|
+
return [
|
|
129
|
+
row(headers),
|
|
130
|
+
widths.map((width) => "-".repeat(width)).join(" "),
|
|
131
|
+
...networkRows
|
|
132
|
+
].join("\n");
|
|
133
|
+
}
|
|
134
|
+
//#endregion
|
|
135
|
+
export { fetchNetworkCapabilities, formatNetworkCapabilities };
|
|
136
|
+
|
|
137
|
+
//# sourceMappingURL=capabilities-GuF58uDa.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"capabilities-GuF58uDa.mjs","names":[],"sources":["../src/mcp/capabilities.ts"],"sourcesContent":["import type { InvestigatorConfig } from '../config/schema.js'\nimport { applyMcpAuthHeaders, resolveGraphMcpEndpoint } from './client.js'\n\nexport interface NetworkTopologyLayer {\n enabled: boolean\n coverage?: {\n from_block?: number\n to_block?: number\n from_timestamp?: string\n to_timestamp?: string\n chain_tip_block?: number\n blocks_behind_tip?: number\n }\n}\n\nexport interface NetworkLayerCapability {\n enabled: boolean\n live?: NetworkTopologyLayer\n archive?: NetworkTopologyLayer\n}\n\nexport interface NetworkCapability {\n network: string\n display_name?: string\n status: string\n default?: boolean\n layers: Record<string, NetworkLayerCapability>\n tools: Record<string, string>\n coverage?: {\n from_block?: number\n to_block?: number\n from_timestamp?: string\n to_timestamp?: string\n chain_tip_block?: number\n blocks_behind_tip?: number\n }\n freshness?: {\n last_processed_at?: string\n last_successful_sync_at?: string\n max_data_age_seconds?: number\n last_processing_duration_seconds?: number\n }\n}\n\nexport interface NetworkCapabilitiesDocument {\n schema: 'chain-insights.network-capabilities.v1'\n networks: NetworkCapability[]\n}\n\nconst BITTENSOR_SEMANTIC_NETWORKS = new Set(['bittensor', 'bittensor_evm', 'bittensor_semantic'])\nconst PUBLIC_CHAIN_INSIGHTS_TOOL_STATUS = {\n aml_address_risk: 'available',\n aml_trace_victim_funds: 'available',\n aml_trace_deposit_sources: 'available',\n aml_trace_suspect_funds: 'available',\n graph_query: 'available',\n graph_query_batch: 'available',\n meta_network_capabilities: 'available',\n meta_usage_status: 'available',\n wallet_balance: 'available',\n} as const\nconst AVAILABLE_TOOLS_PER_LINE = 3\n\nfunction publicNetworkCapabilities(document: NetworkCapabilitiesDocument): NetworkCapabilitiesDocument {\n const source = document.networks.find((network) => BITTENSOR_SEMANTIC_NETWORKS.has(network.network))\n return {\n schema: 'chain-insights.network-capabilities.v1',\n networks: source\n ? [{\n network: 'bittensor',\n display_name: 'Bittensor',\n status: source.status || 'live',\n default: source.default !== false,\n layers: {\n facts: { enabled: source.layers.facts?.enabled === true },\n risk: { enabled: source.layers.risk?.enabled === true },\n topology: {\n enabled: source.layers.topology?.enabled === true,\n ...(source.layers.topology?.live ? { live: source.layers.topology.live } : {}),\n ...(source.layers.topology?.archive ? { archive: source.layers.topology.archive } : {}),\n },\n },\n ...(source.coverage ? { coverage: source.coverage } : {}),\n ...(source.freshness ? { freshness: source.freshness } : {}),\n tools: PUBLIC_CHAIN_INSIGHTS_TOOL_STATUS,\n }]\n : [],\n }\n}\n\nfunction metadataNetworksUrl(endpoint: string): URL {\n const url = new URL(endpoint)\n url.pathname = '/metadata/networks'\n url.search = ''\n url.hash = ''\n return url\n}\n\nexport async function fetchNetworkCapabilities(\n config: Pick<InvestigatorConfig, 'graphMcpAuthToken' | 'graphMcpMode' | 'graphMcpEndpoint'>,\n): Promise<NetworkCapabilitiesDocument> {\n const endpoint = resolveGraphMcpEndpoint(config)\n const request = metadataNetworksUrl(endpoint)\n const headers = new Headers()\n const token = config.graphMcpAuthToken?.trim()\n if (token) {\n applyMcpAuthHeaders(headers, token)\n }\n let response: Response\n try {\n response = await fetch(request, { headers })\n } catch (err) {\n throw new Error(`network capabilities unavailable at ${request}: ${(err as Error).message}`)\n }\n if (!response.ok) {\n throw new Error(`network capabilities unavailable at ${request}: HTTP ${response.status}`)\n }\n const parsed = await response.json() as NetworkCapabilitiesDocument\n if (parsed.schema !== 'chain-insights.network-capabilities.v1' || !Array.isArray(parsed.networks)) {\n throw new Error('network capabilities response has unsupported schema')\n }\n return publicNetworkCapabilities(parsed)\n}\n\nfunction layerValue(network: NetworkCapability, layer: string): string {\n const capability = network.layers[layer]\n if (!capability?.enabled) return 'no'\n return 'yes'\n}\n\nfunction availableTools(network: NetworkCapability): string[] {\n const effectiveTools = BITTENSOR_SEMANTIC_NETWORKS.has(network.network) && network.layers.topology?.enabled === true\n ? {\n ...(network.tools ?? {}),\n ...PUBLIC_CHAIN_INSIGHTS_TOOL_STATUS,\n }\n : network.tools ?? {}\n const tools = Object.entries(effectiveTools)\n .filter(([, status]) => status === 'available')\n .map(([name]) => name)\n return tools.sort()\n}\n\nfunction availableToolLines(network: NetworkCapability): string[] {\n const tools = availableTools(network)\n if (tools.length === 0) return ['none']\n const lines: string[] = []\n for (let index = 0; index < tools.length; index += AVAILABLE_TOOLS_PER_LINE) {\n lines.push(tools.slice(index, index + AVAILABLE_TOOLS_PER_LINE).join(', '))\n }\n return lines\n}\n\nfunction shortDate(value?: string): string {\n if (!value) return ''\n return value.slice(0, 10)\n}\n\nfunction datasetLabel(network: NetworkCapability): string {\n const coverage = network.coverage\n if (!coverage) return 'unknown'\n const blockRange = coverage.from_block !== undefined && coverage.to_block !== undefined\n ? `${coverage.from_block}..${coverage.to_block}`\n : 'blocks unknown'\n const dateRange = coverage.from_timestamp && coverage.to_timestamp\n ? `${shortDate(coverage.from_timestamp)}..${shortDate(coverage.to_timestamp)}`\n : ''\n if (blockRange === 'blocks unknown' && dateRange === '') return 'unknown'\n if (blockRange === 'blocks unknown') return dateRange\n if (dateRange === '') return blockRange\n return `${blockRange} / ${dateRange}`\n}\n\nexport function formatNetworkCapabilities(document: NetworkCapabilitiesDocument): string {\n if (document.networks.length === 0) return 'No supported networks advertised.'\n const headers = ['Network', 'Topology', 'Facts', 'Risk', 'Dataset', 'Available tools']\n const widths = [14, 10, 8, 8, 38, 64]\n const row = (values: string[]) => values.map((value, index) => value.padEnd(widths[index]!)).join(' ')\n const networkRows = document.networks.flatMap((network) => {\n const toolLines = availableToolLines(network)\n return toolLines.map((toolLine, index) => row([\n index === 0 ? network.display_name || network.network : '',\n index === 0 ? layerValue(network, 'topology') : '',\n index === 0 ? layerValue(network, 'facts') : '',\n index === 0 ? layerValue(network, 'risk') : '',\n index === 0 ? datasetLabel(network) : '',\n toolLine,\n ]))\n })\n return [\n row(headers),\n widths.map((width) => '-'.repeat(width)).join(' '),\n ...networkRows,\n ].join('\\n')\n}\n"],"mappings":"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"}
|