feat(settlement): wire real Chain 138 contracts for 1,000 BTC ledger
Some checks failed
CI/CD Pipeline / Solidity Contracts (push) Failing after 52s
CI/CD Pipeline / Security Scanning (push) Successful in 2m40s
CI/CD Pipeline / Lint and Format (push) Failing after 49s
CI/CD Pipeline / Terraform Validation (push) Failing after 24s
CI/CD Pipeline / Kubernetes Validation (push) Successful in 27s
Deploy ChainID 138 / Deploy ChainID 138 (push) Has been cancelled
Validation / validate-genesis (push) Has been cancelled
Validation / validate-terraform (push) Has been cancelled
Validation / validate-kubernetes (push) Has been cancelled
Verify Deployment / Verify Deployment (push) Has been cancelled
Validation / validate-smart-contracts (push) Failing after 14s
Validation / validate-security (push) Failing after 1m20s
Validation / validate-documentation (push) Failing after 18s

Add canonical btc-l1-ledger config, /btc/contracts API, Python chain138-oracle
service, and production deploy scripts so secure.omdnl.org can serve live cBTC,
DODO, and PMM pool addresses with headroom-aware mint gating.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-07-21 02:26:20 -07:00
parent 4e04d9ca51
commit 54ca9bea3b
54 changed files with 2895 additions and 82 deletions

View File

@@ -0,0 +1,172 @@
#!/usr/bin/env bash
# Cut over Chain 138 oracle from legacy shell/Node mesh to Python chain138-oracle.
#
# Stops:
# - scripts/reserve/pmm-mesh-6s-automation.sh (nohup/systemd legacy)
# - scripts/reserve/keeper-service.js
# - external oracle-publisher (systemd) if present
#
# Starts:
# - chain138-oracle-api.service (FastAPI spot prices, port 3500)
# - chain138-oracle-mesh.service (6s oracle + keeper + PMM loop)
#
# Updates .env:
# CHAIN138_ORACLE_URL=http://127.0.0.1:3500
# TOKEN_AGGREGATION_URL=http://127.0.0.1:3000 (OMNL mint/transfer unchanged)
#
# Usage:
# ./scripts/deployment/cutover-chain138-oracle-python.sh [--dry-run]
# RESTART_SETTLEMENT=1 ./scripts/deployment/cutover-chain138-oracle-python.sh
#
set -euo pipefail
DRY_RUN=0
for arg in "$@"; do
case "$arg" in
--dry-run) DRY_RUN=1 ;;
esac
done
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
ORACLE_DIR="$REPO_ROOT/services/chain138-oracle"
ENV_FILE="${OMNL_BANK_ENV:-$REPO_ROOT/.env}"
SYSTEMD_DIR="/etc/systemd/system"
API_UNIT="chain138-oracle-api.service"
MESH_UNIT="chain138-oracle-mesh.service"
LEGACY_UNITS=(chain138-pmm-mesh-automation.service price-feed-keeper.service oracle-publisher.service)
RESTART_SETTLEMENT="${RESTART_SETTLEMENT:-1}"
log() { echo "[$(date -Iseconds)] $*"; }
run() {
if [ "$DRY_RUN" -eq 1 ]; then
log "DRY-RUN: $*"
else
log "RUN: $*"
eval "$@"
fi
}
cd "$REPO_ROOT"
if [ -f "$ENV_FILE" ]; then
set -a
# shellcheck source=/dev/null
source "$ENV_FILE"
set +a
fi
log "=== Chain 138 oracle Python cutover ==="
log "Repo: $REPO_ROOT"
log "Oracle dir: $ORACLE_DIR"
# --- Stop legacy off-chain oracle processes ---
stop_pattern() {
local pattern="$1"
local pids
pids=$(pgrep -f "$pattern" 2>/dev/null || true)
if [ -n "$pids" ]; then
log "Stopping processes matching: $pattern ($pids)"
run "pkill -f '$pattern' || true"
fi
}
for unit in "${LEGACY_UNITS[@]}"; do
if systemctl is-active --quiet "$unit" 2>/dev/null; then
run "systemctl stop '$unit'"
fi
if systemctl is-enabled --quiet "$unit" 2>/dev/null; then
run "systemctl disable '$unit'"
fi
done
stop_pattern "pmm-mesh-6s-automation.sh"
stop_pattern "keeper-service.js"
stop_pattern "oracle_publisher"
# --- Install Python venv + deps ---
if [ ! -d "$ORACLE_DIR/.venv" ]; then
run "python3 -m venv '$ORACLE_DIR/.venv'"
fi
run "'$ORACLE_DIR/.venv/bin/pip' install -q -r '$ORACLE_DIR/requirements.txt'"
# --- Validate token coverage ---
log "Validating M2 registry token price coverage..."
if [ "$DRY_RUN" -eq 0 ]; then
set -a
# shellcheck source=/dev/null
source "$ENV_FILE" 2>/dev/null || true
set +a
PYTHONPATH="$ORACLE_DIR" "$ORACLE_DIR/.venv/bin/python" -m chain138_oracle validate
fi
# --- Patch .env ---
merge_env_key() {
local key="$1"
local value="$2"
if [ ! -f "$ENV_FILE" ]; then
run "touch '$ENV_FILE'"
fi
if grep -q "^${key}=" "$ENV_FILE" 2>/dev/null; then
run "sed -i 's|^${key}=.*|${key}=${value}|' '$ENV_FILE'"
else
run "echo '${key}=${value}' >> '$ENV_FILE'"
fi
}
merge_env_key "CHAIN138_ORACLE_URL" "${CHAIN138_ORACLE_URL:-http://127.0.0.1:3500}"
merge_env_key "CHAIN138_ORACLE_PORT" "${CHAIN138_ORACLE_PORT:-3500}"
merge_env_key "TOKEN_AGGREGATION_URL" "${TOKEN_AGGREGATION_URL:-http://127.0.0.1:3000}"
# --- Install systemd units ---
install_unit() {
local example="$1"
local unit="$2"
local dest="$SYSTEMD_DIR/$unit"
run "cp '$example' '$dest'"
run "sed -i 's|/opt/smom-dbis-138|$REPO_ROOT|g' '$dest'"
}
install_unit "$ORACLE_DIR/systemd/chain138-oracle-api.service.example" "$API_UNIT"
install_unit "$ORACLE_DIR/systemd/chain138-oracle-mesh.service.example" "$MESH_UNIT"
run "systemctl daemon-reload"
run "systemctl enable '$API_UNIT' '$MESH_UNIT'"
run "systemctl restart '$API_UNIT'"
run "systemctl restart '$MESH_UNIT'"
# --- Smoke tests ---
smoke() {
local url="$1"
local label="$2"
if [ "$DRY_RUN" -eq 1 ]; then
log "DRY-RUN smoke: $label $url"
return 0
fi
curl -sf "$url" >/dev/null && log "OK: $label" || { log "FAIL: $label ($url)"; return 1; }
}
ORACLE_BASE="${CHAIN138_ORACLE_URL:-http://127.0.0.1:3500}"
CBTC=0xe94260c555ac1d9d3cc9e1632883452ebdf0082e
sleep 2
smoke "$ORACLE_BASE/health" "oracle health"
smoke "$ORACLE_BASE/api/v1/prices/metamask/v2/chains/138/spot-prices?tokenAddresses=$CBTC" "cBTC spot price"
# --- Restart settlement middleware if requested ---
if [ "$RESTART_SETTLEMENT" = "1" ]; then
for unit in settlement-middleware omnl-settlement-middleware; do
if systemctl is-active --quiet "$unit" 2>/dev/null; then
run "systemctl restart '$unit'"
log "Restarted $unit"
break
fi
done
if docker compose -f "$REPO_ROOT/docker-compose.omnl-production.yml" ps settlement-middleware >/dev/null 2>&1; then
run "docker compose -f '$REPO_ROOT/docker-compose.omnl-production.yml' up -d chain138-oracle settlement-middleware"
fi
fi
log "=== Cutover complete ==="
log "CHAIN138_ORACLE_URL=$ORACLE_BASE"
log "TOKEN_AGGREGATION_URL=${TOKEN_AGGREGATION_URL:-http://127.0.0.1:3000}"
log "Check: systemctl status $API_UNIT $MESH_UNIT"
log "Check: curl -s $ORACLE_BASE/api/v1/oracle/tokens | head"

View File

@@ -0,0 +1,134 @@
#!/usr/bin/env bash
# Deploy 1,000 BTC ledger real contract wiring to production settlement middleware.
#
# Run on the OMNL bank host (dev-bis-ali / secure.omdnl.org backend):
# OMNL_SKIP_GIT_PULL=1 bash scripts/deployment/deploy-btc-ledger-production.sh
# Or after push to main:
# bash scripts/deployment/deploy-btc-ledger-production.sh
#
set -euo pipefail
REPO_DIR="${OMNL_BANK_ROOT:-$HOME/smom-dbis-138}"
ENV_FILE="${OMNL_BANK_ENV:-$REPO_DIR/.env}"
LOG_DIR="${OMNL_BANK_LOG_DIR:-$HOME/omnl-bank/logs}"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
log() { echo "[$(date -Iseconds)] $*"; }
cd "$REPO_DIR"
if [[ "${OMNL_SKIP_GIT_PULL:-0}" != "1" ]]; then
log "Pull latest main..."
git fetch origin
git checkout main
git pull --ff-only origin main
fi
export SETTLEMENT_MIDDLEWARE_CONFIG="${SETTLEMENT_MIDDLEWARE_CONFIG:-$REPO_DIR/config/settlement-middleware.production.v1.json}"
export OMNL_BTC_LEDGER_CONFIG="${OMNL_BTC_LEDGER_CONFIG:-$REPO_DIR/config/btc-l1-ledger-1000.chain138.v1.json}"
if [[ ! -f "$OMNL_BTC_LEDGER_CONFIG" ]]; then
echo "Missing BTC ledger config: $OMNL_BTC_LEDGER_CONFIG" >&2
exit 1
fi
if [[ -f "$ENV_FILE" ]]; then
set -a
set +u
# shellcheck disable=SC1090
source "$ENV_FILE"
set -u
set +a
fi
# Ensure contract env keys are present (merge from canonical JSON if missing).
if [[ -f "$REPO_DIR/scripts/deployment/sync-btc-ledger-contract-env.mjs" ]]; then
FRAG="$(mktemp)"
node "$REPO_DIR/scripts/deployment/sync-btc-ledger-contract-env.mjs" >"$FRAG"
while IFS= read -r line; do
key="${line%%=*}"
if ! grep -q "^${key}=" "$ENV_FILE" 2>/dev/null; then
echo "$line" >>"$ENV_FILE"
log "Added missing env: $key"
fi
done <"$FRAG"
rm -f "$FRAG"
set -a
set +u
# shellcheck disable=SC1090
source "$ENV_FILE"
set -u
set +a
fi
log "Building settlement-core + settlement-middleware..."
for dir in packages/settlement-core services/settlement-middleware; do
cd "$REPO_DIR/$dir"
NODE_ENV=development npm install --no-fund --no-audit
npm run build
done
mkdir -p "$LOG_DIR"
cd "$REPO_DIR/services/settlement-middleware"
pkill -f "smom-dbis-138/services/settlement-middleware" 2>/dev/null || true
fuser -k 3011/tcp 2>/dev/null || true
sleep 1
log "Starting settlement-middleware :3011 with BTC ledger config..."
nohup env \
SETTLEMENT_MIDDLEWARE_CONFIG="$SETTLEMENT_MIDDLEWARE_CONFIG" \
OMNL_BTC_LEDGER_CONFIG="$OMNL_BTC_LEDGER_CONFIG" \
OMNL_SUPPORTED_CHAINS_CONFIG="${OMNL_SUPPORTED_CHAINS_CONFIG:-$REPO_DIR/config/omnl-supported-chains.v1.json}" \
OMNL_M2_TOKEN_REGISTRY="${OMNL_M2_TOKEN_REGISTRY:-$REPO_DIR/config/omnl-m2-token-registry.v1.json}" \
OMNL_API_KEY="${OMNL_API_KEY:-${OMNL_SUPER_ADMIN_SECURE_KEY:-}}" \
OMNL_SUPER_ADMIN_OFFICE24_KEY="${OMNL_SUPER_ADMIN_OFFICE24_KEY:-}" \
OMNL_SUPER_ADMIN_EXCHANGE_KEY="${OMNL_SUPER_ADMIN_EXCHANGE_KEY:-}" \
OMNL_SUPER_ADMIN_SECURE_KEY="${OMNL_SUPER_ADMIN_SECURE_KEY:-}" \
OMNL_SUPER_ADMIN_FOREX_KEY="${OMNL_SUPER_ADMIN_FOREX_KEY:-}" \
OMNL_FINERACT_BASE_URL="${OMNL_FINERACT_BASE_URL:-${FINERACT_BASE_URL:-}}" \
OMNL_FINERACT_TENANT="${OMNL_FINERACT_TENANT:-${FINERACT_TENANT:-omnl}}" \
OMNL_FINERACT_USER="${OMNL_FINERACT_USER:-}" \
OMNL_FINERACT_USERNAME="${OMNL_FINERACT_USERNAME:-}" \
OMNL_FINERACT_PASSWORD="${OMNL_FINERACT_PASSWORD:-}" \
OMNL_PUBLIC_MONEY_SUPPLY="${OMNL_PUBLIC_MONEY_SUPPLY:-1}" \
SETTLEMENT_ALLOW_HYBX_PRODUCTION="${SETTLEMENT_ALLOW_HYBX_PRODUCTION:-1}" \
SETTLEMENT_ALLOW_CHAIN_MINT_EXECUTE="${SETTLEMENT_ALLOW_CHAIN_MINT_EXECUTE:-1}" \
TOKEN_AGGREGATION_URL="${TOKEN_AGGREGATION_URL:-http://127.0.0.1:3000}" \
CHAIN138_ORACLE_URL="${CHAIN138_ORACLE_URL:-http://127.0.0.1:3500}" \
RPC_URL_138="${RPC_URL_138:-${CHAIN_138_RPC_URL:-}}" \
CHAIN_138_RPC_URL="${CHAIN_138_RPC_URL:-${RPC_URL_138:-}}" \
OMNL_MINT_OPERATOR_PRIVATE_KEY="${OMNL_MINT_OPERATOR_PRIVATE_KEY:-}" \
OMNL_REQUIRE_LIVE_BTC_PRICE="${OMNL_REQUIRE_LIVE_BTC_PRICE:-1}" \
CBTC_ADDRESS_138="${CBTC_ADDRESS_138:-}" \
BTC_L1_RECIPIENT_ADDRESS="${BTC_L1_RECIPIENT_ADDRESS:-}" \
BTC_EXISTING_MINT_HOLDER="${BTC_EXISTING_MINT_HOLDER:-}" \
DODO_PMM_INTEGRATION="${DODO_PMM_INTEGRATION:-${CHAIN_138_DODO_PMM_INTEGRATION:-}}" \
CHAIN138_POOL_CBTC_CUSDT="${CHAIN138_POOL_CBTC_CUSDT:-}" \
CHAIN138_POOL_CBTC_CUSDC="${CHAIN138_POOL_CBTC_CUSDC:-}" \
CHAIN138_POOL_CBTC_CXAUC="${CHAIN138_POOL_CBTC_CXAUC:-}" \
RESERVE_SYSTEM="${RESERVE_SYSTEM:-}" \
ORACLE_PROXY_ADDRESS="${ORACLE_PROXY_ADDRESS:-}" \
ORACLE_AGGREGATOR_ADDRESS="${ORACLE_AGGREGATOR_ADDRESS:-${AGGREGATOR_ADDRESS:-}}" \
PRICE_FEED_KEEPER_ADDRESS="${PRICE_FEED_KEEPER_ADDRESS:-}" \
HYBX_MIFOS_FINERACT_SIDECAR_URL="${HYBX_MIFOS_FINERACT_SIDECAR_URL:-}" \
HYBX_BASE_URL="${HYBX_BASE_URL:-}" \
HYBX_API="${HYBX_API:-}" \
npm run start >"$LOG_DIR/settlement-middleware.log" 2>&1 &
echo $! >"$LOG_DIR/settlement-middleware.pid"
sleep 4
API_KEY="${OMNL_API_KEY:-${OMNL_SUPER_ADMIN_SECURE_KEY:-}}"
log "Smoke: /btc/contracts"
curl -sf -H "Authorization: Bearer ${API_KEY}" \
"http://127.0.0.1:3011/api/v1/settlement/btc/contracts" | head -c 400 || {
echo "FAIL: /btc/contracts not reachable" >&2
tail -n 40 "$LOG_DIR/settlement-middleware.log" >&2 || true
exit 1
}
echo
log "Smoke: /btc/ledger headroom"
curl -sf -H "Authorization: Bearer ${API_KEY}" \
"http://127.0.0.1:3011/api/v1/settlement/btc/ledger" | head -c 500 || true
echo
log "BTC ledger production deploy complete"
log "Public: https://secure.omdnl.org/settlement/btc/contracts"

View File

@@ -171,6 +171,19 @@ start_svc() {
AZURE_OPENAI_API_VERSION="${AZURE_OPENAI_API_VERSION:-2024-02-15-preview}" \
OMNL_MINT_OPERATOR_PRIVATE_KEY="${OMNL_MINT_OPERATOR_PRIVATE_KEY:-}" \
OMNL_REQUIRE_LIVE_BTC_PRICE="${OMNL_REQUIRE_LIVE_BTC_PRICE:-1}" \
OMNL_BTC_LEDGER_CONFIG="${OMNL_BTC_LEDGER_CONFIG:-$REPO_DIR/config/btc-l1-ledger-1000.chain138.v1.json}" \
CBTC_ADDRESS_138="${CBTC_ADDRESS_138:-}" \
BTC_L1_RECIPIENT_ADDRESS="${BTC_L1_RECIPIENT_ADDRESS:-}" \
BTC_EXISTING_MINT_HOLDER="${BTC_EXISTING_MINT_HOLDER:-}" \
DODO_PMM_INTEGRATION="${DODO_PMM_INTEGRATION:-${CHAIN_138_DODO_PMM_INTEGRATION:-}}" \
CHAIN138_POOL_CBTC_CUSDT="${CHAIN138_POOL_CBTC_CUSDT:-}" \
CHAIN138_POOL_CBTC_CUSDC="${CHAIN138_POOL_CBTC_CUSDC:-}" \
CHAIN138_POOL_CBTC_CXAUC="${CHAIN138_POOL_CBTC_CXAUC:-}" \
CHAIN138_ORACLE_URL="${CHAIN138_ORACLE_URL:-http://127.0.0.1:3500}" \
RESERVE_SYSTEM="${RESERVE_SYSTEM:-}" \
ORACLE_PROXY_ADDRESS="${ORACLE_PROXY_ADDRESS:-}" \
ORACLE_AGGREGATOR_ADDRESS="${ORACLE_AGGREGATOR_ADDRESS:-${AGGREGATOR_ADDRESS:-}}" \
PRICE_FEED_KEEPER_ADDRESS="${PRICE_FEED_KEEPER_ADDRESS:-}" \
BITCOIND_RPC_URL="${BITCOIND_RPC_URL:-}" \
BITCOIND_RPC_USER="${BITCOIND_RPC_USER:-}" \
BITCOIND_RPC_PASS="${BITCOIND_RPC_PASS:-}" \

View File

@@ -0,0 +1,114 @@
#!/usr/bin/env node
/**
* Post three-leg BTC M2 headroom policy adjustment to Fineract:
* Leg 1 (Office 1): Dr 2100 / Cr 2410
* Leg 2 (Office 24): Dr 1410 / Cr 2100
* Leg 3 (Office 24): Dr 2100 / Cr 2200
*/
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const repoRoot = path.resolve(__dirname, '../..');
const configPath = path.join(repoRoot, 'config/offices/btc-m2-headroom-adjustment-20260720.v1.json');
const dryRun = process.argv.includes('--dry-run');
const cfg = JSON.parse(fs.readFileSync(configPath, 'utf8'));
const base = (process.env.OMNL_FINERACT_BASE_URL || process.env.FINERACT_BASE_URL || '').replace(/\/$/, '');
const tenant = process.env.OMNL_FINERACT_TENANT || process.env.FINERACT_TENANT || 'omnl';
const user =
process.env.OMNL_FINERACT_USER?.trim() ||
process.env.OMNL_FINERACT_USERNAME?.trim() ||
'ali_hospitallers_tenant';
const pass = process.env.OMNL_FINERACT_PASSWORD || '';
const amountRaw = process.env[cfg.amountEnv] || String(cfg.amountUsd || '');
const amount = parseFloat(amountRaw);
if (!base || !pass) {
console.error('Set OMNL_FINERACT_BASE_URL and OMNL_FINERACT_PASSWORD');
process.exit(1);
}
if (!Number.isFinite(amount) || amount <= 0) {
console.error(`Set ${cfg.amountEnv} or amountUsd in config to a positive USD amount`);
process.exit(1);
}
const auth = Buffer.from(`${user}:${pass}`).toString('base64');
const headers = {
Authorization: `Basic ${auth}`,
'Fineract-Platform-TenantId': tenant,
'Content-Type': 'application/json',
Accept: 'application/json',
};
const glCache = new Map();
async function glIdForCode(glCode) {
const code = String(glCode).trim();
if (glCache.has(code)) return glCache.get(code);
const res = await fetch(`${base}/glaccounts?glCode=${encodeURIComponent(code)}`, { headers });
if (!res.ok) throw new Error(`GL lookup failed for ${code} (${res.status})`);
const data = await res.json();
const list = Array.isArray(data) ? data : data?.pageItems ?? [];
const match = list.find((row) => String(row.glCode) === code);
if (!match?.id) throw new Error(`GL code ${code} not found in Fineract tenant ${tenant}`);
glCache.set(code, Number(match.id));
return Number(match.id);
}
const txDate = cfg.transactionDate || new Date().toISOString().slice(0, 10);
const results = [];
for (const leg of cfg.entries) {
const debitGlAccountId = await glIdForCode(leg.debitGlCode);
const creditGlAccountId = await glIdForCode(leg.creditGlCode);
const entry = {
officeId: leg.officeId,
transactionDate: txDate,
referenceNumber: leg.memo,
comments: leg.comments,
currencyCode: cfg.currencyCode || 'USD',
dateFormat: 'yyyy-MM-dd',
locale: 'en',
debits: [{ glAccountId: debitGlAccountId, amount }],
credits: [{ glAccountId: creditGlAccountId, amount }],
};
const summary = {
memo: leg.memo,
officeId: leg.officeId,
amount,
debitGlCode: leg.debitGlCode,
creditGlCode: leg.creditGlCode,
debitGlAccountId,
creditGlAccountId,
};
console.log(JSON.stringify({ dryRun, ...summary }, null, 2));
if (dryRun) {
results.push({ ...summary, status: 'dry-run' });
continue;
}
const res = await fetch(`${base}/journalentries`, {
method: 'POST',
headers,
body: JSON.stringify(entry),
});
const body = await res.text();
if (!res.ok) {
console.error(`Fineract POST failed for ${leg.memo} (${res.status}): ${body}`);
process.exit(1);
}
let parsed;
try {
parsed = JSON.parse(body);
} catch {
parsed = { raw: body };
}
results.push({ ...summary, status: 'posted', response: parsed });
console.log(`Posted ${leg.memo}:`, body);
}
console.log(JSON.stringify({ dryRun, amount, legs: results.length, results }, null, 2));

View File

@@ -26,7 +26,7 @@ set -u
set +a
FRAG="$(mktemp)"
grep -E '^(OMNL_FINERACT_|OMNL_PUBLIC_MONEY_SUPPLY=|OMNL_REQUIRE_API_KEY=|OMNL_CUSTOMER_SECURITY_PRODUCTION=|OMNL_CUSTOMER_API_KEYS=|OFFICE24_OPENING_M1_USD=|OMNL_PORTAL_INTERNAL_SECRET=|JWT_SECRET=|DATABASE_URL=|RPC_URL_138=|CHAIN_138_RPC_URL=|SETTLEMENT_ALLOW_CHAIN_MINT_EXECUTE=|SETTLEMENT_ALLOW_HYBX_PRODUCTION=|OMNL_ALLOW_CHAIN_MINT_EXECUTE=|OMNL_MINT_OPERATOR_PRIVATE_KEY=|TOKEN_AGGREGATION_URL=|SWIFT_LISTENER_URL=|HYBX_MIFOS_FINERACT_SIDECAR_URL=|INFURA_PROJECT_ID=|INFURA_PROJECT_SECRET=)' "$ENV_FILE" >"$FRAG" || true
grep -E '^(OMNL_FINERACT_|OMNL_PUBLIC_MONEY_SUPPLY=|OMNL_REQUIRE_API_KEY=|OMNL_CUSTOMER_SECURITY_PRODUCTION=|OMNL_CUSTOMER_API_KEYS=|OFFICE24_OPENING_M1_USD=|OMNL_PORTAL_INTERNAL_SECRET=|JWT_SECRET=|DATABASE_URL=|RPC_URL_138=|CHAIN_138_RPC_URL=|SETTLEMENT_ALLOW_CHAIN_MINT_EXECUTE=|SETTLEMENT_ALLOW_HYBX_PRODUCTION=|OMNL_ALLOW_CHAIN_MINT_EXECUTE=|OMNL_MINT_OPERATOR_PRIVATE_KEY=|OMNL_BTC_LEDGER_CONFIG=|CBTC_ADDRESS_138=|BTC_L1_RECIPIENT_ADDRESS=|BTC_EXISTING_MINT_HOLDER=|DODO_PMM_INTEGRATION=|CHAIN_138_DODO_PMM_INTEGRATION=|RESERVE_SYSTEM=|ORACLE_PROXY_ADDRESS=|CHAIN138_POOL_CBTC_CUSDT=|CHAIN138_POOL_CBTC_CUSDC=|CHAIN138_POOL_CBTC_CXAUC=|CHAIN138_ORACLE_URL=|CHAIN138_ORACLE_PORT=|TOKEN_AGGREGATION_URL=|OMNL_REQUIRE_LIVE_BTC_PRICE=|KEEPER_PRIVATE_KEY=|PRICE_FEED_KEEPER_ADDRESS=|AGGREGATOR_ADDRESS=|SWIFT_LISTENER_URL=|HYBX_BASE_URL=|HYBX_API=|HYBX_ENVIRONMENT=|HYBX_API_KEY=|HYBX_CLIENT_ID=|HYBX_CLIENT_SECRET=|HYBX_WEBHOOK_SECRET=|HYBX_MIFOS_FINERACT_SIDECAR_URL=|HYBX_ALLOW_LAN_SIDECAR=|INFURA_PROJECT_ID=|INFURA_PROJECT_SECRET=)' "$ENV_FILE" >"$FRAG" || true
ADMIN_ENV_KEY="$(node -e "
const fs = require('fs');

View File

@@ -0,0 +1,31 @@
#!/usr/bin/env node
/**
* Smoke: settlement middleware can fetch live cBTC/USD from chain138-oracle.
*
* CHAIN138_ORACLE_URL=http://127.0.0.1:3500 node scripts/deployment/smoke-chain138-oracle-pricing.mjs
*/
const oracleBase = (process.env.CHAIN138_ORACLE_URL || 'http://127.0.0.1:3500').replace(/\/$/, '');
const cbtc = '0xe94260c555ac1d9d3cc9e1632883452ebdf0082e';
async function main() {
const health = await fetch(`${oracleBase}/health`);
console.log('health', health.status, await health.json());
const url =
`${oracleBase}/api/v1/prices/metamask/v2/chains/138/spot-prices` +
`?tokenAddresses=${cbtc}&vsCurrency=usd`;
const spot = await fetch(url);
const body = await spot.json();
console.log('cBTC spot', spot.status, body);
const rate = body[cbtc]?.usd ?? body[cbtc.toLowerCase()]?.usd;
if (!(rate > 0)) {
console.error('FAIL: no live cBTC/USD from oracle');
process.exit(1);
}
console.log('OK: live BTC/USD =', rate);
}
main().catch((err) => {
console.error(err);
process.exit(1);
});

View File

@@ -0,0 +1,43 @@
#!/usr/bin/env node
/**
* Emit .env lines for 1,000 BTC ledger real contract addresses from
* config/btc-l1-ledger-1000.chain138.v1.json
*
* node scripts/deployment/sync-btc-ledger-contract-env.mjs
* node scripts/deployment/sync-btc-ledger-contract-env.mjs --write .env.fragment
*/
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
const __dirname = path.dirname(fileURLToPath(import.meta.url));
const repoRoot = path.resolve(__dirname, '../..');
const cfgPath = path.join(repoRoot, 'config/btc-l1-ledger-1000.chain138.v1.json');
const cfg = JSON.parse(fs.readFileSync(cfgPath, 'utf8'));
const lines = [
`OMNL_BTC_LEDGER_CONFIG=config/btc-l1-ledger-1000.chain138.v1.json`,
`CBTC_ADDRESS_138=${cfg.token.address}`,
`BTC_L1_RECIPIENT_ADDRESS=${cfg.recipients.primaryMintTarget}`,
`BTC_EXISTING_MINT_HOLDER=${cfg.recipients.existingMintHolder1000}`,
`DODO_PMM_INTEGRATION=${cfg.dodoEvm.pmmIntegration}`,
`CHAIN_138_DODO_PMM_INTEGRATION=${cfg.dodoEvm.pmmIntegration}`,
`RESERVE_SYSTEM=${cfg.oracle.reserveSystem}`,
`ORACLE_PRICE_FEED=${cfg.oracle.oraclePriceFeed}`,
`ORACLE_AGGREGATOR_ADDRESS=${cfg.oracle.aggregator}`,
`AGGREGATOR_ADDRESS=${cfg.oracle.aggregator}`,
`ORACLE_PROXY_ADDRESS=${cfg.oracle.proxy}`,
`PRICE_FEED_KEEPER_ADDRESS=${cfg.oracle.priceFeedKeeper}`,
`CHAIN138_POOL_CBTC_CUSDT=${cfg.pmmPools.cBTC_cUSDT}`,
`CHAIN138_POOL_CBTC_CUSDC=${cfg.pmmPools.cBTC_cUSDC}`,
`CHAIN138_POOL_CBTC_CXAUC=${cfg.pmmPools.cBTC_cXAUC}`,
];
const writeArg = process.argv.indexOf('--write');
if (writeArg >= 0) {
const out = process.argv[writeArg + 1] || path.join(repoRoot, '.env.btc-ledger.fragment');
fs.writeFileSync(out, `${lines.join('\n')}\n`, 'utf8');
console.log(`Wrote ${out}`);
} else {
console.log(lines.join('\n'));
}