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
86 lines
3.5 KiB
JavaScript
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)`);
|