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>
Chain 138 Python Oracle
Unified Python replacement for the Chain 138 oracle stack:
- Off-chain pricing (Frankfurter FX + CoinGecko + on-chain ETH/USD aggregator)
- MetaMask-compatible spot price API (drop-in for token-aggregation routes)
- PMM liquidity (8 canonical DODO pools via
DODOPMMIntegration) - On-chain oracle push (replaces
scripts/update-oracle-price.sh) - Keeper mesh (replaces
scripts/reserve/keeper-service.js+pmm-mesh-6s-automation.sh)
Token coverage is driven by config/omnl-m2-token-registry.v1.json (all M2 symbols) plus config/chain138-pmm-pools.json (PMM pool tokens).
Install
cd services/chain138-oracle
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -r requirements.txt
Load repo root .env (RPC, CoinGecko, keeper/oracle keys).
Commands
| Command | Replaces | Purpose |
|---|---|---|
python -m chain138_oracle serve |
token-aggregation price routes + oracle-publisher | HTTP API on port 3500 (override CHAIN138_ORACLE_PORT) |
python -m chain138_oracle mesh |
pmm-mesh-6s-automation.sh |
6s oracle + keeper + PMM TVL loop |
python -m chain138_oracle keeper |
keeper-service.js |
Keeper-only loop |
python -m chain138_oracle refresh-fx |
iso4217-fx-refresh.ts |
Refresh FX/crypto reference rates |
python -m chain138_oracle update-oracle |
update-oracle-price.sh |
Push ETH/USD to aggregator |
python -m chain138_oracle liquidity |
chain138-dodo-liquidity.ts |
PMM pool TVL snapshot |
python -m chain138_oracle validate |
— | Fail if any registry token lacks USD price |
API endpoints
| Endpoint | Description |
|---|---|
GET /health |
Service + on-chain ETH/USD status |
GET /api/v1/prices/metamask/v2/chains/138/spot-prices?tokenAddresses=0x… |
MetaMask Codefi-compatible spot prices |
GET /api/v1/oracle/tokens |
All registry tokens with price + PMM liquidity USD |
GET /api/v1/oracle/liquidity/pools |
Canonical PMM pool reserves and TVL |
GET /api/v1/oracle/reference-rates |
Live FX/crypto cache + contract addresses |
Settlement / token-aggregation integration
Point spot prices at the Python oracle; keep OMNL mint/transfer on token-aggregation:
CHAIN138_ORACLE_URL=http://127.0.0.1:3500
TOKEN_AGGREGATION_URL=http://127.0.0.1:3000
Settlement middleware reads CHAIN138_ORACLE_URL for live BTC/USD (resolveLiveBtcUsd).
Production cutover (one command)
On the Chain 138 / OMNL host (Linux, systemd):
chmod +x scripts/deployment/cutover-chain138-oracle-python.sh
sudo RESTART_SETTLEMENT=1 ./scripts/deployment/cutover-chain138-oracle-python.sh
Dry-run first:
./scripts/deployment/cutover-chain138-oracle-python.sh --dry-run
This script:
- Stops legacy
pmm-mesh-6s-automation.sh,keeper-service.js, and old systemd units - Installs Python venv + validates all 37 M2 tokens
- Sets
CHAIN138_ORACLE_URLin.env - Enables
chain138-oracle-api.service+chain138-oracle-mesh.service - Smoke-tests cBTC spot price and restarts settlement-middleware
Smoke test only:
CHAIN138_ORACLE_URL=http://127.0.0.1:3500 node scripts/deployment/smoke-chain138-oracle-pricing.mjs
Docker Compose (includes chain138-oracle on port 3500):
docker compose -f docker-compose.omnl-production.yml up -d chain138-oracle settlement-middleware
Required environment
| Variable | Purpose |
|---|---|
RPC_URL_138 |
Chain 138 JSON-RPC |
COINGECKO_API_KEY |
FX/crypto refresh (optional but recommended) |
PRIVATE_KEY / DEPLOYER_PRIVATE_KEY |
On-chain aggregator transmitter |
KEEPER_PRIVATE_KEY |
PriceFeedKeeper.performUpkeep |
PRICE_FEED_KEEPER_ADDRESS |
Keeper contract (default in code) |
AGGREGATOR_ADDRESS |
ETH/USD aggregator |
OMNL_REQUIRE_LIVE_BTC_PRICE=1 |
Block repo BTC fallback (production) |
systemd example
[Unit]
Description=Chain 138 Python Oracle Mesh
After=network.target
[Service]
Type=simple
WorkingDirectory=/opt/smom-dbis-138/services/chain138-oracle
EnvironmentFile=/opt/smom-dbis-138/.env
ExecStart=/opt/smom-dbis-138/services/chain138-oracle/.venv/bin/python -m chain138_oracle mesh
Restart=always
RestartSec=3
[Install]
WantedBy=multi-user.target
## Coverage validation
```bash
python -m chain138_oracle validate
# or
python scripts/validate_coverage.py
Exits 0 when every token in omnl-m2-token-registry.v1.json resolves a positive USD price.
Architecture
flowchart LR
CG[CoinGecko] --> FX[fx_refresh.py]
FF[Frankfurter] --> FX
FX --> CACHE[reference_cache]
AGG[On-chain Aggregator] --> ETH[onchain_eth.py]
ETH --> CACHE
CACHE --> CANON[canonical_price.py]
CANON --> API[FastAPI api.py]
CANON --> LIQ[liquidity.py]
PMM[DODO PMM Integration] --> LIQ
MESH[mesh.py] --> ORA[onchain_oracle.py]
MESH --> KEEP[keeper.py]
See also: docs/integration/ORACLE_AND_KEEPER_CHAIN138.md