Sync workspace: config, docs, scripts, CI, operator rules, and submodule pointers.
- Update dbis_core, cross-chain-pmm-lps, explorer-monorepo, metamask-integration, pr-workspace/chains - Omit embedded publish git dirs and empty placeholders from index Made-with: Cursor
This commit is contained in:
@@ -104,6 +104,9 @@ else
|
||||
and (.approvedBridgePeers | type == "array")
|
||||
and (.transportPairs | type == "array")
|
||||
and (.publicPools | type == "array")
|
||||
and ((.gasAssetFamilies == null) or (.gasAssetFamilies | type == "array"))
|
||||
and ((.gasRedeemGroups == null) or (.gasRedeemGroups | type == "array"))
|
||||
and ((.gasProtocolExposure == null) or (.gasProtocolExposure | type == "array"))
|
||||
' "$PROJECT_ROOT/config/gru-transport-active.json" &>/dev/null; then
|
||||
log_ok "gru-transport-active.json: top-level overlay structure is valid"
|
||||
else
|
||||
@@ -144,6 +147,7 @@ const multichain = readJson('config/token-mapping-multichain.json');
|
||||
const deployment = readJson('cross-chain-pmm-lps/config/deployment-status.json');
|
||||
const poolMatrix = readJson('cross-chain-pmm-lps/config/pool-matrix.json');
|
||||
const currencyManifest = readJson('config/gru-iso4217-currency-manifest.json');
|
||||
const monetaryUnitManifest = readJson('config/gru-monetary-unit-manifest.json');
|
||||
|
||||
const errors = [];
|
||||
|
||||
@@ -159,6 +163,15 @@ const reserveVerifiers = active.reserveVerifiers && typeof active.reserveVerifie
|
||||
const transportPairsByKey = new Map((active.transportPairs || []).map((pair) => [String(pair.key), pair]));
|
||||
const publicPoolsByKey = new Map((active.publicPools || []).map((pool) => [String(pool.key), pool]));
|
||||
const manifestByCode = new Map((currencyManifest.currencies || []).map((currency) => [String(currency.code), currency]));
|
||||
const monetaryUnitsByCode = new Map((monetaryUnitManifest.monetaryUnits || []).map((unit) => [String(unit.code), unit]));
|
||||
const gasFamiliesByKey = new Map(((active.gasAssetFamilies || [])).map((family) => [String(family.familyKey), family]));
|
||||
const gasFamiliesBySymbol = new Map(
|
||||
(active.gasAssetFamilies || []).flatMap((family) => [
|
||||
[String(family.canonicalSymbol138), family],
|
||||
[String(family.mirroredSymbol), family],
|
||||
])
|
||||
);
|
||||
const gasProtocolExposureByKey = new Map((active.gasProtocolExposure || []).map((row) => [String(row.key), row]));
|
||||
|
||||
function getMappingPair(fromChainId, toChainId) {
|
||||
return (multichain.pairs || []).find(
|
||||
@@ -186,6 +199,30 @@ for (const chain of active.enabledDestinationChains || []) {
|
||||
}
|
||||
|
||||
for (const token of enabledCanonicalTokens) {
|
||||
const registryFamily = String(token.registryFamily || '').trim();
|
||||
if (registryFamily === 'gas_native') {
|
||||
const gasFamily = gasFamiliesByKey.get(String(token.familyKey || '')) || gasFamiliesBySymbol.get(String(token.symbol || ''));
|
||||
if (!gasFamily) {
|
||||
errors.push(`enabledCanonicalTokens[${token.symbol}] references missing gas family ${token.familyKey}`);
|
||||
continue;
|
||||
}
|
||||
if (String(gasFamily.canonicalSymbol138 || '') !== String(token.symbol || '')) {
|
||||
errors.push(`enabledCanonicalTokens[${token.symbol}] must match gasAssetFamilies canonicalSymbol138`);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (registryFamily === 'monetary_unit') {
|
||||
const monetaryUnit = monetaryUnitsByCode.get(String(token.currencyCode || ''));
|
||||
if (!monetaryUnit) {
|
||||
errors.push(`enabledCanonicalTokens[${token.symbol}] references missing monetary unit ${token.currencyCode} in gru-monetary-unit-manifest.json`);
|
||||
continue;
|
||||
}
|
||||
if (String(monetaryUnit.canonicalSymbol || '') !== String(token.symbol || '')) {
|
||||
errors.push(`enabledCanonicalTokens[${token.symbol}] must match gru-monetary-unit-manifest.json canonicalSymbol`);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
const currency = manifestByCode.get(String(token.currencyCode || ''));
|
||||
if (!currency) {
|
||||
errors.push(`enabledCanonicalTokens[${token.symbol}] references missing currencyCode ${token.currencyCode} in gru-iso4217-currency-manifest.json`);
|
||||
@@ -243,13 +280,40 @@ for (const pair of active.transportPairs || []) {
|
||||
}
|
||||
|
||||
const deploymentChain = deployment.chains?.[String(destinationChainId)];
|
||||
const deployedMirror = deploymentChain?.cwTokens?.[mirroredSymbol];
|
||||
const deployedMirror = deploymentChain?.cwTokens?.[mirroredSymbol] || deploymentChain?.gasMirrors?.[mirroredSymbol];
|
||||
if (!deploymentChain || !isNonZeroAddress(deployedMirror)) {
|
||||
errors.push(`transportPairs[${pair.key}] mapping exists but deployment-status.json has no deployed ${mirroredSymbol} for chain ${destinationChainId}`);
|
||||
} else if (mappingToken && normalizeAddress(deployedMirror) !== normalizeAddress(mappingToken.addressTo)) {
|
||||
errors.push(`transportPairs[${pair.key}] deployment-status.json ${mirroredSymbol} does not match token-mapping-multichain.json addressTo`);
|
||||
}
|
||||
|
||||
if (pair.assetClass === 'gas_native') {
|
||||
const gasFamily =
|
||||
gasFamiliesByKey.get(String(pair.familyKey || '')) ||
|
||||
gasFamiliesBySymbol.get(canonicalSymbol) ||
|
||||
gasFamiliesBySymbol.get(mirroredSymbol);
|
||||
if (!gasFamily) {
|
||||
errors.push(`transportPairs[${pair.key}] references missing gas family ${pair.familyKey}`);
|
||||
} else {
|
||||
if (String(gasFamily.canonicalSymbol138 || '') !== canonicalSymbol) {
|
||||
errors.push(`transportPairs[${pair.key}] canonicalSymbol must match gas family canonicalSymbol138`);
|
||||
}
|
||||
if (String(gasFamily.mirroredSymbol || '') !== mirroredSymbol) {
|
||||
errors.push(`transportPairs[${pair.key}] mirroredSymbol must match gas family mirroredSymbol`);
|
||||
}
|
||||
if (String(gasFamily.backingMode || '') !== String(pair.backingMode || '')) {
|
||||
errors.push(`transportPairs[${pair.key}] backingMode must match gas family`);
|
||||
}
|
||||
if (!(gasFamily.originChains || []).map(Number).includes(destinationChainId)) {
|
||||
errors.push(`transportPairs[${pair.key}] destinationChainId ${destinationChainId} not allowed by gas family`);
|
||||
}
|
||||
}
|
||||
|
||||
if (!pair.protocolExposureKey || !gasProtocolExposureByKey.has(String(pair.protocolExposureKey))) {
|
||||
errors.push(`transportPairs[${pair.key}] is missing gas protocol exposure wiring`);
|
||||
}
|
||||
}
|
||||
|
||||
if ((pair.publicPoolKeys || []).length > 0) {
|
||||
for (const publicPoolKey of pair.publicPoolKeys) {
|
||||
if (!publicPoolsByKey.has(String(publicPoolKey))) {
|
||||
@@ -286,14 +350,79 @@ for (const pool of active.publicPools || []) {
|
||||
continue;
|
||||
}
|
||||
const deploymentChain = deployment.chains?.[String(pool.chainId)];
|
||||
const deployedPools = Array.isArray(deploymentChain?.pmmPools) ? deploymentChain.pmmPools : [];
|
||||
const deploymentMatch = deployedPools.some((entry) => normalizeAddress(entry?.poolAddress) === normalizeAddress(pool.poolAddress));
|
||||
if (!deploymentMatch) {
|
||||
const deployedStable = Array.isArray(deploymentChain?.pmmPools) ? deploymentChain.pmmPools : [];
|
||||
const deployedVolatile = Array.isArray(deploymentChain?.pmmPoolsVolatile) ? deploymentChain.pmmPoolsVolatile : [];
|
||||
const deployedGas = Array.isArray(deploymentChain?.gasPmmPools) ? deploymentChain.gasPmmPools : [];
|
||||
const deploymentMatch = [...deployedStable, ...deployedVolatile].some(
|
||||
(entry) => normalizeAddress(entry?.poolAddress) === normalizeAddress(pool.poolAddress)
|
||||
);
|
||||
const gasDeploymentMatch = deployedGas.some(
|
||||
(entry) => normalizeAddress(entry?.poolAddress) === normalizeAddress(pool.poolAddress)
|
||||
);
|
||||
const stagedPlaceholder = String(pool.phase || '').toLowerCase().includes('staged');
|
||||
if (!deploymentMatch && !gasDeploymentMatch && !stagedPlaceholder) {
|
||||
errors.push(`publicPools[${pool.key}] is active but deployment-status.json does not contain its poolAddress`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const family of active.gasAssetFamilies || []) {
|
||||
if (!family.familyKey || !family.canonicalSymbol138 || !family.mirroredSymbol) {
|
||||
errors.push(`gasAssetFamilies entry is missing familyKey/canonicalSymbol138/mirroredSymbol`);
|
||||
continue;
|
||||
}
|
||||
if (!Array.isArray(family.originChains) || family.originChains.length === 0) {
|
||||
errors.push(`gasAssetFamilies[${family.familyKey}] must declare originChains`);
|
||||
}
|
||||
if (!multichain.gasAssetRegistry || !Array.isArray(multichain.gasAssetRegistry.families)) {
|
||||
errors.push(`multichain gasAssetRegistry is missing while gas families are enabled`);
|
||||
continue;
|
||||
}
|
||||
const multichainFamily = multichain.gasAssetRegistry.families.find(
|
||||
(entry) => String(entry.familyKey) === String(family.familyKey)
|
||||
);
|
||||
if (!multichainFamily) {
|
||||
errors.push(`gasAssetFamilies[${family.familyKey}] is missing from token-mapping-multichain.json gasAssetRegistry`);
|
||||
continue;
|
||||
}
|
||||
if (String(multichainFamily.canonicalSymbol138) !== String(family.canonicalSymbol138)) {
|
||||
errors.push(`gasAssetFamilies[${family.familyKey}] canonicalSymbol138 mismatch between transport-active and token-mapping-multichain`);
|
||||
}
|
||||
if (String(multichainFamily.mirroredSymbol) !== String(family.mirroredSymbol)) {
|
||||
errors.push(`gasAssetFamilies[${family.familyKey}] mirroredSymbol mismatch between transport-active and token-mapping-multichain`);
|
||||
}
|
||||
}
|
||||
|
||||
for (const group of active.gasRedeemGroups || []) {
|
||||
const family = gasFamiliesByKey.get(String(group.familyKey || ''));
|
||||
if (!family) {
|
||||
errors.push(`gasRedeemGroups[${group.key}] references missing family ${group.familyKey}`);
|
||||
continue;
|
||||
}
|
||||
const allowedChains = Array.isArray(group.allowedChains) ? group.allowedChains.map(Number) : [];
|
||||
if (String(group.redeemPolicy || '') === 'family_fungible_inventory_gated') {
|
||||
const familyOriginChains = (family.originChains || []).map(Number).sort((a, b) => a - b);
|
||||
const sortedAllowed = [...allowedChains].sort((a, b) => a - b);
|
||||
if (JSON.stringify(sortedAllowed) !== JSON.stringify(familyOriginChains)) {
|
||||
errors.push(`gasRedeemGroups[${group.key}] must match the full origin chain set for ${family.familyKey}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const exposure of active.gasProtocolExposure || []) {
|
||||
const family = gasFamiliesByKey.get(String(exposure.familyKey || ''));
|
||||
if (!family) {
|
||||
errors.push(`gasProtocolExposure[${exposure.key}] references missing family ${exposure.familyKey}`);
|
||||
continue;
|
||||
}
|
||||
const oneInch = exposure.oneInch || {};
|
||||
const uniswap = exposure.uniswapV3 || {};
|
||||
const dodo = exposure.dodoPmm || {};
|
||||
if ((oneInch.routingVisible === true || oneInch.live === true) && !(uniswap.live === true && dodo.active === true)) {
|
||||
errors.push(`gasProtocolExposure[${exposure.key}] cannot enable 1inch before DODO and Uniswap are live`);
|
||||
}
|
||||
}
|
||||
|
||||
for (const [chainIdKey, deploymentChain] of Object.entries(deployment.chains || {})) {
|
||||
const destinationChainId = Number(chainIdKey);
|
||||
if (destinationChainId === canonicalChainId) continue;
|
||||
@@ -303,7 +432,7 @@ for (const [chainIdKey, deploymentChain] of Object.entries(deployment.chains ||
|
||||
if (!mappingPair) continue;
|
||||
|
||||
let compatible = true;
|
||||
for (const token of enabledCanonicalTokens) {
|
||||
for (const token of enabledCanonicalTokens.filter((entry) => entry.registryFamily !== 'gas_native')) {
|
||||
const mappingKey = String(token.mappingKey || '');
|
||||
const mirroredSymbol = String(token.mirroredSymbol || '');
|
||||
const mappingToken = mappingKey ? (mappingPair.tokens || []).find((entry) => entry.key === mappingKey) : null;
|
||||
@@ -331,7 +460,7 @@ for (const [chainIdKey, deploymentChain] of Object.entries(deployment.chains ||
|
||||
continue;
|
||||
}
|
||||
|
||||
for (const token of enabledCanonicalTokens) {
|
||||
for (const token of enabledCanonicalTokens.filter((entry) => entry.registryFamily !== 'gas_native')) {
|
||||
const expectedPairKey = `${canonicalChainId}-${destinationChainId}-${token.symbol}-${token.mirroredSymbol}`;
|
||||
const expectedPoolKey = getExpectedPoolKey(destinationChainId, String(token.mirroredSymbol || ''));
|
||||
const pair = transportPairsByKey.get(expectedPairKey);
|
||||
@@ -419,6 +548,33 @@ NODE
|
||||
ERRORS=$((ERRORS + 1))
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -f "$PROJECT_ROOT/explorer-monorepo/backend/api/rest/config/metamask/GRU_V2_PUBLIC_DEPLOYMENT_STATUS.json" ]] && command -v jq &>/dev/null; then
|
||||
if jq -e '(.summary | type == "object") and (.protocols.publicCwMesh | type == "array") and (.transport.wave1 | type == "array")' "$PROJECT_ROOT/explorer-monorepo/backend/api/rest/config/metamask/GRU_V2_PUBLIC_DEPLOYMENT_STATUS.json" &>/dev/null; then
|
||||
log_ok "GRU_V2_PUBLIC_DEPLOYMENT_STATUS valid"
|
||||
else
|
||||
log_err "GRU_V2_PUBLIC_DEPLOYMENT_STATUS invalid"
|
||||
ERRORS=$((ERRORS + 1))
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -f "$PROJECT_ROOT/config/gru-v2-public-protocol-rollout-plan.json" ]] && command -v jq &>/dev/null; then
|
||||
if jq -e '(.protocols | type == "array") and (.protocols | length > 0)' "$PROJECT_ROOT/config/gru-v2-public-protocol-rollout-plan.json" &>/dev/null; then
|
||||
log_ok "gru-v2-public-protocol-rollout-plan.json valid"
|
||||
else
|
||||
log_err "gru-v2-public-protocol-rollout-plan.json invalid"
|
||||
ERRORS=$((ERRORS + 1))
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -f "$PROJECT_ROOT/explorer-monorepo/backend/api/rest/config/metamask/GRU_V2_DEPLOYMENT_QUEUE.json" ]] && command -v jq &>/dev/null; then
|
||||
if jq -e '(.summary | type == "object") and (.assetQueue | type == "array") and (.chainQueue | type == "array") and (.protocolQueue | type == "array")' "$PROJECT_ROOT/explorer-monorepo/backend/api/rest/config/metamask/GRU_V2_DEPLOYMENT_QUEUE.json" &>/dev/null; then
|
||||
log_ok "GRU_V2_DEPLOYMENT_QUEUE valid"
|
||||
else
|
||||
log_err "GRU_V2_DEPLOYMENT_QUEUE invalid"
|
||||
ERRORS=$((ERRORS + 1))
|
||||
fi
|
||||
fi
|
||||
# Public-sector program manifest (served by phoenix-deploy-api GET /api/v1/public-sector/programs)
|
||||
if [[ -f "$PROJECT_ROOT/config/public-sector-program-manifest.json" ]]; then
|
||||
log_ok "Found: config/public-sector-program-manifest.json"
|
||||
@@ -599,6 +755,42 @@ if [[ -d "$PROJECT_ROOT/config/xdc-zero" ]] && [[ -x "$SCRIPT_DIR/validate-xdc-z
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -d "$PROJECT_ROOT/config/xdc-zero" ]] && [[ -x "$SCRIPT_DIR/validate-xdc-zero-relayer-env.sh" ]]; then
|
||||
if bash "$SCRIPT_DIR/validate-xdc-zero-relayer-env.sh" &>/dev/null; then
|
||||
log_ok "config/xdc-zero relayer env/default examples"
|
||||
else
|
||||
log_err "config/xdc-zero relayer env/default validation failed (validate-xdc-zero-relayer-env.sh)"
|
||||
ERRORS=$((ERRORS + 1))
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -x "$SCRIPT_DIR/validate-economics-strategy-json.sh" ]]; then
|
||||
if bash "$SCRIPT_DIR/validate-economics-strategy-json.sh" &>/dev/null; then
|
||||
log_ok "economics-toolkit strategy JSON (smoke + template; optional check-jsonschema)"
|
||||
else
|
||||
log_err "economics-toolkit strategy JSON validation failed (see scripts/validation/validate-economics-strategy-json.sh; run pnpm run economics:build)"
|
||||
ERRORS=$((ERRORS + 1))
|
||||
fi
|
||||
fi
|
||||
|
||||
if command -v python3 &>/dev/null; then
|
||||
for f in \
|
||||
"$PROJECT_ROOT/scripts/it-ops/compute_ipam_drift.py" \
|
||||
"$PROJECT_ROOT/scripts/it-ops/lib/collect_inventory_remote.py" \
|
||||
"$PROJECT_ROOT/scripts/it-ops/persist-it-snapshot-sqlite.py" \
|
||||
"$PROJECT_ROOT/services/sankofa-it-read-api/server.py"
|
||||
do
|
||||
if [[ -f "$f" ]]; then
|
||||
if python3 -m py_compile "$f" &>/dev/null; then
|
||||
log_ok "Python syntax: ${f#$PROJECT_ROOT/}"
|
||||
else
|
||||
log_err "Python syntax failed: $f"
|
||||
ERRORS=$((ERRORS + 1))
|
||||
fi
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
if [[ $ERRORS -gt 0 ]]; then
|
||||
log_err "Validation failed with $ERRORS error(s). Set VALIDATE_REQUIRED_FILES='path1 path2' to require specific files."
|
||||
exit 1
|
||||
|
||||
Reference in New Issue
Block a user