All checks were successful
Deploy to Phoenix / validate (push) Successful in 1m21s
Deploy to Phoenix / deploy (push) Successful in 48s
Deploy to Phoenix / deploy-atomic-swap-dapp (push) Successful in 1m20s
phoenix-deploy Deployed to cloudflare-sync
Deploy to Phoenix / cloudflare (push) Successful in 40s
292 lines
11 KiB
JavaScript
292 lines
11 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* Build a read-only official protocol integration plan.
|
|
*
|
|
* This does not execute transactions. It identifies replacement pools that
|
|
* should be migrated to protocol-native official deployments, optional protocol
|
|
* rows that still need official factory/router/pool evidence, and the minimum
|
|
* unwind/repeg/depth work needed before treating liquidity as deep production.
|
|
*/
|
|
|
|
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
import { resolve } from "node:path";
|
|
|
|
const repoRoot = resolve(new URL("../..", import.meta.url).pathname);
|
|
const matrixPath = resolve(repoRoot, "config/all-mainnet-pool-creation-matrix.json");
|
|
const sourcePath = resolve(repoRoot, "config/official-protocol-integration-sources.json");
|
|
const discoveryPath = resolve(repoRoot, "reports/status/all-mainnet-official-dodo-discovery-latest.json");
|
|
const outJson = resolve(repoRoot, "reports/status/all-mainnet-official-protocol-integration-plan-latest.json");
|
|
const outMd = resolve(repoRoot, "reports/status/all-mainnet-official-protocol-integration-plan-latest.md");
|
|
|
|
function readJson(path) {
|
|
return JSON.parse(readFileSync(path, "utf8"));
|
|
}
|
|
|
|
function table(headers, rows) {
|
|
return [
|
|
`| ${headers.join(" | ")} |`,
|
|
`| ${headers.map(() => "---").join(" | ")} |`,
|
|
...rows.map((row) => `| ${row.map((cell) => String(cell ?? "").replace(/\|/g, "\\|")).join(" | ")} |`),
|
|
].join("\n");
|
|
}
|
|
|
|
function pair(row) {
|
|
return `${row.baseToken?.symbol || "?"}/${row.quoteToken?.symbol || "?"}`;
|
|
}
|
|
|
|
function raw(value) {
|
|
try {
|
|
return BigInt(value || "0");
|
|
} catch {
|
|
return 0n;
|
|
}
|
|
}
|
|
|
|
function imbalanceBps(baseRaw, quoteRaw) {
|
|
const base = raw(baseRaw);
|
|
const quote = raw(quoteRaw);
|
|
const high = base > quote ? base : quote;
|
|
const low = base > quote ? quote : base;
|
|
if (high === 0n) return null;
|
|
return Number(((high - low) * 10_000n) / high);
|
|
}
|
|
|
|
function protocolSource(sources, protocol) {
|
|
return sources.protocols?.[protocol] || null;
|
|
}
|
|
|
|
function dodoOfficialFactory(source, chainId) {
|
|
const key = String(chainId);
|
|
return source?.chainFactories?.[key]?.dvmFactory || null;
|
|
}
|
|
|
|
function discoverySeeded(discoveryRow) {
|
|
return (discoveryRow?.poolEvidence || []).some((pool) => pool.seeded === true);
|
|
}
|
|
|
|
function replacementMigration(row, sources, discoveryByPoolId) {
|
|
const source = protocolSource(sources, row.protocol);
|
|
const officialFactory = row.protocol === "dodo_pmm" ? dodoOfficialFactory(source, row.chainId) : null;
|
|
const unsupported = row.protocol === "dodo_pmm"
|
|
? source?.unsupportedOrUnverifiedChains?.[String(row.chainId)]?.status || null
|
|
: null;
|
|
const discovery = discoveryByPoolId.get(row.poolId) || null;
|
|
const seededOfficialPool = discoverySeeded(discovery);
|
|
const officialPools = (discovery?.poolEvidence || []).map((pool) => ({
|
|
poolAddress: pool.poolAddress,
|
|
baseReserveRaw: pool.baseReserveRaw || null,
|
|
quoteReserveRaw: pool.quoteReserveRaw || null,
|
|
totalSupplyRaw: pool.totalSupplyRaw || null,
|
|
seeded: pool.seeded === true,
|
|
}));
|
|
return {
|
|
poolId: row.poolId,
|
|
chainId: row.chainId,
|
|
network: row.network,
|
|
protocol: row.protocol,
|
|
pair: pair(row),
|
|
currentPoolAddress: row.poolAddress,
|
|
temporaryReplacement: Boolean(row.replacementEvidence),
|
|
oldPoolAddress: row.replacementEvidence?.oldPoolAddress || null,
|
|
officialFactory,
|
|
officialSourceStatus: seededOfficialPool
|
|
? "official_pool_seeded"
|
|
: officialFactory ? (discovery?.status || "official_factory_available") : unsupported || "official_source_not_committed",
|
|
officialPools,
|
|
migrationCompleteThroughSeed: seededOfficialPool,
|
|
actions: [
|
|
seededOfficialPool ? "record_official_seed_evidence" : officialFactory ? "discover_existing_official_pool" : "confirm_official_factory_or_choose_alternate_protocol",
|
|
seededOfficialPool ? "run_protocol_native_canaries" : officialFactory ? "create_official_pool_if_absent" : "keep_replacement_pool_read_only_until_supported",
|
|
seededOfficialPool ? "switch_public_routing_to_official_pool_after_canary" : "seed_official_pool_to_target_depth",
|
|
"run_oracle_normalized_repeg_check",
|
|
"run_10_100_1000_canaries",
|
|
"switch_public_routing_to_official_pool",
|
|
"mark_replacement_pool_deprecated",
|
|
"attempt_recoverable_old_pool_unwind_or_record_stranded_dust",
|
|
],
|
|
};
|
|
}
|
|
|
|
function optionalProtocolAction(row, sources) {
|
|
const source = protocolSource(sources, row.protocol);
|
|
const hasAddresses = Boolean(row.factoryAddress || row.routerAddress || row.poolAddress || row.vaultAddress);
|
|
return {
|
|
poolId: row.poolId,
|
|
chainId: row.chainId,
|
|
network: row.network,
|
|
protocol: row.protocol,
|
|
pair: pair(row),
|
|
status: row.status,
|
|
hasAnyAddress: hasAddresses,
|
|
sourceProfile: source?.poolDiscovery?.factoryProfile || source?.poolDiscovery?.integrationProfile || source?.poolDiscovery?.vaultProfile || null,
|
|
actions: [
|
|
"import_official_factory_router_or_vault_from_source",
|
|
"discover_or_create_pool_using_official_method",
|
|
"record_pool_address_and_source_evidence",
|
|
"fund_to_seed_depth",
|
|
"run_live_reserve_read",
|
|
"run_protocol_native_canary",
|
|
"promote_only_after_canary_and_unwind_path_are_recorded",
|
|
],
|
|
};
|
|
}
|
|
|
|
function depthIntent(row) {
|
|
const base = row.reserveEvidence?.baseBalanceRaw || "0";
|
|
const quote = row.reserveEvidence?.quoteBalanceRaw || "0";
|
|
const skew = imbalanceBps(base, quote);
|
|
const minReserveUsd = row.policy?.minReserveUsd ?? 1000;
|
|
return {
|
|
poolId: row.poolId,
|
|
chainId: row.chainId,
|
|
network: row.network,
|
|
protocol: row.protocol,
|
|
pair: pair(row),
|
|
currentBaseRaw: base,
|
|
currentQuoteRaw: quote,
|
|
rawImbalanceBps: skew,
|
|
currentPolicyMinReserveUsd: minReserveUsd,
|
|
proposedDepthTiersUsd: {
|
|
smoke: Math.max(100, Math.floor(minReserveUsd / 10)),
|
|
productionMinimum: minReserveUsd,
|
|
targetDepth: Math.max(10_000, minReserveUsd * 10),
|
|
institutionalDepthCandidate: Math.max(100_000, minReserveUsd * 100),
|
|
},
|
|
actions: [
|
|
"price_base_and_quote_with_iso4217_oracle_currency",
|
|
"compute_value_normalized_base_and_quote_reserves",
|
|
"top_up_short_side_first",
|
|
"increase_both_sides_in_tranches",
|
|
"rerun_canary_after_each_depth_tier",
|
|
],
|
|
};
|
|
}
|
|
|
|
const matrix = readJson(matrixPath);
|
|
const sources = readJson(sourcePath);
|
|
const discovery = existsSync(discoveryPath) ? readJson(discoveryPath) : { rows: [] };
|
|
const discoveryByPoolId = new Map((discovery.rows || []).map((row) => [row.poolId, row]));
|
|
const generatedAt = new Date().toISOString();
|
|
const requiredRows = matrix.rows.filter((row) => row.requiredForSpend === true);
|
|
const replacementRows = requiredRows.filter((row) => row.replacementEvidence);
|
|
const optionalRows = matrix.rows.filter((row) => row.requiredForSpend !== true);
|
|
const officialMigrations = replacementRows.map((row) => replacementMigration(row, sources, discoveryByPoolId));
|
|
const optionalProtocolRows = optionalRows
|
|
.filter((row) => ["sushiswap_v2", "curve_stable", "balancer_weighted", "aave_backstop", "oneinch_aggregator", "uniswap_v2", "dodo_pmm"].includes(row.protocol))
|
|
.map((row) => optionalProtocolAction(row, sources));
|
|
const depthIntents = requiredRows.map(depthIntent);
|
|
const unwindRows = replacementRows.map((row) => ({
|
|
poolId: row.poolId,
|
|
chainId: row.chainId,
|
|
network: row.network,
|
|
pair: pair(row),
|
|
replacementPoolAddress: row.poolAddress,
|
|
oldPoolAddress: row.replacementEvidence?.oldPoolAddress || null,
|
|
status: "unwind_or_deprecation_required",
|
|
actions: [
|
|
"read_replacement_pool_lp_share_balance",
|
|
"read_old_pool_token_balances",
|
|
"if_official_exit_supported_withdraw_or_remove_liquidity",
|
|
"if_no_exit_supported_mark_deprecated_and_route_disabled_after_migration",
|
|
"record_stranded_or_recovered_balances",
|
|
],
|
|
}));
|
|
|
|
const report = {
|
|
generatedAt,
|
|
mode: "read_only_official_protocol_integration_plan",
|
|
sourcesFile: "config/official-protocol-integration-sources.json",
|
|
matrixFile: "config/all-mainnet-pool-creation-matrix.json",
|
|
summary: {
|
|
requiredRows: requiredRows.length,
|
|
replacementRowsNeedingOfficialMigration: officialMigrations.filter((row) => !row.migrationCompleteThroughSeed).length,
|
|
replacementRowsWithSeededOfficialPool: officialMigrations.filter((row) => row.migrationCompleteThroughSeed).length,
|
|
optionalProtocolRowsNeedingOfficialEvidence: optionalProtocolRows.length,
|
|
depthRows: depthIntents.length,
|
|
unwindRows: unwindRows.length,
|
|
productionGateCurrentlyReady: requiredRows.every((row) => row.status === "production"),
|
|
},
|
|
guardrails: sources.guardrails,
|
|
officialMigrations,
|
|
optionalProtocolRows,
|
|
depthIntents,
|
|
unwindRows,
|
|
executionOrder: [
|
|
"verify_official_sources_and_chain_support",
|
|
"query_existing_official_pools",
|
|
"create_missing_official_pools_only_where_supported",
|
|
"seed_official_pools_to_smoke_depth",
|
|
"run_oracle_normalized_repeg_plan",
|
|
"run_protocol_native_canaries",
|
|
"switch_routes_from_replacement_to_official_pools",
|
|
"unwind_or_deprecate_replacement_and_old_stub_pools",
|
|
"increase_depth_in_tranches",
|
|
"enable_optional_protocol_rows_after_native_canaries",
|
|
],
|
|
};
|
|
|
|
const md = [
|
|
"# ALL Mainnet Official Protocol Integration Plan",
|
|
"",
|
|
`- Generated: \`${generatedAt}\``,
|
|
"- Mode: read-only; no transactions executed.",
|
|
"",
|
|
table(
|
|
["Metric", "Count"],
|
|
Object.entries(report.summary).map(([key, value]) => [key, value]),
|
|
),
|
|
"",
|
|
"## Official Migrations",
|
|
"",
|
|
table(
|
|
["Pool", "Chain", "Protocol", "Pair", "Current Pool", "Official Factory", "Status"],
|
|
officialMigrations.map((row) => [
|
|
row.poolId,
|
|
row.chainId,
|
|
row.protocol,
|
|
row.pair,
|
|
row.currentPoolAddress,
|
|
row.officialFactory || "",
|
|
row.officialSourceStatus,
|
|
]),
|
|
),
|
|
"",
|
|
"## Unwind / Deprecation",
|
|
"",
|
|
table(
|
|
["Pool", "Chain", "Pair", "Replacement Pool", "Old Pool", "Status"],
|
|
unwindRows.map((row) => [
|
|
row.poolId,
|
|
row.chainId,
|
|
row.pair,
|
|
row.replacementPoolAddress,
|
|
row.oldPoolAddress || "",
|
|
row.status,
|
|
]),
|
|
),
|
|
"",
|
|
"## Optional Protocol Rows",
|
|
"",
|
|
table(
|
|
["Pool", "Chain", "Protocol", "Pair", "Status", "Source Profile"],
|
|
optionalProtocolRows.map((row) => [
|
|
row.poolId,
|
|
row.chainId,
|
|
row.protocol,
|
|
row.pair,
|
|
row.status,
|
|
row.sourceProfile || "",
|
|
]),
|
|
),
|
|
"",
|
|
"## Execution Order",
|
|
"",
|
|
...report.executionOrder.map((step, index) => `${index + 1}. \`${step}\``),
|
|
"",
|
|
].join("\n");
|
|
|
|
mkdirSync(resolve(repoRoot, "reports/status"), { recursive: true });
|
|
writeFileSync(outJson, `${JSON.stringify(report, null, 2)}\n`);
|
|
writeFileSync(outMd, `${md}\n`);
|
|
console.log(`[OK] Official protocol integration plan written: ${outJson}`);
|