Files
proxmox/scripts/verify/build-network-deployment-inventory.mjs
defiQUG b8613905bd
Some checks failed
Deploy to Phoenix / validate (push) Failing after 15s
Deploy to Phoenix / deploy (push) Has been skipped
chore: sync workspace — configs, docs, scripts, CI, pnpm, submodules
- Submodule pins: dbis_core, cross-chain-pmm-lps, mcp-proxmox (local, push may be pending), metamask-integration, smom-dbis-138
- Atomic swap + cross-chain-pmm-lops-publish, deploy-portal workflow, phoenix deploy-targets, routing/aggregator matrices
- Docs, token-lists, forge proxy, phoenix API, runbooks, verify scripts

Made-with: Cursor
2026-04-21 22:01:33 -07:00

318 lines
12 KiB
JavaScript

#!/usr/bin/env node
import fs from "node:fs";
import path from "node:path";
import { fileURLToPath } from "node:url";
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const repoRoot = path.resolve(__dirname, "..", "..");
const deploymentStatusPath = path.join(repoRoot, "cross-chain-pmm-lps/config/deployment-status.json");
const manifestPath = path.join(repoRoot, "atomic-swap-dapp/config/ecosystem-manifest.json");
const liveRouteRegistryPath = path.join(repoRoot, "atomic-swap-dapp/config/live-route-registry.json");
const routingRegistryPath = path.join(repoRoot, "config/routing-registry.json");
const allMainnetProtocolSurfacePath = path.join(repoRoot, "config/allmainnet-non-dodo-protocol-surface.json");
const allMainnetTokenDocPath = path.join(repoRoot, "docs/11-references/ALL_MAINNET_TOKEN_ADDRESSES.md");
const markdownOutputPath = path.join(repoRoot, "reports/status/network-deployment-inventory-latest.md");
const jsonOutputPath = path.join(repoRoot, "reports/status/network-deployment-inventory-latest.json");
function readJson(filePath) {
return JSON.parse(fs.readFileSync(filePath, "utf8"));
}
function writeText(filePath, content) {
fs.mkdirSync(path.dirname(filePath), { recursive: true });
fs.writeFileSync(filePath, content);
}
function normalizeBool(value) {
if (value === true) return "✓";
if (value === false) return "—";
return "?";
}
function parseMarkdownTable(markdown, sectionTitle) {
const lines = markdown.split("\n");
const heading = `### ${sectionTitle}`;
const startIndex = lines.findIndex((line) => line.trim() === heading);
if (startIndex === -1) {
return [];
}
const tableLines = [];
for (const rawLine of lines.slice(startIndex + 1)) {
const line = rawLine.trim();
if (line.startsWith("### ") || line.startsWith("## ")) {
break;
}
tableLines.push(line);
}
const relevant = tableLines.filter((line) => line.startsWith("|"));
if (relevant.length < 3) {
return [];
}
const headers = relevant[0]
.split("|")
.slice(1, -1)
.map((cell) => cell.trim());
return relevant.slice(2).map((line) => {
const values = line
.split("|")
.slice(1, -1)
.map((cell) => cell.trim());
return Object.fromEntries(headers.map((header, index) => [header, values[index] ?? ""]));
}).filter(
(row) =>
row.Symbol &&
row.Symbol !== "Symbol" &&
row.Symbol !== "--------" &&
row.Address &&
row.Address !== "Address" &&
row.Address !== "---------"
);
}
function parseAllMainnetTokens(markdown) {
const sections = ["Stablecoins", "Wrapped Tokens", "DeFi Tokens"];
return sections.flatMap((section) =>
parseMarkdownTable(markdown, section).map((row) => ({
category: section,
token: row.Token,
symbol: row.Symbol,
address: row.Address?.replace(/`/g, "") ?? "",
decimals: Number(row.Decimals || 0),
status: row.Status,
notes: row.Notes
}))
);
}
function buildSpecialCaseBridgeList(liveRouteRegistry, routingRegistry, chainId) {
const liveRoutes = (liveRouteRegistry.liveBridgeRoutes ?? [])
.filter((route) => Number(route.fromChainId) === Number(chainId) || Number(route.toChainId) === Number(chainId))
.map((route) => ({
routeId: route.routeId,
fromChainId: route.fromChainId,
toChainId: route.toChainId,
bridgeType: route.bridgeType,
asset: route.assetSymbol,
bridgeAddress: route.bridgeAddress,
status: "live"
}));
if (liveRoutes.length > 0) {
return liveRoutes;
}
return (routingRegistry.routes ?? [])
.filter((route) => Number(route.fromChain) === Number(chainId) || Number(route.toChain) === Number(chainId))
.map((route) => ({
routeId: `${route.fromChain}-${route.toChain}-${route.asset}-${route.pathType}`.toLowerCase(),
fromChainId: route.fromChain,
toChainId: route.toChain,
bridgeType: route.pathType,
asset: route.asset,
bridgeAddress: route.bridgeAddress,
status: "configured"
}));
}
function countTokens(chainStatus) {
return Object.keys(chainStatus.cwTokens ?? {}).length;
}
function countAnchors(chainStatus) {
return Object.keys(chainStatus.anchorAddresses ?? {}).length;
}
function countPools(chainStatus, key) {
return Array.isArray(chainStatus[key]) ? chainStatus[key].length : 0;
}
function buildNextTasks(chainId) {
switch (Number(chainId)) {
case 138:
return [
"Keep Chain 138 PMM inventory, live swap routes, and public manifest synchronized after every token or pool deployment.",
"Replace remaining placeholder bridge metadata with canonical deployed addresses and keep bridge notes current.",
"Re-run route, inventory, and explorer verification audits after any bridge or pool change.",
"Maintain source-chain bridge support for CCIP, GRU, and Alltra routes as the canonical launch surface."
];
case 1111:
return [
"Keep Wemix marked `planned_gas_scaffold` and `bridgeAvailable: false` until a successful bridge proof transfer is recorded.",
"Replace placeholder gas PMM pools and gas reference venues with real deployed venues or remove them from the launch inventory.",
"Complete canonical Wemix bridge readiness: funding, proof transfer verification, and any required inbound/outbound confirmation.",
"Add real same-chain settlement inventory only after WEMIX-side execution is actually deployed and routable."
];
case 651940:
return [
"Add real same-chain Alltra swap inventory if users should settle into assets other than direct bridge receive.",
"Publish deployed PMM or public DEX pool addresses into canonical inventory instead of anchor-only metadata.",
"Expand the canonical Alltra token/routing surface only when those assets are actually part of supported settlement flows.",
"Keep AlltraAdapter bridge metadata, supported assets, and fee assumptions synchronized with deployed bridge behavior."
];
default:
return [];
}
}
function main() {
const deploymentStatus = readJson(deploymentStatusPath);
const manifest = readJson(manifestPath);
const liveRouteRegistry = readJson(liveRouteRegistryPath);
const routingRegistry = readJson(routingRegistryPath);
const allMainnetProtocolSurface = readJson(allMainnetProtocolSurfacePath);
const allMainnetTokenDoc = fs.readFileSync(allMainnetTokenDocPath, "utf8");
const supportedNetworks = manifest.supportedNetworks ?? [];
const manifestByChain = new Map(supportedNetworks.map((network) => [String(network.chainId), network]));
const allMainnetTokens = parseAllMainnetTokens(allMainnetTokenDoc);
const chains = Object.entries(deploymentStatus.chains ?? {})
.map(([chainId, status]) => {
const manifestRow = manifestByChain.get(chainId) ?? {};
return {
chainId: Number(chainId),
chainKey: chainId,
network: status.name ?? manifestRow.name ?? `Chain ${chainId}`,
activationState: status.activationState ?? manifestRow.activationState ?? "live",
bridgeAvailable:
typeof status.bridgeAvailable === "boolean"
? status.bridgeAvailable
: Boolean(manifestRow.bridgeAvailable),
tokenCount: countTokens(status),
anchorCount: countAnchors(status),
pmmPoolCount: countPools(status, "pmmPools"),
volatilePoolCount: countPools(status, "pmmPoolsVolatile"),
gasPmmPoolCount: countPools(status, "gasPmmPools"),
referenceVenueCount: countPools(status, "gasReferenceVenues"),
uniswapV2PoolCount: countPools(status, "uniswapV2Pools"),
bridgeRouteCount: (manifestRow.routeCoverage?.inboundBridgeRoutes ?? 0) + (manifestRow.routeCoverage?.outboundBridgeRoutes ?? 0),
cwTokens: status.cwTokens ?? {},
anchorAddresses: status.anchorAddresses ?? {},
gasMirrors: status.gasMirrors ?? {},
gasQuoteAddresses: status.gasQuoteAddresses ?? {},
specialCaseBridges: buildSpecialCaseBridgeList(liveRouteRegistry, routingRegistry, chainId)
};
})
.sort((left, right) => left.chainId - right.chainId);
const specialCases = chains
.filter((chain) => [138, 1111, 651940].includes(chain.chainId))
.map((chain) => ({
...chain,
documentedTokens:
chain.chainId === 651940
? (allMainnetProtocolSurface.documentedTokens ?? allMainnetTokens)
: [],
nextTasks: buildNextTasks(chain.chainId)
}));
const markdown = [
"# Network Deployment Inventory",
"",
"| Chain | Network | Activation | Bridge Available | Tokens | Anchors | PMM | Volatile | Gas PMM | Ref Venues | UniV2 | Bridge Routes |",
"|---:|---|---|:---:|---:|---:|---:|---:|---:|---:|---:|---:|",
...chains.map(
(chain) =>
`| \`${chain.chainId}\` | ${chain.network} | \`${chain.activationState}\` | ${normalizeBool(chain.bridgeAvailable)} | ${chain.tokenCount} | ${chain.anchorCount} | ${chain.pmmPoolCount} | ${chain.volatilePoolCount} | ${chain.gasPmmPoolCount} | ${chain.referenceVenueCount} | ${chain.uniswapV2PoolCount} | ${chain.bridgeRouteCount} |`
),
"",
"## Special-Case Networks",
"",
...specialCases.flatMap((chain) => {
const bridgeLines =
chain.specialCaseBridges.length > 0
? chain.specialCaseBridges.map(
(bridge) =>
` - \`${bridge.fromChainId} -> ${bridge.toChainId}\` \`${bridge.bridgeType}\` \`${bridge.asset}\` at \`${bridge.bridgeAddress}\``
)
: [" - none recorded"];
const documentedTokenLines =
chain.documentedTokens.length > 0
? [
"",
"- Documented ecosystem tokens:",
...chain.documentedTokens.map(
(token) =>
` - \`${token.symbol}\` ${token.address} (${token.decimals} decimals; ${token.category}; ${token.status})`
)
]
: [];
return [
`### \`${chain.chainId}\` ${chain.network}`,
"",
`- Activation state: \`${chain.activationState}\``,
`- Bridge available: \`${chain.bridgeAvailable}\``,
`- cW tokens: ${Object.keys(chain.cwTokens).length ? Object.keys(chain.cwTokens).join(", ") : "none"}`,
`- Anchors: ${Object.keys(chain.anchorAddresses).length ? Object.entries(chain.anchorAddresses).map(([symbol, address]) => `${symbol}=${address}`).join(", ") : "none"}`,
`- PMM pools: \`${chain.pmmPoolCount}\``,
`- Gas PMM pools: \`${chain.gasPmmPoolCount}\``,
`- Gas/reference venues: \`${chain.referenceVenueCount}\``,
`- UniV2 pools: \`${chain.uniswapV2PoolCount}\``,
"- Bridge routes:",
...bridgeLines,
...documentedTokenLines,
"",
"- Next tasks:",
...chain.nextTasks.map((task) => ` - ${task}`),
""
];
})
].join("\n");
const json = {
name: "Network Deployment Inventory",
generatedAt: new Date().toISOString(),
sourceFiles: [
path.relative(repoRoot, deploymentStatusPath),
path.relative(repoRoot, manifestPath),
path.relative(repoRoot, liveRouteRegistryPath),
path.relative(repoRoot, routingRegistryPath),
path.relative(repoRoot, allMainnetProtocolSurfacePath),
path.relative(repoRoot, allMainnetTokenDocPath)
],
networks: chains.map((chain) => ({
chainId: chain.chainId,
network: chain.network,
activationState: chain.activationState,
bridgeAvailable: chain.bridgeAvailable,
tokenCount: chain.tokenCount,
anchorCount: chain.anchorCount,
pmmPoolCount: chain.pmmPoolCount,
volatilePoolCount: chain.volatilePoolCount,
gasPmmPoolCount: chain.gasPmmPoolCount,
referenceVenueCount: chain.referenceVenueCount,
uniswapV2PoolCount: chain.uniswapV2PoolCount,
bridgeRouteCount: chain.bridgeRouteCount
})),
specialCases: specialCases.map((chain) => ({
chainId: chain.chainId,
network: chain.network,
activationState: chain.activationState,
bridgeAvailable: chain.bridgeAvailable,
cwTokens: chain.cwTokens,
anchors: chain.anchorAddresses,
gasMirrors: chain.gasMirrors,
gasQuoteAddresses: chain.gasQuoteAddresses,
bridgeRoutes: chain.specialCaseBridges,
documentedTokens: chain.documentedTokens,
nextTasks: chain.nextTasks
}))
};
writeText(markdownOutputPath, `${markdown}\n`);
writeText(jsonOutputPath, `${JSON.stringify(json, null, 2)}\n`);
console.log(`Wrote ${path.relative(repoRoot, markdownOutputPath)}`);
console.log(`Wrote ${path.relative(repoRoot, jsonOutputPath)}`);
}
main();