Files
proxmox/scripts/validation/validate-official-protocol-integration-sources.mjs
defiQUG 4f9e33f8b8
All checks were successful
Deploy to Phoenix / validate (push) Successful in 1m19s
Deploy to Phoenix / deploy (push) Successful in 46s
Deploy to Phoenix / deploy-atomic-swap-dapp (push) Successful in 1m22s
phoenix-deploy Deployed to cloudflare-sync
Deploy to Phoenix / cloudflare (push) Successful in 37s
Advance All Mainnet bridge evidence and official protocol planning
2026-04-30 02:48:12 -07:00

86 lines
3.5 KiB
JavaScript

#!/usr/bin/env node
import { readFileSync } from "node:fs";
import { resolve } from "node:path";
const repoRoot = resolve(new URL("../..", import.meta.url).pathname);
const sourcePath = resolve(repoRoot, "config/official-protocol-integration-sources.json");
const addressPattern = /^0x[a-fA-F0-9]{40}$/;
function fail(message) {
console.error(`[validate-official-protocol-sources] ERROR: ${message}`);
process.exitCode = 1;
}
function isObject(value) {
return value && typeof value === "object" && !Array.isArray(value);
}
let config;
try {
config = JSON.parse(readFileSync(sourcePath, "utf8"));
} catch (error) {
fail(`cannot read ${sourcePath}: ${error.message}`);
process.exit();
}
if (typeof config.schemaVersion !== "string") fail("schemaVersion must be a string");
if (typeof config.updated !== "string") fail("updated must be a string");
if (!Array.isArray(config.guardrails) || config.guardrails.length === 0) fail("guardrails must be a non-empty array");
if (!isObject(config.protocols)) fail("protocols must be an object");
const protocols = config.protocols || {};
for (const [protocol, profile] of Object.entries(protocols)) {
if (!isObject(profile)) {
fail(`protocol ${protocol} must be an object`);
continue;
}
if (!Array.isArray(profile.officialSources) || profile.officialSources.length === 0) {
fail(`protocol ${protocol} must declare officialSources[]`);
} else {
for (const [index, source] of profile.officialSources.entries()) {
if (typeof source.label !== "string" || source.label.length === 0) {
fail(`protocol ${protocol} officialSources[${index}].label must be a non-empty string`);
}
if (typeof source.url !== "string" || !/^https:\/\//.test(source.url)) {
fail(`protocol ${protocol} officialSources[${index}].url must be https`);
}
if (typeof source.retrievedAt !== "string" || !/^\d{4}-\d{2}-\d{2}$/.test(source.retrievedAt)) {
fail(`protocol ${protocol} officialSources[${index}].retrievedAt must be YYYY-MM-DD`);
}
}
}
if (!isObject(profile.poolDiscovery)) {
fail(`protocol ${protocol} must declare poolDiscovery`);
}
for (const [chainId, chain] of Object.entries(profile.chainFactories || {})) {
if (!/^\d+$/.test(chainId)) fail(`protocol ${protocol} chainFactories key ${chainId} must be numeric`);
for (const key of ["dvmFactory", "factory", "router", "vault"]) {
if (chain[key] && !addressPattern.test(chain[key])) {
fail(`protocol ${protocol} chain ${chainId} ${key} must be an EVM address`);
}
}
if (typeof chain.network !== "string" || chain.network.length === 0) {
fail(`protocol ${protocol} chain ${chainId} network must be a non-empty string`);
}
if (typeof chain.source !== "string" || chain.source.length === 0) {
fail(`protocol ${protocol} chain ${chainId} source must be a non-empty string`);
}
}
for (const [chainId, chain] of Object.entries(profile.unsupportedOrUnverifiedChains || {})) {
if (!/^\d+$/.test(chainId)) fail(`protocol ${protocol} unsupported key ${chainId} must be numeric`);
if (typeof chain.network !== "string" || chain.network.length === 0) {
fail(`protocol ${protocol} unsupported ${chainId} network must be a non-empty string`);
}
if (typeof chain.status !== "string" || chain.status.length === 0) {
fail(`protocol ${protocol} unsupported ${chainId} status must be a non-empty string`);
}
}
}
if (process.exitCode) process.exit();
console.log(`[validate-official-protocol-sources] OK: ${Object.keys(protocols).length} protocol profile(s)`);