- 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
185 lines
6.8 KiB
Bash
185 lines
6.8 KiB
Bash
#!/usr/bin/env bash
|
|
# Compare the GRU global-priority rollout plan against the current repo state.
|
|
# Usage:
|
|
# bash scripts/verify/check-gru-global-priority-rollout.sh
|
|
# bash scripts/verify/check-gru-global-priority-rollout.sh --json
|
|
# bash scripts/verify/check-gru-global-priority-rollout.sh --wave=wave1
|
|
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
|
export PROJECT_ROOT
|
|
|
|
OUTPUT_JSON=0
|
|
WAVE_FILTER=""
|
|
|
|
for arg in "$@"; do
|
|
case "$arg" in
|
|
--json) OUTPUT_JSON=1 ;;
|
|
--wave=*) WAVE_FILTER="${arg#--wave=}" ;;
|
|
*)
|
|
echo "Unknown argument: $arg" >&2
|
|
exit 2
|
|
;;
|
|
esac
|
|
done
|
|
|
|
need_cmd() {
|
|
command -v "$1" >/dev/null 2>&1 || {
|
|
echo "[FAIL] Missing required command: $1" >&2
|
|
exit 1
|
|
}
|
|
}
|
|
|
|
need_cmd node
|
|
|
|
OUTPUT_JSON="$OUTPUT_JSON" WAVE_FILTER="$WAVE_FILTER" node <<'NODE'
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
const root = process.env.PROJECT_ROOT;
|
|
const outputJson = process.env.OUTPUT_JSON === '1';
|
|
const waveFilter = process.env.WAVE_FILTER || '';
|
|
|
|
function readJson(relPath) {
|
|
return JSON.parse(fs.readFileSync(path.join(root, relPath), 'utf8'));
|
|
}
|
|
|
|
const rollout = readJson('config/gru-global-priority-currency-rollout.json');
|
|
const manifest = readJson('config/gru-iso4217-currency-manifest.json');
|
|
const mapping = readJson('config/token-mapping-multichain.json');
|
|
const transport = readJson('config/gru-transport-active.json');
|
|
|
|
const manifestByCode = new Map((manifest.currencies || []).map((item) => [item.code, item]));
|
|
const transportBySymbol = new Map((transport.enabledCanonicalTokens || []).map((item) => [item.symbol, item]));
|
|
const cToCw = mapping.cToCwSymbolMapping || {};
|
|
const wavesById = new Map((rollout.waves || []).map((item) => [item.id, item]));
|
|
const desiredDestinationNetworks = rollout.desiredDestinationNetworks || {};
|
|
const destinationSummary = {
|
|
evmPublicCwMesh: (desiredDestinationNetworks.evmPublicCwMeshChainIds || []).length,
|
|
altEvmPrograms: (desiredDestinationNetworks.altEvmPrograms || []).length,
|
|
nonEvmRelayPrograms: (desiredDestinationNetworks.nonEvmRelayPrograms || []).length
|
|
};
|
|
|
|
function manifestSymbolsFor(entry) {
|
|
if (!entry || !entry.canonicalAssets) return [];
|
|
const out = [];
|
|
for (const [form, data] of Object.entries(entry.canonicalAssets)) {
|
|
if (data && typeof data.symbol === 'string') {
|
|
out.push({ form, symbol: data.symbol });
|
|
}
|
|
}
|
|
return out;
|
|
}
|
|
|
|
function deriveState(bits) {
|
|
if (bits.transportActive) return 'live_transport';
|
|
if (bits.canonical138Deployed) return 'canonical_only';
|
|
if (bits.manifestPresent) return 'manifest_only';
|
|
if (bits.cToCwMapped) return 'mapping_only';
|
|
return 'backlog';
|
|
}
|
|
|
|
function nextStep(bits) {
|
|
if (!bits.manifestPresent) return 'add_to_manifest_and_standards';
|
|
if (!bits.canonical138Deployed) return 'deploy_canonical_on_chain138';
|
|
if (!bits.cToCwMapped) return 'add_c_to_cw_symbol_mapping';
|
|
if (!bits.transportActive) return 'deploy_cw_and_enable_transport';
|
|
if (!bits.x402Ready) return 'promote_x402_surface';
|
|
return 'monitor_and_scale';
|
|
}
|
|
|
|
const filteredAssets = (rollout.assets || []).filter((asset) => !waveFilter || asset.wave === waveFilter);
|
|
|
|
const results = filteredAssets.map((asset) => {
|
|
const manifestEntry = manifestByCode.get(asset.code);
|
|
const rolloutSymbols = (asset.tokenForms || []).map((item) => ({
|
|
form: item.form,
|
|
canonicalSymbol: item.canonicalSymbol,
|
|
wrappedSymbol: item.wrappedSymbol
|
|
}));
|
|
const manifestSymbols = manifestSymbolsFor(manifestEntry);
|
|
const manifestPresent = Boolean(manifestEntry);
|
|
const canonical138Deployed = Boolean(manifestEntry?.status?.deployed);
|
|
const transportActive = rolloutSymbols.some((item) => {
|
|
const transportEntry = transportBySymbol.get(item.canonicalSymbol);
|
|
return Boolean(transportEntry);
|
|
});
|
|
const x402Ready = Boolean(manifestEntry?.status?.x402Ready);
|
|
const cToCwMapped = rolloutSymbols.length > 0 && rolloutSymbols.every((item) => cToCw[item.canonicalSymbol] === item.wrappedSymbol);
|
|
const manifestMatchesRollout = manifestSymbols.length > 0 && rolloutSymbols.every((item) => manifestSymbols.some((m) => m.symbol === item.canonicalSymbol));
|
|
|
|
const bits = {
|
|
manifestPresent,
|
|
canonical138Deployed,
|
|
cToCwMapped,
|
|
transportActive,
|
|
x402Ready
|
|
};
|
|
|
|
return {
|
|
code: asset.code,
|
|
name: asset.name,
|
|
tier: asset.tier,
|
|
rank: asset.rank,
|
|
wave: asset.wave,
|
|
waveName: wavesById.get(asset.wave)?.name || asset.wave,
|
|
repoTargetState: asset.repoTargetState,
|
|
currentRepoState: deriveState(bits),
|
|
nextStep: nextStep(bits),
|
|
manifestPresent,
|
|
canonical138Deployed,
|
|
cToCwMapped,
|
|
transportActive,
|
|
x402Ready,
|
|
manifestMatchesRollout,
|
|
canonicalSymbols: rolloutSymbols.map((item) => item.canonicalSymbol),
|
|
wrappedSymbols: rolloutSymbols.map((item) => item.wrappedSymbol)
|
|
};
|
|
});
|
|
|
|
const summary = {
|
|
totalAssets: results.length,
|
|
liveTransport: results.filter((item) => item.currentRepoState === 'live_transport').length,
|
|
canonicalOnly: results.filter((item) => item.currentRepoState === 'canonical_only').length,
|
|
manifestOnly: results.filter((item) => item.currentRepoState === 'manifest_only').length,
|
|
backlog: results.filter((item) => item.currentRepoState === 'backlog').length,
|
|
mappingOnly: results.filter((item) => item.currentRepoState === 'mapping_only').length
|
|
};
|
|
|
|
if (outputJson) {
|
|
console.log(JSON.stringify({ summary, destinationSummary, desiredDestinationNetworks, results }, null, 2));
|
|
process.exit(0);
|
|
}
|
|
|
|
console.log('=== GRU Global Priority Cross-Chain Rollout ===');
|
|
console.log(`Assets checked: ${summary.totalAssets}`);
|
|
console.log(`Desired destination networks: EVM cW mesh=${destinationSummary.evmPublicCwMesh}, ALT/gated EVM=${destinationSummary.altEvmPrograms}, non-EVM relay=${destinationSummary.nonEvmRelayPrograms}`);
|
|
console.log(`live_transport: ${summary.liveTransport}`);
|
|
console.log(`canonical_only: ${summary.canonicalOnly}`);
|
|
console.log(`manifest_only: ${summary.manifestOnly}`);
|
|
console.log(`mapping_only: ${summary.mappingOnly}`);
|
|
console.log(`backlog: ${summary.backlog}`);
|
|
if (waveFilter) {
|
|
console.log(`Wave filter: ${waveFilter}`);
|
|
}
|
|
if ((desiredDestinationNetworks.nonEvmRelayPrograms || []).length > 0) {
|
|
const nonEvmNames = desiredDestinationNetworks.nonEvmRelayPrograms
|
|
.map((item) => item.identifier)
|
|
.join(', ');
|
|
console.log(`Non-EVM desired targets: ${nonEvmNames}`);
|
|
}
|
|
|
|
for (const item of results) {
|
|
const flags = [
|
|
item.manifestPresent ? 'manifest' : 'no-manifest',
|
|
item.canonical138Deployed ? 'canonical138' : 'no-canonical138',
|
|
item.cToCwMapped ? 'mapped' : 'no-mapping',
|
|
item.transportActive ? 'transport' : 'no-transport',
|
|
item.x402Ready ? 'x402' : 'no-x402'
|
|
].join(', ');
|
|
console.log(`- ${item.code} (${item.name}) [${item.tier} / ${item.wave}] -> ${item.currentRepoState}; next: ${item.nextStep}; ${flags}`);
|
|
}
|
|
NODE
|