chore: sync all changes to Gitea
Some checks failed
Deploy to Phoenix / deploy (push) Has been cancelled
Some checks failed
Deploy to Phoenix / deploy (push) Has been cancelled
- Config, docs, scripts, and backup manifests - Submodule refs unchanged (m = modified content in submodules) Made-with: Cursor
This commit is contained in:
131
docs/04-configuration/22_TOKENS_13_CHAINS_DEPLOYMENT_RUNBOOK.md
Normal file
131
docs/04-configuration/22_TOKENS_13_CHAINS_DEPLOYMENT_RUNBOOK.md
Normal file
@@ -0,0 +1,131 @@
|
||||
# 22 Tokens on All 13 Chains — Deployment Runbook
|
||||
|
||||
**Purpose:** Ensure all 22 token types are represented across all 13 chains in DUAL_CHAIN_TOKEN_LIST and DUAL_CHAIN_NETWORKS.
|
||||
|
||||
**Status:** Token list expanded; on-chain deployment documented
|
||||
**Last updated:** 2026-02-28
|
||||
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
| Item | Count |
|
||||
|------|-------|
|
||||
| Chains | 13 (138, 1, 651940, 25, 56, 100, 137, 10, 42161, 8453, 43114, 42220, 1111) |
|
||||
| Token list entries | 52+ (USDC, USDT, WETH on all; custom tokens on 138, 1, 25, 651940) |
|
||||
| Unique token symbols | 17 (ETH-USD, WETH, WETH10, LINK, cUSDT, cUSDC, USDT, USDC, DAI, WETH9, USDW, EURW, GBPW, AUDW, JPYW, CHFW, CADW) |
|
||||
|
||||
---
|
||||
|
||||
## Token List Coverage (DUAL_CHAIN_TOKEN_LIST)
|
||||
|
||||
### Per-chain coverage
|
||||
|
||||
| Chain | Name | USDC | USDT | WETH | Custom (cUSDT, cUSDC, WETH10, ISO-4217 W) |
|
||||
|-------|------|------|------|------|------------------------------------------|
|
||||
| 138 | DeFi Oracle Meta | ✓ | ✓ | ✓ | ✓ (cUSDT, cUSDC, WETH10, LINK, ETH-USD) |
|
||||
| 1 | Ethereum | ✓ | ✓ | ✓ | ✓ (DAI, ETH-USD) |
|
||||
| 651940 | ALL Mainnet | ✓ | ✓ | — | — |
|
||||
| 25 | Cronos | ✓ | ✓ | ✓ (WETH9) | ✓ (WETH10, LINK, USDW, EURW, GBPW, AUDW, JPYW, CHFW, CADW) |
|
||||
| 56 | BSC | ✓ | ✓ | ✓ | — |
|
||||
| 100 | Gnosis | ✓ | ✓ | ✓ | — |
|
||||
| 137 | Polygon | ✓ | ✓ | ✓ | — |
|
||||
| 10 | Optimism | ✓ | ✓ | ✓ | — |
|
||||
| 42161 | Arbitrum | ✓ | ✓ | ✓ | — |
|
||||
| 8453 | Base | ✓ | ✓ | ✓ | — |
|
||||
| 43114 | Avalanche | ✓ | ✓ | ✓ | — |
|
||||
| 42220 | Celo | ✓ | ✓ | ✓ | — |
|
||||
| 1111 | Wemix | ✓ | ✓ | — | — |
|
||||
|
||||
**Note:** Wemix uses WEMIX as native; no standard WETH. USDC/USDT use canonical addresses from `canonical-tokens.ts`.
|
||||
|
||||
---
|
||||
|
||||
## Canonical Addresses (token-aggregation)
|
||||
|
||||
`smom-dbis-138/services/token-aggregation/src/config/canonical-tokens.ts` defines FALLBACK_ADDRESSES for cUSDC and cUSDT on all 13 chains:
|
||||
|
||||
- **Chain 138 / 651940:** Custom cUSDT/cUSDC
|
||||
- **L2s (1, 56, 100, 137, 10, 42161, 8453, 43114, 25, 42220, 1111):** Native USDC/USDT addresses (no custom deployment required for token list)
|
||||
|
||||
---
|
||||
|
||||
## On-Chain Deployment (Custom Tokens)
|
||||
|
||||
### When to deploy
|
||||
|
||||
- **cUSDT / cUSDC:** Deploy only if you need *compliant* versions on L2s (e.g. for PMM, CCIP, or regulatory use). Otherwise, use native USDC/USDT.
|
||||
- **WETH10:** Only on Chain 138 and Cronos (25).
|
||||
- **ISO-4217 W (USDW, EURW, GBPW, etc.):** Only on Cronos (25) today; expand to other chains if required.
|
||||
|
||||
### Deploy cUSDT/cUSDC to all 13 chains
|
||||
|
||||
1. **Prerequisites**
|
||||
- `.env` in `smom-dbis-138/` with `PRIVATE_KEY` and per-chain RPC:
|
||||
- `ETHEREUM_MAINNET_RPC`, `BSC_RPC_URL`, `POLYGON_MAINNET_RPC`, `BASE_MAINNET_RPC`, `OPTIMISM_MAINNET_RPC`, `ARBITRUM_MAINNET_RPC`, `AVALANCHE_RPC_URL`, `CRONOS_RPC_URL`, `GNOSIS_MAINNET_RPC`, `CELO_MAINNET_RPC`, `WEMIX_MAINNET_RPC`
|
||||
- Deployer funded with native gas on each chain (ETH, BNB, MATIC, CRO, xDAI, AVAX, CELO, WEMIX, etc.)
|
||||
|
||||
2. **Run deploy script**
|
||||
```bash
|
||||
cd smom-dbis-138
|
||||
./scripts/deployment/deploy-cusdt-cusdc-all-chains.sh
|
||||
```
|
||||
|
||||
3. **Record addresses**
|
||||
- Add `CUSDT_ADDRESS_<chainId>` and `CUSDC_ADDRESS_<chainId>` to `.env` for each chain.
|
||||
- Update `canonical-tokens.ts` FALLBACK_ADDRESSES if you want to override native USDC/USDT with compliant versions.
|
||||
|
||||
4. **Filter by chain (optional)**
|
||||
```bash
|
||||
DEPLOY_CUSDT_CUSDC_FILTER="POLYGON BASE" ./scripts/deployment/deploy-cusdt-cusdc-all-chains.sh
|
||||
```
|
||||
|
||||
5. **Dry run**
|
||||
```bash
|
||||
DEPLOY_CUSDT_CUSDC_DRY_RUN=1 ./scripts/deployment/deploy-cusdt-cusdc-all-chains.sh
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Sync and Deploy Token List
|
||||
|
||||
After updating `DUAL_CHAIN_TOKEN_LIST.tokenlist.json`:
|
||||
|
||||
```bash
|
||||
# 1. Sync configs to all locations
|
||||
bash scripts/sync-dual-chain-configs.sh
|
||||
|
||||
# 2. Deploy to VMID 5000 (Proxmox)
|
||||
# From repo root — via Proxmox host (pct):
|
||||
PROXMOX_HOST=192.168.11.12 # or PROXMOX_HOST_R630_02
|
||||
scp explorer-monorepo/backend/api/rest/config/metamask/DUAL_CHAIN_TOKEN_LIST.tokenlist.json \
|
||||
explorer-monorepo/backend/api/rest/config/metamask/DUAL_CHAIN_NETWORKS.json \
|
||||
root@${PROXMOX_HOST}:/tmp/
|
||||
ssh root@${PROXMOX_HOST} "
|
||||
pct exec 5000 -- mkdir -p /var/www/html/config
|
||||
pct push 5000 /tmp/DUAL_CHAIN_TOKEN_LIST.tokenlist.json /var/www/html/config/DUAL_CHAIN_TOKEN_LIST.tokenlist.json
|
||||
pct push 5000 /tmp/DUAL_CHAIN_NETWORKS.json /var/www/html/config/DUAL_CHAIN_NETWORKS.json
|
||||
"
|
||||
|
||||
# Or use the deploy script (when on Proxmox host with pct):
|
||||
# ./explorer-monorepo/scripts/deploy-explorer-config-to-vmid5000.sh
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Verification
|
||||
|
||||
| Check | Command / location |
|
||||
|-------|--------------------|
|
||||
| Token list JSON | `python3 -c "import json; json.load(open('explorer-monorepo/backend/api/rest/config/metamask/DUAL_CHAIN_TOKEN_LIST.tokenlist.json'))"` |
|
||||
| Config validation | `./scripts/validation/validate-config-files.sh` |
|
||||
| Token on chain | `cast call <ADDRESS> "totalSupply()(uint256)" --rpc-url $RPC_URL` |
|
||||
| Explorer config | `GET https://<explorer>/api/config/DUAL_CHAIN_TOKEN_LIST.tokenlist.json` |
|
||||
|
||||
---
|
||||
|
||||
## Related Docs
|
||||
|
||||
- [CUSDT_CUSDC_MULTICHAIN_LIQUIDITY_RUNBOOK.md](../../smom-dbis-138/docs/deployment/CUSDT_CUSDC_MULTICHAIN_LIQUIDITY_RUNBOOK.md) — PMM, Uniswap, Balancer, Curve
|
||||
- [canonical-tokens.ts](../../smom-dbis-138/services/token-aggregation/src/config/canonical-tokens.ts) — Address mapping
|
||||
- [DEPLOYED_COINS_TOKENS_AND_NETWORKS.md](DEPLOYED_COINS_TOKENS_AND_NETWORKS.md) — Reference addresses
|
||||
@@ -240,6 +240,8 @@ The following VMIDs have been permanently removed:
|
||||
| 7801 | 192.168.11.51 | sankofa-portal-1 | ✅ Running | Web: 3000 | Sankofa Portal (Company Website) |
|
||||
| 7802 | 192.168.11.52 | sankofa-keycloak-1 | ✅ Running | Keycloak: 8080, Admin: /admin | Identity and Access Management |
|
||||
| 7803 | 192.168.11.53 | sankofa-postgres-1 | ✅ Running | PostgreSQL: 5432 | Database Service |
|
||||
| 7804 | 192.168.11.54 | (Gov Portals dev) | ✅ Running | Web: 80 | Gov Portals — DBIS, ICCC, OMNL, XOM (*.xom-dev.phoenix.sankofa.nexus) |
|
||||
| 7805 | 192.168.11.72 | sankofa-studio | — | API: 8000 | Sankofa Studio (FusionAI Creator) — studio.sankofa.nexus (IP .72; .55 = VMID 10230 order-vault) |
|
||||
|
||||
**Public Domains** (NPMplus routing):
|
||||
- `sankofa.nexus` → Routes to `http://192.168.11.51:3000` (Sankofa Portal/VMID 7801) ✅
|
||||
@@ -247,6 +249,7 @@ The following VMIDs have been permanently removed:
|
||||
- `phoenix.sankofa.nexus` → Routes to `http://192.168.11.50:4000` (Phoenix API/VMID 7800) ✅
|
||||
- `www.phoenix.sankofa.nexus` → Routes to `http://192.168.11.50:4000` (Phoenix API/VMID 7800) ✅
|
||||
- `the-order.sankofa.nexus` → ⚠️ **TBD** (not yet configured)
|
||||
- `studio.sankofa.nexus` → Routes to `http://192.168.11.72:8000` (Sankofa Studio / VMID 7805)
|
||||
|
||||
**Service Details:**
|
||||
- **Host:** r630-01 (192.168.11.11)
|
||||
@@ -375,6 +378,8 @@ Direct to RPC Nodes:
|
||||
- VMID 7802 (sankofa-keycloak-1): 192.168.11.52 ✅ **UNIQUE**
|
||||
- VMID 10232 (CT10232): Reassigned to 192.168.11.56 ✅
|
||||
|
||||
4. **192.168.11.55**: ✅ **IN USE** — VMID 10230 (order-vault) only. Sankofa Studio (VMID 7805) uses **192.168.11.72** to avoid conflict.
|
||||
|
||||
**Resolution:** All IP conflicts resolved using `scripts/resolve-ip-conflicts.sh`
|
||||
|
||||
**Verification:** ✅ All IPs verified unique, all services operational
|
||||
@@ -477,6 +482,7 @@ This section lists all endpoints that should be configured in NPMplus, extracted
|
||||
| `phoenix.sankofa.nexus` | `192.168.11.50` | `http` | `4000` | ❌ No | Phoenix API - Cloud Platform Portal (VMID 7800) ✅ **Deployed** |
|
||||
| `www.phoenix.sankofa.nexus` | `192.168.11.50` | `http` | `4000` | ❌ No | Phoenix API (VMID 7800) ✅ **Deployed** |
|
||||
| `the-order.sankofa.nexus` | ⚠️ **TBD** | `http` | `TBD` | ❌ No | The Order Portal - ⚠️ **Not yet configured** |
|
||||
| `studio.sankofa.nexus` | `192.168.11.72` | `http` | `8000` | ❌ No | Sankofa Studio (FusionAI Creator) — VMID 7805 |
|
||||
|
||||
### Path-Based Routing Notes
|
||||
|
||||
@@ -504,6 +510,7 @@ Some domains use path-based routing in NPM configs:
|
||||
| `sankofa.nexus`, `www.sankofa.nexus` | 7801, 192.168.11.51:3000 | 192.168.11.140 (Blockscout) |
|
||||
| `phoenix.sankofa.nexus`, `www.phoenix.sankofa.nexus` | 7800, 192.168.11.50:4000 | 192.168.11.140 (Blockscout) |
|
||||
| `the-order.sankofa.nexus` | TBD (when The Order portal is deployed) | 192.168.11.140 (Blockscout) |
|
||||
| `studio.sankofa.nexus` | 7805, 192.168.11.72:8000 | — |
|
||||
|
||||
If NPMplus proxy hosts for sankofa.nexus or phoenix.sankofa.nexus currently point to 192.168.11.140, update them to the correct IP:port above. See [RPC_ENDPOINTS_MASTER.md](RPC_ENDPOINTS_MASTER.md) and table "Sankofa Phoenix Services" in this document.
|
||||
|
||||
|
||||
44
docs/04-configuration/CHAIN138_X402_TOKEN_SUPPORT.md
Normal file
44
docs/04-configuration/CHAIN138_X402_TOKEN_SUPPORT.md
Normal file
@@ -0,0 +1,44 @@
|
||||
# Chain 138 Token Support for x402 Payments
|
||||
|
||||
**Purpose:** Record which Chain 138 tokens support ERC-2612 (permit) or ERC-3009, and thus can be used with thirdweb x402 payments.
|
||||
|
||||
**References:** [thirdweb x402](https://portal.thirdweb.com/x402), [CHAIN138_TOKEN_ADDRESSES.md](../11-references/CHAIN138_TOKEN_ADDRESSES.md), plan: x402 and Permit Support for Chain 138.
|
||||
|
||||
---
|
||||
|
||||
## On-chain check results
|
||||
|
||||
Run the verification script (from repo root, with Chain 138 RPC reachable):
|
||||
|
||||
```bash
|
||||
./scripts/verify/check-chain138-token-permit-support.sh [RPC_URL]
|
||||
# Optional: --dry-run to print RPC and token addresses only
|
||||
```
|
||||
|
||||
**Last run:** Script confirms the following for deployed contracts on Chain 138.
|
||||
|
||||
| Token | Address | ERC-2612 (permit) | ERC-3009 (transferWithAuthorization) | x402-compatible |
|
||||
|-------|---------|-------------------|--------------------------------------|-----------------|
|
||||
| cUSDT | `0x93E66202A11B1772E55407B32B44e5Cd8eda7f22` | Not supported | Not supported | No |
|
||||
| cUSDC | `0xf22258f57794CC8E06237084b353Ab30fFfa640b` | Not supported | Not supported | No |
|
||||
|
||||
WETH and WETH10 on Chain 138 (see [CHAIN138_TOKEN_ADDRESSES.md](../11-references/CHAIN138_TOKEN_ADDRESSES.md)) are standard approve/transferFrom implementations and do not expose permit or ERC-3009 in the repo; they are not x402-compatible in their current form.
|
||||
|
||||
---
|
||||
|
||||
## Implications
|
||||
|
||||
- **thirdweb x402** requires the payment token to support either **ERC-2612 permit** or **ERC-3009** (e.g. sign + `transferWithAuthorization` / `receiveWithAuthorization`). See [Chain and token support](https://portal.thirdweb.com/x402#chain-and-token-support).
|
||||
- **Current state:** No deployed Chain 138 token in the canonical list (cUSDT, cUSDC, WETH, WETH10, LINK) is x402-compatible until one of them implements permit or ERC-3009.
|
||||
- **Options:**
|
||||
1. **Use another chain for x402 testing:** e.g. Arbitrum Sepolia with USDC (default in thirdweb x402). The x402 API sketch can be built and tested there, then switched to Chain 138 once a token supports permit.
|
||||
2. **Add ERC-2612 to compliant tokens:** Implement and deploy new CompliantUSDT/CompliantUSDC contracts that extend OpenZeppelin `ERC20Permit` (see plan: Part 1.2 Option B). This implies new contract addresses and updates to [CHAIN138_TOKEN_ADDRESSES.md](../11-references/CHAIN138_TOKEN_ADDRESSES.md) and env/config.
|
||||
|
||||
---
|
||||
|
||||
## When a Chain 138 token gains permit
|
||||
|
||||
After a token on Chain 138 supports ERC-2612 or ERC-3009:
|
||||
|
||||
1. Re-run `./scripts/verify/check-chain138-token-permit-support.sh` and update this doc.
|
||||
2. In the x402 API, use `network: chain138` (custom chain definition) and set `price` to the token object, e.g. `price: { amount: "<base units>", asset: { address: "<token address>", decimals: 6 } }` for cUSDC/cUSDT.
|
||||
51
docs/04-configuration/C_TO_CW_MAPPER_MAPPING.md
Normal file
51
docs/04-configuration/C_TO_CW_MAPPER_MAPPING.md
Normal file
@@ -0,0 +1,51 @@
|
||||
# c* → cW* Mapper Mapping (Multi-Chain)
|
||||
|
||||
**Purpose:** Define the mapping of compliant tokens (c*) on Chain 138 to their wrapped representations (cW*) on other chains for bridge/mapper tooling.
|
||||
|
||||
## Source of truth
|
||||
|
||||
- **Config:** [`config/token-mapping-multichain.json`](../../config/token-mapping-multichain.json)
|
||||
- **`cToCwSymbolMapping`** — Symbol correspondence: each c* symbol maps to its cW* symbol (e.g. `cUSDT` → `cWUSDT`).
|
||||
- **Per-pair tokens** — For each `fromChainId: 138` → `toChainId: <chain>` pair, tokens with key `Compliant_*_cW` define: **addressFrom** = c* contract on 138, **addressTo** = cW* contract on the destination chain (or `0x0` placeholder until deployed).
|
||||
|
||||
## Symbol mapping (c* → cW*)
|
||||
|
||||
| c* (Chain 138) | cW* (other chains) |
|
||||
|----------------|--------------------|
|
||||
| cUSDT | cWUSDT |
|
||||
| cUSDC | cWUSDC |
|
||||
| cEURC | cWEURC |
|
||||
| cEURT | cWEURT |
|
||||
| cGBPC | cWGBPC |
|
||||
| cGBPT | cWGBPT |
|
||||
| cAUDC | cWAUDC |
|
||||
| cJPYC | cWJPYC |
|
||||
| cCHFC | cWCHFC |
|
||||
| cCADC | cWCADC |
|
||||
| cXAUC | cWXAUC |
|
||||
| cXAUT | cWXAUT |
|
||||
|
||||
## Per-chain address mapping
|
||||
|
||||
For each destination chain, the mapper (or bridge config) should resolve:
|
||||
|
||||
- **Compliant_USDT_cW**: Chain 138 cUSDT address → cWUSDT address on destination
|
||||
- **Compliant_USDC_cW**: Chain 138 cUSDC address → cWUSDC address on destination
|
||||
- **Compliant_EURC_cW**: Chain 138 cEURC address → cWEURC address on destination
|
||||
|
||||
(Additional c* → cW* pairs can be added to `token-mapping-multichain.json` when those c* and cW* are deployed.)
|
||||
|
||||
In `token-mapping-multichain.json`, entries with key suffix `_cW` use `addressTo: "0x0000000000000000000000000000000000000000"` as a placeholder until the cW* contract is deployed on that chain. **Operators:** after deploying cW* (e.g. via `DeployCWTokens.s.sol` or equivalent), update the corresponding `addressTo` in the JSON (or in env-driven config that overrides it). The **receiver/bridge on the destination chain must support minting cW*** (e.g. dedicated cW* receiver such as TwoWayTokenBridgeL2, or an extended bridge that calls `cW*.mint(recipient, amount)` in `ccipReceive`); see [CW_BRIDGE_APPROACH.md](../07-ccip/CW_BRIDGE_APPROACH.md) and [CW_BRIDGE_TASK_LIST.md](../00-meta/CW_BRIDGE_TASK_LIST.md).
|
||||
|
||||
## Consumer behavior
|
||||
|
||||
- **Mapper / bridge:** When resolving "cUSDT on 138 → token on chain 56", use:
|
||||
- **Native representation:** key `Compliant_USDT` → `addressTo` = that chain’s native USDT (e.g. BSC USDT).
|
||||
- **Wrapped representation:** key `Compliant_USDT_cW` → `addressTo` = that chain’s cWUSDT. If `addressTo` is zero, treat as "cW* not deployed" and optionally fall back to native or reject.
|
||||
|
||||
- **Loading:** [`config/token-mapping-loader.cjs`](../../config/token-mapping-loader.cjs) builds `addressMapFromTo` / `addressMapToFrom` from `tokens`. Keys `*_cW` are first-class; filter by key suffix or use `cToCwSymbolMapping` for symbol-level logic.
|
||||
|
||||
## Related
|
||||
|
||||
- [EXPLORER_TOKENS_GRU_POLICY.md](EXPLORER_TOKENS_GRU_POLICY.md) — All c* on explorer must be GRU-registered.
|
||||
- [TOKENS_DEPLOYER_DEPLOYED_ON_OTHER_CHAINS.md](../11-references/TOKENS_DEPLOYER_DEPLOYED_ON_OTHER_CHAINS.md) — Deploying cW* via `DeployCWTokens.s.sol` and `--deploy-cw`.
|
||||
173
docs/04-configuration/DETAILED_GAPS_AND_ISSUES_LIST.md
Normal file
173
docs/04-configuration/DETAILED_GAPS_AND_ISSUES_LIST.md
Normal file
@@ -0,0 +1,173 @@
|
||||
# Detailed Gaps and Issues List
|
||||
|
||||
**Date:** 2026-03-02
|
||||
**Purpose:** Consolidated list of items requiring fixes, deployment, or operator action.
|
||||
|
||||
---
|
||||
|
||||
## 1. Explorer API (VMID 5000) — ✅ FIXED (2026-02-28)
|
||||
|
||||
| Issue | Status | Fix |
|
||||
|-------|--------|-----|
|
||||
| `/api/config/token-list` returns Blockscout error (400) | ✅ Fixed | Nginx patched; config files deployed |
|
||||
| `/api/config/networks` returns Blockscout error | ✅ Fixed |
|
||||
|
||||
**Applied:** `scripts/patch-nginx-explorer-config.sh` added locations to HTTP and HTTPS blocks. Config deployed via `pct push`.
|
||||
|
||||
**Original cause:** `location = /api/config/token-list` and `location = /api/config/networks` in `fix-nginx-conflicts-vmid5000.sh` are not in the live nginx config. Requests fall through to `location /api/` and get proxied to Blockscout.
|
||||
|
||||
**Steps:**
|
||||
|
||||
1. SSH to Proxmox host or enter VMID 5000.
|
||||
2. Run inside VMID 5000:
|
||||
```bash
|
||||
# From repo root, copy script into container and run:
|
||||
pct exec 5000 -- bash -c "cd /tmp && [your-fix-nginx-script-content]"
|
||||
# Or: scp fix-nginx-conflicts-vmid5000.sh root@<container-ip>:/tmp/ && ssh root@<container-ip> bash /tmp/fix-nginx-conflicts-vmid5000.sh
|
||||
```
|
||||
3. Deploy config files:
|
||||
```bash
|
||||
# From repo root (with pct or SSH):
|
||||
./explorer-monorepo/scripts/deploy-explorer-config-to-vmid5000.sh
|
||||
# Or EXEC_MODE=ssh: EXEC_MODE=ssh EXPLORER_IP=192.168.11.140 ./explorer-monorepo/scripts/deploy-explorer-config-to-vmid5000.sh
|
||||
```
|
||||
4. Verify:
|
||||
```bash
|
||||
curl -s https://explorer.d-bis.org/api/config/token-list | jq '.tokens | length' # → 22
|
||||
curl -s https://explorer.d-bis.org/api/config/networks | jq '.chains | length' # → 4
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. Token-Aggregation Service — ✅ FIXED (2026-02-28)
|
||||
|
||||
| Issue | Status | Fix |
|
||||
|-------|--------|-----|
|
||||
| `/health` returns `{"status":"unhealthy","error":"database \"token_aggregation\" does not exist"}` | ✅ Fixed | DB created; migrations run; service restarted |
|
||||
|
||||
**Applied:** Created `token_aggregation` DB; ran migrations; restarted service. Health now returns `"status":"healthy"`.
|
||||
|
||||
**Original cause:** The deployed token-aggregation service (port 3001) uses `DATABASE_URL` pointing to a database named `token_aggregation`, but that database does not exist or migrations were not run.
|
||||
|
||||
**Steps:**
|
||||
|
||||
1. On VMID 5000 (or wherever PostgreSQL runs):
|
||||
```bash
|
||||
# Create database if using separate DB:
|
||||
createdb -U postgres token_aggregation
|
||||
# Or ensure DATABASE_URL uses explorer_db (migrations create tables there)
|
||||
```
|
||||
2. Run migrations:
|
||||
```bash
|
||||
cd smom-dbis-138/services/token-aggregation
|
||||
DATABASE_URL=postgresql://user:pass@host:5432/token_aggregation bash scripts/run-migrations.sh
|
||||
# Or with explorer_db: DATABASE_URL=postgresql://user:pass@host:5432/explorer_db
|
||||
```
|
||||
3. Restart token-aggregation:
|
||||
```bash
|
||||
systemctl restart token-aggregation
|
||||
```
|
||||
4. Verify:
|
||||
```bash
|
||||
curl -s http://192.168.11.140:3001/health | jq .
|
||||
# Should return "status":"healthy"
|
||||
```
|
||||
|
||||
**Reference:** `docs/04-configuration/TOKEN_AGGREGATION_REPORT_API_RUNBOOK.md`, `smom-dbis-138/services/token-aggregation/scripts/run-migrations.sh`
|
||||
|
||||
---
|
||||
|
||||
## 3. Nginx Proxy Order — Token-Aggregation vs Blockscout
|
||||
|
||||
| Issue | Status | Fix |
|
||||
|-------|--------|-----|
|
||||
| `/api/v1/` may proxy to Blockscout instead of token-aggregation | ✅ Addressed | `fix-nginx-conflicts-vmid5000.sh` defines `location /api/v1/` **before** `location /api/` (lines 132–142 before 159). When applying config on VMID 5000, use this script to preserve order. |
|
||||
|
||||
**Reference:** `explorer-monorepo/scripts/fix-nginx-conflicts-vmid5000.sh` — correct order is in repo; operator should use this script when (re)applying nginx config.
|
||||
|
||||
---
|
||||
|
||||
## 4. Explorer Homepage / Wallet Page Tests — Intermittent
|
||||
|
||||
| Issue | Status | Fix |
|
||||
|-------|--------|-----|
|
||||
| `verify-all-systems.sh` "Explorer homepage" or "Wallet page" may fail | ✅ Improved | Timeout for Explorer homepage and Wallet page increased from 15s to 25s in `scripts/verify-all-systems.sh` to reduce failures on slow networks. |
|
||||
|
||||
**Note:** Homepage uses `SolaceScanScout|Blockscout|blockscout|<!DOCTYPE`; wallet uses `Chain 138|ChainID 138|Add Chain`. test_endpoint already captures curl output to a variable before grep.
|
||||
|
||||
---
|
||||
|
||||
## 5. Wallet Page — Grep Pattern
|
||||
|
||||
| Issue | Status | Fix |
|
||||
|-------|--------|-----|
|
||||
| Wallet page test looked for "Add Chain 138" | ✅ Fixed | Updated to `Chain 138|ChainID 138|Add Chain` |
|
||||
|
||||
---
|
||||
|
||||
## 6. Token-Aggregation Health Test — Resilience
|
||||
|
||||
| Issue | Status | Fix |
|
||||
|-------|--------|-----|
|
||||
| Health test expected `healthy` only; service returns `unhealthy` when DB missing | ✅ Fixed | Test now accepts `healthy`, `"status"`, or `unhealthy` (service reachable) |
|
||||
|
||||
---
|
||||
|
||||
## 7. Token List Validation — CI
|
||||
|
||||
| Issue | Status | Fix |
|
||||
|-------|--------|-----|
|
||||
| Token lists not validated in CI | ✅ Fixed | `validate-config-files.sh` now validates dbis-138, cronos, all-mainnet, DUAL_CHAIN |
|
||||
| Workflow not triggered on token list changes | ✅ Fixed | `validate-config.yml` paths include `token-lists/**` and `explorer-monorepo/backend/api/rest/config/metamask/**` |
|
||||
|
||||
---
|
||||
|
||||
## 8. DUAL_CHAIN Config Sync
|
||||
|
||||
| Issue | Status | Fix |
|
||||
|-------|--------|-----|
|
||||
| DUAL_CHAIN files in 3 locations could diverge | ✅ Fixed | `scripts/sync-dual-chain-configs.sh` syncs from `explorer-monorepo/backend/api/rest/config/metamask/` to docs and metamask-integration |
|
||||
|
||||
**Usage:** After editing DUAL_CHAIN files, run `./scripts/sync-dual-chain-configs.sh` from repo root.
|
||||
|
||||
---
|
||||
|
||||
## 9. Optional / Future Improvements
|
||||
|
||||
| Item | Priority | Notes |
|
||||
|------|----------|-------|
|
||||
| Shellcheck in CI | Low | `run-shellcheck.sh --optional` — install shellcheck if desired |
|
||||
| Token-aggregation DB naming | Medium | Align DATABASE_URL: use `explorer_db` or create `token_aggregation` and document |
|
||||
| Explorer homepage test timeout | Done (2026-03-02) | Increased to 25s for Explorer homepage and Wallet page in `verify-all-systems.sh` |
|
||||
| All-mainnet token logos (HYDX, HYBX, CHT, AUDA) | Done | Placeholder IPFS logo added |
|
||||
|
||||
---
|
||||
|
||||
## 10. Quick Reference — Scripts
|
||||
|
||||
| Script | Purpose |
|
||||
|--------|---------|
|
||||
| `scripts/verify-all-systems.sh` | Full system verification (explorer, APIs, RPC, token-aggregation) |
|
||||
| `scripts/validation/validate-config-files.sh` | Config and token list validation |
|
||||
| `scripts/sync-dual-chain-configs.sh` | Sync DUAL_CHAIN configs to all locations |
|
||||
| `explorer-monorepo/scripts/fix-nginx-conflicts-vmid5000.sh` | Fix nginx config (run inside VMID 5000) |
|
||||
| `explorer-monorepo/scripts/deploy-explorer-config-to-vmid5000.sh` | Deploy token list and networks to VMID 5000 |
|
||||
| `smom-dbis-138/services/token-aggregation/scripts/run-migrations.sh` | Run token-aggregation DB migrations |
|
||||
|
||||
---
|
||||
|
||||
## 11. Summary — Fixes Applied in This Session
|
||||
|
||||
1. **verify-all-systems.sh:** Wallet page pattern, token-aggregation health test resilience
|
||||
2. **validate-config-files.sh:** Token list validation (dbis-138, cronos, all-mainnet, DUAL_CHAIN)
|
||||
3. **validate-config.yml:** Trigger on token list and config changes
|
||||
4. **sync-dual-chain-configs.sh:** New script to keep DUAL_CHAIN in sync
|
||||
5. **DUAL_CHAIN configs:** Synced to docs and metamask-integration
|
||||
|
||||
---
|
||||
|
||||
## 12. Remaining Operator Actions (Requires Proxmox/Server Access)
|
||||
|
||||
1. Apply nginx fix and deploy config on VMID 5000 (see §1)
|
||||
2. Create token_aggregation DB (or align explorer_db) and run migrations (see §2)
|
||||
3. Restart token-aggregation after DB fix
|
||||
200
docs/04-configuration/DEX_AND_AGGREGATORS_CHAIN138_EXPLAINER.md
Normal file
200
docs/04-configuration/DEX_AND_AGGREGATORS_CHAIN138_EXPLAINER.md
Normal file
@@ -0,0 +1,200 @@
|
||||
# Using DEX and Aggregators with ChainID 138 Coins/Tokens — Explainer
|
||||
|
||||
**Last Updated:** 2026-02-28
|
||||
**Purpose:** Explain how to use DEXs and aggregators with coins/tokens from ChainID 138 (DeFi Oracle Meta Mainnet), and how routing works for swaps and cross-chain flows.
|
||||
|
||||
---
|
||||
|
||||
## 1. Chain 138 tokens in DEX flows
|
||||
|
||||
### 1.1 Tokens on Chain 138
|
||||
|
||||
| Symbol | Address | Role in DEX / aggregator |
|
||||
|--------|---------|---------------------------|
|
||||
| **cUSDT** | `0x93E66202A11B1772E55407B32B44e5Cd8eda7f22` | Compliant stablecoin; pair with cUSDC, USDT, WETH in pools |
|
||||
| **cUSDC** | `0xf22258f57794CC8E06237084b353Ab30fFfa640b` | Compliant stablecoin; pair with cUSDT, USDC, WETH in pools |
|
||||
| **WETH** | `0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2` | Wrapped ETH; bridge asset and quote currency |
|
||||
| **WETH10** | `0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9f` | Alternative WETH; used in CCIP bridge flows |
|
||||
| **LINK** | `0xb7721dD53A8c629d9f1Ba31a5819AFe250002b03` | CCIP fee token; not typically a DEX pair |
|
||||
|
||||
**Official reference tokens (for pool pairs):** USDT at `0x15DF1D5BFDD8Aa4b380445D4e3E9B38d34283619`, USDC per deployment. These are used in **cUSDT/USDT** and **cUSDC/USDC** DODO PMM pools so users can swap between compliant and official stablecoins.
|
||||
|
||||
When building swap UIs or aggregator integrations, use these addresses for **tokenIn** / **tokenOut** and for resolving symbols (e.g. from token list or `/api/v1/tokens`).
|
||||
|
||||
---
|
||||
|
||||
## 2. DEX layer on Chain 138
|
||||
|
||||
### 2.1 Native DEX: DODO PMM
|
||||
|
||||
On Chain 138, the primary DEX layer is **DODO-style PMM** (Proactive Market Maker) via:
|
||||
|
||||
- **DODOPMMIntegration** — `0x79cdbaFBaA0FdF9F55D26F360F54cddE5c743F7D`
|
||||
Creates and manages pools; exposes swap functions and pool state.
|
||||
- **DODOPMMProvider** — `0x8EF6657D2a86c569F6ffc337EE6b4260Bd2e59d0`
|
||||
Used by routing/aggregation to get quotes and execute swaps for registered pools.
|
||||
|
||||
**Pools (created and registered):**
|
||||
|
||||
| Pair | Pool address | Use case |
|
||||
|------|--------------|----------|
|
||||
| cUSDT / cUSDC | `0x9fcB06Aa1FD5215DC0E91Fd098aeff4B62fEa5C8` | Compliant↔compliant stablecoin |
|
||||
| cUSDT / USDT | `0xa3Ee6091696B28e5497b6F491fA1e99047250c59` | Compliant↔official USDT |
|
||||
| cUSDC / USDC | `0x90bd9Bf18Daa26Af3e814ea224032d015db58Ea5` | Compliant↔official USDC |
|
||||
|
||||
**How to swap on-chain (direct):**
|
||||
|
||||
- **cUSDT ↔ cUSDC:** `DODOPMMIntegration.swapCUSDTForUSDC` / `swapUSDCForCUSDT(pool, amountIn, minAmountOut)`
|
||||
- **cUSDT ↔ USDT:** `swapCUSDTForUSDT` / `swapUSDTForCUSDT(pool, …)`
|
||||
- **cUSDC ↔ USDC:** `swapCUSDCForUSDC` / `swapUSDCForCUSDC(pool, …)`
|
||||
|
||||
Caller must approve the integration contract for the input token. Use the pool addresses above for the `pool` argument.
|
||||
|
||||
**Uniswap V2/V3 on 138:** Not deployed by default. If you deploy Uniswap factories and create pools (e.g. cUSDT/WETH, cUSDC/WETH), the token-aggregation service can index them when `CHAIN_138_UNISWAP_V2_FACTORY` / `CHAIN_138_UNISWAP_V3_FACTORY` are set in env.
|
||||
|
||||
---
|
||||
|
||||
## 3. Token-aggregation API (quotes and discovery)
|
||||
|
||||
The **token-aggregation** service indexes tokens and liquidity pools (UniswapV2, UniswapV3, DODO from `DODOPMMIntegration`) and exposes a REST API. This is the main way to get **quotes** and **pool data** for Chain 138 tokens without calling the chain yourself.
|
||||
|
||||
**Base URL:** e.g. `https://explorer.d-bis.org/api/v1` or the URL where the service is proxied (see [REST_API_REFERENCE](../../smom-dbis-138/services/token-aggregation/docs/REST_API_REFERENCE.md)).
|
||||
|
||||
### 3.1 Single-hop quote (DEX quote)
|
||||
|
||||
| Endpoint | Method | Purpose |
|
||||
|----------|--------|---------|
|
||||
| **/api/v1/quote** | GET | Best **single-hop** swap quote for a token pair on one chain |
|
||||
|
||||
**Query:** `chainId=138`, `tokenIn=<address>`, `tokenOut=<address>`, `amountIn=<raw amount in smallest unit>`.
|
||||
|
||||
**Response:** `{ amountOut, poolAddress?, dexType?, error? }` — constant-product style from the first/best indexed pool for that pair. Use for “swap cUSDT → cUSDC” or “cUSDT → WETH” (if a pool exists and is indexed).
|
||||
|
||||
**Limitation:** Single-hop only. There is no N-hop path (e.g. cUSDT → WETH → cUSDC) in this API; routing is one direct pool per pair.
|
||||
|
||||
### 3.2 Token and pool discovery
|
||||
|
||||
| Endpoint | Purpose |
|
||||
|----------|---------|
|
||||
| **GET /api/v1/tokens?chainId=138** | List tokens; optional `includeDodoPool`, market data |
|
||||
| **GET /api/v1/tokens/:address?chainId=138** | Token detail, market data, pools, DODO pool flag |
|
||||
| **GET /api/v1/tokens/:address/pools?chainId=138** | All pools containing this token |
|
||||
| **GET /api/v1/report/token-list?chainId=138** | Uniswap-style token list (for MetaMask / dApp) |
|
||||
|
||||
Use these to resolve symbol→address, get logos, and see which pools exist for cUSDT, cUSDC, WETH on Chain 138.
|
||||
|
||||
### 3.3 Bridge routes and token mapping
|
||||
|
||||
| Endpoint | Purpose |
|
||||
|----------|---------|
|
||||
| **GET /api/v1/bridge/routes** | CCIP WETH9/WETH10 bridge routes; Chain 138 bridge addresses |
|
||||
| **GET /api/v1/token-mapping?fromChain=138&toChain=1** | Token address mapping 138↔other chain (for bridge UIs) |
|
||||
| **GET /api/v1/token-mapping/resolve?fromChain=&toChain=&address=** | Resolve one token address to the other chain |
|
||||
|
||||
Use for “bridge WETH from 138 to Mainnet” or “what is cUSDT on 138 in Mainnet terms” (if a wrapped/bridged form exists).
|
||||
|
||||
---
|
||||
|
||||
## 4. Routing for DEXs — how it works
|
||||
|
||||
### 4.1 Single-hop routing (what’s live today)
|
||||
|
||||
- **On-chain:** User (or contract) calls `DODOPMMIntegration` swap functions directly with the correct pool address. No on-chain “router” that picks the pool.
|
||||
- **Off-chain (API):** Client calls `GET /api/v1/quote` with `chainId=138`, `tokenIn`, `tokenOut`, `amountIn`. The service returns the best direct-pool quote from its index (DODO + any configured Uniswap). Client then executes the swap on the integration contract (or via a front-end that submits the tx).
|
||||
|
||||
So “routing” today = **choose the right pool** (cUSDT/cUSDC, cUSDT/USDT, or cUSDC/USDC) and call the matching swap function with that pool.
|
||||
|
||||
### 4.2 Multi-provider routing (design; not yet deployed)
|
||||
|
||||
**EnhancedSwapRouter** (contract) is designed to route **one leg** (e.g. WETH↔stable) across multiple providers:
|
||||
|
||||
- **By size:** Small (<$10k) → Uniswap V3 / Dodoex; medium ($10k–$100k) → Dodoex → Balancer → Uniswap V3; large (>$100k) → Dodoex → Curve → Balancer.
|
||||
- **By slippage / liquidity:** Prefer Dodoex for low slippage; Balancer/Curve for deeper liquidity.
|
||||
|
||||
This contract is **not deployed** on Chain 138. When deployed (and when Uniswap/Balancer/Curve pools exist on 138), it would sit in front of multiple DEXs and return `getQuotes(stablecoin, amountIn)` and `swapToStablecoin(...)` so one call gets the best execution. **DODOPMMProvider** would be one of the registered providers.
|
||||
|
||||
### 4.3 Swap–bridge–swap (cross-chain routing)
|
||||
|
||||
For **cross-chain** flows (e.g. swap on 138 → bridge to Mainnet → swap on Mainnet):
|
||||
|
||||
- **Orchestration API:** `POST /api/bridge/quote` — request includes source/destination chain, token, amount, destination address. Response can include:
|
||||
- **sourceSwapQuote** — optional quote to swap into the bridge asset on source (e.g. 138) when an EnhancedSwapRouter or equivalent is configured.
|
||||
- **destinationSwapQuote** — optional quote to swap on destination chain after the bridge.
|
||||
- **On-chain coordinator (optional):** **SwapBridgeSwapCoordinator** can perform “swap (source) → bridge → swap (destination)” in one transaction when deployed and configured.
|
||||
|
||||
So “routing for DEXs” in a cross-chain context = **source DEX (138)** + **bridge** + **destination DEX**, with the quote API and optional coordinator tying them together.
|
||||
|
||||
---
|
||||
|
||||
## 5. Using aggregators with Chain 138 tokens
|
||||
|
||||
### 5.1 Internal “aggregation” (token-aggregation service)
|
||||
|
||||
The token-aggregation service **aggregates**:
|
||||
|
||||
- **Pools:** From DODO (DODOPMMIntegration) and, if configured, UniswapV2/V3.
|
||||
- **Quote:** Best **single-hop** quote for a given (tokenIn, tokenOut, amountIn) on one chain.
|
||||
|
||||
So for Chain 138, it acts as a **single-hop quote aggregator** over the indexed DEX (today: DODO PMM). It does **not** split orders across multiple pools or chains; it picks the best direct pool for the pair.
|
||||
|
||||
### 5.2 External DEX aggregators (1inch, 0x, ParaSwap)
|
||||
|
||||
- **1inch, 0x, ParaSwap** and similar aggregators support many chains and DEXs. They do **not** support ChainID 138 unless they add it.
|
||||
- **To use them with Chain 138:** The aggregator would need to add Chain 138 to their config, index or connect to DODO PMM (and any other DEX on 138), and expose 138 in their API/UI. Today you would **contact** them for integration (see [DEX_INTEGRATION_GUIDE](../../metamask-integration/docs/DEX_INTEGRATION_GUIDE.md)).
|
||||
- **Until then:** Use the **token-aggregation** API for quotes and the **DODOPMMIntegration** contract for execution on 138.
|
||||
|
||||
### 5.3 Explorer / bridge aggregator (Go backend)
|
||||
|
||||
The **explorer-monorepo** backend has a bridge aggregator that uses Li.Fi, Socket, Squid, Symbiosis, Relay, Stargate. That aggregation is for **bridge routes**, not for on-chain DEX swaps on 138. For **swap + bridge + swap**, the orchestration **POST /api/bridge/quote** and optional SwapBridgeSwapCoordinator are the relevant pieces.
|
||||
|
||||
---
|
||||
|
||||
## 6. End-to-end flows (summary)
|
||||
|
||||
### Flow A: Swap on Chain 138 only (same chain)
|
||||
|
||||
1. **Resolve tokens:** `GET /api/v1/tokens?chainId=138` or token list; get addresses for cUSDT, cUSDC, WETH.
|
||||
2. **Get quote:** `GET /api/v1/quote?chainId=138&tokenIn=<cUSDT>&tokenOut=<cUSDC>&amountIn=...`
|
||||
3. **Execute:** User signs a tx calling `DODOPMMIntegration.swapCUSDTForUSDC(pool, amountIn, minAmountOut)` (or the matching function for the pair), with approval for the input token.
|
||||
|
||||
### Flow B: Bridge from Chain 138 (no destination swap)
|
||||
|
||||
1. **Bridge routes:** `GET /api/v1/bridge/routes` for WETH9/WETH10 and Chain 138 bridge addresses.
|
||||
2. **Token mapping:** If needed, `GET /api/v1/token-mapping/resolve` for 138→destination.
|
||||
3. User sends a bridge tx (e.g. CCIP) from 138 to the destination chain; no DEX swap on 138 unless they first swap into WETH/WETH10.
|
||||
|
||||
### Flow C: Swap on 138 → bridge → swap on destination
|
||||
|
||||
1. **Quote:** `POST /api/bridge/quote` with source chain 138, destination chain, token, amount, destination address. Response may include `sourceSwapQuote` and `destinationSwapQuote`.
|
||||
2. **Source (138):** If user holds cUSDT/cUSDC, optionally swap to WETH via DODOPMMIntegration (or future router) using Flow A.
|
||||
3. **Bridge:** User (or coordinator) executes bridge transfer.
|
||||
4. **Destination:** Optional swap using `destinationSwapQuote` or destination-chain DEX.
|
||||
|
||||
---
|
||||
|
||||
## 7. Config and env (integrators)
|
||||
|
||||
| Use case | Env / config |
|
||||
|----------|---------------|
|
||||
| **Token-aggregation indexing DODO on 138** | `CHAIN_138_DODO_PMM_INTEGRATION=0x79cdbaFBaA0FdF9F55D26F360F54cddE5c743F7D` (and RPC, DB). Optional: `CHAIN_138_DODO_POOL_MANAGER`, `CHAIN_138_DODO_VENDING_MACHINE`. |
|
||||
| **Uniswap on 138 (if deployed)** | `CHAIN_138_UNISWAP_V2_FACTORY`, `CHAIN_138_UNISWAP_V2_ROUTER`, `CHAIN_138_UNISWAP_V2_START_BLOCK` (and V3 equivalents). |
|
||||
| **Bridge quote (swap+bridge+swap)** | `RPC_URL`, `BRIDGE_REGISTRY_ADDRESS`; optional `ENHANCED_SWAP_ROUTER_ADDRESS`, `DESTINATION_RPC_URL`, `DESTINATION_SWAP_ROUTER_ADDRESS`. |
|
||||
| **Token list / MetaMask** | Token-aggregation `GET /api/v1/report/token-list?chainId=138` or static list; point MetaMask/dApp to this URL. |
|
||||
|
||||
---
|
||||
|
||||
## 8. Reference
|
||||
|
||||
| Document | Content |
|
||||
|----------|---------|
|
||||
| [PMM_DEX_ROUTING_STATUS.md](../11-references/PMM_DEX_ROUTING_STATUS.md) | DEX/PMM deployment status, what’s live vs not |
|
||||
| [TASKS_TO_INCREASE_ALL_E2E_FLOWS.md](../00-meta/TASKS_TO_INCREASE_ALL_E2E_FLOWS.md) | **Tasks** required to complete Flow A, B, C and cross-cutting E2E |
|
||||
| [STATUS_AND_TOKEN_ROUTING.md](../../smom-dbis-138/docs/STATUS_AND_TOKEN_ROUTING.md) | Token-aggregation API summary, routing layers, multihop |
|
||||
| [REST_API_REFERENCE.md](../../smom-dbis-138/services/token-aggregation/docs/REST_API_REFERENCE.md) | Full token-aggregation API |
|
||||
| [DODO_PMM_INTEGRATION.md](../../smom-dbis-138/docs/integration/DODO_PMM_INTEGRATION.md) | Pool creation, swap functions, liquidity |
|
||||
| [ENHANCED_ROUTING.md](../../smom-dbis-138/docs/bridge/trustless/integration/ENHANCED_ROUTING.md) | Multi-provider routing design (EnhancedSwapRouter) |
|
||||
| [DEX_INTEGRATION_GUIDE.md](../../metamask-integration/docs/DEX_INTEGRATION_GUIDE.md) | Partner DEX/aggregator options (1inch, 0x, ParaSwap) |
|
||||
| [ADDRESS_MATRIX_AND_STATUS.md](../11-references/ADDRESS_MATRIX_AND_STATUS.md) | All Chain 138 addresses (tokens, pools, contracts) |
|
||||
|
||||
**Explorer (Chain 138):** https://explorer.d-bis.org
|
||||
**RPC (public):** https://rpc-core.d-bis.org (deployment should use Core RPC; see runbooks.)
|
||||
51
docs/04-configuration/EXPLORER_FUNCTIONALITY_REVIEW.md
Normal file
51
docs/04-configuration/EXPLORER_FUNCTIONALITY_REVIEW.md
Normal file
@@ -0,0 +1,51 @@
|
||||
# Explorer functionality review (routes, API, Snap)
|
||||
|
||||
Reference for what works, what the SPA calls, and fixes applied.
|
||||
|
||||
## 1. Site routes and navigation
|
||||
|
||||
All primary routes return **HTTP 200** and render the same SPA shell (Explore: Home, Blocks, Transactions; Tools: Bridge, WETH, Tokens, Watchlist; MetaMask Snap; language toggle; Connect Wallet):
|
||||
|
||||
- `/`, `/home`, `/blocks`, `/transactions`, `/bridge`, `/weth`, `/tokens`, `/watchlist`, `/analytics`, `/operator`
|
||||
|
||||
Static routing and nginx serving are OK.
|
||||
|
||||
## 2. Exact API URLs the SPA calls
|
||||
|
||||
When the page is at `https://explorer.d-bis.org`, the SPA uses **relative** `/api`. In DevTools → Network, filter by `api` and confirm these:
|
||||
|
||||
| Widget / feature | URL |
|
||||
|----------------------------|-----|
|
||||
| Stats (Total Blocks, etc.) | `GET /api/v2/stats` |
|
||||
| Gas & Network | `GET /api/v2/blocks?page=1&page_size=20`, `GET /api/v2/stats`, `GET /api/v2/transactions?page=1&page_size=100` |
|
||||
| Latest Blocks | `GET /api/v2/blocks?page=1&page_size=10` |
|
||||
| Latest Transactions | `GET /api/v2/transactions?page=1&page_size=10` |
|
||||
| Tokens (list) | `GET /api/v2/tokens?page=1&page_size=100` |
|
||||
| Bridge Monitoring | **No API call** — content is static HTML. If it stays "Loading bridge data…", a JS error may prevent the bridge view from running. |
|
||||
|
||||
If any of these return non-200 or (failed) CORS, that’s the failing path. If all return 200 but the UI still shows "Loading…", the issue is in the SPA (parsing, DOM update, or an exception after fetch). See [explorer-monorepo/docs/EXPLORER_LOADING_TROUBLESHOOTING.md](../../explorer-monorepo/docs/EXPLORER_LOADING_TROUBLESHOOTING.md).
|
||||
|
||||
## 3. Blockscout stats endpoint
|
||||
|
||||
- `https://explorer.d-bis.org/api/v2/stats` returns **200** with `total_blocks`, `total_transactions`, `gas_prices`, `average_block_time`, etc. So the API is up.
|
||||
|
||||
## 4. MetaMask Snap section
|
||||
|
||||
- **`/snap/`** — Chain 138 Snap page loads; set `GATSBY_SNAP_API_BASE_URL` for market/summary/bridge/swap cards.
|
||||
- **`/snap/send`** — **Fix applied:** The "Send on Chain 138" link is now built as an **absolute HTTPS** URL when `GATSBY_SNAP_SITE_URL` is set (e.g. `https://explorer.d-bis.org/snap/send`), so the link no longer leads to an HTTP redirect. Rebuild the Snap site with `GATSBY_SNAP_SITE_URL=https://explorer.d-bis.org` (see [chain138-snap/scripts/build-snap-site-for-explorer.sh](../../metamask-integration/chain138-snap/scripts/build-snap-site-for-explorer.sh)) and redeploy to VMID 5000.
|
||||
|
||||
## 5. Contract verification
|
||||
|
||||
- **Blockscout** supports contract verification (Etherscan-compatible and v2 API). From the explorer: open an **address** → **Contract** tab → **Verify & Publish** (if the instance shows it).
|
||||
- **Forge (CLI):** Use the **forge-verification-proxy** and then run verification scripts so Forge’s payload is translated to Blockscout v2. See [08-monitoring/BLOCKSCOUT_VERIFICATION_GUIDE.md](../08-monitoring/BLOCKSCOUT_VERIFICATION_GUIDE.md) and [forge-verification-proxy/README.md](../../forge-verification-proxy/README.md). Scripts: `scripts/verify/run-contract-verification-with-proxy.sh`, `scripts/verify-contracts-blockscout.sh`.
|
||||
- **Gaps and more:** [EXPLORER_GAPS_AND_RECOMMENDATIONS.md](EXPLORER_GAPS_AND_RECOMMENDATIONS.md) § Contract verification.
|
||||
|
||||
---
|
||||
|
||||
## 6. Conclusions from observed behavior
|
||||
|
||||
- **Static routing / nginx:** OK (all pages load).
|
||||
- **Blockscout stats:** OK (`/api/v2/stats` returns 200).
|
||||
- **SPA dynamic widgets:** If still "Loading…" after fixes (relative `/api`, no `filter=to`, cache-bust `?v=3`), verify (1) deployed `explorer-spa.js` on VMID 5000 is the latest, (2) hard-refresh (Ctrl+Shift+R), (3) DevTools Console for first error and Network for failing API URL + status.
|
||||
- **Snap send:** Use absolute HTTPS link (rebuild with `GATSBY_SNAP_SITE_URL`, redeploy Snap site).
|
||||
- **Full gaps, bridge/lanes, verification, user/API keys:** [EXPLORER_GAPS_AND_RECOMMENDATIONS.md](EXPLORER_GAPS_AND_RECOMMENDATIONS.md).
|
||||
125
docs/04-configuration/EXPLORER_GAPS_AND_RECOMMENDATIONS.md
Normal file
125
docs/04-configuration/EXPLORER_GAPS_AND_RECOMMENDATIONS.md
Normal file
@@ -0,0 +1,125 @@
|
||||
# Explorer: Gaps, Recommendations, and Additional Items
|
||||
|
||||
**Purpose:** Single reference for explorer (https://explorer.d-bis.org): loading, bridge/lanes, **contract verification (Verify & Publish + Forge batch)**, user/API keys, and all other recommendations and gaps.
|
||||
|
||||
**Related:** [EXPLORER_FUNCTIONALITY_REVIEW.md](EXPLORER_FUNCTIONALITY_REVIEW.md) | [EXPLORER_METAMASK_TECHNICAL_RESPONSE.md](EXPLORER_METAMASK_TECHNICAL_RESPONSE.md) | [EXPLORER_TROUBLESHOOTING.md](EXPLORER_TROUBLESHOOTING.md) | [BLOCKSCOUT_VERIFICATION_GUIDE.md](../08-monitoring/BLOCKSCOUT_VERIFICATION_GUIDE.md) | [explorer-monorepo/docs/EXPLORER_LOADING_TROUBLESHOOTING.md](../../explorer-monorepo/docs/EXPLORER_LOADING_TROUBLESHOOTING.md)
|
||||
|
||||
---
|
||||
|
||||
## 1. Loading on all pages
|
||||
|
||||
### 1.1 Intended behavior
|
||||
|
||||
| Page / view | Data loaded | Source |
|
||||
|-------------|-------------|--------|
|
||||
| **Home** | Stats, Gas & Network, Latest Blocks, Latest Transactions | `loadStats()`, `loadGasAndNetworkStats()`, `loadLatestBlocks()`, `loadLatestTransactions()` — all use `/api/v2/*` (Blockscout). |
|
||||
| **Blocks** | Paginated block list | `loadAllBlocks()` → `/api/v2/blocks?page=&page_size=25`. |
|
||||
| **Transactions** | Paginated transaction list | `loadAllTransactions()` → `/api/v2/transactions?page=&page_size=25`. |
|
||||
| **Bridge** | Static bridge/lanes content | `refreshBridgeData()` — no API; builds HTML from hardcoded routes. If "Loading bridge data…" persists, a JS error likely prevents this from running. |
|
||||
| **Tokens** | Token list | `loadTokensList()` → `/api/v2/tokens?page=1&page_size=100`. |
|
||||
| **WETH** | Static UI + wallet balance (if connected) | No Blockscout list API; wrap/unwrap uses RPC. |
|
||||
| **Watchlist** | LocalStorage-backed list | `_renderWatchlist()` — no API. |
|
||||
| **Analytics** | Placeholder (Track 3) | "Coming soon" message; gated by `hasAccess(3)`. |
|
||||
| **Operator** | Placeholder (Track 4) | "Coming soon" message; gated by `hasAccess(4)`. |
|
||||
|
||||
### 1.2 If widgets stay "Loading…" or "—"
|
||||
|
||||
- Ensure **all** of these return **200** when opened from the explorer origin: `/api/v2/stats`, `/api/v2/blocks?page=1&page_size=10`, `/api/v2/transactions?page=1&page_size=10`, `/api/v2/tokens?page=1&page_size=100`. See [EXPLORER_LOADING_TROUBLESHOOTING](../../explorer-monorepo/docs/EXPLORER_LOADING_TROUBLESHOOTING.md) for exact URLs and do-now checks.
|
||||
- Redeploy frontend after SPA changes; use cache-bust `explorer-spa.js?v=3` (or higher) and hard-refresh.
|
||||
|
||||
---
|
||||
|
||||
## 2. Bridges and lanes / routes to all networks
|
||||
|
||||
### 2.1 Current state
|
||||
|
||||
- **Bridge Monitoring** view shows:
|
||||
- Chain 138 WETH9/WETH10 bridge addresses (correct: `0x971cD9…`, `0xe0E932…`).
|
||||
- **WETH9 routes:** BSC (56), Polygon (137), Avalanche (43114), Base (8453), Arbitrum (42161), Optimism (10), Ethereum Mainnet (1).
|
||||
- **WETH10 routes:** Same 7 destinations.
|
||||
- **Ethereum Mainnet bridges:** WETH9 `0x2A0840…`, WETH10 `0xb7721d…` (correct).
|
||||
- **Source of truth for lanes:** [07-ccip/CHAIN138_COMPLETE_ROUTING_TABLE.md](../07-ccip/CHAIN138_COMPLETE_ROUTING_TABLE.md), [07-ccip/MAPPER_GAPS_DEPLOYMENTS_AND_IMPROVEMENTS.md](../07-ccip/MAPPER_GAPS_DEPLOYMENTS_AND_IMPROVEMENTS.md).
|
||||
|
||||
### 2.2 Gaps and recommendations
|
||||
|
||||
| Item | Status | Recommendation |
|
||||
|------|--------|----------------|
|
||||
| **Destination-chain "Bridge Address" in SPA** | Addresses for BSC/Polygon/etc. in the SPA are hardcoded; some may be placeholders (e.g. CCIP Router 138 reused). | Source remote bridge (or router) addresses from config/API (e.g. token-aggregation or `config/smart-contracts-master.json`) when available; or add a "Reference" link to CHAIN138_COMPLETE_ROUTING_TABLE. |
|
||||
| **Cronos (25), Gnosis (100), Celo (42220), Wemix (1111)** | Routing table lists Cronos as live; 100/42220/1111 as "Config ready". SPA shows only 7 destinations. | Add Cronos (25) to the Bridge Monitoring table when destination bridge address is confirmed; add a short "More chains (Gnosis, Celo, Wemix) when configured" note and link to routing table. |
|
||||
| **All lanes load** | Bridge view is static HTML; no runtime fetch of lanes. | Optional: call `GET /api/v1/bridge/routes` (or equivalent) if the explorer backend exposes it, and render lanes from response so new chains appear without SPA redeploy. |
|
||||
|
||||
---
|
||||
|
||||
## 3. Contract verification
|
||||
|
||||
### 3.1 What exists
|
||||
|
||||
- **Blockscout** on VMID 5000 supports contract verification (Etherscan-compatible + v2 API).
|
||||
- **Forge verification:** Use the **forge-verification-proxy** so Forge’s payload is translated to Blockscout v2. See [forge-verification-proxy/README.md](../../forge-verification-proxy/README.md) and [08-monitoring/BLOCKSCOUT_VERIFICATION_GUIDE.md](../08-monitoring/BLOCKSCOUT_VERIFICATION_GUIDE.md).
|
||||
- **Scripts:** `scripts/verify/run-contract-verification-with-proxy.sh`, `scripts/verify-contracts-blockscout.sh` (and smom-dbis-138 equivalents).
|
||||
|
||||
### 3.2 Verify & Publish (Blockscout UI)
|
||||
|
||||
To verify a contract from the explorer when automated verification is unavailable or returns 502:
|
||||
|
||||
1. Open **https://explorer.d-bis.org/address/<CONTRACT_ADDRESS>**
|
||||
2. Go to the **Contract** tab → **Verify & Publish**
|
||||
3. Choose method: **Via Standard JSON Input** (recommended), **Via Sourcify**, or **Via Multi-file**
|
||||
4. Upload source (or paste) and provide constructor arguments if needed; submit.
|
||||
|
||||
See [08-monitoring/BLOCKSCOUT_VERIFICATION_GUIDE.md](../08-monitoring/BLOCKSCOUT_VERIFICATION_GUIDE.md) for Forge/proxy batch verification and troubleshooting (502, HTML response).
|
||||
|
||||
### 3.3 Recommendations
|
||||
|
||||
| Item | Recommendation |
|
||||
|------|-----------------|
|
||||
| **Batch verification (Forge + proxy)** | From a host that can reach Blockscout (LAN): `source smom-dbis-138/.env 2>/dev/null; ./scripts/verify/run-contract-verification-with-proxy.sh`. Uses canonical addresses from .env; see [BLOCKSCOUT_VERIFICATION_GUIDE](../08-monitoring/BLOCKSCOUT_VERIFICATION_GUIDE.md). |
|
||||
| **API key for Blockscout** | Self-hosted Blockscout at explorer.d-bis.org does not require an API key for read API. If rate limits or private endpoints are added later, document API key issuance (see §4). |
|
||||
|
||||
---
|
||||
|
||||
## 4. User profile and dev API key issuance
|
||||
|
||||
### 4.1 Gap
|
||||
|
||||
- **No user accounts or developer API keys** are implemented in the explorer or Blockscout today. Blockscout (self-hosted) typically does not ship a "developer portal" for API key signup; read API is public or protected at the reverse-proxy/nginx level.
|
||||
|
||||
### 4.2 Recommendations
|
||||
|
||||
| Option | Effort | Notes |
|
||||
|--------|--------|--------|
|
||||
| **A. Blockscout API keys (if enabled)** | Low | If your Blockscout version supports API keys for the read API, enable them and document how operators issue keys (e.g. via Blockscout admin or env). |
|
||||
| **B. Nginx/API gateway rate limit by key** | Medium | Put an API gateway or nginx in front of `/api` that requires a query param or header (e.g. `?apikey=`) and issue keys out-of-band (e.g. from a simple script or internal form). |
|
||||
| **C. Separate developer portal** | High | Build a small "developer portal" (e.g. in dbis_core or the-order) that allows signup/login and issues API keys for explorer (and other) APIs; store keys and enforce in gateway. |
|
||||
|
||||
**Suggested short-term:** Document that the explorer API is currently public (no key). If you need keys later, start with (A) or (B) and add a one-page "API access" doc with whom to contact for a key and which base URL to use.
|
||||
|
||||
---
|
||||
|
||||
## 5. Other recommendations and suggestions
|
||||
|
||||
### 5.1 From existing docs
|
||||
|
||||
- **Snap /send HTTPS:** Ensure "Send on Chain 138" link is absolute HTTPS (`GATSBY_SNAP_SITE_URL` in Snap build). Done in repo; rebuild and redeploy Snap site to apply.
|
||||
- **CoinGecko / API keys:** Token-aggregation and oracle may use CoinGecko (and optional CMC); see [COINGECKO_API_KEY_SETUP.md](COINGECKO_API_KEY_SETUP.md) and [API_KEYS_REQUIRED.md](../../reports/API_KEYS_REQUIRED.md). Not explorer-specific but affects Snap/market data.
|
||||
- **RPC TRACE:** Already enabled on public RPC (VMID 2201) for Blockscout indexing; see [explorer-monorepo/docs/RPC_FUNCTIONALITY_AND_BLOCKSCOUT_TRACE.md](../../explorer-monorepo/docs/RPC_FUNCTIONALITY_AND_BLOCKSCOUT_TRACE.md).
|
||||
|
||||
### 5.2 Explorer-specific
|
||||
|
||||
| # | Recommendation | Priority |
|
||||
|---|----------------|----------|
|
||||
| 1 | Ensure all SPA views that call `/api` handle 4xx/5xx and show a clear "Retry" or error message. | High |
|
||||
| 2 | Add a "Verify contract" link or short instructions on the address/contract page (link to Blockscout verification or BLOCKSCOUT_VERIFICATION_GUIDE). | Medium |
|
||||
| 3 | Consider serving bridge routes from a small config or API so new chains don’t require an SPA redeploy. | Low |
|
||||
| 4 | Analytics (Track 3) / Operator (Track 4): when implemented, document access control and any API keys. | Future |
|
||||
| 5 | Optional: add Blockscout "API" or "Docs" link in footer (e.g. to Blockscout API docs or internal API overview). | Low |
|
||||
|
||||
---
|
||||
|
||||
## 6. Quick checklist (operator)
|
||||
|
||||
- [ ] All explorer pages load; no persistent "Loading…" for stats, blocks, transactions, tokens, bridge (see §1).
|
||||
- [ ] Bridge Monitoring shows Chain 138 + Mainnet bridges and 7 (or more) destination lanes; add Cronos/config-ready chains if desired (§2).
|
||||
- [ ] Contract verification: proxy + Forge runbook documented; run batch verification for main contracts (§3).
|
||||
- [ ] User/API key: decision documented; if keys are introduced, add "API access" doc and issuance process (§4).
|
||||
- [ ] Snap site: rebuilt with `GATSBY_SNAP_SITE_URL`; `/snap/send` link is HTTPS (§5).
|
||||
170
docs/04-configuration/EXPLORER_METAMASK_TECHNICAL_RESPONSE.md
Normal file
170
docs/04-configuration/EXPLORER_METAMASK_TECHNICAL_RESPONSE.md
Normal file
@@ -0,0 +1,170 @@
|
||||
# Explorer + MetaMask Technical Response — 5 Items for Exact Config
|
||||
|
||||
**Purpose:** Reply to the technical review so you get exact “do this / set that” config values for the explorer and MetaMask.
|
||||
|
||||
---
|
||||
|
||||
## Ready-to-send reply (copy-paste all below)
|
||||
|
||||
**5 items (send as-is)**
|
||||
|
||||
**1) RPC URL used by MetaMask**
|
||||
|
||||
- Public (MetaMask / dApps): `https://rpc-http-pub.d-bis.org`
|
||||
- WebSocket: `wss://rpc-ws-pub.d-bis.org`
|
||||
- Internal: `http://192.168.11.221:8545`
|
||||
|
||||
**2) ChainId**
|
||||
|
||||
- Decimal: `138`
|
||||
- Hex: `0x8a`
|
||||
|
||||
**3) Explorer backend stack**
|
||||
|
||||
- Backend: **Blockscout** (Docker container on VMID 5000, API on port 4000)
|
||||
- Frontend: **SolaceScanScout** SPA served by nginx on VMID 5000; frontend calls `/api` (nginx proxy to `http://127.0.0.1:4000`) and uses the same RPC for wallet/fallback
|
||||
|
||||
**4) Intended wrapped-native (WETH9) on chain (Chain 138)**
|
||||
|
||||
- WETH9: `0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2` (same as Ethereum mainnet **by design**; canonical bytecode verified on 138)
|
||||
- WETH10: `0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9f`
|
||||
- Bridges:
|
||||
- WETH9 Bridge: `0x971cD9D156f193df8051E48043C476e53ECd4693`
|
||||
- WETH10 Bridge: `0xe0E93247376aa097dB308B92e6Ba36bA015535D0`
|
||||
|
||||
**5) EIP-1559**
|
||||
|
||||
- Yes — blocks include `baseFeePerGas`
|
||||
|
||||
**Summary table (paste-friendly)**
|
||||
|
||||
| # | Item | Value |
|
||||
| - | ---------------------- | -------------------------------------------------------------------------- |
|
||||
| 1 | RPC URL (MetaMask) | `https://rpc-http-pub.d-bis.org` (WS: `wss://rpc-ws-pub.d-bis.org`) |
|
||||
| 2 | ChainId | Decimal: **138** — Hex: **0x8a** |
|
||||
| 3 | Explorer backend stack | **Blockscout** (VMID 5000:4000) + **SolaceScanScout** (nginx on VMID 5000) |
|
||||
| 4 | Wrapped-native (WETH9) | **`0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2`** |
|
||||
| 5 | EIP-1559 | **Yes** — `baseFeePerGas` present |
|
||||
|
||||
**Optional: Backend RPC and API wiring (for "Loading…" fixes)**
|
||||
|
||||
- Blockscout env (VMID 5000):
|
||||
- `ETHEREUM_JSONRPC_HTTP_URL=http://192.168.11.221:8545`
|
||||
- `ETHEREUM_JSONRPC_WS_URL=ws://192.168.11.221:8546`
|
||||
- `ETHEREUM_JSONRPC_VARIANT=besu`
|
||||
- `CHAIN_ID=138`
|
||||
- Frontend: calls `/api` (same origin on `https://explorer.d-bis.org`); nginx proxies `/api` → Blockscout `:4000`
|
||||
- TRACE API: enabled on public RPC node (VMID 2201) so Blockscout can index internals/block rewards
|
||||
|
||||
---
|
||||
|
||||
## 1. RPC URL used by MetaMask
|
||||
|
||||
- **Public (recommended for MetaMask / dApps):**
|
||||
- **HTTPS:** `https://rpc-http-pub.d-bis.org`
|
||||
- **WebSocket:** `wss://rpc-ws-pub.d-bis.org`
|
||||
- **Internal (same backend, HTTP only):** `http://192.168.11.221:8545` (VMID 2201, besu-rpc-public-1)
|
||||
|
||||
MetaMask and the explorer frontend use the **HTTPS** URL when the site is served over `https://explorer.d-bis.org`; otherwise they fall back to the HTTP URL. The explorer **backend** (Blockscout) uses `http://192.168.11.221:8545` (same node).
|
||||
|
||||
---
|
||||
|
||||
## 2. ChainId (hex and decimal)
|
||||
|
||||
- **Decimal:** `138`
|
||||
- **Hex:** `0x8a` (also written `0x8A` in some UIs)
|
||||
|
||||
---
|
||||
|
||||
## 3. Explorer backend stack
|
||||
|
||||
- **Backend:** **Blockscout** (Docker container on VMID 5000, API on port 4000).
|
||||
- **Frontend:** Custom SPA **“SolaceScanScout”** (static HTML/JS in `explorer-monorepo/frontend/public/`), served by nginx on VMID 5000. The frontend calls:
|
||||
- **Blockscout API** at `/api` (proxied by nginx to `http://127.0.0.1:4000`).
|
||||
- **RPC** (for fallback / wallet) at `https://rpc-http-pub.d-bis.org` or `http://192.168.11.221:8545` as above.
|
||||
|
||||
So: **Blockscout** is the indexer/API; **SolaceScanScout** is the custom frontend branding and UI.
|
||||
|
||||
**Screenshots (live UI):** See [../images/README.md](../images/README.md) for image list. Reference images (replace with live captures from https://explorer.d-bis.org/ if desired):
|
||||
|
||||
| View | Image |
|
||||
|------|--------|
|
||||
| Home (stats, Gas & Network, Latest Blocks/Transactions) |  |
|
||||
| Blocks list |  |
|
||||
| Transactions list |  |
|
||||
|
||||
---
|
||||
|
||||
## 4. Intended wrapped-native contract addresses (Chain 138)
|
||||
|
||||
Chain 138 intentionally uses the **same addresses as Ethereum mainnet** for WETH9/WETH10 (deployed-at-same-address / CREATE2-style setup). They exist on Chain 138 and are the intended wrapped-native contracts.
|
||||
|
||||
| Token / Bridge | Address (Chain 138) | Notes |
|
||||
|-----------------------|---------------------|--------|
|
||||
| **WETH9** (wrapped-native) | `0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2` | Same as mainnet; canonical WETH9 bytecode verified on 138 (see `smom-dbis-138/scripts/verify-weth9-canonical.js`). |
|
||||
| **WETH10** | `0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9f` | Same as mainnet. |
|
||||
| **WETH9 Bridge** (CCIP) | `0x971cD9D156f193df8051E48043C476e53ECd4693` | In `config/contract-addresses.conf` as `ADDR_CCIPWETH9_BRIDGE`. |
|
||||
| **WETH10 Bridge** (CCIP) | `0xe0E93247376aa097dB308B92e6Ba36bA015535D0` | In `config/contract-addresses.conf` as `ADDR_CCIPWETH10_BRIDGE`. |
|
||||
|
||||
So the **intended wrapped-native (WETH9-equivalent) address** on Chain 138 is **`0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2`**. The explorer is correct to show it; the chain is not “mainnet” but uses that address by design.
|
||||
|
||||
---
|
||||
|
||||
## 5. EIP-1559 (baseFeePerGas)
|
||||
|
||||
- **Yes.** The chain uses EIP-1559; blocks include **baseFeePerGas**.
|
||||
- Deployment and gas scripts (e.g. in `scripts/archive/consolidated/deploy/`) use `eth_getBlockByNumber("latest", false)` and read `baseFeePerGas` for gas pricing.
|
||||
- Docs state EIP-1559 is supported (e.g. `docs/11-references/DEFI_ORACLE_META_MAINNET_PROJECT_DESCRIPTION.md`, `docs/04-configuration/ADD_CHAIN138_TO_LEDGER_LIVE.md`).
|
||||
|
||||
---
|
||||
|
||||
## Summary table (paste-friendly)
|
||||
|
||||
| # | Item | Value |
|
||||
|---|------|--------|
|
||||
| 1 | **RPC URL (MetaMask)** | `https://rpc-http-pub.d-bis.org` (WS: `wss://rpc-ws-pub.d-bis.org`) |
|
||||
| 2 | **ChainId** | Decimal: **138** — Hex: **0x8a** |
|
||||
| 3 | **Explorer backend stack** | **Blockscout** (API on VMID 5000:4000) + custom frontend **SolaceScanScout** (nginx on VMID 5000) |
|
||||
| 4 | **Wrapped-native (WETH9) on chain** | **`0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2`** (same as mainnet by design) |
|
||||
| 5 | **EIP-1559** | **Yes** — baseFeePerGas present in blocks |
|
||||
|
||||
---
|
||||
|
||||
## Optional: Backend RPC and API wiring (for “Loading…” fixes)
|
||||
|
||||
- **Blockscout env (VMID 5000):**
|
||||
- `ETHEREUM_JSONRPC_HTTP_URL=http://192.168.11.221:8545`
|
||||
- `ETHEREUM_JSONRPC_WS_URL=ws://192.168.11.221:8546`
|
||||
- `ETHEREUM_JSONRPC_VARIANT=besu`
|
||||
- `CHAIN_ID=138`
|
||||
- **Frontend:** Calls `/api` (same origin when on `https://explorer.d-bis.org`); nginx proxies `/api` to Blockscout on port 4000.
|
||||
- **TRACE API:** Enabled on the public RPC node (VMID 2201) so Blockscout can index internal transactions and block rewards (see `explorer-monorepo/docs/RPC_FUNCTIONALITY_AND_BLOCKSCOUT_TRACE.md`).
|
||||
|
||||
You can paste the **Summary table** plus the **Optional** paragraph (if they need backend details) into your reply to get the exact explorer env/config, WETH9/WETH10/bridge wiring, and RPC checklist.
|
||||
|
||||
---
|
||||
|
||||
## Verification: explorer vs this doc
|
||||
|
||||
Verification run: config and live endpoints checked against the values above.
|
||||
|
||||
### Codebase (matches doc)
|
||||
|
||||
| Item | Source | Status |
|
||||
|------|--------|--------|
|
||||
| RPC URL (HTTPS/WS) | `explorer-monorepo/frontend/public/explorer-spa.js` | `RPC_FQDN` = `https://rpc-http-pub.d-bis.org`, `RPC_WS_FQDN` = `wss://rpc-ws-pub.d-bis.org`, `RPC_IP` = `http://192.168.11.221:8545` |
|
||||
| ChainId | same file | `CHAIN_ID = 138`, MetaMask `chainId: '0x8A'` |
|
||||
| WETH9 / WETH10 | same file | `0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2`, `0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9f` |
|
||||
| WETH9/WETH10 bridges | same file | `0x971cD9D156f193df8051E48043C476e53ECd4693`, `0xe0E93247376aa097dB308B92e6Ba36bA015535D0` |
|
||||
| Blockscout env | `scripts/run-blockscout-config-direct.sh` | `ETHEREUM_JSONRPC_HTTP_URL=http://192.168.11.221:8545`, `CHAIN_ID=138`, `ETHEREUM_JSONRPC_VARIANT=besu` |
|
||||
| API proxy | `explorer-monorepo/scripts/fix-nginx-serve-custom-frontend.sh` | `location /api/` → `proxy_pass http://127.0.0.1:4000` |
|
||||
|
||||
### Live endpoints
|
||||
|
||||
| Check | Command / URL | Result |
|
||||
|-------|----------------|--------|
|
||||
| Explorer API | `GET https://explorer.d-bis.org/api/v2/stats` | 200; `total_blocks`, `total_transactions`, `gas_prices` present |
|
||||
| RPC chainId | `POST https://rpc-http-pub.d-bis.org` `eth_chainId` | `"result":"0x8a"` (138) |
|
||||
| EIP-1559 | `POST https://rpc-http-pub.d-bis.org` `eth_getBlockByNumber("latest", false)` | `baseFeePerGas` present in block (e.g. `"0x7"`) |
|
||||
|
||||
**Conclusion:** Explorer config and live behaviour match this doc. Use the “Ready-to-send reply” section to respond to the technical review.
|
||||
42
docs/04-configuration/EXPLORER_TOKENS_GRU_POLICY.md
Normal file
42
docs/04-configuration/EXPLORER_TOKENS_GRU_POLICY.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# Explorer tokens and GRU policy
|
||||
|
||||
**Purpose:** All compliant (c*) tokens listed on [https://explorer.d-bis.org/tokens](https://explorer.d-bis.org/tokens) must be part of the GRU (Global Reserve Unit) — i.e. registered in `UniversalAssetRegistry` as `AssetType.GRU`.
|
||||
|
||||
## Policy
|
||||
|
||||
1. **Token lists**
|
||||
The canonical Chain 138 token list (`token-lists/lists/dbis-138.tokenlist.json`) and the explorer/MetaMask list (`explorer-monorepo/backend/config/metamask/DUAL_CHAIN_TOKEN_LIST.tokenlist.json`) include only c* tokens that are **registered as GRU** on Chain 138.
|
||||
|
||||
2. **When adding a new c* token**
|
||||
- Deploy the token (or confirm address).
|
||||
- Register it as GRU: set the token address in `smom-dbis-138/.env` (e.g. `CEURT_ADDRESS_138`, `CGBPC_ADDRESS_138`; see `ENV_EXAMPLE_CONTENT.md`), then run:
|
||||
```bash
|
||||
./scripts/deployment/set-dotenv-c-tokens-and-register-gru.sh
|
||||
```
|
||||
- Add the token to the token lists (dbis-138 and DUAL_CHAIN for Chain 138) **after** it is registered as GRU.
|
||||
|
||||
3. **All c* registered as GRU**
|
||||
The script `set-dotenv-c-tokens-and-register-gru.sh` sets and registers the following c* (addresses from DeployCompliantFiatTokens / ENV_EXAMPLE_CONTENT):
|
||||
- **cUSDT** — `0x93E66202A11B1772E55407B32B44e5Cd8eda7f22`
|
||||
- **cUSDC** — `0xf22258f57794CC8E06237084b353Ab30fFfa640b`
|
||||
- **cEURC** — `0x8085961F9cF02b4d800A3c6d386D31da4B34266a`
|
||||
- **cEURT** — `0xdf4b71c61E5912712C1Bdd451416B9aC26949d72`
|
||||
- **cGBPC** — `0x003960f16D9d34F2e98d62723B6721Fb92074aD2`
|
||||
- **cGBPT** — `0x350f54e4D23795f86A9c03988c7135357CCaD97c`
|
||||
- **cAUDC** — `0xD51482e567c03899eecE3CAe8a058161FD56069D`
|
||||
- **cJPYC** — `0xEe269e1226a334182aace90056EE4ee5Cc8A6770`
|
||||
- **cCHFC** — `0x873990849DDa5117d7C644f0aF24370797C03885`
|
||||
- **cCADC** — `0x54dBd40cF05e15906A2C21f600937e96787f5679`
|
||||
- **cXAUC** — `0x290E52a8819A4fbD0714E517225429aA2B70EC6b`
|
||||
- **cXAUT** — `0x94e408E26c6FD8F4ee00b54dF19082FDA07dC96E`
|
||||
Token lists (dbis-138, DUAL_CHAIN for 138) include at least cUSDT, cUSDC, cEURC; add others to lists after they are deployed and verified on explorer.
|
||||
|
||||
4. **Explorer /tokens page**
|
||||
The explorer loads tokens from the Blockscout API (`/v2/tokens`). Curated lists (e.g. for MetaMask or display) must only include c* that are GRU-registered. When adding new c* to any list that can surface on the explorer, register them as GRU first (see step 2).
|
||||
|
||||
## References
|
||||
|
||||
- [DEPLOYMENT_ORDER_OF_OPERATIONS](../03-deployment/DEPLOYMENT_ORDER_OF_OPERATIONS.md) § Phase 2.4 (Register c* as GRU)
|
||||
- [set-dotenv-c-tokens-and-register-gru.sh](../../scripts/deployment/set-dotenv-c-tokens-and-register-gru.sh)
|
||||
- [RegisterGRUCompliantTokens.s.sol](../../smom-dbis-138/script/deploy/RegisterGRUCompliantTokens.s.sol)
|
||||
- [C_TO_CW_MAPPER_MAPPING.md](C_TO_CW_MAPPER_MAPPING.md) — c* to cW* mapping for mapper on other chains
|
||||
@@ -8,6 +8,8 @@
|
||||
|
||||
**Last updated:** 2026-02-06
|
||||
|
||||
**Reference screenshots:** For expected explorer UI (home, blocks, transactions), see [../images/README.md](../images/README.md) and [EXPLORER_METAMASK_TECHNICAL_RESPONSE.md](EXPLORER_METAMASK_TECHNICAL_RESPONSE.md#3-explorer-backend-stack).
|
||||
|
||||
---
|
||||
|
||||
## "Your connection isn't private" / net::ERR_CERT_AUTHORITY_INVALID
|
||||
@@ -116,6 +118,22 @@ When on your LAN, `explorer.d-bis.org` resolves to `76.53.10.36`. If that’s yo
|
||||
- **Blocks not updating:** Check Blockscout logs:
|
||||
`ssh root@192.168.11.12 "pct exec 5000 -- docker logs blockscout --tail 50"`
|
||||
|
||||
### "Invalid address" when clicking From/To in transaction list
|
||||
|
||||
**Symptom:** Clicking the **From** or **To** cell in the transactions table (especially when **To** shows "—" for contract-creation txs) shows an "Invalid address" toast or error.
|
||||
|
||||
**Cause:** Those cells were clickable even when the value was empty or "N/A", so the app tried to open an address detail for an invalid value.
|
||||
|
||||
**Fix (applied in explorer SPA):** From/To cells are now only clickable when the value is a valid `0x` address. Clicking "—" or "N/A" no longer triggers the address detail; the row still opens the transaction detail when you click elsewhere on the row.
|
||||
|
||||
### Contract verification fails (502 / Invalid JSON)
|
||||
|
||||
When running `run-contract-verification-with-proxy.sh` or Forge verify, you may see "Blockscout returned HTML" or 502. This usually means Blockscout (VMID 5000) is down or the DB needs migrations.
|
||||
|
||||
- **Fix Blockscout:** [03-deployment/BLOCKSCOUT_FIX_RUNBOOK.md](../03-deployment/BLOCKSCOUT_FIX_RUNBOOK.md) — SSL/migrations, thin pool, start stack.
|
||||
- **Verify from UI:** When https://explorer.d-bis.org is up, use **Address → Contract → Verify & Publish** (no proxy needed). See [08-monitoring/BLOCKSCOUT_VERIFICATION_GUIDE.md](../08-monitoring/BLOCKSCOUT_VERIFICATION_GUIDE.md).
|
||||
- **From LAN:** Run verification script from a host that can reach `http://192.168.11.140:4000` so the proxy can forward to Blockscout.
|
||||
|
||||
---
|
||||
|
||||
## Verify Explorer
|
||||
|
||||
146
docs/04-configuration/FULL_PARITY_TOKEN_COVERAGE_RUNBOOK.md
Normal file
146
docs/04-configuration/FULL_PARITY_TOKEN_COVERAGE_RUNBOOK.md
Normal file
@@ -0,0 +1,146 @@
|
||||
# Full Parity Token Coverage — Logos, Pricing, Token Lists, All Networks, All Entry Points
|
||||
|
||||
**Last Updated:** 2026-02-28
|
||||
**Purpose:** Achieve complete coverage for token logos, pricing, and token lists across all networks and all aggregator/wallet entry points.
|
||||
|
||||
---
|
||||
|
||||
## 1. Coverage Matrix
|
||||
|
||||
| Dimension | Target |
|
||||
|-----------|--------|
|
||||
| **Networks** | 138, 1, 651940, 56, 137, 100, 10, 42161, 8453, 43114, 25, 42220, 1111 |
|
||||
| **Token lists** | Uniswap format with logoURI; per-chain and unified |
|
||||
| **Logos** | 512×512 PNG for CoinGecko/CMC; logoURI for all tokens |
|
||||
| **Pricing** | CoinGecko, CMC, on-chain oracle; report API |
|
||||
| **Entry points** | MetaMask, Trust Wallet, Chainlist, CoinGecko, CMC, 1inch, Paraswap, Chain 138 Snap |
|
||||
|
||||
---
|
||||
|
||||
## 2. Entry Points and Requirements
|
||||
|
||||
| Entry Point | Token List | Logos | Pricing | Notes |
|
||||
|-------------|------------|-------|---------|-------|
|
||||
| **MetaMask** | CoinGecko (built-in) or custom URL | logoURI per token | CoinGecko API | Chain 138 not in built-in; use Snap token list |
|
||||
| **Trust Wallet** | Trust Wallet registry | Trust Wallet assets | CoinGecko/CMC | PR to trustwallet/wallet-core |
|
||||
| **Chainlist** | eip155-138.json | Chain icon | — | [04-configuration/pr-ready/](../pr-ready/) |
|
||||
| **CoinGecko** | Submit chain + tokens | 512×512 PNG | CoinGecko API | Primary for MetaMask |
|
||||
| **CoinMarketCap** | Submit chain + tokens | 512×512 PNG | CMC API | Fallback for some wallets |
|
||||
| **Chain 138 Snap** | token-aggregation API | logoURI from API | Report API | `GET /api/v1/report/token-list` |
|
||||
| **1inch / Paraswap** | Token list URL | logoURI | Their APIs | Add token list URL when supported |
|
||||
| **Explorer** | Blockscout / custom | — | — | Token verification |
|
||||
|
||||
---
|
||||
|
||||
## 3. Single Source of Truth
|
||||
|
||||
| Asset | Location | Used By |
|
||||
|-------|----------|---------|
|
||||
| **Canonical tokens** | `smom-dbis-138/services/token-aggregation/src/config/canonical-tokens.ts` | Report API, token-list, coingecko, cmc |
|
||||
| **Token mapping (cross-chain)** | `config/token-mapping-multichain.json` | Bridge tooling, relay |
|
||||
| **Networks (EIP-3085)** | `smom-dbis-138/services/token-aggregation/src/config/networks.ts` | Snap, wallet_addEthereumChain |
|
||||
| **Chain configs** | `smom-dbis-138/services/token-aggregation/src/config/chains.ts` | Indexer, report API |
|
||||
| **Logo URLs** | `canonical-tokens.ts` (getLogoUriForSpec), Trust Wallet assets | Token list, CoinGecko |
|
||||
| **512×512 logos** | `docs/04-configuration/coingecko/logos/` (prepare-token-logos-512x512.sh) | CoinGecko/CMC submission |
|
||||
|
||||
---
|
||||
|
||||
## 4. Per-Network Token List Coverage
|
||||
|
||||
| Chain ID | Network | Tokens in canonical-tokens | Report API | Token list URL |
|
||||
|----------|---------|----------------------------|-----------|----------------|
|
||||
| 138 | Chain 138 | ✅ Full | ✅ | `?chainId=138` |
|
||||
| 651940 | ALL Mainnet | ✅ cUSDC, cUSDT, WETH | ✅ | `?chainId=651940` |
|
||||
| 1 | Ethereum | ✅ (L2_CHAIN_IDS) | ✅ | `?chainId=1` |
|
||||
| 56 | BSC | ✅ | ✅ | `?chainId=56` |
|
||||
| 137 | Polygon | ✅ | ✅ | `?chainId=137` |
|
||||
| 100 | Gnosis | ✅ | ✅ | `?chainId=100` |
|
||||
| 10 | Optimism | ✅ | ✅ | `?chainId=10` |
|
||||
| 42161 | Arbitrum | Env/fallback | Add to chains.ts | `?chainId=42161` |
|
||||
| 8453 | Base | Env/fallback | Add to chains.ts | `?chainId=8453` |
|
||||
| 43114 | Avalanche | Env/fallback | Add to chains.ts | `?chainId=43114` |
|
||||
| 25 | Cronos | ✅ USDW, etc. | Add to chains.ts | `?chainId=25` |
|
||||
| 42220 | Celo | Env | Add to chains.ts | `?chainId=42220` |
|
||||
| 1111 | Wemix | Env | Add to chains.ts | `?chainId=1111` |
|
||||
|
||||
---
|
||||
|
||||
## 5. Implementation Checklist
|
||||
|
||||
### 5.1 Token-Aggregation (All Networks)
|
||||
|
||||
- [ ] Add chains 42161, 8453, 43114, 25, 42220, 1111 to `chains.ts`
|
||||
- [ ] Add WETH9/WETH10 + cUSDT/cUSDC addresses per chain from `token-mapping-multichain.json`
|
||||
- [ ] Add all networks to `networks.ts` with iconUrls (Trust Wallet fallback)
|
||||
- [ ] Ensure `getSupportedChainIds()` returns all 13 chains
|
||||
- [ ] Deploy token-aggregation and proxy `/api/v1/*` before Blockscout
|
||||
|
||||
### 5.2 Logos
|
||||
|
||||
- [ ] Run `prepare-token-logos-512x512.sh` (requires ImageMagick)
|
||||
- [ ] Run `upload-token-logos-to-ipfs.sh` — see [IPFS_TOKEN_LOGOS_RUNBOOK](IPFS_TOKEN_LOGOS_RUNBOOK.md)
|
||||
- [ ] Verify all 23+ tokens have 512×512 PNG in `docs/04-configuration/coingecko/logos/`
|
||||
- [ ] Ensure `getLogoUriForSpec()` returns valid Trust Wallet URLs for all tokens
|
||||
- [ ] Add chain logos (138, 651940) for Chainlist/CoinGecko
|
||||
|
||||
### 5.3 Token Lists (Unified)
|
||||
|
||||
- [ ] Export unified token list: `GET /api/v1/report/token-list` (no chainId = all chains)
|
||||
- [ ] Publish token list URL for 1inch/Paraswap: `https://explorer.d-bis.org/api/v1/report/token-list`
|
||||
- [ ] Sync DUAL_CHAIN_TOKEN_LIST, metamask provider tokens.js with canonical-tokens
|
||||
- [ ] Add Chainlist eip155-138.json to pr-ready (done)
|
||||
|
||||
### 5.4 Pricing
|
||||
|
||||
- [ ] Submit Chain 138 and 651940 to CoinGecko (chain + tokens)
|
||||
- [ ] Submit to CoinMarketCap
|
||||
- [ ] Consensys outreach for MetaMask native support
|
||||
- [ ] Document on-chain oracle addresses per chain for dApp use
|
||||
|
||||
### 5.5 Entry Point Submissions
|
||||
|
||||
| Entry Point | Action | Doc |
|
||||
|-------------|--------|-----|
|
||||
| CoinGecko | Submit chain + tokens via form | [CMC_COINGECKO_SUBMISSION_RUNBOOK](coingecko/CMC_COINGECKO_SUBMISSION_RUNBOOK.md) |
|
||||
| CMC | Submit via listing form | Same |
|
||||
| Trust Wallet | PR to wallet-core | [ADD_CHAIN138_TO_TRUST_WALLET](ADD_CHAIN138_TO_TRUST_WALLET.md) |
|
||||
| Chainlist | Submit eip155-138.json | [pr-ready/README](../pr-ready/README.md) |
|
||||
| 1inch | Token list URL (when chain supported) | — |
|
||||
| Paraswap | Token list URL (when chain supported) | — |
|
||||
|
||||
---
|
||||
|
||||
## 6. Commands
|
||||
|
||||
```bash
|
||||
# Prepare logos (requires ImageMagick)
|
||||
./docs/04-configuration/coingecko/scripts/prepare-token-logos-512x512.sh
|
||||
|
||||
# Upload logos to IPFS (requires ipfs daemon or PINATA_JWT)
|
||||
./scripts/upload-token-logos-to-ipfs.sh
|
||||
|
||||
# Export report data for submission
|
||||
API_BASE="https://explorer.d-bis.org"
|
||||
for chain in 138 651940 1 56 137 100 10 42161 8453 43114 25 42220 1111; do
|
||||
curl -s "${API_BASE}/api/v1/report/coingecko?chainId=$chain" -o "report-coingecko-${chain}.json"
|
||||
curl -s "${API_BASE}/api/v1/report/cmc?chainId=$chain" -o "report-cmc-${chain}.json"
|
||||
done
|
||||
|
||||
# Verify token list
|
||||
curl -s "${API_BASE}/api/v1/report/token-list" | jq '.tokens | length'
|
||||
curl -s "${API_BASE}/api/v1/report/token-list?chainId=138" | jq '.tokens[] | {symbol, logoURI}'
|
||||
|
||||
# Verify Snap API
|
||||
./metamask-integration/chain138-snap/scripts/verify-snap-api-and-icons.sh "$API_BASE"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. References
|
||||
|
||||
- [PUBLICATION_LOCATIONS_MASTER](PUBLICATION_LOCATIONS_MASTER.md) — **All locations to publish token lists, liquidity pools, chain metadata, pricing**
|
||||
- [PRICE_FEED_CHAIN138_METAMASK_AND_WALLETS](PRICE_FEED_CHAIN138_METAMASK_AND_WALLETS.md)
|
||||
- [TOKEN_AGGREGATION_REPORT_API_RUNBOOK](TOKEN_AGGREGATION_REPORT_API_RUNBOOK.md)
|
||||
- [CMC_COINGECKO_SUBMISSION_RUNBOOK](coingecko/CMC_COINGECKO_SUBMISSION_RUNBOOK.md)
|
||||
- [IPFS_TOKEN_LOGOS_RUNBOOK](IPFS_TOKEN_LOGOS_RUNBOOK.md) — IPFS hosting for all logos (explorers, token lists)
|
||||
- [REPOSITORIES_AND_PRS_CHAIN138](../../00-meta/REPOSITORIES_AND_PRS_CHAIN138.md)
|
||||
@@ -0,0 +1,114 @@
|
||||
# GRU M00 Diamond Docs — Gaps and Inconsistencies Review
|
||||
|
||||
**Purpose:** Single review of all GRU M00 Diamond–related documentation for gaps, broken or ambiguous references, and internal inconsistencies. Covers the Facet Map, the Review (Gaps & Recommendations), index/README links, and related references.
|
||||
|
||||
**Scope:** [GRU_M00_DIAMOND_FACET_MAP.md](GRU_M00_DIAMOND_FACET_MAP.md), [GRU_M00_DIAMOND_REVIEW_GAPS_AND_RECOMMENDATIONS.md](GRU_M00_DIAMOND_REVIEW_GAPS_AND_RECOMMENDATIONS.md), [README](README.md), [MASTER_INDEX](../MASTER_INDEX.md), [SUBMODULE_RELATIONSHIP_MAP](../11-references/SUBMODULE_RELATIONSHIP_MAP.md), and linked targets.
|
||||
|
||||
**Status:** Post–review. All “Still open” items completed: institutional spec created, token model and Pattern A locked, GRU Diamond evolution note added, MASTER_INDEX Review row updated with TOKEN_SCOPE_GRU and VAULT_SYSTEM.
|
||||
|
||||
---
|
||||
|
||||
## 1. Missing Documents / Broken References
|
||||
|
||||
| Item | Where referenced | Issue | Resolution |
|
||||
|------|------------------|--------|------------|
|
||||
| **GRU_M00_DIAMOND_INSTITUTIONAL_SPEC.md** | Facet Map “Related documents”; Review §2.1, §5.1, §6 checklist, §7 | **Resolved:** File created with full §1–§8; token model A and Pattern A locked; GRC vs M00 evolution note added. |
|
||||
| **Institutional whitepaper §1–§8** | Facet Map: “or institutional whitepaper §1–§8” | **Resolved:** GRU_M00_DIAMOND_INSTITUTIONAL_SPEC.md is the canonical §1–§8 in repo. |
|
||||
|
||||
---
|
||||
|
||||
## 2. Link and Path Consistency
|
||||
|
||||
| Link | From | Target | Status |
|
||||
|------|------|--------|--------|
|
||||
| GRU_M00_DIAMOND_INSTITUTIONAL_SPEC.md | Facet Map, Review | Same directory (04-configuration) | Target missing; path correct. |
|
||||
| GRU_M00_DIAMOND_REVIEW_GAPS_AND_RECOMMENDATIONS.md | Facet Map | Same directory | OK. |
|
||||
| gru-docs/contracts/README.md | Facet Map, Review | ../../gru-docs/contracts/README.md | OK (submodule at repo root). |
|
||||
| SUBMODULE_RELATIONSHIP_MAP.md | Facet Map | ../11-references/SUBMODULE_RELATIONSHIP_MAP.md | OK. |
|
||||
| TOKEN_SCOPE_GRU.md | Facet Map, Review | ../../smom-dbis-138/docs/tokenization/TOKEN_SCOPE_GRU.md | OK. |
|
||||
| VAULT_SYSTEM_MASTER_TECHNICAL_PLAN.md | Facet Map, Review | ../VAULT_SYSTEM_MASTER_TECHNICAL_PLAN.md (docs root) | OK. |
|
||||
| SMART_CONTRACTS_ISO20022_FIN_METHODOLOGY.md | Review §7 | Same directory | OK. |
|
||||
| REQUIRED_FIXES_UPDATES_GAPS.md | Review §7 | ../REQUIRED_FIXES_UPDATES_GAPS.md | OK. |
|
||||
| MASTER_INDEX “Related” for Review | MASTER_INDEX | GRU_M00_DIAMOND_FACET_MAP.md, REQUIRED_FIXES_UPDATES_GAPS.md | Paths are doc-relative (no leading docs/); correct from docs/MASTER_INDEX.md. |
|
||||
|
||||
**Recommendation:** Add a one-line “Document status” at the top of the Facet Map: “Institutional spec: see GRU_M00_DIAMOND_INSTITUTIONAL_SPEC.md (when present) or external whitepaper.” So the missing file is clearly optional.
|
||||
|
||||
---
|
||||
|
||||
## 3. Terminology and Naming Consistency
|
||||
|
||||
| Topic | Facet Map | Review | Inconsistency / resolution |
|
||||
|-------|-----------|--------|----------------------------|
|
||||
| **Ownership vs Governance** | “OwnershipFacet (or use GovernanceFacet)” | “GovernanceFacet” in checklist | Intentional: both names valid; M00 may use one. No change. |
|
||||
| **Gate vs GateFacet** | Diagram: “ComplianceGate”; table: “ComplianceGateFacet (stub)” | “ComplianceGate” / “ComplianceGateFacet” | Logical gate vs implementing facet. Consistent. |
|
||||
| **Minimum ship list – gates** | §2.1 lists ComplianceGateFacet, AccountingGateFacet only (no Messaging/Reserve as stubs) | §2.6 and §2.7 list all four gates; §2.7 minimum list names only Compliance + Accounting stubs | Facet Map diagram shows 4 gates; minimum list names 2 gate stubs. Align by either (1) adding “MessagingGateFacet (stub), ReserveGateFacet (stub)” to Facet Map §2.1 minimum list, or (2) adding a sentence in Facet Map: “Minimum ship: Compliance and Accounting gate stubs; Messaging and Reserve can be added later.” |
|
||||
| **TokenFactoryFacet vs MarketFactory + AssetRegistry** | “TokenFactoryFacet” in minimum list with “(or consolidated MarketFactoryFacet + AssetRegistryFacet)” | “TokenFactoryFacet (or unify AssetRegistry + MarketFactory)” | Same intent. OK. |
|
||||
| **a/d vs ac/vdc/sdc** | §5 uses a\<ISO>, d\<ISO>; §5.5 now maps a↔ac, d↔vdc/sdc | §4.1 recommends adding this mapping | Fixed in Facet Map §5.5. |
|
||||
|
||||
---
|
||||
|
||||
## 4. Cross-Doc Content Gaps
|
||||
|
||||
| Gap | Description | Suggested fix |
|
||||
|-----|-------------|----------------|
|
||||
| **Token model not locked** | Facet Map said “[ A \| B \| C ]”; no doc locked a choice. | **Fixed:** Institutional spec §8 locks **Token model A**; Facet Map “Token model” line updated to “A (locked)” with link to spec §8. |
|
||||
| **Pattern A vs B** | Review recommended documenting “Target: Pattern A.” | **Fixed:** Institutional spec §6 locks **Target: Pattern A**; Facet Map “Target pattern” line added with link to spec §6. |
|
||||
| **GRC-2535 vs M00 relationship** | Two Diamond designs; migration path undefined. | **Fixed:** Institutional spec now has “GRU Diamond evolution (GRC-2535 vs M00)” at top: GRC = current, M00 = extension/replacement; decision = migrate vs new deploy. |
|
||||
| **Four gates vs two stubs** | See §3 above. | **Fixed:** Facet Map §2.2 now states that the minimum ship list includes Compliance and Accounting gate stubs and that Messaging/Reserve may follow in a later phase. |
|
||||
|
||||
---
|
||||
|
||||
## 5. Index and README Consistency
|
||||
|
||||
| Location | Content | Issue |
|
||||
|----------|---------|--------|
|
||||
| **04-configuration/README.md** | Lists Facet Map and Review under “Smart contracts & ISO-20022.” | No issue. Order: Facet Map then Review. |
|
||||
| **MASTER_INDEX.md** | “GRU Diamond / Smart contracts” subsection with Facet Map and Review rows. | **Fixed:** Review row “Related Documents” now includes TOKEN_SCOPE_GRU and VAULT_SYSTEM_MASTER_TECHNICAL_PLAN; institutional spec row added. |
|
||||
| **SUBMODULE_RELATIONSHIP_MAP** | gru-docs row notes same repo as GRU-Official-Docs-Monetary-Policies and standalone path. | Consistent with Facet Map and Review. |
|
||||
|
||||
---
|
||||
|
||||
## 6. Internal Consistency Within Each Doc
|
||||
|
||||
### 6.1 Facet Map
|
||||
|
||||
- Section numbering 1–5 and 5.1–5.5 is consistent.
|
||||
- Governance levels table has 6 rows (0–5); header matches.
|
||||
- Diagram node IDs (M00, DiamondCut, etc.) match table names; “GovLevel” in diagram = “GovernanceLevelFacet” in table. OK.
|
||||
- **Fixed:** §5.5 now documents a↔ac, d↔vdc/sdc per Review recommendation.
|
||||
|
||||
### 6.2 Review (Gaps and Recommendations)
|
||||
|
||||
- Section numbering 1–7 is consistent.
|
||||
- Checklist in §6 has 12 items; “Institutional spec doc” and “Token model A/B/C locked” appear; both depend on creating/locking in other docs. OK.
|
||||
- References in §7 to “(To be added)” for institutional spec are consistent with §2.1 and §5.1.
|
||||
- “smom-dbis-138” in References is a directory path; link to TOKEN_SCOPE_GRU is the specific doc. No conflict.
|
||||
|
||||
---
|
||||
|
||||
## 7. Summary of Fixes Applied in This Review
|
||||
|
||||
1. **Facet Map:** Added §5.5 “Mapping to deployed token names (a/d vs ac/vdc/sdc)” and a link to TOKEN_SCOPE_GRU so the recommended a↔ac, d↔vdc/sdc alignment is documented in the Facet Map.
|
||||
|
||||
---
|
||||
|
||||
## 8. Recommended Follow-Up — Completed
|
||||
|
||||
1. **Done:** Created **GRU_M00_DIAMOND_INSTITUTIONAL_SPEC.md** with full §1–§8; linked from Facet Map and Review.
|
||||
2. **Done:** Locked **token model A** and **Pattern A** in institutional spec (§8 and §6); updated Facet Map “Token model” and “Target pattern” lines.
|
||||
3. **Done earlier:** Facet Map §2.2 already clarifies minimum ship list (Compliance + Accounting gate stubs; Messaging/Reserve may follow).
|
||||
4. **Done:** Added **“GRU Diamond evolution (GRC-2535 vs M00)”** at top of institutional spec (migrate vs new deploy).
|
||||
5. **Done:** Added TOKEN_SCOPE_GRU and VAULT_SYSTEM_MASTER_TECHNICAL_PLAN to MASTER_INDEX “Related” for the Review row.
|
||||
|
||||
---
|
||||
|
||||
## 9. Related Documents
|
||||
|
||||
- [GRU_M00_DIAMOND_INSTITUTIONAL_SPEC.md](GRU_M00_DIAMOND_INSTITUTIONAL_SPEC.md) — §1–§8 institutional spec (token model A, Pattern A, GRC vs M00 evolution).
|
||||
- [GRU_M00_DIAMOND_FACET_MAP.md](GRU_M00_DIAMOND_FACET_MAP.md)
|
||||
- [GRU_M00_DIAMOND_REVIEW_GAPS_AND_RECOMMENDATIONS.md](GRU_M00_DIAMOND_REVIEW_GAPS_AND_RECOMMENDATIONS.md)
|
||||
- [README.md](README.md) (04-configuration)
|
||||
- [MASTER_INDEX.md](../MASTER_INDEX.md)
|
||||
- [SUBMODULE_RELATIONSHIP_MAP.md](../11-references/SUBMODULE_RELATIONSHIP_MAP.md)
|
||||
- [TOKEN_SCOPE_GRU.md](../../smom-dbis-138/docs/tokenization/TOKEN_SCOPE_GRU.md)
|
||||
- [VAULT_SYSTEM_MASTER_TECHNICAL_PLAN.md](../VAULT_SYSTEM_MASTER_TECHNICAL_PLAN.md)
|
||||
202
docs/04-configuration/GRU_M00_DIAMOND_FACET_MAP.md
Normal file
202
docs/04-configuration/GRU_M00_DIAMOND_FACET_MAP.md
Normal file
@@ -0,0 +1,202 @@
|
||||
# GRU M00 Diamond — Facet Map and Module List (Whitepaper)
|
||||
|
||||
**Purpose:** Single-page reference for the GRU M00 Diamond (ERC-2535) Token Factory architecture. For Solidity engineers and whitepaper authors. All c/a/d token families are implemented as upgradeable facets; storage and governance placeholders support IPSAS, IFRS/US GAAP, ISO-20022, i18n, and future governance levels.
|
||||
|
||||
**Token model:** **A** (locked). Separate ERC-20 contracts deployed by GRU (Aave-like). See [institutional spec §8](GRU_M00_DIAMOND_INSTITUTIONAL_SPEC.md#8-one-key-design-decision-you-should-lock). **Target pattern:** **A** (one factory, many assets); Pattern B only for flagship USD/EUR if needed. See [institutional spec §6](GRU_M00_DIAMOND_INSTITUTIONAL_SPEC.md#6-what-upgradeable-facet-per-iso-means-practical).
|
||||
|
||||
---
|
||||
|
||||
## 1. Facet Map (Mermaid)
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
subgraph diamond [GRU M00 Diamond]
|
||||
M00[M00 Diamond]
|
||||
end
|
||||
|
||||
subgraph core [Core Facets]
|
||||
DiamondCut[DiamondCutFacet]
|
||||
DiamondLoupe[DiamondLoupeFacet]
|
||||
Ownership[OwnershipFacet]
|
||||
Pause[PauseFacet]
|
||||
end
|
||||
|
||||
subgraph tokenFactory [Token Factory Facets]
|
||||
AssetRegistry[AssetRegistryFacet]
|
||||
MarketFactory[MarketFactoryFacet]
|
||||
MintBurn[MintBurnFacet]
|
||||
InterestRate[InterestRateFacet]
|
||||
BridgeWrap[BridgeWrapFacet]
|
||||
DWIN[DWINFacet]
|
||||
end
|
||||
|
||||
subgraph standards [Standards and Compliance Facets]
|
||||
IPSAS[IPSASFacet]
|
||||
IFRS[IFRSUSGAAPFacet]
|
||||
ISO20022[ISO20022Facet]
|
||||
i18n[i18nFacet]
|
||||
GovLevel[GovernanceLevelFacet]
|
||||
end
|
||||
|
||||
subgraph gates [Policy Gates]
|
||||
PolicyRouter[PolicyRouterFacet]
|
||||
ComplianceGate[ComplianceGate]
|
||||
AccountingGate[AccountingGate]
|
||||
MessagingGate[MessagingGate]
|
||||
ReserveGate[ReserveGate]
|
||||
end
|
||||
|
||||
M00 --> DiamondCut
|
||||
M00 --> DiamondLoupe
|
||||
M00 --> Ownership
|
||||
M00 --> Pause
|
||||
M00 --> AssetRegistry
|
||||
M00 --> MarketFactory
|
||||
M00 --> MintBurn
|
||||
M00 --> InterestRate
|
||||
M00 --> BridgeWrap
|
||||
M00 --> DWIN
|
||||
M00 --> IPSAS
|
||||
M00 --> IFRS
|
||||
M00 --> ISO20022
|
||||
M00 --> i18n
|
||||
M00 --> GovLevel
|
||||
M00 --> PolicyRouter
|
||||
PolicyRouter --> ComplianceGate
|
||||
PolicyRouter --> AccountingGate
|
||||
PolicyRouter --> MessagingGate
|
||||
PolicyRouter --> ReserveGate
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. Exact Facet Names
|
||||
|
||||
### 2.1 Facets by family
|
||||
|
||||
| Facet name | Role | Notes |
|
||||
|------------|------|--------|
|
||||
| **Core** | | |
|
||||
| DiamondCutFacet | Upgrade mechanism | ERC-2535 diamondCut |
|
||||
| DiamondLoupeFacet | Introspection | facets, facetAddress, selectors |
|
||||
| OwnershipFacet | Admin / governance | Owner, timelock, upgrade approval (or use GovernanceFacet) |
|
||||
| PauseFacet | Risk controls | Global and per-selector pause (GuardianFacet alias) |
|
||||
| **Token Factory** | | |
|
||||
| AssetRegistryFacet | Asset definitions | ISO code, type, decimals; W positional semantics; assetId hash |
|
||||
| MarketFactoryFacet | Market creation | Emits c/a/d token contracts per ISO asset |
|
||||
| MintBurnFacet | Supply controls | Mint/burn rules, reserve gating, supply caps, emergency locks |
|
||||
| InterestRateFacet | Aave-style indices | Index math for a/d; rate model plug-ins; accrual triggers |
|
||||
| BridgeWrapFacet | W-before-ISO | Wrapped bridge; escrow proofs; bridge operators |
|
||||
| DWINFacet | W-after-T/C | D-WIN; denomination logic; optional windowing rules |
|
||||
| **Standards / Compliance** | | |
|
||||
| IPSASFacet | Public sector accounting | GRU ledger ↔ IPSAS reporting; fund accounting |
|
||||
| IFRSUSGAAPFacet | IFRS / US GAAP | Revenue recognition, lease/contract hooks, impairment/reserve reporting |
|
||||
| ISO20022Facet | Message builders | pacs/camt payloads; dictionary mapping; settlement correlation |
|
||||
| i18nFacet | Internationalization | Locale packs, translation keys, disclosure templates |
|
||||
| GovernanceLevelFacet | Policy levels | Reads policy bitmask; routes enforcement per level 0..N |
|
||||
| **Minimum ship list (stubs)** | | |
|
||||
| PolicyRouterFacet | Gate orchestration | Calls Compliance, Accounting, Messaging, Reserve gates |
|
||||
| ComplianceGateFacet | Stub | Allowlist/denylist, jurisdiction tags placeholders |
|
||||
| AccountingGateFacet | Stub | Journal entry and chart-of-accounts placeholders |
|
||||
| StandardsRegistryFacet | Module activation | Activate/deactivate modules; enforce required modules per governance level |
|
||||
|
||||
### 2.2 Gates (used by PolicyRouter)
|
||||
|
||||
| Gate | Purpose |
|
||||
|------|---------|
|
||||
| ComplianceGate | checkTransfer (KYC/AML, sanctions, jurisdiction) |
|
||||
| AccountingGate | postJournal (ledger entries, CoA) |
|
||||
| MessagingGate | logISO20022 (message logging, correlation IDs) |
|
||||
| ReserveGate | checkBacking (reserve proofs, attestations) |
|
||||
|
||||
Each gate is replaceable via facet upgrade. The **minimum ship list** (§2.1) explicitly includes ComplianceGateFacet and AccountingGateFacet stubs; MessagingGate and ReserveGate may be stubbed or implemented in a later phase.
|
||||
|
||||
---
|
||||
|
||||
## 3. Storage Namespaces (GRUStorage)
|
||||
|
||||
App storage is centralized in **GRUStorage** with namespaced domains so upgrades do not break state.
|
||||
|
||||
| Namespace / domain | Contents |
|
||||
|--------------------|----------|
|
||||
| Governance & roles | DAO / Council / Guardian roles; emergency pause authorities; upgrade admin; timelock address; policy controllers per module |
|
||||
| Token Factory Registry | assetId → token addresses (c, a, d); symbol → assetId; per-asset config (decimals, mint rules, chain domain, W positioning) |
|
||||
| Accounting / Ledger | Journal entries (debits/credits); chart of accounts; cost centers / funds / projects; per-asset reserve attestations; policy metadata hashes |
|
||||
| Compliance & Identity | KYC/AML allowlists; jurisdiction tags; sanctions flags; travel rule metadata pointers; audit proof roots |
|
||||
| ISO-20022 Message Vault | Message schemas registry; outbound/inbound message logs; canonicalization hashes; correlation IDs for settlement events |
|
||||
| i18n Registry | Locale packs (hash pointers); translation keys for UI/clients; multi-jurisdiction disclosure templates |
|
||||
| Expandable Standards Registry | standardId → moduleConfig: enabled, version, validator contracts, policy-level constraints, data namespace pointers |
|
||||
|
||||
---
|
||||
|
||||
## 4. Governance Levels (0–5)
|
||||
|
||||
GovernanceLevelFacet reads the policy bitmask; PolicyRouter calls the gates according to the active level. **Default at deployment:** level **0** (Free / devnet / sandbox); set via GovernanceLevelFacet after init. See [GRU_M00_DIAMOND_DEPLOYMENT_RUNBOOK.md](../runbooks/GRU_M00_DIAMOND_DEPLOYMENT_RUNBOOK.md) and institutional spec.
|
||||
|
||||
| Level | Name | KYC | Reserves | ISO-20022 | Accounting | Transfer restrictions | Timelock / attestors |
|
||||
|-------|------|-----|----------|-----------|-------------|----------------------|----------------------|
|
||||
| 0 | Free / devnet / sandbox | No | No | No | No | None | Minimal |
|
||||
| 1 | KYC optional + audit | Optional | No | No | Audit logs | None | Standard |
|
||||
| 2 | KYC required + proofs | Required | Reserve proofs | Logging | Journal optional | Per policy | Standard |
|
||||
| 3 | IPSAS/IFRS enforced | Required | Reserve proofs | Logging | Journal mandatory | Restricted sets | Extended |
|
||||
| 4 | Sovereign / regulated | Required | Attestations | Full | Full reporting | Restricted + allowlists | Multi-sig, attestors |
|
||||
| 5 | Maximum compliance | Required | Full attestations | Full | Full + disclosures | Strict allowlists | Long timelocks, external attestors |
|
||||
|
||||
---
|
||||
|
||||
## 5. Canonical Symbol Grammar
|
||||
|
||||
Enforced in **AssetRegistryFacet** with deterministic parsing.
|
||||
|
||||
### 5.1 Market artifacts per ISO-4217
|
||||
|
||||
| Prefix | Meaning | Example |
|
||||
|--------|---------|---------|
|
||||
| c\<ISO>\<T\|C\> | Base compliant eMoney | cUSDC, cEURCT |
|
||||
| a\<ISO>\<T\|C\> | Asset token / claim index | aUSDC, aEURCT |
|
||||
| d\<ISO>\<T\|C\> | Debt token / liability index | dUSDC, dEURCT |
|
||||
|
||||
\<T\|C\> = issuer/type suffix (e.g. T = Tether, C = Circle-style).
|
||||
|
||||
### 5.2 W rules
|
||||
|
||||
- **W before ISO (wrapped bridge):** `W` precedes the ISO code.
|
||||
Examples: `cWUSDT`, `aWUSDT`, `dWUSDT`.
|
||||
- **W after T/C (D-WIN):** `W` follows the T or C suffix.
|
||||
Examples: `cUSDTW`, `aUSDTW`, `dUSDTW`.
|
||||
|
||||
### 5.3 BNF-style summary
|
||||
|
||||
```
|
||||
symbol := (c|a|d) iso_suffix | (c|a|d) W iso_suffix | (c|a|d) iso_suffix W
|
||||
iso_suffix := <ISO4217 code><T|C> e.g. USDC, USDT, EURCT, EURCC
|
||||
```
|
||||
|
||||
### 5.4 Examples
|
||||
|
||||
| Symbol | Interpretation |
|
||||
|--------|----------------|
|
||||
| cUSDC | Compliant base eMoney, USD (Circle-style) |
|
||||
| aEURCT | Asset token, EUR (Tether) |
|
||||
| dWUSDT | Debt token, wrapped USDT (bridge) |
|
||||
| cUSDTW | Compliant base, USDT D-WIN (denomination/windowing) |
|
||||
|
||||
### 5.5 Mapping to deployed token names (a/d vs ac/vdc/sdc)
|
||||
|
||||
The canonical grammar uses **a** (asset) and **d** (debt). In the codebase and [TOKEN_SCOPE_GRU](../../smom-dbis-138/docs/tokenization/TOKEN_SCOPE_GRU.md), the same roles use Aave-style names: **a** ↔ **ac** (DepositToken, e.g. acUSDC, acUSDT), **d** ↔ **vdc** / **sdc** (DebtToken, e.g. vdcUSDC, sdcUSDC). The registry may store either form (aUSDC or acUSDC); both denote the same asset token type.
|
||||
|
||||
### 5.6 ISO-4217 Compliant Token Matrix (native / bridged)
|
||||
|
||||
The grammar above aligns with the [ISO4217 Compliant Token Matrix](ISO4217_COMPLIANT_TOKEN_MATRIX.md): native symbols 6-char (`c` + FinChain + ISO + Type), bridged 7-char (`c` + `W` + OriginFinChain + ISO + Type). **ChainID 138 only:** native symbols are v0 (no designator) — `cUSDC`, `cUSDT`; the X is left out. X is used only for origin reference (e.g. bridged `cWXUSDC` on other chains). Registry maps v0 → identity for reporting.
|
||||
|
||||
---
|
||||
|
||||
## Related documents
|
||||
|
||||
- **Full architecture spec:** [GRU_M00_DIAMOND_INSTITUTIONAL_SPEC.md](GRU_M00_DIAMOND_INSTITUTIONAL_SPEC.md) (§1–§8, token model and Pattern A locked).
|
||||
- **Detailed review (gaps, wire-ins, recommendations):** [GRU_M00_DIAMOND_REVIEW_GAPS_AND_RECOMMENDATIONS.md](GRU_M00_DIAMOND_REVIEW_GAPS_AND_RECOMMENDATIONS.md).
|
||||
- **Docs review (gaps and inconsistencies):** [GRU_M00_DIAMOND_DOCS_REVIEW_GAPS_AND_INCONSISTENCIES.md](GRU_M00_DIAMOND_DOCS_REVIEW_GAPS_AND_INCONSISTENCIES.md).
|
||||
- **Existing Diamond (GRC-2535):** [gru-docs/contracts/README.md](../../gru-docs/contracts/README.md). The GRU docs repo is also available as a standalone clone (e.g. **GRU-Official-Docs-Monetary-Policies**); in this repo it is the submodule `gru-docs/`. See [SUBMODULE_RELATIONSHIP_MAP.md](../11-references/SUBMODULE_RELATIONSHIP_MAP.md).
|
||||
- **Token scope (c/a/d, W):** [smom-dbis-138/docs/tokenization/TOKEN_SCOPE_GRU.md](../../smom-dbis-138/docs/tokenization/TOKEN_SCOPE_GRU.md).
|
||||
- **ISO-4217 compliant symbol matrix (native/bridged, v0/v1):** [ISO4217_COMPLIANT_TOKEN_MATRIX.md](ISO4217_COMPLIANT_TOKEN_MATRIX.md).
|
||||
- **Vault / M00 reference:** [VAULT_SYSTEM_MASTER_TECHNICAL_PLAN.md](../VAULT_SYSTEM_MASTER_TECHNICAL_PLAN.md).
|
||||
175
docs/04-configuration/GRU_M00_DIAMOND_INSTITUTIONAL_SPEC.md
Normal file
175
docs/04-configuration/GRU_M00_DIAMOND_INSTITUTIONAL_SPEC.md
Normal file
@@ -0,0 +1,175 @@
|
||||
# GRU M00 Diamond — Institutional Architecture Spec
|
||||
|
||||
**Purpose:** Buildable blueprint for a single “giant Token Factory” inside the GRU ERC-2535 Diamond. Each currency + a/d token family is implemented as an upgradeable facet set; the GRU Diamond contains governance + storage placeholders for IPSAS, IFRS/US GAAP, ISO-20022, i18n, and future governance levels. Hand-off for whitepaper/tech spec and Solidity engineers.
|
||||
|
||||
**Related:** [GRU_M00_DIAMOND_FACET_MAP.md](GRU_M00_DIAMOND_FACET_MAP.md) (single-page facet map, storage namespaces, governance levels, symbol grammar) | [GRU_M00_DIAMOND_REVIEW_GAPS_AND_RECOMMENDATIONS.md](GRU_M00_DIAMOND_REVIEW_GAPS_AND_RECOMMENDATIONS.md) (gaps and wire-ins).
|
||||
|
||||
---
|
||||
|
||||
## GRU Diamond evolution (GRC-2535 vs M00)
|
||||
|
||||
**GRC-2535** (in [gru-docs/contracts](../../gru-docs/contracts/README.md)) is the current GRU Diamond: GrcDiamond + GRCStorage + Monetary, Triangulation, Index, Bond, Audit, Governance, Access, Pause facets. **M00 Diamond** extends or replaces it with the Token Factory, GRUStorage (seven domains), PolicyRouter + gates, and standards placeholders. **Decision:** Either (1) **migrate** GRC → M00 (same contract, add/replace facets and extend storage with reserved GRUStorage namespaces) or (2) **deploy M00 as a new Diamond** and deprecate GRC for token/market flows. Document the chosen path in the deployment runbook.
|
||||
|
||||
**Existing registries:** Until M00 is deployed, **UniversalAssetRegistry** (smom-dbis-138) remains the source of truth for bridges and token lists. After M00 is live, migrate or mirror to GRUStorage.TokenFactoryRegistry and document the cutover.
|
||||
|
||||
---
|
||||
|
||||
## 1) Diamond Topology Overview
|
||||
|
||||
### Core Principle
|
||||
|
||||
* **GRU = M00 Diamond (ERC-2535)**
|
||||
* **All c-tokens + a-tokens + d-tokens** are minted/managed by **facets** attached to the GRU Diamond.
|
||||
* Storage is centralized in **shared app storage** to ensure upgrades don’t break state.
|
||||
* Governance is **layered and expandable**: policy modules are “plugged in” as facets without changing base state layout.
|
||||
|
||||
**Key idea:**
|
||||
|
||||
> “Tokens aren’t separate systems; they are *markets* inside the GRU Diamond, emitted as ERC-20 instances or ledgered as internal balance sheets, governed by standards modules.”
|
||||
|
||||
---
|
||||
|
||||
## 2) Storage Layout (Permanent / Upgrade-Safe)
|
||||
|
||||
### A) Diamond App Storage (GRUStorage)
|
||||
|
||||
Use **placeholder storage** for many future standards:
|
||||
|
||||
* a fixed storage struct (core)
|
||||
* a **namespaced storage registry** for standards modules
|
||||
* a **policy bitmask** and **module pointer map**
|
||||
|
||||
#### Core Storage Domains
|
||||
|
||||
1. **Governance & Roles** — DAO / Council / Guardian roles; emergency pause authorities; upgrade admin / timelock address; policy controllers (per module).
|
||||
2. **Token Factory Registry** — mapping of `assetId → token addresses` (c, a, d variants); mapping of symbol → assetId (canonical parsing); per-asset configuration (decimals, mint rules, chain domain, W positioning, etc.).
|
||||
3. **Accounting / Ledger** — Journal entries (debits/credits); chart of accounts; cost centers / funds / projects; per-asset reserve attestations; policy metadata hashes (auditable). Standards-neutral so IFRS/USGAAP/IPSAS can be added without refactoring.
|
||||
4. **Compliance & Identity** — KYC/AML allowlists; jurisdiction tags; sanctions flags; travel rule metadata pointers; audit proof roots.
|
||||
5. **ISO-20022 Message Vault** — Message schemas registry; outbound/inbound message logs; message “canonicalization” hashes; correlation IDs for settlement events.
|
||||
6. **Internationalization (i18n) Registry** — Locale packs (hash pointers); translation keys for UI/client consumption; multi-jurisdiction disclosure templates.
|
||||
7. **Expandable Standards Registry** — mapping `standardId => moduleConfig` (enabled flags, version, validator contracts, policy-level constraints, data namespace pointers). Enables “turning on” IPSAS or ISO-20022 without migrating storage.
|
||||
|
||||
---
|
||||
|
||||
## 3) Facet Families (Modular + Upgradeable)
|
||||
|
||||
### A) Core Diamond Facets (always present)
|
||||
|
||||
* **DiamondCutFacet** (upgrade)
|
||||
* **DiamondLoupeFacet** (introspection)
|
||||
* **Ownership/GovernanceFacet** (admin model, timelocks)
|
||||
* **Pause/GuardianFacet** (risk controls)
|
||||
|
||||
### B) Token Factory Facets
|
||||
|
||||
1. **AssetRegistryFacet** — create/modify asset definition (ISO code, type, decimals); enforce W positional semantics; generate assetId deterministic hash.
|
||||
2. **MarketFactoryFacet** — create a “market” for a given ISO asset; emit token contracts for **c** (compliant base), **a** (asset/claim), **d** (debt/liability).
|
||||
3. **MintBurnFacet** — mint/burn rules; reserve gating; supply caps; emergency locks.
|
||||
4. **InterestRateFacet (Aave-style)** — index math for a/d behavior; rate model plug-ins (stable/variable); accrual triggers.
|
||||
5. **BridgeWrapFacet** — **W before ISO** assets (wrapped bridge); escrow proofs; bridge operators / trust model.
|
||||
6. **DWINFacet** — **W after T/C** (D-WIN); denomination logic; optional “windowing” rules (maturity, buckets, liquidity windows).
|
||||
|
||||
### C) Standards / Compliance Facets (placeholders, expandable later)
|
||||
|
||||
* **IPSASFacet** — GRU ledger ↔ IPSAS reporting; fund accounting.
|
||||
* **IFRS/USGAAPFacet** — Revenue recognition; lease/contract classification hooks; impairment / reserve adequacy reporting.
|
||||
* **ISO20022Facet** — Message builders (pacs/camt); standard dictionary mapping per assetId; settlement event correlation.
|
||||
* **i18nFacet** — Multi-language disclosure strings by jurisdiction; “legal label packs” versioned and signed.
|
||||
* **GovernanceLevelFacet** — Policy levels 0..N; each level toggles KYC, transfer restrictions, message logging, accounting journal mandatory, oracle requirements, timelock durations, which standards must be enabled. Reads **policy bitmask** in storage and routes enforcement.
|
||||
|
||||
---
|
||||
|
||||
## 4) Governance Model (Expandable + Imposed Levels)
|
||||
|
||||
* **Level 0:** Free / devnet / sandbox rules.
|
||||
* **Level 1:** KYC optional + audit logs.
|
||||
* **Level 2:** KYC required + reserve proofs + ISO-20022 logging.
|
||||
* **Level 3:** IPSAS/IFRS reporting enforced + restricted transfer sets.
|
||||
* **Level 4+:** Sovereign/regulated regime enforcement + multi-sig + external attestors + longer timelocks.
|
||||
|
||||
**Implementation:** A **PolicyRouter** (facet) calls ComplianceGate.checkTransfer(...), AccountingGate.postJournal(...), MessagingGate.logISO20022(...), ReserveGate.checkBacking(...). Each gate is replaceable via facet upgrade.
|
||||
|
||||
---
|
||||
|
||||
## 5) How Currency Codes Become “Markets” Inside GRU
|
||||
|
||||
For each ISO-4217 code (USD, EUR, JPY, etc.):
|
||||
|
||||
* **c\<ISO>\<T|C>** (base compliant eMoney)
|
||||
* **a\<ISO>\<T|C>** (asset token / claim index)
|
||||
* **d\<ISO>\<T|C>** (debt token / liability index)
|
||||
|
||||
**W rules:** Wrapped bridge = `W` before ISO (e.g. aWUSDT, dWUSDT, cWUSDT). D-WIN = `W` after T/C (e.g. aUSDTW, dUSDTW, cUSDTW). Enforced in **AssetRegistryFacet** with deterministic parsing.
|
||||
|
||||
---
|
||||
|
||||
## 6) What “Upgradeable Facet per ISO” Means (Practical)
|
||||
|
||||
**Pattern A (recommended): One Factory, Many Assets (data-driven)** — One set of facets supports unlimited assets via config records. Safer: fewer upgrades, less surface area.
|
||||
|
||||
**Pattern B (if required): “Facet Packs” per asset family** — For major markets (USD/EUR), deploy specialized facets (special rate model, compliance regime, settlement rules). Storage remains standard.
|
||||
|
||||
**Target (locked):** **Pattern A** as default. **Pattern B** only for flagship USD/EUR asset families if required.
|
||||
|
||||
---
|
||||
|
||||
## 7) Minimum Placeholder Checklist (What GRU must include now)
|
||||
|
||||
1. **AppStorage skeleton** — module registry; policy bitmask; ledger/journal base structs; ISO-20022 log structs; i18n registry structs.
|
||||
2. **GovernanceFacet** — role-based access control; timelock hooks; upgrade approval workflow.
|
||||
3. **PolicyRouterFacet** — empty gates initially, but callable; emits events for auditability.
|
||||
4. **TokenFactoryFacet** — can register assets; can deploy token instances (or ledgered balances if internal accounting).
|
||||
5. **ComplianceGateFacet (stub)** — allowlist/denylist placeholder; jurisdiction tags placeholder.
|
||||
6. **AccountingGateFacet (stub)** — journal entry emission placeholder; chart of accounts placeholder.
|
||||
7. **StandardsRegistryFacet** — activate/deactivate modules; enforce “required modules for governance level X.”
|
||||
|
||||
---
|
||||
|
||||
## 8) One Key Design Decision You Should Lock
|
||||
|
||||
**Are tokens:**
|
||||
|
||||
* **A)** Separate ERC-20 contracts deployed by GRU (Aave-like)
|
||||
* **B)** Internal ledger balances inside GRU with ERC-20 views
|
||||
* **C)** Hybrid: ERC-20 external interface, authoritative balances in GRU ledger (tokens as thin proxies)
|
||||
|
||||
For DeFi compatibility, **A** is simplest. For sovereign accounting + ISO-20022 tight control, **B** is more “bank-core-like.”
|
||||
|
||||
**Locked decision:** **Token model A** (separate ERC-20 contracts deployed by GRU, Aave-like). For DeFi compatibility and simplest integration. B or C may be chosen later if sovereign/accounting requirements dictate.
|
||||
|
||||
---
|
||||
|
||||
## Deployment target chain and CREATE2
|
||||
|
||||
- **Primary chain:** Chain 138 (DeFi Oracle Meta Mainnet) first; then mainnet (1), 651940 (ALL Mainnet), or other EVM chains as needed.
|
||||
- **CREATE2:** Use CREATE2 when the same M00 Diamond address is required across chains; otherwise CREATE is acceptable for single-chain (e.g. 138-only) deployment.
|
||||
- **Default governance level at deployment:** **0** (Free / devnet / sandbox). Set via GovernanceLevelFacet after init. For production, set to 1 or 2 (or per policy) in a separate init step.
|
||||
- **Runbook:** [GRU_M00_DIAMOND_DEPLOYMENT_RUNBOOK.md](../runbooks/GRU_M00_DIAMOND_DEPLOYMENT_RUNBOOK.md).
|
||||
|
||||
---
|
||||
|
||||
## Appendix: PolicyRouter and gate event signatures
|
||||
|
||||
For auditability and indexers, PolicyRouter and gates SHOULD emit the following events (or equivalent). Implement when building the spine.
|
||||
|
||||
| Event | Signature (semantic) | Emitted by |
|
||||
|-------|----------------------|------------|
|
||||
| **TransferChecked** | `TransferChecked(address from, address to, address token, uint256 amount, bool allowed, bytes32 reason)` | PolicyRouter after ComplianceGate.checkTransfer |
|
||||
| **JournalPosted** | `JournalPosted(bytes32 journalId, bytes32 coaRef, uint256 amount, address token)` | PolicyRouter after AccountingGate.postJournal |
|
||||
| **MessageLogged** | `MessageLogged(bytes32 correlationId, bytes32 payloadHash, string msgType)` | PolicyRouter after MessagingGate.logISO20022 |
|
||||
| **BackingChecked** | `BackingChecked(bytes32 assetId, uint256 amount, bool sufficient, bytes32 attestationHash)` | PolicyRouter after ReserveGate.checkBacking |
|
||||
| **GovernanceLevelSet** | `GovernanceLevelSet(uint8 previousLevel, uint8 newLevel)` | GovernanceLevelFacet when level is updated |
|
||||
|
||||
Use indexed parameters where appropriate (e.g. `indexed address token`, `indexed bytes32 correlationId`) for efficient filtering. Full ABI and parameter types to be defined in the implementation.
|
||||
|
||||
---
|
||||
|
||||
## Related documents
|
||||
|
||||
- [GRU_M00_DIAMOND_FACET_MAP.md](GRU_M00_DIAMOND_FACET_MAP.md) — Facet map, storage namespaces, governance levels 0–5, canonical symbol grammar.
|
||||
- [GRU_M00_DIAMOND_REVIEW_GAPS_AND_RECOMMENDATIONS.md](GRU_M00_DIAMOND_REVIEW_GAPS_AND_RECOMMENDATIONS.md) — Missing components, wire-ins, recommendations.
|
||||
- [GRU_M00_DIAMOND_DOCS_REVIEW_GAPS_AND_INCONSISTENCIES.md](GRU_M00_DIAMOND_DOCS_REVIEW_GAPS_AND_INCONSISTENCIES.md) — Docs review (gaps and inconsistencies).
|
||||
- [gru-docs/contracts/README.md](../../gru-docs/contracts/README.md) — GRC-2535 Diamond.
|
||||
- [TOKEN_SCOPE_GRU.md](../../smom-dbis-138/docs/tokenization/TOKEN_SCOPE_GRU.md) — c/a/d and W token lists.
|
||||
- [VAULT_SYSTEM_MASTER_TECHNICAL_PLAN.md](../VAULT_SYSTEM_MASTER_TECHNICAL_PLAN.md) — Vault and M00 reference.
|
||||
- [GRU_M00_DIAMOND_DEPLOYMENT_RUNBOOK.md](../runbooks/GRU_M00_DIAMOND_DEPLOYMENT_RUNBOOK.md) — Deploy or migrate M00; target chain, CREATE2, default governance level, testing.
|
||||
@@ -0,0 +1,263 @@
|
||||
# GRU M00 Diamond — Detailed Review: Gaps, Wire-Ins, and Recommendations
|
||||
|
||||
**Purpose:** Structured review of the GRU M00 Diamond (ERC-2535) Token Factory architecture against the current codebase and docs. Covers missing components, functional wire-ins to complete, naming/alignment gaps, and actionable recommendations.
|
||||
|
||||
**References:** [GRU_M00_DIAMOND_FACET_MAP.md](GRU_M00_DIAMOND_FACET_MAP.md), [gru-docs/contracts/README.md](../../gru-docs/contracts/README.md) (GRU docs; same repo as **GRU-Official-Docs-Monetary-Policies** when cloned standalone), [smom-dbis-138](../smom-dbis-138), [VAULT_SYSTEM_MASTER_TECHNICAL_PLAN.md](../VAULT_SYSTEM_MASTER_TECHNICAL_PLAN.md).
|
||||
|
||||
---
|
||||
|
||||
## 1. Executive Summary
|
||||
|
||||
| Area | Status | Summary |
|
||||
|------|--------|---------|
|
||||
| **Spec vs implementation** | Gap | Facet Map describes M00 Diamond + GRUStorage + PolicyRouter + gates; repo has GRC-2535 Diamond (different facets) and standalone UniversalAssetRegistry/TokenFactory/VaultFactory — no single M00 Diamond yet. |
|
||||
| **Missing components** | Multiple | Institutional spec doc, GRUStorage layout, PolicyRouter + four gates (on-chain), Token Factory facets (AssetRegistry, MarketFactory, MintBurn, InterestRate, BridgeWrap, DWIN), Standards facets (IPSAS, IFRS, ISO20022, i18n, GovernanceLevel), minimum ship stubs. |
|
||||
| **Wire-ins** | Incomplete | No Diamond → Token Factory wiring; no PolicyRouter → gate calls; no governance level bitmask → enforcement; off-chain ComplianceGate (dbis_core) not mirrored on-chain. |
|
||||
| **Naming alignment** | Gap | Spec grammar uses **a**\<ISO>, **d**\<ISO>; deployed/specified tokens use **ac***, **vdc***/sdc* — need explicit mapping or doc alignment. |
|
||||
|
||||
---
|
||||
|
||||
## 2. Missing Components
|
||||
|
||||
### 2.1 Documentation
|
||||
|
||||
| Item | Description | Recommendation |
|
||||
|------|-------------|-----------------|
|
||||
| **GRU_M00_DIAMOND_INSTITUTIONAL_SPEC.md** | Full §1–§8 institutional architecture spec (Diamond topology, storage, facets, governance, markets, W rules, Pattern A/B, minimum checklist, token model A/B/C). | **Done:** [GRU_M00_DIAMOND_INSTITUTIONAL_SPEC.md](GRU_M00_DIAMOND_INSTITUTIONAL_SPEC.md) created; token model A and Pattern A locked; GRC vs M00 evolution note added. |
|
||||
| **Token model decision** | Facet Map had “[ A \| B \| C ]”; locked choice was missing. | **Done:** Institutional spec §8 locks **Token model A**; Facet Map updated to “A (locked).” |
|
||||
| **Pattern A vs B** | Target pattern was not stated. | **Done:** Institutional spec §6 locks **Target: Pattern A**; Facet Map “Target pattern” line added. |
|
||||
|
||||
### 2.2 Storage (GRUStorage)
|
||||
|
||||
| Domain | Facet Map / Spec | Current State | Gap |
|
||||
|--------|------------------|---------------|-----|
|
||||
| Governance & roles | DAO/Council/Guardian, upgrade admin, timelock, policy controllers | GRCStorage has Gov (timelock, quorum, proposals), Access (role bits), no DAO/Council/Guardian names. | Add GRUStorage namespace constants and structs for governance; align or migrate from GRCStorage if M00 supersedes GRC. |
|
||||
| Token Factory Registry | assetId → (c,a,d) addresses; symbol → assetId; per-asset config | UniversalAssetRegistry has token → UniversalAsset (type, compliance, metadata); no assetId, no c/a/d triple per asset. | Define GRUStorage.TokenFactoryRegistry (or equivalent) with assetId, symbol→assetId, and c/a/d address triple; or document migration path from UniversalAssetRegistry. |
|
||||
| Accounting / Ledger | Journal entries, CoA, cost centers, reserve attestations, policy hashes | Not in Diamond; OMNL/Fineract off-chain. No on-chain journal/CoA structs. | Add GRUStorage.Accounting placeholder structs (journal entry, CoA slot, attestation hashes) for AccountingGateFacet stub. |
|
||||
| Compliance & Identity | KYC/AML allowlists, jurisdiction, sanctions, travel rule, audit roots | ComplianceGuard (iso4217w) validates mint/reserve only; no allowlist/jurisdiction/sanctions in contracts. dbis_core has ComplianceGateService (sanctions/AML). | Add GRUStorage.Compliance placeholder (allowlist/denylist, jurisdiction tags); wire ComplianceGate to it or to external oracle. |
|
||||
| ISO-20022 Message Vault | Schema registry, in/out logs, canonicalization hashes, correlation IDs | SMART_CONTRACTS_ISO20022_FIN_METHODOLOGY defines canonical struct; no on-chain vault or log storage. | Add GRUStorage.ISO20022Vault (or event-only + off-chain index); implement MessagingGate.logISO20022. |
|
||||
| i18n Registry | Locale packs, translation keys, disclosure templates | Not present in any contract. | Add GRUStorage.i18n placeholder (locale keys, hash pointers); i18nFacet stub reads from it. |
|
||||
| Expandable Standards Registry | standardId → moduleConfig (enabled, version, validators, constraints, pointers) | Not present. | Add GRUStorage.StandardsRegistry; StandardsRegistryFacet activate/deactivate modules and enforce “required modules per governance level.” |
|
||||
|
||||
### 2.3 Core Diamond Facets
|
||||
|
||||
| Facet | Spec | Current State | Gap |
|
||||
|-------|------|---------------|-----|
|
||||
| DiamondCutFacet | Upgrade mechanism | GrcDiamond has diamondCut inline; no separate facet. | OK if M00 keeps cut in core; else extract to DiamondCutFacet. |
|
||||
| DiamondLoupeFacet | Introspection | GrcDiamond has loupe inline. | Same as above. |
|
||||
| OwnershipFacet / GovernanceFacet | Owner, timelock, upgrade approval | GrcDiamond has owner; GovernanceFacet has proposeCut/queue/execute. | Alias or merge into single “GovernanceFacet” for M00; ensure timelock and upgrade approval workflow documented. |
|
||||
| PauseFacet | Global and per-selector pause | PauseFacet exists in gru-docs; GRCStorage has PauseState. | Keep; ensure M00 uses same slot namespace if migrating from GRC. |
|
||||
|
||||
### 2.4 Token Factory Facets (all missing as Diamond facets)
|
||||
|
||||
| Facet | Spec | Current State | Gap |
|
||||
|-------|------|---------------|-----|
|
||||
| AssetRegistryFacet | Asset definitions, W semantics, assetId hash | UniversalAssetRegistry (standalone) has asset types and metadata; iso4217w TokenFactory enforces \<CCC\>W. No deterministic assetId or c/a/d symbol grammar in one place. | Implement as facet (or wrap UniversalAssetRegistry behind facet); add symbol→assetId and W-before/W-after parsing per Facet Map grammar. |
|
||||
| MarketFactoryFacet | Creates market per ISO; emits c/a/d token contracts | VaultFactory creates vault + DepositToken + DebtToken per asset; TokenFactory138 is stub; CompliantUSDC/USDT and CompliantFiatToken are separate contracts. | Either (1) MarketFactoryFacet deploys proxy/minimal clones for c/a/d, or (2) MarketFactoryFacet registers existing external c/a/d addresses in GRUStorage; document vs VaultFactory/TokenFactory138. |
|
||||
| MintBurnFacet | Mint/burn rules, reserve gating, supply caps, emergency locks | ComplianceGuard validates mint; individual token contracts have mint/burn. No single MintBurnFacet. | Implement MintBurnFacet calling ReserveGate and token contracts or internal ledger; centralize caps and emergency locks in storage. |
|
||||
| InterestRateFacet | Aave-style index math, rate models, accrual | Not in gru-docs or smom-dbis-138 as a facet. DepositToken/DebtToken do not implement interest indices. | Add InterestRateFacet (stub or full) with index storage and rate model hooks. |
|
||||
| BridgeWrapFacet | W-before-ISO (wrapped bridge), escrow, bridge operators | Bridge contracts (GRUCCIPBridge, ISO4217WCCIPBridge, etc.) are standalone; no “BridgeWrapFacet” in Diamond. | Add facet that delegates to bridge contracts or holds bridge operator config in GRUStorage. |
|
||||
| DWINFacet | W-after-T/C (D-WIN), denomination, windowing | Not present. | Add DWINFacet stub with storage for denomination/windowing rules. |
|
||||
|
||||
### 2.5 Standards / Compliance Facets (all missing or stub-only)
|
||||
|
||||
| Facet | Spec | Current State | Gap |
|
||||
|-------|------|---------------|-----|
|
||||
| IPSASFacet | GRU ledger ↔ IPSAS reporting, fund accounting | OMNL has IPSAS in Fineract/off-chain journal matrix; no on-chain facet. | Add IPSASFacet stub; document mapping from GRUStorage ledger to IPSAS classifications. |
|
||||
| IFRSUSGAAPFacet | Revenue recognition, lease/contract hooks, impairment | Not present. | Add stub; document future hooks. |
|
||||
| ISO20022Facet | pacs/camt builders, dictionary, settlement correlation | Methodology doc and runbook exist; no on-chain message builder facet. | Add ISO20022Facet stub; emit or store canonical message hashes/correlation IDs per MessagingGate. |
|
||||
| i18nFacet | Locale packs, translation keys, disclosure templates | Not present. | Add stub; read from GRUStorage.i18n. |
|
||||
| GovernanceLevelFacet | Policy levels 0..N, bitmask, routes enforcement | Not present. GRCStorage has no policy level or bitmask. | Add GovernanceLevelFacet; add GRUStorage policy level and bitmask; document “required modules per level.” |
|
||||
|
||||
### 2.6 Policy Layer (Router + Gates)
|
||||
|
||||
| Component | Spec | Current State | Gap |
|
||||
|-----------|------|---------------|-----|
|
||||
| PolicyRouterFacet | Calls ComplianceGate, AccountingGate, MessagingGate, ReserveGate | Not present in contracts. | Implement PolicyRouterFacet: e.g. `checkTransfer` → ComplianceGate, `postJournal` → AccountingGate, `logISO20022` → MessagingGate, `checkBacking` → ReserveGate; gate addresses from storage or facet. |
|
||||
| ComplianceGate | checkTransfer (KYC/AML, sanctions, jurisdiction) | dbis_core ComplianceGateService (off-chain); ComplianceGuard (on-chain) only validates mint/reserve. | Add ComplianceGateFacet (stub) with allowlist/denylist and jurisdiction placeholders; optionally call off-chain or oracle. |
|
||||
| AccountingGate | postJournal (ledger, CoA) | No on-chain gate. | Add AccountingGateFacet stub; write to GRUStorage.Accounting or emit events. |
|
||||
| MessagingGate | logISO20022 (message log, correlation IDs) | No on-chain gate. | Add MessagingGateFacet stub; write to GRUStorage.ISO20022Vault or emit events. |
|
||||
| ReserveGate | checkBacking (reserve proofs, attestations) | ComplianceGuard validates reserve for mint; no generic “checkBacking” gate. | Add ReserveGateFacet stub; delegate to existing reserve/oracle logic or attestation hashes in storage. |
|
||||
|
||||
### 2.7 Minimum Ship List (Stubs)
|
||||
|
||||
| Item | Spec | Current State | Gap |
|
||||
|------|------|---------------|-----|
|
||||
| AppStorage skeleton | Module registry, policy bitmask, ledger/ISO20022/i18n structs | GRCStorage has different namespaces; no GRUStorage. | Define GRUStorage (or extend GRCStorage with reserved namespaces) with all 7 domains + policy bitmask + module registry. |
|
||||
| GovernanceFacet | RBAC, timelock, upgrade approval | Exists in gru-docs (GovernanceFacet). | Verify it fits M00; add “policy controllers per module” if required. |
|
||||
| PolicyRouterFacet | Empty gates callable, events | Missing. | Implement as above. |
|
||||
| TokenFactoryFacet | Register assets, deploy or ledger tokens | TokenFactory138 is stub; no Diamond facet. | Implement TokenFactoryFacet (or unify AssetRegistry + MarketFactory) to register assets and create/link c/a/d. |
|
||||
| ComplianceGateFacet (stub) | Allowlist, jurisdiction placeholders | Missing. | Add stub. |
|
||||
| AccountingGateFacet (stub) | Journal, CoA placeholders | Missing. | Add stub. |
|
||||
| StandardsRegistryFacet | Activate/deactivate modules, enforce required per level | Missing. | Add; wire to GRUStorage.StandardsRegistry and GovernanceLevelFacet. |
|
||||
|
||||
---
|
||||
|
||||
## 3. Functional Wire-Ins to Complete
|
||||
|
||||
### 3.1 Diamond ↔ Token Factory
|
||||
|
||||
- **Current:** No single Diamond owns token creation. VaultFactory, TokenFactory (iso4217w), CompliantFiatToken deployments are independent.
|
||||
- **Target:** M00 Diamond exposes AssetRegistryFacet + MarketFactoryFacet (or TokenFactoryFacet); all c/a/d registration and creation go through Diamond.
|
||||
- **Wire-in:** (1) Deploy M00 Diamond with GRUStorage; (2) Add AssetRegistryFacet + MarketFactoryFacet (or TokenFactoryFacet); (3) MarketFactoryFacet either deploys new c/a/d contracts or registers existing ones in GRUStorage; (4) All mint/burn/transfer that must be gated go through Diamond (or token contracts call back into Diamond for gate checks).
|
||||
|
||||
**c* GRU integration (implemented):** All c* (compliant) tokens are integrated with the GRU ERC-2535 facet path: (1) **UniversalAssetRegistry** — register each c* via `registerGRUCompliantAsset()` (AssetType.GRU, no timelock); (2) **GRUCCIPBridge** and **PoolManager** read the registry and accept GRU assets; (3) **GRUAssetRegistryFacet** delegates to UniversalAssetRegistry so the M00 Diamond can expose the same registry when the facet is attached. Run **RegisterGRUCompliantTokens.s.sol** after deploying c* tokens; run **GRUCompliantTokensRegistryTest** (integration tests) before deployments. See [DEPLOYMENT_ORDER_OF_OPERATIONS](../03-deployment/DEPLOYMENT_ORDER_OF_OPERATIONS.md) § Phase 2.4.
|
||||
|
||||
### 3.2 PolicyRouter → Gates
|
||||
|
||||
- **Current:** No PolicyRouter; no on-chain gates except ComplianceGuard (mint-only).
|
||||
- **Target:** Every transfer (or mint/burn) that is policy-sensitive calls PolicyRouter.checkTransfer (or equivalent); PolicyRouter reads GovernanceLevelFacet level and calls ComplianceGate, AccountingGate, MessagingGate, ReserveGate as required.
|
||||
- **Wire-in:** (1) Implement PolicyRouterFacet with `checkTransfer`, `postJournal`, `logISO20022`, `checkBacking`; (2) Implement each gate as facet or internal module; (3) Token contracts or Diamond entry points call PolicyRouter before state changes; (4) GovernanceLevelFacet exposes level/bitmask; PolicyRouter reads it and skips or enforces each gate.
|
||||
|
||||
### 3.3 Governance Level → Enforcement
|
||||
|
||||
- **Current:** No governance level or bitmask in storage; no routing by level.
|
||||
- **Target:** Governance levels 0–5 (per Facet Map); level stored in GRUStorage; GovernanceLevelFacet and PolicyRouter use it to decide which gates to call and with what strictness.
|
||||
- **Wire-in:** (1) Add `governanceLevel` (and optional `policyBitmask`) to GRUStorage; (2) GovernanceLevelFacet get/set level (restricted); (3) PolicyRouter and gate stubs branch on level; (4) Document level semantics (0–5) in Facet Map and runbooks.
|
||||
|
||||
### 3.4 Off-Chain vs On-Chain Compliance
|
||||
|
||||
- **Current:** dbis_core ComplianceGateService does sanctions/AML off-chain; on-chain ComplianceGuard only validates mint/reserve for ISO4217W.
|
||||
- **Target:** Clear split: which checks are on-chain (allowlist/denylist, jurisdiction tags) vs off-chain (full sanctions/AML); on-chain ComplianceGateFacet calls external adapter or stores results.
|
||||
- **Wire-in:** (1) Define interface for “compliance result” (allowed/denied + reason); (2) ComplianceGateFacet stub stores allowlist/denylist and jurisdiction in GRUStorage; (3) Optionally add “oracle” or relayer that posts off-chain ComplianceGateService result on-chain for PolicyRouter to read.
|
||||
|
||||
### 3.5 ISO-20022 and MessagingGate
|
||||
|
||||
- **Current:** Canonical message format and methodology doc exist; no on-chain message log or correlation.
|
||||
- **Target:** MessagingGate.logISO20022 stores or emits message hash + correlation ID; ISO20022Facet can build/reference pacs/camt payloads.
|
||||
- **Wire-in:** (1) Add GRUStorage.ISO20022Vault (or event-only design); (2) MessagingGateFacet accepts canonical struct hash + correlationId; (3) Emit event and/or write to storage; (4) Link to SMART_CONTRACTS_ISO20022_FIN_METHODOLOGY and MULTI_CHAIN_EXECUTION_ISO20022_EMONEY.
|
||||
|
||||
### 3.6 Reserve and Attestation
|
||||
|
||||
- **Current:** ComplianceGuard validates reserve for mint; PoR in GRCStorage (AuditPeriod); no generic “checkBacking” for all operations.
|
||||
- **Target:** ReserveGate.checkBacking(assetId, amount) used by PolicyRouter before mint/transfer where level requires; attestation hashes in GRUStorage.
|
||||
- **Wire-in:** (1) ReserveGateFacet stub checks GRUStorage or external oracle for reserve/attestation; (2) MintBurnFacet (or token contracts) call ReserveGate when level ≥ 2; (3) Document attestation format and who posts hashes.
|
||||
|
||||
---
|
||||
|
||||
## 4. Naming and Alignment Gaps
|
||||
|
||||
### 4.1 Symbol Grammar: a/d vs ac/vdc/sdc
|
||||
|
||||
- **Facet Map / institutional spec:** Canonical grammar uses **a**\<ISO>\<T|C\> (asset) and **d**\<ISO>\<T|C\> (debt). Examples: aUSDC, dUSDC, aEURCT, dWUSDT.
|
||||
- **TOKEN_SCOPE_GRU and deployment:** Tokens are named **ac*** (e.g. acUSDC, acUSDT) and **vdc***/sdc* (e.g. vdcUSDC, sdcUSDC). These are Aave-style “deposit” and “debt” tokens.
|
||||
- **Gap:** “a” and “d” in the spec are logical roles; “ac” and “vdc/sdc” are implementation names. Either (1) document that **a** = **ac** (asset/deposit) and **d** = **vdc/sdc** (debt) and keep both nomenclatures, or (2) rename in spec to ac/d for consistency with deployed tokens.
|
||||
- **Recommendation:** Add a short subsection in Facet Map or TOKEN_SCOPE_GRU: “Canonical grammar: **a** (asset) ↔ **ac** (DepositToken), **d** (debt) ↔ **vdc** / **sdc** (DebtToken). Symbol in registry may be aUSDC or acUSDC; both refer to same asset token type.”
|
||||
|
||||
### 4.2 GRC-2535 vs M00 Diamond
|
||||
|
||||
- **GRC-2535 (gru-docs):** GrcDiamond + GRCStorage + Monetary, Triangulation, Index, Bond, Audit, Governance, Access, Pause, ComplianceFacet (stub), OracleAggregatorFacet (stub). No Token Factory, no PolicyRouter, no GRUStorage as in Facet Map.
|
||||
- **M00 Diamond (Facet Map):** Single Diamond with GRUStorage, Token Factory facets, Standards facets, PolicyRouter + gates.
|
||||
- **Gap:** Two different “Diamond” designs. Migration path or relationship is undefined.
|
||||
- **Recommendation:** Document in institutional spec or a “GRU Diamond Evolution” note: “GRC-2535 is the current GRU Diamond (monetary, bond, index, audit). M00 Diamond extends or replaces it with Token Factory + GRUStorage + policy gates. Decision: migrate GRC → M00 (same contract, new facets + storage) vs deploy M00 as new Diamond and deprecate GRC.”
|
||||
|
||||
### 4.3 UniversalAssetRegistry vs AssetRegistryFacet
|
||||
|
||||
- **UniversalAssetRegistry (smom-dbis-138):** Central registry for asset types (GRU, ISO4217W, Commodity, etc.); used by bridges, PoolManager, GovernanceController, TokenlistGovernanceSync. Not a Diamond facet.
|
||||
- **AssetRegistryFacet (spec):** Asset definitions, W semantics, assetId, symbol→assetId inside M00 Diamond.
|
||||
- **Gap:** Duplication or migration path unclear.
|
||||
- **Recommendation:** (1) If M00 is new deployment: AssetRegistryFacet could wrap or replace UniversalAssetRegistry (Diamond holds registry state or delegates to external registry). (2) Document “UniversalAssetRegistry remains source of truth for bridges until M00 is deployed; then migrate or mirror to GRUStorage.TokenFactoryRegistry.”
|
||||
|
||||
---
|
||||
|
||||
## 5. Recommendations and Suggestions
|
||||
|
||||
### 5.1 High priority
|
||||
|
||||
1. **Create GRU_M00_DIAMOND_INSTITUTIONAL_SPEC.md** — Paste the full §1–§8 institutional spec; link from Facet Map. This is the single hand-off doc for Solidity engineers.
|
||||
2. **Lock token model (A/B/C)** — Document in spec or Facet Map which of (A) separate ERC-20, (B) internal ledger, (C) hybrid is the target; update Facet Map “Token model” line accordingly.
|
||||
3. **Define GRUStorage layout** — One Solidity library or doc with namespaced structs and slots for all 7 domains + policy bitmask + standards registry. Reserve namespaces for future facets to avoid collision.
|
||||
4. **Implement minimum ship list** — PolicyRouterFacet + four gate stubs (Compliance, Accounting, Messaging, Reserve), StandardsRegistryFacet, GovernanceLevelFacet (level + bitmask), and TokenFactoryFacet (or AssetRegistry + MarketFactory) that register assets and optionally deploy/link c/a/d. Start with stubs that revert or no-op with events.
|
||||
5. **Wire PolicyRouter to governance level** — PolicyRouter reads level from GovernanceLevelFacet; for each transfer/mint path, call only the gates required for that level; document in runbook.
|
||||
|
||||
### 5.2 Medium priority
|
||||
|
||||
6. **Align symbol grammar with TOKEN_SCOPE_GRU** — Add a↔ac, d↔vdc/sdc mapping and keep single source of truth for “canonical symbol” (either Facet Map or TOKEN_SCOPE_GRU with cross-link).
|
||||
7. **Document GRC-2535 → M00 path** — One-page “Diamond evolution” or “M00 migration”: whether M00 is new Diamond or upgrade of GrcDiamond; which facets/storage are reused vs new.
|
||||
8. **Reserve GRUStorage namespaces** — Even if a domain is stub-only, reserve its slot (keccak256 namespace) so future facets can extend without migration.
|
||||
9. **ISO-20022 on-chain footprint** — Decide event-only vs storage for message log; implement MessagingGate.logISO20022 and optional ISO20022Facet stub.
|
||||
10. **Off-chain ComplianceGate integration** — Define how dbis_core ComplianceGateService result is consumed on-chain (relayer, oracle, or keep transfer checks off-chain and only log).
|
||||
|
||||
### 5.3 Lower priority / optional
|
||||
|
||||
11. **InterestRateFacet and DWINFacet** — Stub with storage for rate indices and D-WIN rules; full implementation when a/d token behavior is finalized.
|
||||
12. **IPSASFacet / IFRSUSGAAPFacet** — Stub and mapping doc from GRU ledger codes to IPSAS/IFRS; full logic later.
|
||||
13. **i18nFacet** — Stub reading locale/key hashes from GRUStorage; UI/legal can consume from indexer or API.
|
||||
14. **Pattern B (facet packs per asset)** — Only if a flagship USD/EUR market needs dedicated rate/compliance/settlement logic; document when and how.
|
||||
|
||||
---
|
||||
|
||||
## 6. Checklist for “Spine” Completion
|
||||
|
||||
Use this as a quick gate for “deployable spine” per institutional spec §7.
|
||||
|
||||
| # | Item | Done |
|
||||
|---|------|------|
|
||||
| 1 | AppStorage skeleton (module registry, policy bitmask, ledger/ISO20022/i18n structs) | ☐ |
|
||||
| 2 | GovernanceFacet (RBAC, timelock, upgrade approval) | ☐ (exists in GRC; verify for M00) |
|
||||
| 3 | PolicyRouterFacet (callable gates, events) | ☐ |
|
||||
| 4 | TokenFactoryFacet or AssetRegistry + MarketFactory (register assets, deploy or ledger c/a/d) | ☐ |
|
||||
| 5 | ComplianceGateFacet (stub: allowlist, jurisdiction) | ☐ |
|
||||
| 6 | AccountingGateFacet (stub: journal, CoA) | ☐ |
|
||||
| 7 | StandardsRegistryFacet (activate/deactivate, require per level) | ☐ |
|
||||
| 8 | GovernanceLevelFacet (level 0..N, bitmask) | ☐ |
|
||||
| 9 | GRUStorage namespaces defined and reserved | ☐ |
|
||||
| 10 | PolicyRouter wired to level and gates | ☐ |
|
||||
| 11 | Institutional spec doc created and linked | ☑ (GRU_M00_DIAMOND_INSTITUTIONAL_SPEC.md) |
|
||||
| 12 | Token model A/B/C locked and documented | ☑ (Token model A, Pattern A in institutional spec §8, §6) |
|
||||
| 13 | Testing and verification (post-deploy) | ☐ — Run [GRU_M00_DIAMOND_DEPLOYMENT_RUNBOOK.md](../runbooks/GRU_M00_DIAMOND_DEPLOYMENT_RUNBOOK.md) §6 (loupe, governance level, PolicyRouter, storage layout, upgrade, events). Add Forge/Hardhat tests when spine is implemented. |
|
||||
|
||||
---
|
||||
|
||||
## 7. Additional Recommendations, Suggestions, and Gaps
|
||||
|
||||
Beyond §2–§6 and the spine checklist, the following are additional recommendations, suggestions, or gaps.
|
||||
|
||||
### 7.1 Runbooks and deployment
|
||||
|
||||
| Item | Gap | Recommendation |
|
||||
|------|-----|-----------------|
|
||||
| **M00 deployment runbook** | Institutional spec said “Document the chosen path in the deployment runbook”; no runbook existed. | **Done:** [GRU_M00_DIAMOND_DEPLOYMENT_RUNBOOK.md](../runbooks/GRU_M00_DIAMOND_DEPLOYMENT_RUNBOOK.md) — Option A (new Diamond), Option B (migrate GRC→M00), target chain, CREATE2, initial facet order, testing §6. |
|
||||
| **Chain and CREATE2** | M00 Diamond spec did not state target chain(s) or CREATE2. | **Done:** Runbook §1 and institutional spec "Deployment target chain and CREATE2" state: primary chain 138, then mainnet/651940; CREATE2 when same-address parity required. |
|
||||
|
||||
### 7.2 Cross-doc and repo alignment
|
||||
|
||||
| Item | Gap | Recommendation |
|
||||
|------|-----|-----------------|
|
||||
| **TOKEN_SCOPE_GRU ↔ Facet Map** | Facet Map §5.5 links to TOKEN_SCOPE_GRU; TOKEN_SCOPE_GRU did not link back. | **Done:** TOKEN_SCOPE_GRU §8 has “Canonical symbol grammar” note with link to Facet Map §5. |
|
||||
| **VAULT_SYSTEM_MASTER_TECHNICAL_PLAN** | VAULT_SYSTEM mentioned M00 but did not link to M00 docs. | **Done:** VAULT_SYSTEM §3 (GRU Assets) links to institutional spec and Facet Map. |
|
||||
| **REQUIRED_FIXES_UPDATES_GAPS** | Repo-wide gaps doc did not list GRU M00 Diamond spine. | **Done:** §9 includes “GRU M00 Diamond spine (optional)” with links to institutional spec §7, Review §6 checklist, deployment runbook. |
|
||||
|
||||
### 7.3 Defaults and interfaces
|
||||
|
||||
| Item | Gap | Recommendation |
|
||||
|------|-----|-----------------|
|
||||
| **Default governance level** | Facet Map defined levels 0–5 but did not state default at deployment. | **Done:** Institutional spec “Deployment target chain and CREATE2” and runbook §2 state default level 0; Facet Map §4 references runbook and spec. |
|
||||
| **PolicyRouter and gate events** | Spec said gates “emit events” but no standard event names/signatures were defined. | **Done:** Institutional spec **Appendix: PolicyRouter and gate event signatures** defines TransferChecked, JournalPosted, MessageLogged, BackingChecked, GovernanceLevelSet. Runbook §6 references the appendix. |
|
||||
|
||||
### 7.4 Testing and verification
|
||||
|
||||
| Item | Gap | Recommendation |
|
||||
|------|-----|-----------------|
|
||||
| **M00 Diamond tests** | No tests or verification steps were documented for M00 Diamond. | **Done:** Runbook §6 defines post-deploy checks (loupe, governance level, PolicyRouter, storage layout, upgrade, events). Spine checklist item 13 added; add Forge/Hardhat tests when spine is implemented. |
|
||||
|
||||
### 7.5 UniversalAssetRegistry migration
|
||||
|
||||
| Item | Gap | Recommendation |
|
||||
|------|-----|-----------------|
|
||||
| **Explicit migration note** | Review §4.3 recommended documenting UniversalAssetRegistry as source of truth until M00. | **Done:** Institutional spec “GRU Diamond evolution” includes “Existing registries”: UniversalAssetRegistry remains source of truth until M00; after M00, migrate or mirror to GRUStorage.TokenFactoryRegistry and document cutover. |
|
||||
|
||||
---
|
||||
|
||||
## 8. Related Documents
|
||||
|
||||
- [GRU_M00_DIAMOND_FACET_MAP.md](GRU_M00_DIAMOND_FACET_MAP.md) — Facet map, storage namespaces, governance levels, symbol grammar.
|
||||
- [GRU_M00_DIAMOND_DOCS_REVIEW_GAPS_AND_INCONSISTENCIES.md](GRU_M00_DIAMOND_DOCS_REVIEW_GAPS_AND_INCONSISTENCIES.md) — Review of all GRU M00 Diamond docs for gaps and inconsistencies.
|
||||
- [GRU_M00_DIAMOND_INSTITUTIONAL_SPEC.md](GRU_M00_DIAMOND_INSTITUTIONAL_SPEC.md) — Full §1–§8 institutional spec; token model A and Pattern A locked; GRC vs M00 evolution.
|
||||
- [gru-docs/contracts/README.md](../../gru-docs/contracts/README.md) — GRC-2535 Diamond.
|
||||
- [smom-dbis-138/docs/tokenization/TOKEN_SCOPE_GRU.md](../../smom-dbis-138/docs/tokenization/TOKEN_SCOPE_GRU.md) — c/a/d and W token lists.
|
||||
- [SMART_CONTRACTS_ISO20022_FIN_METHODOLOGY.md](SMART_CONTRACTS_ISO20022_FIN_METHODOLOGY.md) — Canonical message format.
|
||||
- [VAULT_SYSTEM_MASTER_TECHNICAL_PLAN.md](../VAULT_SYSTEM_MASTER_TECHNICAL_PLAN.md) — Vault and M00 reference.
|
||||
- [REQUIRED_FIXES_UPDATES_GAPS.md](../REQUIRED_FIXES_UPDATES_GAPS.md) — Repo-wide fixes and gaps.
|
||||
|
||||
**See also §7** for additional recommendations (runbooks, cross-docs, defaults, events, testing, UniversalAssetRegistry migration).
|
||||
@@ -20,6 +20,8 @@ This runbook provides step-by-step verification procedures for the complete ingr
|
||||
|
||||
## Prerequisites
|
||||
|
||||
**Production note:** Example values below (e.g. `your-token`, `your-password`) are placeholders. In production, source real values from your `.env` file only; do not commit secrets.
|
||||
|
||||
### Access Credentials
|
||||
|
||||
Ensure the following are configured in `.env`:
|
||||
|
||||
180
docs/04-configuration/IPFS_TOKEN_LOGOS_RUNBOOK.md
Normal file
180
docs/04-configuration/IPFS_TOKEN_LOGOS_RUNBOOK.md
Normal file
@@ -0,0 +1,180 @@
|
||||
# IPFS Token Logos — Full Coverage for All Networks and Explorers
|
||||
|
||||
**Last Updated:** 2026-02-28
|
||||
**Purpose:** Host all token logos on IPFS so they are available for explorer.d-bis.org (Blockscout), token lists, MetaMask, CoinGecko/CMC, and all bridge networks.
|
||||
|
||||
---
|
||||
|
||||
## 1. Current State
|
||||
|
||||
### IPFS in This Repo
|
||||
|
||||
| Component | Location | Purpose |
|
||||
|-----------|----------|---------|
|
||||
| **Firefly IPFS** | `smom-dbis-138/k8s/firefly/ipfs.yaml`, `smom-dbis-138-proxmox/install/firefly-install.sh` | Firefly shared storage (internal) |
|
||||
| **Kubo (standalone)** | `ProxmoxVE/install/kubo-install.sh` | General-purpose IPFS node (LXC) |
|
||||
|
||||
### Logo Consumers
|
||||
|
||||
| Consumer | Where | Format |
|
||||
|----------|-------|--------|
|
||||
| **Blockscout (explorer.d-bis.org)** | `tokens.logo_url` in DB, or `/images/tokens/{address}.png` | PNG, any size |
|
||||
| **Token list (dbis-138.tokenlist.json)** | `logoURI` per token | URL (PNG/SVG) |
|
||||
| **Token-aggregation API** | `getLogoUriForSpec()` in canonical-tokens.ts | Trust Wallet URLs |
|
||||
| **MetaMask / Snap** | Fetches token list with logoURI | URL |
|
||||
| **CoinGecko / CMC** | 512×512 PNG for submission | PNG |
|
||||
| **Other explorers** | etherscan.io, bscscan.com, polygonscan.com, etc. | Token metadata or external lists |
|
||||
|
||||
### Networks and Explorers
|
||||
|
||||
| Chain ID | Network | Explorer | Token Logo Source |
|
||||
|----------|---------|----------|-------------------|
|
||||
| 138 | Chain 138 | explorer.d-bis.org | Blockscout DB / static / IPFS |
|
||||
| 651940 | ALL Mainnet | — | Token list |
|
||||
| 1 | Ethereum | etherscan.io | Contract metadata, token lists |
|
||||
| 56 | BSC | bscscan.com | Same |
|
||||
| 137 | Polygon | polygonscan.com | Same |
|
||||
| 100 | Gnosis | gnosisscan.io | Same |
|
||||
| 10 | Optimism | optimistic.etherscan.io | Same |
|
||||
| 42161 | Arbitrum | arbiscan.io | Same |
|
||||
| 8453 | Base | basescan.org | Same |
|
||||
| 43114 | Avalanche | snowtrace.io | Same |
|
||||
| 25 | Cronos | cronoscan.com | Same |
|
||||
| 42220 | Celo | celoscan.io | Same |
|
||||
| 1111 | Wemix | scan.wemix.com | Same |
|
||||
|
||||
**Key:** Third-party explorers (Etherscan, BSCScan, etc.) resolve logos from contract metadata, token lists, or their own registries. Our token list URL (`https://explorer.d-bis.org/api/v1/report/token-list`) provides logoURI for wallets. For Blockscout (our explorer), we control logo display.
|
||||
|
||||
---
|
||||
|
||||
## 2. Logo Inventory (All Tokens)
|
||||
|
||||
### Chain 138 Tokens (dbis-138.tokenlist.json)
|
||||
|
||||
| Symbol | Address (138) | Current logoURI |
|
||||
|--------|---------------|-----------------|
|
||||
| ETH-USD | 0x3304b747E565a97ec8AC220b0B6A1f6ffDB837e6 | ethereum.org |
|
||||
| WETH | 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 | ethereum.org |
|
||||
| WETH10 | 0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9f | ethereum.org |
|
||||
| LINK | 0xb7721dD53A8c629d9f1Ba31a5819AFe250002b03 | chainlink-docs |
|
||||
| cUSDT | 0x93E66202A11B1772E55407B32B44e5Cd8eda7f22 | Trust Wallet |
|
||||
| cUSDC | 0xf22258f57794CC8E06237084b353Ab30fFfa640b | Trust Wallet |
|
||||
|
||||
### Canonical Tokens (All Networks)
|
||||
|
||||
From `canonical-tokens.ts`: cUSDC, cUSDT, cEURC, cEURT, cGBPC, cGBPT, cAUDC, cJPYC, cCHFC, cCADC, cXAUC, cXAUT, LiXAU, USDW, EURW, GBPW, AUDW, JPYW, CHFW, CADW, WETH, WETH10, LINK, ETH-USD (oracle).
|
||||
|
||||
---
|
||||
|
||||
## 3. IPFS Setup Options
|
||||
|
||||
### Option A: Use Existing Firefly IPFS
|
||||
|
||||
If Firefly IPFS is running and has a public gateway:
|
||||
|
||||
```bash
|
||||
# Gateway typically at http://<ipfs-host>:8080
|
||||
# Add file: curl -X POST -F file=@logo.png "http://<ipfs-api>:5001/api/v0/add"
|
||||
```
|
||||
|
||||
### Option B: Standalone Kubo (ProxmoxVE Script)
|
||||
|
||||
```bash
|
||||
# Install Kubo on LXC via ProxmoxVE script
|
||||
# ProxmoxVE/install/kubo-install.sh
|
||||
# Then: ipfs add logo.png
|
||||
```
|
||||
|
||||
### Option C: Pinata / Infura / Web3.Storage
|
||||
|
||||
For production, use a pinning service so logos stay available even when your node is offline:
|
||||
|
||||
- **Pinata:** https://pinata.cloud — free tier, pin by upload
|
||||
- **Web3.Storage:** https://web3.storage — free, IPFS + Filecoin
|
||||
- **Infura IPFS:** https://infura.io/product/ipfs
|
||||
|
||||
### Option D: Public Gateway (ipfs.io)
|
||||
|
||||
After `ipfs add`, use `https://ipfs.io/ipfs/<CID>` or `https://<cid>.ipfs.dweb.link`. No pinning service needed if you pin locally and others fetch; for reliability, use a pinning service.
|
||||
|
||||
---
|
||||
|
||||
## 4. Workflow: Prepare → Upload → Update
|
||||
|
||||
### Step 1: Prepare 512×512 PNGs
|
||||
|
||||
```bash
|
||||
./docs/04-configuration/coingecko/scripts/prepare-token-logos-512x512.sh
|
||||
# Output: docs/04-configuration/coingecko/logos/*.png
|
||||
```
|
||||
|
||||
### Step 2: Upload to IPFS
|
||||
|
||||
```bash
|
||||
./scripts/upload-token-logos-to-ipfs.sh
|
||||
# Uses: ipfs add (local) or Pinata API (if PINATA_JWT set)
|
||||
# Output: docs/04-configuration/coingecko/logos/ipfs-manifest.json
|
||||
```
|
||||
|
||||
### Step 3: Update Configs
|
||||
|
||||
- **Token list:** Replace logoURI with IPFS gateway URL
|
||||
- **canonical-tokens.ts:** Add `logoUrl` to specs or change LOGO_BASE to IPFS
|
||||
- **Blockscout:** Update `tokens.logo_url` via migration or admin; or serve from `/images/tokens/{address}.png` (nginx static)
|
||||
|
||||
### Step 4: Pin for Persistence
|
||||
|
||||
If using local IPFS: `ipfs pin add <CID>`
|
||||
If using Pinata: upload pins the file automatically.
|
||||
|
||||
---
|
||||
|
||||
## 5. Blockscout Logo Paths
|
||||
|
||||
Blockscout can show token logos from:
|
||||
|
||||
1. **`tokens.logo_url`** — Set in DB per token (address). Use IPFS gateway URL.
|
||||
2. **Static files** — `/images/tokens/{address}.png` (lowercase address). Nginx serves from Blockscout static dir or custom path.
|
||||
3. **External URL** — If logo_url is an external URL, Blockscout may proxy or hotlink (check Blockscout version).
|
||||
|
||||
Recommended: Set `logo_url` in DB to `https://ipfs.io/ipfs/<CID>` or your gateway. Run migration to backfill:
|
||||
|
||||
```sql
|
||||
UPDATE tokens SET logo_url = 'https://ipfs.io/ipfs/Qm...' WHERE address = '0x...';
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. Chainlist Icon (eip155-138.json)
|
||||
|
||||
Chainlist requires `_data/icons/defioraclemeta.json` if you use `"icon": "defioraclemeta"`. Format:
|
||||
|
||||
```json
|
||||
[{"url":"ipfs://Qm...","width":1000,"height":1628,"format":"png"}]
|
||||
```
|
||||
|
||||
Upload chain logo (512×512 or larger) to IPFS, then add this file to chains repo. Or omit `icon` (current approach).
|
||||
|
||||
---
|
||||
|
||||
## 7. Checklist
|
||||
|
||||
- [x] Run `prepare-token-logos-512x512.sh` — all 24 tokens
|
||||
- [x] Run `upload-token-logos-to-ipfs.sh` — CIDs in ipfs-manifest.json
|
||||
- [ ] Run `upload-token-logos-to-ipfs.sh` — get CIDs
|
||||
- [ ] Pin CIDs (local or Pinata/Web3.Storage)
|
||||
- [ ] Update `dbis-138.tokenlist.json` logoURI to IPFS URLs
|
||||
- [ ] Update `canonical-tokens.ts` LOGO_BASE or per-spec logoUrl
|
||||
- [ ] Backfill Blockscout `tokens.logo_url` for Chain 138
|
||||
- [ ] Serve `/images/tokens/{address}.png` from nginx (optional fallback)
|
||||
- [ ] Add chain icon to Chainlist if desired
|
||||
- [ ] Verify logos in MetaMask, Blockscout, token list API
|
||||
|
||||
---
|
||||
|
||||
## See Also
|
||||
|
||||
- [FULL_PARITY_TOKEN_COVERAGE_RUNBOOK](FULL_PARITY_TOKEN_COVERAGE_RUNBOOK.md)
|
||||
- [PUBLICATION_LOCATIONS_MASTER](PUBLICATION_LOCATIONS_MASTER.md)
|
||||
- [prepare-token-logos-512x512.sh](coingecko/scripts/prepare-token-logos-512x512.sh)
|
||||
- [scripts/upload-token-logos-to-ipfs.sh](../../scripts/upload-token-logos-to-ipfs.sh)
|
||||
@@ -0,0 +1,176 @@
|
||||
# ISO-20022 Intake / Gateway Contract on Different Blockchain Networks
|
||||
|
||||
**Version:** 1.0
|
||||
**Last Updated:** 2026-02-23
|
||||
**Status:** Active
|
||||
**Companion to:** [SMART_CONTRACTS_ISO20022_FIN_METHODOLOGY.md](SMART_CONTRACTS_ISO20022_FIN_METHODOLOGY.md)
|
||||
|
||||
---
|
||||
|
||||
## 1. Purpose
|
||||
|
||||
This document describes **how the intake or gateway contract** that receives ISO-20022 (and Fin) messages **works across different blockchain networks**: same logical contract, same address where possible, two delivery paths (relayer-submitted vs cross-chain), and per-chain configuration without breaking deterministic deployment.
|
||||
|
||||
---
|
||||
|
||||
## 2. Role of the Intake / Gateway Contract
|
||||
|
||||
The **ISO intake contract** is the **single on-chain entry point** that:
|
||||
|
||||
1. **Accepts** a **canonical ISO message** (see [SMART_CONTRACTS_ISO20022_FIN_METHODOLOGY.md](SMART_CONTRACTS_ISO20022_FIN_METHODOLOGY.md)) from either:
|
||||
- an **off-chain relayer** (gateway that parsed MX/MT and submits the canonical payload), or
|
||||
- a **cross-chain message** (e.g. CCIP) that carries the canonical payload from another chain.
|
||||
2. **Enforces** idempotency (by `instructionId` / `msgId`), **authorisation** (relayer role or CCIP router), and optional **policy** (ComplianceGuard, allowlists).
|
||||
3. **Executes** the intended action: mint, transfer, or unlock for bridge, and **emits events** with canonical metadata for audit and ISO-20022 reporting.
|
||||
|
||||
The contract does **not** parse raw MX/MT; it only ever sees the **canonical struct**. Parsing and mapping happen off-chain or on the source chain before submission.
|
||||
|
||||
---
|
||||
|
||||
## 3. Same Address on Every Network
|
||||
|
||||
To keep integration simple and avoid per-chain address maps, the intake contract is deployed at the **same address on every supported chain**, following the same pattern as [UniversalCCIPBridge](../runbooks/MULTI_CHAIN_EXECUTION_CROSS_CHAIN_MESSAGE_HANDLING.md) and [MULTI_CHAIN_EXECUTION_DETERMINISTIC_DEPLOYMENT](../runbooks/MULTI_CHAIN_EXECUTION_DETERMINISTIC_DEPLOYMENT.md).
|
||||
|
||||
### 3.1 Deterministic Deployment (CREATE2)
|
||||
|
||||
- **Formula:** `address = keccak256(0xff ++ deployer ++ salt ++ keccak256(bytecode))[12:]`.
|
||||
- **Identical bytecode** on every chain (same compiler, no chain-specific branches in bytecode).
|
||||
- **Identical constructor / initializer args** for the core contract; any **chain-specific** config (e.g. CCIP router, relayer list) is set **after** deployment via `initialize()` or setters.
|
||||
|
||||
### 3.2 Suggested Salt and Initialization
|
||||
|
||||
| Item | Value |
|
||||
|------|--------|
|
||||
| **Contract name** | ISO20022IntakeGateway (or equivalent) |
|
||||
| **Salt** | `keccak256("ISO20022IntakeGateway")` (fixed, documented) |
|
||||
| **Constructor** | Minimal (e.g. none) or same admin everywhere |
|
||||
| **initialize(args)** | `admin`, optional `ccipRouter`, optional `relayer`; same `admin` on all chains; `ccipRouter` can be set to 0 and configured per chain later |
|
||||
|
||||
This yields **one canonical intake contract address** across all networks (e.g. 138, 1, 56, 10, 137, 42161, 8453, 43114, and 651940 if supported). Integrators and off-chain gateways can use that single address regardless of chain.
|
||||
|
||||
---
|
||||
|
||||
## 4. Two Ways Messages Reach the Intake Contract
|
||||
|
||||
Messages reach the intake contract in two ways: **direct submission by a relayer** (same chain) or **delivery via a cross-chain protocol** (e.g. CCIP) from another chain.
|
||||
|
||||
### 4.1 Path A: Relayer-Submitted (Same Chain)
|
||||
|
||||
**Flow:**
|
||||
|
||||
1. Off-chain **gateway** receives ISO-20022 MX or SWIFT Fin MT.
|
||||
2. Gateway **parses, validates, and maps** to the **canonical struct** (see methodology doc).
|
||||
3. Gateway (as a **relayer**) calls the intake contract on the **target chain**:
|
||||
- `submitInbound(CanonicalMessage calldata m)` for credits (mint / release), or
|
||||
- `submitOutbound(CanonicalMessage calldata m)` for debits (burn / lock),
|
||||
with the relayer’s EOA or contract holding **RELAYER_ROLE** (or **INTAKE_RELAYER_ROLE**).
|
||||
|
||||
**On-chain:**
|
||||
|
||||
- `msg.sender` must have the relayer role.
|
||||
- Contract checks `processedInstructions[m.instructionId]` (or `processedMessages[m.msgId]`); reverts if already processed.
|
||||
- Contract optionally checks ComplianceGuard / PolicyManager using `m.debtorId`, `m.creditorId`, `m.purpose`.
|
||||
- Contract performs the action (mint, transfer, bridge unlock) and sets `processedInstructions[m.instructionId] = true`.
|
||||
- Contract emits an event with canonical fields for audit and pacs.002/camt.054 mapping.
|
||||
|
||||
**Per-chain:** Only the **relayer address(es)** need to be configured per chain (e.g. different gateway EOA or multisig per network). The intake contract bytecode and address stay the same.
|
||||
|
||||
### 4.2 Path B: Cross-Chain Delivery (e.g. CCIP)
|
||||
|
||||
**Flow:**
|
||||
|
||||
1. On the **source chain**, an authorised sender (e.g. the **same intake contract** at the same address, or a dedicated “sender” contract) encodes the **canonical struct** into `bytes data` and sends a **CCIP** (or other cross-chain) message to the **destination chain**, with **receiver** = intake contract address (same canonical address).
|
||||
2. On the **destination chain**, the **CCIP router** calls the intake contract’s **receive** entry point (e.g. `ccipReceive(Any2EVMMessage calldata message)`).
|
||||
3. The intake contract:
|
||||
- Verifies the call is from the **CCIP router** (or a designated receiver adapter) via `msg.sender == ccipRouter` or a **ROUTER_ROLE** check.
|
||||
- Decodes `message.data` to obtain the **CanonicalMessage**.
|
||||
- Applies **replay protection** using `message.messageId` and/or the decoded `instructionId` (must not already be in `processedMessages` / `processedInstructions`).
|
||||
- Optionally validates **source chain** and **sender** from `message.sourceChainSelector` and `message.sender` (allowlist or “same intake contract on source chain”).
|
||||
- Executes the same logic as Path A (mint / transfer / unlock) and emits the same canonical events.
|
||||
|
||||
**Per-chain:** The **CCIP router address** is chain-specific. It is set in `initialize()` or via `setCCIPRouter(address)` after deployment so that the same bytecode is used everywhere. On chains without CCIP (e.g. 651940), the router can be set to `address(0)` and Path B disabled; only Path A (relayer) is used.
|
||||
|
||||
---
|
||||
|
||||
## 5. Contract Interface (Summary)
|
||||
|
||||
The intake contract exposes at least:
|
||||
|
||||
| Entry point | Caller | Purpose |
|
||||
|-------------|--------|---------|
|
||||
| **submitInbound(CanonicalMessage)** | Relayer (Path A) | Process an inbound credit (mint / release from bridge). |
|
||||
| **submitOutbound(CanonicalMessage)** | Relayer (Path A) | Process an outbound debit (burn / lock for bridge). |
|
||||
| **ccipReceive(Any2EVMMessage)** | CCIP router only (Path B) | Decode payload to CanonicalMessage and process as inbound (or outbound if encoded so). |
|
||||
|
||||
Optional:
|
||||
|
||||
- **setCCIPRouter(address)** – Admin; for deterministic deploy, init with router=0 then set per chain.
|
||||
- **addRelayer(address)** / **removeRelayer(address)** – Admin; manage who can call submitInbound/submitOutbound.
|
||||
|
||||
Idempotency key: **instructionId** (and optionally msgId). Storage: `mapping(bytes32 => bool) public processedInstructions;` and, for CCIP, `mapping(bytes32 => bool) public processedMessages;` keyed by CCIP `messageId` to avoid replay from the transport layer.
|
||||
|
||||
---
|
||||
|
||||
## 6. How It Works on Different Networks (By Chain Type)
|
||||
|
||||
### 6.1 Chains With CCIP (e.g. 138, 1, 56, 10, 137, 42161, 8453, 43114)
|
||||
|
||||
- **Deploy** the intake contract via CREATE2 with the same salt and init args (e.g. admin; router=0).
|
||||
- **Post-deploy:** Call `setCCIPRouter(ccipRouterAddress)` with that chain’s CCIP router.
|
||||
- **Relayer:** Grant RELAYER_ROLE to the gateway(s) that will submit canonical messages on this chain.
|
||||
- **Behaviour:** Both Path A (relayer) and Path B (CCIP) are active. Messages can arrive from off-chain (Path A) or from another chain (Path B) with the same canonical format.
|
||||
|
||||
### 6.2 Chains Without CCIP (e.g. ALL Mainnet 651940)
|
||||
|
||||
- **Deploy** the same contract at the same address via CREATE2 (same salt, same init; no CCIP router).
|
||||
- Leave **CCIP router** as `address(0)` (or never set it). **Path B is unused.**
|
||||
- **Relayer:** Only Path A is used; the off-chain gateway submits canonical messages via `submitInbound` / `submitOutbound` from an address with RELAYER_ROLE.
|
||||
- Optionally, a **custom cross-chain transport** (e.g. AlltraCustomBridge-style) could later call a dedicated function that accepts the same canonical payload, with access control analogous to the CCIP router check.
|
||||
|
||||
### 6.3 Same Address, Different Config
|
||||
|
||||
- **Address:** Identical across all networks (CREATE2 + same bytecode + same constructor/init args).
|
||||
- **Config that can differ per chain:**
|
||||
- CCIP router address (or 0),
|
||||
- Relayer list (RELAYER_ROLE),
|
||||
- Optional: ComplianceGuard / PolicyManager / vault addresses if set via setters after deploy.
|
||||
|
||||
No per-chain address map is needed in application logic; only the single intake contract address is used, and chain-specific behaviour is controlled by which roles and router are set on that chain.
|
||||
|
||||
---
|
||||
|
||||
## 7. Security and Replay
|
||||
|
||||
- **Path A:** Idempotency by `instructionId` (and optionally `msgId`). Only RELAYER_ROLE can submit; relayer identity is per chain.
|
||||
- **Path B:** Replay protection by CCIP `messageId` and by decoded `instructionId`; only the CCIP router (or ROUTER_ROLE) can call `ccipReceive`. Validate source chain and sender if required (e.g. only accept from the same intake contract on allowed source chains).
|
||||
- **Payload integrity:** Optional check of `payloadHash` in the canonical struct against an off-chain attested hash; contract can store or emit it for audit.
|
||||
|
||||
---
|
||||
|
||||
## 8. Downstream Actions
|
||||
|
||||
The intake contract does not hold balances long-term; it **forwards** the intent to:
|
||||
|
||||
- **Mint:** Call token factory or mint controller (with reserve/attestation checks as in [MULTI_CHAIN_EXECUTION_ISO20022_EMONEY](../runbooks/MULTI_CHAIN_EXECUTION_ISO20022_EMONEY.md)).
|
||||
- **Transfer:** Call token `transfer` or a vault that holds tokens.
|
||||
- **Bridge unlock:** Call the bridge/vault contract’s release or unlock function with the same canonical metadata so that bridge and e-money runbooks stay aligned.
|
||||
|
||||
All such downstream calls should carry or emit the same canonical identifiers (instructionId, msgId, debtorId, creditorId, payloadHash) for audit and ISO-20022 reporting.
|
||||
|
||||
---
|
||||
|
||||
## 9. Related Documents
|
||||
|
||||
| Document | Description |
|
||||
|----------|-------------|
|
||||
| [SMART_CONTRACTS_ISO20022_FIN_METHODOLOGY.md](SMART_CONTRACTS_ISO20022_FIN_METHODOLOGY.md) | Canonical format, mapping, validation, and contract interface for ISO/Fin. |
|
||||
| [MULTI_CHAIN_EXECUTION_ISO20022_EMONEY.md](../runbooks/MULTI_CHAIN_EXECUTION_ISO20022_EMONEY.md) | E-Money and ISO-20022 canonical message semantics. |
|
||||
| [MULTI_CHAIN_EXECUTION_CROSS_CHAIN_MESSAGE_HANDLING.md](../runbooks/MULTI_CHAIN_EXECUTION_CROSS_CHAIN_MESSAGE_HANDLING.md) | Cross-chain message handling, same address, replay, sender verification. |
|
||||
| [MULTI_CHAIN_EXECUTION_DETERMINISTIC_DEPLOYMENT.md](../runbooks/MULTI_CHAIN_EXECUTION_DETERMINISTIC_DEPLOYMENT.md) | CREATE2, salts, and deployment order. |
|
||||
|
||||
---
|
||||
|
||||
**Document Control**
|
||||
|
||||
- **Owner:** Configuration / Integration
|
||||
- **Review:** When intake contract interface or supported chains change
|
||||
168
docs/04-configuration/ISO4217_COMPLIANT_TOKEN_MATRIX.md
Normal file
168
docs/04-configuration/ISO4217_COMPLIANT_TOKEN_MATRIX.md
Normal file
@@ -0,0 +1,168 @@
|
||||
# ISO-4217 Compliant Token Matrix (Native + Bridged)
|
||||
|
||||
This matrix formalizes the **symbol construction standard** for compliant ISO-4217 coins/tokens across:
|
||||
|
||||
- **Financial Chains (Native issuance)** using a **6-character** symbol
|
||||
- **Public Chains (Bridged/wrapped issuance)** using a **7-character** symbol where **ISO shifts to positions 4–6**
|
||||
|
||||
---
|
||||
|
||||
## 1. Character-Position Rules
|
||||
|
||||
### A) Native Financial-Chain Symbol (6 characters)
|
||||
|
||||
**Format:** `c` + `[FinChain]` + `[ISO4217]` + `[Type]`
|
||||
|
||||
| Position | Meaning | Allowed Values |
|
||||
| -------: | -------------------------- | ------------------------------------ |
|
||||
| 1 | Compliance prefix | `c` |
|
||||
| 2 | Financial chain designator | See FIN_CHAIN_SET |
|
||||
| 3–5 | ISO-4217 currency code | See ISO4217_SET |
|
||||
| 6 | Asset type | `C` (coin), `T` (token), `W` (D‑WIN) |
|
||||
|
||||
Example: `cAUSDT` = `c` + `A` + `USD` + `T`
|
||||
|
||||
### B) Bridged Public-Chain Symbol (7 characters)
|
||||
|
||||
**Format:** `c` + `W` + `[OriginFinChain]` + `[ISO4217]` + `[Type]`
|
||||
|
||||
| Position | Meaning | Allowed Values |
|
||||
| -------: | --------------------------------- | ------------------------------------ |
|
||||
| 1 | Compliance prefix | `c` |
|
||||
| 2 | Public wrapper class | `W` |
|
||||
| 3 | Origin financial chain designator | See FIN_CHAIN_SET |
|
||||
| 4–6 | ISO-4217 currency code | See ISO4217_SET |
|
||||
| 7 | Asset type | `C` (coin), `T` (token), `W` (D‑WIN) |
|
||||
|
||||
Example: `cWAUSDT` = `c` + `W` + `A` + `USD` + `T`
|
||||
|
||||
---
|
||||
|
||||
## 2. FIN_CHAIN_SET
|
||||
|
||||
| Designator | Chain | Chain ID | Notes |
|
||||
| ---------- | ------------------------------------ | -------- | --------------------------------------------------------------------- |
|
||||
| *(none)* | Chain 138 (DeFi Oracle Meta Mainnet) | 138 | **v0 only:** native symbols omit designator (e.g. `cUSDC`, `cUSDT`) |
|
||||
| `X` | Chain 138 (origin reference only) | 138 | Used only when denoting origin 138 on other chains (e.g. bridged) |
|
||||
| `A` | Alltra Mainnet | 651940 | ALL Mainnet |
|
||||
|
||||
**Chain 138:** On ChainID 138, token symbols are **v0 only** — the chain designator is **left out**. Use `cUSDC`, `cUSDT` (no `X`). The `X` designator is used only for bridged tokens on public chains when the origin is Chain 138 (e.g. `cWXUSDC`). Reserved designators: do not reuse. Add new chains via registry.
|
||||
|
||||
---
|
||||
|
||||
## 3. ISO4217_SET
|
||||
|
||||
Reference: [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217). Supported subset for implementation:
|
||||
|
||||
- **Fiat:** USD, EUR, GBP, JPY, AUD, CHF, CAD, CNY
|
||||
- **Commodity:** XAU (gold)
|
||||
- **Future:** Add codes via registry; validation enforces **3 uppercase letters only** (no 4-letter codes in v1)
|
||||
|
||||
---
|
||||
|
||||
## 4. Validation Rules
|
||||
|
||||
### Native (len = 6)
|
||||
|
||||
- `s[0] == 'c'`
|
||||
- `s[1] in FIN_CHAIN_SET`
|
||||
- `s[2:5] in ISO4217_SET` (positions 2, 3, 4)
|
||||
- `s[5] in {'C','T','W'}`
|
||||
|
||||
### Bridged (len = 7)
|
||||
|
||||
- `s[0] == 'c'`
|
||||
- `s[1] == 'W'`
|
||||
- `s[2] in FIN_CHAIN_SET` (origin chain)
|
||||
- `s[3:6] in ISO4217_SET` (positions 3, 4, 5)
|
||||
- `s[6] in {'C','T','W'}`
|
||||
|
||||
---
|
||||
|
||||
## 5. v0 Symbols (Chain 138 Only)
|
||||
|
||||
On **ChainID 138 only**, compliant token symbols use the **v0 form** with **no chain designator** (the X is left out):
|
||||
|
||||
| v0 Symbol | Identity | Type | Chain |
|
||||
| --------- | -------------- | ----- | ------ |
|
||||
| `cUSDT` | ISO USD, Type T | Token | 138 |
|
||||
| `cUSDC` | ISO USD, Type C | Coin | 138 |
|
||||
|
||||
- These symbols are **maintained only on Chain 138**; they are not used on other chains.
|
||||
- Registry maps v0 → `{ iso, type, originChain: 'X' }` for reporting and for bridged-origin reference; on-chain on 138 the symbol stays `cUSDC` / `cUSDT`.
|
||||
|
||||
---
|
||||
|
||||
## 6. Chain 138: No X in Native Symbols
|
||||
|
||||
- **On Chain 138:** Native token symbols remain **v0** — `cUSDC`, `cUSDT` (no `X`, no designator). Do not use `cXUSDC` or `cXUSDT` on Chain 138.
|
||||
- **X** is used only when referring to Chain 138 as **origin** elsewhere (e.g. bridged tokens on public chains: `cWXUSDC`, `cWXUSDT`).
|
||||
- Registry maps v0 → v1 identity for reporting and validation; the on-chain symbol on 138 does not change.
|
||||
|
||||
---
|
||||
|
||||
## 7. Case Sensitivity
|
||||
|
||||
- Symbols are **case-sensitive**.
|
||||
- Compliance prefix: **lowercase** `c`.
|
||||
- FinChain, ISO4217, Type: **uppercase** (e.g. `A`, `USD`, `T`).
|
||||
|
||||
---
|
||||
|
||||
## 8. Edge Cases
|
||||
|
||||
- **ISO codes:** 3 letters only (A–Z); no 4-letter codes in v1.
|
||||
- **Reserved designators:** `X` (Chain 138), `A` (Alltra); do not reuse.
|
||||
- **Invalid examples:** `cAUSD` (missing type), `cAUSDCX` (7-char without W at position 2).
|
||||
|
||||
---
|
||||
|
||||
## 9. Migration Strategy
|
||||
|
||||
- **Chain 138:** v0 symbols `cUSDT`, `cUSDC` are **maintained only on ChainID 138**; the X is left out. No on-chain symbol change on 138.
|
||||
- **v1 registry:** Maps v0 symbol → `{ iso, type, originChain: 'X' }` for reporting; origin `X` denotes Chain 138 when needed (e.g. bridged).
|
||||
- **New chains:** Use v1 symbols with designator (e.g. `cAUSDT` on Alltra, `cWAUSDT` on public chains).
|
||||
- **Bridged from Chain 138:** Use 7-char with origin X (e.g. `cWXUSDC`, `cWXUSDT`) on public chains only.
|
||||
|
||||
---
|
||||
|
||||
## 10. Matrix Examples
|
||||
|
||||
### Native on Chain 138 (v0 only — no designator)
|
||||
|
||||
| ISO | Coin (`C`) | Token (`T`) |
|
||||
| --- | ---------- | ----------- |
|
||||
| USD | `cUSDC` | `cUSDT` |
|
||||
|
||||
### Native (6-char) — Other financial chains (e.g. Alltra A)
|
||||
|
||||
| ISO | Coin (`C`) | Token (`T`) | D‑WIN (`W`) |
|
||||
| --- | ---------- | ----------- | ----------- |
|
||||
| USD | `cAUSDC` | `cAUSDT` | `cAUSDW` |
|
||||
| EUR | `cAEURC` | `cAEURT` | `cAEURW` |
|
||||
| GBP | `cAGBPC` | `cAGBPT` | `cAGBPW` |
|
||||
|
||||
### Bridged (7-char) — Public networks
|
||||
|
||||
| ISO | Coin (`C`) | Token (`T`) | D‑WIN (`W`) |
|
||||
| --- | ---------- | ----------- | ----------- |
|
||||
| USD | `cWXUSDC` | `cWXUSDT` | `cWXUSDW` |
|
||||
| USD | `cWAUSDC` | `cWAUSDT` | `cWAUSDW` |
|
||||
| EUR | `cWAEURC` | `cWAEURT` | `cWAEURW` |
|
||||
|
||||
---
|
||||
|
||||
## 11. Chain-Context Mapping
|
||||
|
||||
- **Chain 138:** Native symbols are **v0 only** (no X): `cUSDC`, `cUSDT`. No 6-char form with X is used on Chain 138.
|
||||
- **Other financial chains:** Native symbols use 6-char with designator (e.g. Alltra `cAUSDC`, `cAUSDT`).
|
||||
- **Bridged symbols** (7-char) live on **Public chains** (Ethereum, Base, Polygon, etc.); use `cWXUSDC` when origin is Chain 138.
|
||||
- Chain specificity remains defined by **chainId + contract address**; the symbol encodes **class + origin** (except v0 on 138, which encodes class only).
|
||||
|
||||
---
|
||||
|
||||
## References
|
||||
|
||||
- [CHAIN138_TOKEN_ADDRESSES.md](../11-references/CHAIN138_TOKEN_ADDRESSES.md) — v0 symbol mapping
|
||||
- [TOKEN_SCOPE_GRU.md](../../smom-dbis-138/docs/tokenization/TOKEN_SCOPE_GRU.md) — token scope
|
||||
- [GRU_M00_DIAMOND_FACET_MAP.md](GRU_M00_DIAMOND_FACET_MAP.md) — canonical symbol grammar §5
|
||||
42
docs/04-configuration/MAINNET_RAMP_USER_FLOWS.md
Normal file
42
docs/04-configuration/MAINNET_RAMP_USER_FLOWS.md
Normal file
@@ -0,0 +1,42 @@
|
||||
# On-Ramp and Off-Ramp User Flows (Mainnet ↔ Chain 138)
|
||||
|
||||
**Purpose:** Document the recommended user flows for fiat on-ramp and off-ramp when using mainnet liquidity and third-party bridges. Companion/dApp copy and links should point here.
|
||||
|
||||
**Related:** [MAINNET_LIQUIDITY_AND_RAMPS_PRIORITY](../00-meta/MAINNET_LIQUIDITY_AND_RAMPS_PRIORITY.md) | [METAMASK_BRIDGE_SWAP](../../smom-dbis-138/docs/operations/integrations/METAMASK_BRIDGE_SWAP.md)
|
||||
|
||||
---
|
||||
|
||||
## On-ramp (Fiat → Crypto on Chain 138)
|
||||
|
||||
**Flow:** User buys on a supported chain (e.g. Ethereum Mainnet) via ramp, then bridges to Chain 138.
|
||||
|
||||
| Step | User action |
|
||||
|------|-------------|
|
||||
| 1 | Open companion/dApp and choose **Buy** (on-ramp). |
|
||||
| 2 | Select **Ethereum Mainnet** (or another ramp-supported chain). Complete purchase via ramp provider (MoonPay, Ramp, etc.) — funds arrive on mainnet. |
|
||||
| 3 | Switch to **Bridge** and send assets **Mainnet → Chain 138** using a supported bridge (trustless or third-party). |
|
||||
| 4 | Receive assets on Chain 138; use for gas, swaps, or dApps. |
|
||||
|
||||
**Operator:** Ensure ramp API keys are set and mainnet is funded so bridges can operate. Ramp API: `POST /ramps/on-ramp/session` with `chainId: 1`.
|
||||
|
||||
---
|
||||
|
||||
## Off-ramp (Crypto on Chain 138 → Fiat)
|
||||
|
||||
**Flow:** User bridges from Chain 138 to Mainnet, then sells on mainnet via off-ramp.
|
||||
|
||||
| Step | User action |
|
||||
|------|-------------|
|
||||
| 1 | On Chain 138, open **Bridge** and send assets **Chain 138 → Ethereum Mainnet**. |
|
||||
| 2 | Wait for bridge confirmation; assets arrive on user’s mainnet address. |
|
||||
| 3 | Open companion/dApp and choose **Sell** (off-ramp). Select **Ethereum Mainnet** and complete sale via ramp provider. |
|
||||
| 4 | Fiat is sent to user’s linked bank/payment method per provider terms. |
|
||||
|
||||
**Operator:** Mainnet liquidity (LiquidityPoolETH and/or Relay Bridge) must be funded so 138→mainnet payouts succeed. Ramp API: `POST /ramps/off-ramp/session` with `chainId: 1`.
|
||||
|
||||
---
|
||||
|
||||
## Where to link in companion/dApp
|
||||
|
||||
- **Buy (on-ramp):** Link to this doc or a short in-app guide: “Buy on Ethereum → Bridge to Chain 138.”
|
||||
- **Sell (off-ramp):** Link to this doc or a short in-app guide: “Bridge to Ethereum → Sell on mainnet.”
|
||||
140
docs/04-configuration/MIGRATION_PLAN_R630_01_DATA.md
Normal file
140
docs/04-configuration/MIGRATION_PLAN_R630_01_DATA.md
Normal file
@@ -0,0 +1,140 @@
|
||||
# Migration Plan: r630-01 Data Pool (72% → target <70%)
|
||||
|
||||
**Last updated:** 2026-02-28
|
||||
|
||||
**Phase 1 completed (2026-02-28):** Migrated 8 CTs from data → thin1 on r630-01. **data** now **65.8%** (was 72%); **thin1** 50.6% (was 43.5%). Migrated VMIDs: 10233, 10120, 10100, 10101, 10235, 10236, 7804, 8640.
|
||||
|
||||
Goal: Reduce r630-01 **data** pool usage (currently ~65.8%, 280G pool) so it stays below 85% and has headroom. Options: move CTs to **r630-01 thin1** (same host) or to **r630-02 thin5** (cross-host).
|
||||
|
||||
---
|
||||
|
||||
## 1. Current layout (r630-01)
|
||||
|
||||
| Pool | Size | Used% | Free (approx) | Notes |
|
||||
|-------|-------|-------|----------------|-------|
|
||||
| **data** | 280G | **65.8%** ✓ | ~100G | After Phase 1 migrations; target <70% met. |
|
||||
| **thin1** | 208G | 50.6% | ~107G | Now holds migrated CTs from Phase 1. |
|
||||
|
||||
**CTs on data (by size, VMID = container):**
|
||||
|
||||
| VMID | Allocated | Role / name (typical) | Migration priority |
|
||||
|-------|-----------|------------------------|--------------------|
|
||||
| 2500–2505 | 200G each | RPC (alltra etc.) | Low (critical RPC); move only if needed. |
|
||||
| 2101 | 200G | Core RPC | **Do not move** (deploy/admin). |
|
||||
| 1000, 1001, 1002 | 100G each | Validators | **Do not move** (consensus). |
|
||||
| 1500, 1501, 1502 | 100G each | Sentries | Prefer stay; move only if necessary. |
|
||||
| 10130, 10150, 10151 | 50–100G | Services | Good candidates (Phase 2). |
|
||||
| 8640, 8642 | 50G each | Services | Good candidates. |
|
||||
| 7804 | 20G | Gov/portal | Good candidate. |
|
||||
| 10235, 10236 | 10–20G | Small services | Good candidates. |
|
||||
| 10232, 10233 | 1–3G | Small | Easy wins. |
|
||||
| 10100, 10101 | 8G each | Small | Easy wins. |
|
||||
| 10120 | 4G | Small | Easy win. |
|
||||
|
||||
---
|
||||
|
||||
## 2. Migration options
|
||||
|
||||
### Option A: Same host — data → thin1 (r630-01)
|
||||
|
||||
- **Pros:** No node change; no IP/network change; quick (stop → vzdump → destroy → restore to thin1 → start).
|
||||
- **Cons:** thin1 has ~118G free; cannot move all 200G CTs without exceeding thin1.
|
||||
- **Best for:** Smaller CTs (total ~50–80G) to free space on data without touching validators/core RPC.
|
||||
|
||||
### Option B: Cross host — r630-01 → r630-02 thin5
|
||||
|
||||
- **Pros:** thin5 is empty (237G); can move one or two large CTs (e.g. 200G each).
|
||||
- **Cons:** Node migration (IP may change unless static); service dependency and DNS/load balancer updates.
|
||||
- **Best for:** One or two 200G RPC CTs (e.g. 2503, 2504, 2505) if you need to free a lot of data in one go.
|
||||
|
||||
---
|
||||
|
||||
## 3. Recommended phases
|
||||
|
||||
### Phase 1 — Same host (data → thin1)
|
||||
|
||||
**Goal:** Free ~50–80G on data (get data from 72% to ~55–60%) by moving smaller CTs to thin1.
|
||||
|
||||
**Candidates (order by size, smaller first for low risk):**
|
||||
|
||||
1. 10232 (1G), 10233 (3G), 10120 (4G)
|
||||
2. 10100 (8G), 10101 (8G), 10235 (10G)
|
||||
3. 10236 (20G), 7804 (20G)
|
||||
4. Optionally one of: 8640 (50G), 8642 (50G), or 10130 (50G)
|
||||
|
||||
**Steps per CT (run on r630-01 or via SSH):**
|
||||
|
||||
```bash
|
||||
# On r630-01 (192.168.11.11). Replace VMID with actual (e.g. 10232).
|
||||
VMID=10232
|
||||
ssh root@192.168.11.11 bash -s << 'EOF'
|
||||
set -e
|
||||
pct stop $VMID
|
||||
vzdump $VMID --storage local --compress gzip --mode stop --remove 0
|
||||
BACKUP=$(ls -t /var/lib/vz/dump/vzdump-lxc-$VMID-*.tar.gz | head -1)
|
||||
pct destroy $VMID --force
|
||||
pct restore $VMID $BACKUP --storage thin1
|
||||
rm -f $BACKUP
|
||||
pct start $VMID
|
||||
EOF
|
||||
```
|
||||
|
||||
**Automation:** Run for each VMID:
|
||||
```bash
|
||||
bash scripts/maintenance/migrate-ct-r630-01-data-to-thin1.sh <VMID> # e.g. 10232
|
||||
bash scripts/maintenance/migrate-ct-r630-01-data-to-thin1.sh 10232 --dry-run # preview
|
||||
```
|
||||
Suggested order: 10232, 10233, 10120, 10100, 10101, 10235, 10236, 7804, then 8640 or 8642.
|
||||
|
||||
---
|
||||
|
||||
### Phase 2 — If data still >70%: move one large CT to r630-02 thin5
|
||||
|
||||
**Goal:** Free ~200G on r630-01 data by migrating one 200G CT to r630-02 and placing it on thin5.
|
||||
|
||||
**Candidates:** 2503, 2504, or 2505 (non–core RPC; confirm which can be moved without breaking dependencies).
|
||||
|
||||
**Steps:**
|
||||
|
||||
1. **Confirm** the CT can run on r630-02 (network, DNS, NPM proxy, etc.).
|
||||
2. **Migrate** (cross-node):
|
||||
`pct migrate <VMID> r630-02 --storage thin5`
|
||||
Or: backup on r630-01, copy backup to r630-02, restore on r630-02 with `--storage thin5`, then destroy on r630-01.
|
||||
3. **Update** any static IPs, DNS, or proxy config pointing to the old host.
|
||||
4. **Verify** service and re-run `audit-proxmox-rpc-storage.sh`.
|
||||
|
||||
---
|
||||
|
||||
## 4. Scripts to use / create
|
||||
|
||||
| Action | Script / command |
|
||||
|--------|-------------------|
|
||||
| List CTs on data | `ssh root@192.168.11.11 'lvs -o lv_name,lv_size,pool_lv --noheadings pve \| grep " data "'` |
|
||||
| Same-host migration (data → thin1) | New script or inline: `vzdump` → `pct destroy` → `pct restore --storage thin1` → `pct start` |
|
||||
| Cross-host migration | `pct migrate <VMID> r630-02 --storage thin5` (or backup/restore to r630-02). |
|
||||
| Verify after | `bash scripts/audit-proxmox-rpc-storage.sh` and `pvesm status` on both hosts. |
|
||||
|
||||
---
|
||||
|
||||
## 5. Checklist before migration
|
||||
|
||||
- [ ] Backup or snapshot critical CTs before Phase 1.
|
||||
- [ ] Run prune on r630-01 data CTs again if not done recently: `fix-storage-r630-01-and-thin5.sh`.
|
||||
- [ ] Ensure no critical operations (deploy, consensus) during the migration window.
|
||||
- [ ] For Phase 2: document which VMID is moved and update DNS/NPM/load balancer.
|
||||
|
||||
---
|
||||
|
||||
## 6. Success criteria
|
||||
|
||||
- **Phase 1:** r630-01 data pool <70% (ideally 55–65%); thin1 still <75%.
|
||||
- **Phase 2 (if run):** r630-01 data <65%; r630-02 thin5 used by migrated CT(s); all services verified.
|
||||
|
||||
---
|
||||
|
||||
## 7. Reference
|
||||
|
||||
- **r630-01 data:** 280G, 72% used; LVs: 1000, 1001, 1002, 1500–1502, 2101, 2500–2505, 10100, 10101, 10120, 10130, 10150, 10151, 10232, 10233, 10235, 10236, 7804, 8640, 8642.
|
||||
- **r630-01 thin1:** 208G, 43.5% used; ~118G free.
|
||||
- **r630-02 thin5:** 237G, 0% used (empty).
|
||||
- Storage docs: `STORAGE_RECOMMENDATIONS_BY_FILL_RATE.md`, `PHYSICAL_DRIVES_AND_CONFIG.md`.
|
||||
69
docs/04-configuration/PHYSICAL_DRIVES_AND_CONFIG.md
Normal file
69
docs/04-configuration/PHYSICAL_DRIVES_AND_CONFIG.md
Normal file
@@ -0,0 +1,69 @@
|
||||
# Physical Drives and Current Configurations — All Three Proxmox Hosts
|
||||
|
||||
**Last updated:** 2026-02-28
|
||||
|
||||
---
|
||||
|
||||
## ml110 (192.168.11.10)
|
||||
|
||||
| Device | Size | Model | Serial | Configuration |
|
||||
|--------|--------|------------------------|----------|----------------|
|
||||
| **sda** | 931.5G | ST1000DM003-1ER162 (HDD) | Z4YE0TMR | Partitioned: sda1 (1M), sda2 (1G vfat /boot/efi), sda3 (930.5G LVM2). VG **pve**: swap 8G, root 96G ext4 `/`, **data** thin pool 794G (CTs 1003, 1004, 1503–1508, 2102, 2301, 2304–2308, 2400, 2402, 2403). |
|
||||
| **sdb** | 931.5G | ST1000DM003-1ER162 (HDD) | Z4YDLPZ3 | **In VG pve** — extended `data` thin pool (data_tdata). Pool now ~1.7 TB total. |
|
||||
|
||||
**RAID:** None.
|
||||
|
||||
**Summary:** 2× 1TB HDDs. Both in use: sda (OS + original data pool); sdb added to pve and used to extend the data thin pool (~930G added). Data/local-lvm pool now ~1.7 TB.
|
||||
|
||||
---
|
||||
|
||||
## r630-01 (192.168.11.11)
|
||||
|
||||
| Device | Size | Model | Serial | Configuration |
|
||||
|--------|--------|-------------------|--------------|----------------|
|
||||
| **sda** | 558.9G | HUC109060CSS600 (SSD) | KSKUZEZF | Partitioned: sda1 (1M), sda2 (1G vfat), sda3 (557G **zfs_member**). ZFS used for Proxmox root (rpool). |
|
||||
| **sdb** | 558.9G | HUC109060CSS600 (SSD) | KSKM1B4F | Same layout as sda — ZFS mirror partner for root. |
|
||||
| **sdc** | 232.9G | CT250MX500SSD1 (SSD) | 2203E5FE090E | Member of **md0** (RAID10). |
|
||||
| **sdd** | 232.9G | CT250MX500SSD1 | 2203E5FE08F8 | Member of **md0** (RAID10). |
|
||||
| **sde** | 232.9G | CT250MX500SSD1 | 2203E5FE08FA | Member of **md0** (RAID10). |
|
||||
| **sdf** | 232.9G | CT250MX500SSD1 | 2203E5FE08F1 | Member of **md0** (RAID10). |
|
||||
| **sdg** | 232.9G | CT250MX500SSD1 | 2203E5FE095E | Member of **md0** (RAID10). |
|
||||
| **sdh** | 232.9G | CT250MX500SSD1 | 2203E5FE0901 | Member of **md0** (RAID10). |
|
||||
|
||||
**RAID:** **md0** = RAID10, 6× 233G SSDs → **~698G** usable. State: **active**, 6/6 devices [UUUUUU].
|
||||
|
||||
**LVM on md0:** VG **pve** (single PV `/dev/md0`). Thin pools: **pve-thin1** 208G, **pve-data** 280G. Hosts CTs for validators, RPC 2101, 2500–2505, 1000–1002, 1500–1502, 7800–7804, 10130, 10150–10151, 10200–10236, 3000–3501, 100–105, 130, etc.
|
||||
|
||||
**Summary:** 2× 559G SSDs (ZFS root) + 6× 233G SSDs (RAID10 → LVM data/thin1). All drives in use.
|
||||
|
||||
---
|
||||
|
||||
## r630-02 (192.168.11.12)
|
||||
|
||||
| Device | Size | Model | Serial | Configuration |
|
||||
|--------|--------|-------------------|--------------|----------------|
|
||||
| **sda** | 232.9G | CT250MX500SSD1 | 2202E5FB4CB9 | Partitioned: sda1 (1M), sda2 (1G vfat), sda3 (231G **zfs_member**). ZFS for Proxmox root. |
|
||||
| **sdb** | 232.9G | CT250MX500SSD1 | 2203E5FE090D | Same — ZFS mirror for root. |
|
||||
| **sdc** | 232.9G | CT250MX500SSD1 | 2203E5FE07E1 | sdc3 → LVM VG **thin2** (thin pool → VMIDs 5000, 6000, 6001, 6002). |
|
||||
| **sdd** | 232.9G | CT250MX500SSD1 | 2202E5FB186E | sdd3 → LVM VG **thin3** (VMIDs 5800, 10237, 8641, 5801). |
|
||||
| **sde** | 232.9G | CT250MX500SSD1 | 2203E5FE0905 | sde3 → LVM VG **thin4** (VMIDs 7810, 7811). |
|
||||
| **sdf** | 232.9G | CT250MX500SSD1 | 2203E5FE0964 | sdf3 → LVM VG **thin5** (empty pool after 5000 migrated to thin2). |
|
||||
| **sdg** | 232.9G | CT250MX500SSD1 | 2203E5FE0928 | sdg3 → LVM VG **thin6** (VMIDs 5700, 6400, 6401, 6402). |
|
||||
| **sdh** | 232.9G | CT250MX500SSD1 | 2203E5FE0903 | sdh3 → LVM VG **thin1** (thin1-r630-02: 2201, 2303, 2401, 5200–5202, 6200, 10234). |
|
||||
|
||||
**RAID:** None (each data disk is a separate LVM PV).
|
||||
|
||||
**Summary:** 2× 233G SSDs (ZFS root) + 6× 233G SSDs (each its own VG: thin1–thin6). All 8 drives in use.
|
||||
|
||||
---
|
||||
|
||||
## Quick reference
|
||||
|
||||
| Host | Physical drives | Layout | Unused / notes |
|
||||
|---------|------------------|--------|-----------------|
|
||||
| ml110 | 2× 1TB HDD | sda: OS+LVM data; sdb: LVM PV only | **sdb** — 931G not in any VG |
|
||||
| r630-01 | 2× 559G + 6× 233G SSD | ZFS root + RAID10 md0 → LVM | All in use |
|
||||
| r630-02 | 2× 233G + 6× 233G SSD | ZFS root + 6× single-disk LVM (thin1–thin6) | All in use |
|
||||
|
||||
To re-check:
|
||||
`ssh root@<host> 'lsblk -o NAME,SIZE,TYPE,FSTYPE,MODEL,SERIAL; echo; pvs; vgs'`
|
||||
@@ -0,0 +1,120 @@
|
||||
# Price Feed for Chain 138 — MetaMask and All Wallets
|
||||
|
||||
**Last Updated:** 2026-02-28
|
||||
**Purpose:** Single reference for adding Chain 138 USD price feeds to MetaMask and other wallets
|
||||
|
||||
---
|
||||
|
||||
## 1. Current State
|
||||
|
||||
| Wallet / Platform | Chain 138 USD Display | Cause |
|
||||
|-------------------|------------------------|-------|
|
||||
| **MetaMask** | ❌ $0.00 / "No conversion rate available" | MetaMask uses **CoinGecko API** (primary) and **LavaPack** for prices; Chain 138 is not in their supported chains |
|
||||
| **Trust Wallet** | ❌ Likely no USD | Trust Wallet also pulls from CoinGecko/CMC |
|
||||
| **Ledger Live** | ❌ Awaiting integration | Ledger form submitted; awaiting response |
|
||||
| **Other wallets** | ❌ Most use CoinGecko/CMC | Chain 138 not listed |
|
||||
|
||||
**Important:** MetaMask does **not** query on-chain oracle contracts for USD display. Even with a working ETH/USD oracle on Chain 138 (`0x3304b747e565a97ec8ac220b0b6a1f6ffdb837e6`), MetaMask will not show native USD until Chain 138 and tokens are listed on CoinGecko (or MetaMask’s provider adds support).
|
||||
|
||||
---
|
||||
|
||||
## 2. Paths to Add Price Feeds
|
||||
|
||||
### 2.1 CoinGecko (Primary — MetaMask and many wallets)
|
||||
|
||||
**Why:** MetaMask’s primary price source is CoinGecko. CoinGecko is also used by Trust Wallet, DeFi dashboards, and many other wallets.
|
||||
|
||||
**Steps:**
|
||||
1. **Chain submission (if applicable):** Request Chain 138 (DeFi Oracle Meta Mainnet) be added as a supported blockchain.
|
||||
2. **Token submission:** Submit each token (cUSDT, cUSDC, WETH, ETH, etc.) with contract address, chain ID 138, decimals, logo.
|
||||
3. **Form:** https://www.coingecko.com/en/request or https://www.coingecko.com/en/coins/new
|
||||
|
||||
**Docs:** [COINGECKO_SUBMISSION_GUIDE](coingecko/COINGECKO_SUBMISSION_GUIDE.md), [COINGECKO_SUBMISSION_PACKAGE](coingecko/COINGECKO_SUBMISSION_PACKAGE.md), [CMC_COINGECKO_SUBMISSION_RUNBOOK](coingecko/CMC_COINGECKO_SUBMISSION_RUNBOOK.md)
|
||||
|
||||
**Export data:** Use token-aggregation report API:
|
||||
```bash
|
||||
curl "https://<your-api>/api/v1/report/coingecko?chainId=138" -o report-coingecko-138.json
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 2.2 CoinMarketCap (CMC)
|
||||
|
||||
**Why:** Some wallets and aggregators use CMC as a fallback or primary source.
|
||||
|
||||
**Steps:** Same process as CoinGecko — submit chain and tokens via CMC’s listing forms.
|
||||
|
||||
**Export:** `GET /api/v1/report/cmc?chainId=138`
|
||||
|
||||
---
|
||||
|
||||
### 2.3 Consensys / MetaMask Direct Outreach
|
||||
|
||||
**Why:** MetaMask may add Chain 138 to their native price feed if Consensys approves.
|
||||
|
||||
**Steps:**
|
||||
1. Contact: **business@consensys.io**
|
||||
2. Request: Add Chain 138 (DeFi Oracle Meta Mainnet) to MetaMask’s price feed provider.
|
||||
3. Provide: Chain ID 138, RPC URLs, explorer, token list, oracle contract address if relevant.
|
||||
|
||||
**Status:** Outreach form submitted; awaiting response. No public PR repo for Swaps/Bridge/price feed.
|
||||
|
||||
**Ref:** [REPOSITORIES_AND_PRS_CHAIN138](../../00-meta/REPOSITORIES_AND_PRS_CHAIN138.md)
|
||||
|
||||
---
|
||||
|
||||
### 2.4 On-Chain Oracle (dApps, not meta-wallet)
|
||||
|
||||
**For dApps and custom UIs:** You can query the Chain 138 ETH/USD oracle directly:
|
||||
|
||||
| Property | Value |
|
||||
|----------|-------|
|
||||
| **Oracle Proxy** | `0x3304b747e565a97ec8ac220b0b6a1f6ffdb837e6` |
|
||||
| **RPC** | `https://rpc-http-pub.d-bis.org` |
|
||||
| **Method** | `latestRoundData()` → answer in 8 decimals |
|
||||
|
||||
**Docs:** [ORACLE_PRICE_FEED_SETUP](metamask/ORACLE_PRICE_FEED_SETUP.md)
|
||||
|
||||
---
|
||||
|
||||
### 2.5 Chain 138 Snap (Workaround)
|
||||
|
||||
**For MetaMask users:** The Chain 138 Snap provides market data via the token-aggregation API. Users can:
|
||||
|
||||
- Open the Snap companion site (e.g. https://explorer.d-bis.org/snap/)
|
||||
- Use **"Show market data"** or **"Fetch market summary"** to see USD prices
|
||||
|
||||
This does **not** change MetaMask’s native balance display; it is a separate UX flow.
|
||||
|
||||
---
|
||||
|
||||
## 3. Action Checklist
|
||||
|
||||
| # | Action | Owner | Doc |
|
||||
|---|--------|-------|-----|
|
||||
| 1 | Submit Chain 138 to CoinGecko (chain listing) | You | [COINGECKO_SUBMISSION_PACKAGE](coingecko/COINGECKO_SUBMISSION_PACKAGE.md) |
|
||||
| 2 | Submit tokens (cUSDT, cUSDC, WETH, etc.) to CoinGecko | You | [COINGECKO_SUBMISSION_GUIDE](coingecko/COINGECKO_SUBMISSION_GUIDE.md) |
|
||||
| 3 | Submit Chain 138 and tokens to CoinMarketCap | You | [CMC_COINGECKO_SUBMISSION_RUNBOOK](coingecko/CMC_COINGECKO_SUBMISSION_RUNBOOK.md) |
|
||||
| 4 | Follow up Consensys outreach | You | [REPOSITORIES_AND_PRS_CHAIN138](../../00-meta/REPOSITORIES_AND_PRS_CHAIN138.md) |
|
||||
| 5 | Ensure token-aggregation report API is reachable | Ops | [TOKEN_AGGREGATION_REPORT_API_RUNBOOK](TOKEN_AGGREGATION_REPORT_API_RUNBOOK.md) |
|
||||
| 6 | Prepare 512×512 PNG logos for each token | You | [prepare-token-logos-512x512.sh](coingecko/scripts/prepare-token-logos-512x512.sh) or [COINGECKO_SUBMISSION_GUIDE](coingecko/COINGECKO_SUBMISSION_GUIDE.md) §Step 1 |
|
||||
|
||||
---
|
||||
|
||||
## 4. Prerequisites
|
||||
|
||||
- **Token-aggregation API:** Running and reachable; `GET /api/v1/report/coingecko?chainId=138` and `GET /api/v1/report/cmc?chainId=138` return valid JSON.
|
||||
- **Token logos:** 512×512 PNG for each token you submit.
|
||||
- **Chain details:** Chain name, Chain ID 138, RPC URLs, explorer, native currency (see [COINGECKO_SUBMISSION_PACKAGE](coingecko/COINGECKO_SUBMISSION_PACKAGE.md)).
|
||||
|
||||
**Note:** CoinGecko and CMC may not list ChainID 138 or 651940 until they add the chain. The report API remains the source of truth; submit when ready and keep the runbook for when platforms add support.
|
||||
|
||||
---
|
||||
|
||||
## 5. Related Docs
|
||||
|
||||
- [TOKEN_AGGREGATION_REPORT_API_RUNBOOK](TOKEN_AGGREGATION_REPORT_API_RUNBOOK.md) — Ensure report API is reachable
|
||||
- [ORACLE_PRICE_FEED_SETUP](metamask/ORACLE_PRICE_FEED_SETUP.md) — On-chain oracle, MetaMask limitation
|
||||
- [CHAIN138_SNAP_TROUBLESHOOTING](../../../metamask-integration/chain138-snap/docs/CHAIN138_SNAP_TROUBLESHOOTING.md) — Main balance USD display
|
||||
- [REPOSITORIES_AND_PRS_CHAIN138](../../00-meta/REPOSITORIES_AND_PRS_CHAIN138.md) — Ledger, Trust, Consensys, CoinGecko/CMC
|
||||
- [CMC_COINGECKO_REPORTING](../../../smom-dbis-138/services/token-aggregation/docs/CMC_COINGECKO_REPORTING.md) — Report API reference
|
||||
171
docs/04-configuration/PR_ADDITIONS_VALIDATION_REPORT.md
Normal file
171
docs/04-configuration/PR_ADDITIONS_VALIDATION_REPORT.md
Normal file
@@ -0,0 +1,171 @@
|
||||
# PR Additions Validation Report — Format and Content Checks
|
||||
|
||||
**Last Updated:** 2026-02-28
|
||||
**Purpose:** Double-check formatting and content for each PR addition before submission.
|
||||
|
||||
---
|
||||
|
||||
## 1. Token List (dbis-138.tokenlist.json) — tokenlists.org / Uniswap schema
|
||||
|
||||
### Schema requirements (from tokenlist.schema.json)
|
||||
|
||||
| Field | Requirement | Our value | Status |
|
||||
|-------|--------------|-----------|--------|
|
||||
| **name** | string, 1–30 chars, pattern `^[\w ]+$` | "DBIS Chain 138 Token List" (24 chars) | ✅ |
|
||||
| **timestamp** | date-time format | "2026-02-16T00:00:00.000Z" | ✅ |
|
||||
| **version** | { major, minor, patch } | { 1, 3, 0 } | ✅ |
|
||||
| **tokens** | array, 1–10000 items | 6 tokens | ✅ |
|
||||
| **token.chainId** | integer, min 1 | 138 | ✅ |
|
||||
| **token.address** | checksummed 0x hex or Solana | Must be EIP-55 | ⚠️ Verify |
|
||||
| **token.decimals** | 0–255 | 6, 8, 18 | ✅ |
|
||||
| **token.name** | max 60 chars | All valid | ✅ |
|
||||
| **token.symbol** | max 20 chars, `^\S+$` | ETH-USD, WETH, etc. | ✅ |
|
||||
| **tags** (in tokens) | must exist in list-level tags | oracle, pricefeed, defi, wrapped, stablecoin, compliant, ccip | ✅ |
|
||||
| **logoURI** | format uri | https://... | ✅ |
|
||||
|
||||
### Issues to fix
|
||||
|
||||
1. **ETH/USD Price Feed** — Oracle contract at `0x3304b747E565a97ec8AC220b0B6A1f6ffDB837e6` is not a standard ERC20; tokenlists.org typically lists ERC20 tokens. Consider removing or confirming it's acceptable.
|
||||
2. **Address checksums** — Run `cast to-checksum-address` for each address to ensure EIP-55. WETH10: CHAIN138_TOKEN_ADDRESSES has `0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9f` (lowercase f); token list has `0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9F` (uppercase F). One is wrong.
|
||||
3. **tokenMap** — Schema allows optional `tokenMap`; our list omits it. Optional, no change needed.
|
||||
|
||||
### Validation command
|
||||
|
||||
```bash
|
||||
cd /home/intlc/projects/token-lists && npm install && npx ajv validate -s src/tokenlist.schema.json -d /home/intlc/projects/proxmox/token-lists/lists/dbis-138.tokenlist.json
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. Chainlist (eip155-138.json) — ethereum-lists/chains
|
||||
|
||||
### Schema requirements (chainSchema.json)
|
||||
|
||||
| Field | Required | Our value | Status |
|
||||
|-------|----------|-----------|--------|
|
||||
| **name** | ✅ | "Defi Oracle Meta Mainnet" | ✅ |
|
||||
| **shortName** | ✅ | "dfio-meta-main" — pattern `^[A-Za-z0-9-_]{1,64}$` | ✅ |
|
||||
| **chain** | ✅ | "dfiometa" | ✅ |
|
||||
| **chainId** | ✅ | 138 | ✅ |
|
||||
| **networkId** | ✅ | 1 | ⚠️ Verify |
|
||||
| **rpc** | ✅ | array of strings | ✅ |
|
||||
| **faucets** | ✅ | [] | ✅ |
|
||||
| **infoURL** | ✅ | "https://d-bis.org" | ✅ |
|
||||
| **nativeCurrency** | ✅ | { name, symbol, decimals } | ✅ |
|
||||
| **icon** | ❌ | "defioraclemeta" | ⚠️ Requires icon file |
|
||||
|
||||
### Issues to fix
|
||||
|
||||
1. **networkId** — Currently `1`. Most EVM mainnets use `networkId === chainId`. Chain 138 may use networkId 138; verify from chain config. If wrong, change to `138`.
|
||||
2. **icon** — Using `"icon": "defioraclemeta"` requires `_data/icons/defioraclemeta.json` to exist. Format:
|
||||
```json
|
||||
[{"url":"ipfs://Qm...","width":1000,"height":1628,"format":"png"}]
|
||||
```
|
||||
The URL must be IPFS and retrievable via `ipfs get`. **Option:** Remove `icon` field to avoid needing the icon file (some chains omit it).
|
||||
3. **explorers[].icon** — We don't use explorer icon; OK.
|
||||
4. **Prettier** — Run `npx prettier --write _data/chains/eip155-138.json` before PR.
|
||||
|
||||
### Validation command
|
||||
|
||||
```bash
|
||||
cd /home/intlc/projects/chains
|
||||
cp /home/intlc/projects/proxmox/docs/04-configuration/pr-ready/eip155-138.json _data/chains/
|
||||
./gradlew run
|
||||
npx prettier --write _data/chains/eip155-138.json
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. Trust Wallet (trust-wallet-registry-chain138.json) — wallet-core
|
||||
|
||||
### Registry format (from registry-fields.md)
|
||||
|
||||
| Field | Requirement | Our value | Status |
|
||||
|-------|--------------|-----------|--------|
|
||||
| **id** | lowercase, never change | "dfiometa" | ✅ |
|
||||
| **name** | readable | "Defi Oracle Meta Mainnet" | ✅ |
|
||||
| **coinId** | 10000000 + chainId for EVM clones | 10000138 | ✅ |
|
||||
| **symbol** | native coin | "ETH" | ✅ |
|
||||
| **decimals** | 18 | 18 | ✅ |
|
||||
| **blockchain** | "Ethereum" for EVM | "Ethereum" | ✅ |
|
||||
| **derivation** | path m/44'/60'/0'/0/0 | ✅ | ✅ |
|
||||
| **chainId** | string | "138" | ✅ |
|
||||
| **explorer.sampleTx** | Real tx hash for URL validation | "" | ❌ **MUST FIX** |
|
||||
| **explorer.sampleAccount** | Real address for URL validation | "" | ❌ **MUST FIX** |
|
||||
|
||||
### Issues to fix
|
||||
|
||||
1. **sampleTx** — Must be a real transaction hash from Chain 138. Get from https://explorer.d-bis.org (any recent tx).
|
||||
2. **sampleAccount** — Must be a real address. Use any address that has had activity.
|
||||
|
||||
From registry-fields.md: *"Note that the sample values should include existing IDs, so that the resulting full URL is valid."*
|
||||
|
||||
### How to get sample values
|
||||
|
||||
```bash
|
||||
# From explorer or RPC
|
||||
curl -s "https://explorer.d-bis.org/api/v2/transactions" | jq '.items[0].hash'
|
||||
curl -s "https://explorer.d-bis.org/api/v2/addresses/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2" | jq '.hash'
|
||||
# Or use a known address: 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 (WETH)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. DefiLlama-Adapters — Protocol TVL
|
||||
|
||||
### Not a token list
|
||||
|
||||
DefiLlama adapters return TVL (total value locked), not token lists. Each protocol (e.g. DODO) has an `index.js` exporting `tvl(api)` per chain.
|
||||
|
||||
### Chain 138 support
|
||||
|
||||
- DefiLlama uses chain keys: `ethereum`, `bsc`, `polygon`, `arbitrum`, etc.
|
||||
- Chain 138 is likely **not** a built-in chain key. Check `DefiLlama-Adapters/helper/chains.js` or similar.
|
||||
- If adding DODO on Chain 138, you must:
|
||||
1. Confirm DefiLlama supports chain 138 (may need PR to add chain first)
|
||||
2. Add config entry and tvl logic for the chain key they use (e.g. `chain138` or `defi-oracle-meta`)
|
||||
|
||||
### No PR-ready file
|
||||
|
||||
We do not have a DefiLlama adapter file. Create one only after confirming chain support.
|
||||
|
||||
---
|
||||
|
||||
## Summary — Action Items
|
||||
|
||||
| Addition | File | Status |
|
||||
|----------|------|--------|
|
||||
| **Token list** | dbis-138.tokenlist.json | ✅ WETH10 address fixed to checksum per CHAIN138_TOKEN_ADDRESSES |
|
||||
| **Chainlist** | eip155-138.json | ✅ networkId→138; icon removed (avoids needing _data/icons file) |
|
||||
| **Trust Wallet** | trust-wallet-registry-chain138.json | ✅ sampleTx and sampleAccount added (real tx from explorer) |
|
||||
| **DefiLlama** | N/A | No PR until chain 138 is supported; adapter structure differs |
|
||||
|
||||
---
|
||||
|
||||
## Verification commands (run before PR)
|
||||
|
||||
```bash
|
||||
# Token list (from token-lists repo)
|
||||
cd /home/intlc/projects/token-lists
|
||||
npm install
|
||||
# Validate schema (if ajv available)
|
||||
node -e "
|
||||
const schema = require('./src/tokenlist.schema.json');
|
||||
const list = require('/home/intlc/projects/proxmox/token-lists/lists/dbis-138.tokenlist.json');
|
||||
console.log('name length:', list.name.length, '(max 30)');
|
||||
console.log('tokens:', list.tokens.length);
|
||||
list.tokens.forEach(t => console.log(t.symbol, t.address));
|
||||
"
|
||||
|
||||
# Chains
|
||||
cd /home/intlc/projects/chains
|
||||
cp ../../proxmox/docs/04-configuration/pr-ready/eip155-138.json _data/chains/
|
||||
npx prettier --write _data/chains/eip155-138.json
|
||||
./gradlew run
|
||||
|
||||
# Trust Wallet - use registry id, not chainId
|
||||
# Add entry from pr-ready/trust-wallet-registry-chain138.json to registry.json first
|
||||
. "$HOME/.cargo/env" # if Rust installed via rustup
|
||||
cd /home/intlc/projects/wallet-core
|
||||
./tools/new-evmchain dfiometa # use registry id, NOT 138
|
||||
```
|
||||
@@ -46,6 +46,16 @@ This directory contains setup and configuration guides.
|
||||
|
||||
- **Fireblocks Web3:** Submodule **[fireblocks-integration/](../fireblocks-integration/)** (Gitea: [d-bis/fireblocks-integration](https://gitea.d-bis.org/d-bis/fireblocks-integration)) — Dedicated RPC (VMID 2301), Console/SDK docs, `.env.example`. In-repo copy: [FIREBLOCKS_WEB3_INTEGRATION.md](FIREBLOCKS_WEB3_INTEGRATION.md) (operator/hosting ref).
|
||||
|
||||
**Price feed (MetaMask and all wallets):**
|
||||
- **[PRICE_FEED_CHAIN138_METAMASK_AND_WALLETS.md](PRICE_FEED_CHAIN138_METAMASK_AND_WALLETS.md)** ⭐⭐⭐ - **Single reference** for adding Chain 138 USD prices to MetaMask and wallets: CoinGecko, CMC, Consensys outreach, on-chain oracle, Snap workaround.
|
||||
|
||||
**Explorer tokens and GRU:**
|
||||
- **[EXPLORER_TOKENS_GRU_POLICY.md](EXPLORER_TOKENS_GRU_POLICY.md)** ⭐⭐ - Policy: all c* tokens on [explorer.d-bis.org/tokens](https://explorer.d-bis.org/tokens) must be registered as GRU; token list and registration steps.
|
||||
- **[C_TO_CW_MAPPER_MAPPING.md](C_TO_CW_MAPPER_MAPPING.md)** ⭐⭐ - c* → cW* mapping for mapper: symbol mapping and per-chain address mapping in `config/token-mapping-multichain.json`.
|
||||
|
||||
**DEX and aggregators (Chain 138 tokens and routing):**
|
||||
- **[DEX_AND_AGGREGATORS_CHAIN138_EXPLAINER.md](DEX_AND_AGGREGATORS_CHAIN138_EXPLAINER.md)** ⭐⭐⭐ - Using DEX and aggregators with Chain 138 coins/tokens; routing for DEXs; token-aggregation API, DODO PMM, swap–bridge–swap flows.
|
||||
|
||||
**Chain 138 / Wallets (overview first; all repos in ~/projects/):**
|
||||
- **[CHAIN138_WALLET_REPOSITORIES.md](CHAIN138_WALLET_REPOSITORIES.md)** ⭐⭐⭐ - **Canonical layout:** metamask-integration, LedgerLive, app-ethereum, TrustWallet-Integration each in `~/projects/`. All items **Yes / Completed.**
|
||||
- **[CHAIN138_WALLET_ECOSYSTEM_AND_RATIONALE.md](CHAIN138_WALLET_ECOSYSTEM_AND_RATIONALE.md)** ⭐⭐⭐ - **Why** we have the MetaMask Snap, **why** we need Ledger Live when we already use App-Ethereum, Trust Wallet support; links to all wallet docs.
|
||||
@@ -58,6 +68,37 @@ This directory contains setup and configuration guides.
|
||||
- **[FIXES_PREPARED.md](FIXES_PREPARED.md)** ⭐⭐⭐ - Single checklist of all fixes (required + optional) with copy-paste commands: UDM Pro Alltra/HYBX port forward, Alltra/HYBX 502 diagnosis, NPMplus certs, Explorer SSL, shellcheck, verification re-run.
|
||||
- **[FULL_FIXES_PREPARED.md](FULL_FIXES_PREPARED.md)** ⭐⭐⭐ - Consolidated full fixes: validators & block production, stuck tx, Sentries (1503/1504), RPCs (2301, 2402, 2503–2508), UDM Pro, Alltra/HYBX 502, optional (certs, Explorer SSL, shellcheck, verification). Master table + execution order.
|
||||
|
||||
**Smart contracts & ISO-20022 / Fin messaging:**
|
||||
- **[SMART_CONTRACTS_ISO20022_FIN_METHODOLOGY.md](SMART_CONTRACTS_ISO20022_FIN_METHODOLOGY.md)** ⭐⭐⭐ - Methodology for smart contracts to accept ISO-20022 and SWIFT Fin messages: canonical format, mapping, validation, and contract interface.
|
||||
- **[ISO20022_INTAKE_GATEWAY_CONTRACT_MULTI_NETWORK.md](ISO20022_INTAKE_GATEWAY_CONTRACT_MULTI_NETWORK.md)** ⭐⭐⭐ - How the intake/gateway contract receives ISO messages on different blockchain networks: relayer vs cross-chain (CCIP), same address (CREATE2), per-chain config.
|
||||
- **[GRU_M00_DIAMOND_INSTITUTIONAL_SPEC.md](GRU_M00_DIAMOND_INSTITUTIONAL_SPEC.md)** ⭐⭐⭐ - GRU M00 Diamond institutional spec (§1–§8): topology, storage, facets, governance, markets, Pattern A/B, minimum checklist; token model A and Pattern A locked.
|
||||
- **[GRU_M00_DIAMOND_FACET_MAP.md](GRU_M00_DIAMOND_FACET_MAP.md)** ⭐⭐⭐ - GRU M00 Diamond (ERC-2535) Token Factory: facet map, storage namespaces, governance levels 0–5, canonical symbol grammar (c/a/d, W rules). Whitepaper-ready.
|
||||
- **[GRU_M00_DIAMOND_REVIEW_GAPS_AND_RECOMMENDATIONS.md](GRU_M00_DIAMOND_REVIEW_GAPS_AND_RECOMMENDATIONS.md)** ⭐⭐⭐ - Detailed review: missing components, functional wire-ins, naming alignment (a/d vs ac/vdc/sdc), checklist and recommendations.
|
||||
- **[GRU_M00_DIAMOND_DOCS_REVIEW_GAPS_AND_INCONSISTENCIES.md](GRU_M00_DIAMOND_DOCS_REVIEW_GAPS_AND_INCONSISTENCIES.md)** ⭐⭐ - Review of all GRU M00 Diamond docs: missing refs, link consistency, terminology, and follow-up list.
|
||||
- **[DBIS Rail Technical Spec v1](../dbis-rail/DBIS_RAIL_TECHNICAL_SPEC_V1.md)** ⭐⭐⭐ - Bank-rail settlement and GRU mint orchestration on Chain 138: RootRegistry, ParticipantRegistry, SignerRegistry, SettlementRouter, GRU_MintController, MintAuth lifecycle, EIP-712 signer quorum (3-of-5), replay protection, and audit events.
|
||||
- **[DBIS Rail Rulebook v1](../dbis-rail/DBIS_RAIL_RULEBOOK_V1.md)** ⭐⭐⭐ - Operational and compliance policy: good funds matrix, finality triggers per rail (wire/ACH/cash/internal), accounting sequence and deterministic accountingRef, MintAuth preconditions, reversal and exception handling, signer revocation timing, incident controls, audit and reporting standards.
|
||||
- **[DBIS Rail Security Threat Model v1](../dbis-rail/DBIS_RAIL_SECURITY_THREAT_MODEL_V1.md)** ⭐⭐⭐ - Trust boundaries, authorization/ledger/router/mint/validator/off-chain threat categories, severity classification, mitigations, residual risk, versioning and review cycle.
|
||||
- **[DBIS Rail Regulator-Facing Brief v1](../dbis-rail/DBIS_RAIL_REGULATOR_BRIEF_V1.md)** ⭐⭐⭐ - Institutional narrative for banks, examiners, counsel, risk committees: overview, governance, settlement lifecycle, good funds and finality, controls, risk posture, audit, residual risk disclosure, amendment process.
|
||||
- **[DBIS Rail Audit Readiness Checklist v1](../dbis-rail/DBIS_RAIL_AUDIT_READINESS_CHECKLIST_V1.md)** ⭐⭐⭐ - Pre-audit control verification: mint path, authorization, signer governance, accounting/evidence, router controls, validator layer, emergency controls, documentation integrity.
|
||||
- **[DBIS Rail Audit Readiness Results v1](../dbis-rail/DBIS_RAIL_AUDIT_READINESS_RESULTS_V1.md)** ⭐⭐ - Baseline checklist run: status per section, gaps, and prioritized remediation (rail contracts, mint path lock, tests, ops).
|
||||
- **[DBIS Rail Control Mapping v1](../dbis-rail/DBIS_RAIL_CONTROL_MAPPING_V1.md)** ⭐⭐ - Control IDs mapped to checklist, Spec, Rulebook, and Threat Model for audit and SOC 2 / ISO 27001 alignment.
|
||||
- **[DBIS Rail and Project Completion Master v1](../dbis-rail/DBIS_RAIL_AND_PROJECT_COMPLETION_MASTER_V1.md)** ⭐⭐ - Project and deployment status; full task list (required and optional) for DBIS Rail and project completion.
|
||||
- **[Implementation coordination (transcript 540ae663)](../dbis-rail/IMPLEMENTATION_COORDINATION_WITH_TRANSCRIPT_540AE663.md)** ⭐⭐ - Coordinate implementations with PMM/DEX, tokens, GRU, cW*, deployments; maps Completion Master tasks to done/partial/open.
|
||||
- **[DBIS Rail Ledger Attestation Add-On v1.5](../dbis-rail/DBIS_RAIL_LEDGER_ATTESTATION_ADDON_V1_5.md)** ⭐⭐ - LPA state machine, reversal matrix, signer effectiveFromBlock/revokedAtBlock mandatory.
|
||||
- **[DBIS Rail Conversion Router Spec v1.5](../dbis-rail/DBIS_RAIL_CONVERSION_ROUTER_SPEC_V1_5.md)** ⭐⭐ - SwapAuth, best execution/MEV, quote provenance, venue allowlist, sanctions/AML for swaps.
|
||||
- **[DBIS Rail Stablecoin Policy v1.5](../dbis-rail/DBIS_RAIL_STABLECOIN_POLICY_V1_5.md)** ⭐⭐ - Canonical stablecoin definition, registry, routing and monitoring.
|
||||
- **[DBIS Rail Hash Canonicalization and Test Vectors v1.5](../dbis-rail/DBIS_RAIL_HASH_CANONICALIZATION_AND_TEST_VECTORS_V1_5.md)** ⭐⭐ - LEB/LPA/ISO schemas, canonicalization rules, test vectors.
|
||||
|
||||
**Mainnet liquidity & ramps (priority):**
|
||||
- **[MAINNET_RAMP_USER_FLOWS.md](MAINNET_RAMP_USER_FLOWS.md)** ⭐⭐ - On-ramp (buy on mainnet → bridge to 138) and off-ramp (138→mainnet → sell) user flows. Companion/dApp link target.
|
||||
- **Priority plan:** [MAINNET_LIQUIDITY_AND_RAMPS_PRIORITY.md](../00-meta/MAINNET_LIQUIDITY_AND_RAMPS_PRIORITY.md) - Obtain liquid on mainnet (fund LP + relay bridge), then wire off/on-ramps.
|
||||
|
||||
**Explorer (explorer.d-bis.org):**
|
||||
- **[EXPLORER_FUNCTIONALITY_REVIEW.md](EXPLORER_FUNCTIONALITY_REVIEW.md)** - Routes, API URLs, contract verification, Snap send HTTPS.
|
||||
- **[EXPLORER_GAPS_AND_RECOMMENDATIONS.md](EXPLORER_GAPS_AND_RECOMMENDATIONS.md)** - Loading on all pages, bridge/lanes, **Verify & Publish** (UI) and batch verification (Forge + proxy), user/API key issuance, operator checklist.
|
||||
- **[EXPLORER_TROUBLESHOOTING.md](EXPLORER_TROUBLESHOOTING.md)** - SSL, NPMplus, 502/verification failures, common errors.
|
||||
- **Contract verification (Forge + Blockscout):** [../08-monitoring/BLOCKSCOUT_VERIFICATION_GUIDE.md](../08-monitoring/BLOCKSCOUT_VERIFICATION_GUIDE.md) — proxy, manual UI, 502/HTML troubleshooting.
|
||||
|
||||
## Quick Reference
|
||||
|
||||
**Initial Setup:**
|
||||
|
||||
@@ -29,10 +29,11 @@ This is the **authoritative source** for all RPC endpoint configurations. All ot
|
||||
| **138 Public RPC** | `RPC_URL_138_PUBLIC` | Bridge, monitoring, frontend, browser | `http://192.168.11.221:8545` (VMID 2201); public URL: `https://rpc-http-pub.d-bis.org` |
|
||||
|
||||
- Set in `config/ip-addresses.conf` or `smom-dbis-138/.env`. In smom `.env`, **`RPC_URL`** is an accepted alias for **Core** and is normalized to `RPC_URL_138`. `CHAIN138_RPC_URL` / `CHAIN138_RPC` are derived from `RPC_URL_138`. `WS_URL_138_PUBLIC` is the WebSocket for Public (e.g. `ws://192.168.11.221:8546`).
|
||||
- **Core RPC (VMID 2101) for deploy:** Use **IP and port**, not FQDN. Set `RPC_URL_138=http://192.168.11.211:8545` in `smom-dbis-138/.env` for contract deployment and gas checks. Do not use `https://rpc-core.d-bis.org` for deployment (avoids DNS/tunnel dependency; direct IP is reliable from LAN). See [TODOS_CONSOLIDATED](../00-meta/TODOS_CONSOLIDATED.md) § First (0b).
|
||||
|
||||
| Variable / use | Canonical value | Notes |
|
||||
|----------------|-----------------|--------|
|
||||
| **RPC_URL_138** (Core) | `http://192.168.11.211:8545` or `https://rpc-core.d-bis.org` | Single standard for Chain 138 admin/deploy |
|
||||
| **RPC_URL_138** (Core) | `http://192.168.11.211:8545` | **Prefer IP:port for admin/deploy.** Fallback from off-LAN: `https://rpc-core.d-bis.org` |
|
||||
| **RPC_URL_138_PUBLIC** (Public) | `http://192.168.11.221:8545` or `https://rpc-http-pub.d-bis.org` | Single standard for Chain 138 public; VITE_RPC_URL_138 in frontend |
|
||||
| **RPC_URL_138_FIREBLOCKS** (Fireblocks) | `http://192.168.11.232:8545` or `https://rpc-fireblocks.d-bis.org` | Dedicated RPC for Fireblocks Web3 (VMID 2301); `WS_URL_138_FIREBLOCKS`: `wss://ws.rpc-fireblocks.d-bis.org` |
|
||||
| **Ethereum Mainnet** | `https://eth.llamarpc.com` or Infura/Alchemy | `ETHEREUM_MAINNET_RPC` or `RPC_URL_MAINNET` in .env; CCIP relay uses both. Prefer Infura `https://mainnet.infura.io/v3/<PROJECT_ID>` to avoid 429. |
|
||||
|
||||
205
docs/04-configuration/SECRETS_CONSOLIDATED_DOWNLOAD.env
Normal file
205
docs/04-configuration/SECRETS_CONSOLIDATED_DOWNLOAD.env
Normal file
@@ -0,0 +1,205 @@
|
||||
# =============================================================================
|
||||
# CONSOLIDATED SECRETS — Single file for download / backup / fill-from-sources
|
||||
# =============================================================================
|
||||
# INSTRUCTIONS:
|
||||
# 1. Download this file (or copy from repo).
|
||||
# 2. Fill each value from your existing .env files (see comments after each key).
|
||||
# 3. Save the filled file as secrets-consolidated.env or .env.master in a secure
|
||||
# location. NEVER commit the filled file. Keep it off cloud/email.
|
||||
# 4. Use for backup, new machine setup, or feeding into a secrets manager.
|
||||
# =============================================================================
|
||||
# Sources: root = proxmox repo root .env; smom = smom-dbis-138/.env;
|
||||
# dbis = dbis_core/.env; omnis = OMNIS/backend/.env; etc.
|
||||
# =============================================================================
|
||||
|
||||
# --- Proxmox (root) ---
|
||||
PROXMOX_ML110=
|
||||
PROXMOX_R630_01=
|
||||
PROXMOX_R630_02=
|
||||
PROXMOX_HOST=
|
||||
PROXMOX_PORT=
|
||||
PROXMOX_USER=
|
||||
PROXMOX_TOKEN_NAME=
|
||||
PROXMOX_TOKEN_VALUE=
|
||||
PROXMOX_ALLOW_ELEVATED=
|
||||
|
||||
# --- Cloudflare (root) ---
|
||||
CLOUDFLARE_API_TOKEN=
|
||||
CLOUDFLARE_EMAIL=
|
||||
CLOUDFLARE_API_KEY=
|
||||
CLOUDFLARE_ZONE_ID=
|
||||
CLOUDFLARE_ZONE_ID_D_BIS_ORG=
|
||||
CLOUDFLARE_ZONE_ID_MIM4U_ORG=
|
||||
CLOUDFLARE_ZONE_ID_SANKOFA_NEXUS=
|
||||
CLOUDFLARE_ZONE_ID_DEFI_ORACLE_IO=
|
||||
CLOUDFLARE_TUNNEL_TOKEN=
|
||||
CLOUDFLARE_TUNNEL_ID=
|
||||
CLOUDFLARE_TUNNEL_ID_ALLTRA_HYBX=
|
||||
CLOUDFLARE_TUNNEL_ID_MIFOS_R630_02=
|
||||
CLOUDFLARE_TUNNEL_TOKEN_MIFOS_R630_02=
|
||||
CLOUDFLARE_ORIGIN_CA_KEY=
|
||||
CLOUDFLARE_ACCOUNT_ID=
|
||||
|
||||
# --- ClouDNS (root) ---
|
||||
CLOUDNS_AUTH_ID=
|
||||
CLOUDNS_AUTH_PASSWORD=
|
||||
|
||||
# --- NPM / NPMplus (root) ---
|
||||
NPM_URL=
|
||||
NPM_EMAIL=
|
||||
NPM_PASSWORD=
|
||||
NPM_HOST=
|
||||
NPM_PROXMOX_HOST=
|
||||
NPMPLUS_HOST=
|
||||
NPM_VMID=
|
||||
NPMPLUS_VMID=
|
||||
NPMPLUS_ALLTRA_HYBX_VMID=
|
||||
IP_NPMPLUS_ALLTRA_HYBX=
|
||||
NPM_URL_MIFOS=
|
||||
|
||||
# --- Fastly (root) ---
|
||||
FASTLY_API_TOKEN=
|
||||
|
||||
# --- Network / UniFi (root) | Omada (omada-api/.env) ---
|
||||
PUBLIC_IP=
|
||||
PROXMOX_HOST_FOR_TEST=
|
||||
UNIFI_UDM_URL=
|
||||
UNIFI_API_KEY=
|
||||
UNIFI_API_MODE=
|
||||
UNIFI_SITE_ID=
|
||||
UNIFI_VERIFY_SSL=
|
||||
OMADA_API_KEY=
|
||||
OMADA_CLIENT_SECRET=
|
||||
|
||||
# --- Gitea (root) ---
|
||||
GITEA_URL=
|
||||
GITEA_TOKEN=
|
||||
GITEA_ORG=
|
||||
|
||||
# --- Database & app auth (root, dbis_core, omnis, explorer) ---
|
||||
DATABASE_URL=
|
||||
JWT_SECRET=
|
||||
JWT_REFRESH_SECRET=
|
||||
JWT_EXPIRES_IN=
|
||||
JWT_REFRESH_EXPIRES_IN=
|
||||
SESSION_SECRET=
|
||||
ADMIN_CENTRAL_API_KEY=
|
||||
DBIS_CENTRAL_URL=
|
||||
ADMIN_JWT_SECRET=
|
||||
|
||||
# --- Storage AWS/Azure (root, omnis) ---
|
||||
STORAGE_TYPE=
|
||||
STORAGE_PATH=
|
||||
AWS_REGION=
|
||||
AWS_ACCESS_KEY_ID=
|
||||
AWS_SECRET_ACCESS_KEY=
|
||||
AWS_S3_BUCKET=
|
||||
AZURE_STORAGE_CONNECTION_STRING=
|
||||
AZURE_STORAGE_CONTAINER=
|
||||
|
||||
# --- Blockchain / SMOM-DBIS-138 (smom-dbis-138/.env, root) ---
|
||||
PRIVATE_KEY=
|
||||
RPC_URL_138=
|
||||
RPC_URL_138_PUBLIC=
|
||||
ETHEREUM_MAINNET_RPC=
|
||||
CHAIN_651940_RPC_URL=
|
||||
ETHERLINK_RPC_URL=
|
||||
TEZOS_RPC_URL=
|
||||
ETHERSCAN_API_KEY=
|
||||
ETHERLINK_CCIP_SELECTOR=
|
||||
TEZOS_BRIDGE_ENABLED=
|
||||
ETHERLINK_BRIDGE_ENABLED=
|
||||
TEZOS_RELAY_ORACLE_KEY=
|
||||
ETHERLINK_RELAY_BRIDGE=
|
||||
ETHERLINK_RELAY_PRIVATE_KEY=
|
||||
JUMPER_API_KEY=
|
||||
ONEINCH_API_KEY=
|
||||
MOONPAY_API_KEY=
|
||||
MOONPAY_SECRET_KEY=
|
||||
RAMP_NETWORK_API_KEY=
|
||||
ONRAMPER_API_KEY=
|
||||
|
||||
# --- Alerts & monitoring (root, dbis_core) ---
|
||||
SLACK_WEBHOOK_URL=
|
||||
PAGERDUTY_INTEGRATION_KEY=
|
||||
EMAIL_ALERT_API_URL=
|
||||
EMAIL_ALERT_RECIPIENTS=
|
||||
SENTRY_DSN=
|
||||
|
||||
# --- Legal / e-signature (root, the-order/legal-documents) ---
|
||||
E_SIGNATURE_BASE_URL=
|
||||
|
||||
# --- OTC / exchanges (dbis_core/.env) ---
|
||||
CRYPTO_COM_API_KEY=
|
||||
CRYPTO_COM_API_SECRET=
|
||||
CRYPTO_COM_ENVIRONMENT=
|
||||
BINANCE_API_KEY=
|
||||
BINANCE_API_SECRET=
|
||||
KRAKEN_API_KEY=
|
||||
KRAKEN_PRIVATE_KEY=
|
||||
OANDA_API_KEY=
|
||||
OANDA_ACCOUNT_ID=
|
||||
OANDA_ENVIRONMENT=
|
||||
FXCM_API_TOKEN=
|
||||
|
||||
# --- Price / market data (root, token-aggregation, smom-dbis-138) ---
|
||||
COINGECKO_API_KEY=
|
||||
COINDESK_API_KEY=
|
||||
COINMARKETCAP_API_KEY=
|
||||
DEXSCREENER_API_KEY=
|
||||
|
||||
# --- Mifos / Fineract / OMNL (root, omnl-fineract) ---
|
||||
MIFOS_BASE_URL=
|
||||
MIFOS_TENANT=
|
||||
MIFOS_USER=
|
||||
MIFOS_PASSWORD=
|
||||
MIFOS_INSECURE=
|
||||
OMNL_FINERACT_BASE_URL=
|
||||
OMNL_FINERACT_TENANT=
|
||||
OMNL_FINERACT_USER=
|
||||
OMNL_FINERACT_PASSWORD=
|
||||
|
||||
# --- Phoenix / Sankofa / OMNIS backend (OMNIS/backend/.env) ---
|
||||
SANKOFA_PHOENIX_API_URL=
|
||||
SANKOFA_PHOENIX_CLIENT_ID=
|
||||
SANKOFA_PHOENIX_CLIENT_SECRET=
|
||||
SANKOFA_PHOENIX_TENANT_ID=
|
||||
|
||||
# --- Frontend / MetaMask / Explorer (various .env) ---
|
||||
VITE_WALLETCONNECT_PROJECT_ID=
|
||||
VITE_THIRDWEB_CLIENT_ID=
|
||||
VITE_ETHERSCAN_API_KEY=
|
||||
VITE_SENTRY_DSN=
|
||||
VITE_API_URL=
|
||||
VITE_API_BASE_URL=
|
||||
NEXT_PUBLIC_API_URL=
|
||||
NEXT_PUBLIC_CHAIN_ID=
|
||||
METAMASK_API_KEY=
|
||||
THIRDWEB_SECRET_KEY=
|
||||
NPM_ACCESS_TOKEN=
|
||||
|
||||
# --- DeFi aggregators (alltra-lifi-settlement/.env) ---
|
||||
PARASWAP_API_KEY=
|
||||
ZEROX_API_KEY=
|
||||
|
||||
# --- ProxmoxVE API (ProxmoxVE/api/.env) ---
|
||||
MONGO_USER=
|
||||
MONGO_PASSWORD=
|
||||
MONGO_IP=
|
||||
MONGO_PORT=
|
||||
MONGO_DATABASE=
|
||||
|
||||
# --- Chain138 / Fireblocks (root, fireblocks-integration) ---
|
||||
CHAIN138_RPC_URL=
|
||||
RPC_URL_138_FIREBLOCKS=
|
||||
WS_URL_138_FIREBLOCKS=
|
||||
CHAIN_ID_138=
|
||||
|
||||
# --- Phoenix deploy API (phoenix-deploy-api/.env) ---
|
||||
PORT=
|
||||
GITEA_TOKEN=
|
||||
|
||||
# --- Optional / per-service ---
|
||||
MARKET_REPORTING_API_KEY=
|
||||
E_FILING_ENABLED=
|
||||
NODE_ENV=
|
||||
@@ -0,0 +1,262 @@
|
||||
# Methodology: Smart Contracts Accepting ISO-20022 and Fin Messages
|
||||
|
||||
**Version:** 1.0
|
||||
**Last Updated:** 2026-02-23
|
||||
**Status:** Active
|
||||
**Scope:** Chain 138 (and multi-chain) e-money and bridge contracts
|
||||
|
||||
---
|
||||
|
||||
## 1. Purpose and Scope
|
||||
|
||||
This document defines the **methodology** for designing and operating smart contracts that **accept** ISO-20022 financial messages (MX/XML) and, where applicable, **SWIFT Fin** (MT) messages, by normalising them to a single **canonical on-chain representation** and processing them through a well-defined contract interface.
|
||||
|
||||
### 1.1 Objectives
|
||||
|
||||
- **Interoperability:** Enable value transfers and settlement flows that originate from or are traceable to ISO-20022 (and Fin) messaging.
|
||||
- **Auditability:** Ensure every on-chain transfer, mint, burn, or cross-chain action can be correlated with a standardised message identifier and metadata (e.g. MsgId, UETR, debtor/creditor, purpose).
|
||||
- **Compliance:** Support regulatory and E-Money requirements (par redeemability, safeguarded reserves, transaction monitoring) while preserving ISO-20022 semantics at the boundary.
|
||||
|
||||
### 1.2 Out of Scope
|
||||
|
||||
- Off-chain generation or routing of ISO-20022/Fin messages (covered by [ISO 20022 Mapping Table](../../gru-docs/docs/integration/iso20022/Mapping_Table.md) and [dbis_core ISO 20022 integration](../../dbis_core/docs/nostro-vostro/iso20022-mapping.md)).
|
||||
- Contract deployment or network topology (see deployment runbooks).
|
||||
|
||||
---
|
||||
|
||||
## 2. Message Sources: ISO-20022 and Fin
|
||||
|
||||
### 2.1 ISO-20022 (MX) Messages
|
||||
|
||||
| Message Type | Purpose | Typical Use in Smart Contract Context |
|
||||
|-------------------|----------------------------------|----------------------------------------|
|
||||
| **pain.001** | Customer credit transfer initiation | Initiation of a payment that may settle on-chain |
|
||||
| **pacs.008** | FI-to-FI customer credit transfer | Settlement instruction; primary input for on-chain credit |
|
||||
| **pacs.009** | FI-to-FI direct debit | Debit-side settlement |
|
||||
| **pacs.002** | Payment status report | Status/correlation off-chain or in events |
|
||||
| **camt.053** | Bank statement | Off-chain reconciliation |
|
||||
| **camt.054** | Debit/credit notification | Notifications; optional event mapping |
|
||||
|
||||
Messages are **XML** with namespaces per ISO 20022 XSDs (e.g. `urn:iso:std:iso:20022:tech:xsd:pacs.008.001.10`). Parsing and validation are done **off-chain**; only a **canonical payload** is passed to the contract.
|
||||
|
||||
### 2.2 SWIFT Fin (MT) Messages
|
||||
|
||||
Where legacy flows use **SWIFT Fin** (e.g. MT103, MT202), the methodology treats them as **additional input formats** that must be **mapped into the same canonical structure** as ISO-20022 before being passed to smart contracts.
|
||||
|
||||
| MT Type | Purpose | Mapping Notes |
|
||||
|-----------|----------------------|----------------------------------------------------|
|
||||
| **MT103** | Single customer transfer | Field 20 → instructionId; 32A → amount/currency; 50/59 → debtor/creditor |
|
||||
| **MT202** | Bank transfer | Map to pacs.008-like canonical fields |
|
||||
|
||||
Fin messages are **normalised to the canonical format** (Section 3) so that contracts do not need separate MT vs MX logic.
|
||||
|
||||
---
|
||||
|
||||
## 3. Canonical Message Format (On-Chain Contract View)
|
||||
|
||||
All accepted messages (ISO-20022 MX or SWIFT Fin) are reduced to a **single canonical struct** used in contract interfaces and events. This aligns with the extended CanonicalMessage described in [MULTI_CHAIN_EXECUTION_ISO20022_EMONEY.md](../runbooks/MULTI_CHAIN_EXECUTION_ISO20022_EMONEY.md).
|
||||
|
||||
### 3.1 Canonical Struct (Semantic Definition)
|
||||
|
||||
| Field | Type | Purpose |
|
||||
|--------------------|---------|--------|
|
||||
| `msgType` | string | Message type: `pacs.008`, `pain.001`, `camt.054`, or normalized equivalent (e.g. `MT103`) |
|
||||
| `instructionId` | bytes32 | InstrId – unique instruction reference (hashed if longer than 32 bytes) |
|
||||
| `endToEndId` | string | EndToEndId (optional) |
|
||||
| `msgId` | string | MsgId (optional) |
|
||||
| `uetr` | string | UETR (optional) |
|
||||
| `accountRefId` | string | Account reference (debtor account or equivalent) |
|
||||
| `counterpartyRefId`| string | Counterparty account reference (creditor or equivalent) |
|
||||
| `debtorId` | string | Debtor identifier (optional) |
|
||||
| `creditorId` | string | Creditor identifier (optional) |
|
||||
| `purpose` | string | Purpose / remittance info (optional) |
|
||||
| `settlementMethod` | string | Settlement method (optional) |
|
||||
| `categoryPurpose` | string | Category purpose (optional) |
|
||||
| `token` | address | Token contract address |
|
||||
| `amount` | uint256 | Amount (in token’s smallest unit) |
|
||||
| `currencyCode` | string | Currency code (ISO 4217) |
|
||||
| `payloadHash` | bytes32 | Hash of off-chain payload (full MX/MT or selected elements) for audit |
|
||||
|
||||
Strings that exceed on-chain limits (e.g. 32 bytes for a single storage slot) should be **hashed** for storage and the full value emitted in events or stored in an off-chain index keyed by `instructionId` or `msgId`.
|
||||
|
||||
### 3.2 Solidity-Oriented Representation
|
||||
|
||||
Contracts may use a struct such as:
|
||||
|
||||
```solidity
|
||||
struct CanonicalMessage {
|
||||
string msgType;
|
||||
bytes32 instructionId;
|
||||
string endToEndId;
|
||||
string msgId;
|
||||
string uetr;
|
||||
string accountRefId;
|
||||
string counterpartyRefId;
|
||||
string debtorId;
|
||||
string creditorId;
|
||||
string purpose;
|
||||
string settlementMethod;
|
||||
string categoryPurpose;
|
||||
address token;
|
||||
uint256 amount;
|
||||
string currencyCode;
|
||||
bytes32 payloadHash;
|
||||
}
|
||||
```
|
||||
|
||||
Optional fields can be empty strings or zero values where not applicable. Events should expose at least `instructionId`, `msgId` (if present), `token`, `amount`, `debtorId`, `creditorId`, and `payloadHash` so that off-chain systems can map back to ISO-20022.
|
||||
|
||||
---
|
||||
|
||||
## 4. End-to-End Flow: From Fin/ISO-20022 to Smart Contract
|
||||
|
||||
### 4.1 High-Level Pipeline
|
||||
|
||||
```
|
||||
[ISO-20022 MX / SWIFT Fin] → Parse & Validate (off-chain) → Map to Canonical → Submit to Contract → Contract applies policy & executes
|
||||
```
|
||||
|
||||
1. **Ingest:** Receive MX (XML) or Fin (MT) message at an off-chain service (e.g. [dbis_core Iso20022Service](../../dbis_core/src/integration/iso20022/iso20022.service.ts), [Iso20022Adapter](../../dbis_core/src/integration/plugins/iso20022-adapter.ts), or a dedicated gateway).
|
||||
2. **Parse and validate:** Check schema, mandatory elements, and business rules (amounts, currency, identifiers). Reject invalid messages before any on-chain step.
|
||||
3. **Map to canonical:** Fill the canonical struct from the message (see Section 5). For MT, use a dedicated MT→canonical mapping (e.g. MT103 field 20 → instructionId, 32A → amount/currencyCode, 50/59 → debtorId/creditorId).
|
||||
4. **Submit to contract:** Call the contract’s **accept** entry point (e.g. `submitInbound` / `submitOutbound` or equivalent) with the canonical payload. The contract must verify sender (relayer/guardian), idempotency (e.g. by `instructionId` or `msgId`), and policy (ComplianceGuard, PolicyManager, allowlists).
|
||||
5. **Execute and emit:** Contract performs transfer/mint/burn/cross-chain and emits events that include canonical metadata so that off-chain systems can map to ISO-20022 reports (pacs.002, camt.054, etc.).
|
||||
|
||||
### 4.2 Idempotency and Replay Protection
|
||||
|
||||
- **Unique key:** Use `instructionId` (and optionally `msgId` or `uetr`) as the idempotency key. Contracts must maintain a mapping (e.g. `processedInstructions[instructionId]`) and **revert or no-op** if the same key is submitted again.
|
||||
- **Replay:** Ensure the same MX/Fin message cannot be replayed on another chain or at another time by binding the canonical payload to chain and, if needed, to a nonce or timestamp validated off-chain or on-chain.
|
||||
|
||||
---
|
||||
|
||||
## 5. Mapping Rules: ISO-20022 and Fin → Canonical
|
||||
|
||||
### 5.1 ISO-20022 MX → Canonical
|
||||
|
||||
Use the same semantic mapping as in the [ISO 20022 Mapping Table](../../gru-docs/docs/integration/iso20022/Mapping_Table.md) and [dbis_core iso20022-mapping](../../dbis_core/docs/nostro-vostro/iso20022-mapping.md), then project onto the canonical struct:
|
||||
|
||||
| Canonical Field | ISO-20022 Source (e.g. pacs.008) |
|
||||
|----------------------|-----------------------------------|
|
||||
| msgType | Message type (e.g. `pacs.008`) |
|
||||
| instructionId | `PmtId/InstrId` (hash if needed) |
|
||||
| endToEndId | `PmtId/EndToEndId` |
|
||||
| msgId | `GrpHdr/MsgId` |
|
||||
| uetr | UETR element if present |
|
||||
| accountRefId | `DbtrAcct/Id` (IBAN or Othr/Id) |
|
||||
| counterpartyRefId | `CdtrAcct/Id` (IBAN or Othr/Id) |
|
||||
| debtorId | `Dbtr/Nm` or `Dbtr/Id` |
|
||||
| creditorId | `Cdtr/Nm` or `Cdtr/Id` |
|
||||
| purpose | `RmtInf/Ustrd` or `Purp` |
|
||||
| settlementMethod | Settlement method element |
|
||||
| categoryPurpose | `CategoryPurp` |
|
||||
| token | Resolved from currency/account (off-chain config) |
|
||||
| amount | `IntrBkSttlmAmt` (scaled to token decimals) |
|
||||
| currencyCode | `IntrBkSttlmAmt/@Ccy` |
|
||||
| payloadHash | `keccak256(rawMessage)` or hash of selected elements |
|
||||
|
||||
### 5.2 SWIFT Fin (MT) → Canonical
|
||||
|
||||
Example for **MT103**:
|
||||
|
||||
| Canonical Field | MT103 Field | Notes |
|
||||
|----------------------|-------------|--------|
|
||||
| msgType | — | Set to `MT103` |
|
||||
| instructionId | 20 | Hash if > 32 bytes |
|
||||
| endToEndId | 121 (UETR) or 20 | If present |
|
||||
| msgId | — | From header or generate |
|
||||
| uetr | 121 | If present |
|
||||
| accountRefId | 50a / 52a | Sender account |
|
||||
| counterpartyRefId | 59a | Beneficiary account |
|
||||
| debtorId | 50K / 50a | Ordering customer |
|
||||
| creditorId | 59 / 59a | Beneficiary |
|
||||
| purpose | 72 | Sender to receiver info |
|
||||
| token | — | From currency in 32A + config |
|
||||
| amount | 32A | Parse amount; scale to token decimals |
|
||||
| currencyCode | 32A | Currency from 32A |
|
||||
| payloadHash | — | Hash of MT text block or full message |
|
||||
|
||||
Contracts only ever see the **canonical** struct; they do not need to know whether the source was MX or MT.
|
||||
|
||||
---
|
||||
|
||||
## 6. Contract Interface Requirements
|
||||
|
||||
### 6.1 Entry Points for “Accepting” Messages
|
||||
|
||||
Smart contracts that **accept** ISO-20022/Fin semantics should expose at least one of the following (or equivalent):
|
||||
|
||||
- **Inbound (e.g. submitInbound):** For instructions that result in **credit** to the chain (e.g. mint, or release from bridge). Caller must be an authorised relayer/guardian; payload is the canonical struct.
|
||||
- **Outbound (e.g. submitOutbound):** For instructions that result in **debit** from the chain (e.g. burn, or lock for bridge). Same authorisation and canonical payload.
|
||||
|
||||
Naming may vary (e.g. `processInboundMessage`, `acceptCreditTransfer`); the important part is that the **payload is the canonical struct** and that **idempotency** and **policy checks** are enforced.
|
||||
|
||||
### 6.2 Authorisation
|
||||
|
||||
- Only designated roles (e.g. `ROUTER_ROLE`, `RELAYER_ROLE`, or a guard contract) may call the submit functions. Use AccessControl or equivalent.
|
||||
- Optionally, require that the **sender** of the transaction is a known **guardian** or **relayer** address list, and that the canonical payload’s `payloadHash` matches an off-chain attested hash.
|
||||
|
||||
### 6.3 Events
|
||||
|
||||
Emit events that carry enough canonical metadata for off-chain systems to map to ISO-20022 status and reporting (e.g. pacs.002, camt.054):
|
||||
|
||||
- At least: `instructionId`, `msgId` (if any), `token`, `amount`, `debtorId`, `creditorId`, `payloadHash`, success/failure.
|
||||
- Prefer including `msgType`, `endToEndId`, `uetr` where available so that reconciliation and compliance reporting are straightforward.
|
||||
|
||||
### 6.4 Integration with E-Money and Compliance
|
||||
|
||||
- **ComplianceGuard / PolicyManager / ComplianceRegistry:** Before executing the transfer/mint/burn, contracts should enforce allowlists, KYT, and circuit breakers as described in [MULTI_CHAIN_EXECUTION_ISO20022_EMONEY.md](../runbooks/MULTI_CHAIN_EXECUTION_ISO20022_EMONEY.md). The canonical struct supplies `debtorId`, `creditorId`, and `purpose` for policy checks.
|
||||
- **Reserve and par redeemability:** For base-money mints, ensure reserve attestation and par redeemability rules are applied as in the same runbook; the canonical message does not replace those checks.
|
||||
|
||||
---
|
||||
|
||||
## 7. Validation and Security
|
||||
|
||||
### 7.1 Off-Chain Validation (Before Submit)
|
||||
|
||||
- **Schema:** Validate MX against the appropriate ISO 20022 XSD; validate MT format per SWIFT rules.
|
||||
- **Business rules:** Amount > 0, currency matches token, mandatory identifiers present, no duplicate `instructionId`/`msgId` in the system.
|
||||
- **Payload hash:** Compute `payloadHash` over the raw or normalized message and attach to the canonical struct so the contract (or a verifier) can optionally check it.
|
||||
|
||||
### 7.2 On-Chain Checks
|
||||
|
||||
- **Idempotency:** Revert or skip if `instructionId` (or chosen key) already processed.
|
||||
- **Role:** Only authorised roles can call submit.
|
||||
- **Token:** Ensure `token` is a known, allowed token (e.g. via TokenRegistry or allowlist).
|
||||
- **Amount:** Ensure `amount` is within bounds and, for mints, consistent with reserve/attestation logic.
|
||||
|
||||
### 7.3 Audit and Non-Repudiation
|
||||
|
||||
- Store or log `payloadHash` and `instructionId` on-chain so that auditors can match on-chain execution to off-chain MX/Fin messages.
|
||||
- Prefer emitting full canonical metadata in events and indexing them off-chain for compliance and reconciliation.
|
||||
|
||||
---
|
||||
|
||||
## 8. Implementation Checklist
|
||||
|
||||
- [ ] **Off-chain:** Parser for ISO-20022 MX (and optionally SWIFT Fin MT) producing the canonical struct.
|
||||
- [ ] **Off-chain:** Mapping tables and validation rules (amounts, currency, identifiers) aligned with [Mapping_Table.md](../../gru-docs/docs/integration/iso20022/Mapping_Table.md) and [iso20022-mapping.md](../../dbis_core/docs/nostro-vostro/iso20022-mapping.md).
|
||||
- [ ] **Contract:** Canonical struct and submit interface (e.g. `submitInbound`/`submitOutbound`) with role-based access.
|
||||
- [ ] **Contract:** Idempotency (e.g. `processedInstructions[instructionId]`) and policy hooks (ComplianceGuard, PolicyManager, ComplianceRegistry).
|
||||
- [ ] **Contract:** Events that expose canonical metadata for ISO-20022 mapping and reporting.
|
||||
- [ ] **Integration:** Bridge and e-money entry points (BridgeVault, UniversalCCIPBridge, etc.) carry or reference canonical metadata in events as per [MULTI_CHAIN_EXECUTION_ISO20022_EMONEY.md](../runbooks/MULTI_CHAIN_EXECUTION_ISO20022_EMONEY.md).
|
||||
|
||||
---
|
||||
|
||||
## 9. Related Documents
|
||||
|
||||
| Document | Description |
|
||||
|----------|-------------|
|
||||
| [ISO20022_INTAKE_GATEWAY_CONTRACT_MULTI_NETWORK.md](ISO20022_INTAKE_GATEWAY_CONTRACT_MULTI_NETWORK.md) | How the intake/gateway contract receives ISO messages on different blockchain networks (relayer vs cross-chain, same address, per-chain config) |
|
||||
| [MULTI_CHAIN_EXECUTION_ISO20022_EMONEY.md](../runbooks/MULTI_CHAIN_EXECUTION_ISO20022_EMONEY.md) | ISO-20022 canonical message and E-Money requirements for GRU multi-chain |
|
||||
| [Mapping_Table.md](../../gru-docs/docs/integration/iso20022/Mapping_Table.md) | ISO 20022 (pain.001, pacs.008, etc.) field-level mapping and validation |
|
||||
| [iso20022-mapping.md](../../dbis_core/docs/nostro-vostro/iso20022-mapping.md) | ISO 20022 to DBIS API mapping and Iso20022Adapter usage |
|
||||
| [iso20022-message-flow.md](../../dbis_core/docs/flows/iso20022-message-flow.md) | ISO 20022 message processing flow |
|
||||
| [LEGAL_COMPLIANCE_REQUIREMENTS.md](../../explorer-monorepo/docs/LEGAL_COMPLIANCE_REQUIREMENTS.md) | Legal and ISO 20022 compliance for smart contracts |
|
||||
|
||||
---
|
||||
|
||||
**Document Control**
|
||||
|
||||
- **Owner:** Configuration / Integration
|
||||
- **Review:** Align with runbook and mapping table changes
|
||||
- **Next review:** When contract interfaces or ISO-20022 message set change
|
||||
64
docs/04-configuration/STORAGE_FIX_R630_01_AND_THIN5.md
Normal file
64
docs/04-configuration/STORAGE_FIX_R630_01_AND_THIN5.md
Normal file
@@ -0,0 +1,64 @@
|
||||
# Storage fix: r630-01 (72%) and r630-02 thin5 (84.6%)
|
||||
|
||||
**Last updated:** 2026-02-28
|
||||
|
||||
## Situation
|
||||
|
||||
- **r630-01** `data` / `local-lvm`: **~72%** used. Many CTs (validators, RPC 2101, 2500–2505, etc.) use this pool.
|
||||
- **r630-02** `thin5`: **~84.6%** used. **Only VMID 5000 (Blockscout/Explorer)** uses thin5.
|
||||
|
||||
## Fix options
|
||||
|
||||
### 1. Prune only (recommended first)
|
||||
|
||||
Frees space without moving any container:
|
||||
|
||||
- **thin5:** Prune inside VMID 5000: journal, Docker logs/images, logrotate, backups.
|
||||
- **r630-01:** Prune journal and logs in all running CTs on the host.
|
||||
|
||||
```bash
|
||||
# From project root (LAN, SSH to both hosts)
|
||||
bash scripts/maintenance/fix-storage-r630-01-and-thin5.sh
|
||||
```
|
||||
|
||||
Dry-run:
|
||||
|
||||
```bash
|
||||
bash scripts/maintenance/fix-storage-r630-01-and-thin5.sh --dry-run
|
||||
```
|
||||
|
||||
### 2. Prune + migrate VMID 5000 to an empty pool
|
||||
|
||||
To free thin5, migrate Blockscout (5000) to the emptiest pool on r630-02: **thin2** (~4.8% used):
|
||||
|
||||
```bash
|
||||
# Migrate 5000 from thin5 -> thin2 (empty pool)
|
||||
bash scripts/maintenance/fix-storage-r630-01-and-thin5.sh --migrate-5000 thin2
|
||||
```
|
||||
|
||||
Other options: `thin6` (~14% used), `thin3` (~11% used). This will: stop 5000 → vzdump to local → destroy CT → restore to target pool → start. Expect 15–45 min; Blockscout is down during backup/restore.
|
||||
|
||||
### 3. Manual VMID 5000 prune (if script not run from repo)
|
||||
|
||||
On r630-02 or from a host that can SSH there:
|
||||
|
||||
```bash
|
||||
bash scripts/maintenance/vmid5000-free-disk-and-logs.sh
|
||||
```
|
||||
|
||||
## Verify after fix
|
||||
|
||||
```bash
|
||||
bash scripts/audit-proxmox-rpc-storage.sh
|
||||
# or
|
||||
ssh root@192.168.11.11 'pvesm status'
|
||||
ssh root@192.168.11.12 'pvesm status'
|
||||
```
|
||||
|
||||
LVM thin reclaim can take a few minutes after deleting data inside CTs; re-run `pvesm status` or `lvs` after a short wait.
|
||||
|
||||
## Reference
|
||||
|
||||
- thin5 on r630-02: single consumer **VMID 5000**.
|
||||
- r630-01 data: shared by VMIDs 2101, 1000, 1001, 1002, 10100, 10101, 10120, and others on that host.
|
||||
- Existing prune script for 5000: `scripts/maintenance/vmid5000-free-disk-and-logs.sh`.
|
||||
145
docs/04-configuration/STORAGE_RECOMMENDATIONS_BY_FILL_RATE.md
Normal file
145
docs/04-configuration/STORAGE_RECOMMENDATIONS_BY_FILL_RATE.md
Normal file
@@ -0,0 +1,145 @@
|
||||
# Storage Recommendations by Fill Rate and Growth
|
||||
|
||||
**Last updated:** 2026-02-28
|
||||
|
||||
Based on current usage, history in `logs/storage-growth/history.csv`, and physical drive layout across ml110, r630-01, and r630-02.
|
||||
|
||||
**Completed (2026-02-28):** Storage growth cron verified; prune (VMID 5000 + r630-01 CTs) run; ml110 sdb added to VG `pve` and data thin pool extended to ~1.7 TB (ml110 data now ~11% used). **Phase 1 migration (r630-01 data → thin1):** 8 CTs migrated (10233, 10120, 10100, 10101, 10235, 10236, 7804, 8640); r630-01 data **65.8%** (was 72%), thin1 50.6%.
|
||||
|
||||
---
|
||||
|
||||
## 1. Thresholds and monitoring
|
||||
|
||||
| Level | Use % | Action |
|
||||
|-------|--------|--------|
|
||||
| **Healthy** | < 75% | Continue normal collection; review quarterly. |
|
||||
| **Watch** | 75–84% | Weekly review; plan prune or migration. |
|
||||
| **WARN** | 85–94% | Prune and/or migrate within 1–2 weeks; do not add new large CTs. |
|
||||
| **CRIT** | ≥ 95% | Immediate action; LVM thin pools can fail or go read-only. |
|
||||
|
||||
Current scripts: `check-disk-all-vmids.sh` uses WARN 85%, CRIT 95% for **container root** usage. These recommendations apply to **host storage (pvesm / LVM)** as well.
|
||||
|
||||
---
|
||||
|
||||
## 2. Observed fill behavior (from history)
|
||||
|
||||
| Host | Storage | Trend (recent) | Implied rate / note |
|
||||
|------|---------|----------------|----------------------|
|
||||
| **ml110** | data | ~28.7% → ~25% (Feb 15 → 27) | Slight decrease (prune/dedup). Plenty of free space. |
|
||||
| **r630-01** | data | 88% → 100% → 72% → **65.8%** (Phase 1 migration) | After Phase 1 (8 CTs data→thin1). Main growth host (validators, RPCs, many CTs). |
|
||||
| **r630-02** | thin1-r630-02 | ~26.5% stable | Low growth. |
|
||||
| **r630-02** | thin2 | ~4.8% → ~9% after 5000 migration | Now holds Blockscout (5000); monitor. |
|
||||
| **r630-02** | thin5 | Was 84.6% → 0% after migration | Empty; available for future moves. |
|
||||
|
||||
**Conclusion:** The pool that fills fastest and needs the most attention is **r630-01 data** (72% now; many CTs, Besu/DB growth). **ml110 data** is stable and has headroom. **r630-02** is manageable if you avoid concentrating more large CTs on a single thin pool.
|
||||
|
||||
---
|
||||
|
||||
## 3. Recommendations by host and pool
|
||||
|
||||
### ml110
|
||||
|
||||
- **data / local-lvm (~25%)**
|
||||
- **Rate:** Low/slow.
|
||||
- **Recommendations:**
|
||||
- Keep running `collect-storage-growth-data.sh --append` (e.g. cron every 6h).
|
||||
- Prune logs in CTs periodically (e.g. with `fix-storage-r630-01-and-thin5.sh`-style logic for ml110 or a dedicated prune script).
|
||||
- No urgency; review again when approaching 70%.
|
||||
|
||||
- **Unused sdb (931G)**
|
||||
- **Recommendation:** Use it before adding new disks elsewhere.
|
||||
- **Option A:** Add sdb to VG `pve` and extend the `data` thin pool (or create a second thin pool). Frees pressure on sda and doubles effective data capacity.
|
||||
- **Option B:** Create a separate VG + thin pool on sdb for new or migrated CTs.
|
||||
- Document the chosen layout and any new Proxmox storage names in `storage.cfg` and in `PHYSICAL_DRIVES_AND_CONFIG.md`.
|
||||
|
||||
### r630-01
|
||||
|
||||
- **data / local-lvm (~72%)**
|
||||
- **Rate:** Highest risk; this pool has the most CTs and Besu/DB growth.
|
||||
- **Recommendations:**
|
||||
1. **Short term:**
|
||||
- Run log/journal prune on all r630-01 CTs regularly (e.g. `fix-storage-r630-01-and-thin5.sh` Phase 2, or a cron job).
|
||||
- Keep storage growth collection (e.g. every 6h) and review weekly when > 70%.
|
||||
2. **Before 85%:**
|
||||
- Move one or more large CTs to **thin1** on r630-01 (thin1 ~43% used, has space) if VMIDs allow, or plan migration to r630-02 thin pools.
|
||||
- Identify biggest CTs: `check-disk-all-vmids.sh` and `lvs` on r630-01 (data pool).
|
||||
3. **Before 90%:**
|
||||
- Decide on expansion (e.g. add disks to RAID10 and extend md0/LVM) or permanent migration of several CTs to r630-02.
|
||||
- **Do not** let this pool sit above 85% for long; it has already hit 100% once.
|
||||
|
||||
- **thin1 (~43%)**
|
||||
- **Rate:** Moderate.
|
||||
- **Recommendations:** Use as spillover for data pool migrations when possible. Monitor monthly; act if > 75%.
|
||||
|
||||
### r630-02
|
||||
|
||||
- **thin1-r630-02 (~26%)**
|
||||
- **Rate:** Low.
|
||||
- **Recommendation:** Monitor; no change needed unless you add many CTs here.
|
||||
|
||||
- **thin2 (~9% after 5000 migration)**
|
||||
- **Rate:** May grow with Blockscout (5000) and other CTs.
|
||||
- **Recommendations:**
|
||||
- Run VMID 5000 prune periodically: `vmid5000-free-disk-and-logs.sh`.
|
||||
- If thin2 approaches 75%, consider moving one CT to thin5 (now empty) or thin6.
|
||||
|
||||
- **thin3, thin4, thin6 (roughly 11–22%)**
|
||||
- **Rate:** Low to moderate.
|
||||
- **Recommendation:** Include in weekly pvesm/lvs review; no special action unless one pool trends > 75%.
|
||||
|
||||
- **thin5 (0% after migration)**
|
||||
- **Recommendation:** Keep as reserve for migrations from thin2 or other pools when they approach WARN.
|
||||
|
||||
---
|
||||
|
||||
## 4. Operational schedule (by fill rate)
|
||||
|
||||
| When | Action |
|
||||
|------|--------|
|
||||
| **Always** | Cron: `collect-storage-growth-data.sh --append` every 6h; weekly: `prune-storage-snapshots.sh` (e.g. Sun 08:00). |
|
||||
| **Weekly** | Review `pvesm status` and `lvs` (or run `audit-proxmox-rpc-storage.sh`); check any pool > 70%. |
|
||||
| **75% ≤ use < 85%** | Plan and run prune; plan migration for largest CTs on that pool; consider using ml110 sdb (if not yet in use). |
|
||||
| **85% ≤ use < 95%** | Execute prune and migration within 1–2 weeks; do not add new large VMs/CTs to that pool. |
|
||||
| **≥ 95%** | Immediate prune + migration; consider emergency migration to ml110 (after adding sdb) or r630-02. |
|
||||
|
||||
---
|
||||
|
||||
## 5. Scripts to support these recommendations
|
||||
|
||||
| Script | Purpose |
|
||||
|--------|--------|
|
||||
| `scripts/monitoring/collect-storage-growth-data.sh --append` | Record fill over time (for rate). |
|
||||
| `scripts/maintenance/schedule-storage-growth-cron.sh --install` | Install 6h collect + weekly prune. |
|
||||
| `scripts/audit-proxmox-rpc-storage.sh` | Current pvesm + RPC rootfs mapping. |
|
||||
| `scripts/maintenance/check-disk-all-vmids.sh` | Per-CT disk usage (find big consumers). |
|
||||
| `scripts/maintenance/fix-storage-r630-01-and-thin5.sh` | Prune 5000 + r630-01 CT logs; optional migrate 5000. |
|
||||
| `scripts/maintenance/migrate-ct-r630-01-data-to-thin1.sh <VMID>` | Migrate one CT from r630-01 data → thin1 (same host). |
|
||||
| `scripts/maintenance/vmid5000-free-disk-and-logs.sh` | Prune Blockscout (5000) only. |
|
||||
|
||||
---
|
||||
|
||||
## 6. Adding ml110 sdb to increase capacity (suggested steps)
|
||||
|
||||
1. On ml110: `vgextend pve /dev/sdb` (if sdb is already a PV) or `pvcreate /dev/sdb && vgextend pve /dev/sdb`.
|
||||
2. Extend the data thin pool: `lvextend -L +900G /dev/pve/data` (or use `lvextend -l +100%FREE` and adjust as needed).
|
||||
3. Re-run `pvesm status` and update documentation.
|
||||
4. No CT migration required; existing LVs on data can use the new space.
|
||||
|
||||
(If sdb is a raw disk with no PV, partition or use full disk as PV per your policy; then add to `pve` and extend the data LV as above.)
|
||||
|
||||
---
|
||||
|
||||
## 7. Summary table by risk
|
||||
|
||||
| Host | Pool | Current (approx) | Risk | Priority recommendation |
|
||||
|------|------|-------------------|------|--------------------------|
|
||||
| ml110 | data | ~11% (post-extension) | Low | **Done:** sdb added; pool ~1.7 TB. Monitor as before. |
|
||||
| ml110 | sdb | In use (extended data) | — | **Done:** sdb added to pve, data thin pool extended (~1.7 TB total). |
|
||||
| r630-01 | data | ~72% | High | Prune weekly; plan migrations before 85%; consider thin1 spillover. |
|
||||
| r630-01 | thin1 | ~43% | Medium | Use for migrations from data; monitor monthly. |
|
||||
| r630-02 | thin1-r630-02 | ~26% | Low | Monitor. |
|
||||
| r630-02 | thin2 | ~9% | Low | Prune 5000 periodically; watch growth. |
|
||||
| r630-02 | thin5 | 0% | Low | Keep as reserve for migrations. |
|
||||
| r630-02 | thin3, thin4, thin6 | ~11–22% | Low | Include in weekly review. |
|
||||
|
||||
These recommendations are based on the rate of filling observed in history and current configurations; adjust thresholds or schedule if your growth pattern changes.
|
||||
41
docs/04-configuration/THIRDWEB_BRIDGE_VS_CCIP.md
Normal file
41
docs/04-configuration/THIRDWEB_BRIDGE_VS_CCIP.md
Normal file
@@ -0,0 +1,41 @@
|
||||
# Thirdweb Bridge Tab vs Custom CCIP Bridge – Do You Deploy a Contract?
|
||||
|
||||
**Short answer:**
|
||||
**No.** For the **Thirdweb** bridge tab in the Interoperability Bridge app, you do **not** deploy any contract. That tab embeds Thirdweb’s hosted bridge (iframe to `thirdweb.com/bridge`). Thirdweb runs the bridge contracts and supports a fixed set of chains (85+). You only need a **Thirdweb Client ID** (from the [thirdweb dashboard](https://thirdweb.com/dashboard)) and `VITE_THIRDWEB_CLIENT_ID` in the dapp env.
|
||||
|
||||
**Custom CCIP bridge (Custom tab):**
|
||||
For the **Custom** tab (Wrap → Approve → Bridge WETH9 via CCIP), **you do** use your own deployed contracts on Chain 138 and mainnet: WETH9, WETH9 Bridge (CCIP), and LINK for fees. Those are already configured in `config/bridge.ts` and the Custom tab uses them. No extra “Thirdweb bridge contract” is required for the Thirdweb tab.
|
||||
|
||||
---
|
||||
|
||||
## 1. Thirdweb tab (iframe)
|
||||
|
||||
- **What it is:** The “ThirdWeb” tab loads Thirdweb’s **hosted** bridge UI in an iframe:
|
||||
`https://thirdweb.com/bridge?clientId=...&fromChain=138&toChain=...`
|
||||
- **Who runs the contracts:** Thirdweb. Their bridge supports a fixed list of chains (85+). Chain 138 may or may not be in that list.
|
||||
- **What you need:**
|
||||
- A thirdweb project and **Client ID**.
|
||||
- `VITE_THIRDWEB_CLIENT_ID` set in the frontend-dapp env (or the fallback in code).
|
||||
- **Do you deploy a contract?** **No.** You do not deploy any contract for this tab.
|
||||
|
||||
If Chain 138 is not supported by Thirdweb’s bridge, the iframe may show an error or “no entry” until Thirdweb adds Chain 138. For Chain 138 → EVM bridging that you control, use the **Custom** tab with your CCIP contracts.
|
||||
|
||||
---
|
||||
|
||||
## 2. Custom tab (CCIP)
|
||||
|
||||
- **What it is:** Your own UI (BridgeButtons, etc.) that talks to your WETH9 and WETH9 Bridge (CCIP) contracts on Chain 138 and LINK on mainnet.
|
||||
- **Who runs the contracts:** You (addresses in `config/bridge.ts` / env).
|
||||
- **What you need:** Deployed WETH9, WETH9 Bridge, and LINK (and any allowlists) on Chain 138 and mainnet as per your deployment runbooks.
|
||||
- **Do you deploy a contract?** **Yes.** This tab uses **your** deployed CCIP/bridge contracts; no Thirdweb bridge contract is involved.
|
||||
|
||||
---
|
||||
|
||||
## 3. Summary
|
||||
|
||||
| Tab | Contract deployment for the bridge? | Who runs bridge contracts? |
|
||||
|----------|--------------------------------------|-----------------------------|
|
||||
| ThirdWeb | **No** | Thirdweb (hosted) |
|
||||
| Custom | **Yes** (WETH9, WETH9 Bridge, LINK) | You (Chain 138 + mainnet) |
|
||||
|
||||
So: **there is no separate “Thirdweb bridge contract” for you to deploy.** For the Thirdweb tab you only need a Client ID; for the Custom tab you use your existing CCIP bridge deployment.
|
||||
124
docs/04-configuration/THIRDWEB_WALLETS_INTEGRATION.md
Normal file
124
docs/04-configuration/THIRDWEB_WALLETS_INTEGRATION.md
Normal file
@@ -0,0 +1,124 @@
|
||||
# Thirdweb Wallets – Documentation Review and Integration
|
||||
|
||||
**Purpose:** Review [thirdweb Wallets portal](https://portal.thirdweb.com/wallets) and document how we use or can fully integrate user/embedded wallets (email, phone, social, passkey, external) across the repo.
|
||||
|
||||
**References:** [thirdweb Wallets – Get Started](https://portal.thirdweb.com/wallets), [User Wallets](https://portal.thirdweb.com/wallets/users), [External Wallets](https://portal.thirdweb.com/wallets/external-wallets), [Quickstart (TypeScript/React)](https://portal.thirdweb.com/wallets/quickstart), [Connect SDK v5](https://portal.thirdweb.com/react/v5).
|
||||
|
||||
---
|
||||
|
||||
## 1. Portal overview
|
||||
|
||||
The thirdweb Wallets section covers:
|
||||
|
||||
- **User wallets (embedded/in-app):** Email, phone, social OAuth (Google, Apple, Facebook, Discord, X, etc.), passkey, guest, custom JWT.
|
||||
- **External wallets:** 500+ wallets, EIP-6963; MetaMask, WalletConnect, Coinbase Wallet, etc.
|
||||
- **Server wallets:** Backend-controlled wallets (send tx, monitor).
|
||||
- **Gas sponsorship / session keys:** Optional.
|
||||
|
||||
For each user, thirdweb can create a **non-custodial wallet** and expose it via SDK or HTTP API.
|
||||
|
||||
---
|
||||
|
||||
## 2. HTTP API (Wallets)
|
||||
|
||||
Relevant for backend or headless flows:
|
||||
|
||||
| Endpoint | Purpose |
|
||||
|----------|--------|
|
||||
| `POST /v1/auth/initiate` | Start auth (email, phone, passkey, SIWE); get challenge. |
|
||||
| `POST /v1/auth/complete` | Verify and complete auth; returns `token`, `userId`, `walletAddress`. |
|
||||
| `GET /v1/auth/social` | Redirect to OAuth provider (`provider`, `redirectUrl`). |
|
||||
| `GET /v1/wallets/me` | Get authenticated user wallet (use token from complete). |
|
||||
|
||||
**Headers:**
|
||||
|
||||
- **Frontend:** `x-client-id` (project Client ID).
|
||||
- **Backend:** `x-secret-key` (Dashboard → Settings → API Keys); never in frontend.
|
||||
|
||||
**Auth flow (e.g. email):**
|
||||
|
||||
1. `POST /v1/auth/initiate` with `{ "type": "email", "email": "user@example.com" }`.
|
||||
2. User receives code; then `POST /v1/auth/complete` with `{ "type": "email", "email": "...", "code": "123456" }`.
|
||||
3. Response includes `token`, `walletAddress`; use `token` for `GET /v1/wallets/me` or other authenticated calls.
|
||||
|
||||
**Custom auth:** If you already have an auth system, you can attach thirdweb wallets via [Custom Authentication](https://portal.thirdweb.com/wallets/custom-auth).
|
||||
|
||||
---
|
||||
|
||||
## 3. Current usage in this repo
|
||||
|
||||
| Area | What we use | Notes |
|
||||
|------|-------------|--------|
|
||||
| **smom-dbis-138/frontend-dapp** | `ThirdwebProvider` (v4), `useAddress` / `useBalance` / `useContract` from `@thirdweb-dev/react`; bridge UI uses thirdweb v4 hooks. | Connect UI is **wagmi** (MetaMask, WalletConnect, Coinbase) in `WalletConnect.tsx`; no embedded wallet (email/social) yet. |
|
||||
| **x402-api** | `thirdweb` v5: `createThirdwebClient`, `facilitator`, `settlePayment` from `thirdweb/x402`; custom Chain 138. | Server-side only; no user wallets. |
|
||||
| **explorer-monorepo** | Raw ethers + MetaMask + custom `/api/v1/auth/nonce` and `/api/v1/auth/wallet`. | No thirdweb SDK. |
|
||||
|
||||
**Secrets / env:**
|
||||
|
||||
- **frontend-dapp:** `VITE_THIRDWEB_CLIENT_ID`, `VITE_WALLETCONNECT_PROJECT_ID` (see [MASTER_SECRETS.md](MASTER_SECRETS.md), [DAPP_LXC_DEPLOYMENT.md](../03-deployment/DAPP_LXC_DEPLOYMENT.md)).
|
||||
- **x402-api:** `THIRDWEB_SECRET_KEY` (backend only).
|
||||
|
||||
---
|
||||
|
||||
## 4. Full integration options
|
||||
|
||||
### 4.1 Frontend: one connect experience (embedded + external)
|
||||
|
||||
**Goal:** Single “Connect” that supports both **in-app wallets** (email, phone, social) and **external wallets** (MetaMask, WalletConnect, etc.) as in the [portal Get Started](https://portal.thirdweb.com/wallets) and [Quickstart](https://portal.thirdweb.com/wallets/quickstart).
|
||||
|
||||
**Recommended path: thirdweb SDK v5**
|
||||
|
||||
- Portal and Quickstart use **v5** (`thirdweb` package, `thirdweb/react`).
|
||||
- v5 provides `ConnectButton` / `ConnectEmbed`, `inAppWallet({ auth: { options: ["email", "google", "passkey", ...] } })`, and 500+ external wallets with smaller bundle and better perf than v4.
|
||||
- v4 (`@thirdweb-dev/react`) is still in use in the dapp for contract hooks; v5 can run [alongside v4](https://portal.thirdweb.com/react/v5/migrate) for a gradual move.
|
||||
|
||||
**Steps:**
|
||||
|
||||
1. **Add v5 and a dedicated wallets flow (e.g. demo page)**
|
||||
- Install: `npm i thirdweb`.
|
||||
- Use `createThirdwebClient({ clientId })`, `ThirdwebProvider`, `ConnectButton` from `thirdweb/react`.
|
||||
- Configure `ConnectButton` with `inAppWallet({ auth: { options: ["email", "google", "apple", "passkey"] } })` so users can sign in with email/social or connect MetaMask/WalletConnect.
|
||||
- **Done:** The frontend-dapp has a **Wallets** page (`/wallets`, `src/pages/WalletsDemoPage.tsx`) that uses only v5: `ConnectButton` with in-app wallet + external wallets, `useActiveAccount`, `useWalletBalance` on Chain 138. Use it to try email/social/external connect without changing the rest of the app.
|
||||
|
||||
2. **Unify connect UI (full integration)**
|
||||
- Replace the current wagmi-only connect modal in `Layout` / `WalletConnect.tsx` with thirdweb v5’s `ConnectButton` (or `ConnectEmbed`) so the same button offers embedded + external.
|
||||
- Migrate bridge and other features from v4 hooks to v5: e.g. `useAddress` → `useActiveAccount`, `useContract`/`useContractWrite` → v5 contract extensions + `useSendTransaction` (see [v5 migrate](https://portal.thirdweb.com/react/v5/migrate)).
|
||||
- Keep Chain 138 in v5 (e.g. `defineChain` or use a chain list that includes 138) so the same RPC and chain are used.
|
||||
|
||||
3. **Env**
|
||||
- Use the same `VITE_THIRDWEB_CLIENT_ID` (and optional `VITE_WALLETCONNECT_PROJECT_ID` if needed by v5). No backend secret in frontend.
|
||||
|
||||
### 4.2 Backend: optional use of Wallets API
|
||||
|
||||
- If you need to **resolve or manage user wallets server-side** (e.g. after a custom auth), call `GET /v1/wallets/me` with the thirdweb token, or use the HTTP auth flow (`/v1/auth/initiate`, `/v1/auth/complete`) with `x-secret-key` from a secure backend.
|
||||
- **x402-api** already uses `THIRDWEB_SECRET_KEY` for x402; the same key can be used for server-side Wallets API calls if you add them.
|
||||
|
||||
### 4.3 Explorer (Blockscout frontend)
|
||||
|
||||
- The explorer uses ethers + MetaMask and custom auth endpoints; it does not use thirdweb.
|
||||
- Full thirdweb Wallets integration there would mean adding the thirdweb SDK and either replacing or complementing the current connect flow with `ConnectButton` + in-app wallet; that’s a separate, optional project.
|
||||
|
||||
---
|
||||
|
||||
## 5. Checklist for “fully integrated” thirdweb Wallets
|
||||
|
||||
- [x] **Documentation:** This file + links to portal (Get Started, Users, Quickstart, v5 migrate).
|
||||
- [x] **Client ID:** `VITE_THIRDWEB_CLIENT_ID` set in frontend-dapp (and any other app that uses thirdweb).
|
||||
- [x] **Connect UI (demo):** `/wallets` page with v5 `ConnectButton` + `inAppWallet` (email, google, apple, passkey) + external wallets; Chain 138 balance shown.
|
||||
- [ ] **Chain 138:** Supported in the thirdweb client/chains config used by the dapp.
|
||||
- [ ] **Migration (optional):** Bridge and other components moved from v4 hooks to v5 extensions/hooks so one account source is used everywhere.
|
||||
- [ ] **Backend (optional):** Use of `/v1/wallets/me` or auth endpoints from a secure service when needed.
|
||||
|
||||
---
|
||||
|
||||
## 6. Quick links
|
||||
|
||||
- [Wallets – Get Started](https://portal.thirdweb.com/wallets)
|
||||
- [User Wallets (auth methods)](https://portal.thirdweb.com/wallets/users)
|
||||
- [External Wallets](https://portal.thirdweb.com/wallets/external-wallets)
|
||||
- [Quickstart (TypeScript/React)](https://portal.thirdweb.com/wallets/quickstart)
|
||||
- [React v5 ConnectButton / ConnectEmbed](https://portal.thirdweb.com/react/v5/components/ConnectButton)
|
||||
- [In-App Wallet (v5)](https://portal.thirdweb.com/react/v5/in-app-wallet/get-started)
|
||||
- [Migrate from v4 to v5](https://portal.thirdweb.com/react/v5/migrate)
|
||||
- [API Reference – Authentication](https://portal.thirdweb.com/reference#tag/authentication)
|
||||
- [Custom auth](https://portal.thirdweb.com/wallets/custom-auth)
|
||||
124
docs/04-configuration/TOKEN_AGGREGATION_REPORT_API_RUNBOOK.md
Normal file
124
docs/04-configuration/TOKEN_AGGREGATION_REPORT_API_RUNBOOK.md
Normal file
@@ -0,0 +1,124 @@
|
||||
# Token-Aggregation Report API — Reachability Runbook
|
||||
|
||||
**Purpose:** Ensure `GET /api/v1/report/coingecko`, `GET /api/v1/report/cmc`, and `GET /api/v1/report/token-list` are reachable for CoinGecko/CMC submission and Chain 138 Snap.
|
||||
|
||||
---
|
||||
|
||||
## 1. Verify current state
|
||||
|
||||
```bash
|
||||
# From repo root
|
||||
bash metamask-integration/chain138-snap/scripts/verify-snap-api-and-icons.sh https://explorer.d-bis.org
|
||||
```
|
||||
|
||||
**Expected when working:** Token list and networks return valid JSON with `.tokens` and `.networks`.
|
||||
|
||||
**If you see "no .tokens" or "no .networks":** The `/api/v1/` path is likely proxied to Blockscout (or another backend) instead of token-aggregation. Proceed to §2.
|
||||
|
||||
---
|
||||
|
||||
## 2. Deploy token-aggregation (if not running)
|
||||
|
||||
### 2.1 On explorer VM (VMID 5000) or dedicated host
|
||||
|
||||
1. **Deploy the service:**
|
||||
```bash
|
||||
cd smom-dbis-138/services/token-aggregation
|
||||
cp .env.example .env
|
||||
# Edit .env: DATABASE_URL, CUSDC_ADDRESS_138, CUSDT_ADDRESS_138 (minimum for report)
|
||||
npm install && npm run build
|
||||
```
|
||||
|
||||
2. **Run via systemd** (or use `deploy-to-proxmox.sh` / `deploy-to-vmid.sh`):
|
||||
```bash
|
||||
# Example systemd unit
|
||||
ExecStart=/usr/bin/node /opt/token-aggregation/dist/index.js
|
||||
WorkingDirectory=/opt/token-aggregation
|
||||
```
|
||||
|
||||
3. **Verify locally:**
|
||||
```bash
|
||||
curl -s "http://localhost:3000/api/v1/report/token-list?chainId=138" | jq '.tokens | length'
|
||||
curl -s "http://localhost:3000/api/v1/report/coingecko?chainId=138" | jq '.'
|
||||
curl -s "http://localhost:3000/api/v1/networks" | jq '.networks | length'
|
||||
```
|
||||
|
||||
### 2.2 Minimum env for report API
|
||||
|
||||
| Var | Purpose |
|
||||
|-----|---------|
|
||||
| `CUSDC_ADDRESS_138` | cUSDC on Chain 138 |
|
||||
| `CUSDT_ADDRESS_138` | cUSDT on Chain 138 |
|
||||
| `CHAIN_138_RPC_URL` or `RPC_URL_138` | RPC for indexing |
|
||||
| `DATABASE_URL` | PostgreSQL (required for full service) |
|
||||
|
||||
**Note:** The report endpoints may work with minimal config; full indexing requires DB and RPC.
|
||||
|
||||
---
|
||||
|
||||
## 3. Proxy /api/v1/ to token-aggregation (explorer.d-bis.org)
|
||||
|
||||
If token-aggregation runs on the **explorer VM** (e.g. port 3000):
|
||||
|
||||
```bash
|
||||
# SSH to explorer VM (VMID 5000), then:
|
||||
TOKEN_AGG_PORT=3000 CONFIG_FILE=/etc/nginx/sites-available/blockscout \
|
||||
bash /path/to/explorer-monorepo/scripts/apply-nginx-token-aggregation-proxy.sh
|
||||
```
|
||||
|
||||
This inserts `location /api/v1/` proxying to `http://127.0.0.1:3000/api/v1/`. **Important:** The token-aggregation `location` must be defined **before** any Blockscout API `location` that might also match `/api/v1/`, so token-aggregation takes precedence.
|
||||
|
||||
### 3.1 If token-aggregation runs elsewhere
|
||||
|
||||
- **Option A:** Run token-aggregation on the explorer host (same machine as nginx) and proxy to `127.0.0.1:3000`.
|
||||
- **Option B:** Run on a different host; proxy to that host, e.g. `proxy_pass http://192.168.11.XXX:3000/api/v1/;`
|
||||
- **Option C:** Use a separate domain (e.g. `api.d-bis.org`) for the token-aggregation API and set `GATSBY_SNAP_API_BASE_URL` to that URL when building the Snap site.
|
||||
|
||||
---
|
||||
|
||||
## 4. Re-verify
|
||||
|
||||
```bash
|
||||
bash metamask-integration/chain138-snap/scripts/verify-snap-api-and-icons.sh https://explorer.d-bis.org
|
||||
```
|
||||
|
||||
All checks should pass. Then:
|
||||
|
||||
```bash
|
||||
curl -s "https://explorer.d-bis.org/api/v1/report/coingecko?chainId=138" -o report-coingecko-138.json
|
||||
curl -s "https://explorer.d-bis.org/api/v1/report/cmc?chainId=138" -o report-cmc-138.json
|
||||
```
|
||||
|
||||
Use these files for CoinGecko/CMC submission per [CMC_COINGECKO_SUBMISSION_RUNBOOK](coingecko/CMC_COINGECKO_SUBMISSION_RUNBOOK.md).
|
||||
|
||||
---
|
||||
|
||||
## 5. Troubleshooting
|
||||
|
||||
| Issue | Cause | Fix |
|
||||
|-------|-------|-----|
|
||||
| `curl .../api/v1/report/token-list` returns Blockscout-style JSON (`message`, `result`, `status`) | `/api/v1/` proxied to Blockscout, not token-aggregation | Ensure token-aggregation `location` is first; reload nginx |
|
||||
| Connection refused to 127.0.0.1:3000 | Token-aggregation not running | Start service; check `systemctl status token-aggregation` |
|
||||
| Empty `tokens` array | `CUSDC_ADDRESS_138`, `CUSDT_ADDRESS_138` unset or wrong | Set in `.env`; restart service |
|
||||
| 502 Bad Gateway | Token-aggregation crashed or wrong port | Check logs; verify `TOKEN_AGG_PORT` matches service |
|
||||
|
||||
---
|
||||
|
||||
## 6. Quick commands summary
|
||||
|
||||
```bash
|
||||
# 1. Verify (from repo root)
|
||||
bash metamask-integration/chain138-snap/scripts/verify-snap-api-and-icons.sh https://explorer.d-bis.org
|
||||
|
||||
# 2. Export for submission (after API is reachable)
|
||||
curl -s "https://explorer.d-bis.org/api/v1/report/coingecko?chainId=138" -o report-coingecko-138.json
|
||||
curl -s "https://explorer.d-bis.org/api/v1/report/cmc?chainId=138" -o report-cmc-138.json
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. Related docs
|
||||
|
||||
- [PRICE_FEED_CHAIN138_METAMASK_AND_WALLETS](PRICE_FEED_CHAIN138_METAMASK_AND_WALLETS.md) — Price feed checklist
|
||||
- [CMC_COINGECKO_SUBMISSION_RUNBOOK](coingecko/CMC_COINGECKO_SUBMISSION_RUNBOOK.md) — Export and submit
|
||||
- [smom-dbis-138/services/token-aggregation/README.md](../../../smom-dbis-138/services/token-aggregation/README.md) — Service setup
|
||||
94
docs/04-configuration/TOKEN_LISTS_E2E_VERIFICATION.md
Normal file
94
docs/04-configuration/TOKEN_LISTS_E2E_VERIFICATION.md
Normal file
@@ -0,0 +1,94 @@
|
||||
# Token Lists E2E Verification Report
|
||||
|
||||
**Date:** 2026-02-28
|
||||
**Status:** Verification complete
|
||||
|
||||
---
|
||||
|
||||
## 1. Token List Validation
|
||||
|
||||
| List | Status | Tokens | Notes |
|
||||
|------|--------|--------|-------|
|
||||
| dbis-138.tokenlist.json | ✅ Valid | 6 | All IPFS logos, EIP-55 checksummed |
|
||||
| cronos.tokenlist.json | ✅ Valid | 10 | All IPFS logos, ISO-4217 W tokens |
|
||||
| all-mainnet.tokenlist.json | ✅ Valid | 9 | All 9 tokens have logoURI (IPFS) |
|
||||
| DUAL_CHAIN_TOKEN_LIST | ✅ Valid | 22 | Chains 138, 1, 25, 651940 |
|
||||
|
||||
---
|
||||
|
||||
## 2. Cross-File Consistency
|
||||
|
||||
| Check | Result |
|
||||
|-------|--------|
|
||||
| Chain 138 addresses (dbis-138 vs DUAL_CHAIN) | ✅ Consistent |
|
||||
| Cronos addresses (cronos vs DUAL_CHAIN) | ✅ Consistent |
|
||||
| DUAL_CHAIN synced to backend/config, docs, metamask | ✅ Done |
|
||||
|
||||
---
|
||||
|
||||
## 3. IPFS Manifest
|
||||
|
||||
- **addressToUrl:** 14 of 22 DUAL_CHAIN addresses covered
|
||||
- **Missing:** Chain 1 (USDT, USDC, DAI, ETH-USD, WETH) and Chain 651940 USDC, Cronos WETH9/LINK — these use external logo URLs in token lists (TrustWallet, ethereum.org)
|
||||
- **Our tokens (138, 25):** All covered
|
||||
|
||||
---
|
||||
|
||||
## 4. Explorer API (`/api/config/token-list`)
|
||||
|
||||
| Check | Result |
|
||||
|-------|--------|
|
||||
| Public URL | ❌ Returns 400 (Blockscout error) |
|
||||
| Cause | Nginx config not yet applied on VMID 5000 |
|
||||
| Fix | Run on Proxmox host: |
|
||||
| | 1. `fix-nginx-conflicts-vmid5000.sh` (inside VMID 5000) |
|
||||
| | 2. `deploy-explorer-config-to-vmid5000.sh` (from repo root, with pct or EXEC_MODE=ssh) |
|
||||
|
||||
---
|
||||
|
||||
## 5. Deploy Script
|
||||
|
||||
| Check | Result |
|
||||
|-------|--------|
|
||||
| Config source path | ✅ Correct |
|
||||
| pct mode | Requires Proxmox host |
|
||||
| ssh mode | `EXEC_MODE=ssh EXPLORER_IP=192.168.11.140 ./explorer-monorepo/scripts/deploy-explorer-config-to-vmid5000.sh` |
|
||||
|
||||
---
|
||||
|
||||
## 6. Nginx Location Order
|
||||
|
||||
```
|
||||
location = /api/config/token-list # Exact match (highest priority)
|
||||
location = /api/config/networks
|
||||
location /api/v1/ # Token-aggregation
|
||||
location /api/ # Blockscout (fallback)
|
||||
```
|
||||
|
||||
✅ Correct — `/api/config/*` takes precedence over `/api/`
|
||||
|
||||
---
|
||||
|
||||
## 7. Frontend tokenIcons.ts
|
||||
|
||||
- Chain 138: 6 addresses ✅
|
||||
- Cronos WETH9, LINK, ISO-4217 W tokens: 9 addresses ✅
|
||||
|
||||
---
|
||||
|
||||
## 8. E2E Checklist (Operator)
|
||||
|
||||
To achieve full E2E:
|
||||
|
||||
1. [ ] SSH to Proxmox host (or VMID 5000)
|
||||
2. [ ] Run `fix-nginx-conflicts-vmid5000.sh` inside VMID 5000
|
||||
3. [ ] Run `deploy-explorer-config-to-vmid5000.sh` from repo root (pct or ssh)
|
||||
4. [ ] Verify: `curl -s https://explorer.d-bis.org/api/config/token-list | jq '.tokens | length'` → 22
|
||||
5. [ ] Verify: `curl -s https://explorer.d-bis.org/api/config/networks | jq '.chains | length'` → 4
|
||||
|
||||
---
|
||||
|
||||
## 9. Completed Improvements
|
||||
|
||||
- ✅ all-mainnet: logoURI added for HYDX, HYBX, CHT, AUDA
|
||||
- ✅ tokenIcons.ts: Cronos WETH9, LINK added to TOKEN_ICON_BY_ADDRESS
|
||||
198
docs/04-configuration/TOKEN_LIST_PR_REVIEW.md
Normal file
198
docs/04-configuration/TOKEN_LIST_PR_REVIEW.md
Normal file
@@ -0,0 +1,198 @@
|
||||
# Token List PR Review — How Each Repo Handles Token Lists
|
||||
|
||||
**Cloned repos:** `/home/intlc/projects/token-lists`, `chains`, `wallet-core`, `DefiLlama-Adapters`
|
||||
**Last Updated:** 2026-02-28
|
||||
|
||||
---
|
||||
|
||||
## 1. Uniswap token-lists (`/home/intlc/projects/token-lists`)
|
||||
|
||||
### What it is
|
||||
- **Schema + TypeScript package**, not a registry of token lists
|
||||
- Defines the Uniswap token list JSON schema (`src/tokenlist.schema.json`)
|
||||
- Schema ID: `https://uniswap.org/tokenlist.schema.json`
|
||||
- Used by tokenlists.org, Uniswap Interface, MetaMask, etc.
|
||||
|
||||
### Token list format (from `example.tokenlist.json`)
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "My Token List",
|
||||
"logoURI": "ipfs://...",
|
||||
"keywords": ["audited", "verified"],
|
||||
"tags": { "stablecoin": { "name": "Stablecoin", "description": "..." } },
|
||||
"timestamp": "2020-06-12T00:00:00+00:00",
|
||||
"tokens": [
|
||||
{
|
||||
"chainId": 1,
|
||||
"address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
|
||||
"symbol": "USDC",
|
||||
"name": "USD Coin",
|
||||
"decimals": 6,
|
||||
"logoURI": "ipfs://..."
|
||||
}
|
||||
],
|
||||
"version": { "major": 1, "minor": 0, "patch": 0 }
|
||||
}
|
||||
```
|
||||
|
||||
### Cross-chain (from `example-crosschain.tokenlist.json`)
|
||||
- Same structure; tokens can have `extensions.bridgeInfo` mapping chainId → bridged address
|
||||
- Each chain gets its own token entry with `chainId`
|
||||
|
||||
### PR process
|
||||
- **This repo does NOT host token lists** — it only provides the schema
|
||||
- To add a list: host it (GitHub Raw, IPFS, ENS) and submit to **tokenlists.org** via https://github.com/Uniswap/tokenlists-org/issues (template: "add list request")
|
||||
- Or use your own URL (e.g. `explorer.d-bis.org/api/v1/report/token-list`)
|
||||
|
||||
### Chain 138 action
|
||||
- Ensure `proxmox/token-lists/lists/dbis-138.tokenlist.json` validates against schema
|
||||
- Host at GitHub Raw or explorer API
|
||||
- Submit URL to tokenlists.org
|
||||
|
||||
---
|
||||
|
||||
## 2. Chainlist / ethereum-lists/chains (`/home/intlc/projects/chains`)
|
||||
|
||||
### What it is
|
||||
- **Chain metadata** (RPC, explorers, native currency) — not token lists
|
||||
- Used by chainlist.org, wallets, MESC, etc.
|
||||
- File: `_data/chains/eip155-{chainId}.json`
|
||||
|
||||
### Chain format (from `eip155-1.json`)
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "Ethereum Mainnet",
|
||||
"chain": "ETH",
|
||||
"icon": "ethereum",
|
||||
"rpc": ["https://mainnet.infura.io/...", "..."],
|
||||
"features": [{"name": "EIP155"}, {"name": "EIP1559"}],
|
||||
"faucets": [],
|
||||
"nativeCurrency": { "name": "Ether", "symbol": "ETH", "decimals": 18 },
|
||||
"infoURL": "https://ethereum.org",
|
||||
"shortName": "eth",
|
||||
"chainId": 1,
|
||||
"networkId": 1,
|
||||
"slip44": 60,
|
||||
"explorers": [{ "name": "etherscan", "url": "https://etherscan.io", "standard": "EIP3091" }]
|
||||
}
|
||||
```
|
||||
|
||||
### PR process
|
||||
1. Add `_data/chains/eip155-138.json`
|
||||
2. If using `icon`, add `_data/icons/defioraclemeta.json` (IPFS URL for logo)
|
||||
3. Run `./gradlew run` and `npx prettier --write _data/*/*.json`
|
||||
4. Open PR to https://github.com/ethereum-lists/chains
|
||||
|
||||
### Chain 138 status
|
||||
- **Not present** (no eip155-138.json in chains repo)
|
||||
- PR-ready: `proxmox/docs/04-configuration/pr-ready/eip155-138.json`
|
||||
|
||||
---
|
||||
|
||||
## 3. Trust Wallet wallet-core (`/home/intlc/projects/wallet-core`)
|
||||
|
||||
### What it is
|
||||
- **Coin/chain registry** for Trust Wallet app
|
||||
- `registry.json` — flat array of coins/chains
|
||||
- EVM chains have: `id`, `name`, `coinId`, `symbol`, `blockchain`, `chainId`, `explorer`, `info.rpc`
|
||||
|
||||
### EVM chain format (from registry.json)
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "ethereum",
|
||||
"name": "Ethereum",
|
||||
"coinId": 60,
|
||||
"symbol": "ETH",
|
||||
"decimals": 18,
|
||||
"blockchain": "Ethereum",
|
||||
"derivation": [{ "path": "m/44'/60'/0'/0/0" }],
|
||||
"curve": "secp256k1",
|
||||
"publicKeyType": "secp256k1Extended",
|
||||
"chainId": "1",
|
||||
"addressHasher": "keccak256",
|
||||
"explorer": {
|
||||
"url": "https://etherscan.io",
|
||||
"txPath": "/tx/",
|
||||
"accountPath": "/address/",
|
||||
"sampleTx": "...",
|
||||
"sampleAccount": "..."
|
||||
},
|
||||
"info": {
|
||||
"url": "https://ethereum.org",
|
||||
"source": "https://github.com/ethereum/go-ethereum",
|
||||
"rpc": "https://mainnet.infura.io",
|
||||
"documentation": "..."
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### PR process
|
||||
1. Add entry to `registry.json` (EVM: `blockchain: "Ethereum"`, `chainId`, `explorer`, `info.rpc`)
|
||||
2. Run codegen: `cd codegen-v2 && cargo run -- new-evmchain 138` (or per their CLI)
|
||||
3. Extend derivation tests
|
||||
4. Open PR to https://github.com/trustwallet/wallet-core
|
||||
|
||||
### Chain 138 status
|
||||
- **Not present**
|
||||
- PR-ready: `proxmox/docs/04-configuration/pr-ready/trust-wallet-registry-chain138.json`
|
||||
|
||||
---
|
||||
|
||||
## 4. DefiLlama-Adapters (`/home/intlc/projects/DefiLlama-Adapters`)
|
||||
|
||||
### What it is
|
||||
- **Protocol TVL adapters** — not token lists
|
||||
- Each project (e.g. `dodo`, `1inch`) has `index.js` that exports `tvl(api)` per chain
|
||||
- DefiLlama uses chain keys: `ethereum`, `bsc`, `polygon`, `arbitrum`, `avax`, `optimism`, `base`, etc.
|
||||
|
||||
### Adapter format (from `dodo/index.js`)
|
||||
|
||||
```javascript
|
||||
const config = {
|
||||
ethereum: { dvmFactory: '0x...', fromBlock: 10613640, ... },
|
||||
arbitrum: { dvmFactory: '0x...', fromBlock: 226578, ... },
|
||||
// Add new chain: chain138: { ... }
|
||||
};
|
||||
|
||||
Object.keys(config).forEach(chain => {
|
||||
module.exports[chain] = {
|
||||
tvl: async (api) => {
|
||||
// Fetch balances, return { 'ethereum:0xToken': balance }
|
||||
}
|
||||
};
|
||||
});
|
||||
```
|
||||
|
||||
### PR process
|
||||
1. Add adapter under `projects/{protocol-name}/`
|
||||
2. Export `tvl` (and optionally `staking`, `borrowed`) per chain
|
||||
3. Chain 138 would need DefiLlama to add `chain138` as a supported chain key first (see docs.llama.fi)
|
||||
4. Open PR to https://github.com/DefiLlama/DefiLlama-Adapters
|
||||
|
||||
### Chain 138 action
|
||||
- DefiLlama may not have `chain138` as a chain key yet
|
||||
- Check `helper/chains.js` or similar for supported chains
|
||||
- If adding DODO/other protocol on Chain 138, add config entry + tvl logic
|
||||
|
||||
---
|
||||
|
||||
## Summary: PR Targets by Repo
|
||||
|
||||
| Repo | Content | Chain 138 PR |
|
||||
|------|---------|--------------|
|
||||
| **token-lists** | Schema only; lists hosted elsewhere | N/A — use tokenlists.org issue to add list URL |
|
||||
| **chains** | Chain metadata (eip155-138.json) | Add `_data/chains/eip155-138.json` |
|
||||
| **wallet-core** | Coin/chain registry | Add entry to `registry.json` + codegen |
|
||||
| **DefiLlama-Adapters** | Protocol TVL adapters | Add adapter for DODO/etc. on Chain 138 (if chain supported) |
|
||||
|
||||
---
|
||||
|
||||
## References
|
||||
|
||||
- [PUBLICATION_LOCATIONS_MASTER](PUBLICATION_LOCATIONS_MASTER.md)
|
||||
- [pr-ready/eip155-138.json](pr-ready/eip155-138.json)
|
||||
- [pr-ready/trust-wallet-registry-chain138.json](pr-ready/trust-wallet-registry-chain138.json)
|
||||
- [ADD_CHAIN138_TO_TRUST_WALLET](ADD_CHAIN138_TO_TRUST_WALLET.md)
|
||||
@@ -1,6 +1,6 @@
|
||||
# Verification Scripts and Documentation - Gaps and TODOs
|
||||
|
||||
**Last Updated:** 2026-01-31
|
||||
**Last Updated:** 2026-03-02
|
||||
**Document Version:** 1.0
|
||||
**Status:** Active Documentation
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
**Status**: Gap Analysis Complete
|
||||
**Purpose**: Identify all placeholders, missing components, and incomplete implementations
|
||||
|
||||
**Documentation note (2026-03-02):** Runbook placeholders (e.g. `your-token`, `your-password`) are intentional examples. In production, use values from `.env` only; do not commit secrets. [INGRESS_VERIFICATION_RUNBOOK.md](INGRESS_VERIFICATION_RUNBOOK.md) updated with a production note in Prerequisites. Other runbooks (NPMPLUS_BACKUP_RESTORE, SANKOFA_CUTOVER_PLAN) keep example placeholders; operators should source from .env when running commands.
|
||||
|
||||
---
|
||||
|
||||
## Critical Missing Components
|
||||
@@ -106,7 +108,7 @@
|
||||
- Line 125: `NPM_PASSWORD="your-password"` → Example placeholder (acceptable)
|
||||
- Line 178: `NPM_PASSWORD="your-password"` → Example placeholder (acceptable)
|
||||
|
||||
**Action Required**: Add clear notes that these are examples and should use `.env` file in production.
|
||||
**Status (2026-03-02):** Addressed. INGRESS_VERIFICATION_RUNBOOK.md now includes a production note in Prerequisites. VERIFICATION_GAPS_AND_TODOS documents that runbooks use example placeholders and production should source from .env.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -67,10 +67,18 @@ This guide provides step-by-step instructions for submitting cUSDT and cUSDC tok
|
||||
|
||||
**Requirements:**
|
||||
- Format: PNG
|
||||
- Size: 512x512 pixels
|
||||
- Size: 512×512 pixels
|
||||
- Background: Transparent preferred
|
||||
- Quality: High resolution
|
||||
|
||||
**Quick prepare (script):**
|
||||
```bash
|
||||
# From repo root. Requires ImageMagick (convert) or Pillow for 512×512 resize.
|
||||
# Install: apt install imagemagick OR pip install Pillow
|
||||
./docs/04-configuration/coingecko/scripts/prepare-token-logos-512x512.sh
|
||||
# Output: docs/04-configuration/coingecko/logos/*-512x512.png
|
||||
```
|
||||
|
||||
**Where to get logos:**
|
||||
- Use USDT/USDC logos as reference
|
||||
- Create distinct versions for cUSDT/cUSDC
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
{"message":"Params 'module' and 'action' are required parameters","result":null,"status":"0"}
|
||||
@@ -0,0 +1 @@
|
||||
{"message":"Params 'module' and 'action' are required parameters","result":null,"status":"0"}
|
||||
@@ -0,0 +1 @@
|
||||
{"message":"Params 'module' and 'action' are required parameters","result":null,"status":"0"}
|
||||
@@ -0,0 +1 @@
|
||||
{"message":"Params 'module' and 'action' are required parameters","result":null,"status":"0"}
|
||||
@@ -0,0 +1 @@
|
||||
{"message":"Params 'module' and 'action' are required parameters","result":null,"status":"0"}
|
||||
@@ -0,0 +1 @@
|
||||
{"message":"Params 'module' and 'action' are required parameters","result":null,"status":"0"}
|
||||
@@ -0,0 +1 @@
|
||||
{"message":"Params 'module' and 'action' are required parameters","result":null,"status":"0"}
|
||||
@@ -0,0 +1 @@
|
||||
{"message":"Params 'module' and 'action' are required parameters","result":null,"status":"0"}
|
||||
@@ -0,0 +1 @@
|
||||
{"message":"Params 'module' and 'action' are required parameters","result":null,"status":"0"}
|
||||
@@ -0,0 +1 @@
|
||||
{"message":"Params 'module' and 'action' are required parameters","result":null,"status":"0"}
|
||||
@@ -0,0 +1 @@
|
||||
{"message":"Params 'module' and 'action' are required parameters","result":null,"status":"0"}
|
||||
@@ -0,0 +1 @@
|
||||
{"message":"Params 'module' and 'action' are required parameters","result":null,"status":"0"}
|
||||
@@ -0,0 +1 @@
|
||||
{"message":"Params 'module' and 'action' are required parameters","result":null,"status":"0"}
|
||||
@@ -0,0 +1 @@
|
||||
{"message":"Params 'module' and 'action' are required parameters","result":null,"status":"0"}
|
||||
@@ -0,0 +1 @@
|
||||
{"message":"Params 'module' and 'action' are required parameters","result":null,"status":"0"}
|
||||
@@ -0,0 +1 @@
|
||||
{"message":"Params 'module' and 'action' are required parameters","result":null,"status":"0"}
|
||||
@@ -0,0 +1 @@
|
||||
{"message":"Params 'module' and 'action' are required parameters","result":null,"status":"0"}
|
||||
@@ -0,0 +1 @@
|
||||
{"message":"Params 'module' and 'action' are required parameters","result":null,"status":"0"}
|
||||
@@ -0,0 +1 @@
|
||||
{"message":"Params 'module' and 'action' are required parameters","result":null,"status":"0"}
|
||||
@@ -0,0 +1 @@
|
||||
{"message":"Params 'module' and 'action' are required parameters","result":null,"status":"0"}
|
||||
@@ -0,0 +1 @@
|
||||
{"message":"Params 'module' and 'action' are required parameters","result":null,"status":"0"}
|
||||
@@ -0,0 +1 @@
|
||||
{"message":"Params 'module' and 'action' are required parameters","result":null,"status":"0"}
|
||||
@@ -0,0 +1 @@
|
||||
{"message":"Params 'module' and 'action' are required parameters","result":null,"status":"0"}
|
||||
@@ -0,0 +1 @@
|
||||
{"message":"Params 'module' and 'action' are required parameters","result":null,"status":"0"}
|
||||
@@ -0,0 +1 @@
|
||||
{"message":"Params 'module' and 'action' are required parameters","result":null,"status":"0"}
|
||||
@@ -0,0 +1 @@
|
||||
{"message":"Params 'module' and 'action' are required parameters","result":null,"status":"0"}
|
||||
@@ -0,0 +1 @@
|
||||
{"message":"Params 'module' and 'action' are required parameters","result":null,"status":"0"}
|
||||
@@ -0,0 +1 @@
|
||||
{"message":"Params 'module' and 'action' are required parameters","result":null,"status":"0"}
|
||||
122
docs/04-configuration/coingecko/logos/ipfs-manifest.json
Normal file
122
docs/04-configuration/coingecko/logos/ipfs-manifest.json
Normal file
@@ -0,0 +1,122 @@
|
||||
{
|
||||
"gateway": "https://ipfs.io/ipfs",
|
||||
"symbols": {
|
||||
"cEURT": {
|
||||
"cid": "QmWUVjZ4V6nUGgbvDGeVcQbd2V395TmjaLDdm87tF8VDC1",
|
||||
"url": "https://ipfs.io/ipfs/QmWUVjZ4V6nUGgbvDGeVcQbd2V395TmjaLDdm87tF8VDC1"
|
||||
},
|
||||
"cEURC": {
|
||||
"cid": "QmNPq4D5JXzurmi9jAhogVMzhAQRk1PZ1r9H3qQUV9gjDm",
|
||||
"url": "https://ipfs.io/ipfs/QmNPq4D5JXzurmi9jAhogVMzhAQRk1PZ1r9H3qQUV9gjDm"
|
||||
},
|
||||
"USDW": {
|
||||
"cid": "QmNPq4D5JXzurmi9jAhogVMzhAQRk1PZ1r9H3qQUV9gjDm",
|
||||
"url": "https://ipfs.io/ipfs/QmNPq4D5JXzurmi9jAhogVMzhAQRk1PZ1r9H3qQUV9gjDm"
|
||||
},
|
||||
"cUSDC": {
|
||||
"cid": "QmNPq4D5JXzurmi9jAhogVMzhAQRk1PZ1r9H3qQUV9gjDm",
|
||||
"url": "https://ipfs.io/ipfs/QmNPq4D5JXzurmi9jAhogVMzhAQRk1PZ1r9H3qQUV9gjDm",
|
||||
"address138": "0xf22258f57794CC8E06237084b353Ab30fFfa640b"
|
||||
},
|
||||
"cUSDT": {
|
||||
"cid": "QmRfhPs9DcyFPpGjKwF6CCoVDWUHSxkQR34n9NK7JSbPCP",
|
||||
"url": "https://ipfs.io/ipfs/QmRfhPs9DcyFPpGjKwF6CCoVDWUHSxkQR34n9NK7JSbPCP",
|
||||
"address138": "0x93E66202A11B1772E55407B32B44e5Cd8eda7f22"
|
||||
},
|
||||
"CHFW": {
|
||||
"cid": "Qmb9JmuD9ehaQtTLBBZmAoiAbvE53e3FMjkEty8rvbPf9K",
|
||||
"url": "https://ipfs.io/ipfs/Qmb9JmuD9ehaQtTLBBZmAoiAbvE53e3FMjkEty8rvbPf9K"
|
||||
},
|
||||
"CADW": {
|
||||
"cid": "Qmb9JmuD9ehaQtTLBBZmAoiAbvE53e3FMjkEty8rvbPf9K",
|
||||
"url": "https://ipfs.io/ipfs/Qmb9JmuD9ehaQtTLBBZmAoiAbvE53e3FMjkEty8rvbPf9K"
|
||||
},
|
||||
"cJPYC": {
|
||||
"cid": "Qmb9JmuD9ehaQtTLBBZmAoiAbvE53e3FMjkEty8rvbPf9K",
|
||||
"url": "https://ipfs.io/ipfs/Qmb9JmuD9ehaQtTLBBZmAoiAbvE53e3FMjkEty8rvbPf9K"
|
||||
},
|
||||
"AUDW": {
|
||||
"cid": "Qmb9JmuD9ehaQtTLBBZmAoiAbvE53e3FMjkEty8rvbPf9K",
|
||||
"url": "https://ipfs.io/ipfs/Qmb9JmuD9ehaQtTLBBZmAoiAbvE53e3FMjkEty8rvbPf9K"
|
||||
},
|
||||
"JPYW": {
|
||||
"cid": "Qmb9JmuD9ehaQtTLBBZmAoiAbvE53e3FMjkEty8rvbPf9K",
|
||||
"url": "https://ipfs.io/ipfs/Qmb9JmuD9ehaQtTLBBZmAoiAbvE53e3FMjkEty8rvbPf9K"
|
||||
},
|
||||
"cXAUT": {
|
||||
"cid": "Qma3FKtLce9MjgJgWbtyCxBiPjJ6xi8jGWUSKNS5Jc2ong",
|
||||
"url": "https://ipfs.io/ipfs/Qma3FKtLce9MjgJgWbtyCxBiPjJ6xi8jGWUSKNS5Jc2ong"
|
||||
},
|
||||
"cXAUC": {
|
||||
"cid": "Qma3FKtLce9MjgJgWbtyCxBiPjJ6xi8jGWUSKNS5Jc2ong",
|
||||
"url": "https://ipfs.io/ipfs/Qma3FKtLce9MjgJgWbtyCxBiPjJ6xi8jGWUSKNS5Jc2ong"
|
||||
},
|
||||
"GBPW": {
|
||||
"cid": "QmT2nJ6WyhYBCsYJ6NfS1BPAqiGKkCEuMxiC8ye93Co1hF",
|
||||
"url": "https://ipfs.io/ipfs/QmT2nJ6WyhYBCsYJ6NfS1BPAqiGKkCEuMxiC8ye93Co1hF"
|
||||
},
|
||||
"WETH": {
|
||||
"cid": "Qma3FKtLce9MjgJgWbtyCxBiPjJ6xi8jGWUSKNS5Jc2ong",
|
||||
"url": "https://ipfs.io/ipfs/Qma3FKtLce9MjgJgWbtyCxBiPjJ6xi8jGWUSKNS5Jc2ong",
|
||||
"address138": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"
|
||||
},
|
||||
"WETH10": {
|
||||
"cid": "QmanDFPHxnbKd6SSNzzXHf9GbpL9dLXSphxDZSPPYE6ds4",
|
||||
"url": "https://ipfs.io/ipfs/QmanDFPHxnbKd6SSNzzXHf9GbpL9dLXSphxDZSPPYE6ds4",
|
||||
"address138": "0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9F"
|
||||
},
|
||||
"cAUDC": {
|
||||
"cid": "QmPh16PY241zNtePyeK7ep1uf1RcARV2ynGAuRU8U7sSqS",
|
||||
"url": "https://ipfs.io/ipfs/QmPh16PY241zNtePyeK7ep1uf1RcARV2ynGAuRU8U7sSqS"
|
||||
},
|
||||
"EURW": {
|
||||
"cid": "QmPh16PY241zNtePyeK7ep1uf1RcARV2ynGAuRU8U7sSqS",
|
||||
"url": "https://ipfs.io/ipfs/QmPh16PY241zNtePyeK7ep1uf1RcARV2ynGAuRU8U7sSqS"
|
||||
},
|
||||
"cCADC": {
|
||||
"cid": "QmPh16PY241zNtePyeK7ep1uf1RcARV2ynGAuRU8U7sSqS",
|
||||
"url": "https://ipfs.io/ipfs/QmPh16PY241zNtePyeK7ep1uf1RcARV2ynGAuRU8U7sSqS"
|
||||
},
|
||||
"cCHFC": {
|
||||
"cid": "QmPh16PY241zNtePyeK7ep1uf1RcARV2ynGAuRU8U7sSqS",
|
||||
"url": "https://ipfs.io/ipfs/QmPh16PY241zNtePyeK7ep1uf1RcARV2ynGAuRU8U7sSqS"
|
||||
},
|
||||
"cGBPT": {
|
||||
"cid": "QmV4frsJmDTWzLdxdj1z81uMqVXcbGpHZLzwkpj6GvEX4k",
|
||||
"url": "https://ipfs.io/ipfs/QmV4frsJmDTWzLdxdj1z81uMqVXcbGpHZLzwkpj6GvEX4k"
|
||||
},
|
||||
"cGBPC": {
|
||||
"cid": "QmNQF73WjxU6FwTXNH8PXoDRFaSFKTYQWL7d4Q1kdRVJ4o",
|
||||
"url": "https://ipfs.io/ipfs/QmNQF73WjxU6FwTXNH8PXoDRFaSFKTYQWL7d4Q1kdRVJ4o"
|
||||
},
|
||||
"ETH-USD": {
|
||||
"cid": "QmPZuycjyJEe2otREuQ5HirvPJ8X6Yc6MBtwz1VhdD79pY",
|
||||
"url": "https://ipfs.io/ipfs/QmPZuycjyJEe2otREuQ5HirvPJ8X6Yc6MBtwz1VhdD79pY",
|
||||
"address138": "0x3304b747E565a97ec8AC220b0B6A1f6ffDB837e6"
|
||||
},
|
||||
"LINK": {
|
||||
"cid": "QmenWcmfNGfssz4HXvrRV912eZDiKqLTt6z2brRYuTGz9A",
|
||||
"url": "https://ipfs.io/ipfs/QmenWcmfNGfssz4HXvrRV912eZDiKqLTt6z2brRYuTGz9A",
|
||||
"address138": "0xb7721dD53A8c629d9f1Ba31a5819AFe250002b03"
|
||||
},
|
||||
"LiXAU": {
|
||||
"cid": "QmUVY5trUM5N1UnS4abReb66fNzGw7kenjU9AjL7TgR3M1",
|
||||
"url": "https://ipfs.io/ipfs/QmUVY5trUM5N1UnS4abReb66fNzGw7kenjU9AjL7TgR3M1"
|
||||
}
|
||||
},
|
||||
"addressToUrl": {
|
||||
"0xf22258f57794CC8E06237084b353Ab30fFfa640b": "https://ipfs.io/ipfs/QmNPq4D5JXzurmi9jAhogVMzhAQRk1PZ1r9H3qQUV9gjDm",
|
||||
"0x93E66202A11B1772E55407B32B44e5Cd8eda7f22": "https://ipfs.io/ipfs/QmRfhPs9DcyFPpGjKwF6CCoVDWUHSxkQR34n9NK7JSbPCP",
|
||||
"0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2": "https://ipfs.io/ipfs/Qma3FKtLce9MjgJgWbtyCxBiPjJ6xi8jGWUSKNS5Jc2ong",
|
||||
"0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9F": "https://ipfs.io/ipfs/QmanDFPHxnbKd6SSNzzXHf9GbpL9dLXSphxDZSPPYE6ds4",
|
||||
"0x3304b747E565a97ec8AC220b0B6A1f6ffDB837e6": "https://ipfs.io/ipfs/QmPZuycjyJEe2otREuQ5HirvPJ8X6Yc6MBtwz1VhdD79pY",
|
||||
"0xb7721dD53A8c629d9f1Ba31a5819AFe250002b03": "https://ipfs.io/ipfs/QmenWcmfNGfssz4HXvrRV912eZDiKqLTt6z2brRYuTGz9A",
|
||||
"0x948690147D2e50ffe50C5d38C14125aD6a9FA036": "https://ipfs.io/ipfs/QmNPq4D5JXzurmi9jAhogVMzhAQRk1PZ1r9H3qQUV9gjDm",
|
||||
"0x58a8D8F78F1B65c06dAd7542eC46b299629A60dd": "https://ipfs.io/ipfs/QmPh16PY241zNtePyeK7ep1uf1RcARV2ynGAuRU8U7sSqS",
|
||||
"0xFb4B6Cc81211F7d886950158294A44C312abCA29": "https://ipfs.io/ipfs/QmT2nJ6WyhYBCsYJ6NfS1BPAqiGKkCEuMxiC8ye93Co1hF",
|
||||
"0xf9f5D0ACD71C76F9476F10B3F3d3E201F0883C68": "https://ipfs.io/ipfs/Qmb9JmuD9ehaQtTLBBZmAoiAbvE53e3FMjkEty8rvbPf9K",
|
||||
"0xeE17bB0322383fecCA2784fbE2d4CD7d02b1905B": "https://ipfs.io/ipfs/Qmb9JmuD9ehaQtTLBBZmAoiAbvE53e3FMjkEty8rvbPf9K",
|
||||
"0xc9750828124D4c10e7a6f4B655cA8487bD3842EB": "https://ipfs.io/ipfs/Qmb9JmuD9ehaQtTLBBZmAoiAbvE53e3FMjkEty8rvbPf9K",
|
||||
"0x328Cd365Bb35524297E68ED28c6fF2C9557d1363": "https://ipfs.io/ipfs/Qmb9JmuD9ehaQtTLBBZmAoiAbvE53e3FMjkEty8rvbPf9K"
|
||||
}
|
||||
}
|
||||
85
docs/04-configuration/coingecko/scripts/prepare-token-logos-512x512.sh
Executable file
85
docs/04-configuration/coingecko/scripts/prepare-token-logos-512x512.sh
Executable file
@@ -0,0 +1,85 @@
|
||||
#!/usr/bin/env bash
|
||||
# Prepare 512×512 PNG logos for CoinGecko/CMC token submission.
|
||||
# Downloads logos from Trust Wallet (or provided URLs) and resizes to 512×512.
|
||||
# Output: docs/04-configuration/coingecko/logos/ (gitignored by default).
|
||||
#
|
||||
# Requires: curl, and one of: convert (ImageMagick), magick (ImageMagick 7), sips (macOS), or python3+PIL
|
||||
# Install ImageMagick for resize: apt install imagemagick / brew install imagemagick
|
||||
# Usage: ./prepare-token-logos-512x512.sh [OUTPUT_DIR]
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
OUTPUT_DIR="${1:-${SCRIPT_DIR}/../logos}"
|
||||
mkdir -p "$OUTPUT_DIR"
|
||||
|
||||
LOGO_BASE="https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets"
|
||||
|
||||
# Symbol -> URL (Trust Wallet mainnet addresses for USDC, USDT, WETH)
|
||||
declare -A LOGOS=(
|
||||
["WETH"]="${LOGO_BASE}/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png"
|
||||
["WETH10"]="${LOGO_BASE}/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png"
|
||||
["cUSDC"]="${LOGO_BASE}/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png"
|
||||
["cUSDT"]="${LOGO_BASE}/0xdAC17F958D2ee523a2206206994597C13D831ec7/logo.png"
|
||||
["cEURC"]="${LOGO_BASE}/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png"
|
||||
["cEURT"]="${LOGO_BASE}/0xdAC17F958D2ee523a2206206994597C13D831ec7/logo.png"
|
||||
["cGBPC"]="${LOGO_BASE}/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png"
|
||||
["cGBPT"]="${LOGO_BASE}/0xdAC17F958D2ee523a2206206994597C13D831ec7/logo.png"
|
||||
["cAUDC"]="${LOGO_BASE}/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png"
|
||||
["cJPYC"]="${LOGO_BASE}/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png"
|
||||
["cCHFC"]="${LOGO_BASE}/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png"
|
||||
["cCADC"]="${LOGO_BASE}/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png"
|
||||
["cXAUC"]="${LOGO_BASE}/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png"
|
||||
["cXAUT"]="${LOGO_BASE}/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png"
|
||||
["LiXAU"]="${LOGO_BASE}/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png"
|
||||
["USDW"]="${LOGO_BASE}/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png"
|
||||
["EURW"]="${LOGO_BASE}/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png"
|
||||
["GBPW"]="${LOGO_BASE}/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png"
|
||||
["AUDW"]="${LOGO_BASE}/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png"
|
||||
["JPYW"]="${LOGO_BASE}/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png"
|
||||
["CHFW"]="${LOGO_BASE}/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png"
|
||||
["CADW"]="${LOGO_BASE}/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png"
|
||||
["LINK"]="${LOGO_BASE}/0x514910771AF9Ca656af840dff83E8264EcF986CA/logo.png"
|
||||
["ETH-USD"]="${LOGO_BASE}/0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2/logo.png"
|
||||
)
|
||||
|
||||
resize_to_512() {
|
||||
local src="$1"
|
||||
local dst="$2"
|
||||
if command -v convert &>/dev/null; then
|
||||
convert "$src" -resize 512x512! -background none -gravity center -extent 512x512 "$dst"
|
||||
elif command -v magick &>/dev/null; then
|
||||
magick "$src" -resize 512x512! -background none -gravity center -extent 512x512 "$dst"
|
||||
elif command -v sips &>/dev/null; then
|
||||
sips -z 512 512 "$src" --out "$dst"
|
||||
elif python3 -c "from PIL import Image" 2>/dev/null; then
|
||||
python3 -c "
|
||||
from PIL import Image
|
||||
img = Image.open('$src').convert('RGBA')
|
||||
img = img.resize((512, 512), Image.Resampling.LANCZOS)
|
||||
img.save('$dst')
|
||||
"
|
||||
else
|
||||
echo "No ImageMagick, sips, or PIL found. Copying without resize (may not be 512×512)." >&2
|
||||
cp "$src" "$dst"
|
||||
fi
|
||||
}
|
||||
|
||||
echo "Preparing 512×512 PNG logos in $OUTPUT_DIR"
|
||||
for symbol in "${!LOGOS[@]}"; do
|
||||
url="${LOGOS[$symbol]}"
|
||||
out="$OUTPUT_DIR/${symbol}-512x512.png"
|
||||
tmp="$OUTPUT_DIR/.tmp-${symbol}.png"
|
||||
if curl -sS -L -o "$tmp" "$url" 2>/dev/null && [ -s "$tmp" ]; then
|
||||
resize_to_512 "$tmp" "$out"
|
||||
rm -f "$tmp"
|
||||
echo " ✅ $symbol -> $out"
|
||||
else
|
||||
echo " ❌ $symbol: failed to fetch $url"
|
||||
rm -f "$tmp"
|
||||
fi
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "Done. Logos in $OUTPUT_DIR"
|
||||
echo "Use these for CoinGecko/CMC submission (512×512 PNG required)."
|
||||
@@ -1,61 +1,19 @@
|
||||
{
|
||||
"name": "MetaMask Multi-Chain Networks (Chain 138 + Ethereum Mainnet + ALL Mainnet)",
|
||||
"version": { "major": 1, "minor": 1, "patch": 0 },
|
||||
"name": "MetaMask Multi-Chain Networks (13 chains)",
|
||||
"version": {"major": 1, "minor": 2, "patch": 0},
|
||||
"chains": [
|
||||
{
|
||||
"chainId": "0x8a",
|
||||
"chainIdDecimal": 138,
|
||||
"chainName": "DeFi Oracle Meta Mainnet",
|
||||
"rpcUrls": [
|
||||
"https://rpc-http-pub.d-bis.org",
|
||||
"https://rpc.d-bis.org",
|
||||
"https://rpc2.d-bis.org",
|
||||
"https://rpc.defi-oracle.io"
|
||||
],
|
||||
"nativeCurrency": {
|
||||
"name": "Ether",
|
||||
"symbol": "ETH",
|
||||
"decimals": 18
|
||||
},
|
||||
"blockExplorerUrls": ["https://explorer.d-bis.org"],
|
||||
"iconUrls": [
|
||||
"https://raw.githubusercontent.com/ethereum/ethereum.org/main/static/images/eth-diamond-black.png"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": "0x1",
|
||||
"chainIdDecimal": 1,
|
||||
"chainName": "Ethereum Mainnet",
|
||||
"rpcUrls": [
|
||||
"https://eth.llamarpc.com",
|
||||
"https://rpc.ankr.com/eth",
|
||||
"https://ethereum.publicnode.com",
|
||||
"https://1rpc.io/eth"
|
||||
],
|
||||
"nativeCurrency": {
|
||||
"name": "Ether",
|
||||
"symbol": "ETH",
|
||||
"decimals": 18
|
||||
},
|
||||
"blockExplorerUrls": ["https://etherscan.io"],
|
||||
"iconUrls": [
|
||||
"https://raw.githubusercontent.com/ethereum/ethereum.org/main/static/images/eth-diamond-black.png"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": "0x9f2c4",
|
||||
"chainIdDecimal": 651940,
|
||||
"chainName": "ALL Mainnet",
|
||||
"rpcUrls": ["https://mainnet-rpc.alltra.global"],
|
||||
"nativeCurrency": {
|
||||
"name": "Ether",
|
||||
"symbol": "ETH",
|
||||
"decimals": 18
|
||||
},
|
||||
"blockExplorerUrls": ["https://alltra.global"],
|
||||
"iconUrls": [
|
||||
"https://raw.githubusercontent.com/ethereum/ethereum.org/main/static/images/eth-diamond-black.png"
|
||||
]
|
||||
}
|
||||
{"chainId":"0x8a","chainIdDecimal":138,"chainName":"DeFi Oracle Meta Mainnet","rpcUrls":["https://rpc-http-pub.d-bis.org","https://rpc.d-bis.org","https://rpc2.d-bis.org","https://rpc.defi-oracle.io"],"nativeCurrency":{"name":"Ether","symbol":"ETH","decimals":18},"blockExplorerUrls":["https://explorer.d-bis.org"],"iconUrls":["https://raw.githubusercontent.com/ethereum/ethereum.org/main/static/images/eth-diamond-black.png"]},
|
||||
{"chainId":"0x1","chainIdDecimal":1,"chainName":"Ethereum Mainnet","rpcUrls":["https://eth.llamarpc.com","https://rpc.ankr.com/eth","https://ethereum.publicnode.com","https://1rpc.io/eth"],"nativeCurrency":{"name":"Ether","symbol":"ETH","decimals":18},"blockExplorerUrls":["https://etherscan.io"],"iconUrls":["https://raw.githubusercontent.com/ethereum/ethereum.org/main/static/images/eth-diamond-black.png"]},
|
||||
{"chainId":"0x9f2c4","chainIdDecimal":651940,"chainName":"ALL Mainnet","rpcUrls":["https://mainnet-rpc.alltra.global"],"nativeCurrency":{"name":"Ether","symbol":"ETH","decimals":18},"blockExplorerUrls":["https://alltra.global"],"iconUrls":["https://raw.githubusercontent.com/ethereum/ethereum.org/main/static/images/eth-diamond-black.png"]},
|
||||
{"chainId":"0x19","chainIdDecimal":25,"chainName":"Cronos Mainnet","rpcUrls":["https://evm.cronos.org","https://cronos-rpc.publicnode.com"],"nativeCurrency":{"name":"CRO","symbol":"CRO","decimals":18},"blockExplorerUrls":["https://cronos.org/explorer"],"iconUrls":["https://ipfs.io/ipfs/Qma3FKtLce9MjgJgWbtyCxBiPjJ6xi8jGWUSKNS5Jc2ong"]},
|
||||
{"chainId":"0x38","chainIdDecimal":56,"chainName":"BNB Smart Chain","rpcUrls":["https://bsc-dataseed.binance.org","https://bsc-dataseed1.defibit.io","https://bsc-dataseed1.ninicoin.io"],"nativeCurrency":{"name":"BNB","symbol":"BNB","decimals":18},"blockExplorerUrls":["https://bscscan.com"],"iconUrls":["https://raw.githubusercontent.com/ethereum/ethereum.org/main/static/images/eth-diamond-black.png"]},
|
||||
{"chainId":"0x64","chainIdDecimal":100,"chainName":"Gnosis Chain","rpcUrls":["https://rpc.gnosischain.com","https://gnosis-rpc.publicnode.com","https://1rpc.io/gnosis"],"nativeCurrency":{"name":"xDAI","symbol":"xDAI","decimals":18},"blockExplorerUrls":["https://gnosisscan.io"],"iconUrls":["https://raw.githubusercontent.com/ethereum/ethereum.org/main/static/images/eth-diamond-black.png"]},
|
||||
{"chainId":"0x89","chainIdDecimal":137,"chainName":"Polygon","rpcUrls":["https://polygon-rpc.com","https://polygon.llamarpc.com","https://polygon-bor-rpc.publicnode.com"],"nativeCurrency":{"name":"MATIC","symbol":"MATIC","decimals":18},"blockExplorerUrls":["https://polygonscan.com"],"iconUrls":["https://raw.githubusercontent.com/ethereum/ethereum.org/main/static/images/eth-diamond-black.png"]},
|
||||
{"chainId":"0xa","chainIdDecimal":10,"chainName":"Optimism","rpcUrls":["https://mainnet.optimism.io","https://optimism.llamarpc.com","https://optimism-rpc.publicnode.com"],"nativeCurrency":{"name":"Ether","symbol":"ETH","decimals":18},"blockExplorerUrls":["https://optimistic.etherscan.io"],"iconUrls":["https://raw.githubusercontent.com/ethereum/ethereum.org/main/static/images/eth-diamond-black.png"]},
|
||||
{"chainId":"0xa4b1","chainIdDecimal":42161,"chainName":"Arbitrum One","rpcUrls":["https://arb1.arbitrum.io/rpc","https://arbitrum.llamarpc.com","https://arbitrum-one-rpc.publicnode.com"],"nativeCurrency":{"name":"Ether","symbol":"ETH","decimals":18},"blockExplorerUrls":["https://arbiscan.io"],"iconUrls":["https://raw.githubusercontent.com/ethereum/ethereum.org/main/static/images/eth-diamond-black.png"]},
|
||||
{"chainId":"0x2105","chainIdDecimal":8453,"chainName":"Base","rpcUrls":["https://mainnet.base.org","https://base.llamarpc.com","https://base-rpc.publicnode.com"],"nativeCurrency":{"name":"Ether","symbol":"ETH","decimals":18},"blockExplorerUrls":["https://basescan.org"],"iconUrls":["https://raw.githubusercontent.com/ethereum/ethereum.org/main/static/images/eth-diamond-black.png"]},
|
||||
{"chainId":"0xa86a","chainIdDecimal":43114,"chainName":"Avalanche C-Chain","rpcUrls":["https://api.avax.network/ext/bc/C/rpc","https://avalanche-c-chain-rpc.publicnode.com","https://1rpc.io/avax/c"],"nativeCurrency":{"name":"AVAX","symbol":"AVAX","decimals":18},"blockExplorerUrls":["https://snowtrace.io"],"iconUrls":["https://raw.githubusercontent.com/ethereum/ethereum.org/main/static/images/eth-diamond-black.png"]},
|
||||
{"chainId":"0xa4ec","chainIdDecimal":42220,"chainName":"Celo","rpcUrls":["https://forno.celo.org","https://celo-mainnet-rpc.publicnode.com","https://1rpc.io/celo"],"nativeCurrency":{"name":"CELO","symbol":"CELO","decimals":18},"blockExplorerUrls":["https://celoscan.io"],"iconUrls":["https://raw.githubusercontent.com/ethereum/ethereum.org/main/static/images/eth-diamond-black.png"]},
|
||||
{"chainId":"0x457","chainIdDecimal":1111,"chainName":"Wemix","rpcUrls":["https://api.wemix.com","https://wemix-mainnet-rpc.publicnode.com"],"nativeCurrency":{"name":"WEMIX","symbol":"WEMIX","decimals":18},"blockExplorerUrls":["https://scan.wemix.com"],"iconUrls":["https://raw.githubusercontent.com/ethereum/ethereum.org/main/static/images/eth-diamond-black.png"]}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,115 +1,859 @@
|
||||
{
|
||||
"name": "Multi-Chain Token List (Chain 138 + Ethereum Mainnet + ALL Mainnet)",
|
||||
"version": { "major": 1, "minor": 1, "patch": 0 },
|
||||
"timestamp": "2026-01-30T00:00:00.000Z",
|
||||
"logoURI": "https://raw.githubusercontent.com/ethereum/ethereum.org/main/static/images/eth-diamond-black.png",
|
||||
"tokens": [
|
||||
{
|
||||
"chainId": 138,
|
||||
"address": "0x3304b747e565a97ec8ac220b0b6a1f6ffdb837e6",
|
||||
"name": "ETH/USD Price Feed",
|
||||
"symbol": "ETH-USD",
|
||||
"decimals": 8,
|
||||
"logoURI": "https://raw.githubusercontent.com/ethereum/ethereum.org/main/static/images/eth-diamond-black.png",
|
||||
"tags": ["oracle", "price-feed"]
|
||||
},
|
||||
{
|
||||
"chainId": 138,
|
||||
"address": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
|
||||
"name": "Wrapped Ether",
|
||||
"symbol": "WETH",
|
||||
"decimals": 18,
|
||||
"logoURI": "https://raw.githubusercontent.com/ethereum/ethereum.org/main/static/images/eth-diamond-black.png",
|
||||
"tags": ["defi", "wrapped"]
|
||||
},
|
||||
{
|
||||
"chainId": 138,
|
||||
"address": "0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9f",
|
||||
"name": "Wrapped Ether v10",
|
||||
"symbol": "WETH10",
|
||||
"decimals": 18,
|
||||
"logoURI": "https://raw.githubusercontent.com/ethereum/ethereum.org/main/static/images/eth-diamond-black.png",
|
||||
"tags": ["defi", "wrapped"]
|
||||
},
|
||||
{
|
||||
"chainId": 138,
|
||||
"address": "0x93E66202A11B1772E55407B32B44e5Cd8eda7f22",
|
||||
"name": "Compliant Tether USD",
|
||||
"symbol": "cUSDT",
|
||||
"decimals": 6,
|
||||
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xdAC17F958D2ee523a2206206994597C13D831ec7/logo.png",
|
||||
"tags": ["stablecoin", "defi", "compliant"]
|
||||
},
|
||||
{
|
||||
"chainId": 138,
|
||||
"address": "0xf22258f57794CC8E06237084b353Ab30fFfa640b",
|
||||
"name": "Compliant USD Coin",
|
||||
"symbol": "cUSDC",
|
||||
"decimals": 6,
|
||||
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png",
|
||||
"tags": ["stablecoin", "defi", "compliant"]
|
||||
},
|
||||
{
|
||||
"chainId": 1,
|
||||
"address": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
|
||||
"name": "Wrapped Ether",
|
||||
"symbol": "WETH",
|
||||
"decimals": 18,
|
||||
"logoURI": "https://raw.githubusercontent.com/ethereum/ethereum.org/main/static/images/eth-diamond-black.png",
|
||||
"tags": ["defi", "wrapped"]
|
||||
},
|
||||
{
|
||||
"chainId": 1,
|
||||
"address": "0xdAC17F958D2ee523a2206206994597C13D831ec7",
|
||||
"name": "Tether USD",
|
||||
"symbol": "USDT",
|
||||
"decimals": 6,
|
||||
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xdAC17F958D2ee523a2206206994597C13D831ec7/logo.png",
|
||||
"tags": ["stablecoin", "defi"]
|
||||
},
|
||||
{
|
||||
"chainId": 1,
|
||||
"address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
|
||||
"name": "USD Coin",
|
||||
"symbol": "USDC",
|
||||
"decimals": 6,
|
||||
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png",
|
||||
"tags": ["stablecoin", "defi"]
|
||||
},
|
||||
{
|
||||
"chainId": 1,
|
||||
"address": "0x6B175474E89094C44Da98b954EedeAC495271d0F",
|
||||
"name": "Dai Stablecoin",
|
||||
"symbol": "DAI",
|
||||
"decimals": 18,
|
||||
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6B175474E89094C44Da98b954EedeAC495271d0F/logo.png",
|
||||
"tags": ["stablecoin", "defi"]
|
||||
},
|
||||
{
|
||||
"chainId": 1,
|
||||
"address": "0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419",
|
||||
"name": "ETH/USD Price Feed",
|
||||
"symbol": "ETH-USD",
|
||||
"decimals": 8,
|
||||
"logoURI": "https://raw.githubusercontent.com/ethereum/ethereum.org/main/static/images/eth-diamond-black.png",
|
||||
"tags": ["oracle", "price-feed"]
|
||||
},
|
||||
{
|
||||
"chainId": 651940,
|
||||
"address": "0xa95EeD79f84E6A0151eaEb9d441F9Ffd50e8e881",
|
||||
"name": "USD Coin",
|
||||
"symbol": "USDC",
|
||||
"decimals": 6,
|
||||
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png",
|
||||
"tags": ["stablecoin", "defi"]
|
||||
}
|
||||
],
|
||||
"tags": {
|
||||
"defi": { "name": "DeFi", "description": "Decentralized Finance tokens" },
|
||||
"wrapped": { "name": "Wrapped", "description": "Wrapped tokens representing native assets" },
|
||||
"oracle": { "name": "Oracle", "description": "Oracle price feed contracts" },
|
||||
"price-feed": { "name": "Price Feed", "description": "Price feed oracle contracts" },
|
||||
"stablecoin": { "name": "Stablecoin", "description": "Stable value tokens pegged to fiat" },
|
||||
"compliant": { "name": "Compliant", "description": "Regulatory compliant tokens" }
|
||||
}
|
||||
"name": "Multi-Chain Token List (13 chains, 138 base)",
|
||||
"version": {
|
||||
"major": 1,
|
||||
"minor": 3,
|
||||
"patch": 0
|
||||
},
|
||||
"timestamp": "2026-02-28T00:00:00.000Z",
|
||||
"logoURI": "https://ipfs.io/ipfs/Qma3FKtLce9MjgJgWbtyCxBiPjJ6xi8jGWUSKNS5Jc2ong",
|
||||
"tokens": [
|
||||
{
|
||||
"chainId": 138,
|
||||
"address": "0x3304b747e565a97ec8ac220b0b6a1f6ffdb837e6",
|
||||
"name": "ETH/USD Price Feed",
|
||||
"symbol": "ETH-USD",
|
||||
"decimals": 8,
|
||||
"logoURI": "https://ipfs.io/ipfs/QmPZuycjyJEe2otREuQ5HirvPJ8X6Yc6MBtwz1VhdD79pY",
|
||||
"tags": [
|
||||
"oracle",
|
||||
"price-feed"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 138,
|
||||
"address": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
|
||||
"name": "Wrapped Ether",
|
||||
"symbol": "WETH",
|
||||
"decimals": 18,
|
||||
"logoURI": "https://ipfs.io/ipfs/Qma3FKtLce9MjgJgWbtyCxBiPjJ6xi8jGWUSKNS5Jc2ong",
|
||||
"tags": [
|
||||
"defi",
|
||||
"wrapped"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 138,
|
||||
"address": "0xf4BB2e28688e89fCcE3c0580D37d36A7672E8A9F",
|
||||
"name": "Wrapped Ether v10",
|
||||
"symbol": "WETH10",
|
||||
"decimals": 18,
|
||||
"logoURI": "https://ipfs.io/ipfs/QmanDFPHxnbKd6SSNzzXHf9GbpL9dLXSphxDZSPPYE6ds4",
|
||||
"tags": [
|
||||
"defi",
|
||||
"wrapped"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 138,
|
||||
"address": "0xb7721dD53A8c629d9f1Ba31a5819AFe250002b03",
|
||||
"name": "Chainlink Token",
|
||||
"symbol": "LINK",
|
||||
"decimals": 18,
|
||||
"logoURI": "https://ipfs.io/ipfs/QmenWcmfNGfssz4HXvrRV912eZDiKqLTt6z2brRYuTGz9A",
|
||||
"tags": [
|
||||
"defi",
|
||||
"oracle",
|
||||
"ccip"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 138,
|
||||
"address": "0x93E66202A11B1772E55407B32B44e5Cd8eda7f22",
|
||||
"name": "Compliant Tether USD",
|
||||
"symbol": "cUSDT",
|
||||
"decimals": 6,
|
||||
"logoURI": "https://ipfs.io/ipfs/QmRfhPs9DcyFPpGjKwF6CCoVDWUHSxkQR34n9NK7JSbPCP",
|
||||
"tags": [
|
||||
"stablecoin",
|
||||
"defi",
|
||||
"compliant"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 138,
|
||||
"address": "0xf22258f57794CC8E06237084b353Ab30fFfa640b",
|
||||
"name": "Compliant USD Coin",
|
||||
"symbol": "cUSDC",
|
||||
"decimals": 6,
|
||||
"logoURI": "https://ipfs.io/ipfs/QmNPq4D5JXzurmi9jAhogVMzhAQRk1PZ1r9H3qQUV9gjDm",
|
||||
"tags": [
|
||||
"stablecoin",
|
||||
"defi",
|
||||
"compliant"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 1,
|
||||
"address": "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
|
||||
"name": "USD Coin",
|
||||
"symbol": "USDC",
|
||||
"decimals": 6,
|
||||
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png",
|
||||
"tags": [
|
||||
"stablecoin",
|
||||
"defi"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 1,
|
||||
"address": "0xdAC17F958D2ee523a2206206994597C13D831ec7",
|
||||
"name": "Tether USD",
|
||||
"symbol": "USDT",
|
||||
"decimals": 6,
|
||||
"logoURI": "https://ipfs.io/ipfs/QmRfhPs9DcyFPpGjKwF6CCoVDWUHSxkQR34n9NK7JSbPCP",
|
||||
"tags": [
|
||||
"stablecoin",
|
||||
"defi"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 1,
|
||||
"address": "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2",
|
||||
"name": "Wrapped Ether",
|
||||
"symbol": "WETH",
|
||||
"decimals": 18,
|
||||
"logoURI": "https://ipfs.io/ipfs/Qma3FKtLce9MjgJgWbtyCxBiPjJ6xi8jGWUSKNS5Jc2ong",
|
||||
"tags": [
|
||||
"defi",
|
||||
"wrapped"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 1,
|
||||
"address": "0x514910771AF9Ca656af840dff83E8264EcF986CA",
|
||||
"name": "Chainlink Token",
|
||||
"symbol": "LINK",
|
||||
"decimals": 18,
|
||||
"logoURI": "https://ipfs.io/ipfs/QmenWcmfNGfssz4HXvrRV912eZDiKqLTt6z2brRYuTGz9A",
|
||||
"tags": [
|
||||
"defi",
|
||||
"oracle",
|
||||
"ccip"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 1,
|
||||
"address": "0x6B175474E89094C44Da98b954EedeAC495271d0F",
|
||||
"name": "Dai Stablecoin",
|
||||
"symbol": "DAI",
|
||||
"decimals": 18,
|
||||
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6B175474E89094C44Da98b954EedeAC495271d0F/logo.png",
|
||||
"tags": [
|
||||
"stablecoin",
|
||||
"defi"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 1,
|
||||
"address": "0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419",
|
||||
"name": "ETH/USD Price Feed",
|
||||
"symbol": "ETH-USD",
|
||||
"decimals": 8,
|
||||
"logoURI": "https://raw.githubusercontent.com/ethereum/ethereum.org/main/static/images/eth-diamond-black.png",
|
||||
"tags": [
|
||||
"oracle",
|
||||
"price-feed"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 651940,
|
||||
"address": "0xa95EeD79f84E6A0151eaEb9d441F9Ffd50e8e881",
|
||||
"name": "USD Coin",
|
||||
"symbol": "USDC",
|
||||
"decimals": 6,
|
||||
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png",
|
||||
"tags": [
|
||||
"stablecoin",
|
||||
"defi"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 651940,
|
||||
"address": "0x015B1897Ed5279930bC2Be46F661894d219292A6",
|
||||
"name": "Tether USD",
|
||||
"symbol": "USDT",
|
||||
"decimals": 6,
|
||||
"logoURI": "https://ipfs.io/ipfs/QmRfhPs9DcyFPpGjKwF6CCoVDWUHSxkQR34n9NK7JSbPCP",
|
||||
"tags": [
|
||||
"stablecoin",
|
||||
"defi"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 25,
|
||||
"address": "0xc21223249CA28397B4B6541dfFaEcC539BfF0c59",
|
||||
"name": "USD Coin",
|
||||
"symbol": "USDC",
|
||||
"decimals": 6,
|
||||
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png",
|
||||
"tags": [
|
||||
"stablecoin",
|
||||
"defi"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 25,
|
||||
"address": "0x66e4286603D22FF153A6547700f37C7Eae42F8E2",
|
||||
"name": "Tether USD",
|
||||
"symbol": "USDT",
|
||||
"decimals": 6,
|
||||
"logoURI": "https://ipfs.io/ipfs/QmRfhPs9DcyFPpGjKwF6CCoVDWUHSxkQR34n9NK7JSbPCP",
|
||||
"tags": [
|
||||
"stablecoin",
|
||||
"defi"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 25,
|
||||
"address": "0x99B3511A2d315A497C8112C1fdd8D508d4B1E506",
|
||||
"name": "Wrapped Ether (WETH9)",
|
||||
"symbol": "WETH",
|
||||
"decimals": 18,
|
||||
"logoURI": "https://ipfs.io/ipfs/Qma3FKtLce9MjgJgWbtyCxBiPjJ6xi8jGWUSKNS5Jc2ong",
|
||||
"tags": [
|
||||
"defi",
|
||||
"wrapped"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 25,
|
||||
"address": "0x3304b747E565a97ec8AC220b0B6A1f6ffDB837e6",
|
||||
"name": "Wrapped Ether v10",
|
||||
"symbol": "WETH10",
|
||||
"decimals": 18,
|
||||
"logoURI": "https://ipfs.io/ipfs/QmanDFPHxnbKd6SSNzzXHf9GbpL9dLXSphxDZSPPYE6ds4",
|
||||
"tags": [
|
||||
"defi",
|
||||
"wrapped"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 25,
|
||||
"address": "0x8c80A01F461f297Df7F9DA3A4f740D7297C8Ac85",
|
||||
"name": "Chainlink Token",
|
||||
"symbol": "LINK",
|
||||
"decimals": 18,
|
||||
"logoURI": "https://ipfs.io/ipfs/QmenWcmfNGfssz4HXvrRV912eZDiKqLTt6z2brRYuTGz9A",
|
||||
"tags": [
|
||||
"defi",
|
||||
"oracle",
|
||||
"ccip"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 25,
|
||||
"address": "0x948690147D2e50ffe50C5d38C14125aD6a9FA036",
|
||||
"name": "USD W Token",
|
||||
"symbol": "USDW",
|
||||
"decimals": 2,
|
||||
"logoURI": "https://ipfs.io/ipfs/QmNPq4D5JXzurmi9jAhogVMzhAQRk1PZ1r9H3qQUV9gjDm",
|
||||
"tags": [
|
||||
"stablecoin",
|
||||
"iso4217w"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 25,
|
||||
"address": "0x58a8D8F78F1B65c06dAd7542eC46b299629A60dd",
|
||||
"name": "EUR W Token",
|
||||
"symbol": "EURW",
|
||||
"decimals": 2,
|
||||
"logoURI": "https://ipfs.io/ipfs/QmPh16PY241zNtePyeK7ep1uf1RcARV2ynGAuRU8U7sSqS",
|
||||
"tags": [
|
||||
"stablecoin",
|
||||
"iso4217w"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 25,
|
||||
"address": "0xFb4B6Cc81211F7d886950158294A44C312abCA29",
|
||||
"name": "GBP W Token",
|
||||
"symbol": "GBPW",
|
||||
"decimals": 2,
|
||||
"logoURI": "https://ipfs.io/ipfs/QmT2nJ6WyhYBCsYJ6NfS1BPAqiGKkCEuMxiC8ye93Co1hF",
|
||||
"tags": [
|
||||
"stablecoin",
|
||||
"iso4217w"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 25,
|
||||
"address": "0xf9f5D0ACD71C76F9476F10B3F3d3E201F0883C68",
|
||||
"name": "AUD W Token",
|
||||
"symbol": "AUDW",
|
||||
"decimals": 2,
|
||||
"logoURI": "https://ipfs.io/ipfs/Qmb9JmuD9ehaQtTLBBZmAoiAbvE53e3FMjkEty8rvbPf9K",
|
||||
"tags": [
|
||||
"stablecoin",
|
||||
"iso4217w"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 25,
|
||||
"address": "0xeE17bB0322383fecCA2784fbE2d4CD7d02b1905B",
|
||||
"name": "JPY W Token",
|
||||
"symbol": "JPYW",
|
||||
"decimals": 2,
|
||||
"logoURI": "https://ipfs.io/ipfs/Qmb9JmuD9ehaQtTLBBZmAoiAbvE53e3FMjkEty8rvbPf9K",
|
||||
"tags": [
|
||||
"stablecoin",
|
||||
"iso4217w"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 25,
|
||||
"address": "0xc9750828124D4c10e7a6f4B655cA8487bD3842EB",
|
||||
"name": "CHF W Token",
|
||||
"symbol": "CHFW",
|
||||
"decimals": 2,
|
||||
"logoURI": "https://ipfs.io/ipfs/Qmb9JmuD9ehaQtTLBBZmAoiAbvE53e3FMjkEty8rvbPf9K",
|
||||
"tags": [
|
||||
"stablecoin",
|
||||
"iso4217w"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 25,
|
||||
"address": "0x328Cd365Bb35524297E68ED28c6fF2C9557d1363",
|
||||
"name": "CAD W Token",
|
||||
"symbol": "CADW",
|
||||
"decimals": 2,
|
||||
"logoURI": "https://ipfs.io/ipfs/Qmb9JmuD9ehaQtTLBBZmAoiAbvE53e3FMjkEty8rvbPf9K",
|
||||
"tags": [
|
||||
"stablecoin",
|
||||
"iso4217w"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 56,
|
||||
"address": "0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d",
|
||||
"name": "USD Coin",
|
||||
"symbol": "USDC",
|
||||
"decimals": 6,
|
||||
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png",
|
||||
"tags": [
|
||||
"stablecoin",
|
||||
"defi"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 56,
|
||||
"address": "0x55d398326f99059fF775485246999027B3197955",
|
||||
"name": "Tether USD",
|
||||
"symbol": "USDT",
|
||||
"decimals": 6,
|
||||
"logoURI": "https://ipfs.io/ipfs/QmRfhPs9DcyFPpGjKwF6CCoVDWUHSxkQR34n9NK7JSbPCP",
|
||||
"tags": [
|
||||
"stablecoin",
|
||||
"defi"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 56,
|
||||
"address": "0x2170Ed0880ac9A755fd29B2688956BD959F933F8",
|
||||
"name": "Wrapped Ether",
|
||||
"symbol": "WETH",
|
||||
"decimals": 18,
|
||||
"logoURI": "https://ipfs.io/ipfs/Qma3FKtLce9MjgJgWbtyCxBiPjJ6xi8jGWUSKNS5Jc2ong",
|
||||
"tags": [
|
||||
"defi",
|
||||
"wrapped"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 56,
|
||||
"address": "0x404460C6A5EdE2D891e8297795264fDe62ADBB75",
|
||||
"name": "Chainlink Token",
|
||||
"symbol": "LINK",
|
||||
"decimals": 18,
|
||||
"logoURI": "https://ipfs.io/ipfs/QmenWcmfNGfssz4HXvrRV912eZDiKqLTt6z2brRYuTGz9A",
|
||||
"tags": [
|
||||
"defi",
|
||||
"oracle",
|
||||
"ccip"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 56,
|
||||
"address": "0x1AF3F329e8BE154074D8769D1FFa4eE058B1DBc3",
|
||||
"name": "Dai Stablecoin",
|
||||
"symbol": "DAI",
|
||||
"decimals": 18,
|
||||
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6B175474E89094C44Da98b954EedeAC495271d0F/logo.png",
|
||||
"tags": [
|
||||
"stablecoin",
|
||||
"defi"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 100,
|
||||
"address": "0xDDAfbb505ad214D7b80b1f830fcCc89B60fb7A83",
|
||||
"name": "USD Coin",
|
||||
"symbol": "USDC",
|
||||
"decimals": 6,
|
||||
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png",
|
||||
"tags": [
|
||||
"stablecoin",
|
||||
"defi"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 100,
|
||||
"address": "0x4ECaBa5870353805a9F068101A40E0f32ed605C6",
|
||||
"name": "Tether USD",
|
||||
"symbol": "USDT",
|
||||
"decimals": 6,
|
||||
"logoURI": "https://ipfs.io/ipfs/QmRfhPs9DcyFPpGjKwF6CCoVDWUHSxkQR34n9NK7JSbPCP",
|
||||
"tags": [
|
||||
"stablecoin",
|
||||
"defi"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 100,
|
||||
"address": "0x6A023CCd1ff6F2045C3309768eAd9E68F978f6e1",
|
||||
"name": "Wrapped Ether",
|
||||
"symbol": "WETH",
|
||||
"decimals": 18,
|
||||
"logoURI": "https://ipfs.io/ipfs/Qma3FKtLce9MjgJgWbtyCxBiPjJ6xi8jGWUSKNS5Jc2ong",
|
||||
"tags": [
|
||||
"defi",
|
||||
"wrapped"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 100,
|
||||
"address": "0xE2e73A1c69ecF83F464EFCE6A5be353a37cA09b2",
|
||||
"name": "Chainlink Token",
|
||||
"symbol": "LINK",
|
||||
"decimals": 18,
|
||||
"logoURI": "https://ipfs.io/ipfs/QmenWcmfNGfssz4HXvrRV912eZDiKqLTt6z2brRYuTGz9A",
|
||||
"tags": [
|
||||
"defi",
|
||||
"oracle",
|
||||
"ccip"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 100,
|
||||
"address": "0xe91D153E0b41518A2Ce8Dd3D7944Fa863463a97d",
|
||||
"name": "Dai Stablecoin",
|
||||
"symbol": "DAI",
|
||||
"decimals": 18,
|
||||
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6B175474E89094C44Da98b954EedeAC495271d0F/logo.png",
|
||||
"tags": [
|
||||
"stablecoin",
|
||||
"defi"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 137,
|
||||
"address": "0x3c499c542cEF5E3811e1192ce70d8cC03d5c1369",
|
||||
"name": "USD Coin",
|
||||
"symbol": "USDC",
|
||||
"decimals": 6,
|
||||
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png",
|
||||
"tags": [
|
||||
"stablecoin",
|
||||
"defi"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 137,
|
||||
"address": "0xc2132D05D31c914a87C6611C10748AEb04B58e8F",
|
||||
"name": "Tether USD",
|
||||
"symbol": "USDT",
|
||||
"decimals": 6,
|
||||
"logoURI": "https://ipfs.io/ipfs/QmRfhPs9DcyFPpGjKwF6CCoVDWUHSxkQR34n9NK7JSbPCP",
|
||||
"tags": [
|
||||
"stablecoin",
|
||||
"defi"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 137,
|
||||
"address": "0x7ceB23fD6bC0adD59E62ac25578270cFf1b9f619",
|
||||
"name": "Wrapped Ether",
|
||||
"symbol": "WETH",
|
||||
"decimals": 18,
|
||||
"logoURI": "https://ipfs.io/ipfs/Qma3FKtLce9MjgJgWbtyCxBiPjJ6xi8jGWUSKNS5Jc2ong",
|
||||
"tags": [
|
||||
"defi",
|
||||
"wrapped"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 137,
|
||||
"address": "0xb0897686c545045aFc77CF20eC7A532E3120E0F1",
|
||||
"name": "Chainlink Token",
|
||||
"symbol": "LINK",
|
||||
"decimals": 18,
|
||||
"logoURI": "https://ipfs.io/ipfs/QmenWcmfNGfssz4HXvrRV912eZDiKqLTt6z2brRYuTGz9A",
|
||||
"tags": [
|
||||
"defi",
|
||||
"oracle",
|
||||
"ccip"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 137,
|
||||
"address": "0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063",
|
||||
"name": "Dai Stablecoin",
|
||||
"symbol": "DAI",
|
||||
"decimals": 18,
|
||||
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6B175474E89094C44Da98b954EedeAC495271d0F/logo.png",
|
||||
"tags": [
|
||||
"stablecoin",
|
||||
"defi"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 10,
|
||||
"address": "0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85",
|
||||
"name": "USD Coin",
|
||||
"symbol": "USDC",
|
||||
"decimals": 6,
|
||||
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png",
|
||||
"tags": [
|
||||
"stablecoin",
|
||||
"defi"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 10,
|
||||
"address": "0x94b008aA00579c1307B0EF2c499aD98a8ce58e58",
|
||||
"name": "Tether USD",
|
||||
"symbol": "USDT",
|
||||
"decimals": 6,
|
||||
"logoURI": "https://ipfs.io/ipfs/QmRfhPs9DcyFPpGjKwF6CCoVDWUHSxkQR34n9NK7JSbPCP",
|
||||
"tags": [
|
||||
"stablecoin",
|
||||
"defi"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 10,
|
||||
"address": "0x4200000000000000000000000000000000000006",
|
||||
"name": "Wrapped Ether",
|
||||
"symbol": "WETH",
|
||||
"decimals": 18,
|
||||
"logoURI": "https://ipfs.io/ipfs/Qma3FKtLce9MjgJgWbtyCxBiPjJ6xi8jGWUSKNS5Jc2ong",
|
||||
"tags": [
|
||||
"defi",
|
||||
"wrapped"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 10,
|
||||
"address": "0x350a791Bfc2C21F9Ed5d10980Dad2e2638ffa7f6",
|
||||
"name": "Chainlink Token",
|
||||
"symbol": "LINK",
|
||||
"decimals": 18,
|
||||
"logoURI": "https://ipfs.io/ipfs/QmenWcmfNGfssz4HXvrRV912eZDiKqLTt6z2brRYuTGz9A",
|
||||
"tags": [
|
||||
"defi",
|
||||
"oracle",
|
||||
"ccip"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 10,
|
||||
"address": "0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1",
|
||||
"name": "Dai Stablecoin",
|
||||
"symbol": "DAI",
|
||||
"decimals": 18,
|
||||
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6B175474E89094C44Da98b954EedeAC495271d0F/logo.png",
|
||||
"tags": [
|
||||
"stablecoin",
|
||||
"defi"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 42161,
|
||||
"address": "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
|
||||
"name": "USD Coin",
|
||||
"symbol": "USDC",
|
||||
"decimals": 6,
|
||||
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png",
|
||||
"tags": [
|
||||
"stablecoin",
|
||||
"defi"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 42161,
|
||||
"address": "0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9",
|
||||
"name": "Tether USD",
|
||||
"symbol": "USDT",
|
||||
"decimals": 6,
|
||||
"logoURI": "https://ipfs.io/ipfs/QmRfhPs9DcyFPpGjKwF6CCoVDWUHSxkQR34n9NK7JSbPCP",
|
||||
"tags": [
|
||||
"stablecoin",
|
||||
"defi"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 42161,
|
||||
"address": "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1",
|
||||
"name": "Wrapped Ether",
|
||||
"symbol": "WETH",
|
||||
"decimals": 18,
|
||||
"logoURI": "https://ipfs.io/ipfs/Qma3FKtLce9MjgJgWbtyCxBiPjJ6xi8jGWUSKNS5Jc2ong",
|
||||
"tags": [
|
||||
"defi",
|
||||
"wrapped"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 42161,
|
||||
"address": "0xf97f4df75117a78c1A5a0DBb814Af92458539FB4",
|
||||
"name": "Chainlink Token",
|
||||
"symbol": "LINK",
|
||||
"decimals": 18,
|
||||
"logoURI": "https://ipfs.io/ipfs/QmenWcmfNGfssz4HXvrRV912eZDiKqLTt6z2brRYuTGz9A",
|
||||
"tags": [
|
||||
"defi",
|
||||
"oracle",
|
||||
"ccip"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 42161,
|
||||
"address": "0xDA10009cBd5D07dd0CeCc66161FC93D7c9000da1",
|
||||
"name": "Dai Stablecoin",
|
||||
"symbol": "DAI",
|
||||
"decimals": 18,
|
||||
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6B175474E89094C44Da98b954EedeAC495271d0F/logo.png",
|
||||
"tags": [
|
||||
"stablecoin",
|
||||
"defi"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 8453,
|
||||
"address": "0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
|
||||
"name": "USD Coin",
|
||||
"symbol": "USDC",
|
||||
"decimals": 6,
|
||||
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png",
|
||||
"tags": [
|
||||
"stablecoin",
|
||||
"defi"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 8453,
|
||||
"address": "0xfde4C96c8593536E31F229EA8f37b2ADa2699bb2",
|
||||
"name": "Tether USD",
|
||||
"symbol": "USDT",
|
||||
"decimals": 6,
|
||||
"logoURI": "https://ipfs.io/ipfs/QmRfhPs9DcyFPpGjKwF6CCoVDWUHSxkQR34n9NK7JSbPCP",
|
||||
"tags": [
|
||||
"stablecoin",
|
||||
"defi"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 8453,
|
||||
"address": "0x4200000000000000000000000000000000000006",
|
||||
"name": "Wrapped Ether",
|
||||
"symbol": "WETH",
|
||||
"decimals": 18,
|
||||
"logoURI": "https://ipfs.io/ipfs/Qma3FKtLce9MjgJgWbtyCxBiPjJ6xi8jGWUSKNS5Jc2ong",
|
||||
"tags": [
|
||||
"defi",
|
||||
"wrapped"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 8453,
|
||||
"address": "0x88Fb150BDc53A65fe94Dea0c9BA0a6dAf8C6e196",
|
||||
"name": "Chainlink Token",
|
||||
"symbol": "LINK",
|
||||
"decimals": 18,
|
||||
"logoURI": "https://ipfs.io/ipfs/QmenWcmfNGfssz4HXvrRV912eZDiKqLTt6z2brRYuTGz9A",
|
||||
"tags": [
|
||||
"defi",
|
||||
"oracle",
|
||||
"ccip"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 8453,
|
||||
"address": "0x50c5725949A6F0c72E6C4a641F24049A917DB0Cb",
|
||||
"name": "Dai Stablecoin",
|
||||
"symbol": "DAI",
|
||||
"decimals": 18,
|
||||
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6B175474E89094C44Da98b954EedeAC495271d0F/logo.png",
|
||||
"tags": [
|
||||
"stablecoin",
|
||||
"defi"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 43114,
|
||||
"address": "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E",
|
||||
"name": "USD Coin",
|
||||
"symbol": "USDC",
|
||||
"decimals": 6,
|
||||
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png",
|
||||
"tags": [
|
||||
"stablecoin",
|
||||
"defi"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 43114,
|
||||
"address": "0x9702230A8Ea53601f5cD2dc00fDBc13d4dF4A8c7",
|
||||
"name": "Tether USD",
|
||||
"symbol": "USDT",
|
||||
"decimals": 6,
|
||||
"logoURI": "https://ipfs.io/ipfs/QmRfhPs9DcyFPpGjKwF6CCoVDWUHSxkQR34n9NK7JSbPCP",
|
||||
"tags": [
|
||||
"stablecoin",
|
||||
"defi"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 43114,
|
||||
"address": "0x49D5c2BdFfac6CE2BFdB6640F4F80f226bc10bAB",
|
||||
"name": "Wrapped Ether",
|
||||
"symbol": "WETH",
|
||||
"decimals": 18,
|
||||
"logoURI": "https://ipfs.io/ipfs/Qma3FKtLce9MjgJgWbtyCxBiPjJ6xi8jGWUSKNS5Jc2ong",
|
||||
"tags": [
|
||||
"defi",
|
||||
"wrapped"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 43114,
|
||||
"address": "0x5947BB275c521040051D82396192181b413227A3",
|
||||
"name": "Chainlink Token",
|
||||
"symbol": "LINK",
|
||||
"decimals": 18,
|
||||
"logoURI": "https://ipfs.io/ipfs/QmenWcmfNGfssz4HXvrRV912eZDiKqLTt6z2brRYuTGz9A",
|
||||
"tags": [
|
||||
"defi",
|
||||
"oracle",
|
||||
"ccip"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 43114,
|
||||
"address": "0xd586E7F844cEa2F87f50152665BCbc2C279D8d70",
|
||||
"name": "Dai Stablecoin",
|
||||
"symbol": "DAI",
|
||||
"decimals": 18,
|
||||
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0x6B175474E89094C44Da98b954EedeAC495271d0F/logo.png",
|
||||
"tags": [
|
||||
"stablecoin",
|
||||
"defi"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 42220,
|
||||
"address": "0xcebA9300f2b948710d2653dD7B07f33A8B32118C",
|
||||
"name": "USD Coin",
|
||||
"symbol": "USDC",
|
||||
"decimals": 6,
|
||||
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png",
|
||||
"tags": [
|
||||
"stablecoin",
|
||||
"defi"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 42220,
|
||||
"address": "0x48065fbBE25f71C9282ddf5e1cD6D6A887483D5e",
|
||||
"name": "Tether USD",
|
||||
"symbol": "USDT",
|
||||
"decimals": 6,
|
||||
"logoURI": "https://ipfs.io/ipfs/QmRfhPs9DcyFPpGjKwF6CCoVDWUHSxkQR34n9NK7JSbPCP",
|
||||
"tags": [
|
||||
"stablecoin",
|
||||
"defi"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 42220,
|
||||
"address": "0x122013fd7dF1C6F636a5bb8f03108E876548b455",
|
||||
"name": "Wrapped Ether",
|
||||
"symbol": "WETH",
|
||||
"decimals": 18,
|
||||
"logoURI": "https://ipfs.io/ipfs/Qma3FKtLce9MjgJgWbtyCxBiPjJ6xi8jGWUSKNS5Jc2ong",
|
||||
"tags": [
|
||||
"defi",
|
||||
"wrapped"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 42220,
|
||||
"address": "0xd07294e6E917e07dfDcee882dd1e2565085C2ae0",
|
||||
"name": "Chainlink Token",
|
||||
"symbol": "LINK",
|
||||
"decimals": 18,
|
||||
"logoURI": "https://ipfs.io/ipfs/QmenWcmfNGfssz4HXvrRV912eZDiKqLTt6z2brRYuTGz9A",
|
||||
"tags": [
|
||||
"defi",
|
||||
"oracle",
|
||||
"ccip"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 1111,
|
||||
"address": "0xE3F5a90F9cb311505cd691a46596599aA1A0AD7D",
|
||||
"name": "USD Coin",
|
||||
"symbol": "USDC",
|
||||
"decimals": 6,
|
||||
"logoURI": "https://raw.githubusercontent.com/trustwallet/assets/master/blockchains/ethereum/assets/0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48/logo.png",
|
||||
"tags": [
|
||||
"stablecoin",
|
||||
"defi"
|
||||
]
|
||||
},
|
||||
{
|
||||
"chainId": 1111,
|
||||
"address": "0xA649325Aa7C5093d12D6F98EB4378deAe68CE23F",
|
||||
"name": "Tether USD",
|
||||
"symbol": "USDT",
|
||||
"decimals": 6,
|
||||
"logoURI": "https://ipfs.io/ipfs/QmRfhPs9DcyFPpGjKwF6CCoVDWUHSxkQR34n9NK7JSbPCP",
|
||||
"tags": [
|
||||
"stablecoin",
|
||||
"defi"
|
||||
]
|
||||
}
|
||||
],
|
||||
"tags": {
|
||||
"defi": {
|
||||
"name": "DeFi",
|
||||
"description": "Decentralized Finance tokens"
|
||||
},
|
||||
"wrapped": {
|
||||
"name": "Wrapped",
|
||||
"description": "Wrapped tokens representing native assets"
|
||||
},
|
||||
"oracle": {
|
||||
"name": "Oracle",
|
||||
"description": "Oracle price feed contracts"
|
||||
},
|
||||
"price-feed": {
|
||||
"name": "Price Feed",
|
||||
"description": "Price feed oracle contracts"
|
||||
},
|
||||
"stablecoin": {
|
||||
"name": "Stablecoin",
|
||||
"description": "Stable value tokens pegged to fiat"
|
||||
},
|
||||
"compliant": {
|
||||
"name": "Compliant",
|
||||
"description": "Regulatory compliant tokens"
|
||||
},
|
||||
"iso4217w": {
|
||||
"name": "ISO4217W",
|
||||
"description": "ISO 4217 compliant wrapped fiat tokens"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,184 @@
|
||||
# Crunchygalaxy Unip. Lda. — Office Creation + 1.0B USD M1 Funding
|
||||
|
||||
**Entity:** CRUNCHYGALAXY UNIP. LDA.
|
||||
**NIPC:** 515159573
|
||||
**Address:** Av. da Liberdade nº 110 – 1º, 1269-046 Lisboa, Portugal
|
||||
|
||||
Full cycle: create office → 1.0B M1 from Head Office (Rail B two-leg) → audit → closure → artifact packaging → upload per PDF.
|
||||
|
||||
---
|
||||
|
||||
## Phase 1 — Create New Office (Crunchygalaxy)
|
||||
|
||||
### 1.1 Confirm next available officeId
|
||||
|
||||
```bash
|
||||
source omnl-fineract/.env
|
||||
BASE="${OMNL_FINERACT_BASE_URL}"
|
||||
TENANT="${OMNL_FINERACT_TENANT:-omnl}"
|
||||
AUTH="-u ${OMNL_FINERACT_USER}:${OMNL_FINERACT_PASSWORD}"
|
||||
|
||||
curl -s -H "Fineract-Platform-TenantId: $TENANT" -H "Content-Type: application/json" $AUTH \
|
||||
"$BASE/offices" | jq '.[] | {id, name}'
|
||||
```
|
||||
|
||||
Use the next free ID (e.g. **21**). Replace `21` below if different.
|
||||
|
||||
### 1.2 Create Office
|
||||
|
||||
```bash
|
||||
curl -X POST "$BASE/offices" \
|
||||
-H "Fineract-Platform-TenantId: $TENANT" \
|
||||
-H "Content-Type: application/json" $AUTH \
|
||||
-d '{
|
||||
"name": "Crunchygalaxy Unip Lda - Portugal",
|
||||
"parentId": 1,
|
||||
"openingDate": "2026-02-24",
|
||||
"dateFormat": "yyyy-MM-dd",
|
||||
"locale": "en",
|
||||
"externalId": "CRUNCHYGALAXY-515159573"
|
||||
}'
|
||||
```
|
||||
|
||||
Confirm HTTP 200 and note returned `resourceId` / `officeId` (e.g. 21).
|
||||
|
||||
---
|
||||
|
||||
## Phase 2 — Transfer 1.0B USD M1 (Rail B: HO → Office 21)
|
||||
|
||||
**Economic result:** HO −1.0B; Office 21 +1.0B (symmetric).
|
||||
|
||||
### 2.1 Prep (IDs + closures + pre-audit)
|
||||
|
||||
```bash
|
||||
bash scripts/omnl/resolve_ids.sh
|
||||
source ids.env
|
||||
|
||||
bash scripts/omnl/omnl-gl-closures-post.sh
|
||||
# Pre-audit for HO/Office 20 (baseline); then post-audit for Office 21 after funding
|
||||
OFFICE_ID=21 bash scripts/omnl/omnl-audit-packet-office20.sh
|
||||
```
|
||||
|
||||
(Pre-audit for office 21 will be empty until after Leg 2; optional. Alternatively run pre-audit for office 20 only.)
|
||||
|
||||
### 2.2 Leg 1 — Head Office reduction (Office 1)
|
||||
|
||||
Dr 2100 / Cr 1410, 1,000,000,000. Replace `<<APPROVER_NAME>>`.
|
||||
|
||||
```bash
|
||||
export REFERENCE_NUMBER="CRUNCHY-1-20260224-TR1-1B-L1"
|
||||
export TX_DATE="2026-02-24"
|
||||
export AMOUNT="1000000000"
|
||||
|
||||
REQUIRES_APPROVAL=1 APPROVER="<<APPROVER_NAME>>" \
|
||||
REFERENCE_NUMBER="$REFERENCE_NUMBER" TX_DATE="$TX_DATE" OFFICE_ID=1 \
|
||||
DEBIT_GL_ID="$ID_2100" CREDIT_GL_ID="$ID_1410" AMOUNT="$AMOUNT" \
|
||||
bash scripts/omnl/omnl-je-maker.sh
|
||||
|
||||
# Payload file may have trailing _ (safe_ref); use the one created
|
||||
PAYLOAD_FILE="reconciliation/je-${REFERENCE_NUMBER}_.payload.json" \
|
||||
bash scripts/omnl/omnl-je-checker.sh
|
||||
```
|
||||
|
||||
If the payload has no trailing underscore, use `reconciliation/je-${REFERENCE_NUMBER}.payload.json`.
|
||||
|
||||
### 2.3 Leg 2 — Crunchygalaxy office funding (Office 21)
|
||||
|
||||
Dr 1410 / Cr 2100, 1,000,000,000.
|
||||
|
||||
```bash
|
||||
export REFERENCE_NUMBER="CRUNCHY-21-20260224-TR1-1B-L2"
|
||||
|
||||
REQUIRES_APPROVAL=1 APPROVER="<<APPROVER_NAME>>" \
|
||||
REFERENCE_NUMBER="$REFERENCE_NUMBER" TX_DATE="$TX_DATE" OFFICE_ID=21 \
|
||||
DEBIT_GL_ID="$ID_1410" CREDIT_GL_ID="$ID_2100" AMOUNT="$AMOUNT" \
|
||||
bash scripts/omnl/omnl-je-maker.sh
|
||||
|
||||
PAYLOAD_FILE="reconciliation/je-${REFERENCE_NUMBER}_.payload.json" \
|
||||
bash scripts/omnl/omnl-je-checker.sh
|
||||
```
|
||||
|
||||
If maker did not add a trailing underscore, use `reconciliation/je-${REFERENCE_NUMBER}.payload.json` for PAYLOAD_FILE.
|
||||
|
||||
---
|
||||
|
||||
## Phase 3 — Post-audit (Office 21)
|
||||
|
||||
Audit script supports any `OFFICE_ID`; default script name is office20 but it uses `OFFICE_ID` env.
|
||||
|
||||
```bash
|
||||
OFFICE_ID=21 bash scripts/omnl/omnl-audit-packet-office20.sh
|
||||
```
|
||||
|
||||
**Expected:** Packet folder `reconciliation/audit-office21-<timestamp>/` with:
|
||||
- Office 21: **1410 Dr = 1,000,000,000**, **2100 Cr = 1,000,000,000**
|
||||
- HO reduced by 1.0B
|
||||
|
||||
Movement monitor (if run for office 21 or all offices): exit 2 when movement detected.
|
||||
|
||||
---
|
||||
|
||||
## Phase 4 — Re-lock GL period
|
||||
|
||||
```bash
|
||||
bash scripts/omnl/omnl-gl-closures-post.sh
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phase 5 — Artifact packaging
|
||||
|
||||
Set the audit folder from Phase 3 output (e.g. `reconciliation/audit-office21-20260224-HHMMSS`).
|
||||
|
||||
```bash
|
||||
export AUDIT_FOLDER="reconciliation/audit-office21-<timestamp>"
|
||||
export ZIP_NAME="CRUNCHY-21-20260224-TR1-1B-AUDIT.zip"
|
||||
|
||||
HASH_LINE=$(tail -n 1 audit_log.jsonl 2>/dev/null || echo "Hash not found")
|
||||
cat > "$AUDIT_FOLDER/README.txt" <<EOF
|
||||
Tranche: CRUNCHY-21-20260224-TR1-1B
|
||||
Entity: Crunchygalaxy Unip. Lda. (NIPC 515159573)
|
||||
Date: 2026-02-24
|
||||
Contents: snapshot.json, snapshot.meta, computed_balances.json, recent_journal_entries.json, manifest.json
|
||||
|
||||
Audit Log Reference:
|
||||
$HASH_LINE
|
||||
EOF
|
||||
|
||||
cd reconciliation && zip -r "../$ZIP_NAME" "$(basename "$AUDIT_FOLDER")" && cd ..
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Phase 6 — Upload + confirmation
|
||||
|
||||
1. Upload **CRUNCHY-21-20260224-TR1-1B-AUDIT.zip** to **https://upload.siemb-samama.com/** (credentials from vault).
|
||||
2. Contact Samama per File Upload Procedure PDF; include ref **CRUNCHY-21-20260224-TR1-1B** and file name.
|
||||
3. Log confirmation when received.
|
||||
|
||||
---
|
||||
|
||||
## Expected final ledger state
|
||||
|
||||
| Office | 1410 | 2100 |
|
||||
|------------|--------|--------|
|
||||
| Head Office (1) | −1.0B | −1.0B |
|
||||
| Crunchygalaxy (21) | +1.0B | +1.0B |
|
||||
|
||||
---
|
||||
|
||||
## Controls
|
||||
|
||||
- Maker-checker enforced (≥10M)
|
||||
- Unique reference numbers (L1/L2)
|
||||
- posted_refs durable
|
||||
- Audit packet hashed (audit_log.jsonl)
|
||||
- Movement monitor functional
|
||||
- Closure re-applied
|
||||
- Artifact uploaded + confirmation logged
|
||||
|
||||
---
|
||||
|
||||
## Reusable script
|
||||
|
||||
For automation, use **scripts/omnl/create-office-and-fund.sh** with entity parameters (see script header or OPERATING_RAILS.md).
|
||||
@@ -14,8 +14,8 @@ The memo uses five nominal accounts (migration-specific). Create these in Finera
|
||||
|---------------------------------|------------------|---------------|--------|-------|
|
||||
| 1000-USD-SETTLEMENT-RESERVES | 1000 | 1 (ASSET) | DETAIL | USD settlement & reserve assets |
|
||||
| 1050-USD-TREASURY-CONVERSION-RESERVE-M0 | 1050 | 1 (ASSET) | DETAIL | Treasury Conversion Reserve (M0); backs M1 capacity at 1:5 |
|
||||
| 2000-USD-CENTRAL-DEPOSITS | 2000 | 2 (LIABILITY) | DETAIL | Central bank customer deposits; M1-denominated claims backed by 1050 where applicable |
|
||||
| 2100-USD-RESTRICTED-LIABILITIES | 2100 | 2 (LIABILITY) | DETAIL | Restricted / held deposits (client sub-ledger by client ID) |
|
||||
| 2000-USD-CENTRAL-DEPOSITS (M0) | 2000 | 2 (LIABILITY) | DETAIL | **M0** — Monetary base / central bank customer deposits |
|
||||
| 2100-USD-RESTRICTED-LIABILITIES (M1) | 2100 | 2 (LIABILITY) | DETAIL | **M1** — Narrow money / demand deposits; restricted or available by narrative |
|
||||
| 3000-OPENING-BALANCE-CONTROL | 3000 | 3 (EQUITY) | DETAIL | Migration control account |
|
||||
|
||||
**Note:** Fineract GL is typically shared across the tenant; client-specific breakdown (Client 1 vs 2 vs 3…) may be tracked via **savings/loan sub-ledgers** linked to clients, or via **custom dimensions/tags** if supported. Where the memo shows “(Client N)”, implement per your CoA: either one GL account per client (e.g. 2001, 2002…) or one account 2000 with client tracked in journal line narrative or external reporting. The table above uses a single code per memo account; expand to 2001, 2002, 2101, 2102, etc. if you need per-client GL accounts.
|
||||
|
||||
@@ -8,11 +8,11 @@
|
||||
|
||||
| # | Check | Done |
|
||||
|---|--------|------|
|
||||
| 1 | GL accounts exist: **1000**, **1050**, **2000**, **2100**, **3000** (`GET /glaccounts`) | ☐ |
|
||||
| 1 | GL accounts exist: **1000**, **1050**, **2000**, **2100**, **3000**; for Phase C interoffice add **1410**, **2410** (`GET /glaccounts`) | ☐ |
|
||||
| 2 | Office and currency resolved (`GET /offices`, `GET /currencies`); use correct `officeId` and USD | ☐ |
|
||||
| 3 | Maker-checker / board approval obtained for **conversion event** (T-001B) per memo §9 | ☐ |
|
||||
| 4 | Single **transaction date** chosen for migration (e.g. opening balance date) | ☐ |
|
||||
| 5 | Memo and [LEDGER_ALLOCATION_GL_MAPPING.md](LEDGER_ALLOCATION_GL_MAPPING.md) to hand for narrative and account IDs | ☐ |
|
||||
| 5 | Memo and [LEDGER_ALLOCATION_GL_MAPPING.md](LEDGER_ALLOCATION_GL_MAPPING.md) (and optionally [OMNL_JOURNAL_LEDGER_MATRIX.md](OMNL_JOURNAL_LEDGER_MATRIX.md) + [omnl-journal-matrix.json](omnl-journal-matrix.json)) to hand for narrative and account IDs | ☐ |
|
||||
|
||||
---
|
||||
|
||||
@@ -33,6 +33,8 @@
|
||||
|
||||
**API:** `POST /journalentries` — use Fineract **GL account IDs** (from `GET /glaccounts`) for each glCode; include `officeId`, `transactionDate`, `comments` (memo ref + narrative). Exact schema: [Swagger UI](https://omnl.hybxfinance.io/fineract-provider/swagger-ui/index.html) → `journalentries`.
|
||||
|
||||
**Posting:** From repo root, create GL first: `bash scripts/omnl/omnl-gl-accounts-create.sh`. Then: **original Phase C** — `omnl-ledger-post.sh` or `omnl-ledger-post-from-matrix.sh` (default matrix); **Phase C interoffice (Due-To/Due-From)** — `JOURNAL_MATRIX=.../omnl-journal-matrix-phase-c-interoffice.json bash scripts/omnl/omnl-ledger-post-from-matrix.sh` (see [OMNL_PHASE_C_INTEROFFICE_DUE_TO_DUE_FROM.md](OMNL_PHASE_C_INTEROFFICE_DUE_TO_DUE_FROM.md)). Use `DRY_RUN=1` to preview.
|
||||
|
||||
---
|
||||
|
||||
## Post-posting reconciliation
|
||||
@@ -51,7 +53,7 @@
|
||||
|
||||
| # | Action | Done |
|
||||
|---|--------|------|
|
||||
| 1 | Attach this runbook and [LEDGER_ALLOCATION_GL_MAPPING.md](LEDGER_ALLOCATION_GL_MAPPING.md) to audit trail | ☐ |
|
||||
| 1 | Attach this runbook, [LEDGER_ALLOCATION_GL_MAPPING.md](LEDGER_ALLOCATION_GL_MAPPING.md), and [OMNL_JOURNAL_LEDGER_MATRIX.md](OMNL_JOURNAL_LEDGER_MATRIX.md) to audit trail | ☐ |
|
||||
| 2 | Retain immutable copy of [MIGRATION_AND_LEDGER_ALLOCATION_MEMORANDUM.md](MIGRATION_AND_LEDGER_ALLOCATION_MEMORANDUM.md) and December-2023 source | ☐ |
|
||||
| 3 | If maker-checker enabled in Fineract, ensure conversion (T-001B) and restricted releases have separate approvals | ☐ |
|
||||
|
||||
@@ -72,4 +74,4 @@
|
||||
|
||||
---
|
||||
|
||||
**See also:** [MIGRATION_AND_LEDGER_ALLOCATION_MEMORANDUM.md](MIGRATION_AND_LEDGER_ALLOCATION_MEMORANDUM.md) (full memo) · [LEDGER_ALLOCATION_GL_MAPPING.md](LEDGER_ALLOCATION_GL_MAPPING.md) (GL mapping & API) · [MAKER_CHECKER_POLICY.md](MAKER_CHECKER_POLICY.md)
|
||||
**See also:** [MIGRATION_AND_LEDGER_ALLOCATION_MEMORANDUM.md](MIGRATION_AND_LEDGER_ALLOCATION_MEMORANDUM.md) (full memo) · [LEDGER_ALLOCATION_GL_MAPPING.md](LEDGER_ALLOCATION_GL_MAPPING.md) (GL mapping & API) · [OMNL_JOURNAL_LEDGER_MATRIX.md](OMNL_JOURNAL_LEDGER_MATRIX.md) (matrix, full GL, IPSAS, post-from-matrix script) · [OMNL_PHASE_C_INTEROFFICE_DUE_TO_DUE_FROM.md](OMNL_PHASE_C_INTEROFFICE_DUE_TO_DUE_FROM.md) (Phase C strict double-entry) · [OMNL_POSTING_AND_RECONCILIATION_EVIDENCE.md](OMNL_POSTING_AND_RECONCILIATION_EVIDENCE.md) (posting evidence and reconciliation) · [SAMAMA_OFFICE_AND_5B_M1_TRANSFER.md](SAMAMA_OFFICE_AND_5B_M1_TRANSFER.md) (Samama office + 5B M1) · [MAKER_CHECKER_POLICY.md](MAKER_CHECKER_POLICY.md)
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
# OMNL Material Posting Policy
|
||||
|
||||
**Purpose:** Define “material” thresholds and enforce maker-checker + approval + audit packet for high-value or Office 20–sensitive postings.
|
||||
|
||||
---
|
||||
|
||||
## 1) Thresholds (configurable via env)
|
||||
|
||||
| Threshold | Default (USD minor units) | Rule |
|
||||
|-----------|---------------------------|------|
|
||||
| **Maker-checker required** | 10,000,000 (10M) | Single JE ≥ this → maker must set `REQUIRES_APPROVAL=1` and `APPROVER=<name>`; checker refuses to post without approval metadata in payload. |
|
||||
| **Reviewer + audit packet** | 100,000,000 (100M) | Single JE ≥ this → maker-checker + second reviewer + run audit packet before and after. |
|
||||
| **Office 20 rails (1410/2100/2410)** | any | Any posting touching officeId=20 and these GLs → audit packet mandatory after post. |
|
||||
|
||||
Defaults: `MATERIAL_THRESHOLD_MAKER_CHECKER=10000000`, `MATERIAL_THRESHOLD_REVIEWER=100000000`.
|
||||
|
||||
---
|
||||
|
||||
## 2) Maker script (omnl-je-maker.sh)
|
||||
|
||||
- If `AMOUNT >= MATERIAL_THRESHOLD_MAKER_CHECKER` and neither `REQUIRES_APPROVAL=1` nor `APPROVER` is set → **refuse** to generate payload and exit non-zero.
|
||||
- When `REQUIRES_APPROVAL=1` and `APPROVER` is set, maker writes **approvalMetadata** into the payload file (or a sidecar): `{ "approver": "<APPROVER>", "approvedAt": "<iso timestamp>" }`. Checker expects this in/alongside the payload for material amounts.
|
||||
|
||||
---
|
||||
|
||||
## 3) Checker script (omnl-je-checker.sh)
|
||||
|
||||
- If payload amount ≥ `MATERIAL_THRESHOLD_MAKER_CHECKER` and payload (or sidecar) does **not** contain valid approvalMetadata → **refuse** to post and exit non-zero.
|
||||
- Optional: if amount ≥ `MATERIAL_THRESHOLD_REVIEWER`, checker can require `AUDIT_PACKET_PATH` to be set (path to a just-generated audit packet) before posting.
|
||||
|
||||
---
|
||||
|
||||
## 4) Matrix posting (omnl-ledger-post-from-matrix.sh)
|
||||
|
||||
- `MAX_POST_AMOUNT` caps any single entry; use it to enforce a hard ceiling (e.g. 100B).
|
||||
- `ALLOWED_OFFICE_IDS` restricts which offices can receive postings.
|
||||
|
||||
---
|
||||
|
||||
## 5) Success conditions
|
||||
|
||||
- No one can post ≥10M without going through maker + checker with approval.
|
||||
- No one can post ≥100M without second reviewer + audit packet.
|
||||
- Office 20 postings to 1410/2100/2410 always trigger audit packet (run manually or in runbook after post).
|
||||
@@ -0,0 +1,74 @@
|
||||
# Office 20 Audit Packet
|
||||
|
||||
**Purpose:** One folder per run with snapshot, computed balances, recent journal entries, and manifest so the 5B position is defensible in any review.
|
||||
|
||||
**Script:** `scripts/omnl/omnl-audit-packet-office20.sh`
|
||||
|
||||
**Dynamic office:** The script uses `OFFICE_ID` (default 20). For any other office, run e.g. `OFFICE_ID=21 bash scripts/omnl/omnl-audit-packet-office20.sh`; output folder is `audit-office<ID>-<timestamp>/`.
|
||||
|
||||
---
|
||||
|
||||
## Output layout (one folder per run)
|
||||
|
||||
```
|
||||
reconciliation/audit-office20-<YYYYMMDD>-<HHMMSS>/
|
||||
snapshot.json # Offices (1, 20) + GL 1410/2100/2410
|
||||
snapshot.meta # sha256, timestamp
|
||||
computed_balances.json # Sum-based balances by glAccountId (deterministic)
|
||||
recent_journal_entries.json # Last N days of JEs for office 20 (id, date, ref, amount, createdBy)
|
||||
manifest.json # Script name, repo, git commit/branch, operator, tenant
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Snapshot schema
|
||||
|
||||
- **timestamp**, **officeId**, **operator**
|
||||
- **offices**: array of office objects (id, name, externalId, …)
|
||||
- **glRelevant**: array of GL accounts 1410, 2100, 2410 with glCode, id, name, organizationRunningBalance (if API provides it)
|
||||
|
||||
---
|
||||
|
||||
## Computed balances
|
||||
|
||||
- **computedBy**: `"sum_of_journal_entries"`
|
||||
- **balancesByGlId**: map of GL account id → sum of amounts from recent JEs
|
||||
- Deterministic: does not depend on Trial Balance endpoint. Compare to reported TB for reconciliation.
|
||||
|
||||
---
|
||||
|
||||
## Recent journal entries
|
||||
|
||||
- Sourced from `GET /journalentries?officeId=20&fromDate=...&toDate=...&dateFormat=yyyy-MM-dd&locale=en` (required for many Fineract builds). Date window: `fromDate` = today − RECENT_JE_DAYS, `toDate` = today + 1 day (avoids boundary/timezone gaps).
|
||||
- **API shape:** This tenant returns `{ "totalFilteredRecords": N, "pageItems": [ ... ] }` where each item is a **line-level** entry (one row per debit/credit): **id**, **officeId**, **glAccountId**, **glAccountCode**, **amount**, **entryType** (object with **value** "DEBIT"/"CREDIT"), **transactionDate** (array [y,m,d]), **transactionId**, **referenceNumber**, **comments**. The script normalizes to a flat list and derives **computed_balances** by summing signed amounts (DEBIT +, CREDIT −) per glAccountId.
|
||||
- If the API does not support listing by office/date, the file may be empty; ensure **dateFormat** and **locale** are set and that the response uses **pageItems** (not a top-level array).
|
||||
|
||||
---
|
||||
|
||||
## Manifest
|
||||
|
||||
- **script**, **repo**, **gitCommit**, **gitBranch**, **operator**, **tenant**
|
||||
- **envBaseUrl**: redacted; no credentials.
|
||||
|
||||
---
|
||||
|
||||
## Acceptance (Office 20 after 5B)
|
||||
|
||||
- **1410** net Dr = 5,000,000,000
|
||||
- **2100** net Cr = 5,000,000,000
|
||||
- HO **2410** increased by 5,000,000,000
|
||||
|
||||
Use **computed_balances** + **recent_journal_entries** to trace the position to exact JE IDs.
|
||||
|
||||
---
|
||||
|
||||
## Usage
|
||||
|
||||
```bash
|
||||
# From repo root
|
||||
source omnl-fineract/.env
|
||||
bash scripts/omnl/omnl-audit-packet-office20.sh
|
||||
# Optional: RECENT_JE_DAYS=30 OUT_BASE=./reconciliation OFFICE_ID=20
|
||||
```
|
||||
|
||||
Run daily or after any material posting to Office 20.
|
||||
@@ -0,0 +1,60 @@
|
||||
# Office 20 Disaster Recovery Runbook
|
||||
|
||||
**Purpose:** Backups, reversal protocol, and recovery steps for Office 20 (Samama) 5B position.
|
||||
|
||||
---
|
||||
|
||||
## 1) Backups
|
||||
|
||||
- **Reconciliation snapshots:** Keep audit packets (e.g. `reconciliation/audit-office20-*`) retained per policy (e.g. 90 days). Copy to immutable or off-site storage if required.
|
||||
- **Posting manifests:** When using maker-checker, retain the payload file and its sha256; store with the audit packet or in a dedicated manifest store.
|
||||
- **Scripts and config:** Repo is source of truth; tag releases and document which git commit was used for each posting run.
|
||||
|
||||
---
|
||||
|
||||
## 2) Reversal protocol
|
||||
|
||||
To reverse a mistaken posting identified by **referenceNumber**:
|
||||
|
||||
### 2.1 One-command reversal (when JE list API returns the entry)
|
||||
|
||||
```bash
|
||||
REFERENCE_NUMBER=SAMAMA-20-20260224-HO bash scripts/omnl/omnl-je-reverse-by-reference.sh
|
||||
```
|
||||
|
||||
- Script finds the JE (via GET journalentries filtered by date range; then jq filter by referenceNumber).
|
||||
- Posts a **new** journal entry with opposite debits/credits and comment `REVERSAL: <ref>`.
|
||||
- Reversal itself gets referenceNumber `REV-<ref>`.
|
||||
|
||||
### 2.2 If JE list API does not support referenceNumber filter
|
||||
|
||||
1. Run **audit packet** to get `recent_journal_entries.json` and identify the JE **id** and its debits/credits.
|
||||
2. Manually or via script: **POST /journalentries** with same officeId/transactionDate, comments `REVERSAL: <ref>`, **debits** = original credits, **credits** = original debits.
|
||||
3. Record the reversal in a reversal manifest (ref, reversal JE id, timestamp).
|
||||
|
||||
### 2.3 Reversal manifest
|
||||
|
||||
After any reversal, record:
|
||||
|
||||
- Original referenceNumber
|
||||
- Reversal referenceNumber (e.g. REV-…)
|
||||
- Reversal JE id (if returned)
|
||||
- Timestamp and operator
|
||||
|
||||
Store in `reconciliation/reversals.log` or equivalent (do not commit secrets).
|
||||
|
||||
---
|
||||
|
||||
## 3) Recovery after outage
|
||||
|
||||
1. **Verify Office 20 and HO** — GET /offices, GET /glclosures (office 20 and 1).
|
||||
2. **Run audit packet** — Produce a fresh packet and compare computed_balances to expected (1410 Dr 5B, 2100 Cr 5B for office 20).
|
||||
3. **Reconcile** — If TB or computed totals differ from expected, trace via recent_journal_entries.json and GL ledger in UI; then correct or reverse as per §2.
|
||||
|
||||
---
|
||||
|
||||
## 4) References
|
||||
|
||||
- [OPERATING_RAILS.md](OPERATING_RAILS.md) — Controls, idempotency, reconciliation
|
||||
- [OFFICE_20_AUDIT_PACKET.md](OFFICE_20_AUDIT_PACKET.md) — Audit packet layout
|
||||
- [SAMAMA_OFFICE_AND_5B_M1_TRANSFER.md](SAMAMA_OFFICE_AND_5B_M1_TRANSFER.md) — Office 20 creation and 5B transfer
|
||||
@@ -0,0 +1,67 @@
|
||||
# Office 20 Fire Drill Runbook
|
||||
|
||||
**Purpose:** Prove end-to-end: detect → document → reverse → verify. Run once in a calm period.
|
||||
|
||||
**Prereqs:** `omnl-fineract/.env` and `ids.env` (run `scripts/omnl/resolve_ids.sh` from repo root).
|
||||
|
||||
---
|
||||
|
||||
## Steps
|
||||
|
||||
### 1) Maker: generate $1 payload (ref DRILL-…)
|
||||
|
||||
```bash
|
||||
cd /path/to/repo
|
||||
source ids.env
|
||||
REF="DRILL-$(date +%Y%m%d)-001" AMOUNT=1 OFFICE_ID=20 \
|
||||
DEBIT_GL_ID=$ID_2100 CREDIT_GL_ID=$ID_1410 \
|
||||
bash scripts/omnl/omnl-je-maker.sh
|
||||
```
|
||||
|
||||
Expect: `reconciliation/je-DRILL-<date>-001.payload.json` and `.payload.sha256`.
|
||||
|
||||
### 2) Checker: post the JE
|
||||
|
||||
```bash
|
||||
PAYLOAD_FILE=reconciliation/je-DRILL-$(date +%Y%m%d)-001.payload.json \
|
||||
bash scripts/omnl/omnl-je-checker.sh
|
||||
```
|
||||
|
||||
Expect: HTTP 200, ref recorded in `.posted_refs`.
|
||||
|
||||
### 3) Movement monitor: confirm alert (exit 2)
|
||||
|
||||
```bash
|
||||
bash scripts/omnl/omnl-monitor-office20-movement.sh
|
||||
echo "Exit code: $?"
|
||||
```
|
||||
|
||||
Expect: exit code **2** and JSON indicating Office 20 movement.
|
||||
|
||||
### 4) Audit packet (before reversal)
|
||||
|
||||
```bash
|
||||
bash scripts/omnl/omnl-audit-packet-office20.sh
|
||||
```
|
||||
|
||||
Archive the printed packet path (and optional `audit_log.jsonl` line).
|
||||
|
||||
### 5) Reverse by reference
|
||||
|
||||
```bash
|
||||
bash scripts/omnl/omnl-je-reverse-by-reference.sh DRILL-$(date +%Y%m%d)-001
|
||||
```
|
||||
|
||||
Expect: reversal JE created.
|
||||
|
||||
### 6) Audit packet again (after reversal)
|
||||
|
||||
```bash
|
||||
bash scripts/omnl/omnl-audit-packet-office20.sh
|
||||
```
|
||||
|
||||
Compare with step 4 to confirm returned state.
|
||||
|
||||
---
|
||||
|
||||
**Success:** You have demonstrated detect → document → reverse → verify. See PRODUCTION_OPS_OFFICE20.md for alert wiring and durable posted_refs.
|
||||
@@ -0,0 +1,38 @@
|
||||
# Office 2 (Shamrayan Enterprises) — Readiness Confirmation
|
||||
|
||||
**Entity:** Shamrayan Enterprises
|
||||
**Office ID:** 2
|
||||
**Date confirmed:** 2026-02-24
|
||||
|
||||
---
|
||||
|
||||
## Confirmation Summary
|
||||
|
||||
| Item | Status | Reference |
|
||||
|------|--------|-----------|
|
||||
| **5B USD M1** | ✅ Confirmed | Office 2 holds 5,000,000,000 USD M1 (1410 Dr / 2100 Cr). Source: [OMNL_OFFICE_BALANCES.md](OMNL_OFFICE_BALANCES.md) — Office 2 totals: Assets 5B, Liabilities 5B; 0 M0 (2000); 5B M1 (2100) only. |
|
||||
| **Full accounting** | ✅ In place | GL 1410 (Due From HO), 2100 (M1); journal entries via Fineract API; referenceNumber idempotency; closures and trial balance. |
|
||||
| **Audit** | ✅ In place | Audit packet script supports any office: `OFFICE_ID=2 bash scripts/omnl/omnl-audit-packet-office20.sh`. Output: snapshot, computed_balances, recent_journal_entries, manifest; hash in audit_log.jsonl. See [OFFICE_20_AUDIT_PACKET.md](OFFICE_20_AUDIT_PACKET.md) (dynamic OFFICE_ID). |
|
||||
| **Compliance** | ✅ In place | Maker-checker (≥10M), material policy, ALLOWED_OFFICE_IDS, MAX_POST_AMOUNT, durable posted_refs, chain-of-custody. See [OPERATING_RAILS.md](OPERATING_RAILS.md), [MATERIAL_POSTING_POLICY.md](MATERIAL_POSTING_POLICY.md). |
|
||||
| **Ready for transfer via API P2P Bank Rail** | ✅ Ready | Runbook and controls support outbound settlement: (1) Execute P2P call to recipient endpoint; (2) Confirm settlement (e.g. status SETTLED); (3) Post mirror ledger entry (Dr 2100 / Cr 1410 at Office 2); (4) Audit + closure + package. See [OFFICE_2_SHAMRAYAN_RUNBOOK.md](OFFICE_2_SHAMRAYAN_RUNBOOK.md) (Phase 2–6) and P2P pattern in [P2P_SETTLEMENT_CRUNCHYGALAXY_RAIL.md](P2P_SETTLEMENT_CRUNCHYGALAXY_RAIL.md) (adapt for Shamrayan when endpoint/auth available). |
|
||||
| **Reconcile** | ✅ Supported | Reconciliation snapshot via audit packet (computed_balances from JE lines); movement monitor for Office 2: `OFFICE_ID=2 bash scripts/omnl/omnl-monitor-office20-movement.sh`. |
|
||||
| **Settlement** | ✅ Supported | Settlement = P2P confirmation (SETTLED) then mirror entry; no mirror before confirmation. Close package: request + response + settlement confirmation + mirror JE + audit packet + hash + closing memo. |
|
||||
|
||||
---
|
||||
|
||||
## Ledger Position (Office 2)
|
||||
|
||||
- **1410 (Due From Head Office):** Dr 5,000,000,000
|
||||
- **2100 (M1):** Cr 5,000,000,000
|
||||
- **Office 2 totals:** Assets 5B; Liabilities 5B. 0 M0; 5B M1 only.
|
||||
|
||||
---
|
||||
|
||||
## Runbooks
|
||||
|
||||
- **Funding / tranche (Rail B HO → Office 2):** [OFFICE_2_SHAMRAYAN_RUNBOOK.md](OFFICE_2_SHAMRAYAN_RUNBOOK.md)
|
||||
- **P2P settlement pattern (adapt for Shamrayan):** [P2P_SETTLEMENT_CRUNCHYGALAXY_RAIL.md](P2P_SETTLEMENT_CRUNCHYGALAXY_RAIL.md) — use when Shamrayan P2P endpoint and auth are defined.
|
||||
|
||||
---
|
||||
|
||||
**Conclusion:** Office 2 has 5B USD M1, full accounting and audit, compliance controls, and is ready for transfer via API P2P Bank Rail, reconcile, and settlement following the documented runbooks and control rule (no mirror entry before settlement confirmed).
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,98 @@
|
||||
# OMNL Client API → UI Column Mapping
|
||||
|
||||
**Purpose:** Map the UI client list columns to the Fineract list API response so each column shows the correct data.
|
||||
|
||||
**API:** `GET /fineract-provider/api/v1/clients` → response has `pageItems[]` (one object per client). Tenant `omnl`, Basic auth.
|
||||
|
||||
---
|
||||
|
||||
## UI column → API field mapping
|
||||
|
||||
| UI column | API field / expression | Notes |
|
||||
|-------------|------------------------|--------|
|
||||
| **Name** | `firstname` (or see below) | API does not return `displayName` or `fullname`. Use `firstname`; if `lastname === "."` show only `firstname`, else `firstname + " " + lastname`. |
|
||||
| **Account No.** | `accountNo` | String, e.g. `"000000001"`. |
|
||||
| **External Id** | `externalId` | String, e.g. `"OMNL-1-M0-M1"`, `"OMNL-9"`. |
|
||||
| **Status** | `status.value` | Status is an object; use the `value` property, e.g. `"Pending"`. |
|
||||
| **Office Name** | `officeName` | String, e.g. `"Head Office"`. |
|
||||
|
||||
---
|
||||
|
||||
## Name column (detail)
|
||||
|
||||
The API returns **`firstname`** and **`lastname`** only (no `displayName` / `fullname`). For OMNL we set `lastname` to `"."` when there is no real last name. To show a clean name:
|
||||
|
||||
```ts
|
||||
// Recommended: show firstname only when lastname is the placeholder
|
||||
const displayName = (client.lastname === '.' || !client.lastname)
|
||||
? client.firstname
|
||||
: `${client.firstname} ${client.lastname}`;
|
||||
```
|
||||
|
||||
Bind the **Name** column to `displayName` (computed as above) or, for simplicity, to **`firstname`** only.
|
||||
|
||||
---
|
||||
|
||||
## Full list API shape (reference)
|
||||
|
||||
Each item in `pageItems` has (among others):
|
||||
|
||||
| API key | Type | Example |
|
||||
|---------|------|---------|
|
||||
| `id` | number | 1 |
|
||||
| `accountNo` | string | "000000001" |
|
||||
| `externalId` | string | "OMNL-9" |
|
||||
| `status` | object | `{ "id": 100, "code": "clientStatusType.pending", "value": "Pending" }` |
|
||||
| `firstname` | string | "FIDIS" |
|
||||
| `lastname` | string | "." |
|
||||
| `officeId` | number | 1 |
|
||||
| `officeName` | string | "Head Office" |
|
||||
|
||||
`displayName` and `fullname` are **not** in the API response; do not bind any column to them.
|
||||
|
||||
---
|
||||
|
||||
## Edit form (Home / Clients / Edit)
|
||||
|
||||
When loading a client for edit (e.g. from `GET /clients/{id}`), the form fields must be filled from the API response. The **Entity Name** field is required but often appears empty because it is not bound to the API.
|
||||
|
||||
| Form label | API field (load & save) | Notes |
|
||||
|-----------------|--------------------------|--------|
|
||||
| **Entity Name *** | **`firstname`** | **Required.** Load this from the client payload when opening the form; on Submit, send it as `firstname`. If the field is bound to `displayName` or `fullname` (which the API does not return), it will stay empty — bind it to **`firstname`**. |
|
||||
| Account No. | `accountNo` | Read-only; display only. |
|
||||
| External Id | `externalId` | Load and save. |
|
||||
| Office | `officeId` / `officeName` | Dropdown; use `officeId` for save. |
|
||||
| Legal Form | `legalForm` / `legalForm.id` | Already correct if showing "Entity". |
|
||||
| Submitted On * | `timeline.submittedOnDate` or equivalent | For display/load. |
|
||||
| Mobile No | `mobileNo` (if present) | Optional. |
|
||||
| Email Address | `emailAddress` (if present) | Optional. |
|
||||
|
||||
**Fix for empty Entity Name on edit:** Ensure the edit form loads **`firstname`** from the client response into the "Entity Name" input. On submit, send **`firstname`** (and **`lastname`**: use `"."` if no real last name, since the tenant requires non-blank lastname).
|
||||
|
||||
---
|
||||
|
||||
## Verification
|
||||
|
||||
To re-check the API response from repo root:
|
||||
|
||||
```bash
|
||||
source omnl-fineract/.env # or .env
|
||||
curl -s -u "${OMNL_FINERACT_USER}:${OMNL_FINERACT_PASSWORD}" \
|
||||
-H "Fineract-Platform-TenantId: omnl" \
|
||||
"${OMNL_FINERACT_BASE_URL}/clients" | jq '.pageItems[0] | keys'
|
||||
```
|
||||
|
||||
To list only name-related fields for all clients:
|
||||
|
||||
```bash
|
||||
curl -s -u "${OMNL_FINERACT_USER}:${OMNL_FINERACT_PASSWORD}" \
|
||||
-H "Fineract-Platform-TenantId: omnl" \
|
||||
"${OMNL_FINERACT_BASE_URL}/clients" | jq '.pageItems[] | { accountNo, firstname, lastname }'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## References
|
||||
|
||||
- [OMNL_CLIENT_NAMES_FIX.md](OMNL_CLIENT_NAMES_FIX.md) — How names are set via API
|
||||
- [OMNL_ENTITY_MASTER_DATA.json](OMNL_ENTITY_MASTER_DATA.json) — Canonical entity names (1–15)
|
||||
@@ -0,0 +1,112 @@
|
||||
# OMNL Clients — Blank Name Column Fix
|
||||
|
||||
**Issue:** The Clients list at [https://omnl.hybxfinance.io/#/clients](https://omnl.hybxfinance.io/#/clients) shows **blank names** for all clients. Account No., External Id (e.g. `OMNL-1-M0-M1`), Status (Pending), and Office are present.
|
||||
|
||||
**Cause:** Clients were created (e.g. via import or API) without `firstname` / `lastname` (or `fullname` / `displayName`). The Fineract UI “Name” column often shows the client’s **displayName**; when that field is empty, the column is blank.
|
||||
|
||||
**Note:** The API stores **firstname** and **lastname** (we set lastname to `"."` because the tenant requires a non-blank value). Some tenants or list endpoints return **displayName** as null even when firstname/lastname are set. If the Name column stays blank after running the fix: try a **hard refresh** (Ctrl+Shift+R or Cmd+Shift+R) or clear browser cache; if it still stays blank, the list view may be bound to displayName and the platform may need to show firstname when displayName is null.
|
||||
|
||||
---
|
||||
|
||||
## Canonical client names (Operating / External-Facing Entities)
|
||||
|
||||
| Client | Account No. | Name |
|
||||
|--------|-------------|------|
|
||||
| 1 | 000000001 | **OMNL Head Office (DBIS)** – Central Bank |
|
||||
| 2 | 000000002 | Shamrayan Enterprises |
|
||||
| 3 | 000000003 | HYBX |
|
||||
| 4 | 000000004 | TAJ Private Single Family Office |
|
||||
| 5 | 000000005 | Aseret Mortgage Bank |
|
||||
| 6 | 000000006 | Mann Li Family Offices |
|
||||
| 7 | 000000007 | Sovereign Order of Malta OSJ |
|
||||
| 8 | 000000008 | Alltra Mainnet |
|
||||
| 9 | 000000009 | FIDIS |
|
||||
| 10 | 000000010 | Alpha Omega Holdings |
|
||||
| 11 | 000000011 | SGI Capital |
|
||||
| 12 | 000000012 | Titan Financial |
|
||||
| 13 | 000000013 | Roy Walker PLLC |
|
||||
| 14 | 000000014 | SGI Partners LLC |
|
||||
| 15 | 000000015 | Tsunami Holdings AG |
|
||||
|
||||
The fix script maps by **Account No.** (000000001 → Client 1, …) and sets the name above for each.
|
||||
|
||||
---
|
||||
|
||||
## Fix options
|
||||
|
||||
### 1. Script (recommended): set canonical names
|
||||
|
||||
From repo root, with `omnl-fineract/.env` (or root `.env`) containing `OMNL_FINERACT_BASE_URL` and `OMNL_FINERACT_PASSWORD`:
|
||||
|
||||
```bash
|
||||
# Dry run: print what would be updated
|
||||
DRY_RUN=1 bash scripts/omnl/omnl-client-names-fix.sh
|
||||
|
||||
# Apply: PUT firstname for each client (canonical name from table above)
|
||||
bash scripts/omnl/omnl-client-names-fix.sh
|
||||
```
|
||||
|
||||
The script sets each client’s display name to the canonical operating-entity name in the table above.
|
||||
|
||||
### 2. Manual API (one client)
|
||||
|
||||
1. Get client list:
|
||||
```bash
|
||||
curl -s -u "${OMNL_FINERACT_USER}:${OMNL_FINERACT_PASSWORD}" \
|
||||
-H "Fineract-Platform-TenantId: omnl" \
|
||||
"${OMNL_FINERACT_BASE_URL}/clients"
|
||||
```
|
||||
2. Update one client (replace `{clientId}` and name):
|
||||
```bash
|
||||
curl -s -X PUT -u "${OMNL_FINERACT_USER}:${OMNL_FINERACT_PASSWORD}" \
|
||||
-H "Fineract-Platform-TenantId: omnl" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"firstname":"OMNL Head Office (DBIS) – Central Bank","lastname":""}' \
|
||||
"${OMNL_FINERACT_BASE_URL}/clients/{clientId}"
|
||||
```
|
||||
|
||||
### 3. Via Mifos UI (if allowed)
|
||||
|
||||
If the tenant allows editing pending clients: open each client, edit and set First name / Last name, then save.
|
||||
|
||||
---
|
||||
|
||||
## Preventing blank names for new clients
|
||||
|
||||
When creating clients via API (`POST /clients`), always send at least one of:
|
||||
|
||||
- `firstname` and `lastname`, or
|
||||
- `fullname` (e.g. for organisations)
|
||||
|
||||
Example minimal body:
|
||||
|
||||
```json
|
||||
{
|
||||
"officeId": 1,
|
||||
"firstname": "OMNL",
|
||||
"lastname": "2-M0-M1",
|
||||
"externalId": "OMNL-2-M0-M1",
|
||||
"dateFormat": "yyyy-MM-dd",
|
||||
"locale": "en",
|
||||
"active": false,
|
||||
"submittedOnDate": "2026-02-21"
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Full entity data (name + LEI + address + contacts)
|
||||
|
||||
For **entity names plus LEI, address, and contacts**, use the master data file and apply script:
|
||||
|
||||
- **[OMNL_ENTITY_MASTER_DATA.md](OMNL_ENTITY_MASTER_DATA.md)** — Data file description, how to fill LEI/address/contacts, Fineract mapping
|
||||
- **[OMNL_ENTITY_MASTER_DATA.json](OMNL_ENTITY_MASTER_DATA.json)** — Edit this file with LEI, address, and contact details per entity
|
||||
- **Script:** `bash scripts/omnl/omnl-entity-data-apply.sh` (applies names, identifiers (LEI), addresses, contacts)
|
||||
|
||||
---
|
||||
|
||||
## References
|
||||
|
||||
- [FINERACT_API_REFERENCE.md](FINERACT_API_REFERENCE.md) — Auth, tenant header, base URL
|
||||
- [OMNL Fineract README](../../../omnl-fineract/README.md) — Env vars and quick API reference
|
||||
- OpenAPI spec: `docs/api/omnl-fineract-openapi.json` — `Client` / `PostClientsRequest` schemas
|
||||
@@ -0,0 +1,386 @@
|
||||
{
|
||||
"description": "Operating / external-facing entities for OMNL. Used for Offices (Organization / Manage Offices) or Clients. Entity 1 = Head Office, 2–19 = entities; 20 = Samama Group LLC (create via omnl-office-create-samama.sh). Fill LEI, address, contact when used as clients.",
|
||||
"source": "https://omnl.hybxfinance.io/#/clients",
|
||||
"entities": [
|
||||
{
|
||||
"clientNumber": 1,
|
||||
"accountNo": "000000001",
|
||||
"entityName": "OMNL Head Office (DBIS) – Central Bank",
|
||||
"lei": "",
|
||||
"address": {
|
||||
"street": "",
|
||||
"addressLine1": "",
|
||||
"addressLine2": "",
|
||||
"city": "",
|
||||
"stateProvinceId": null,
|
||||
"countryId": null,
|
||||
"postalCode": ""
|
||||
},
|
||||
"contact": {
|
||||
"mobileNo": "",
|
||||
"emailAddress": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"clientNumber": 2,
|
||||
"accountNo": "000000002",
|
||||
"entityName": "Shamrayan Enterprises",
|
||||
"lei": "",
|
||||
"address": {
|
||||
"street": "",
|
||||
"addressLine1": "",
|
||||
"addressLine2": "",
|
||||
"city": "",
|
||||
"stateProvinceId": null,
|
||||
"countryId": null,
|
||||
"postalCode": ""
|
||||
},
|
||||
"contact": {
|
||||
"mobileNo": "",
|
||||
"emailAddress": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"clientNumber": 3,
|
||||
"accountNo": "000000003",
|
||||
"entityName": "HYBX",
|
||||
"lei": "",
|
||||
"address": {
|
||||
"street": "",
|
||||
"addressLine1": "",
|
||||
"addressLine2": "",
|
||||
"city": "",
|
||||
"stateProvinceId": null,
|
||||
"countryId": null,
|
||||
"postalCode": ""
|
||||
},
|
||||
"contact": {
|
||||
"mobileNo": "",
|
||||
"emailAddress": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"clientNumber": 4,
|
||||
"accountNo": "000000004",
|
||||
"entityName": "TAJ Private Single Family Office",
|
||||
"lei": "",
|
||||
"address": {
|
||||
"street": "",
|
||||
"addressLine1": "",
|
||||
"addressLine2": "",
|
||||
"city": "",
|
||||
"stateProvinceId": null,
|
||||
"countryId": null,
|
||||
"postalCode": ""
|
||||
},
|
||||
"contact": {
|
||||
"mobileNo": "",
|
||||
"emailAddress": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"clientNumber": 5,
|
||||
"accountNo": "000000005",
|
||||
"entityName": "Aseret Mortgage Bank",
|
||||
"lei": "",
|
||||
"address": {
|
||||
"street": "",
|
||||
"addressLine1": "",
|
||||
"addressLine2": "",
|
||||
"city": "",
|
||||
"stateProvinceId": null,
|
||||
"countryId": null,
|
||||
"postalCode": ""
|
||||
},
|
||||
"contact": {
|
||||
"mobileNo": "",
|
||||
"emailAddress": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"clientNumber": 6,
|
||||
"accountNo": "000000006",
|
||||
"entityName": "Mann Li Family Offices",
|
||||
"lei": "",
|
||||
"address": {
|
||||
"street": "",
|
||||
"addressLine1": "",
|
||||
"addressLine2": "",
|
||||
"city": "",
|
||||
"stateProvinceId": null,
|
||||
"countryId": null,
|
||||
"postalCode": ""
|
||||
},
|
||||
"contact": {
|
||||
"mobileNo": "",
|
||||
"emailAddress": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"clientNumber": 7,
|
||||
"accountNo": "000000007",
|
||||
"entityName": "Sovereign Order of Malta OSJ",
|
||||
"lei": "",
|
||||
"address": {
|
||||
"street": "",
|
||||
"addressLine1": "",
|
||||
"addressLine2": "",
|
||||
"city": "",
|
||||
"stateProvinceId": null,
|
||||
"countryId": null,
|
||||
"postalCode": ""
|
||||
},
|
||||
"contact": {
|
||||
"mobileNo": "",
|
||||
"emailAddress": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"clientNumber": 8,
|
||||
"accountNo": "000000008",
|
||||
"entityName": "Alltra Mainnet",
|
||||
"lei": "",
|
||||
"address": {
|
||||
"street": "",
|
||||
"addressLine1": "",
|
||||
"addressLine2": "",
|
||||
"city": "",
|
||||
"stateProvinceId": null,
|
||||
"countryId": null,
|
||||
"postalCode": ""
|
||||
},
|
||||
"contact": {
|
||||
"mobileNo": "",
|
||||
"emailAddress": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"clientNumber": 9,
|
||||
"accountNo": "000000009",
|
||||
"entityName": "FIDIS",
|
||||
"lei": "",
|
||||
"address": {
|
||||
"street": "",
|
||||
"addressLine1": "",
|
||||
"addressLine2": "",
|
||||
"city": "",
|
||||
"stateProvinceId": null,
|
||||
"countryId": null,
|
||||
"postalCode": ""
|
||||
},
|
||||
"contact": {
|
||||
"mobileNo": "",
|
||||
"emailAddress": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"clientNumber": 10,
|
||||
"accountNo": "000000010",
|
||||
"entityName": "Alpha Omega Holdings",
|
||||
"lei": "",
|
||||
"address": {
|
||||
"street": "",
|
||||
"addressLine1": "",
|
||||
"addressLine2": "",
|
||||
"city": "",
|
||||
"stateProvinceId": null,
|
||||
"countryId": null,
|
||||
"postalCode": ""
|
||||
},
|
||||
"contact": {
|
||||
"mobileNo": "",
|
||||
"emailAddress": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"clientNumber": 11,
|
||||
"accountNo": "000000011",
|
||||
"entityName": "SGI Capital",
|
||||
"lei": "",
|
||||
"address": {
|
||||
"street": "",
|
||||
"addressLine1": "",
|
||||
"addressLine2": "",
|
||||
"city": "",
|
||||
"stateProvinceId": null,
|
||||
"countryId": null,
|
||||
"postalCode": ""
|
||||
},
|
||||
"contact": {
|
||||
"mobileNo": "",
|
||||
"emailAddress": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"clientNumber": 12,
|
||||
"accountNo": "000000012",
|
||||
"entityName": "Titan Financial",
|
||||
"lei": "",
|
||||
"address": {
|
||||
"street": "",
|
||||
"addressLine1": "",
|
||||
"addressLine2": "",
|
||||
"city": "",
|
||||
"stateProvinceId": null,
|
||||
"countryId": null,
|
||||
"postalCode": ""
|
||||
},
|
||||
"contact": {
|
||||
"mobileNo": "",
|
||||
"emailAddress": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"clientNumber": 13,
|
||||
"accountNo": "000000013",
|
||||
"entityName": "Roy Walker PLLC",
|
||||
"lei": "",
|
||||
"address": {
|
||||
"street": "",
|
||||
"addressLine1": "",
|
||||
"addressLine2": "",
|
||||
"city": "",
|
||||
"stateProvinceId": null,
|
||||
"countryId": null,
|
||||
"postalCode": ""
|
||||
},
|
||||
"contact": {
|
||||
"mobileNo": "",
|
||||
"emailAddress": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"clientNumber": 14,
|
||||
"accountNo": "000000014",
|
||||
"entityName": "SGI Partners LLC",
|
||||
"lei": "",
|
||||
"address": {
|
||||
"street": "",
|
||||
"addressLine1": "",
|
||||
"addressLine2": "",
|
||||
"city": "",
|
||||
"stateProvinceId": null,
|
||||
"countryId": null,
|
||||
"postalCode": ""
|
||||
},
|
||||
"contact": {
|
||||
"mobileNo": "",
|
||||
"emailAddress": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"clientNumber": 15,
|
||||
"accountNo": "000000015",
|
||||
"entityName": "Tsunami Holdings AG",
|
||||
"lei": "",
|
||||
"address": {
|
||||
"street": "",
|
||||
"addressLine1": "",
|
||||
"addressLine2": "",
|
||||
"city": "",
|
||||
"stateProvinceId": null,
|
||||
"countryId": null,
|
||||
"postalCode": ""
|
||||
},
|
||||
"contact": {
|
||||
"mobileNo": "",
|
||||
"emailAddress": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"clientNumber": 16,
|
||||
"accountNo": "000000016",
|
||||
"entityName": "Anakatech",
|
||||
"lei": "",
|
||||
"address": {
|
||||
"street": "",
|
||||
"addressLine1": "",
|
||||
"addressLine2": "",
|
||||
"city": "",
|
||||
"stateProvinceId": null,
|
||||
"countryId": null,
|
||||
"postalCode": ""
|
||||
},
|
||||
"contact": {
|
||||
"mobileNo": "",
|
||||
"emailAddress": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"clientNumber": 17,
|
||||
"accountNo": "000000017",
|
||||
"entityName": "Anema Camden Walker Global",
|
||||
"lei": "",
|
||||
"address": {
|
||||
"street": "",
|
||||
"addressLine1": "",
|
||||
"addressLine2": "",
|
||||
"city": "",
|
||||
"stateProvinceId": null,
|
||||
"countryId": null,
|
||||
"postalCode": ""
|
||||
},
|
||||
"contact": {
|
||||
"mobileNo": "",
|
||||
"emailAddress": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"clientNumber": 18,
|
||||
"accountNo": "000000018",
|
||||
"entityName": "NEPAL RASTRA BANK",
|
||||
"lei": "25490000MX377HHPSR96",
|
||||
"address": {
|
||||
"street": "Baluwatar, Kathmandu",
|
||||
"addressLine1": "Baluwatar, Kathmandu",
|
||||
"addressLine2": "",
|
||||
"city": "Kathmandu",
|
||||
"stateProvinceId": null,
|
||||
"countryId": null,
|
||||
"postalCode": "44616"
|
||||
},
|
||||
"contact": {
|
||||
"mobileNo": "",
|
||||
"emailAddress": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"clientNumber": 19,
|
||||
"accountNo": "000000019",
|
||||
"entityName": "SANIMA BANK LIMITED",
|
||||
"lei": "25490043FER1B108XE95",
|
||||
"address": {
|
||||
"street": "Alkapuri, Naxal, Kathmandu",
|
||||
"addressLine1": "Alkapuri, Naxal, Kathmandu",
|
||||
"addressLine2": "",
|
||||
"city": "Kathmandu",
|
||||
"stateProvinceId": null,
|
||||
"countryId": null,
|
||||
"postalCode": "20394"
|
||||
},
|
||||
"contact": {
|
||||
"mobileNo": "",
|
||||
"emailAddress": ""
|
||||
}
|
||||
},
|
||||
{
|
||||
"clientNumber": 20,
|
||||
"accountNo": "SAMAMA-AZ-1703722701",
|
||||
"entityName": "Samama Group LLC - Azerbaijan",
|
||||
"lei": "",
|
||||
"address": {
|
||||
"street": "Sabail District, Nizami, Home 1",
|
||||
"addressLine1": "Sabail District, Nizami, Home 1",
|
||||
"addressLine2": "",
|
||||
"city": "Baku",
|
||||
"stateProvinceId": null,
|
||||
"countryId": null,
|
||||
"postalCode": "AZ1001"
|
||||
},
|
||||
"contact": {
|
||||
"mobileNo": "",
|
||||
"emailAddress": ""
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
# OMNL Entity Master Data — Names, LEI, Address, Contacts
|
||||
|
||||
**Purpose:** Single source of truth for the 19 operating / external-facing entities. Used to populate either **Offices** (Organization / Manage Offices) or **Clients** (names, LEI, address, contacts).
|
||||
|
||||
**Data file:** [OMNL_ENTITY_MASTER_DATA.json](OMNL_ENTITY_MASTER_DATA.json)
|
||||
|
||||
**Using entities as Offices (recommended):** To model the 15 as offices instead of clients, see [OMNL_OFFICES_POPULATE.md](OMNL_OFFICES_POPULATE.md). Run `omnl-offices-populate-15.sh` then `omnl-clients-remove-15.sh`.
|
||||
|
||||
---
|
||||
|
||||
## Entity list (reference)
|
||||
|
||||
| # | Account No. | Entity name |
|
||||
|---|-------------|-------------|
|
||||
| 1 | 000000001 | OMNL Head Office (DBIS) – Central Bank |
|
||||
| 2 | 000000002 | Shamrayan Enterprises |
|
||||
| 3 | 000000003 | HYBX |
|
||||
| 4 | 000000004 | TAJ Private Single Family Office |
|
||||
| 5 | 000000005 | Aseret Mortgage Bank |
|
||||
| 6 | 000000006 | Mann Li Family Offices |
|
||||
| 7 | 000000007 | Sovereign Order of Malta OSJ |
|
||||
| 8 | 000000008 | Alltra Mainnet |
|
||||
| 9 | 000000009 | FIDIS |
|
||||
| 10 | 000000010 | Alpha Omega Holdings |
|
||||
| 11 | 000000011 | SGI Capital |
|
||||
| 12 | 000000012 | Titan Financial |
|
||||
| 13 | 000000013 | Roy Walker PLLC |
|
||||
| 14 | 000000014 | SGI Partners LLC |
|
||||
| 15 | 000000015 | Tsunami Holdings AG |
|
||||
| 16 | 000000016 | Anakatech |
|
||||
| 17 | 000000017 | Anema Camden Walker Global |
|
||||
| 18 | 000000018 | NEPAL RASTRA BANK (Central Bank) |
|
||||
| 19 | 000000019 | SANIMA BANK LIMITED |
|
||||
|
||||
---
|
||||
|
||||
## Fields to complete per entity
|
||||
|
||||
### 1. Entity name
|
||||
- Already set in the JSON.
|
||||
- Pushed to Fineract as client **firstname** (full name); **lastname** empty.
|
||||
|
||||
### 2. LEI (Legal Entity Identifier)
|
||||
- **Format:** 20-character alphanumeric (e.g. `5493001KJTIIGC8Y1R12`).
|
||||
- **In Fineract:** Stored as a **Client Identifier** with document type **LEI** (or “Legal Entity Identifier”). The tenant must have a document/identifier type named LEI (or equivalent); the apply script uses the first matching type from `GET /clients/{clientId}/identifiers/template` (`allowedDocumentTypes`).
|
||||
- **In JSON:** `"lei": "<20-char LEI>"`. Leave `""` if not yet assigned.
|
||||
|
||||
### 3. Address
|
||||
- **In Fineract:** Stored via **Client Addresses** API: `POST /client/{clientId}/addresses` (and optionally `PUT` to update). Fields: `street`, `addressLine1`, `addressLine2`, `addressLine3`, `city`, `stateProvinceId`, `countryId`, `postalCode`, `isActive`. `countryId` and optionally `stateProvinceId` are Fineract reference IDs (from `GET /codes` or the UI).
|
||||
- **In JSON:** Under `address`: fill `street`, `addressLine1`, `addressLine2`, `city`, `postalCode`; set `countryId` (and `stateProvinceId` if applicable) when you have the Fineract code IDs. Use `null` or omit to skip address for that entity.
|
||||
|
||||
### 4. Contacts
|
||||
- **In Fineract:** Client-level **mobile** and **email** (e.g. `mobileNo`, `emailAddress`). May be updatable via `PUT /clients/{clientId}` if the server allows it; otherwise via UI or datatables.
|
||||
- **In JSON:** Under `contact`: `"mobileNo": "+1234567890"`, `"emailAddress": "entity@example.com"`. Leave `""` if not yet known.
|
||||
|
||||
---
|
||||
|
||||
## How to fill the JSON
|
||||
|
||||
1. Open [OMNL_ENTITY_MASTER_DATA.json](OMNL_ENTITY_MASTER_DATA.json).
|
||||
2. For each entity in `entities`:
|
||||
- **LEI:** Set `lei` to the 20-character LEI when assigned; otherwise leave `""`.
|
||||
- **Address:** Fill `address.street`, `addressLine1`, `addressLine2`, `city`, `postalCode`. For `countryId` (and `stateProvinceId`) you need the Fineract code IDs from the tenant (Admin → Code values / address config, or `GET /codes`).
|
||||
- **Contact:** Fill `contact.mobileNo` and `contact.emailAddress` as appropriate; leave `""` if unknown.
|
||||
3. Save the file. The apply script reads this file and updates Fineract (names, then LEI identifiers, addresses, then contact fields when supported).
|
||||
|
||||
---
|
||||
|
||||
## Applying data to Fineract
|
||||
|
||||
From repo root, with `omnl-fineract/.env` (or root `.env`) set:
|
||||
|
||||
```bash
|
||||
# Data file path (default: docs/04-configuration/mifos-omnl-central-bank/OMNL_ENTITY_MASTER_DATA.json)
|
||||
ENTITY_DATA="docs/04-configuration/mifos-omnl-central-bank/OMNL_ENTITY_MASTER_DATA.json"
|
||||
|
||||
# Dry run: show what would be updated
|
||||
DRY_RUN=1 bash scripts/omnl/omnl-entity-data-apply.sh
|
||||
|
||||
# Apply: names, then LEI (identifiers), addresses, contacts
|
||||
bash scripts/omnl/omnl-entity-data-apply.sh
|
||||
```
|
||||
|
||||
**Complete all clients (1–15) in one go:** If clients 9–15 do not exist yet, create them first, then apply entity data:
|
||||
|
||||
```bash
|
||||
bash scripts/omnl/omnl-clients-create-9-15.sh
|
||||
bash scripts/omnl/omnl-entity-data-apply.sh
|
||||
```
|
||||
|
||||
See [scripts/omnl/README.md](../../../scripts/omnl/README.md) for full script list.
|
||||
|
||||
---
|
||||
|
||||
## Fineract API mapping summary
|
||||
|
||||
| Master data | Fineract API | Notes |
|
||||
|-------------|--------------|--------|
|
||||
| Entity name | `PUT /clients/{clientId}` body `firstname`, `lastname` | One-line display name in UI |
|
||||
| LEI | `POST /clients/{clientId}/identifiers` | `documentTypeId` = LEI type from template; `documentKey` = LEI value |
|
||||
| Address | `POST /client/{clientId}/addresses` | Requires `countryId` (and optionally `stateProvinceId`) from tenant codes |
|
||||
| Mobile / email | `PUT /clients/{clientId}` body `mobileNo`, `emailAddress` | If server accepts; else use UI |
|
||||
|
||||
---
|
||||
|
||||
## References
|
||||
|
||||
- [OMNL_CLIENT_NAMES_FIX.md](OMNL_CLIENT_NAMES_FIX.md) — Name-only fix and canonical names
|
||||
- [FINERACT_API_REFERENCE.md](FINERACT_API_REFERENCE.md) — Auth, tenant, base URL
|
||||
- OpenAPI: `docs/api/omnl-fineract-openapi.json` — `Client`, identifiers, addresses
|
||||
@@ -0,0 +1,108 @@
|
||||
# OMNL — FX and GRU GL Accounts (Create Script & Manual Steps)
|
||||
|
||||
**Purpose:** Create the FX (foreign exchange) and GRU (M00 base reserve) GL accounts from the [Chart of Accounts](CHART_OF_ACCOUNTS.md) in Fineract. Use the script for automation or follow the step-by-step list for manual creation.
|
||||
|
||||
**Reference:** [CHART_OF_ACCOUNTS.md](CHART_OF_ACCOUNTS.md) · [FX_AND_VALUATION.md](FX_AND_VALUATION.md)
|
||||
|
||||
---
|
||||
|
||||
## 1. Script (recommended)
|
||||
|
||||
From repo root with `omnl-fineract/.env` set:
|
||||
|
||||
```bash
|
||||
bash scripts/omnl/omnl-gl-accounts-fx-gru-create.sh
|
||||
```
|
||||
|
||||
- **Idempotent:** Skips any glCode that already exists.
|
||||
- **Order:** Creates parents before children (headers then detail accounts).
|
||||
- **Accounts created:** Assets 10000, 12000, 12010, 12020, 12090, 13000, 13010; Liabilities 20000, 21000, 21010; Income 40000, 42000, 42100; Expenses 50000, 51000, 52100.
|
||||
|
||||
---
|
||||
|
||||
## 2. Step-by-step list (manual creation)
|
||||
|
||||
Create accounts in this order so parents exist before children. Use **Organization → Chart of Accounts** in the UI, or `POST /v1/glaccounts` with the body below.
|
||||
|
||||
**Fineract types:** 1 = ASSET, 2 = LIABILITY, 4 = INCOME, 5 = EXPENSE.
|
||||
**Usage:** 1 = DETAIL (postable), 2 = HEADER (grouping only).
|
||||
|
||||
### 2.1 Assets (FX reserves and settlement)
|
||||
|
||||
| Step | glCode | Name | Type | Usage | Parent glCode | Description |
|
||||
|------|--------|------|------|-------|---------------|--------------|
|
||||
| 1 | 10000 | Assets (header) | 1 ASSET | HEADER (2) | — | Total assets |
|
||||
| 2 | 12000 | Foreign currency reserves (header) | 1 ASSET | HEADER (2) | 10000 | FX reserves header |
|
||||
| 3 | 12010 | FX reserves — USD | 1 ASSET | DETAIL (1) | 12000 | Foreign currency reserves — USD |
|
||||
| 4 | 12020 | FX reserves — EUR | 1 ASSET | DETAIL (1) | 12000 | Foreign currency reserves — EUR |
|
||||
| 5 | 12090 | FX reserves — other | 1 ASSET | DETAIL (1) | 12000 | Other ISO-4217 and special units |
|
||||
| 6 | 13000 | FX settlement balances (header) | 1 ASSET | HEADER (2) | 10000 | FX settlement header |
|
||||
| 7 | 13010 | FX settlement — nostro | 1 ASSET | DETAIL (1) | 13000 | Settlement balances with counterparties |
|
||||
|
||||
### 2.2 Liabilities (GRU / M00)
|
||||
|
||||
| Step | glCode | Name | Type | Usage | Parent glCode | Description |
|
||||
|------|--------|------|------|-------|---------------|--------------|
|
||||
| 8 | 20000 | Liabilities (header) | 2 LIABILITY | HEADER (2) | — | Total liabilities |
|
||||
| 9 | 21000 | M00 — Base reserve (header) | 2 LIABILITY | HEADER (2) | 20000 | Central bank reserve unit; GRU-denominated |
|
||||
| 10 | 21010 | M00 — Bank reserves (control) | 2 LIABILITY | DETAIL (1) | 21000 | Control account for M00 |
|
||||
|
||||
### 2.3 Income (FX gains)
|
||||
|
||||
| Step | glCode | Name | Type | Usage | Parent glCode | Description |
|
||||
|------|--------|------|------|-------|---------------|--------------|
|
||||
| 11 | 40000 | Income (header) | 4 INCOME | HEADER (2) | — | Total income |
|
||||
| 12 | 42000 | FX gains (realized) | 4 INCOME | DETAIL (1) | 40000 | Realized foreign exchange gains |
|
||||
| 13 | 42100 | Unrealized FX gain (P&L) | 4 INCOME | DETAIL (1) | 40000 | Unrealized FX gain (revaluation) |
|
||||
|
||||
### 2.4 Expenses (FX losses)
|
||||
|
||||
| Step | glCode | Name | Type | Usage | Parent glCode | Description |
|
||||
|------|--------|------|------|-------|---------------|--------------|
|
||||
| 14 | 50000 | Expenses (header) | 5 EXPENSE | HEADER (2) | — | Total expenses |
|
||||
| 15 | 51000 | FX losses (realized) | 5 EXPENSE | DETAIL (1) | 50000 | Realized foreign exchange losses |
|
||||
| 16 | 52100 | Unrealized FX loss (P&L) | 5 EXPENSE | DETAIL (1) | 50000 | Unrealized FX loss (revaluation) |
|
||||
|
||||
---
|
||||
|
||||
## 3. API request body (per account)
|
||||
|
||||
For each row above, `POST /v1/glaccounts` with a body like (replace placeholders):
|
||||
|
||||
```json
|
||||
{
|
||||
"glCode": "<glCode>",
|
||||
"name": "<Name>",
|
||||
"type": <Type 1|2|4|5>,
|
||||
"usage": <1=DETAIL, 2=HEADER>,
|
||||
"parentId": <optional; Fineract id of parent account from GET /glaccounts>,
|
||||
"manualEntriesAllowed": true,
|
||||
"description": "<Description>"
|
||||
}
|
||||
```
|
||||
|
||||
- Omit `parentId` for root headers (10000, 20000, 40000, 50000).
|
||||
- For child accounts, run `GET /v1/glaccounts` and set `parentId` to the `id` of the parent’s glCode (e.g. parent 12000 → use 12000’s `id`).
|
||||
|
||||
---
|
||||
|
||||
## 4. Verification
|
||||
|
||||
After creation:
|
||||
|
||||
```bash
|
||||
curl -s -u "${OMNL_FINERACT_USER}:${OMNL_FINERACT_PASSWORD}" \
|
||||
-H "Fineract-Platform-TenantId: omnl" \
|
||||
"${OMNL_FINERACT_BASE_URL}/glaccounts" | jq '.[] | select(.glCode | test("^1[023]|^2[01]|^4[02]|^5[12]")) | {glCode, name, type: .type.value}'
|
||||
```
|
||||
|
||||
Expect 10000, 12000, 12010, 12020, 12090, 13000, 13010, 20000, 21000, 21010, 40000, 42000, 42100, 50000, 51000, 52100.
|
||||
|
||||
---
|
||||
|
||||
## 5. References
|
||||
|
||||
- [CHART_OF_ACCOUNTS.md](CHART_OF_ACCOUNTS.md) — Full CoA (gold, M0, M1, equity, etc.)
|
||||
- [FX_AND_VALUATION.md](FX_AND_VALUATION.md) — XAU triangulation, revaluation, 42100/52100 usage
|
||||
- [OMNL_GL_ACCOUNTS_REQUIRED.md](OMNL_GL_ACCOUNTS_REQUIRED.md) — Migration GL (1000, 1050, 2000, 2100, 3000)
|
||||
- [scripts/omnl/README.md](../../scripts/omnl/README.md) — Script list
|
||||
@@ -0,0 +1,106 @@
|
||||
# OMNL — Required GL Accounts and Office Usage
|
||||
|
||||
**Purpose:** List all necessary GL accounts for the OMNL ledger and clarify how offices use them. In Fineract, **GL accounts are tenant-wide** (shared); every office posts journal entries to the same chart of accounts.
|
||||
|
||||
---
|
||||
|
||||
## 1. Required GL accounts (migration and operations)
|
||||
|
||||
These are the GL accounts needed for the [Migration & Ledger Allocation Memorandum](MIGRATION_AND_LEDGER_ALLOCATION_MEMORANDUM.md), matrix posting ([OMNL_JOURNAL_LEDGER_MATRIX.md](OMNL_JOURNAL_LEDGER_MATRIX.md)), and runbook ([LEDGER_ALLOCATION_POSTING_RUNBOOK.md](LEDGER_ALLOCATION_POSTING_RUNBOOK.md)).
|
||||
|
||||
| glCode | Name | Fineract type | Usage | Purpose |
|
||||
|--------|------|----------------|-------|---------|
|
||||
| **1000** | USD Settlement / Reserve Assets | 1 (ASSET) | DETAIL | USD settlement & reserve assets; opening balance (T-001 debit) |
|
||||
| **1050** | USD Treasury Conversion Reserve (M0) | 1 (ASSET) | DETAIL | Treasury Conversion Reserve; backs M1 capacity at 1:5 (T-001B debit) |
|
||||
| **2000** | USD Central Deposits **(M0)** | 2 (LIABILITY) | DETAIL | **M0** — Monetary base; T-001 credit; reduced by T-001B and T-001C (M0→M1 conversion) |
|
||||
| **2100** | USD Liabilities **(M1)** | 2 (LIABILITY) | DETAIL | **M1** — Narrow money; T-001C credit at HO; offices 2–8 receive only 2100 (M1) in Phase C |
|
||||
| **3000** | Opening Balance Control | 3 (EQUITY) | DETAIL | Migration control account (optional in posting) |
|
||||
| **1410** | Due From Head Office (Interoffice Receivable) | 1 (ASSET) | DETAIL | For Phase C interoffice (Due-To/Due-From); branch receivable |
|
||||
| **2410** | Due To Offices (Interoffice Payable) | 2 (LIABILITY) | DETAIL | For Phase C interoffice; Head Office payable to branches |
|
||||
|
||||
**Optional in current matrix:** 3000 is referenced in the full CoA; the posted entries use 1000, 1050, 2000, 2100. If your instance uses **3100** for Opening Balance Control, that is consistent with [CHART_OF_ACCOUNTS.md](CHART_OF_ACCOUNTS.md); keep 3000 or 3100 as configured.
|
||||
|
||||
---
|
||||
|
||||
## 2. Instance alignment (OMNL Hybx)
|
||||
|
||||
After ensuring 1050 exists, the instance should have at least:
|
||||
|
||||
| glCode | Required | Notes |
|
||||
|--------|----------|--------|
|
||||
| 1000 | Yes | Reserve / settlement assets |
|
||||
| 1050 | Yes | Treasury Conversion Reserve (M0) — create if missing |
|
||||
| 2000 | Yes | Central deposits |
|
||||
| 2100 | Yes | Central or restricted liabilities (matrix credits 2100 for restricted) |
|
||||
| 2200 | Optional | Some instances use 2200 for “M1 Restricted”; matrix uses 2100 |
|
||||
| 3000 / 3100 | Optional | Control / equity; 3000 or 3100 per your CoA |
|
||||
|
||||
**Create missing accounts:** Run from repo root:
|
||||
|
||||
```bash
|
||||
bash scripts/omnl/omnl-gl-accounts-create.sh
|
||||
```
|
||||
|
||||
That script creates 1000, 1050, 2000, 2100, 3000 (idempotent). If the instance already uses 3100 for Opening Balance Control, you can keep both 3000 and 3100.
|
||||
|
||||
---
|
||||
|
||||
## 3. Each office and GL accounts
|
||||
|
||||
**In Fineract there are no per-office GL accounts.** The chart of accounts is **shared across the tenant**. Every office (Head Office and entities 2–17) posts journal entries using the **same** GL account IDs (same glCodes).
|
||||
|
||||
So:
|
||||
|
||||
- **Each office “has” all required GL accounts** in the sense that they can use them when posting: every office may post debits/credits to 1000, 1050, 2000, 2100 (and 3000/3100 if used).
|
||||
- **No office-specific GL accounts** need to be created; no “2002”, “2003” per office unless you explicitly design a per-entity CoA (not required for the current matrix).
|
||||
|
||||
**Office list (for reference):** 1 = Head Office; 2–17 = Shamrayan, HYBX, TAJ, Aseret, Mann Li, OSJ, Alltra, FIDIS, Alpha Omega, SGI Capital, Titan, Roy Walker, SGI Partners, Tsunami, Anakatech, Anema Camden Walker Global. All use the same GL.
|
||||
|
||||
---
|
||||
|
||||
## 4. Updating offices (if needed)
|
||||
|
||||
Offices are managed via **Organization / Manage Offices** (API: `GET/PUT/POST /offices`). To ensure each office is correct:
|
||||
|
||||
- **Names** — Match [OMNL_ENTITY_MASTER_DATA.json](OMNL_ENTITY_MASTER_DATA.json); run `omnl-offices-populate-15.sh` (or equivalent for 17 entities) to sync names and create missing offices.
|
||||
- **Opening date** — Set per office if required for reporting; API supports opening date on office.
|
||||
- **Parent** — Head Office (1) is root; offices 2–17 have `parentId=1`.
|
||||
|
||||
No GL-specific office updates are required; GL is tenant-wide.
|
||||
|
||||
---
|
||||
|
||||
## 5. Verification
|
||||
|
||||
From repo root with `omnl-fineract/.env` loaded:
|
||||
|
||||
```bash
|
||||
# List GL accounts (expect 1000, 1050, 2000, 2100, and optionally 3000/3100)
|
||||
curl -s -u "${OMNL_FINERACT_USER}:${OMNL_FINERACT_PASSWORD}" \
|
||||
-H "Fineract-Platform-TenantId: omnl" \
|
||||
"${OMNL_FINERACT_BASE_URL}/glaccounts" | jq '.[] | {glCode, id, name}'
|
||||
|
||||
# List offices (expect 1–17)
|
||||
curl -s -u "${OMNL_FINERACT_USER}:${OMNL_FINERACT_PASSWORD}" \
|
||||
-H "Fineract-Platform-TenantId: omnl" \
|
||||
"${OMNL_FINERACT_BASE_URL}/offices" | jq '.[] | {id, name}'
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. FX and GRU (full CoA)
|
||||
|
||||
For FX reserves (12xxx, 13xxx), GRU/M00 (21xxx), and FX gain/loss (42xxx, 52xxx), use:
|
||||
|
||||
- **Script:** `bash scripts/omnl/omnl-gl-accounts-fx-gru-create.sh`
|
||||
- **Doc:** [OMNL_GL_ACCOUNTS_FX_GRU.md](OMNL_GL_ACCOUNTS_FX_GRU.md) (script + step-by-step manual list)
|
||||
|
||||
---
|
||||
|
||||
## 7. References
|
||||
|
||||
- [LEDGER_ALLOCATION_GL_MAPPING.md](LEDGER_ALLOCATION_GL_MAPPING.md) — GL mapping and memo
|
||||
- [OMNL_JOURNAL_LEDGER_MATRIX.md](OMNL_JOURNAL_LEDGER_MATRIX.md) — Journal matrix and IPSAS
|
||||
- [omnl-gl-accounts-create.sh](../../scripts/omnl/omnl-gl-accounts-create.sh) — Create 1000, 1050, 2000, 2100, 3000
|
||||
- [OMNL_GL_ACCOUNTS_FX_GRU.md](OMNL_GL_ACCOUNTS_FX_GRU.md) — FX and GRU GL creation (script + manual steps)
|
||||
- [OMNL_ENTITY_MASTER_DATA.json](OMNL_ENTITY_MASTER_DATA.json) — Office/entity names
|
||||
@@ -0,0 +1,135 @@
|
||||
# OMNL Journal / Ledger Matrix — Full GL & IPSAS Compliance
|
||||
|
||||
**Purpose:** Single reference for the OMNL Hybx (Fineract) journal and ledger structure: **matrix** of journal entries for Head Office and all operating entities (offices 1–17), **full GL** mapping, and **IPSAS** (International Public Sector Accounting Standards) alignment. All entries are postable via the Fineract API to [omnl.hybxfinance.io](https://omnl.hybxfinance.io/).
|
||||
|
||||
**Target:** OMNL tenant `omnl`; API base `https://omnl.hybxfinance.io/fineract-provider/api/v1`. Credentials in `omnl-fineract/.env` (see [OMNL_FINERACT_CONFIGURATION.md](../OMNL_FINERACT_CONFIGURATION.md)).
|
||||
|
||||
---
|
||||
|
||||
## 1. Office / Entity mapping (Organization)
|
||||
|
||||
| officeId | Entity (Office name) | Role in ledger |
|
||||
|----------|------------------------|-----------------|
|
||||
| 1 | OMNL Head Office (DBIS) – Central Bank | Central bank; holds settlement reserves (1000), conversion reserve (1050), central deposits (2000), restricted (2100) |
|
||||
| 2 | Shamrayan Enterprises | Allocatee (M1 available + restricted) |
|
||||
| 3 | HYBX | Allocatee (capitalization escrow) |
|
||||
| 4 | TAJ Private Single Family Office | Allocatee |
|
||||
| 5 | Aseret Mortgage Bank | Allocatee |
|
||||
| 6 | Mann Li Family Offices | Allocatee |
|
||||
| 7 | Sovereign Order of Malta OSJ | Allocatee |
|
||||
| 8 | Alltra Mainnet | Allocatee |
|
||||
| 9–17 | FIDIS, Alpha Omega Holdings, …, Anakatech, Anema Camden Walker Global | Optional future allocations; same GL structure |
|
||||
|
||||
---
|
||||
|
||||
## 2. Full GL structure (IPSAS-aligned)
|
||||
|
||||
### 2.1 Migration / operational GL (in use for matrix)
|
||||
|
||||
| glCode | Name | Fineract type | Usage | IPSAS / purpose |
|
||||
|--------|------|----------------|-------|------------------|
|
||||
| 1000 | USD Settlement & Reserve Assets | 1 (ASSET) | DETAIL | Cash and cash equivalents (IPSAS 2); settlement balances |
|
||||
| 1050 | USD Treasury Conversion Reserve (M0) | 1 (ASSET) | DETAIL | Reserve backing M1 capacity; financial asset (IPSAS 28/29) |
|
||||
| 2000 | USD Central Deposits (M1) | 2 (LIABILITY) | DETAIL | Demand deposits; financial liability (IPSAS 28/29) |
|
||||
| 2100 | USD Restricted Liabilities | 2 (LIABILITY) | DETAIL | Restricted/escrow; financial liability |
|
||||
| 3000 | Opening Balance Control | 3 (EQUITY) | DETAIL | Migration control; equity (IPSAS 1) |
|
||||
|
||||
### 2.2 Extended CoA (full central bank — reference)
|
||||
|
||||
The full OMNL Chart of Accounts (M00/M0/M1, reserves, FX, income/expense) is in [CHART_OF_ACCOUNTS.md](CHART_OF_ACCOUNTS.md). Summary:
|
||||
|
||||
- **1xxxx** ASSETS (11xxx gold/commodity, 12xxx FX reserves, 13xxx settlement)
|
||||
- **2xxxx** LIABILITIES (21xxx M00, 22xxx M0, 23xxx M1)
|
||||
- **3xxxx** EQUITY (31xxx sovereign capital, 32xxx revaluation)
|
||||
- **4xxxx** INCOME (41xxx seigniorage, 42xxx FX gains)
|
||||
- **5xxxx** EXPENSES (51xxx FX losses, 52xxx monetary ops)
|
||||
|
||||
Migration accounts 1000, 1050, 2000, 2100, 3000 map into this structure for opening balance and allocation; expand to 13xxx/23xxx etc. when consolidating to full IPSAS reporting.
|
||||
|
||||
---
|
||||
|
||||
## 3. IPSAS compliance mapping
|
||||
|
||||
| IPSAS | Topic | OMNL application |
|
||||
|-------|--------|-------------------|
|
||||
| IPSAS 1 | Presentation of Financial Statements | Structure of FS (assets, liabilities, equity, income, expense); segment reporting by office/entity |
|
||||
| IPSAS 2 | Cash Flow Statements | 1000/1050/2000/2100 support cash and cash-equivalent classification |
|
||||
| IPSAS 3 | Accounting Policies, Changes, Errors | Documented in [MIGRATION_AND_LEDGER_ALLOCATION_MEMORANDUM.md](MIGRATION_AND_LEDGER_ALLOCATION_MEMORANDUM.md) and this matrix |
|
||||
| IPSAS 9 | Revenue from Exchange Transactions | Revenue (4xxxx) separated; allocation entries are internal transfers, not revenue |
|
||||
| IPSAS 23 | Revenue from Non-Exchange Transactions | Non-exchange flows (e.g. grants) if any; narrative in journal |
|
||||
| IPSAS 28 | Financial Instruments: Presentation | 1000, 1050, 2000, 2100 as financial assets/liabilities; classified and disclosed |
|
||||
| IPSAS 29 | Financial Instruments: Recognition & Measurement | Amortized cost for deposits/reserves; fair value if applicable and disclosed |
|
||||
| IPSAS 41 | Financial Reporting Under the Cash Basis | Cash basis option; OMNL uses accrual (double-entry) |
|
||||
| IPSAS 42 | Social Benefits | N/A for central bank monetary operations |
|
||||
|
||||
---
|
||||
|
||||
## 4. Journal entry matrix (Head Office + entities)
|
||||
|
||||
All entries are posted with **officeId = 1** (Head Office) in the current Fineract model; narrative and memo identify the entity. Amounts in USD. Post in order.
|
||||
|
||||
| # | Memo | Debit glCode | Credit glCode | Amount (USD) | Narrative / entity | IPSAS note |
|
||||
|---|------|--------------|---------------|--------------|-------------------|------------|
|
||||
| 1 | T-001 | 1000 | 2000 | 900,000,000,000 | Opening Balance Migration (Head Office) | IPSAS 3, 28 |
|
||||
| 2 | T-001B | 1050 | 2000 | 250,000,000,000 | Treasury Conversion — Transfer to Reserve (M0); Head Office | IPSAS 28, 29 |
|
||||
| 3 | T-002A | 2000 | 2000 | 2,900,000,000 | Shamrayan Available (M1) — Office 2 | IPSAS 28 |
|
||||
| 4 | T-002B | 2000 | 2100 | 2,100,000,000 | Shamrayan Restricted — Office 2 | IPSAS 28 |
|
||||
| 5 | T-003 | 2000 | 2100 | 350,000,000,000 | HYBX Capitalization Escrow — Office 3 | IPSAS 28 |
|
||||
| 6 | T-004 | 2000 | 2000 | 5,000,000,000 | TAJ Allocation (M1) — Office 4 | IPSAS 28 |
|
||||
| 7 | T-005 | 2000 | 2000 | 5,000,000,000 | Aseret Allocation (M1) — Office 5 | IPSAS 28 |
|
||||
| 8 | T-006 | 2000 | 2000 | 5,000,000,000 | Mann Li Allocation (M1) — Office 6 | IPSAS 28 |
|
||||
| 9 | T-007 | 2000 | 2000 | 50,000,000,000 | OSJ Allocation (M1) — Office 7 | IPSAS 28 |
|
||||
| 10 | T-008 | 2000 | 2000 | 50,000,000,000 | Alltra Allocation (M1) — Office 8 | IPSAS 28 |
|
||||
|
||||
**Note:** For per-entity/segment reporting, Fineract journal entries use a single `officeId` per entry. Entity is identified in `comments`/narrative. If the tenant is extended to per-office GL (e.g. 2002, 2003, …), the matrix can be updated to debit/credit those accounts and post with the corresponding `officeId`.
|
||||
|
||||
---
|
||||
|
||||
## 5. API usage (OMNL Hybx)
|
||||
|
||||
- **Create GL accounts:** `POST /glaccounts` — ensure 1000, 1050, 2000, 2100, 3000 exist ([omnl-gl-accounts-create.sh](../../scripts/omnl/omnl-gl-accounts-create.sh)).
|
||||
- **Resolve GL IDs:** `GET /glaccounts` — map glCode → id for each journal line.
|
||||
- **Post journal entries:** `POST /journalentries` — body: `officeId`, `transactionDate`, `dateFormat`, `locale`, `currencyCode`, `comments`, `debits[]`, `credits[]` (each with `glAccountId`, `amount`).
|
||||
|
||||
**Scripts:**
|
||||
|
||||
- **From runbook (fixed list):** [omnl-ledger-post.sh](../../scripts/omnl/omnl-ledger-post.sh) — posts T-001 through T-008 per [LEDGER_ALLOCATION_POSTING_RUNBOOK.md](LEDGER_ALLOCATION_POSTING_RUNBOOK.md).
|
||||
- **From matrix JSON:** [omnl-ledger-post-from-matrix.sh](../../scripts/omnl/omnl-ledger-post-from-matrix.sh) — reads [omnl-journal-matrix.json](omnl-journal-matrix.json), resolves glCode → id, posts in order.
|
||||
|
||||
**Environment:** `omnl-fineract/.env`: `OMNL_FINERACT_BASE_URL`, `OMNL_FINERACT_PASSWORD`. Optional: `TRANSACTION_DATE=yyyy-MM-dd`, `OFFICE_ID=1`, `DRY_RUN=1`.
|
||||
|
||||
---
|
||||
|
||||
## 6. Reconciliation (matrix totals)
|
||||
|
||||
| GL (glCode) | Expected balance (USD) after all entries | Notes |
|
||||
|-------------|------------------------------------------|--------|
|
||||
| 1000 | 900,000,000,000 | Debit (T-001) |
|
||||
| 1050 | 250,000,000,000 | Debit (T-001B) |
|
||||
| 2000 | 780,000,000,000 | Credit: 900B+250B − 470B allocations; net liability |
|
||||
| 2100 | 352,100,000,000 | Credit: 2.1B + 350B (Shamrayan restricted + HYBX escrow) |
|
||||
|
||||
---
|
||||
|
||||
## 7. Next steps (complete flow)
|
||||
|
||||
| Step | Action | Script / doc |
|
||||
|------|--------|---------------|
|
||||
| 1 | **Create GL accounts** (1000, 1050, 2000, 2100, 3000, and for Phase C interoffice 1410, 2410) if not present | `bash scripts/omnl/omnl-gl-accounts-create.sh` |
|
||||
| 2 | **Verify** offices and GL: `GET /offices`, `GET /glaccounts` | [LEDGER_ALLOCATION_POSTING_RUNBOOK.md](LEDGER_ALLOCATION_POSTING_RUNBOOK.md) pre-posting checklist |
|
||||
| 3 | **Post journal entries** from matrix (or runbook list). For **Phase C interoffice** use [omnl-journal-matrix-phase-c-interoffice.json](omnl-journal-matrix-phase-c-interoffice.json) (see [OMNL_PHASE_C_INTEROFFICE_DUE_TO_DUE_FROM.md](OMNL_PHASE_C_INTEROFFICE_DUE_TO_DUE_FROM.md)) | `DRY_RUN=1 bash scripts/omnl/omnl-ledger-post-from-matrix.sh` then run without DRY_RUN |
|
||||
| 4 | **Reconcile** trial balance / GL report per runbook | [LEDGER_ALLOCATION_POSTING_RUNBOOK.md](LEDGER_ALLOCATION_POSTING_RUNBOOK.md) § Post-posting reconciliation |
|
||||
| 5 | **Sign-off and audit** — attach memo, runbook, matrix to audit trail | [LEDGER_ALLOCATION_POSTING_RUNBOOK.md](LEDGER_ALLOCATION_POSTING_RUNBOOK.md) § Sign-off and audit |
|
||||
|
||||
**Optional:** Use `omnl-ledger-post.sh` (fixed T-001–T-008 list) instead of the matrix script if you prefer not to use the JSON file.
|
||||
|
||||
---
|
||||
|
||||
## 8. References
|
||||
|
||||
- [MIGRATION_AND_LEDGER_ALLOCATION_MEMORANDUM.md](MIGRATION_AND_LEDGER_ALLOCATION_MEMORANDUM.md) — Authoritative migration memo
|
||||
- [LEDGER_ALLOCATION_GL_MAPPING.md](LEDGER_ALLOCATION_GL_MAPPING.md) — GL mapping and implementation
|
||||
- [LEDGER_ALLOCATION_POSTING_RUNBOOK.md](LEDGER_ALLOCATION_POSTING_RUNBOOK.md) — Posting runbook
|
||||
- [CHART_OF_ACCOUNTS.md](CHART_OF_ACCOUNTS.md) — Full OMNL CoA (1xxxx–5xxxx)
|
||||
- [OMNL_ENTITY_MASTER_DATA.json](OMNL_ENTITY_MASTER_DATA.json) — Office/entity list (1–17)
|
||||
- Swagger UI: [omnl.hybxfinance.io/fineract-provider/swagger-ui](https://omnl.hybxfinance.io/fineract-provider/swagger-ui/index.html)
|
||||
@@ -0,0 +1,72 @@
|
||||
# OMNL — Populate Entities as Offices (Remove as Clients)
|
||||
|
||||
**Purpose:** Use the operating entities from master data as **Offices** (Organization / Manage Offices) instead of Clients. This updates the head office name and creates child offices 2–19 (from entity data), then removes the corresponding client records.
|
||||
|
||||
**API:** Fineract **Offices** API (`GET/PUT/POST /offices`); **Clients** API (`DELETE /clients/{id}`).
|
||||
|
||||
---
|
||||
|
||||
## Entity list (same as master data)
|
||||
|
||||
| # | Entity name | As office |
|
||||
|---|-------------|-----------|
|
||||
| 1 | OMNL Head Office (DBIS) – Central Bank | Office 1 (updated name) |
|
||||
| 2 | Shamrayan Enterprises | New office, parent=1 |
|
||||
| 3 | HYBX | New office, parent=1 |
|
||||
| … | … | … |
|
||||
| 15 | Tsunami Holdings AG | New office, parent=1 |
|
||||
| 16 | Anakatech | New office, parent=1 |
|
||||
| 17 | Anema Camden Walker Global | New office, parent=1 |
|
||||
| 18 | NEPAL RASTRA BANK (Central Bank) | New office, parent=1 |
|
||||
| 19 | SANIMA BANK LIMITED | New office, parent=1 |
|
||||
|
||||
Office 1 already exists (Head Office). It is **renamed** to entity 1. Offices 2, 3, … are **created** with `parentId=1` and `externalId=OMNL-2`, `OMNL-3`, … (one per entity in master data with clientNumber ≥ 2).
|
||||
|
||||
---
|
||||
|
||||
## Steps
|
||||
|
||||
### 1. Populate entities as offices
|
||||
|
||||
From repo root with `omnl-fineract/.env` set:
|
||||
|
||||
```bash
|
||||
# Preview
|
||||
DRY_RUN=1 bash scripts/omnl/omnl-offices-populate-15.sh
|
||||
|
||||
# Run: update office 1 name, create offices 2–19 (from entity data)
|
||||
bash scripts/omnl/omnl-offices-populate-15.sh
|
||||
```
|
||||
|
||||
- **ENTITY_DATA:** Path to [OMNL_ENTITY_MASTER_DATA.json](OMNL_ENTITY_MASTER_DATA.json) (default).
|
||||
- **OPENING_DATE:** `yyyy-MM-dd` for new offices (default `2026-01-01`).
|
||||
|
||||
Idempotent: offices already present (by externalId) are skipped.
|
||||
|
||||
### 2. Remove the 15 clients
|
||||
|
||||
After the offices are in place, delete the 15 client records:
|
||||
|
||||
```bash
|
||||
# Preview
|
||||
DRY_RUN=1 bash scripts/omnl/omnl-clients-remove-15.sh
|
||||
|
||||
# Run (requires confirmation)
|
||||
CONFIRM_REMOVE=1 bash scripts/omnl/omnl-clients-remove-15.sh
|
||||
```
|
||||
|
||||
Deletes client ids 1–15 (in reverse order). If any client has linked data (e.g. accounts), the API may reject the delete; resolve those first in the UI or API.
|
||||
|
||||
---
|
||||
|
||||
## Result
|
||||
|
||||
- **Organization / Manage Offices:** 19 offices: “OMNL Head Office (DBIS) – Central Bank” (id=1) plus Shamrayan Enterprises, HYBX, … NEPAL RASTRA BANK, SANIMA BANK LIMITED (ids 2–19), all under office 1.
|
||||
- **Clients:** The former entity clients are removed; new clients can be created and assigned to any of these offices.
|
||||
|
||||
---
|
||||
|
||||
## References
|
||||
|
||||
- [OMNL_ENTITY_MASTER_DATA.json](OMNL_ENTITY_MASTER_DATA.json) — Source of entity names
|
||||
- [scripts/omnl/README.md](../../../scripts/omnl/README.md) — Script list and usage
|
||||
@@ -0,0 +1,138 @@
|
||||
# OMNL-2 Access Security Test — Collateral Attacks and Data Isolation
|
||||
|
||||
**Purpose:** Verify that the office OMNL-2 (Office 2, Shamrayan) user **cannot** gain access to anything beyond Office 2 data—including no shell access, no arbitrary file read (e.g. `cat` or directory listing), and no exposure of “secret sauce” (config, .env, other offices’ data).
|
||||
|
||||
**Principle:** Nothing more than the data for office OMNL-2 may be exposed. Access must not be abusable for collateral attacks.
|
||||
|
||||
---
|
||||
|
||||
## 1. Attack surface
|
||||
|
||||
| Vector | What the office-2 user has | What they must NOT get |
|
||||
|--------|---------------------------|-------------------------|
|
||||
| **Fineract API** | HTTP Basic auth to `omnl.hybxfinance.io` (REST) | Other offices’ data; shell execution; filesystem read |
|
||||
| **Mifos UI** | Web login to same instance | Other offices in dropdowns/reports; dev tools / network revealing other offices |
|
||||
| **SSH / server** | Only if explicitly granted (separate from Mifos) | Shell on app host; read of `.env`, app config, or repo |
|
||||
|
||||
The Fineract application itself does **not** grant OS shell or filesystem access to API users. The tests below check that the API and UI do not leak other offices’ data and that no parameter allows path traversal, command injection, or SSRF that could expose files or run commands.
|
||||
|
||||
---
|
||||
|
||||
## 2. Data isolation (API)
|
||||
|
||||
**Objective:** With office-2 user credentials, the user must not see or access data for other offices (e.g. 1, 20, 21).
|
||||
|
||||
| Test | Action | Expected |
|
||||
|------|--------|----------|
|
||||
| 2.1 | `GET /offices` as office-2 user | Only office 2 (and parent if applicable); **no** full list of all offices (e.g. no 20, 21). |
|
||||
| 2.2 | `GET /offices/1` or `GET /offices/20` (if IDs exist) as office-2 user | 403 Forbidden or 404, or only office 2 in response. |
|
||||
| 2.3 | `GET /clients?officeId=1` or `officeId=20` as office-2 user | 403 or empty/filtered so only office-2 clients (if any) when querying within allowed scope. |
|
||||
| 2.4 | `GET /journalentries?officeId=1` or `officeId=20` as office-2 user | 403 or empty/filtered; no journal entries for other offices. |
|
||||
| 2.5 | `GET /glaccounts` as office-2 user | If allowed, only for reporting; must not return data that reveals other offices’ balances (e.g. by officeId) beyond what’s allowed for office 2. |
|
||||
|
||||
Run with the office-2 user’s Basic auth (e.g. `shamrayan.admin` / password). See **Section 5** for a script.
|
||||
|
||||
---
|
||||
|
||||
## 3. Path traversal and local file read
|
||||
|
||||
**Objective:** No API parameter must allow reading arbitrary files (e.g. `cat /etc/passwd` or `../../.env`).
|
||||
|
||||
| Test | Action | Expected |
|
||||
|------|--------|----------|
|
||||
| 3.1 | Any endpoint that accepts a **file path**, **template name**, or **report path** (e.g. report export, document template): send `../../../etc/passwd` or `file:///etc/passwd` (if URL is accepted). | 400 Bad Request or 404; **no** content of `/etc/passwd` or any server file in the response body. |
|
||||
| 3.2 | Try path-like values in query or body: `template=../../.env`, `file=....//....//....//etc/passwd`. | Same: no file content in response. |
|
||||
|
||||
Fineract’s standard REST endpoints (offices, clients, journalentries, glaccounts) do not take arbitrary file paths; if your instance exposes custom or report endpoints that do, test those specifically.
|
||||
|
||||
---
|
||||
|
||||
## 4. Command injection (no `cat`, bash, or OS commands)
|
||||
|
||||
**Objective:** No API parameter must be executed as an OS command (e.g. bash, `cat`, `id`).
|
||||
|
||||
| Test | Action | Expected |
|
||||
|------|--------|----------|
|
||||
| 4.1 | In **comments**, **narrative**, **reference**, or **name** fields (e.g. journal entry, client name): send `; cat /etc/passwd`, `$(cat /etc/passwd)`, `` `id` ``, `| cat /etc/passwd`. | Value stored or reflected as **literal text**; **no** output of `cat` or `id` in response or anywhere else. |
|
||||
| 4.2 | Same in query parameters (e.g. `comments=;id`). | Treated as literal; no command execution. |
|
||||
|
||||
If any response body or later API response contains `/etc/passwd` contents or `uid=` output, treat as **critical** and fix.
|
||||
|
||||
---
|
||||
|
||||
## 5. SSRF (no internal or file URL fetch)
|
||||
|
||||
**Objective:** No endpoint that takes a URL may fetch internal resources or `file://` from the server.
|
||||
|
||||
| Test | Action | Expected |
|
||||
|------|--------|----------|
|
||||
| 5.1 | If any endpoint accepts a URL (e.g. webhook, callback, document URL): send `file:///etc/passwd` or `http://169.254.169.254/` (metadata). | 400 or no fetch of that URL; response must not contain contents of that resource. |
|
||||
|
||||
---
|
||||
|
||||
## 6. Shell and filesystem (clarification)
|
||||
|
||||
- **Fineract/Mifos API:** Does not provide shell or direct filesystem access. The only way to “run `cat`” or “see files in directories” via the **application** would be a bug (e.g. path traversal, RCE, or SSRF). The tests above are designed to catch such issues.
|
||||
- **SSH to a host:** If the same person (office-2 operator) is granted **SSH** to a server (e.g. for running scripts), that is a **separate** access path. Then:
|
||||
- **Do not** use the same credentials as Fineract; use a dedicated OS user.
|
||||
- Use a **restricted shell** or **allowed commands only** so they cannot run arbitrary `cat`, `ls`, or access app directories.
|
||||
- Ensure the user **cannot** read: `.env`, `omnl-fineract/.env`, app config with credentials, or any directory that holds other offices’ exports or “secret sauce.”
|
||||
- Prefer a **jump host** or **restricted VM** that only has the minimum needed (e.g. run one script) and no access to the Fineract server’s filesystem.
|
||||
|
||||
---
|
||||
|
||||
## 7. Executable test script (API tests)
|
||||
|
||||
From repo root, with **office-2** credentials set (do **not** use the global `app.omnl` admin):
|
||||
|
||||
```bash
|
||||
# Option A: use OMNL-2–specific dotenv (omnl-fineract/.env.office2)
|
||||
set -a && source omnl-fineract/.env.office2 && set +a
|
||||
bash scripts/omnl/omnl-office2-access-security-test.sh
|
||||
|
||||
# Option B: set variables manually
|
||||
export OMNL_OFFICE2_TEST_USER="shamrayan_admin"
|
||||
export OMNL_OFFICE2_TEST_PASSWORD="<office-2-password>"
|
||||
export OMNL_FINERACT_BASE_URL="https://omnl.hybxfinance.io/fineract-provider/api/v1"
|
||||
export OMNL_FINERACT_TENANT="omnl"
|
||||
bash scripts/omnl/omnl-office2-access-security-test.sh
|
||||
```
|
||||
|
||||
The script will:
|
||||
|
||||
- **[1]** `GET /offices` — **Fail** if office 2 is not in the response. If other offices (e.g. 20, 21) are listed, **warn** only unless `STRICT_OFFICE_LIST=1`.
|
||||
- **[2]** `GET /offices/20` — **Fail** only in strict mode (`STRICT_OFFICE_LIST=1`) if 200 with office 20 data.
|
||||
- **[3]** `GET /clients?officeId=20` — **Fail** if 200 with any clients (office-2 user must not see other offices’ clients).
|
||||
- **[4]** Command injection — **Fail** if response contains actual file/command output (e.g. `root:...:0:0:`, `uid=...gid=`).
|
||||
- **[5]** Path traversal — **Fail** if response contains `/etc/passwd`-style line content.
|
||||
|
||||
To enforce strict office list (fail when other offices are visible or when `GET /offices/20` returns 200):
|
||||
|
||||
```bash
|
||||
export STRICT_OFFICE_LIST=1
|
||||
bash scripts/omnl/omnl-office2-access-security-test.sh
|
||||
```
|
||||
|
||||
See `scripts/omnl/omnl-office2-access-security-test.sh` for the exact checks and exit codes.
|
||||
|
||||
---
|
||||
|
||||
## 8. Checklist summary
|
||||
|
||||
| # | Check | Pass criteria |
|
||||
|---|--------|----------------|
|
||||
| 1 | Data isolation (API) | Office-2 user sees only office 2 (and allowed parent); no other offices’ clients/JEs. |
|
||||
| 2 | Path traversal | No parameter returns server file content (e.g. `/etc/passwd`, `.env`). |
|
||||
| 3 | Command injection | No parameter executes OS commands; payloads appear as literal text. |
|
||||
| 4 | SSRF | No URL parameter fetches `file://` or internal endpoints. |
|
||||
| 5 | Shell/filesystem | No shell or directory access via Fineract; if SSH is granted, it is restricted and cannot read secret sauce. |
|
||||
|
||||
Run the script and the manual UI checks from [OMNL_OFFICE_LOGINS_AND_CREDENTIALS.md](OMNL_OFFICE_LOGINS_AND_CREDENTIALS.md#verification-only-omnl-2-data-exposed) at least once before treating OMNL-2 access as production-ready.
|
||||
|
||||
---
|
||||
|
||||
## References
|
||||
|
||||
- [OMNL_OFFICE_LOGINS_AND_CREDENTIALS.md](OMNL_OFFICE_LOGINS_AND_CREDENTIALS.md) — Data isolation requirement and verification
|
||||
- [OMNL_FINERACT_CONFIGURATION.md](../OMNL_FINERACT_CONFIGURATION.md) — Base URL, tenant, auth
|
||||
- Fineract Swagger: [omnl.hybxfinance.io/fineract-provider/swagger-ui](https://omnl.hybxfinance.io/fineract-provider/swagger-ui/index.html)
|
||||
@@ -0,0 +1,56 @@
|
||||
# OMNL Office Address Book
|
||||
|
||||
**Purpose:** Per-office identity, API Banking Rail instructions (endpoint, auth, **secrets reference** only — no secrets in repo), and pointer to Master Runbook and sub-runbooks. See [OMNL_OFFICE_MASTER_RUNBOOK_INDEX.md](OMNL_OFFICE_MASTER_RUNBOOK_INDEX.md) for Master vs sub-runbooks by office.
|
||||
|
||||
**Secrets:** Store credentials in vault. This doc references vault path only; do not commit tokens or keys.
|
||||
|
||||
---
|
||||
|
||||
## Office 1 — Head Office
|
||||
|
||||
- **officeId:** 1 | **Entity:** OMNL Head Office (DBIS) – Central Bank
|
||||
- **Master Runbook:** [OPERATING_RAILS.md](OPERATING_RAILS.md) | **Sub:** [LEDGER_ALLOCATION_POSTING_RUNBOOK.md](LEDGER_ALLOCATION_POSTING_RUNBOOK.md)
|
||||
- **Banking Rail:** N/A (HO is originator)
|
||||
|
||||
---
|
||||
|
||||
## Office 2 — Shamrayan Enterprises
|
||||
|
||||
- **officeId:** 2 | **Entity:** Shamrayan Enterprises
|
||||
- **Master Runbook:** [OFFICE_2_SHAMRAYAN_RUNBOOK.md](OFFICE_2_SHAMRAYAN_RUNBOOK.md) | **Sub:** [OFFICE_2_READINESS_CONFIRMATION.md](OFFICE_2_READINESS_CONFIRMATION.md); P2P API send in runbook
|
||||
- **Banking Rail:** `https://banktransfer.devmindgroup.com` (POST `/api/bank-servers`, `/api/bank-accounts`, `/api/transactions`) | Auth: Bearer + API key | **Secrets:** Vault `omnl/offices/2/p2p` (Bearer token, API key) | Idempotency: `SHAMRAYAN-2-<YYYYMMDD>-SET-<amount>` | Channel: Instant Server Settlement | Receiver: DFCUUGKA / 02650010158937 (see runbook)
|
||||
|
||||
---
|
||||
|
||||
## Office 20 — Samama Group LLC (Azerbaijan)
|
||||
|
||||
- **officeId:** 20 | **Entity:** Samama Group LLC - Azerbaijan | **externalId:** SAMAMA-AZ-1703722701
|
||||
- **Master Runbook:** [SAMAMA_OFFICE_AND_5B_M1_TRANSFER.md](SAMAMA_OFFICE_AND_5B_M1_TRANSFER.md) + [TRANCHE_1_500M_RUNBOOK.md](TRANCHE_1_500M_RUNBOOK.md) | **Sub:** OFFICE_20_AUDIT_PACKET, DR, Fire Drill
|
||||
- **Banking Rail:** Artifact upload `https://upload.siemb-samama.com/` | **Secrets:** Vault `omnl/offices/20/upload` | P2P settlement TBD
|
||||
|
||||
---
|
||||
|
||||
## Office 21 — Crunchygalaxy Unip. Lda. (Portugal)
|
||||
|
||||
- **officeId:** 21 | **Entity:** Crunchygalaxy Unip Lda - Portugal | **externalId:** CRUNCHYGALAXY-515159573
|
||||
- **Master Runbook:** [CRUNCHYGALAXY_OFFICE_AND_1B_FUNDING.md](CRUNCHYGALAXY_OFFICE_AND_1B_FUNDING.md) | **Sub:** [P2P_SETTLEMENT_CRUNCHYGALAXY_RAIL.md](P2P_SETTLEMENT_CRUNCHYGALAXY_RAIL.md)
|
||||
- **Banking Rail:** Settlement endpoint TBD | Auth TBD | **Secrets:** Vault `omnl/offices/21/p2p` | Idempotency: `CRUNCHY-21-<YYYYMMDD>-SET-<amount>` | Mirror ref: `CRUNCHY-21-<date>-SETTLED-<amount>`
|
||||
|
||||
---
|
||||
|
||||
## Other offices (3–19)
|
||||
|
||||
Add a row when an office gets a Banking Rail endpoint or Master Runbook: officeId, Entity, Master Runbook, Sub-runbooks, Banking Rail (endpoint, auth, **vault path only**).
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
| officeId | Entity | Master Runbook | Secrets (vault path) |
|
||||
|----------|--------|----------------|----------------------|
|
||||
| 1 | Head Office | OPERATING_RAILS | N/A |
|
||||
| 2 | Shamrayan | OFFICE_2_SHAMRAYAN_RUNBOOK | offices/2/p2p |
|
||||
| 20 | Samama | SAMAMA + TRANCHE_1_500M | offices/20/upload |
|
||||
| 21 | Crunchygalaxy | CRUNCHYGALAXY_OFFICE_AND_1B_FUNDING | offices/21/p2p |
|
||||
|
||||
Credentials live only in vault; this address book holds instructions and vault references.
|
||||
@@ -0,0 +1,193 @@
|
||||
# OMNL — Balances by Office
|
||||
|
||||
**Purpose:** GL balances per office after Phase A+B and Phase C interoffice posting. All amounts in **USD**. Debit (Dr) = asset increase / liability decrease; Credit (Cr) = liability increase / asset decrease. **Transaction date of postings:** 2026-02-23.
|
||||
|
||||
**GL classification:** **2000 = M0** (monetary base / central deposits). **2100 = M1** (narrow money / demand deposits). M0 is converted to M1 at Head Office (T-001C: Dr 2000 Cr 2100); distribution to offices debits OMNL **2100 (M1)** and credits **2100 (M1)** at each office only.
|
||||
|
||||
**Policy for offices 2–20:** **Zero Debt** and **Only M1 Credits (2100).**
|
||||
- **Zero Debt:** Offices 2–20 have no debt. Any 1410 (Due From HO) is an interoffice asset, not debt.
|
||||
- **Only M1 Credits:** The only credit balances at offices 2–20 are **2100 (M1)**. Offices do not hold 2000 (M0). **Offices 9–19 each have 1B M1**; **Office 20 (Samama) has 5B M1** (create via [SAMAMA_OFFICE_AND_5B_M1_TRANSFER.md](SAMAMA_OFFICE_AND_5B_M1_TRANSFER.md)).
|
||||
|
||||
**Source:** [omnl-journal-matrix-phase-a-b-only.json](omnl-journal-matrix-phase-a-b-only.json), [omnl-journal-matrix-phase-c-interoffice.json](omnl-journal-matrix-phase-c-interoffice.json), [omnl-journal-matrix-m0-m1-supplement-11b.json](omnl-journal-matrix-m0-m1-supplement-11b.json), [omnl-journal-matrix-phase-c-offices-9-19.json](omnl-journal-matrix-phase-c-offices-9-19.json), [omnl-journal-matrix-samama-5b.json](omnl-journal-matrix-samama-5b.json) (Office 20).
|
||||
|
||||
---
|
||||
|
||||
## Offices 2–19: Zero Debt / M1 Credits Only (summary)
|
||||
|
||||
| Office ID | Office name | Debt (borrowings / other liabilities) | M1 Credits only (2100) |
|
||||
|-----------|-------------|----------------------------------------|------------------------|
|
||||
| 2 | Shamrayan Enterprises | **0** | **5,000,000,000** (2100 M1 only) |
|
||||
| 3 | HYBX | **0** | **350,000,000,000** (2100 M1 only) |
|
||||
| 4 | TAJ Private Single Family Office | **0** | **5,000,000,000** (2100 M1 only) |
|
||||
| 5 | Aseret Mortgage Bank | **0** | **5,000,000,000** (2100 M1 only) |
|
||||
| 6 | Mann Li Family Offices | **0** | **5,000,000,000** (2100 M1 only) |
|
||||
| 7 | Sovereign Order of Malta OSJ | **0** | **50,000,000,000** (2100 M1 only) |
|
||||
| 8 | Alltra Mainnet | **0** | **50,000,000,000** (2100 M1 only) |
|
||||
| 9 | FIDIS | **0** | **1,000,000,000** (2100 M1 only) |
|
||||
| 10 | Alpha Omega Holdings | **0** | **1,000,000,000** (2100 M1 only) |
|
||||
| 11 | SGI Capital | **0** | **1,000,000,000** (2100 M1 only) |
|
||||
| 12 | Titan Financial | **0** | **1,000,000,000** (2100 M1 only) |
|
||||
| 13 | Roy Walker PLLC | **0** | **1,000,000,000** (2100 M1 only) |
|
||||
| 14 | SGI Partners LLC | **0** | **1,000,000,000** (2100 M1 only) |
|
||||
| 15 | Tsunami Holdings AG | **0** | **1,000,000,000** (2100 M1 only) |
|
||||
| 16 | Anakatech | **0** | **1,000,000,000** (2100 M1 only) |
|
||||
| 17 | Anema Camden Walker Global | **0** | **1,000,000,000** (2100 M1 only) |
|
||||
| 18 | NEPAL RASTRA BANK | **0** | **1,000,000,000** (2100 M1 only) |
|
||||
| 19 | SANIMA BANK LIMITED | **0** | **1,000,000,000** (2100 M1 only) |
|
||||
| 20 | Samama Group LLC - Azerbaijan | **0** | **5,000,000,000** (2100 M1 only) |
|
||||
|
||||
*Note:* 1410 (Due From Head Office) at offices 2–19 is an interoffice **asset** (receivable from HO), not debt. It balances the M1 credits for double-entry; the office has no debt liabilities.
|
||||
|
||||
---
|
||||
|
||||
## Summary by office (full GL view)
|
||||
|
||||
| Office ID | Office name | Total assets (Dr) | Total liabilities (Cr) | Net (assets − liabilities) |
|
||||
|-----------|-------------|-------------------|------------------------|-----------------------------|
|
||||
| 1 | OMNL Head Office (DBIS) – Central Bank | 1,161,000,000,000 | 1,161,000,000,000 | 0 |
|
||||
| 2 | Shamrayan Enterprises | 5,000,000,000 | 5,000,000,000 | 0 |
|
||||
| 3 | HYBX | 350,000,000,000 | 350,000,000,000 | 0 |
|
||||
| 4 | TAJ Private Single Family Office | 5,000,000,000 | 5,000,000,000 | 0 |
|
||||
| 5 | Aseret Mortgage Bank | 5,000,000,000 | 5,000,000,000 | 0 |
|
||||
| 6 | Mann Li Family Offices | 5,000,000,000 | 5,000,000,000 | 0 |
|
||||
| 7 | Sovereign Order of Malta OSJ | 50,000,000,000 | 50,000,000,000 | 0 |
|
||||
| 8 | Alltra Mainnet | 50,000,000,000 | 50,000,000,000 | 0 |
|
||||
| 9 | FIDIS | 1,000,000,000 | 1,000,000,000 | 0 |
|
||||
| 10 | Alpha Omega Holdings | 1,000,000,000 | 1,000,000,000 | 0 |
|
||||
| 11 | SGI Capital | 1,000,000,000 | 1,000,000,000 | 0 |
|
||||
| 12 | Titan Financial | 1,000,000,000 | 1,000,000,000 | 0 |
|
||||
| 13 | Roy Walker PLLC | 1,000,000,000 | 1,000,000,000 | 0 |
|
||||
| 14 | SGI Partners LLC | 1,000,000,000 | 1,000,000,000 | 0 |
|
||||
| 15 | Tsunami Holdings AG | 1,000,000,000 | 1,000,000,000 | 0 |
|
||||
| 16 | Anakatech | 1,000,000,000 | 1,000,000,000 | 0 |
|
||||
| 17 | Anema Camden Walker Global | 1,000,000,000 | 1,000,000,000 | 0 |
|
||||
| 18 | NEPAL RASTRA BANK | 1,000,000,000 | 1,000,000,000 | 0 |
|
||||
| 19 | SANIMA BANK LIMITED | 1,000,000,000 | 1,000,000,000 | 0 |
|
||||
| 20 | Samama Group LLC - Azerbaijan | 5,000,000,000 | 5,000,000,000 | 0 |
|
||||
| **Total** | | **1,596,000,000,000** | **1,596,000,000,000** | **0** |
|
||||
|
||||
---
|
||||
|
||||
## Office 1 — Head Office (OMNL Head Office (DBIS) – Central Bank)
|
||||
|
||||
| GL code | Account name | Balance type | Amount (USD) |
|
||||
|--------|--------------|--------------|--------------|
|
||||
| 1000 | USD Reserve Assets | **Dr** (asset) | 900,000,000,000 |
|
||||
| 1050 | USD Treasury Conversion Reserve (M0) | **Dr** (asset) | 250,000,000,000 |
|
||||
| 2000 | USD Central Deposits (M0) | **Cr** (liability) | 169,000,000,000 |
|
||||
| 2100 | USD Restricted / M1 Liabilities | **Cr** (liability) | 0 |
|
||||
| 2410 | Due To Offices (Interoffice Payable) | **Cr** (liability) | 481,000,000,000 |
|
||||
|
||||
**Office 1 totals:** Assets 1,161B; Liabilities 1,161B. After T-001C (470B) + T-001C-SUPPL (11B): 2000 = 180−11 = **169B** (M0); 2100 = 11B then Phase C offices 9–19 debits reduce 2100 to **0**; 2410 = 470+11 = **481B**. If T-Samama (Office 20) is posted: 2410 = **486B**, total assets/liabilities 1,166B.
|
||||
|
||||
---
|
||||
|
||||
## Office 2 — Shamrayan Enterprises
|
||||
|
||||
| GL code | Account name | Balance type | Amount (USD) |
|
||||
|--------|--------------|--------------|--------------|
|
||||
| 1410 | Due From Head Office | **Dr** (asset) | 5,000,000,000 |
|
||||
| 2100 | M1 (narrow money) | **Cr** (liability) | 5,000,000,000 |
|
||||
|
||||
**Office 2 totals:** Assets 5B; Liabilities 5B. **0 M0 (2000); 5B M1 (2100) only.**
|
||||
If the ledger had 2.9B in 2000 from an earlier posting, run the correction so all 5B is in 2100:
|
||||
`JOURNAL_MATRIX=docs/04-configuration/mifos-omnl-central-bank/omnl-journal-matrix-shamrayan-2000-to-2100-correction.json bash scripts/omnl/omnl-ledger-post-from-matrix.sh`
|
||||
|
||||
---
|
||||
|
||||
## Office 3 — HYBX
|
||||
|
||||
| GL code | Account name | Balance type | Amount (USD) |
|
||||
|--------|--------------|--------------|--------------|
|
||||
| 1410 | Due From Head Office | **Dr** (asset) | 350,000,000,000 |
|
||||
| 2100 | USD Restricted Liabilities (escrow) | **Cr** (liability) | 350,000,000,000 |
|
||||
|
||||
**Office 3 totals:** Assets 350B; Liabilities 350B. **Debt: 0. M1 credits only (2100):** 350B.
|
||||
|
||||
---
|
||||
|
||||
## Office 4 — TAJ Private Single Family Office
|
||||
|
||||
| GL code | Account name | Balance type | Amount (USD) |
|
||||
|--------|--------------|--------------|--------------|
|
||||
| 1410 | Due From Head Office | **Dr** (asset) | 5,000,000,000 |
|
||||
| 2100 | M1 | **Cr** (liability) | 5,000,000,000 |
|
||||
|
||||
**Office 4 totals:** Assets 5B; Liabilities 5B. **Debt: 0. M1 credits only (2100):** 5B.
|
||||
|
||||
---
|
||||
|
||||
## Office 5 — Aseret Mortgage Bank
|
||||
|
||||
| GL code | Account name | Balance type | Amount (USD) |
|
||||
|--------|--------------|--------------|--------------|
|
||||
| 1410 | Due From Head Office | **Dr** (asset) | 5,000,000,000 |
|
||||
| 2100 | M1 | **Cr** (liability) | 5,000,000,000 |
|
||||
|
||||
**Office 5 totals:** Assets 5B; Liabilities 5B. **Debt: 0. M1 credits only (2100):** 5B.
|
||||
|
||||
---
|
||||
|
||||
## Office 6 — Mann Li Family Offices
|
||||
|
||||
| GL code | Account name | Balance type | Amount (USD) |
|
||||
|--------|--------------|--------------|--------------|
|
||||
| 1410 | Due From Head Office | **Dr** (asset) | 5,000,000,000 |
|
||||
| 2100 | M1 | **Cr** (liability) | 5,000,000,000 |
|
||||
|
||||
**Office 6 totals:** Assets 5B; Liabilities 5B. **Debt: 0. M1 credits only (2100):** 5B.
|
||||
|
||||
---
|
||||
|
||||
## Office 7 — Sovereign Order of Malta OSJ
|
||||
|
||||
| GL code | Account name | Balance type | Amount (USD) |
|
||||
|--------|--------------|--------------|--------------|
|
||||
| 1410 | Due From Head Office | **Dr** (asset) | 50,000,000,000 |
|
||||
| 2100 | M1 | **Cr** (liability) | 50,000,000,000 |
|
||||
|
||||
**Office 7 totals:** Assets 50B; Liabilities 50B. **Debt: 0. M1 credits only (2100):** 50B.
|
||||
|
||||
---
|
||||
|
||||
## Office 8 — Alltra Mainnet
|
||||
|
||||
| GL code | Account name | Balance type | Amount (USD) |
|
||||
|--------|--------------|--------------|--------------|
|
||||
| 1410 | Due From Head Office | **Dr** (asset) | 50,000,000,000 |
|
||||
| 2100 | M1 | **Cr** (liability) | 50,000,000,000 |
|
||||
|
||||
**Office 8 totals:** Assets 50B; Liabilities 50B. **Debt: 0. M1 credits only (2100):** 50B.
|
||||
|
||||
---
|
||||
|
||||
## Office 20 — Samama Group LLC - Azerbaijan
|
||||
|
||||
| GL code | Account name | Balance type | Amount (USD) |
|
||||
|--------|--------------|--------------|--------------|
|
||||
| 1410 | Due From Head Office | **Dr** (asset) | 5,000,000,000 |
|
||||
| 2100 | M1 | **Cr** (liability) | 5,000,000,000 |
|
||||
|
||||
**Office 20 totals:** Assets 5B; Liabilities 5B. **Debt: 0. M1 credits only (2100):** 5B. Create office and post via `bash scripts/omnl/omnl-office-create-samama.sh`. See [SAMAMA_OFFICE_AND_5B_M1_TRANSFER.md](SAMAMA_OFFICE_AND_5B_M1_TRANSFER.md).
|
||||
|
||||
---
|
||||
|
||||
## Offices 9–19 (1B M1 each)
|
||||
|
||||
Phase C offices 9–19 was posted live: each of offices 9–19 received **1,000,000,000** M1 from Head Office (HO leg Dr 2100 Cr 2410; office leg Dr 1410 Cr 2100). Matrix: [omnl-journal-matrix-phase-c-offices-9-19.json](omnl-journal-matrix-phase-c-offices-9-19.json). A supplement of 11B M0→M1 at HO was posted first: [omnl-journal-matrix-m0-m1-supplement-11b.json](omnl-journal-matrix-m0-m1-supplement-11b.json). **Debt: 0. M1 credits only (2100):** 1B each.
|
||||
|
||||
---
|
||||
|
||||
## Interoffice check
|
||||
|
||||
- **2410 (Head Office)** = 486B Cr = Due To Offices (470B offices 2–8 + 11B offices 9–19 + 5B Office 20 Samama).
|
||||
- **Sum of 1410 (offices 2–20)** = 486B Dr = Due From Head Office.
|
||||
- **Sum of 2100 (M1) at offices 2–20** = 486B Cr. HO 2100 (M1) debited 486B in Phase C + Samama; offices credit 2100 only (M1).
|
||||
|
||||
---
|
||||
|
||||
## References
|
||||
|
||||
- [OMNL_POSTING_AND_RECONCILIATION_EVIDENCE.md](OMNL_POSTING_AND_RECONCILIATION_EVIDENCE.md) — Posting log and reconciliation
|
||||
- [OMNL_PHASE_C_INTEROFFICE_DUE_TO_DUE_FROM.md](OMNL_PHASE_C_INTEROFFICE_DUE_TO_DUE_FROM.md) — Phase C two-leg design
|
||||
- [OMNL_ENTITY_MASTER_DATA.json](OMNL_ENTITY_MASTER_DATA.json) — Office/entity names
|
||||
@@ -0,0 +1,134 @@
|
||||
# OMNL Office Logins and Credentials
|
||||
|
||||
**Purpose:** Document how office-specific logins work in Fineract and provide generated credentials for the **Shamrayan** office (admin access limited to that office only).
|
||||
|
||||
---
|
||||
|
||||
## Data isolation requirement (OMNL-2)
|
||||
|
||||
**Nothing more than the data for office OMNL-2 may be exposed** to the office-2 user. No other office’s clients, accounts, journal entries, or reports must be visible or accessible via this login (UI or API).
|
||||
|
||||
Enforcement:
|
||||
|
||||
- **Staff** is created with `officeId: 2` only; the user is tied to that staff.
|
||||
- **User** is created with the same `officeId: 2` and a **role that is office-scoped** (e.g. “Office Admin” or “Branch manager”), **not** “Super user” or any role that grants “all offices” access.
|
||||
- Fineract restricts data by the staff’s office: APIs and UI only return data for offices the user is allowed to see (here, office 2 only).
|
||||
|
||||
Before going live, verify that the chosen role does **not** have “all offices” permission and that logging in as the office-2 user shows only Office 2 (Shamrayan) data.
|
||||
|
||||
---
|
||||
|
||||
## Do office-2 users have access to the databases?
|
||||
|
||||
**No.** The OMNL-2 (office 2) user has **only** Fineract/Mifos **API and web UI** access. They do **not** have:
|
||||
|
||||
- Direct database access (no MySQL/MariaDB/PostgreSQL connection, credentials, or client)
|
||||
- Shell or SSH access to the application or database servers
|
||||
- Access to the Fineract backend’s DB connection strings or `.env` files
|
||||
|
||||
The Fineract application connects to its database using a **service account** on the server. Office-2 users interact only with the application over HTTP; the application enforces office scoping and returns only office-2 data. So they cannot query the database directly or see other offices’ data at the DB layer—only what the API/UI returns, which is restricted to office 2.
|
||||
|
||||
If you separately grant the same person **SSH** or **database credentials** to a host or DB, that is a separate permission and should be locked down (e.g. read-only, or no access to Fineract’s DB or other tenants).
|
||||
|
||||
---
|
||||
|
||||
## Do offices have their own logins (user/password)?
|
||||
|
||||
**Yes.** In Apache Fineract, each office can have its own logins by creating:
|
||||
|
||||
1. **Staff** — A staff record is tied to a single **office** (`officeId`). Staff defines who can act in the system and to which office they belong.
|
||||
2. **User** — A user (login) is linked to a **staff** member and has **roles** (permissions). Because staff is office-scoped, the user effectively has access only to that office’s data when using a role that is not “all offices” (e.g. Branch manager–style role).
|
||||
|
||||
So: **one Staff per office** (e.g. “Shamrayan Office Admin”) + **one User** linked to that staff, with a role that has full admin permissions but is restricted by the staff’s office. The result is a **user/password login that has full admin access only to that office and no other**.
|
||||
|
||||
- **API:** `POST /v1/staff` (body: `officeId`, `firstname`, `lastname`, `joiningDate`, …)
|
||||
- **API:** `POST /v1/users` (body: `username`, `password`, `staffId`, `roles[]`, …)
|
||||
- **API:** `GET /v1/roles` to choose the right role (e.g. “Branch manager” or custom full-permission role scoped by office).
|
||||
|
||||
Credentials and the script to create the Shamrayan office login are below.
|
||||
|
||||
---
|
||||
|
||||
## Shamrayan office (Office ID 2)
|
||||
|
||||
- **Office name:** Shamrayan Enterprises
|
||||
- **Office id:** `2`
|
||||
- **Entity:** From [OMNL_ENTITY_MASTER_DATA.json](OMNL_ENTITY_MASTER_DATA.json) (clientNumber 2).
|
||||
|
||||
---
|
||||
|
||||
## Generated credentials: Shamrayan office admin
|
||||
|
||||
**For:** Full admin access to **Shamrayan Enterprises (office 2) only** — no access to other offices.
|
||||
|
||||
| Item | Value |
|
||||
|------|--------|
|
||||
| **Username** | `shamrayan.admin` |
|
||||
| **Password** | *(see below; store in secrets manager or secure vault)* |
|
||||
| **Scope** | Office 2 (Shamrayan Enterprises) only |
|
||||
| **Intended role** | Full admin within that office (create/edit clients, accounts, reports, etc. for office 2 only) |
|
||||
|
||||
**Generated password (one-time):**
|
||||
|
||||
```
|
||||
Sh@mr4y4n-0ff1c3-2026!
|
||||
```
|
||||
|
||||
**Security notes:**
|
||||
|
||||
- Change this password on first login if the instance supports it.
|
||||
- Do not commit this password to the repo. Store it in `omnl-fineract/.env` (e.g. `OMNL_SHAMRAYAN_ADMIN_PASSWORD`) only if needed for automation, or in a secrets manager.
|
||||
- This document can live in a private or restricted area; the script that creates the user can read the password from env (e.g. `OMNL_SHAMRAYAN_ADMIN_PASSWORD`).
|
||||
|
||||
---
|
||||
|
||||
## Creating the Shamrayan office login
|
||||
|
||||
Use the script from repo root (with `omnl-fineract/.env` loaded):
|
||||
|
||||
```bash
|
||||
# Required: set password via env (script has no default)
|
||||
export OMNL_SHAMRAYAN_ADMIN_PASSWORD='Sh@mr4y4n-0ff1c3-2026!'
|
||||
|
||||
# Create staff for office 2 and user with office-scoped admin
|
||||
bash scripts/omnl/omnl-user-shamrayan-office-create.sh
|
||||
```
|
||||
|
||||
The script:
|
||||
|
||||
1. Creates **Staff** for office 2 (firstname/lastname e.g. “Shamrayan Office Admin”).
|
||||
2. Fetches **roles** and selects an **office-scoped** role (e.g. “Office Admin” or “Branch manager”), explicitly excluding “Super user” and “System” so that only OMNL-2 data can be exposed.
|
||||
3. Creates **User** with username `shamrayan.admin`, the chosen password, linked to that staff and role.
|
||||
|
||||
Result: one login (`shamrayan.admin` / password) with full admin access **only to office 2** (Shamrayan Enterprises); no other office data is exposed.
|
||||
|
||||
---
|
||||
|
||||
## Verification: only OMNL-2 data exposed
|
||||
|
||||
After creating the office-2 user, confirm that no other office’s data is visible:
|
||||
|
||||
1. **Log in** to [omnl.hybxfinance.io](https://omnl.hybxfinance.io/) as `shamrayan.admin` (or the office-2 username).
|
||||
2. **Offices:** Organization → Offices. Only **Shamrayan Enterprises (office 2)** (and possibly the parent Head Office for hierarchy) should be visible or selectable; no other branch offices.
|
||||
3. **Clients / accounts / reports:** Only clients and data under office 2 should be listed; no clients or journal entries for other offices.
|
||||
4. **API:** Using the office-2 user’s Basic auth, `GET /offices` (or equivalent) should return only offices the user is allowed to see (e.g. office 2 and its parent), not the full list. Same for clients, journal entries, and reports scoped by office.
|
||||
|
||||
If any other office’s data is visible, the role has “all offices” or similar; change the user’s role to an office-scoped one (e.g. “Office Admin”) and re-test.
|
||||
|
||||
---
|
||||
|
||||
## Security test (collateral attacks)
|
||||
|
||||
To ensure the office-2 user **cannot** access other offices’ data, run shell commands (e.g. `cat`), or read arbitrary files (path traversal), run the security test script and runbook:
|
||||
|
||||
- **Script:** `bash scripts/omnl/omnl-office2-access-security-test.sh` (set office-2 user and password via env).
|
||||
- **Runbook:** [OMNL_OFFICE_2_ACCESS_SECURITY_TEST.md](OMNL_OFFICE_2_ACCESS_SECURITY_TEST.md) — data isolation, path traversal, command injection, SSRF, and SSH lock-down.
|
||||
|
||||
---
|
||||
|
||||
## References
|
||||
|
||||
- [OMNL_ENTITY_MASTER_DATA.json](OMNL_ENTITY_MASTER_DATA.json) — Entity list (Shamrayan = clientNumber 2)
|
||||
- [OMNL_OFFICES_POPULATE.md](OMNL_OFFICES_POPULATE.md) — How offices 1–17 are created
|
||||
- [OMNL_OFFICE_2_ACCESS_SECURITY_TEST.md](OMNL_OFFICE_2_ACCESS_SECURITY_TEST.md) — Security test for OMNL-2 access (no collateral attacks)
|
||||
- Fineract API: `GET/POST /v1/staff`, `GET/POST /v1/users`, `GET /v1/roles` — [Swagger](https://omnl.hybxfinance.io/fineract-provider/swagger-ui/index.html)
|
||||
@@ -0,0 +1,69 @@
|
||||
# OMNL Office Master Runbook Index
|
||||
|
||||
**Purpose:** Every office has **one Master Runbook** (single entry point) and optionally **sub-runbooks** (funding, P2P settlement, audit, DR, artifact upload). This index maps officeId to Master Runbook and sub-runbooks.
|
||||
|
||||
Use with [OMNL_OFFICE_ADDRESS_BOOK.md](OMNL_OFFICE_ADDRESS_BOOK.md) for API Banking Rail instructions and secrets references.
|
||||
|
||||
---
|
||||
|
||||
## Convention
|
||||
|
||||
- **Master Runbook:** Primary doc for that office (create/funding, tranche execution, or how we operate this office).
|
||||
- **Sub-runbooks:** Linked from the master or address book; cover specific flows (P2P, audit, DR, upload).
|
||||
|
||||
---
|
||||
|
||||
## Office 1 — Head Office
|
||||
|
||||
| Type | Document | Purpose |
|
||||
|------|----------|---------|
|
||||
| **Master** | [OPERATING_RAILS.md](OPERATING_RAILS.md) | Global controls, closures, idempotency, resolve_ids, audit, maker-checker, monitoring |
|
||||
| **Sub** | [LEDGER_ALLOCATION_POSTING_RUNBOOK.md](LEDGER_ALLOCATION_POSTING_RUNBOOK.md) | Pre-posting checklist, journal entry table, reconciliation |
|
||||
|
||||
---
|
||||
|
||||
## Office 2 — Shamrayan Enterprises
|
||||
|
||||
| Type | Document | Purpose |
|
||||
|------|----------|---------|
|
||||
| **Master** | [OFFICE_2_SHAMRAYAN_RUNBOOK.md](OFFICE_2_SHAMRAYAN_RUNBOOK.md) | Confirm office, Rail B funding, audit, closure, packaging, upload |
|
||||
| **Sub** | [OFFICE_2_READINESS_CONFIRMATION.md](OFFICE_2_READINESS_CONFIRMATION.md) | 5B M1, accounting, audit, compliance, P2P readiness |
|
||||
| **Sub** | P2P (when defined) | P2P settlement (adapt from [P2P_SETTLEMENT_CRUNCHYGALAXY_RAIL.md](P2P_SETTLEMENT_CRUNCHYGALAXY_RAIL.md)) |
|
||||
|
||||
---
|
||||
|
||||
## Office 20 — Samama Group LLC (Azerbaijan)
|
||||
|
||||
| Type | Document | Purpose |
|
||||
|------|----------|---------|
|
||||
| **Master** | [SAMAMA_OFFICE_AND_5B_M1_TRANSFER.md](SAMAMA_OFFICE_AND_5B_M1_TRANSFER.md) | Create office, 5B M1 transfer |
|
||||
| **Master (tranche)** | [TRANCHE_1_500M_RUNBOOK.md](TRANCHE_1_500M_RUNBOOK.md) | Tranche execution (Rail A/B), audit, zip, upload, confirmation |
|
||||
| **Sub** | [OFFICE_20_AUDIT_PACKET.md](OFFICE_20_AUDIT_PACKET.md) | Audit packet layout, dynamic OFFICE_ID |
|
||||
| **Sub** | [OFFICE_20_DR_RUNBOOK.md](OFFICE_20_DR_RUNBOOK.md) | Disaster recovery, reversal |
|
||||
| **Sub** | [OFFICE_20_FIRE_DRILL_RUNBOOK.md](OFFICE_20_FIRE_DRILL_RUNBOOK.md) | Fire drill: maker, checker, alert, audit, reverse |
|
||||
|
||||
---
|
||||
|
||||
## Office 21 — Crunchygalaxy Unip. Lda. (Portugal)
|
||||
|
||||
| Type | Document | Purpose |
|
||||
|------|----------|---------|
|
||||
| **Master** | [CRUNCHYGALAXY_OFFICE_AND_1B_FUNDING.md](CRUNCHYGALAXY_OFFICE_AND_1B_FUNDING.md) | Create office, 1.0B M1 (Rail B), audit, closure, packaging, upload |
|
||||
| **Sub** | [P2P_SETTLEMENT_CRUNCHYGALAXY_RAIL.md](P2P_SETTLEMENT_CRUNCHYGALAXY_RAIL.md) | P2P Banking Rail: request/response, SETTLED, mirror entry, close package |
|
||||
|
||||
---
|
||||
|
||||
## Other offices (3–19)
|
||||
|
||||
When an office gets a dedicated runbook set: add a row to the Address Book (entity, Banking Rail API, secrets reference) and add a section here with Master and Sub runbooks.
|
||||
|
||||
---
|
||||
|
||||
## Quick reference
|
||||
|
||||
| officeId | Master Runbook | Key sub-runbooks |
|
||||
|----------|----------------|------------------|
|
||||
| 1 | OPERATING_RAILS | Ledger Allocation |
|
||||
| 2 | OFFICE_2_SHAMRAYAN_RUNBOOK | Readiness; P2P (when defined) |
|
||||
| 20 | SAMAMA_OFFICE + TRANCHE_1_500M | Audit, DR, Fire Drill |
|
||||
| 21 | CRUNCHYGALAXY_OFFICE_AND_1B_FUNDING | P2P Settlement |
|
||||
@@ -0,0 +1,175 @@
|
||||
# OMNL Phase C — Interoffice Due-To / Due-From (Strict Double-Entry)
|
||||
|
||||
**GL classification:** **2000 = M0** (monetary base / central deposits). **2100 = M1** (narrow money / demand deposits). Offices 2–17 receive **only 2100 (M1)**; M1 is debited from OMNL (Head Office) **2100** after **2000 (M0)** is converted to **2100 (M1)** at HO (entry T-001C).
|
||||
|
||||
**Purpose:** Phase C (office distributions) as **two-leg interoffice transfers**. Each distribution is:
|
||||
|
||||
1. **Head Office leg:** Debit **2100 (M1)** at HO, credit 2410 (Due To Office).
|
||||
2. **Office leg:** Debit 1410 (Due From HO), credit **2100 (M1)** at the receiving office — **only 2100**, never 2000.
|
||||
|
||||
**Policy for offices 2–19:** **Zero Debt** and **Only M1 Credits (2100).** Offices 2–19 have no debt; the only credit balances are **2100 (M1)**. Offices 9–19 have zero balances unless allocated. See [OMNL_OFFICE_BALANCES.md](OMNL_OFFICE_BALANCES.md).
|
||||
|
||||
**Reference:** [MIGRATION_AND_LEDGER_ALLOCATION_MEMORANDUM.md](MIGRATION_AND_LEDGER_ALLOCATION_MEMORANDUM.md) · [OMNL_TRANSACTION_SEQUENCE_FULL.md](OMNL_TRANSACTION_SEQUENCE_FULL.md)
|
||||
|
||||
---
|
||||
|
||||
## Interoffice GL accounts (required)
|
||||
|
||||
Create these if not already present (e.g. via `bash scripts/omnl/omnl-gl-accounts-create.sh`):
|
||||
|
||||
| glCode | Name | Type | Description |
|
||||
|--------|------|------|-------------|
|
||||
| **1410** | Due From Head Office (Interoffice Receivable) | 1 ASSET | Interoffice receivable at branch |
|
||||
| **2410** | Due To Offices (Interoffice Payable) | 2 LIABILITY | Interoffice payable at Head Office |
|
||||
|
||||
Optional: if your CoA uses office-specific subaccounts, you can add 2410.02 (Shamrayan), 2410.03 (HYBX), etc. The logic below is unchanged.
|
||||
|
||||
---
|
||||
|
||||
## Phase C — Corrected office postings (post in order)
|
||||
|
||||
Each memo is two journal entries: **-HO** at Head Office (officeId=1), **-OF** at the receiving office (officeId=2..8).
|
||||
|
||||
### T-002A — Shamrayan (available) — 2,900,000,000
|
||||
|
||||
| Leg | Office | Debit | Credit | Amount (USD) |
|
||||
|-----|--------|-------|--------|--------------|
|
||||
| **T-002A-HO** | Head Office (1) | **2100 (M1)** | 2410 | 2,900,000,000 |
|
||||
| **T-002A-OF** | Office 2 (Shamrayan) | 1410 | **2100 (M1)** | 2,900,000,000 |
|
||||
|
||||
Effect: HO 2100 (M1) decreases; Shamrayan 2100 (M1) increases; interoffice balances match.
|
||||
|
||||
---
|
||||
|
||||
### T-002B — Shamrayan (restricted) — 2,100,000,000
|
||||
|
||||
| Leg | Office | Debit | Credit | Amount (USD) |
|
||||
|-----|--------|-------|--------|--------------|
|
||||
| **T-002B-HO** | Head Office (1) | **2100 (M1)** | 2410 | 2,100,000,000 |
|
||||
| **T-002B-OF** | Office 2 (Shamrayan) | 1410 | **2100 (M1)** | 2,100,000,000 |
|
||||
|
||||
---
|
||||
|
||||
### T-003 — HYBX (restricted escrow) — 350,000,000,000
|
||||
|
||||
| Leg | Office | Debit | Credit | Amount (USD) |
|
||||
|-----|--------|-------|--------|--------------|
|
||||
| **T-003-HO** | Head Office (1) | **2100 (M1)** | 2410 | 350,000,000,000 |
|
||||
| **T-003-OF** | Office 3 (HYBX) | 1410 | **2100 (M1)** | 350,000,000,000 |
|
||||
|
||||
---
|
||||
|
||||
### T-004 — TAJ — 5,000,000,000
|
||||
|
||||
| Leg | Office | Debit | Credit | Amount (USD) |
|
||||
|-----|--------|-------|--------|--------------|
|
||||
| **T-004-HO** | Head Office (1) | **2100 (M1)** | 2410 | 5,000,000,000 |
|
||||
| **T-004-OF** | Office 4 (TAJ) | 1410 | **2100 (M1)** | 5,000,000,000 |
|
||||
|
||||
---
|
||||
|
||||
### T-005 — Aseret — 5,000,000,000
|
||||
|
||||
| Leg | Office | Debit | Credit | Amount (USD) |
|
||||
|-----|--------|-------|--------|--------------|
|
||||
| **T-005-HO** | Head Office (1) | **2100 (M1)** | 2410 | 5,000,000,000 |
|
||||
| **T-005-OF** | Office 5 (Aseret) | 1410 | **2100 (M1)** | 5,000,000,000 |
|
||||
|
||||
---
|
||||
|
||||
### T-006 — Mann Li — 5,000,000,000
|
||||
|
||||
| Leg | Office | Debit | Credit | Amount (USD) |
|
||||
|-----|--------|-------|--------|--------------|
|
||||
| **T-006-HO** | Head Office (1) | **2100 (M1)** | 2410 | 5,000,000,000 |
|
||||
| **T-006-OF** | Office 6 (Mann Li) | 1410 | **2100 (M1)** | 5,000,000,000 |
|
||||
|
||||
---
|
||||
|
||||
### T-007 — OSJ — 50,000,000,000
|
||||
|
||||
| Leg | Office | Debit | Credit | Amount (USD) |
|
||||
|-----|--------|-------|--------|--------------|
|
||||
| **T-007-HO** | Head Office (1) | **2100 (M1)** | 2410 | 50,000,000,000 |
|
||||
| **T-007-OF** | Office 7 (OSJ) | 1410 | **2100 (M1)** | 50,000,000,000 |
|
||||
|
||||
---
|
||||
|
||||
### T-008 — Alltra — 50,000,000,000
|
||||
|
||||
| Leg | Office | Debit | Credit | Amount (USD) |
|
||||
|-----|--------|-------|--------|--------------|
|
||||
| **T-008-HO** | Head Office (1) | **2100 (M1)** | 2410 | 50,000,000,000 |
|
||||
| **T-008-OF** | Office 8 (Alltra) | 1410 | **2100 (M1)** | 50,000,000,000 |
|
||||
|
||||
---
|
||||
|
||||
### T-Samama — Samama Group LLC (Azerbaijan) — 5,000,000,000
|
||||
|
||||
| Leg | Office | Debit | Credit | Amount (USD) |
|
||||
|-----|--------|-------|--------|---------------|
|
||||
| **T-Samama-HO** | Head Office (1) | **2100 (M1)** | 2410 | 5,000,000,000 |
|
||||
| **T-Samama-OF** | Samama (new office) | 1410 | **2100 (M1)** | 5,000,000,000 |
|
||||
|
||||
Create the office first (e.g. `scripts/omnl/omnl-office-create-samama.sh`); then post the two legs, or use the same script to create office and post in one go. See [SAMAMA_OFFICE_AND_5B_M1_TRANSFER.md](SAMAMA_OFFICE_AND_5B_M1_TRANSFER.md) and [omnl-journal-matrix-samama-5b.json](omnl-journal-matrix-samama-5b.json).
|
||||
|
||||
---
|
||||
|
||||
### T-009 to T-019 — Offices 9–19 (1B M1 each)
|
||||
|
||||
Each of offices 9–19 receives **1,000,000,000** M1 from Head Office. Post **after** an M0→M1 supplement of 11B at HO ([omnl-journal-matrix-m0-m1-supplement-11b.json](omnl-journal-matrix-m0-m1-supplement-11b.json)). Matrix: [omnl-journal-matrix-phase-c-offices-9-19.json](omnl-journal-matrix-phase-c-offices-9-19.json) (22 entries). Offices 18–19 must exist; if created after the main run, post the office legs with [omnl-journal-matrix-phase-c-offices-18-19-of-only.json](omnl-journal-matrix-phase-c-offices-18-19-of-only.json).
|
||||
|
||||
| Memo | Office | Amount (USD) |
|
||||
|------|--------|---------------|
|
||||
| T-009 | FIDIS (9) | 1,000,000,000 |
|
||||
| T-010 | Alpha Omega Holdings (10) | 1,000,000,000 |
|
||||
| T-011 | SGI Capital (11) | 1,000,000,000 |
|
||||
| T-012 | Titan Financial (12) | 1,000,000,000 |
|
||||
| T-013 | Roy Walker PLLC (13) | 1,000,000,000 |
|
||||
| T-014 | SGI Partners LLC (14) | 1,000,000,000 |
|
||||
| T-015 | Tsunami Holdings AG (15) | 1,000,000,000 |
|
||||
| T-016 | Anakatech (16) | 1,000,000,000 |
|
||||
| T-017 | Anema Camden Walker Global (17) | 1,000,000,000 |
|
||||
| T-018 | NEPAL RASTRA BANK (18) | 1,000,000,000 |
|
||||
| T-019 | SANIMA BANK LIMITED (19) | 1,000,000,000 |
|
||||
|
||||
---
|
||||
|
||||
## Why this closes to the dollar
|
||||
|
||||
- Every memo debits **2100 (M1)** at HO and credits 2410; at the office, Dr 1410 and Cr **2100 (M1)**. Offices receive only 2100 (M1). M0 (2000) is converted to M1 (2100) at HO by T-001C (Dr 2000 Cr 2100, 470B) before Phase C.
|
||||
- No “Dr 2000 / Cr 2000” same-office self-canceling entries.
|
||||
|
||||
Interoffice balances (1410 at offices, 2410 at HO) represent internal settlement rails; they net in consolidation if you run an elimination step (optional, often not in operational ledgers).
|
||||
|
||||
---
|
||||
|
||||
## Posting
|
||||
|
||||
**Phase A + B + conversion:** Post T-001, T-001B, and **T-001C** (M0→M1 at HO: Dr 2000 Cr 2100, 470B) using [omnl-journal-matrix-phase-a-b-only.json](omnl-journal-matrix-phase-a-b-only.json) (now includes T-001C).
|
||||
|
||||
**Phase C (offices 2–8):** Post the 16 entries using [omnl-journal-matrix-phase-c-interoffice.json](omnl-journal-matrix-phase-c-interoffice.json).
|
||||
|
||||
**Phase C (offices 9–19, 1B M1 each):** Post M0→M1 supplement (11B at HO), then office transfers:
|
||||
|
||||
```bash
|
||||
# 1. Supplement: 11B M0→M1 at HO (Dr 2000 Cr 2100)
|
||||
JOURNAL_MATRIX=docs/04-configuration/mifos-omnl-central-bank/omnl-journal-matrix-m0-m1-supplement-11b.json \
|
||||
bash scripts/omnl/omnl-ledger-post-from-matrix.sh
|
||||
|
||||
# 2. Offices 9–19: 1B each (22 entries; ensure offices 18–19 exist)
|
||||
JOURNAL_MATRIX=docs/04-configuration/mifos-omnl-central-bank/omnl-journal-matrix-phase-c-offices-9-19.json \
|
||||
bash scripts/omnl/omnl-ledger-post-from-matrix.sh
|
||||
```
|
||||
|
||||
Use `DRY_RUN=1` to preview. Same `TRANSACTION_DATE` as Phase A/B for migration date.
|
||||
|
||||
---
|
||||
|
||||
## References
|
||||
|
||||
- [omnl-journal-matrix-phase-c-interoffice.json](omnl-journal-matrix-phase-c-interoffice.json) — Phase C offices 2–8 (16 entries)
|
||||
- [omnl-journal-matrix-m0-m1-supplement-11b.json](omnl-journal-matrix-m0-m1-supplement-11b.json) — 11B M0→M1 at HO for offices 9–19
|
||||
- [omnl-journal-matrix-phase-c-offices-9-19.json](omnl-journal-matrix-phase-c-offices-9-19.json) — Phase C offices 9–19 (22 entries, 1B M1 each)
|
||||
- [OMNL_TRANSACTION_SEQUENCE_FULL.md](OMNL_TRANSACTION_SEQUENCE_FULL.md) — Full sequence (Phase A/B + Phase C options)
|
||||
- [LEDGER_ALLOCATION_POSTING_RUNBOOK.md](LEDGER_ALLOCATION_POSTING_RUNBOOK.md) — Pre-post checklist and reconciliation
|
||||
@@ -0,0 +1,65 @@
|
||||
# OMNL — Posting and Reconciliation Evidence
|
||||
|
||||
**Purpose:** Record completion of Phase A+B and Phase C interoffice posting and reconciliation checklist. **Transaction date used:** 2026-02-23.
|
||||
|
||||
---
|
||||
|
||||
## 1. Posting completed
|
||||
|
||||
| Phase | Matrix | Entries | Status |
|
||||
|-------|--------|---------|--------|
|
||||
| **A+B** | omnl-journal-matrix-phase-a-b-only.json | T-001, T-001B (2) | ✅ Posted |
|
||||
| **C (interoffice)** | omnl-journal-matrix-phase-c-interoffice.json | T-002A-HO/OF through T-008-HO/OF (16) | ✅ Posted |
|
||||
|
||||
**Commands run (from repo root):**
|
||||
|
||||
```bash
|
||||
JOURNAL_MATRIX=docs/04-configuration/mifos-omnl-central-bank/omnl-journal-matrix-phase-a-b-only.json \
|
||||
bash scripts/omnl/omnl-ledger-post-from-matrix.sh
|
||||
|
||||
JOURNAL_MATRIX=docs/04-configuration/mifos-omnl-central-bank/omnl-journal-matrix-phase-c-interoffice.json \
|
||||
bash scripts/omnl/omnl-ledger-post-from-matrix.sh
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. Post-posting reconciliation (runbook checklist)
|
||||
|
||||
| # | Check | Expected (Phase A+B + Phase C interoffice) | Done |
|
||||
|---|--------|---------------------------------------------|------|
|
||||
| 1 | Trial balance / GL report | Assets: **1000** = 900B, **1050** = 250B; **1410** (offices 2–8) = 470B total | ☐ Verify in UI |
|
||||
| 2 | Liability **2000** (Head Office) | 900 − 250 − 470 = **180B** | ☐ Verify in UI |
|
||||
| 3 | Liability **2410** (Head Office) | **470B** (Due To Offices) | ☐ Verify in UI |
|
||||
| 4 | **1410** (offices 2–8) vs **2410** (HO) | Interoffice nets: sum(1410) = 2410 = 470B | ☐ Verify in UI |
|
||||
| 5 | **2000** (offices 2–8) + **2100** (offices 2, 3) | 117.9B available + 352.1B restricted = 470B | ☐ Verify in UI |
|
||||
| 6 | M0 / M1 consistency | 650B M0 unconverted; 1,250B M1 capacity; 470B distributed; 780B M1 at HO | ☐ Verify in UI |
|
||||
|
||||
*Note:* Fineract `GET /glaccounts` did not return `organizationRunningBalance` in this run. Verify trial balance and GL balances in the Mifos/Fineract UI (Reports → Trial balance or equivalent).
|
||||
|
||||
---
|
||||
|
||||
## 3. Sign-off and audit
|
||||
|
||||
| # | Action | Done |
|
||||
|---|--------|------|
|
||||
| 1 | Attach this runbook, [LEDGER_ALLOCATION_GL_MAPPING.md](LEDGER_ALLOCATION_GL_MAPPING.md), [OMNL_JOURNAL_LEDGER_MATRIX.md](OMNL_JOURNAL_LEDGER_MATRIX.md), and [OMNL_PHASE_C_INTEROFFICE_DUE_TO_DUE_FROM.md](OMNL_PHASE_C_INTEROFFICE_DUE_TO_DUE_FROM.md) to audit trail | ☐ |
|
||||
| 2 | Retain immutable copy of [MIGRATION_AND_LEDGER_ALLOCATION_MEMORANDUM.md](MIGRATION_AND_LEDGER_ALLOCATION_MEMORANDUM.md) and December-2023 source | ☐ |
|
||||
| 3 | If maker-checker enabled, ensure conversion (T-001B) and restricted releases have separate approvals | ☐ |
|
||||
|
||||
---
|
||||
|
||||
## 4. Quick reference — Expected balances (Option A + Phase C interoffice)
|
||||
|
||||
| GL | Role | Expected (USD) |
|
||||
|----|------|-----------------|
|
||||
| 1000 | Assets | 900B |
|
||||
| 1050 | Assets | 250B |
|
||||
| 1410 | Assets (offices 2–8) | 470B total (Due From HO) |
|
||||
| 2000 | Liabilities (HO) | 180B |
|
||||
| 2000 | Liabilities (offices 2–8) | 117.9B (available M1) |
|
||||
| 2100 | Liabilities (offices 2, 3) | 352.1B (restricted) |
|
||||
| 2410 | Liabilities (HO) | 470B (Due To Offices) |
|
||||
|
||||
---
|
||||
|
||||
**See also:** [LEDGER_ALLOCATION_POSTING_RUNBOOK.md](LEDGER_ALLOCATION_POSTING_RUNBOOK.md) · [OMNL_TRANSACTION_SEQUENCE_FULL.md](OMNL_TRANSACTION_SEQUENCE_FULL.md)
|
||||
@@ -0,0 +1,30 @@
|
||||
# OMNL Product Namespace — Office 20 (Samama)
|
||||
|
||||
**Purpose:** Naming and accounting conventions for products tied to Office 20, before committing to Path B or C.
|
||||
|
||||
---
|
||||
|
||||
## Naming convention
|
||||
|
||||
- **Savings (Path B):** e.g. `M1 Wallet (USD) - Samama`, shortName `M1USD-SAM`. Prefix or suffix with `-Samama` or `SAM` for Office 20.
|
||||
- **Loans (Path C):** e.g. `Samama M1 Funding Loan (USD)`, shortName `SAM-M1L`.
|
||||
|
||||
---
|
||||
|
||||
## Accounting mapping (when products exist)
|
||||
|
||||
- **Client liabilities (Path B):** Prefer a dedicated sub-ledger GL (e.g. 2101 or 2100.20) for Office 20 client balances so they do not mix with HO/other offices in 2100. If using shared 2100, track by officeId and client in reporting.
|
||||
- **Loan portfolio (Path C):** Map to a portfolio asset GL; interest income and fees to income GLs; provisions if applicable. Document in loan product accounting rule.
|
||||
|
||||
---
|
||||
|
||||
## Readiness detection
|
||||
|
||||
**omnl-operator-rail.sh** prints savings product count and loan product count. Path B is “ready” when savings products exist and accounting is enabled (and payment type resolved). Path C is “ready” when loan products exist and accounting rule is enabled.
|
||||
|
||||
---
|
||||
|
||||
## References
|
||||
|
||||
- [OPERATING_RAILS.md](OPERATING_RAILS.md) — A/B/C templates and rail
|
||||
- [SAMAMA_OFFICE_AND_5B_M1_TRANSFER.md](SAMAMA_OFFICE_AND_5B_M1_TRANSFER.md) — Office 20 setup
|
||||
@@ -0,0 +1,124 @@
|
||||
# OMNL — Full Transaction Sequence (Head Office → M1 to Offices)
|
||||
|
||||
**Purpose:** Single reference for the **exact order** of all migration and allocation transactions: (1) Head Office setup, (2) Head Office conversion, (3) M1 from Head Office to each office at the specified amounts. Post in this order.
|
||||
|
||||
**Source:** [MIGRATION_AND_LEDGER_ALLOCATION_MEMORANDUM.md](MIGRATION_AND_LEDGER_ALLOCATION_MEMORANDUM.md) (Option A) · [omnl-journal-matrix.json](omnl-journal-matrix.json)
|
||||
|
||||
---
|
||||
|
||||
## Summary
|
||||
|
||||
| Phase | Transactions | Description |
|
||||
|-------|---------------|-------------|
|
||||
| **A** | T-001 | Head Office: opening balance (900B M0 onto ledger) |
|
||||
| **B** | T-001B | Head Office: treasury conversion (250B M0 → reserve; creates 1,250B M1 capacity) |
|
||||
| **B+** | T-001C | Head Office: M0→M1 conversion (Dr 2000 Cr 2100, 470B) before distribution |
|
||||
| **C** | T-002A → T-008 | M1 from Head Office 2100 to offices 2–8 (only 2100 M1 at offices; HO debits 2100, offices credit 2100) |
|
||||
|
||||
**Outcome:** After T-001C: 180B M0 (2000) at HO; 470B M1 (2100) at HO then distributed to offices 2–8. Offices 2–8 hold **only 2100 (M1)**; 780B M1 remaining at Head Office after Phase C.
|
||||
|
||||
---
|
||||
|
||||
## Full sequence (post in this order)
|
||||
|
||||
### Phase A — Head Office: Opening balance
|
||||
|
||||
| # | Memo | Debit GL | Credit GL | Amount (USD) | Narrative |
|
||||
|---|------|----------|-----------|--------------|-----------|
|
||||
| 1 | **T-001** | 1000 (Settlement reserves) | 2000 (Central deposits) | **900,000,000,000** | Opening Balance Migration (Head Office) |
|
||||
|
||||
**Effect:** Books 900B M0 at Head Office (Client/Office 1) as settlement reserves and central deposits.
|
||||
|
||||
---
|
||||
|
||||
### Phase B — Head Office: Treasury conversion (M0 → conversion reserve, M1 capacity)
|
||||
|
||||
| # | Memo | Debit GL | Credit GL | Amount (USD) | Narrative |
|
||||
|---|------|----------|-----------|--------------|-----------|
|
||||
| 2 | **T-001B** | 1050 (Treasury conversion reserve M0) | 2000 (Central deposits) | **250,000,000,000** | Treasury Conversion — Transfer to Reserve (M0); Head Office |
|
||||
|
||||
**Effect:** Moves 250B M0 from Head Office available into conversion reserve (1050). Under ratio 1 M0 = 5 M1 this creates **1,250B M1** capacity. Head Office M0 (2000) remaining = 650B.
|
||||
|
||||
---
|
||||
|
||||
### Phase B+ — M0 to M1 conversion at Head Office
|
||||
|
||||
| # | Memo | Debit GL | Credit GL | Amount (USD) | Narrative |
|
||||
|---|------|----------|-----------|--------------|-----------|
|
||||
| 3 | **T-001C** | 2000 (M0) | 2100 (M1) | **470,000,000,000** | M0 to M1 conversion at HO — 470B for distribution to offices |
|
||||
|
||||
**Effect:** Converts 470B from 2000 (M0) to 2100 (M1) at Head Office. After T-001C, HO 2000 = 180B (M0), HO 2100 = 470B (M1). Phase C then debits HO 2100 and credits 2100 at each office (offices receive **only 2100 M1**).
|
||||
|
||||
---
|
||||
|
||||
### Phase C — M1 from Head Office 2100 to offices (only 2100 at offices)
|
||||
|
||||
**GL:** **2000 = M0**, **2100 = M1**. Offices 2–17 have **only 2100 (M1)** credits.
|
||||
|
||||
- **Interoffice (recommended):** HO leg Dr **2100 (M1)** Cr 2410; office leg Dr 1410 Cr **2100 (M1)**. Matrix: [omnl-journal-matrix-phase-c-interoffice.json](omnl-journal-matrix-phase-c-interoffice.json). Post after [omnl-journal-matrix-phase-a-b-only.json](omnl-journal-matrix-phase-a-b-only.json) (includes T-001C). See [OMNL_PHASE_C_INTEROFFICE_DUE_TO_DUE_FROM.md](OMNL_PHASE_C_INTEROFFICE_DUE_TO_DUE_FROM.md).
|
||||
|
||||
Original Phase C (single-office) entries:
|
||||
|
||||
| # | Memo | Debit GL | Credit GL | Amount (USD) | Office / entity | M1 type |
|
||||
|---|------|----------|-----------|--------------|-----------------|--------|
|
||||
| 3 | **T-002A** | 2000 | 2000 | 2,900,000,000 | Office 2 — Shamrayan Enterprises | Available |
|
||||
| 4 | **T-002B** | 2000 | 2100 | 2,100,000,000 | Office 2 — Shamrayan Enterprises | Restricted |
|
||||
| 5 | **T-003** | 2000 | 2100 | 350,000,000,000 | Office 3 — HYBX | Restricted (capitalization escrow) |
|
||||
| 6 | **T-004** | 2000 | 2000 | 5,000,000,000 | Office 4 — TAJ Private Single Family Office | Available |
|
||||
| 7 | **T-005** | 2000 | 2000 | 5,000,000,000 | Office 5 — Aseret Mortgage Bank | Available |
|
||||
| 8 | **T-006** | 2000 | 2000 | 5,000,000,000 | Office 6 — Mann Li Family Offices | Available |
|
||||
| 9 | **T-007** | 2000 | 2000 | 50,000,000,000 | Office 7 — Sovereign Order of Malta OSJ | Available |
|
||||
| 10 | **T-008** | 2000 | 2000 | 50,000,000,000 | Office 8 — Alltra Mainnet | Available |
|
||||
|
||||
**M1 totals per office:**
|
||||
|
||||
| Office | Entity | Available (2000) | Restricted (2100) | Total M1 |
|
||||
|--------|--------|------------------|-------------------|----------|
|
||||
| 2 | Shamrayan Enterprises | 2.9B | 2.1B | **5B** |
|
||||
| 3 | HYBX | — | 350B | **350B** |
|
||||
| 4 | TAJ Private Single Family Office | 5B | — | **5B** |
|
||||
| 5 | Aseret Mortgage Bank | 5B | — | **5B** |
|
||||
| 6 | Mann Li Family Offices | 5B | — | **5B** |
|
||||
| 7 | Sovereign Order of Malta OSJ | 50B | — | **50B** |
|
||||
| 8 | Alltra Mainnet | 50B | — | **50B** |
|
||||
| **Total** | | | | **470B** |
|
||||
|
||||
---
|
||||
|
||||
## Checklist (post in order)
|
||||
|
||||
1. ☐ **T-001** — Opening balance 900B (1000 ↑, 2000 ↓)
|
||||
2. ☐ **T-001B** — Conversion 250B (1050 ↑, 2000 ↓)
|
||||
3. ☐ **T-002A** — Shamrayan available 2.9B (2000 → 2000 Office 2)
|
||||
4. ☐ **T-002B** — Shamrayan restricted 2.1B (2000 → 2100 Office 2)
|
||||
5. ☐ **T-003** — HYBX restricted 350B (2000 → 2100 Office 3)
|
||||
6. ☐ **T-004** — TAJ 5B (2000 → 2000 Office 4)
|
||||
7. ☐ **T-005** — Aseret 5B (2000 → 2000 Office 5)
|
||||
8. ☐ **T-006** — Mann Li 5B (2000 → 2000 Office 6)
|
||||
9. ☐ **T-007** — OSJ 50B (2000 → 2000 Office 7)
|
||||
10. ☐ **T-008** — Alltra 50B (2000 → 2000 Office 8)
|
||||
11. ☐ **T-Samama (optional)** — Samama Group LLC (Azerbaijan) 5B M1: create office then HO leg + office leg. See [SAMAMA_OFFICE_AND_5B_M1_TRANSFER.md](SAMAMA_OFFICE_AND_5B_M1_TRANSFER.md); `bash scripts/omnl/omnl-office-create-samama.sh`.
|
||||
|
||||
---
|
||||
|
||||
## How to post
|
||||
|
||||
- **Phase A+B (T-001, T-001B):** From repo root: `bash scripts/omnl/omnl-ledger-post-from-matrix.sh` (uses [omnl-journal-matrix.json](omnl-journal-matrix.json)). Use `DRY_RUN=1` to preview.
|
||||
- **Phase C — Original:** Same script with default matrix (10 entries total; Phase C at officeId=1).
|
||||
- **Phase C — Interoffice (Due-To/Due-From):** Create GL 1410 and 2410. Post Phase A+B only with [omnl-journal-matrix-phase-a-b-only.json](omnl-journal-matrix-phase-a-b-only.json), then Phase C with [omnl-journal-matrix-phase-c-interoffice.json](omnl-journal-matrix-phase-c-interoffice.json). See [OMNL_PHASE_C_INTEROFFICE_DUE_TO_DUE_FROM.md](OMNL_PHASE_C_INTEROFFICE_DUE_TO_DUE_FROM.md) and [OMNL_POSTING_AND_RECONCILIATION_EVIDENCE.md](OMNL_POSTING_AND_RECONCILIATION_EVIDENCE.md).
|
||||
- **Manual:** `POST /v1/journalentries` for each row; use GL account **IDs** from `GET /v1/glaccounts`. Single `transactionDate` for migration.
|
||||
- **Post–Phase C (optional) — Samama:** Create office and post 5B M1: `bash scripts/omnl/omnl-office-create-samama.sh`. Matrix: [omnl-journal-matrix-samama-5b.json](omnl-journal-matrix-samama-5b.json). See [SAMAMA_OFFICE_AND_5B_M1_TRANSFER.md](SAMAMA_OFFICE_AND_5B_M1_TRANSFER.md).
|
||||
|
||||
---
|
||||
|
||||
## References
|
||||
|
||||
- [MIGRATION_AND_LEDGER_ALLOCATION_MEMORANDUM.md](MIGRATION_AND_LEDGER_ALLOCATION_MEMORANDUM.md) — Authoritative memo
|
||||
- [LEDGER_ALLOCATION_POSTING_RUNBOOK.md](LEDGER_ALLOCATION_POSTING_RUNBOOK.md) — Pre-post checklist and reconciliation
|
||||
- [OMNL_JOURNAL_LEDGER_MATRIX.md](OMNL_JOURNAL_LEDGER_MATRIX.md) — Matrix and IPSAS
|
||||
- [omnl-journal-matrix.json](omnl-journal-matrix.json) — Machine-readable entries (Phase A+B+C original)
|
||||
- [omnl-journal-matrix-phase-a-b-only.json](omnl-journal-matrix-phase-a-b-only.json) — Phase A+B only (T-001, T-001B)
|
||||
- [omnl-journal-matrix-phase-c-interoffice.json](omnl-journal-matrix-phase-c-interoffice.json) — Phase C only, interoffice legs (1410/2410)
|
||||
- [OMNL_PHASE_C_INTEROFFICE_DUE_TO_DUE_FROM.md](OMNL_PHASE_C_INTEROFFICE_DUE_TO_DUE_FROM.md) — Phase C strict double-entry (Due-To/Due-From)
|
||||
- [OMNL_POSTING_AND_RECONCILIATION_EVIDENCE.md](OMNL_POSTING_AND_RECONCILIATION_EVIDENCE.md) — Posting evidence and reconciliation checklist
|
||||
- [SAMAMA_OFFICE_AND_5B_M1_TRANSFER.md](SAMAMA_OFFICE_AND_5B_M1_TRANSFER.md) — Samama Group LLC office creation and 5B M1 transfer
|
||||
202
docs/04-configuration/mifos-omnl-central-bank/OPERATING_RAILS.md
Normal file
202
docs/04-configuration/mifos-omnl-central-bank/OPERATING_RAILS.md
Normal file
@@ -0,0 +1,202 @@
|
||||
# OMNL Operating Rails — Controls, Reconciliation, Idempotency
|
||||
|
||||
**Purpose:** Repeatable, safe operating rail for Office 20 (Samama) and beyond: confirm journal entry schema, hard controls (closures + idempotency), ID resolver, reconciliation snapshot, and one-command operator rail. Use this after Office 20 + 5B are posted.
|
||||
|
||||
**Tenancy:** [omnl.hybxfinance.io](https://omnl.hybxfinance.io/) — tenant `omnl`. Credentials in `omnl-fineract/.env` or root `.env`.
|
||||
|
||||
---
|
||||
|
||||
## 1) Journal entry schema (locked in)
|
||||
|
||||
The OMNL/HYBX tenant uses **Form 1: `debits` / `credits`** for `POST /journalentries`:
|
||||
|
||||
- **debits:** `[ { "glAccountId": <id>, "amount": <number> } ]`
|
||||
- **credits:** `[ { "glAccountId": <id>, "amount": <number> } ]`
|
||||
- Plus: `officeId`, `transactionDate`, `dateFormat`, `locale`, `currencyCode`, `comments`, and (where supported) **`referenceNumber`** for idempotency.
|
||||
|
||||
Confirmed via HTTP 200 on Samama 5B postings. Do **not** use `glJournalEntryDetails` unless your deployment documents that shape; standardize on `debits`/`credits` everywhere.
|
||||
|
||||
**Quick check:** Run a $1 test JE with the same structure, or open [Swagger](https://omnl.hybxfinance.io/fineract-provider/swagger-ui/index.html) → `POST /journalentries` and confirm request body.
|
||||
|
||||
---
|
||||
|
||||
## 2) Hard controls
|
||||
|
||||
### 2.1 GL closures (Office 20 and HO)
|
||||
|
||||
Prevent backdating: post a closure for the funding date (or later).
|
||||
|
||||
```bash
|
||||
# From repo root
|
||||
CLOSING_DATE=2026-02-24 bash scripts/omnl/omnl-gl-closures-post.sh
|
||||
```
|
||||
|
||||
Verify:
|
||||
|
||||
- `GET /glclosures?officeId=20`
|
||||
- `GET /glclosures?officeId=1`
|
||||
|
||||
Acceptance: closure exists and date matches (or is after) the funded posting date.
|
||||
|
||||
### 2.2 Idempotency via referenceNumber
|
||||
|
||||
Every journal entry (and, where supported, deposit/disbursement) must use a **unique, deterministic** reference:
|
||||
|
||||
- Format: `SAMAMA-20-YYYYMMDD-SEQ` or `OMNL-JE-<officeId>-YYYYMMDD-<seq>`
|
||||
- Enforce at gateway/middleware if Fineract does not reject duplicates.
|
||||
|
||||
Scripts in this repo:
|
||||
|
||||
- **omnl-ledger-post-from-matrix.sh** — adds `referenceNumber` per entry (e.g. `OMNL-JE-{officeId}-{date}-{index}`).
|
||||
- **omnl-office-create-samama.sh** — uses `SAMAMA-20-{date}-HO` and `SAMAMA-20-{date}-OF` for the 5B legs.
|
||||
|
||||
---
|
||||
|
||||
## 3) ID resolver (no copy-paste of IDs)
|
||||
|
||||
Resolve GL and payment type IDs once; write `ids.env` for downstream commands.
|
||||
|
||||
```bash
|
||||
# From repo root
|
||||
source omnl-fineract/.env
|
||||
bash scripts/omnl/resolve_ids.sh
|
||||
source ids.env
|
||||
```
|
||||
|
||||
Output: `ids.env` in current directory with `ID_1410`, `ID_2100`, `ID_2410`, `PAYMENT_TYPE_ID`. Exits non-zero if any required GL code is missing. Do not commit `ids.env` if it contains env-specific values.
|
||||
|
||||
---
|
||||
|
||||
## 4) Reconciliation (minimum viable)
|
||||
|
||||
### 4.1 Daily snapshot for Office 20
|
||||
|
||||
```bash
|
||||
bash scripts/omnl/omnl-reconciliation-office20.sh
|
||||
```
|
||||
|
||||
Writes under `reconciliation/` (or `OUT_DIR`):
|
||||
|
||||
- `office20-<timestamp>.json` — combined snapshot (offices, GL 1410/2100/2410).
|
||||
- `office20-<timestamp>.meta` — timestamp, file path, sha256 hash.
|
||||
|
||||
Acceptance for Office 20 after 5B funding:
|
||||
|
||||
- **1410** net Dr = 5,000,000,000
|
||||
- **2100** net Cr = 5,000,000,000
|
||||
- HO **2410** increased by 5,000,000,000
|
||||
|
||||
Verify in UI (Reports → Trial balance) or via the snapshot + trial balance export if your report runner supports `R_officeId=20`.
|
||||
|
||||
### 4.2 Automate (optional)
|
||||
|
||||
Run `omnl-reconciliation-office20.sh` on a schedule (cron or CI). For Samama-side delivery, use your existing upload endpoint and credentials stored in a vault (do not paste credentials in chat or logs).
|
||||
|
||||
---
|
||||
|
||||
## 5) One-command operator rail
|
||||
|
||||
Run in order: resolve IDs → closures (if missing) → verification → reconciliation → print safe A/B/C templates.
|
||||
|
||||
```bash
|
||||
# From repo root
|
||||
source omnl-fineract/.env
|
||||
bash scripts/omnl/omnl-operator-rail.sh
|
||||
```
|
||||
|
||||
Optional:
|
||||
|
||||
- `SKIP_CLOSURES=1` — do not post GL closures.
|
||||
- `SKIP_RECON=1` — do not run reconciliation snapshot.
|
||||
- `CLOSING_DATE=yyyy-MM-dd` — use this closure date.
|
||||
|
||||
The script prints curl-style templates for:
|
||||
|
||||
- **Path A:** Treasury transfer out from Office 20 (Dr 2100, Cr 1410) with `referenceNumber`.
|
||||
- **Path B:** Savings deposit (uses `PAYMENT_TYPE_ID` from `ids.env`).
|
||||
- **Path C:** Loan disburse (uses `PAYMENT_TYPE_ID`).
|
||||
|
||||
Replace `AMOUNT`, `SAVINGS_ACCOUNT_ID`, `LOAN_ID` as needed; keep credentials and IDs out of version control.
|
||||
|
||||
---
|
||||
|
||||
## 6) Movement rule (Path A)
|
||||
|
||||
Canonical transfer-out from Office 20 (treasury only):
|
||||
|
||||
- **Dr 2100** (M1 liability at office)
|
||||
- **Cr 1410** (Due From HO asset)
|
||||
|
||||
Reduces treasury asset and internal liability. Use a unique `referenceNumber` and consistent memo format. For transfers **to** another office, mirror the interoffice pattern (HO leg + destination office leg) as in Phase C.
|
||||
|
||||
---
|
||||
|
||||
## 7) Enabling B or C (after controls + reconciliation)
|
||||
|
||||
- **Path B (clients + savings):** Define a standard wallet/savings product with accounting; map client liabilities to 2100 or a dedicated sub-ledger. Use `resolve_ids.sh` and `ids.env` for `paymentTypeId` and GL.
|
||||
- **Path C (lending):** Define loan product and GL mappings (portfolio, interest, fees, provisions). Do not start product creation until closures are in place and reconciliation is running.
|
||||
|
||||
---
|
||||
|
||||
## 8) Posting guardrails (idempotency-by-enforcement)
|
||||
|
||||
In **omnl-ledger-post-from-matrix.sh**:
|
||||
|
||||
- **Duplicate referenceNumber:** Before each post, check a local `reconciliation/.posted_refs` file (or API if supported). If the ref was already posted → skip with message.
|
||||
- **Sanity checks:** Reject negative/zero amount; reject amount > `MAX_POST_AMOUNT` (if set); reject `officeId` not in `ALLOWED_OFFICE_IDS` (default 1–20).
|
||||
|
||||
Set `MAX_POST_AMOUNT` (e.g. `1000000000000`) to cap single-JE amount. Set `POSTED_REFS_FILE` to change the idempotency file path. For shared/durable refs (two operators, two machines): set `POSTED_REFS_FILE` to a shared path or use `POSTED_REFS_SYNC_PULL_CMD` / `POSTED_REFS_SYNC_PUSH_CMD` (e.g. S3 pull before, push after). See [PRODUCTION_OPS_OFFICE20.md](PRODUCTION_OPS_OFFICE20.md).
|
||||
|
||||
---
|
||||
|
||||
## 9) Audit packet and DR
|
||||
|
||||
- **omnl-audit-packet-office20.sh** — One folder per run: `snapshot.json`, `snapshot.meta`, `computed_balances.json`, `recent_journal_entries.json`, `manifest.json`. See [OFFICE_20_AUDIT_PACKET.md](OFFICE_20_AUDIT_PACKET.md).
|
||||
- **omnl-je-reverse-by-reference.sh** — Find JE by referenceNumber and post reversal (opposite debits/credits). See [OFFICE_20_DR_RUNBOOK.md](OFFICE_20_DR_RUNBOOK.md).
|
||||
- **omnl-je-maker.sh** / **omnl-je-checker.sh** — Maker writes payload + sha256; checker validates and posts (maker-checker).
|
||||
|
||||
---
|
||||
|
||||
## 10) Monitoring and config drift
|
||||
|
||||
- **omnl-monitor-office20-movement.sh** — Exits 2 if any JE for office 20 in the last N days (alert payload to stdout). Use in cron or alerting pipeline.
|
||||
- **omnl-config-hash.sh** — Outputs sha256 of payment types, GL 1410/2100/2410, office 20 config. Diff against baseline to detect drift.
|
||||
|
||||
---
|
||||
|
||||
## 11) Script reference
|
||||
|
||||
| Script | Purpose |
|
||||
|--------|---------|
|
||||
| **resolve_ids.sh** | Resolve ID_1410, ID_2100, ID_2410, PAYMENT_TYPE_ID; write ids.env |
|
||||
| **omnl-gl-closures-post.sh** | Post GL closures for Office 20 and HO (idempotent) |
|
||||
| **omnl-reconciliation-office20.sh** | Snapshot Office 20 (offices + GL + optional trial balance), hash, meta |
|
||||
| **omnl-operator-rail.sh** | Full rail: resolve IDs, closures, verify, reconciliation, A/B/C readiness, print templates |
|
||||
| **omnl-audit-packet-office20.sh** | Audit packet: snapshot, computed_balances, recent JEs, manifest |
|
||||
| **omnl-je-reverse-by-reference.sh** | Reverse JE by referenceNumber |
|
||||
| **omnl-je-maker.sh** / **omnl-je-checker.sh** | Maker-checker for single JE |
|
||||
| **omnl-monitor-office20-movement.sh** | Alert if Office 20 movement detected |
|
||||
| **omnl-config-hash.sh** | Config hashes for drift detection |
|
||||
| **omnl-baseline-create.sh** | Day 0 baseline: config-hash + audit packet under reconciliation/baseline/<date>/ |
|
||||
| **create-office-and-fund.sh** | Create office (name, externalId, openingDate) + two-leg M1 funding from HO (Rail B); post-audit for new office |
|
||||
| **validate-rail.sh** | CI: .gitignore, resolve_ids pattern, shellcheck |
|
||||
|
||||
All under `scripts/omnl/`. See [scripts/omnl/README.md](../../scripts/omnl/README.md).
|
||||
|
||||
---
|
||||
|
||||
## 12) Production ops (baselines, alerts, material policy, fire drill)
|
||||
|
||||
- **[PRODUCTION_OPS_OFFICE20.md](PRODUCTION_OPS_OFFICE20.md)** — Baselines (Day 0), alert path, retention/chain-of-custody, durable posted_refs, alert wiring (no secrets).
|
||||
- **[MATERIAL_POSTING_POLICY.md](MATERIAL_POSTING_POLICY.md)** — Thresholds (e.g. ≥10M maker-checker, ≥100M + reviewer + audit); maker/checker approval gating.
|
||||
- **[OFFICE_20_FIRE_DRILL_RUNBOOK.md](OFFICE_20_FIRE_DRILL_RUNBOOK.md)** — One-time drill: maker $1 → checker → alert → audit → reverse → audit.
|
||||
- **omnl-baseline-create.sh** — Creates `reconciliation/baseline/<YYYYMMDD>/` (config-hash + audit packet); copy off-box for Day 0.
|
||||
- **Audit packet** appends folder hash to `audit_log.jsonl` (chain-of-custody); Path B/C templates in operator rail print only when ready (payment type + savings / loan products).
|
||||
|
||||
---
|
||||
|
||||
## 13) References
|
||||
|
||||
- [SAMAMA_OFFICE_AND_5B_M1_TRANSFER.md](SAMAMA_OFFICE_AND_5B_M1_TRANSFER.md) — Office 20 creation and 5B M1
|
||||
- [LEDGER_ALLOCATION_POSTING_RUNBOOK.md](LEDGER_ALLOCATION_POSTING_RUNBOOK.md) — Pre-post checklist
|
||||
- [OMNL_PHASE_C_INTEROFFICE_DUE_TO_DUE_FROM.md](OMNL_PHASE_C_INTEROFFICE_DUE_TO_DUE_FROM.md) — Phase C two-leg design
|
||||
@@ -0,0 +1,179 @@
|
||||
# P2P Banking Rail — HYBX → CrunchyGalaxy Settlement
|
||||
|
||||
**Scope:** Server-to-server banking API settlement (not internal ledger only, not Samama upload, not SWIFT). Funds originate from HYBX; delivery and confirmation are via CrunchyGalaxy’s banking endpoint.
|
||||
|
||||
**Current state (as of runbook date):**
|
||||
- ✅ Internal ledger funded (Office 21 = 1.0B M1)
|
||||
- ❌ No HYBX → CrunchyGalaxy P2P API call executed
|
||||
- ❌ No settlement confirmation
|
||||
- ❌ No mirror ledger reduction
|
||||
- ❌ No wire settlement package
|
||||
|
||||
**Control rule:** Do **not** post the mirror ledger entry until settlement is confirmed (`status == SETTLED`). Otherwise the internal state would not match actual settlement.
|
||||
|
||||
---
|
||||
|
||||
## Required inputs (before Phase 1)
|
||||
|
||||
You must have:
|
||||
|
||||
| Input | Description |
|
||||
|-------|-------------|
|
||||
| **Settlement endpoint URL** | CrunchyGalaxy P2P settlement API (e.g. `https://api.crunchygalaxy.com/v1/p2p/settlement`) |
|
||||
| **Authentication** | JWT / mTLS / API key — method and how to obtain (no secrets in repo) |
|
||||
| **Idempotency key** | Unique per settlement (e.g. `CRUNCHY-21-20260224-SET-510M`) |
|
||||
| **Settlement reference** | Same or linked to idempotency key |
|
||||
| **Amount** | Minor units (e.g. 510000000 USD) |
|
||||
| **Value date** | e.g. 2026-02-24 |
|
||||
| **Purpose code** | e.g. Tranche 1 Commitment Settlement |
|
||||
| **Signature/hash** | If required by the API |
|
||||
|
||||
*Once endpoint, auth method, and (if available) API spec or sample call are provided, this runbook can be updated with exact production curl and verification call.*
|
||||
|
||||
---
|
||||
|
||||
## Phase 1 — Execute P2P settlement call
|
||||
|
||||
Authenticated S2S call from HYBX to CrunchyGalaxy banking endpoint.
|
||||
|
||||
**Example structure (replace with actual rail schema):**
|
||||
|
||||
```bash
|
||||
curl -X POST https://api.crunchygalaxy.com/v1/p2p/settlement \
|
||||
-H "Authorization: Bearer <JWT_TOKEN>" \
|
||||
-H "Content-Type: application/json" \
|
||||
-H "Idempotency-Key: CRUNCHY-21-20260224-SET-510M" \
|
||||
-d '{
|
||||
"sourceInstitution": "HYBX",
|
||||
"sourceOfficeId": 21,
|
||||
"amount": 510000000,
|
||||
"currency": "USD",
|
||||
"valueDate": "2026-02-24",
|
||||
"reference": "CRUNCHY-21-20260224-SET-510M",
|
||||
"purpose": "Tranche 1 Commitment Settlement"
|
||||
}'
|
||||
```
|
||||
|
||||
**You must capture (verbatim):**
|
||||
- **A)** Full request JSON (as sent)
|
||||
- **B)** Full headers (redact token/value)
|
||||
- **C)** Full response JSON (see Phase 2)
|
||||
|
||||
---
|
||||
|
||||
## Phase 2 — Confirm settlement
|
||||
|
||||
Settlement is **not** closed until one of:
|
||||
|
||||
- Response body contains `"status": "SETTLED"`, or
|
||||
- A follow-up verification call returns SETTLED, e.g.
|
||||
`GET /v1/p2p/settlement/{transactionId}` → `status: SETTLED`
|
||||
|
||||
**Example expected response:**
|
||||
|
||||
```json
|
||||
{
|
||||
"transactionId": "HYBX-SET-884733",
|
||||
"status": "SETTLED",
|
||||
"receivedAmount": 510000000,
|
||||
"currency": "USD",
|
||||
"settlementTimestamp": "2026-02-24T19:02:11Z",
|
||||
"destinationReference": "CGX-ACK-550112"
|
||||
}
|
||||
```
|
||||
|
||||
If `status != SETTLED`, do **not** proceed to Phase 3.
|
||||
|
||||
---
|
||||
|
||||
## Phase 3 — Post ledger mirror entry (only after SETTLED)
|
||||
|
||||
Reduce Office 21 treasury: **Dr 2100 / Cr 1410** for the settled amount (e.g. 510,000,000).
|
||||
|
||||
```bash
|
||||
# From repo root; source ids.env first
|
||||
source ids.env
|
||||
|
||||
export REFERENCE_NUMBER="CRUNCHY-21-20260224-SETTLED-510M"
|
||||
export TX_DATE="2026-02-24"
|
||||
export AMOUNT=510000000
|
||||
|
||||
REQUIRES_APPROVAL=1 APPROVER="<<APPROVER_NAME>>" \
|
||||
REFERENCE_NUMBER="$REFERENCE_NUMBER" TX_DATE="$TX_DATE" OFFICE_ID=21 \
|
||||
DEBIT_GL_ID="$ID_2100" CREDIT_GL_ID="$ID_1410" AMOUNT="$AMOUNT" \
|
||||
bash scripts/omnl/omnl-je-maker.sh
|
||||
|
||||
PAYLOAD_FILE="reconciliation/je-${REFERENCE_NUMBER}_.payload.json"
|
||||
# If no trailing underscore: PAYLOAD_FILE="reconciliation/je-${REFERENCE_NUMBER}.payload.json"
|
||||
PAYLOAD_FILE="$PAYLOAD_FILE" bash scripts/omnl/omnl-je-checker.sh
|
||||
```
|
||||
|
||||
**Resulting balance (example):** 1.0B − 510M = **490M** remaining at Office 21 (1410 Dr / 2100 Cr).
|
||||
|
||||
---
|
||||
|
||||
## Phase 4 — Audit and closure
|
||||
|
||||
```bash
|
||||
OFFICE_ID=21 bash scripts/omnl/omnl-audit-packet-office20.sh
|
||||
bash scripts/omnl/omnl-gl-closures-post.sh
|
||||
```
|
||||
|
||||
**Confirm in audit packet:**
|
||||
|
||||
| GL | Balance (example) |
|
||||
|-----|-------------------|
|
||||
| 1410 | 490,000,000 |
|
||||
| 2100 | −490,000,000 |
|
||||
|
||||
---
|
||||
|
||||
## Phase 5 — Full send / settlement / close package
|
||||
|
||||
ZIP must include:
|
||||
|
||||
1. Full request payload JSON (Phase 1)
|
||||
2. Full response JSON (Phase 1/2)
|
||||
3. Settlement confirmation (response or GET result showing SETTLED)
|
||||
4. Ledger mirror JE payload (and/or ref + transactionId)
|
||||
5. Audit packet folder (Phase 4)
|
||||
6. Hash line (e.g. from `audit_log.jsonl`)
|
||||
7. **Closing memo** (short summary):
|
||||
- Amount settled
|
||||
- SettlementId / transactionId / destinationReference
|
||||
- Timestamp
|
||||
- Remaining balance at Office 21
|
||||
|
||||
Only then is this equivalent to “full send & close” for the P2P rail.
|
||||
|
||||
---
|
||||
|
||||
## Status summary
|
||||
|
||||
| Item | Status |
|
||||
|------|--------|
|
||||
| Ledger funded (Office 21 = 1.0B) | ✅ |
|
||||
| P2P settlement call made | ❌ |
|
||||
| Settlement confirmed (SETTLED) | ❌ |
|
||||
| Mirror ledger entry posted | ❌ |
|
||||
| Audit + closure | ❌ |
|
||||
| Close package produced | ❌ |
|
||||
|
||||
**Next required action:** Execute HYBX → CrunchyGalaxy P2P settlement call once endpoint, auth method, and (if available) API spec or sample are provided.
|
||||
|
||||
---
|
||||
|
||||
## Deliverables (once you provide endpoint + auth)
|
||||
|
||||
When you supply:
|
||||
|
||||
- Actual CrunchyGalaxy P2P endpoint URL
|
||||
- Auth method (JWT / mTLS / API key) and how to obtain it (no secrets in repo)
|
||||
- Any existing API spec or sample call
|
||||
|
||||
This runbook will be updated with:
|
||||
|
||||
- Exact production-ready settlement `curl` (or script)
|
||||
- Verification call (e.g. GET by transactionId)
|
||||
- Complete close-package template (ZIP contents + closing memo)
|
||||
- Executive settlement summary template
|
||||
@@ -0,0 +1,93 @@
|
||||
# Pelican Motors And Finance LLC — Office Creation (OMNL/HYBX)
|
||||
|
||||
**Purpose:** Create a new **Office** in the OMNL/HYBX Fineract instance for **Pelican Motors And Finance LLC** (Chalmette, LA) using the CIS (Client Information Sheet) data.
|
||||
|
||||
**Instance:** Use the API for **omnl.hybx.global** (or omnl.hybxfinance.io). Set `OMNL_FINERACT_BASE_URL` in `.env` accordingly.
|
||||
|
||||
---
|
||||
|
||||
## 1. CIS fields (Office record)
|
||||
|
||||
| Field | Value |
|
||||
|-------|--------|
|
||||
| **Proposed Office Name** | Pelican Motors And Finance LLC |
|
||||
| **Office / Company Address** | 8651 W Judge Perez Drive, Chalmette, LA 70043 |
|
||||
| **Primary Contact (represented by)** | Glen McInerney |
|
||||
| **Title** | CEO |
|
||||
|
||||
Banking, passport, and incorporation docs are supporting KYC/formation; they do not populate the Fineract Office object. Address and contact can be stored in the UI or external master data.
|
||||
|
||||
---
|
||||
|
||||
## 2. Required by Fineract “Create Office”
|
||||
|
||||
| API field | Value used | Notes |
|
||||
|-----------|------------|--------|
|
||||
| **name** | Pelican Motors And Finance LLC | From CIS |
|
||||
| **parentId** | `1` | Head Office (this office rolls up under HO) |
|
||||
| **openingDate** | `2026-02-26` (configurable) | System opening date; override with `OPENING_DATE=yyyy-MM-dd` |
|
||||
| **externalId** | PEL-MOTORS-CHALMETTE-LA | Suggested slug (no office code in CIS) |
|
||||
|
||||
---
|
||||
|
||||
## 3. API payload (Fineract REST)
|
||||
|
||||
**Endpoint:** `POST /fineract-provider/api/v1/offices`
|
||||
|
||||
**Example payload** (dateFormat `yyyy-MM-dd` used by scripts):
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "Pelican Motors And Finance LLC",
|
||||
"parentId": 1,
|
||||
"openingDate": "2026-02-26",
|
||||
"dateFormat": "yyyy-MM-dd",
|
||||
"locale": "en",
|
||||
"externalId": "PEL-MOTORS-CHALMETTE-LA"
|
||||
}
|
||||
```
|
||||
|
||||
Alternative date format (if your instance expects it): `"openingDate": "26 February 2026"`, `"dateFormat": "dd MMMM yyyy"`.
|
||||
|
||||
---
|
||||
|
||||
## 4. Script (recommended)
|
||||
|
||||
From repo root with `omnl-fineract/.env` or root `.env` set (and for **omnl.hybx.global** ensure `OMNL_FINERACT_BASE_URL=https://omnl.hybx.global/fineract-provider/api/v1`):
|
||||
|
||||
```bash
|
||||
# Dry run (print payload only)
|
||||
DRY_RUN=1 bash scripts/omnl/omnl-office-create-pelican.sh
|
||||
|
||||
# Create office (idempotent by externalId)
|
||||
bash scripts/omnl/omnl-office-create-pelican.sh
|
||||
```
|
||||
|
||||
**Optional overrides:**
|
||||
|
||||
- `OPENING_DATE=2026-02-26` — default; change if needed.
|
||||
- `PELICAN_EXTERNAL_ID=PEL-MOTORS-CHALMETTE-LA` — default.
|
||||
- `PELICAN_OFFICE_NAME="Pelican Motors And Finance LLC"` — default.
|
||||
|
||||
Script outputs `OFFICE_ID_PELICAN=<id>` on success.
|
||||
|
||||
---
|
||||
|
||||
## 5. UI steps (Mifos X)
|
||||
|
||||
1. **Organization** → **Offices**
|
||||
2. **Create Office**
|
||||
3. Enter:
|
||||
- **Name:** Pelican Motors And Finance LLC
|
||||
- **Parent Office:** Head Office (or your OMNL/HYBX parent office)
|
||||
- **Opening Date:** e.g. 26 February 2026
|
||||
- **External ID** (if shown): PEL-MOTORS-CHALMETTE-LA
|
||||
- Address/notes: 8651 W Judge Perez Drive, Chalmette, LA 70043 (if supported)
|
||||
4. **Submit**
|
||||
|
||||
---
|
||||
|
||||
## 6. Related
|
||||
|
||||
- [OMNL_FINERACT_CONFIGURATION.md](../OMNL_FINERACT_CONFIGURATION.md) — Base URL, tenant, credentials.
|
||||
- [SAMAMA_OFFICE_AND_5B_M1_TRANSFER.md](SAMAMA_OFFICE_AND_5B_M1_TRANSFER.md) — Same POST /offices pattern; optional M1 funding flow.
|
||||
@@ -0,0 +1,160 @@
|
||||
# OMNL Production Operations — Office 20 and Beyond
|
||||
|
||||
Production-operable rails: baselines, alert path, retention/chain-of-custody, material policy, durable posted_refs, fire drill, Path B/C gating.
|
||||
|
||||
---
|
||||
|
||||
## 1) Baselines (Day 0)
|
||||
|
||||
**Purpose:** Immutable “Day 0” to compare every future run against (drift detection).
|
||||
|
||||
**Create baseline (run once after confirming 5B in UI):**
|
||||
|
||||
```bash
|
||||
bash scripts/omnl/omnl-baseline-create.sh
|
||||
```
|
||||
|
||||
Output:
|
||||
|
||||
- `reconciliation/baseline/<YYYYMMDD>/config-hash.json` — from `omnl-config-hash.sh`
|
||||
- `reconciliation/baseline/<YYYYMMDD>/audit-office20-<timestamp>/` — full audit packet
|
||||
|
||||
**Convention:** `reconciliation/baseline/<YYYYMMDD>/`. Copy off-box (S3/Drive/Vault) and keep immutable.
|
||||
|
||||
**Success:** You have a signed baseline to diff against for config drift and audit comparison.
|
||||
|
||||
---
|
||||
|
||||
## 2) Alert path (monitoring + drift)
|
||||
|
||||
**Movement monitor** — Run every 5–15 min (cron/systemd/GitHub Actions). Exit code **2** = “alert”.
|
||||
|
||||
```bash
|
||||
# Example cron: every 10 min
|
||||
*/10 * * * * /path/to/scripts/omnl/omnl-monitor-office20-movement.sh || [ $? -eq 2 ] && /path/to/alert-wrapper.sh movement
|
||||
```
|
||||
|
||||
**Config drift** — Run daily (or hourly). Diff `omnl-config-hash.sh` output against `reconciliation/baseline/<YYYYMMDD>/config-hash.json`.
|
||||
|
||||
**Alert wrapper:** See [Alert wiring](#alert-wiring) below. Treat exit 2 and script JSON output as alert payload; do not log secrets.
|
||||
|
||||
---
|
||||
|
||||
## 3) Retention and chain-of-custody (audit packets)
|
||||
|
||||
**Retention:**
|
||||
|
||||
- Keep **30–90 days** locally (rolling); delete older packets under `reconciliation/` (or your OUT_BASE).
|
||||
- Keep **all “material event” packets** permanently off-site (e.g. S3/archive).
|
||||
|
||||
**Chain-of-custody:** When `omnl-audit-packet-office20.sh` runs it:
|
||||
|
||||
- Builds the packet folder.
|
||||
- Computes a **folder content hash** (sha256 of sorted file hashes).
|
||||
- Appends one line to **`audit_log.jsonl`** (outside `reconciliation/`):
|
||||
`{"timestamp":"...", "packetDir":"...", "folderSha256":"...", "officeId":20}`
|
||||
|
||||
`audit_log.jsonl` is append-only. Optionally push the hash into your change record or ticket.
|
||||
|
||||
**Success:** Tamper-evident history of Office 20 state; you can prove packet integrity.
|
||||
|
||||
---
|
||||
|
||||
## 4) Material posting policy
|
||||
|
||||
See **MATERIAL_POSTING_POLICY.md**. Summary:
|
||||
|
||||
- ≥ **10M** → maker-checker required; maker needs `REQUIRES_APPROVAL=1` and `APPROVER=<name>`; checker refuses without approvalMetadata in payload.
|
||||
- ≥ **100M** → maker-checker + second reviewer + audit packet.
|
||||
- Office 20 postings touching 1410/2100/2410 → audit packet mandatory.
|
||||
|
||||
---
|
||||
|
||||
## 5) Durable `.posted_refs` (no double-post across operators)
|
||||
|
||||
The duplicate guard uses a file (default `reconciliation/.posted_refs`). For production, make it **shared** so two operators on two machines cannot double-post the same ref.
|
||||
|
||||
**Options:**
|
||||
|
||||
| Option | How |
|
||||
|--------|-----|
|
||||
| **Shared path** | Set `POSTED_REFS_FILE` to a path on shared storage (NFS, shared volume). All runners use the same file. |
|
||||
| **S3 (or similar)** | Set `POSTED_REFS_FILE` to a local path and set `POSTED_REFS_SYNC_CMD` to a command that pulls before and pushes after. Example: `POSTED_REFS_SYNC_CMD='aws s3 cp s3://bucket/omnl/.posted_refs $POSTED_REFS_FILE'` for pull; script runs sync after each append (or use a wrapper that syncs once at end). |
|
||||
| **API** | If your platform supports “list journal entries by referenceNumber”, enforce uniqueness by checking before post (document as preferred when available). |
|
||||
|
||||
**In scripts:**
|
||||
|
||||
- `omnl-ledger-post-from-matrix.sh` uses `POSTED_REFS_FILE` (default `reconciliation/.posted_refs`).
|
||||
- Optional sync for shared storage:
|
||||
- `POSTED_REFS_SYNC_PULL_CMD` — run once before the posting loop (e.g. `aws s3 cp s3://bucket/omnl/.posted_refs $POSTED_REFS_FILE`).
|
||||
- `POSTED_REFS_SYNC_PUSH_CMD` — run after each new ref is appended (e.g. `aws s3 cp $POSTED_REFS_FILE s3://bucket/omnl/.posted_refs`).
|
||||
|
||||
**Success:** Two operators on two machines cannot post the same referenceNumber; refs are the single source of truth.
|
||||
|
||||
---
|
||||
|
||||
## 6) Fire drill (DR + reversal + audit)
|
||||
|
||||
Run once in a calm period to prove: detect → document → reverse → verify.
|
||||
|
||||
1. **Maker** generates $1 payload with ref `DRILL-<date>-001`:
|
||||
```bash
|
||||
source ids.env
|
||||
REF="DRILL-$(date +%Y%m%d)-001" AMOUNT=1 OFFICE_ID=20 DEBIT_GL_ID=$ID_2100 CREDIT_GL_ID=$ID_1410 \
|
||||
bash scripts/omnl/omnl-je-maker.sh
|
||||
```
|
||||
2. **Checker** posts it:
|
||||
`PAYLOAD_FILE=reconciliation/je-DRILL-....payload.json bash scripts/omnl/omnl-je-checker.sh`
|
||||
3. **Movement monitor** — run and confirm it triggers (exit 2).
|
||||
4. **Audit packet** — run and archive.
|
||||
5. **Reverse** by reference:
|
||||
`bash scripts/omnl/omnl-je-reverse-by-reference.sh DRILL-<date>-001`
|
||||
6. **Audit packet** again — prove returned state.
|
||||
|
||||
**Success:** End-to-end detect → document → reverse → verify.
|
||||
|
||||
---
|
||||
|
||||
## 7) Path B/C gating (operator rail)
|
||||
|
||||
The operator rail prints “Path B” (deposit) and “Path C” (disburse) templates only when ready:
|
||||
|
||||
- **Path B:** Only if a payment type exists and savings products exist (and accounting enabled when we can detect it).
|
||||
- **Path C:** Only if loan products exist (and loan accounting enabled when we can detect it).
|
||||
|
||||
Otherwise it prints a “not ready” message and does not emit the template. This keeps the rail a safe truth tool.
|
||||
|
||||
---
|
||||
|
||||
## Alert wiring
|
||||
|
||||
Use a small wrapper so exit codes and JSON become alerts **without leaking secrets**.
|
||||
|
||||
**Pattern:**
|
||||
|
||||
1. Run the script; capture exit code and stdout/stderr.
|
||||
2. If exit code = 2 (or your chosen “alert” code), send an alert.
|
||||
3. Alert payload: script name, exit code, timestamp, and **only** the script’s JSON or summary line (scripts already avoid printing passwords). Do **not** include `.env`, `PASSWORD`, or raw curl.
|
||||
|
||||
**Example (cron + Slack webhook):**
|
||||
|
||||
```bash
|
||||
# /usr/local/bin/omnl-alert-on-movement.sh
|
||||
OUT=$(/path/to/scripts/omnl/omnl-monitor-office20-movement.sh 2>&1); EXIT=$?
|
||||
if [ "$EXIT" = "2" ]; then
|
||||
curl -s -X POST -H 'Content-Type: application/json' \
|
||||
-d "{\"text\": \"OMNL movement alert (exit $EXIT): ${OUT}\"}" \
|
||||
"$SLACK_WEBHOOK_URL"
|
||||
fi
|
||||
exit $EXIT
|
||||
```
|
||||
|
||||
**Example (PagerDuty):** Use their CLI or API with a summary like “OMNL Office 20 movement detected” and attach the JSON in a details field, not in the title.
|
||||
|
||||
**Success:** Alerts fire when movement or drift is detected; no credentials in alerts.
|
||||
|
||||
---
|
||||
|
||||
## Closure delete (high-risk; avoid if possible)
|
||||
|
||||
**DELETE /glclosures/{id}** reopens a period and is a high-risk operational pattern. Prefer: set closure dates so the intended posting date stays open until after you post, or use an "operations window" checklist (post first, then run closure script). If you must reopen: use a logged change record, post the JE, then re-run the closure script immediately and generate an audit packet before/after.
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user