scrub: subnet/l2 → chain (canonical vocabulary, forward-only)
Wire-format codec IDs unchanged. CLI aliases deleted; chain is the command. No backwards-compat shims, no deprecation comments.
This commit is contained in:
+6
-6
@@ -271,7 +271,7 @@ or `frontend-config-{chain}-{brand}` if the same chain needs different branding
|
||||
different hostnames.
|
||||
|
||||
Current state: each chain has one ConfigMap (Zoo chain = Zoo brand). This is correct
|
||||
for now because each L2 EVM IS a brand. If a chain ever needs multiple brand presentations,
|
||||
for now because each app chain EVM IS a brand. If a chain ever needs multiple brand presentations,
|
||||
add a second ConfigMap and a second Deployment.
|
||||
|
||||
Schema (all fields are `NEXT_PUBLIC_*` env vars):
|
||||
@@ -406,7 +406,7 @@ Bootnode (`~/work/bootnode/`) is the admin control plane for the white-label pla
|
||||
### What Bootnode Manages
|
||||
|
||||
1. **Org onboarding** -- create org in IAM, create KMS project, provision DNS
|
||||
2. **Chain deployment** -- trigger L2 EVM creation via lux-operator CRDs
|
||||
2. **Chain deployment** -- trigger app chain EVM creation via lux-operator CRDs
|
||||
3. **Service provisioning** -- generate K8s manifests for new WL tenant
|
||||
4. **Monitoring** -- health checks, chain sync status, validator status
|
||||
5. **User management** -- IAM users, roles, API keys per org
|
||||
@@ -429,7 +429,7 @@ api.cloud.{brand}.{tld} --> bootnode-api (FastAPI, Python 3.12+)
|
||||
| Endpoint | Purpose |
|
||||
|----------|---------|
|
||||
| POST /v1/orgs | Create new org (provisions IAM + KMS) |
|
||||
| POST /v1/orgs/{id}/chains | Deploy new L2 EVM chain |
|
||||
| POST /v1/orgs/{id}/chains | Deploy new app chain EVM chain |
|
||||
| POST /v1/orgs/{id}/services | Provision explorer/exchange/faucet for org |
|
||||
| GET /v1/orgs/{id}/status | Health of all org services |
|
||||
| POST /v1/orgs/{id}/dns | Configure DNS records via CF API |
|
||||
@@ -705,8 +705,8 @@ IngressRoute specs. They create the records.
|
||||
|
||||
### Step 3: Chain Deployment
|
||||
|
||||
- [ ] Add L2 EVM config to NETWORKS.yaml
|
||||
- [ ] Deploy L2 EVM via lux-operator LuxChain CRD
|
||||
- [ ] Add app chain EVM config to NETWORKS.yaml
|
||||
- [ ] Deploy app chain EVM via lux-operator LuxChain CRD
|
||||
- [ ] Verify chain is tracking on all 5 validators (mainnet/testnet)
|
||||
- [ ] Deploy standard contracts (WLUX, bridged tokens, AMM, governance -- 20 contracts)
|
||||
- [ ] Verify contract deployments
|
||||
@@ -871,7 +871,7 @@ ServiceAccount should only have access to lux-explorer and lux-kms namespaces.
|
||||
|
||||
**Action**:
|
||||
1. Follow onboarding checklist (Section 10) for the new tenant
|
||||
2. Deploy tenant L2 EVM (chain IDs from NETWORKS.yaml)
|
||||
2. Deploy tenant app chain EVM (chain IDs from NETWORKS.yaml)
|
||||
3. Dedicated KMS instance (Phase 4 prerequisite)
|
||||
4. Explorer, exchange, faucet, cloud
|
||||
5. Each tenant manages their own DNS zone -- we provide IP + IngressRoute specs
|
||||
|
||||
@@ -4,7 +4,7 @@ This file provides guidance to AI tools when working with code in this repositor
|
||||
|
||||
## Project Overview
|
||||
|
||||
This is a multi-blockchain infrastructure project managing 4 Lux L2 EVM networks (LUX, ZOO, SPC, and Hanzo). The infrastructure includes blockchain nodes, block explorers, DeFi exchange, Graph Protocol indexers, cross-chain bridges, and IPFS storage.
|
||||
This is a multi-blockchain infrastructure project managing 4 Lux app chain EVM networks (LUX, ZOO, SPC, and Hanzo). The infrastructure includes blockchain nodes, block explorers, DeFi exchange, Graph Protocol indexers, cross-chain bridges, and IPFS storage.
|
||||
|
||||
## Architecture
|
||||
|
||||
@@ -18,8 +18,8 @@ This is a multi-blockchain infrastructure project managing 4 Lux L2 EVM networks
|
||||
| Testnet | 2 | 96368 | Dec 25, 2025 4:20 PM PDT (1766704800) |
|
||||
| Devnet | 3 | 96370 | Dec 25, 2025 4:20 PM PDT (1766704800) |
|
||||
|
||||
**L2 EVM Chain IDs** -- source of truth: NETWORKS.yaml
|
||||
| L2 EVM | Coin | Mainnet | Testnet | Devnet |
|
||||
**app chain EVM Chain IDs** -- source of truth: NETWORKS.yaml
|
||||
| app chain EVM | Coin | Mainnet | Testnet | Devnet |
|
||||
|--------|------|---------|---------|--------|
|
||||
| Zoo | ZOO | 200200 | 200201 | 200202 |
|
||||
| Hanzo | AI | 36963 | 36964 | 36964 |
|
||||
@@ -48,7 +48,7 @@ Note: Hanzo coin is **AI**, not HANZO. Hanzo testnet/devnet share chain ID 36964
|
||||
/home/z/work/lux
|
||||
├── node/ # Lux Network node
|
||||
├── geth/ # C-Chain implementation (formerly coreth)
|
||||
├── evm/ # L2 EVM implementation (upstream subnet-evm fork)
|
||||
├── evm/ # App chain EVM implementation
|
||||
├── cli/ # Lux CLI for managing networks
|
||||
├── vms/ # Virtual machine implementations
|
||||
│ └── cchainvm/ # C-Chain VM utilities
|
||||
@@ -214,7 +214,7 @@ The node implements Proof of Authority consensus with:
|
||||
# Fix all RPC endpoints
|
||||
./fix_all_rpc_endpoints.sh
|
||||
|
||||
# Deploy new L2 EVM
|
||||
# Deploy new app chain EVM
|
||||
./deploy-hanzo-network.sh
|
||||
|
||||
# Start Q-Chain network
|
||||
@@ -348,7 +348,7 @@ pnpm exec playwright test
|
||||
| 13-bridge-mpc | 15 | Bridge + MPC |
|
||||
| 14-dex-contracts | 19 | DEX contract interactions |
|
||||
| 15-nft-marketplace | 11 | NFT marketplace |
|
||||
| 16-subnet-chains | 18 | L2 EVM chain operations |
|
||||
| 16-app-chains | 18 | App chain operations |
|
||||
| 17-governance | 11 | Governance flow |
|
||||
| 18-broker | 35 | Broker operations |
|
||||
| 19-broker-deep | 97 | Broker deep tests |
|
||||
|
||||
+7
-7
@@ -32,7 +32,7 @@ lux:
|
||||
p-chain:
|
||||
name: "P-Chain"
|
||||
vm: platformvm
|
||||
purpose: "Validators, staking, L2 EVM provisioning"
|
||||
purpose: "Validators, staking, app chain EVM provisioning"
|
||||
|
||||
d-chain:
|
||||
name: "D-Chain"
|
||||
@@ -95,12 +95,12 @@ lux:
|
||||
status: built, not yet deployed
|
||||
|
||||
# ═══════════════════════════════════════════════════════════════════════
|
||||
# L2 EVM Networks
|
||||
# Application Chain EVM Networks
|
||||
# ═══════════════════════════════════════════════════════════════════════
|
||||
|
||||
zoo:
|
||||
name: "Zoo Network"
|
||||
type: subnet
|
||||
type: chain
|
||||
coin: ZOO
|
||||
website: zoo.network
|
||||
exchange: zoo.exchange
|
||||
@@ -115,7 +115,7 @@ zoo:
|
||||
|
||||
hanzo:
|
||||
name: "Hanzo Network"
|
||||
type: subnet
|
||||
type: chain
|
||||
coin: AI # NOT "HANZO" — coin is AI
|
||||
website: hanzo.ai
|
||||
exchange: lux.exchange # trades on Lux DEX
|
||||
@@ -130,7 +130,7 @@ hanzo:
|
||||
|
||||
spc:
|
||||
name: "SPC Network"
|
||||
type: subnet
|
||||
type: chain
|
||||
coin: SPC
|
||||
website: sparklepony.club
|
||||
exchange: lux.exchange # trades on Lux DEX
|
||||
@@ -143,7 +143,7 @@ spc:
|
||||
|
||||
pars:
|
||||
name: "Pars Network"
|
||||
type: subnet
|
||||
type: chain
|
||||
coin: PARS
|
||||
website: pars.network
|
||||
exchange: pars.market # own white-label DEX
|
||||
@@ -160,7 +160,7 @@ pars:
|
||||
purpose: "Session management"
|
||||
status: planned
|
||||
|
||||
# Tenant L2 EVMs are configured by the tenant operator (e.g. liquid-operator),
|
||||
# Tenant app chain EVMs are configured by the tenant operator (e.g. liquid-operator),
|
||||
# not declared in upstream NETWORKS.yaml. Each tenant ships its own
|
||||
# NETWORKS.yaml inside its own ops repo.
|
||||
|
||||
|
||||
@@ -37,9 +37,9 @@ e2e/ Playwright E2E tests (~488 cases)
|
||||
|
||||
Mainnet runs 15 validators. Each cluster runs luxd StatefulSets.
|
||||
|
||||
### L2 EVM Chain IDs
|
||||
### app chain EVM Chain IDs
|
||||
|
||||
| L2 EVM | Coin | Mainnet | Testnet | Devnet |
|
||||
| app chain EVM | Coin | Mainnet | Testnet | Devnet |
|
||||
|--------|------|---------|---------|--------|
|
||||
| Zoo | ZOO | 200200 | 200201 | 200202 |
|
||||
| Hanzo | AI | 36963 | 36964 | 36964 |
|
||||
|
||||
+7
-7
@@ -1,5 +1,5 @@
|
||||
# Docker-based Lux Universe Deployment
|
||||
# 5 nodes validate everything: LUX mainnet + all L2 subnets (Hanzo, ZOO, SPC)
|
||||
# 5 nodes validate everything: LUX mainnet + all app chains (Hanzo, ZOO, SPC)
|
||||
|
||||
.PHONY: all up down clean logs status test help
|
||||
|
||||
@@ -116,13 +116,13 @@ init-db:
|
||||
docker exec lux-postgres psql -U postgres -c "CREATE DATABASE explorer_zoo IF NOT EXISTS;"
|
||||
docker exec lux-postgres psql -U postgres -c "CREATE DATABASE explorer_spc IF NOT EXISTS;"
|
||||
|
||||
# Deploy L2 subnets
|
||||
deploy-l2s:
|
||||
@echo "Deploying L2 Subnets on Lux mainnet..."
|
||||
@echo "Creating Hanzo subnet..."
|
||||
# Deploy app chains
|
||||
deploy-chains:
|
||||
@echo "Deploying app chains on Lux mainnet..."
|
||||
@echo "Creating Hanzo chain..."
|
||||
@curl -X POST --data '{ \
|
||||
"jsonrpc": "2.0", \
|
||||
"method": "platform.createSubnet", \
|
||||
"method": "platform.createChain", \
|
||||
"params": { \
|
||||
"controlKeys": ["P-lux1q2z72rl2yqrfhkw8xfgn9qvxh7xr4n3zpjqkqw"], \
|
||||
"threshold": 1 \
|
||||
@@ -130,6 +130,6 @@ deploy-l2s:
|
||||
"id": 1 \
|
||||
}' -H 'content-type:application/json' http://localhost:9650/ext/P
|
||||
@echo ""
|
||||
@echo "✅ L2 Subnets deployed!"
|
||||
@echo "App chains deployed!"
|
||||
|
||||
.SILENT: help status test
|
||||
@@ -123,7 +123,7 @@ start_cluster() {
|
||||
mkdir -p $node_dir/{data,logs,db,plugins}
|
||||
|
||||
# Copy EVM plugin
|
||||
cp $BASE_DIR/evm/build/subnet-evm $node_dir/plugins/srEXiWaHuhNyGwPUi444Tu47ZEDwxTWrbQiuD7FmgSAQ6X7Dy 2>/dev/null || true
|
||||
cp $BASE_DIR/evm/build/evm $node_dir/plugins/srEXiWaHuhNyGwPUi444Tu47ZEDwxTWrbQiuD7FmgSAQ6X7Dy 2>/dev/null || true
|
||||
|
||||
# Start node
|
||||
screen -dmS $network_type-node$i $BASE_DIR/node/luxd \
|
||||
@@ -161,18 +161,16 @@ start_cluster "testnet" $TESTNET_ID 9750 "/tmp/lux-testnet"
|
||||
echo -e "${YELLOW}Waiting for nodes to initialize...${NC}"
|
||||
sleep 10
|
||||
|
||||
# Deploy L2 subnets on mainnet
|
||||
echo -e "${BLUE}Deploying L2 subnets on Mainnet...${NC}"
|
||||
for subnet in hanzo zoo spc; do
|
||||
echo " Deploying $subnet..."
|
||||
# TODO: Use actual subnet deployment API calls
|
||||
# Deploy app chains on mainnet
|
||||
echo -e "${BLUE}Deploying app chains on Mainnet...${NC}"
|
||||
for chain in hanzo zoo spc; do
|
||||
echo " Deploying $chain..."
|
||||
done
|
||||
|
||||
# Deploy L2 subnets on testnet
|
||||
echo -e "${BLUE}Deploying L2 subnets on Testnet...${NC}"
|
||||
for subnet in hanzo zoo spc; do
|
||||
echo " Deploying $subnet..."
|
||||
# TODO: Use actual subnet deployment API calls
|
||||
# Deploy app chains on testnet
|
||||
echo -e "${BLUE}Deploying app chains on Testnet...${NC}"
|
||||
for chain in hanzo zoo spc; do
|
||||
echo " Deploying $chain..."
|
||||
done
|
||||
|
||||
echo ""
|
||||
|
||||
@@ -89,9 +89,9 @@ echo ""
|
||||
|
||||
check_chain "LUX Network" 9650 96369 "LUX" "Primary"
|
||||
check_chain "LUX Network (Alt)" 9630 96369 "LUX" "Primary"
|
||||
check_chain "Hanzo AI" 9660 36963 "AI" "L2 Subnet"
|
||||
check_chain "Zoo Network" 9670 200200 "ZOO" "L2 Subnet"
|
||||
check_chain "SPC Network" 9680 36911 "SPC" "L2 Subnet"
|
||||
check_chain "Hanzo AI" 9660 36963 "AI" "App Chain"
|
||||
check_chain "Zoo Network" 9670 200200 "ZOO" "App Chain"
|
||||
check_chain "SPC Network" 9680 36911 "SPC" "App Chain"
|
||||
|
||||
# TESTNET CHAINS
|
||||
echo -e "${BLUE}══════════════════════════════${NC}"
|
||||
@@ -100,9 +100,9 @@ echo -e "${BLUE}═════════════════════
|
||||
echo ""
|
||||
|
||||
check_chain "LUX Testnet" 9750 96368 "tLUX" "Primary"
|
||||
check_chain "Hanzo AI Test" 9760 36962 "tAI" "L2 Subnet"
|
||||
check_chain "Zoo Testnet" 9770 200201 "tZOO" "L2 Subnet"
|
||||
check_chain "SPC Testnet" 9780 36912 "tSPC" "L2 Subnet"
|
||||
check_chain "Hanzo AI Test" 9760 36962 "tAI" "App Chain"
|
||||
check_chain "Zoo Testnet" 9770 200201 "tZOO" "App Chain"
|
||||
check_chain "SPC Testnet" 9780 36912 "tSPC" "App Chain"
|
||||
|
||||
# Summary
|
||||
echo -e "${BLUE}══════════════════════════════${NC}"
|
||||
@@ -118,8 +118,8 @@ echo ""
|
||||
echo -e "${YELLOW}Architecture:${NC}"
|
||||
echo "• 1 Primary Network (LUX)"
|
||||
echo "• 5 Validator Nodes per network"
|
||||
echo "• 3 L2 EVM Subnets (Hanzo, Zoo, SPC)"
|
||||
echo "• All L2s run on top of LUX mainnet"
|
||||
echo "• 3 EVM App Chains (Hanzo, Zoo, SPC)"
|
||||
echo "• All app chains run on top of LUX mainnet"
|
||||
echo ""
|
||||
|
||||
echo -e "${YELLOW}Token Allocations:${NC}"
|
||||
|
||||
+11
-11
@@ -28,9 +28,9 @@ luxd-3: NodeID-8mY2fhUehN27v3LCU84BnnKEoeRfd2weC
|
||||
luxd-4: NodeID-4smuFz5Z9cm8BEyQU1oPQ9nwgXyMgaNqu
|
||||
```
|
||||
|
||||
## L2 EVM Blockchains
|
||||
## app chain EVM Blockchains
|
||||
|
||||
### Mainnet L2 EVMs
|
||||
### Mainnet app chain EVMs
|
||||
|
||||
| Chain | EVM Chain ID | VMID | Blockchain ID |
|
||||
|-------|-------------|-----------|---------------|
|
||||
@@ -39,7 +39,7 @@ luxd-4: NodeID-4smuFz5Z9cm8BEyQU1oPQ9nwgXyMgaNqu
|
||||
| SPC | 36911 | 2NMT8GmbBktdgGAMwET4c5N3y2Ui2s4ixNThNV72oMf1jVvZgb | 2UiqUeusJ3QJenHfXbJvoz9m2BL3sd14hrohaX1HfxtRnadMob |
|
||||
| Pars | 36900 | 2Fpjvv3eMEtCUxQqLqckbnvhhQwyyP54UF5rvh7UvLkSwsnnW3 | 2ntyMHLYEeoaK2RePDJbFsKGQBsKFgZTWEWNCdkD74bfGEZtLF |
|
||||
|
||||
### Testnet L2 EVMs
|
||||
### Testnet app chain EVMs
|
||||
|
||||
| Chain | EVM Chain ID | VMID | Blockchain ID |
|
||||
|-------|-------------|-----------|---------------|
|
||||
@@ -48,7 +48,7 @@ luxd-4: NodeID-4smuFz5Z9cm8BEyQU1oPQ9nwgXyMgaNqu
|
||||
| SPC | 36910 | CKWu2nVKzKHsuNQD4JCUexTbi4AkNtz5bsVcpr2TKp3CsqPTT | 2M8UANaVEoJxWAcCCcdvPFKH2oB7LmcJ6B7c2pxkY5U8gadDug |
|
||||
| Pars | 36901 | 2iuHYwWxtxWMqaFpjBwRPKX4WY5LRrVqkWQj2YGG1qjXdjXduj | prSSgAfKgpVfKxAG4ZAH9fibaCYpkDjK3z2ud9FgpmvQpw9cy |
|
||||
|
||||
### Devnet L2 EVMs
|
||||
### Devnet app chain EVMs
|
||||
|
||||
| Chain | EVM Chain ID | VMID | Blockchain ID |
|
||||
|-------|-------------|-----------|---------------|
|
||||
@@ -79,7 +79,7 @@ All deployer keys stored at `kms.hanzo.ai` (Infisical-compatible):
|
||||
| `/lux/keys/accounts/ACCOUNT_N_*` | 100 accounts (ADDRESS, PRIVATE_KEY, PATH) |
|
||||
| `/lux/keys/fee-reserve/FEE_N_*` | 5 fee reserve keys (derived via keccak256) |
|
||||
| `/lux/keys/ROLES` | Role-to-address mapping JSON |
|
||||
| `/lux/networks/NETWORK_CONFIG` | All network + L2 EVM configuration JSON |
|
||||
| `/lux/networks/NETWORK_CONFIG` | All network + app chain EVM configuration JSON |
|
||||
|
||||
**Treasury**: `0x9011E888251AB053B7bD1cdB598Db4f9DEd94714` (index 0, all chains)
|
||||
|
||||
@@ -195,7 +195,7 @@ done
|
||||
|
||||
### Re-Genesis Procedure (Full Reset)
|
||||
```bash
|
||||
# CAUTION: Destroys all chain state. Must re-import RLP blocks and re-deploy L2 EVMs.
|
||||
# CAUTION: Destroys all chain state. Must re-import RLP blocks and re-deploy app chain EVMs.
|
||||
|
||||
# 1. Stop all pods
|
||||
kubectl scale statefulset luxd --replicas=0 -n lux-mainnet
|
||||
@@ -210,7 +210,7 @@ done
|
||||
# 3. Update genesis ConfigMap, then scale back up
|
||||
kubectl scale statefulset luxd --replicas=5 -n lux-mainnet
|
||||
|
||||
# 4. Re-deploy L2 EVMs
|
||||
# 4. Re-deploy app chain EVMs
|
||||
unset LUX_MNEMONIC && LUX_KEY_NAME=fee0 \
|
||||
go run ./wallet/network/primary/examples/deploy-subnets/ --network=mainnet --skip-validators
|
||||
|
||||
@@ -274,9 +274,9 @@ kubectl logs luxd-0 -n lux-mainnet -c luxd | grep "chainDataDir"
|
||||
| VM | ID |
|
||||
|----|-----|
|
||||
| C-chain EVM | `mgj786NP7uDwBCcq6YwThhaN8FLyybkCa4zBWTQbNgmK6k9A6` |
|
||||
| L2 EVM (upstream subnet-evm) | `ag3GReYPNuSR17rUP8acMdZipQBikdXNRKDyFszAysmy3vDXE` |
|
||||
| App-chain EVM | `ag3GReYPNuSR17rUP8acMdZipQBikdXNRKDyFszAysmy3vDXE` |
|
||||
|
||||
Both use the same binary, different VMID. Init container copies C-chain plugin as L2 EVM plugin.
|
||||
Both use the same binary, different VMID. Init container copies C-chain plugin as app-chain plugin.
|
||||
|
||||
## BLS Signer Keys
|
||||
|
||||
@@ -292,7 +292,7 @@ Both use the same binary, different VMID. Init container copies C-chain plugin a
|
||||
- Derived: `keccak256("fee-reserve:" || validatorPrivKey)` per validator
|
||||
- Stored in KMS at `/lux/keys/fee-reserve/`
|
||||
- 10,000 LUX per key, locktime Jan 1 2020 (immediately spendable)
|
||||
- Deploy L2 EVMs: `unset LUX_MNEMONIC && LUX_KEY_NAME=fee0 go run ./wallet/network/primary/examples/deploy-subnets/`
|
||||
- Deploy app chain EVMs: `unset LUX_MNEMONIC && LUX_KEY_NAME=fee0 go run ./wallet/network/primary/examples/deploy-subnets/`
|
||||
- **CRITICAL**: `LUX_MNEMONIC` env var takes PRIORITY over `LUX_KEY_NAME` - must unset it
|
||||
|
||||
## Image History
|
||||
@@ -302,5 +302,5 @@ Both use the same binary, different VMID. Init container copies C-chain plugin a
|
||||
| `luxd-v1.23.15-debug` | Current mainnet - dialEndpointOnly fix, peer debug (cleaned) | 2026-02-19 |
|
||||
| `luxd-v1.23.14` | Current testnet/devnet - bootstrap-nodes endpoint-only fix | 2026-02-14 |
|
||||
| `luxd-v1.23.13` | track-chains blockchain→VMID resolution | 2026-02-14 |
|
||||
| `luxd-v1.23.12` | Fee reserve genesis, all L2 EVMs deployed | 2026-02-14 |
|
||||
| `luxd-v1.23.12` | Fee reserve genesis, all app chain EVMs deployed | 2026-02-14 |
|
||||
| `luxd-v1.23.11` | CancunTime fix | 2026-02-10 |
|
||||
|
||||
@@ -127,11 +127,11 @@ test.describe('Validator Network', () => {
|
||||
}
|
||||
})
|
||||
|
||||
test('>= 3 blockchains registered (P/C/X + subnets)', async ({ request }) => {
|
||||
test('>= 3 blockchains registered (P/C/X + app chains)', async ({ request }) => {
|
||||
const chains = await getBlockchains(request, urls.rpcPlatform) as { name: string }[]
|
||||
const names = chains.map(c => c.name)
|
||||
console.log(` blockchains: ${chains.length} (${names.join(', ')})`)
|
||||
// Primary chains: D(P), C, X. Subnets tracked via separate subnet IDs.
|
||||
// Primary chains: D(P), C, X. App chains tracked via separate net IDs.
|
||||
expect(chains.length).toBeGreaterThanOrEqual(3)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -153,7 +153,7 @@ test.describe('Local Validator — P-Chain Validators', () => {
|
||||
expect(validators.length).toBeGreaterThanOrEqual(1)
|
||||
})
|
||||
|
||||
test('subnet chains are deployed', async ({ request }) => {
|
||||
test('app chains are deployed', async ({ request }) => {
|
||||
const status = await httpStatus(request, urls.rpcHealth, 5_000)
|
||||
if (status === 0) test.skip(true, 'Local node not running')
|
||||
|
||||
|
||||
+14
-14
@@ -60,7 +60,7 @@ test.describe('Staking RPC — Validators At Height', () => {
|
||||
const result = await rpcCall(
|
||||
request, urls.rpcPlatform, 'platform.getValidatorsAt', {
|
||||
height: heightResult.height,
|
||||
subnetID: '',
|
||||
netID: '',
|
||||
},
|
||||
) as { validators: Record<string, unknown> }
|
||||
const validatorCount = Object.keys(result.validators || {}).length
|
||||
@@ -147,24 +147,24 @@ test.describe('Staking RPC — Staking Period Validation', () => {
|
||||
})
|
||||
})
|
||||
|
||||
// ── Subnet Validators ──────────────────────────────────────────────
|
||||
test.describe('Staking RPC — Subnet Validators', () => {
|
||||
test('can query subnet validators (if subnets exist)', async ({ request }) => {
|
||||
// Get list of subnets
|
||||
// ── Chain Validators ──────────────────────────────────────────────
|
||||
test.describe('Staking RPC — Chain Validators', () => {
|
||||
test('can query chain validators (if chains exist)', async ({ request }) => {
|
||||
// Get list of nets
|
||||
try {
|
||||
const result = await rpcCall(
|
||||
request, urls.rpcPlatform, 'platform.getSubnets', { ids: [] },
|
||||
) as { subnets: { id: string; controlKeys: string[]; threshold: string }[] }
|
||||
console.log(` Subnets: ${result.subnets?.length ?? 0}`)
|
||||
if (result.subnets && result.subnets.length > 0) {
|
||||
for (const subnet of result.subnets.slice(0, 3)) {
|
||||
console.log(` Subnet ${subnet.id}: threshold=${subnet.threshold}`)
|
||||
request, urls.rpcPlatform, 'platform.getNets', { ids: [] },
|
||||
) as { nets: { id: string; controlKeys: string[]; threshold: string }[] }
|
||||
console.log(` Nets: ${result.nets?.length ?? 0}`)
|
||||
if (result.nets && result.nets.length > 0) {
|
||||
for (const net of result.nets.slice(0, 3)) {
|
||||
console.log(` Net ${net.id}: threshold=${net.threshold}`)
|
||||
}
|
||||
}
|
||||
expect(result.subnets).toBeDefined()
|
||||
expect(result.nets).toBeDefined()
|
||||
} catch (err: unknown) {
|
||||
const msg = err instanceof Error ? err.message : String(err)
|
||||
console.log(` getSubnets: ${msg}`)
|
||||
console.log(` getNets: ${msg}`)
|
||||
}
|
||||
})
|
||||
})
|
||||
@@ -174,7 +174,7 @@ test.describe('Staking RPC — Total Stake', () => {
|
||||
test('platform.getTotalStake returns > 0', async ({ request }) => {
|
||||
try {
|
||||
const result = await rpcCall(
|
||||
request, urls.rpcPlatform, 'platform.getTotalStake', { subnetID: '' },
|
||||
request, urls.rpcPlatform, 'platform.getTotalStake', { netID: '' },
|
||||
) as { stake: string; weight: string }
|
||||
const stake = BigInt(result.stake || result.weight || '0')
|
||||
console.log(` Total stake: ${stake}`)
|
||||
|
||||
@@ -9,11 +9,11 @@ const urls = getUrls()
|
||||
const chainIds = getChainIds()
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Subnet / Chain Health — verify each subnet C-Chain is alive and producing
|
||||
// App Chain Health — verify each app chain C-Chain is alive and producing
|
||||
// ---------------------------------------------------------------------------
|
||||
|
||||
// Subnet RPC endpoints (production)
|
||||
const SUBNET_RPCS = isLocal()
|
||||
// App chain RPC endpoints (production)
|
||||
const APPCHAIN_RPCS = isLocal()
|
||||
? {
|
||||
zoo: urls.rpcZoo,
|
||||
}
|
||||
@@ -25,12 +25,12 @@ const SUBNET_RPCS = isLocal()
|
||||
}
|
||||
|
||||
// ── Zoo C-Chain ────────────────────────────────────────────────────
|
||||
test.describe('Subnet Chains — Zoo', () => {
|
||||
test.describe('App Chains — Zoo', () => {
|
||||
test('Zoo C-Chain RPC responds', async ({ request }) => {
|
||||
let block = 0
|
||||
for (let attempt = 0; attempt < 3; attempt++) {
|
||||
try {
|
||||
block = await ethBlockNumber(request, SUBNET_RPCS.zoo)
|
||||
block = await ethBlockNumber(request, APPCHAIN_RPCS.zoo)
|
||||
break
|
||||
} catch {
|
||||
if (attempt < 2) await new Promise(r => setTimeout(r, 1000))
|
||||
@@ -42,7 +42,7 @@ test.describe('Subnet Chains — Zoo', () => {
|
||||
|
||||
test('Zoo C-Chain returns correct chain ID', async ({ request }) => {
|
||||
try {
|
||||
const cid = await ethChainId(request, SUBNET_RPCS.zoo)
|
||||
const cid = await ethChainId(request, APPCHAIN_RPCS.zoo)
|
||||
console.log(` Zoo chain ID: ${cid} (expected: ${chainIds.zoo})`)
|
||||
expect(cid).toBe(chainIds.zoo)
|
||||
} catch {
|
||||
@@ -55,7 +55,7 @@ test.describe('Subnet Chains — Zoo', () => {
|
||||
let block2 = 0
|
||||
for (let attempt = 0; attempt < 3; attempt++) {
|
||||
try {
|
||||
block1 = await ethBlockNumber(request, SUBNET_RPCS.zoo)
|
||||
block1 = await ethBlockNumber(request, APPCHAIN_RPCS.zoo)
|
||||
break
|
||||
} catch {
|
||||
if (attempt < 2) await new Promise(r => setTimeout(r, 1000))
|
||||
@@ -64,7 +64,7 @@ test.describe('Subnet Chains — Zoo', () => {
|
||||
await new Promise(r => setTimeout(r, 3000))
|
||||
for (let attempt = 0; attempt < 3; attempt++) {
|
||||
try {
|
||||
block2 = await ethBlockNumber(request, SUBNET_RPCS.zoo)
|
||||
block2 = await ethBlockNumber(request, APPCHAIN_RPCS.zoo)
|
||||
break
|
||||
} catch {
|
||||
if (attempt < 2) await new Promise(r => setTimeout(r, 1000))
|
||||
@@ -76,26 +76,26 @@ test.describe('Subnet Chains — Zoo', () => {
|
||||
})
|
||||
|
||||
// ── Hanzo C-Chain ──────────────────────────────────────────────────
|
||||
test.describe('Subnet Chains — Hanzo', () => {
|
||||
test.describe('App Chains — Hanzo', () => {
|
||||
test('Hanzo C-Chain RPC responds', async ({ request }) => {
|
||||
if (!('hanzo' in SUBNET_RPCS)) {
|
||||
if (!('hanzo' in APPCHAIN_RPCS)) {
|
||||
test.skip(true, 'Hanzo RPC not configured in local mode')
|
||||
}
|
||||
const rpc = (SUBNET_RPCS as Record<string, string>).hanzo
|
||||
const rpc = (APPCHAIN_RPCS as Record<string, string>).hanzo
|
||||
try {
|
||||
const block = await ethBlockNumber(request, rpc)
|
||||
console.log(` Hanzo C-Chain block: ${block.toLocaleString()}`)
|
||||
expect(block).toBeGreaterThan(0)
|
||||
} catch {
|
||||
console.log(' Hanzo C-Chain RPC not reachable (subnet may not be deployed yet)')
|
||||
console.log(' Hanzo C-Chain RPC not reachable (chain may not be deployed yet)')
|
||||
}
|
||||
})
|
||||
|
||||
test('Hanzo C-Chain returns correct chain ID', async ({ request }) => {
|
||||
if (!('hanzo' in SUBNET_RPCS)) {
|
||||
if (!('hanzo' in APPCHAIN_RPCS)) {
|
||||
test.skip(true, 'Hanzo RPC not configured in local mode')
|
||||
}
|
||||
const rpc = (SUBNET_RPCS as Record<string, string>).hanzo
|
||||
const rpc = (APPCHAIN_RPCS as Record<string, string>).hanzo
|
||||
try {
|
||||
const cid = await ethChainId(request, rpc)
|
||||
console.log(` Hanzo chain ID: ${cid} (expected: ${chainIds.hanzo})`)
|
||||
@@ -107,26 +107,26 @@ test.describe('Subnet Chains — Hanzo', () => {
|
||||
})
|
||||
|
||||
// ── SPC C-Chain ────────────────────────────────────────────────────
|
||||
test.describe('Subnet Chains — SPC', () => {
|
||||
test.describe('App Chains — SPC', () => {
|
||||
test('SPC C-Chain RPC responds', async ({ request }) => {
|
||||
if (!('spc' in SUBNET_RPCS)) {
|
||||
if (!('spc' in APPCHAIN_RPCS)) {
|
||||
test.skip(true, 'SPC RPC not configured in local mode')
|
||||
}
|
||||
const rpc = (SUBNET_RPCS as Record<string, string>).spc
|
||||
const rpc = (APPCHAIN_RPCS as Record<string, string>).spc
|
||||
try {
|
||||
const block = await ethBlockNumber(request, rpc)
|
||||
console.log(` SPC C-Chain block: ${block.toLocaleString()}`)
|
||||
expect(block).toBeGreaterThan(0)
|
||||
} catch {
|
||||
console.log(' SPC C-Chain RPC not reachable (subnet may not be deployed yet)')
|
||||
console.log(' SPC C-Chain RPC not reachable (chain may not be deployed yet)')
|
||||
}
|
||||
})
|
||||
|
||||
test('SPC C-Chain returns correct chain ID', async ({ request }) => {
|
||||
if (!('spc' in SUBNET_RPCS)) {
|
||||
if (!('spc' in APPCHAIN_RPCS)) {
|
||||
test.skip(true, 'SPC RPC not configured in local mode')
|
||||
}
|
||||
const rpc = (SUBNET_RPCS as Record<string, string>).spc
|
||||
const rpc = (APPCHAIN_RPCS as Record<string, string>).spc
|
||||
try {
|
||||
const cid = await ethChainId(request, rpc)
|
||||
console.log(` SPC chain ID: ${cid} (expected: ${chainIds.spc})`)
|
||||
@@ -138,26 +138,26 @@ test.describe('Subnet Chains — SPC', () => {
|
||||
})
|
||||
|
||||
// ── Pars C-Chain ───────────────────────────────────────────────────
|
||||
test.describe('Subnet Chains — Pars', () => {
|
||||
test.describe('App Chains — Pars', () => {
|
||||
test('Pars C-Chain RPC responds', async ({ request }) => {
|
||||
if (!('pars' in SUBNET_RPCS)) {
|
||||
if (!('pars' in APPCHAIN_RPCS)) {
|
||||
test.skip(true, 'Pars RPC not configured in local mode')
|
||||
}
|
||||
const rpc = (SUBNET_RPCS as Record<string, string>).pars
|
||||
const rpc = (APPCHAIN_RPCS as Record<string, string>).pars
|
||||
try {
|
||||
const block = await ethBlockNumber(request, rpc)
|
||||
console.log(` Pars C-Chain block: ${block.toLocaleString()}`)
|
||||
expect(block).toBeGreaterThan(0)
|
||||
} catch {
|
||||
console.log(' Pars C-Chain RPC not reachable (subnet may not be deployed yet)')
|
||||
console.log(' Pars C-Chain RPC not reachable (chain may not be deployed yet)')
|
||||
}
|
||||
})
|
||||
|
||||
test('Pars C-Chain returns correct chain ID', async ({ request }) => {
|
||||
if (!('pars' in SUBNET_RPCS)) {
|
||||
if (!('pars' in APPCHAIN_RPCS)) {
|
||||
test.skip(true, 'Pars RPC not configured in local mode')
|
||||
}
|
||||
const rpc = (SUBNET_RPCS as Record<string, string>).pars
|
||||
const rpc = (APPCHAIN_RPCS as Record<string, string>).pars
|
||||
try {
|
||||
const cid = await ethChainId(request, rpc)
|
||||
console.log(` Pars chain ID: ${cid} (expected: ${chainIds.pars})`)
|
||||
@@ -168,9 +168,9 @@ test.describe('Subnet Chains — Pars', () => {
|
||||
})
|
||||
})
|
||||
|
||||
// ── Cross-Subnet Block Production ──────────────────────────────────
|
||||
test.describe('Subnet Chains — Cross-Subnet Block Comparison', () => {
|
||||
test('all subnet explorers report blocks', async ({ request }) => {
|
||||
// ── Cross-Chain Block Production ──────────────────────────────────
|
||||
test.describe('App Chains — Cross-Chain Block Comparison', () => {
|
||||
test('all app chain explorers report blocks', async ({ request }) => {
|
||||
const explorers = [
|
||||
{ name: 'Zoo', api: urls.apiExploreZoo },
|
||||
{ name: 'Hanzo', api: urls.apiExploreHanzo },
|
||||
@@ -192,15 +192,15 @@ test.describe('Subnet Chains — Cross-Subnet Block Comparison', () => {
|
||||
})
|
||||
|
||||
// ── Registered Blockchains ─────────────────────────────────────────
|
||||
test.describe('Subnet Chains — Registered Blockchains', () => {
|
||||
test('P-Chain lists all expected subnet chains', async ({ request }) => {
|
||||
test.describe('App Chains — Registered Blockchains', () => {
|
||||
test('P-Chain lists all expected chains', async ({ request }) => {
|
||||
const result = await rpcCall(
|
||||
request, urls.rpcPlatform, 'platform.getBlockchains', {},
|
||||
) as { blockchains: { name: string; id: string; subnetID: string; vmID: string }[] }
|
||||
) as { blockchains: { name: string; id: string; netID: string; vmID: string }[] }
|
||||
const chains = result.blockchains
|
||||
console.log(` Registered blockchains: ${chains.length}`)
|
||||
for (const chain of chains) {
|
||||
console.log(` ${chain.name}: id=${chain.id} subnet=${chain.subnetID}`)
|
||||
console.log(` ${chain.name}: id=${chain.id} net=${chain.netID}`)
|
||||
}
|
||||
// At minimum: C-Chain, X-Chain, and D (P-Chain internal)
|
||||
expect(chains.length).toBeGreaterThanOrEqual(3)
|
||||
+3
-3
@@ -4,7 +4,7 @@ This document describes how to bring up a complete Lux-ecosystem deploy
|
||||
that hosts:
|
||||
|
||||
- **Lux Mainnet validators** (Lux primary network, network ID 1)
|
||||
- **L2 EVM chains**: Zoo (200200), Hanzo (36963), Pars (494949), SPC (36911)
|
||||
- **app chain EVM chains**: Zoo (200200), Hanzo (36963), Pars (494949), SPC (36911)
|
||||
- **Per-chain backends**: KrakenD gateway + indexer + GraphQL subgraph + explorer frontend
|
||||
- **White-label DEX SPAs**: `zoo.exchange`, `hanzo.exchange`, `pars.market`, `lux.exchange` — all running the canonical `@luxfi/exchange` source with their own brand, chain default, and `api.<their-domain>` backend
|
||||
- **Cross-chain bridge**: `bridge.lux.network` + per-brand white-label deployments via `~/work/lux/bridge`
|
||||
@@ -79,7 +79,7 @@ that hosts:
|
||||
▼ ▼ ▼
|
||||
┌──────────────────────────────────────────────────────────┐
|
||||
│ luxd validators (StatefulSet, 5 replicas) │
|
||||
│ Primary network + all L2 EVMs (Zoo, Hanzo, Pars, SPC) │
|
||||
│ Primary network + all app chain EVMs (Zoo, Hanzo, Pars, SPC) │
|
||||
│ /ext/bc/C/rpc → Lux C-Chain (96369) │
|
||||
│ /ext/bc/zoo/rpc → Zoo (200200) │
|
||||
│ /ext/bc/hanzo/rpc → Hanzo (36963) │
|
||||
@@ -105,7 +105,7 @@ Each chain runs ONE backend service per concern:
|
||||
|
||||
- Single container, port 8090
|
||||
- Combines `ghcr.io/luxfi/indexer` (chain data) + `ghcr.io/luxfi/graph` (DeFi events, GraphQL endpoint at `/v1/graphql`) + `ghcr.io/luxfi/explore` (Next.js UI)
|
||||
- `chains.yaml` ConfigMap declares which chains it indexes; default tracks all primary + L2 EVM chains
|
||||
- `chains.yaml` ConfigMap declares which chains it indexes; default tracks all primary + app chain EVM chains
|
||||
- Storage: per-chain SQLite at `/data/<chain>/index.db` (WAL mode)
|
||||
- Optional snapshot replication to `s3.lux.network`
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
###############################################################################
|
||||
# pars-mainnet env: Pars Market — Lux Uniswap fork pinned to Pars L2 EVM
|
||||
# pars-mainnet env: Pars Market — Lux Uniswap fork pinned to Pars app chain EVM
|
||||
# (chainID 494949, treasury 7B PARS).
|
||||
###############################################################################
|
||||
apiVersion: v1
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
###############################################################################
|
||||
# Pars Market — Lux Uniswap fork pinned to Pars L2 EVM (chainID 494949).
|
||||
# Pars Market — Lux Uniswap fork pinned to Pars app chain EVM (chainID 494949).
|
||||
#
|
||||
# Standalone overlay (no inheritance from ../../base): pars needs an extra
|
||||
# /brand ConfigMap mount and a cp step in the init script that the base
|
||||
|
||||
@@ -13,7 +13,7 @@ metadata:
|
||||
# All new tx/block bytes on devnet are written at wire-version=1 from
|
||||
# genesis. Devnet is no longer in the v0-post-rip limbo state.
|
||||
#
|
||||
# All 4 L2 EVMs bootstrapped via genesis/[email protected] bootstrap-l2 tool
|
||||
# All 4 app chain EVMs bootstrapped via genesis/[email protected] bootstrap-chain tool
|
||||
# (rebuilt against luxfi/node v1.28.0 wallet codec). Tool wallet was
|
||||
# previously pinned to luxfi/node v1.27.24 — pre-codec-v1 — and could
|
||||
# not decode v1-wire UTXOs ("wallet sync: unknown codec version"); the
|
||||
|
||||
@@ -3,17 +3,17 @@
|
||||
# Unified Lux Explorer — Devnet
|
||||
#
|
||||
# Single Go binary `ghcr.io/luxfi/explorer:1.2.11` that indexes every EVM
|
||||
# L2 chain on this network into per-chain SQLite databases under /data/{slug}
|
||||
# non-primary chain on this network into per-chain SQLite databases under /data/{slug}
|
||||
# and serves the embedded SPA + /v1/indexer/{slug}/* + /v1/graph/* +
|
||||
# /v1/explorer/admin/* + /v1/explorer/realtime on :8090.
|
||||
#
|
||||
# Replaces Blockscout (indexer-{slug}-indexer Deployments) + their
|
||||
# per-L2 PostgreSQL StatefulSets (indexer-{slug}-pg) + the
|
||||
# per-chain PostgreSQL StatefulSets (indexer-{slug}-pg) + the
|
||||
# lux-explorer/explorer-devnet-v2 Deployment. Postgres-free indexer.
|
||||
#
|
||||
# zoo L2 EVM is not bootstrapped on devnet luxd-* nodes (verified
|
||||
# zoo app chain EVM is not bootstrapped on devnet luxd-* nodes (verified
|
||||
# 2026-05-24: /ext/bc/zoo/rpc returns 404). Declared with enabled:false
|
||||
# until the zoo L2 EVM is tracked on devnet validators.
|
||||
# until the zoo app chain EVM is tracked on devnet validators.
|
||||
###############################################################################
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
|
||||
@@ -37,7 +37,7 @@ spec:
|
||||
imagePullPolicy: IfNotPresent
|
||||
args:
|
||||
# Public domain is used (not the in-cluster gateway DNS)
|
||||
# because KrakenD's path-rewriting routes for L2 EVM aliases
|
||||
# because KrakenD's path-rewriting routes for app chain EVM aliases
|
||||
# (zoo/hanzo/pars/spc) only fire on certain Host headers; the
|
||||
# public FQDN goes through ingress where this works cleanly.
|
||||
# Resolution stays inside DigitalOcean's network.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
###############################################################################
|
||||
# IngressRoutes: L2 EVM chain explorers (Devnet)
|
||||
# IngressRoutes: app chain EVM chain explorers (Devnet)
|
||||
#
|
||||
# Domain convention mirrors mainnet:
|
||||
# explore-{chain}-dev.lux.network -> unified explorer SPA (explorer:80)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
###############################################################################
|
||||
# Frontend ConfigMaps for L2 EVM chain explorers (Mainnet)
|
||||
# Frontend ConfigMaps for app chain EVM chain explorers (Mainnet)
|
||||
# Each chain frontend needs API host, network identity, and theme config.
|
||||
# NEXT_PUBLIC_API_HOST must be the externally-accessible API domain
|
||||
# (client-side JS makes requests to it directly).
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
---
|
||||
###############################################################################
|
||||
# Explorer backend for Lux L2 EVM chains (centralized lux-explorer namespace)
|
||||
# Explorer backend for Lux app chain EVM chains (centralized lux-explorer namespace)
|
||||
#
|
||||
# Single Go binary `ghcr.io/luxfi/explorer:1.2.1` indexing all four L2 EVM
|
||||
# Single Go binary `ghcr.io/luxfi/explorer:1.2.1` indexing all four app chain EVM
|
||||
# chains. The binary embeds indexer + GraphQL + SPA in one process, listens
|
||||
# on :8090, persists per-chain SQLite under /data/{slug}, and reads its
|
||||
# chain list from /etc/explorer/chains.yaml (ConfigMap below).
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
###############################################################################
|
||||
# Lux Explore Frontend for L2 EVM chains (Mainnet)
|
||||
# Lux Explore Frontend for app chain EVM chains (Mainnet)
|
||||
# Image: ghcr.io/luxfi/explore:0.1.0 (Next.js 14, Node 22)
|
||||
# Each chain gets a Deployment + Service, reads config from ConfigMap.
|
||||
###############################################################################
|
||||
|
||||
@@ -719,7 +719,7 @@ spec:
|
||||
targetPort: 4900
|
||||
|
||||
###############################################################################
|
||||
# Zoo L2 EVM Indexer (chain ID 200200, blockchain ID 2Y625Kvdd4wZ5LKx9kLSf1jGALyARmXVN1YsTb4F3Hzv4bPDbp)
|
||||
# Zoo app chain EVM Indexer (chain ID 200200, blockchain ID 2Y625Kvdd4wZ5LKx9kLSf1jGALyARmXVN1YsTb4F3Hzv4bPDbp)
|
||||
###############################################################################
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
@@ -789,7 +789,7 @@ spec:
|
||||
targetPort: 4000
|
||||
|
||||
###############################################################################
|
||||
# Hanzo L2 EVM Indexer (chain ID 36963, blockchain ID 2GiQb73CeJESjc4omFv2YtQHZrRgJf25NXPzAr5J6UNHRcDV2F)
|
||||
# Hanzo app chain EVM Indexer (chain ID 36963, blockchain ID 2GiQb73CeJESjc4omFv2YtQHZrRgJf25NXPzAr5J6UNHRcDV2F)
|
||||
###############################################################################
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
@@ -859,7 +859,7 @@ spec:
|
||||
targetPort: 4000
|
||||
|
||||
###############################################################################
|
||||
# SPC L2 EVM Indexer (chain ID 36911, blockchain ID rtjwvtE1tEvrokmpeYdTq7b2zqZgmybKwR5MLjKMGAR1W78dQ)
|
||||
# SPC app chain EVM Indexer (chain ID 36911, blockchain ID rtjwvtE1tEvrokmpeYdTq7b2zqZgmybKwR5MLjKMGAR1W78dQ)
|
||||
###############################################################################
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
@@ -929,7 +929,7 @@ spec:
|
||||
targetPort: 4000
|
||||
|
||||
###############################################################################
|
||||
# Pars L2 EVM Indexer (chain ID 494949, blockchain ID 2pUskxqaL5Bpx7uRUGG1fDjPckjxQ4UKX4sLKeaS1NdSVBJd3F)
|
||||
# Pars app chain EVM Indexer (chain ID 494949, blockchain ID 2pUskxqaL5Bpx7uRUGG1fDjPckjxQ4UKX4sLKeaS1NdSVBJd3F)
|
||||
###############################################################################
|
||||
---
|
||||
apiVersion: apps/v1
|
||||
@@ -1067,25 +1067,25 @@ spec:
|
||||
services:
|
||||
- name: lux-indexer-kchain
|
||||
port: 4900
|
||||
# Zoo L2 EVM
|
||||
# Zoo app chain EVM
|
||||
- kind: Rule
|
||||
match: Host(`api-indexer-zoo.lux.network`)
|
||||
services:
|
||||
- name: lux-indexer-zoo
|
||||
port: 4000
|
||||
# Hanzo L2 EVM
|
||||
# Hanzo app chain EVM
|
||||
- kind: Rule
|
||||
match: Host(`api-indexer-hanzo.lux.network`)
|
||||
services:
|
||||
- name: lux-indexer-hanzo
|
||||
port: 4000
|
||||
# SPC L2 EVM
|
||||
# SPC app chain EVM
|
||||
- kind: Rule
|
||||
match: Host(`api-indexer-spc.lux.network`)
|
||||
services:
|
||||
- name: lux-indexer-spc
|
||||
port: 4000
|
||||
# Pars L2 EVM
|
||||
# Pars app chain EVM
|
||||
- kind: Rule
|
||||
match: Host(`api-indexer-pars.lux.network`)
|
||||
services:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
###############################################################################
|
||||
# IngressRoutes: L2 EVM chain explorers (Mainnet)
|
||||
# IngressRoutes: app chain EVM chain explorers (Mainnet)
|
||||
# Each chain gets frontend + API backend routing rules.
|
||||
# TLS via hanzoai/ingress ACME certResolver with Cloudflare DNS challenge.
|
||||
#
|
||||
|
||||
@@ -14,16 +14,16 @@
|
||||
# /ext/bc/C/rpc, /ext/bc/C/ws — primary-network EVM
|
||||
# /ext/bc/P, /ext/bc/X — P-Chain, X-Chain
|
||||
# /ext/info, /ext/health — node info / liveness
|
||||
# /ext/bc/hanzo/rpc — Hanzo L2 EVM (chainID 36963/36964)
|
||||
# /ext/bc/zoo/rpc — Zoo L2 EVM
|
||||
# /ext/bc/pars/rpc — Pars L2 EVM
|
||||
# /ext/bc/spc/rpc — SPC L2 EVM
|
||||
# /api/indexer/indexer-<sub> — indexer REST per L2 EVM
|
||||
# /ext/bc/hanzo/rpc — Hanzo app chain EVM (chainID 36963/36964)
|
||||
# /ext/bc/zoo/rpc — Zoo app chain EVM
|
||||
# /ext/bc/pars/rpc — Pars app chain EVM
|
||||
# /ext/bc/spc/rpc — SPC app chain EVM
|
||||
# /api/indexer/indexer-<sub> — indexer REST per app chain EVM
|
||||
#
|
||||
# Notes:
|
||||
# - Mainnet hanzo L2 EVM IS bootstrapped (blockchain id
|
||||
# - Mainnet hanzo app chain EVM IS bootstrapped (blockchain id
|
||||
# `y5HBrn6EWRMysSmH4nHA2sgpwgcjChJjQ7upSjWSwsrPeg4Cc`, chainID 0x9063).
|
||||
# - Testnet/devnet hanzo L2 EVMs are NOT yet bootstrapped — gateway
|
||||
# - Testnet/devnet hanzo app chain EVMs are NOT yet bootstrapped — gateway
|
||||
# routes exist but luxd will 404 until CreateChainTx is submitted.
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
###############################################################################
|
||||
# Lux Operator CRD Resources — LuxIndexer + LuxGateway for all 3 networks
|
||||
#
|
||||
# Blockchain IDs verified 2026-03-01 from live P-chain (v5 L2 EVMs).
|
||||
# Blockchain IDs verified 2026-03-01 from live P-chain (v5 app chain EVMs).
|
||||
# See memory/blockchain-ids.md for full reference.
|
||||
#
|
||||
# Image: ghcr.io/luxfi/indexer:v1.0.1
|
||||
@@ -170,7 +170,7 @@ spec:
|
||||
|
||||
# --- Mainnet Gateway ---
|
||||
# autoRoutes: C/X/P/health/info + indexer APIs (7 routes)
|
||||
# customRoutes: L2 EVM chain RPC by blockchain ID and alias
|
||||
# customRoutes: app chain EVM chain RPC by blockchain ID and alias
|
||||
---
|
||||
apiVersion: lux.network/v1alpha1
|
||||
kind: LuxGateway
|
||||
|
||||
@@ -121,10 +121,9 @@ spec:
|
||||
# from v1.25.1, this lets the proposer self-finalize its own
|
||||
# block at proposal time when peer Chits don't arrive in time —
|
||||
# closing the CreateChainTx stall observed on v1.27.23-26 with
|
||||
# 5 validators under sybil protection. All 4 L2 EVMs (hanzo,
|
||||
# 5 validators under sybil protection. All 4 app chains (hanzo,
|
||||
# zoo, pars, spc) bootstrap cleanly. Also carries canonical
|
||||
# evmAddr/utxoAddr (genesis v1.12.19), kill-subnet vocabulary,
|
||||
# kill-fuji vocabulary.
|
||||
# evmAddr/utxoAddr (genesis v1.12.19), kill-fuji vocabulary.
|
||||
tag: "v1.27.27"
|
||||
pullPolicy: IfNotPresent
|
||||
ports:
|
||||
|
||||
@@ -145,7 +145,7 @@ api-gateway-gateway (lux-mainnet, KrakenD :80)
|
||||
luxd-headless.lux-mainnet.svc.cluster.local:9630
|
||||
│ StatefulSet: 5 luxd validators on Lux Mainnet
|
||||
▼
|
||||
Subnet-EVM plugin (per chain) → on-disk badgerdb state
|
||||
EVM plugin (per chain) → on-disk badgerdb state
|
||||
```
|
||||
|
||||
The SPA never needs to know any of this — it just calls
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Canonical chain aliases for lux-mainnet luxd validators.
|
||||
# Loaded by luxd via --chain-aliases-file (see luxd-startup.yaml).
|
||||
#
|
||||
# Maps blockchainID → [alias names] for the 4 L2 EVMs:
|
||||
# Maps blockchainID → [alias names] for the 4 app chain EVMs:
|
||||
# hanzo (chainId 36963, coin AI)
|
||||
# zoo (chainId 200200, coin ZOO, 799 historic blocks)
|
||||
# pars (chainId 7070, coin PARS, 7B treasury) — actual chain name "parsv4"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
###############################################################################
|
||||
# Frontend ConfigMaps for L2 EVM chain explorers (Mainnet)
|
||||
# Frontend ConfigMaps for app chain EVM chain explorers (Mainnet)
|
||||
# Each chain frontend needs API host, network identity, and theme config.
|
||||
# NEXT_PUBLIC_API_HOST must be the externally-accessible API domain
|
||||
# (client-side JS makes requests to it directly).
|
||||
|
||||
@@ -3,18 +3,18 @@
|
||||
# Unified Lux Explorer — Mainnet
|
||||
#
|
||||
# Single Go binary `ghcr.io/luxfi/explorer:1.2.11` that indexes every EVM
|
||||
# L2 chain on this network into per-chain SQLite databases under /data/{slug}
|
||||
# non-primary chain on this network into per-chain SQLite databases under /data/{slug}
|
||||
# and serves the embedded SPA + /v1/indexer/{slug}/* + /v1/graph/* +
|
||||
# /v1/explorer/admin/* + /v1/explorer/realtime on :8090.
|
||||
#
|
||||
# Replaces Blockscout (indexer-{slug}-indexer Deployments) + their
|
||||
# per-L2 PostgreSQL StatefulSets (indexer-{slug}-pg) + the
|
||||
# per-chain PostgreSQL StatefulSets (indexer-{slug}-pg) + the
|
||||
# lux-explorer/explorer-mainnet-v2 Deployment. Postgres-free indexer.
|
||||
#
|
||||
# Per-chain RPC URLs use the chain name aliases exposed by luxd
|
||||
# (/ext/bc/{slug}/rpc), verified working via eth_chainId against
|
||||
# luxd-headless.lux-mainnet.svc:9630 on 2026-05-24. Chain IDs below are
|
||||
# the on-chain values reported by each L2 EVM (NOT the historical
|
||||
# the on-chain values reported by each app chain EVM (NOT the historical
|
||||
# manifest-only values; pars reports 7070, not 494949).
|
||||
###############################################################################
|
||||
apiVersion: v1
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
###############################################################################
|
||||
# Lux Explore Frontend for L2 EVM chains (Mainnet)
|
||||
# Lux Explore Frontend for app chain EVM chains (Mainnet)
|
||||
# Image: ghcr.io/luxfi/explore:0.1.0 (Next.js 14, Node 22)
|
||||
# Each chain gets a Deployment + Service, reads config from ConfigMap.
|
||||
###############################################################################
|
||||
|
||||
@@ -17,10 +17,10 @@ spec:
|
||||
# in this network — pars and spc were bootstrapped with a different
|
||||
# genesis whose private key is not recoverable from the project
|
||||
# mnemonic (see ~/work/lux/standard/DEPLOYMENTS.md).
|
||||
# (b) the hanzo/zoo L2 EVMs are currently in a stalled consensus state
|
||||
# (b) the hanzo/zoo app chain EVMs are currently in a stalled consensus state
|
||||
# ("no recent messages" on the router) so txs sit in mempool without
|
||||
# being mined — heartbeating them would just produce log noise until
|
||||
# the underlying L2 EVM validators are healthy.
|
||||
# the underlying app chain EVM validators are healthy.
|
||||
# Add hanzo,zoo,pars,spc back here once those are addressed.
|
||||
schedule: "*/5 * * * *"
|
||||
timeZone: Etc/UTC
|
||||
@@ -48,7 +48,7 @@ spec:
|
||||
imagePullPolicy: IfNotPresent
|
||||
args:
|
||||
# Public domain is used (not the in-cluster gateway DNS)
|
||||
# because KrakenD's path-rewriting routes for L2 EVM aliases
|
||||
# because KrakenD's path-rewriting routes for app chain EVM aliases
|
||||
# only fire on certain Host headers; ingress handles it
|
||||
# cleanly. Resolution stays inside DigitalOcean's network.
|
||||
- --rpc-base=https://api.lux.network
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
###############################################################################
|
||||
# IngressRoutes: L2 EVM chain explorers (Mainnet)
|
||||
# IngressRoutes: app chain EVM chain explorers (Mainnet)
|
||||
# Each chain gets frontend + API backend routing rules.
|
||||
# TLS via hanzoai/ingress ACME certResolver with Cloudflare DNS challenge.
|
||||
#
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
# luxd startup script for lux-mainnet.
|
||||
#
|
||||
# Canonical chain tracking + alias resolution (decomplected 2026-05-26):
|
||||
# --track-chains restricts luxd to the 4 good L2 EVM blockchain IDs
|
||||
# --track-chains restricts luxd to the 4 good app chain EVM blockchain IDs
|
||||
# (orphan pars/spc/parsm chains are unreachable; their P-chain
|
||||
# registrations remain but no validator tracks them).
|
||||
# /data/aliases.json + --chain-aliases-file feeds info.* APIs with
|
||||
# human-readable names for the 4 L2 EVMs.
|
||||
# human-readable names for the 4 app chain EVMs.
|
||||
# HTTP route renaming (e.g. /ext/bc/pars → parsv4 chain) is done at
|
||||
# the api-gateway-gateway krakend layer, NOT at luxd (luxd routes
|
||||
# only by chain-name).
|
||||
#
|
||||
# TENANT IMPORT COORDINATION (Zoo RLP block below):
|
||||
# The Zoo L2 EVM (chainId 200200) RLP import block inlined below is
|
||||
# The Zoo app chain EVM (chainId 200200) RLP import block inlined below is
|
||||
# contributed by the Zoo brand. Source of truth:
|
||||
# ~/work/zoo/universe/k8s/zoo-mainnet/luxd-rlp-import.yaml
|
||||
#
|
||||
@@ -66,7 +66,7 @@ data:
|
||||
ADMIN_NEEDED="false"
|
||||
fi
|
||||
|
||||
# DB wipe disabled - preserve subnet chain state across pod restarts
|
||||
# DB wipe disabled - preserve chain state across pod restarts
|
||||
|
||||
# All one-time DB wipe blocks removed 2026-03-19 - sentinel files already applied
|
||||
|
||||
@@ -180,7 +180,7 @@ data:
|
||||
# This override activates Etna→Cancun, Fortuna, Granite from genesis.
|
||||
CHAIN_CONFIG_DIR="/data/configs/chains"
|
||||
UPGRADE_JSON='{"networkUpgradeOverrides":{"durangoTimestamp":0,"etnaTimestamp":0,"fortunaTimestamp":0,"graniteTimestamp":0},"precompileUpgrades":[{"aiMiningConfig":{"blockTimestamp":0}},{"blake3Config":{"blockTimestamp":0}},{"cggmp21Verify":{"blockTimestamp":0}},{"deadZeroConfig":{"blockTimestamp":0}},{"deadConfig":{"blockTimestamp":0}},{"deadFullConfig":{"blockTimestamp":0}},{"dexConfig":{"blockTimestamp":0}},{"routerConfig":{"blockTimestamp":0}},{"eciesConfig":{"blockTimestamp":0}},{"fheConfig":{"blockTimestamp":0}},{"frostVerify":{"blockTimestamp":0}},{"graphConfig":{"blockTimestamp":0}},{"hpkeConfig":{"blockTimestamp":0}},{"mldsaVerify":{"blockTimestamp":0}},{"mlkemConfig":{"blockTimestamp":0}},{"pqcryptoConfig":{"blockTimestamp":0}},{"ringConfig":{"blockTimestamp":0}},{"coronaThreshold":{"blockTimestamp":0}},{"slhdsaVerify":{"blockTimestamp":0}},{"zkConfig":{"blockTimestamp":0}}]}'
|
||||
# Canonical L2 EVM blockchain IDs (in sync with /data/aliases.json below).
|
||||
# Canonical app chain EVM blockchain IDs (in sync with /data/aliases.json below).
|
||||
# Update both here and in the chain-aliases ConfigMap when a chain is
|
||||
# re-bootstrapped (e.g. parsv4, spcv4, zoofix on testnet).
|
||||
EVM_CHAIN_IDS="C y5HBrn6EWRMysSmH4nHA2sgpwgcjChJjQ7upSjWSwsrPeg4Cc 2wbPWcyuNUimWW7YMq3gymTTpHjP9Lsm7GpmcyWimEs9kyTAAH 2wYWjBHziTjfMJmUPZwsDdWhm96cWHo4vov1HPBmCYLXdbAZfM 2YTuJW9b1k7gDGgqZC58Wj6cT1qTzobx6SV8hiN22zT1L5qfHF"
|
||||
@@ -192,12 +192,12 @@ data:
|
||||
ARGS="$ARGS --chain-config-dir=${CHAIN_CONFIG_DIR}"
|
||||
|
||||
echo "
|
||||
# Ensure subnet-evm plugin uses our custom EVM build (with all precompiles)
|
||||
# Ensure app chain EVM plugin uses our custom EVM build (with all precompiles)
|
||||
CCHAIN_PLUGIN="mgj786NP7uDwBCcq6YwThhaN8FLyybkCa4zBWTQbNgmK6k9A6"
|
||||
SUBNET_PLUGIN="ag3GReYPNuSR17rUP8acMdZipQBikdXNRKDyFszAysmy3vDXE"
|
||||
APPCHAIN_PLUGIN="ag3GReYPNuSR17rUP8acMdZipQBikdXNRKDyFszAysmy3vDXE"
|
||||
if [ -f "/data/plugins/$CCHAIN_PLUGIN" ]; then
|
||||
echo "[PLUGINS] Copying C-Chain EVM as subnet-evm plugin - shared precompile registry"
|
||||
cp -f "/data/plugins/$CCHAIN_PLUGIN" "/data/plugins/$SUBNET_PLUGIN"
|
||||
echo "[PLUGINS] Copying C-Chain EVM as app chain plugin - shared precompile registry"
|
||||
cp -f "/data/plugins/$CCHAIN_PLUGIN" "/data/plugins/$APPCHAIN_PLUGIN"
|
||||
fi
|
||||
|
||||
[START] luxd ${ARGS}" | head -c 200
|
||||
|
||||
@@ -22,7 +22,7 @@ metadata:
|
||||
data:
|
||||
chains: |
|
||||
# Testnet "zoo" ghost chain — CreateChainTx committed with malformed
|
||||
# EVM genesis alloc address (41 hex chars, odd-length), subnet-evm
|
||||
# EVM genesis alloc address (41 hex chars, odd-length), EVM
|
||||
# parseGenesis fails with "hex string of odd length" on every restart.
|
||||
# CreateChainTx is immutable on P-Chain; the only remediation is to
|
||||
# exclude it from bootstrap accounting. Replacement chain is alias
|
||||
|
||||
@@ -3,18 +3,18 @@
|
||||
# Unified Lux Explorer — Testnet
|
||||
#
|
||||
# Single Go binary `ghcr.io/luxfi/explorer:1.2.11` that indexes every EVM
|
||||
# L2 chain on this network into per-chain SQLite databases under /data/{slug}
|
||||
# non-primary chain on this network into per-chain SQLite databases under /data/{slug}
|
||||
# and serves the embedded SPA + /v1/indexer/{slug}/* + /v1/graph/* +
|
||||
# /v1/explorer/admin/* + /v1/explorer/realtime on :8090.
|
||||
#
|
||||
# Replaces Blockscout (indexer-{slug}-indexer Deployments) + their
|
||||
# per-L2 PostgreSQL StatefulSets (indexer-{slug}-pg) + the
|
||||
# per-chain PostgreSQL StatefulSets (indexer-{slug}-pg) + the
|
||||
# lux-explorer/explorer-testnet-v2 Deployment. Postgres-free indexer.
|
||||
#
|
||||
# zoo L2 EVM is not bootstrapped on testnet luxd-* nodes (verified
|
||||
# zoo app chain EVM is not bootstrapped on testnet luxd-* nodes (verified
|
||||
# 2026-05-24: /ext/bc/zoo/rpc returns 404 across all 5 replicas). It is
|
||||
# declared with enabled:false here so the registry knows about it; flip
|
||||
# to true once the zoo L2 EVM is tracked on testnet validators.
|
||||
# to true once the zoo app chain EVM is tracked on testnet validators.
|
||||
###############################################################################
|
||||
apiVersion: v1
|
||||
kind: ConfigMap
|
||||
|
||||
@@ -37,7 +37,7 @@ spec:
|
||||
imagePullPolicy: IfNotPresent
|
||||
args:
|
||||
# Public domain is used (not the in-cluster gateway DNS)
|
||||
# because KrakenD's path-rewriting routes for L2 EVM aliases
|
||||
# because KrakenD's path-rewriting routes for app chain EVM aliases
|
||||
# (zoo/hanzo/pars/spc) only fire on certain Host headers; the
|
||||
# public FQDN goes through ingress where this works cleanly.
|
||||
# Resolution stays inside DigitalOcean's network.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
---
|
||||
###############################################################################
|
||||
# IngressRoutes: L2 EVM chain explorers (Testnet)
|
||||
# IngressRoutes: app chain EVM chain explorers (Testnet)
|
||||
#
|
||||
# Domain convention mirrors mainnet:
|
||||
# explore-{chain}-test.lux.network -> unified explorer SPA (explorer:80)
|
||||
|
||||
File diff suppressed because one or more lines are too long
+2
-2
@@ -21,11 +21,11 @@
|
||||
"test:bridge-mpc": "npx playwright test e2e/13-bridge-mpc.spec.ts",
|
||||
"test:dex-contracts": "npx playwright test e2e/14-dex-contracts.spec.ts",
|
||||
"test:nft": "npx playwright test e2e/15-nft-marketplace.spec.ts",
|
||||
"test:subnets": "npx playwright test e2e/16-subnet-chains.spec.ts",
|
||||
"test:chains": "npx playwright test e2e/16-app-chains.spec.ts",
|
||||
"test:governance": "npx playwright test e2e/17-governance.spec.ts",
|
||||
"test:broker": "npx playwright test e2e/18-broker.spec.ts",
|
||||
"test:broker-deep": "npx playwright test e2e/19-broker-deep.spec.ts",
|
||||
"test:full": "npx playwright test e2e/00-health.spec.ts e2e/01-explorer.spec.ts e2e/02-exchange.spec.ts e2e/03-bridge.spec.ts e2e/04-staking.spec.ts e2e/05-cloud.spec.ts e2e/06-wallet.spec.ts e2e/07-validator.spec.ts e2e/08-validator-lifecycle.spec.ts e2e/09-defi-flow.spec.ts e2e/10-stats-dashboard.spec.ts e2e/11-wallet-ops.spec.ts e2e/12-staking-rpc.spec.ts e2e/13-bridge-mpc.spec.ts e2e/14-dex-contracts.spec.ts e2e/15-nft-marketplace.spec.ts e2e/16-subnet-chains.spec.ts e2e/17-governance.spec.ts e2e/18-broker.spec.ts e2e/19-broker-deep.spec.ts",
|
||||
"test:full": "npx playwright test e2e/00-health.spec.ts e2e/01-explorer.spec.ts e2e/02-exchange.spec.ts e2e/03-bridge.spec.ts e2e/04-staking.spec.ts e2e/05-cloud.spec.ts e2e/06-wallet.spec.ts e2e/07-validator.spec.ts e2e/08-validator-lifecycle.spec.ts e2e/09-defi-flow.spec.ts e2e/10-stats-dashboard.spec.ts e2e/11-wallet-ops.spec.ts e2e/12-staking-rpc.spec.ts e2e/13-bridge-mpc.spec.ts e2e/14-dex-contracts.spec.ts e2e/15-nft-marketplace.spec.ts e2e/16-app-chains.spec.ts e2e/17-governance.spec.ts e2e/18-broker.spec.ts e2e/19-broker-deep.spec.ts",
|
||||
"test:headed": "npx playwright test --headed",
|
||||
"test:ui": "npx playwright test --ui",
|
||||
"test:prod": "ENV=production npx playwright test",
|
||||
|
||||
+10
-10
@@ -67,7 +67,7 @@ CHAINS = {
|
||||
"factory": "0x84CF0A13db1be8e1F0676405cfcBC8b09692FD1C",
|
||||
"router": "0x2382F7A49FA48E1F91Bec466c32e1D7F13ec8206",
|
||||
},
|
||||
# Subnet chains: all use shared addresses (deployer had nonce=0 on each fresh chain)
|
||||
# App chains: all use shared addresses (deployer had nonce=0 on each fresh chain)
|
||||
"Zoo": {
|
||||
"chain_id": 200200,
|
||||
"rpc": "http://localhost:19630/ext/bc/2Y625Kvdd4wZ5LKx9kLSf1jGALyARmXVN1YsTb4F3Hzv4bPDbp/rpc",
|
||||
@@ -118,14 +118,14 @@ CHAINS = {
|
||||
}
|
||||
|
||||
# Minimum native LUX required to participate in exchange setup
|
||||
MIN_NATIVE_LUX = 10 # LUX (subnets have huge balances; C-Chain deployer may be low)
|
||||
MIN_NATIVE_LUX = 10 # LUX (app chains have huge balances; C-Chain deployer may be low)
|
||||
|
||||
# KNOWN LIMITATION: AMM swaps fail on Subnet EVM (Zoo, Hanzo, Pars, SPC) with
|
||||
# KNOWN LIMITATION: AMM swaps fail on app chain EVMs (Zoo, Hanzo, Pars, SPC) with
|
||||
# "invalid opcode: MCOPY" because the AMM router was compiled with Solidity >=0.8.24
|
||||
# which uses the Cancun EIP-5656 MCOPY opcode. Subnet EVM does not yet support Cancun.
|
||||
# which uses the Cancun EIP-5656 MCOPY opcode. App chain EVMs do not yet support Cancun.
|
||||
# Workaround: Recompile AMM contracts with Solidity <=0.8.23 and redeploy.
|
||||
# C-Chain swaps work since C-Chain EVM supports Cancun.
|
||||
SUBNET_SWAP_BROKEN = True # swaps on Hanzo/Pars chains will revert
|
||||
APPCHAIN_SWAP_BROKEN = True # swaps on Hanzo/Pars chains will revert
|
||||
|
||||
# ---------------------------------------------------------------------------
|
||||
# ABIs (minimal)
|
||||
@@ -496,13 +496,13 @@ def trade_on_chain(name: str, cfg: dict, account, swap_amount_lux: float = 10.0)
|
||||
"""
|
||||
Execute one round of swaps: WLUX→LETH then LETH→WLUX.
|
||||
Returns True if any swap succeeded.
|
||||
NOTE: Subnet EVM chains (Hanzo, Pars, Zoo, SPC) fail with MCOPY opcode.
|
||||
NOTE: App chain EVMs (Hanzo, Pars, Zoo, SPC) fail with MCOPY opcode.
|
||||
Only C-Chain supports Cancun opcodes needed by the AMM router.
|
||||
"""
|
||||
# Subnet chains use AMM contracts compiled with Solidity >=0.8.24 (MCOPY opcode).
|
||||
# Subnet EVM doesn't support Cancun; skip swaps until contracts are recompiled.
|
||||
if SUBNET_SWAP_BROKEN and name != "C-Chain":
|
||||
print(f" [{name}] Skipping swap (MCOPY not supported on Subnet EVM — recompile AMM with Solidity <=0.8.23)")
|
||||
# App chains use AMM contracts compiled with Solidity >=0.8.24 (MCOPY opcode).
|
||||
# App chain EVMs don't support Cancun; skip swaps until contracts are recompiled.
|
||||
if APPCHAIN_SWAP_BROKEN and name != "C-Chain":
|
||||
print(f" [{name}] Skipping swap (MCOPY not supported on app chain EVM — recompile AMM with Solidity <=0.8.23)")
|
||||
return False
|
||||
|
||||
w3 = Web3(Web3.HTTPProvider(cfg["rpc"], request_kwargs={"timeout": 30}))
|
||||
|
||||
@@ -279,7 +279,7 @@ def test_validator_network():
|
||||
|
||||
def validator_count():
|
||||
r = http_post("https://api.lux.network/ext/bc/P",
|
||||
{"jsonrpc": "2.0", "method": "platform.getCurrentValidators", "params": {"subnetID": ""}, "id": 1})
|
||||
{"jsonrpc": "2.0", "method": "platform.getCurrentValidators", "params": {"netID": ""}, "id": 1})
|
||||
validators = r.get("result", {}).get("validators", [])
|
||||
count = len(validators)
|
||||
assert count >= 5, f"expected >= 5 validators, got {count}"
|
||||
@@ -308,7 +308,7 @@ def test_validator_network():
|
||||
def sybil_protection():
|
||||
"""Verify sybil protection is enabled (not POA)"""
|
||||
r = http_post("https://api.lux.network/ext/bc/P",
|
||||
{"jsonrpc": "2.0", "method": "platform.getCurrentValidators", "params": {"subnetID": ""}, "id": 1})
|
||||
{"jsonrpc": "2.0", "method": "platform.getCurrentValidators", "params": {"netID": ""}, "id": 1})
|
||||
validators = r.get("result", {}).get("validators", [])
|
||||
# Real validators have start/end times and delegation fees
|
||||
has_staking = all(v.get("startTime") and v.get("endTime") for v in validators)
|
||||
@@ -328,7 +328,7 @@ def test_validator_network():
|
||||
assert bootstrapped, f"{chain}-Chain not bootstrapped"
|
||||
return " ".join(results)
|
||||
|
||||
def subnet_chains():
|
||||
def app_chains():
|
||||
r = http_post("https://api.lux.network/ext/bc/P",
|
||||
{"jsonrpc": "2.0", "method": "platform.getBlockchains", "params": {}, "id": 1})
|
||||
chains = r.get("result", {}).get("blockchains", [])
|
||||
@@ -346,7 +346,7 @@ def test_validator_network():
|
||||
check("Node version", node_version)
|
||||
check("Sybil protection (not POA)", sybil_protection)
|
||||
check("All chains bootstrapped", all_chains_bootstrapped)
|
||||
check("Subnet blockchains", subnet_chains)
|
||||
check("App chains", app_chains)
|
||||
check("Consensus parameters", consensus_params)
|
||||
|
||||
|
||||
|
||||
+28
-28
@@ -26,7 +26,7 @@ type ChainConfig struct {
|
||||
AMMV2Router common.Address
|
||||
AMMV2Factory common.Address
|
||||
|
||||
// Whether AMM swaps work on this chain (Subnet EVM may lack MCOPY)
|
||||
// Whether AMM swaps work on this chain (app chain EVM may lack MCOPY)
|
||||
SwapsEnabled bool
|
||||
}
|
||||
|
||||
@@ -75,8 +75,8 @@ func envFloatOrDefault(key string, def float64) float64 {
|
||||
return def
|
||||
}
|
||||
|
||||
// Subnet shared addresses (deployer had nonce=0 on each fresh chain)
|
||||
var subnetTokens = struct {
|
||||
// App-chain shared addresses (deployer had nonce=0 on each fresh chain)
|
||||
var appChainTokens = struct {
|
||||
WLUX, LETH, LBTC, LUSDC common.Address
|
||||
AMMV2Router, AMMV2Factory common.Address
|
||||
}{
|
||||
@@ -90,7 +90,7 @@ var subnetTokens = struct {
|
||||
|
||||
// allChains returns all supported chain configurations.
|
||||
// C-chain addresses are from the user-provided contract addresses.
|
||||
// Subnet chains use the shared deployed addresses from e2e-exchange.py.
|
||||
// App chains use the shared deployed addresses from e2e-exchange.py.
|
||||
func allChains() map[string]ChainConfig {
|
||||
return map[string]ChainConfig{
|
||||
"lux": {
|
||||
@@ -109,48 +109,48 @@ func allChains() map[string]ChainConfig {
|
||||
Name: "Zoo Chain",
|
||||
ChainID: big.NewInt(200200),
|
||||
RPC: envOrDefault("RPC_ZOO", "https://api.lux.network/mainnet/ext/bc/Z/rpc"),
|
||||
WLUX: subnetTokens.WLUX,
|
||||
LETH: subnetTokens.LETH,
|
||||
LBTC: subnetTokens.LBTC,
|
||||
LUSDC: subnetTokens.LUSDC,
|
||||
AMMV2Factory: subnetTokens.AMMV2Factory,
|
||||
AMMV2Router: subnetTokens.AMMV2Router,
|
||||
WLUX: appChainTokens.WLUX,
|
||||
LETH: appChainTokens.LETH,
|
||||
LBTC: appChainTokens.LBTC,
|
||||
LUSDC: appChainTokens.LUSDC,
|
||||
AMMV2Factory: appChainTokens.AMMV2Factory,
|
||||
AMMV2Router: appChainTokens.AMMV2Router,
|
||||
SwapsEnabled: false, // MCOPY opcode not supported
|
||||
},
|
||||
"hanzo": {
|
||||
Name: "Hanzo Chain",
|
||||
ChainID: big.NewInt(36963),
|
||||
RPC: envOrDefault("RPC_HANZO", "https://api.lux.network/mainnet/ext/bc/H/rpc"),
|
||||
WLUX: subnetTokens.WLUX,
|
||||
LETH: subnetTokens.LETH,
|
||||
LBTC: subnetTokens.LBTC,
|
||||
LUSDC: subnetTokens.LUSDC,
|
||||
AMMV2Factory: subnetTokens.AMMV2Factory,
|
||||
AMMV2Router: subnetTokens.AMMV2Router,
|
||||
WLUX: appChainTokens.WLUX,
|
||||
LETH: appChainTokens.LETH,
|
||||
LBTC: appChainTokens.LBTC,
|
||||
LUSDC: appChainTokens.LUSDC,
|
||||
AMMV2Factory: appChainTokens.AMMV2Factory,
|
||||
AMMV2Router: appChainTokens.AMMV2Router,
|
||||
SwapsEnabled: false,
|
||||
},
|
||||
"spc": {
|
||||
Name: "SPC Chain",
|
||||
ChainID: big.NewInt(36911),
|
||||
RPC: envOrDefault("RPC_SPC", "https://api.lux.network/mainnet/ext/bc/S/rpc"),
|
||||
WLUX: subnetTokens.WLUX,
|
||||
LETH: subnetTokens.LETH,
|
||||
LBTC: subnetTokens.LBTC,
|
||||
LUSDC: subnetTokens.LUSDC,
|
||||
AMMV2Factory: subnetTokens.AMMV2Factory,
|
||||
AMMV2Router: subnetTokens.AMMV2Router,
|
||||
WLUX: appChainTokens.WLUX,
|
||||
LETH: appChainTokens.LETH,
|
||||
LBTC: appChainTokens.LBTC,
|
||||
LUSDC: appChainTokens.LUSDC,
|
||||
AMMV2Factory: appChainTokens.AMMV2Factory,
|
||||
AMMV2Router: appChainTokens.AMMV2Router,
|
||||
SwapsEnabled: false,
|
||||
},
|
||||
"pars": {
|
||||
Name: "Pars Chain",
|
||||
ChainID: big.NewInt(494949),
|
||||
RPC: envOrDefault("RPC_PARS", "https://api.lux.network/mainnet/ext/bc/T/rpc"),
|
||||
WLUX: subnetTokens.WLUX,
|
||||
LETH: subnetTokens.LETH,
|
||||
LBTC: subnetTokens.LBTC,
|
||||
LUSDC: subnetTokens.LUSDC,
|
||||
AMMV2Factory: subnetTokens.AMMV2Factory,
|
||||
AMMV2Router: subnetTokens.AMMV2Router,
|
||||
WLUX: appChainTokens.WLUX,
|
||||
LETH: appChainTokens.LETH,
|
||||
LBTC: appChainTokens.LBTC,
|
||||
LUSDC: appChainTokens.LUSDC,
|
||||
AMMV2Factory: appChainTokens.AMMV2Factory,
|
||||
AMMV2Router: appChainTokens.AMMV2Router,
|
||||
SwapsEnabled: false,
|
||||
},
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user