mirror of
https://github.com/luxfi/bridge.git
synced 2026-09-24 00:26:46 +00:00
luxd serves chain routes under /v1/chain, and the node, cli and sdk releases already ship it. The deployed gateways still answer the old prefix, so remote reads break until they are redeployed; the estate moves together rather than sitting half converted. Lines that record an observation - a probe, a status code, a past release - keep the prefix they were written against, as do URLs on hosts that are not ours. Avalanche endpoints move to /ext/bc, which is the path that host serves.
930 lines
24 KiB
YAML
930 lines
24 KiB
YAML
apiVersion: v1
|
|
kind: Namespace
|
|
metadata:
|
|
name: lux-bridge
|
|
---
|
|
# KV Store — hanzoai/kv (Redis/Valkey)
|
|
# Used for session caching and bridge state. Replaces legacy NATS/Consul.
|
|
# MPC nodes use consensus mode (ZAP p2p) and do NOT need NATS or Consul.
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: kv
|
|
namespace: lux-bridge
|
|
spec:
|
|
replicas: 1
|
|
selector:
|
|
matchLabels:
|
|
app: kv
|
|
template:
|
|
metadata:
|
|
labels:
|
|
app: kv
|
|
spec:
|
|
containers:
|
|
- name: kv
|
|
image: hanzoai/kv:latest
|
|
ports:
|
|
- containerPort: 6379
|
|
name: redis
|
|
volumeMounts:
|
|
- name: kv-storage
|
|
mountPath: /data
|
|
livenessProbe:
|
|
tcpSocket:
|
|
port: 6379
|
|
initialDelaySeconds: 10
|
|
periodSeconds: 10
|
|
readinessProbe:
|
|
tcpSocket:
|
|
port: 6379
|
|
initialDelaySeconds: 5
|
|
periodSeconds: 5
|
|
volumes:
|
|
- name: kv-storage
|
|
persistentVolumeClaim:
|
|
claimName: kv-pvc
|
|
---
|
|
apiVersion: v1
|
|
kind: Service
|
|
metadata:
|
|
name: kv
|
|
namespace: lux-bridge
|
|
spec:
|
|
selector:
|
|
app: kv
|
|
ports:
|
|
- port: 6379
|
|
targetPort: 6379
|
|
name: redis
|
|
---
|
|
# MPC Config
|
|
apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: mpc-config
|
|
namespace: lux-bridge
|
|
data:
|
|
config.yaml: |
|
|
# MPC nodes coordinate via ZAP p2p — no NATS or Consul needed.
|
|
environment: mainnet
|
|
mpc_threshold: 3
|
|
mpc_total_nodes: 5
|
|
# badger_password is injected via ZAPDB_PASSWORD env var from mpc-secrets k8s Secret (KMS-managed)
|
|
event_initiator_pubkey: "c3f3511cd2f849fd61e81ea62a842fd33367ee8fb5b867bb900877c7fb72ce3b"
|
|
max_concurrent_keygen: 3
|
|
db_path: /data/mpc
|
|
backup_enabled: true
|
|
backup_period_seconds: 300
|
|
backup_dir: /data/mpc/backups
|
|
peers.json: |
|
|
{
|
|
"node0": "0ce02715-0ead-48ef-9772-2583316cc860",
|
|
"node1": "c95c340e-5a18-472d-b9b0-5ac68218213a",
|
|
"node2": "ac37e85f-caca-4bee-8a3a-49a0fe35abff",
|
|
"node3": "ee42a050-c1e8-4875-ae03-4260047666ff",
|
|
"node4": "f67ec0b6-5a2f-410b-b43b-800b99315b41"
|
|
}
|
|
node0_identity.json: |
|
|
{"node_name":"node0","node_id":"0ce02715-0ead-48ef-9772-2583316cc860","public_key":"96e47112bab4cb83e59a0a222964fad096f02a9dc52e449097f8991470a141ab"}
|
|
node1_identity.json: |
|
|
{"node_name":"node1","node_id":"c95c340e-5a18-472d-b9b0-5ac68218213a","public_key":"d49b5caace90b8317accd728b7b4419baef2ff32a164411d9ac7c1f703e13f7e"}
|
|
node2_identity.json: |
|
|
{"node_name":"node2","node_id":"ac37e85f-caca-4bee-8a3a-49a0fe35abff","public_key":"e0a570f5e7b52f76ba54aca0578dcd0c7f6569b7640027664af5be2ba8f0cf49"}
|
|
node3_identity.json: |
|
|
{"node_name":"node3","node_id":"ee42a050-c1e8-4875-ae03-4260047666ff","public_key":"a0082b30a0c5598b0d4d998e80866a6b7d1c4c66d0d8d907fd64ada5dceddd8b"}
|
|
node4_identity.json: |
|
|
{"node_name":"node4","node_id":"f67ec0b6-5a2f-410b-b43b-800b99315b41","public_key":"9f387cbaba446ffc05d69cc5cd2f35ed82531b860ceae0febc25560251fcdd36"}
|
|
---
|
|
# IMPORTANT: mpc-identity-keys is managed externally via KMS (kms.hanzo.ai).
|
|
# Keys are stored in KMS under: MPC_NODE{0,1,2}_PRIVATE_KEY and MPC_INITIATOR_KEY
|
|
# Apply with:
|
|
# kubectl create secret generic mpc-identity-keys -n lux-bridge \
|
|
# --from-literal="node0_private.key=$(kms get MPC_NODE0_PRIVATE_KEY)" \
|
|
# --from-literal="node1_private.key=$(kms get MPC_NODE1_PRIVATE_KEY)" \
|
|
# --from-literal="node2_private.key=$(kms get MPC_NODE2_PRIVATE_KEY)" \
|
|
# --from-literal="initiator.key=$(kms get MPC_INITIATOR_KEY)" \
|
|
# --dry-run=client -o yaml | kubectl apply -f -
|
|
# DO NOT add secret values here — never commit keys to git.
|
|
---
|
|
# MPC Node StatefulSet
|
|
apiVersion: apps/v1
|
|
kind: StatefulSet
|
|
metadata:
|
|
name: mpc-node
|
|
namespace: lux-bridge
|
|
spec:
|
|
serviceName: mpc-node
|
|
replicas: 5
|
|
selector:
|
|
matchLabels:
|
|
app: mpc-node
|
|
template:
|
|
metadata:
|
|
labels:
|
|
app: mpc-node
|
|
spec:
|
|
securityContext:
|
|
runAsNonRoot: true
|
|
runAsUser: 1000
|
|
runAsGroup: 1000
|
|
fsGroup: 1000
|
|
seccompProfile:
|
|
type: RuntimeDefault
|
|
initContainers:
|
|
- name: setup-identity
|
|
image: alpine:latest
|
|
command: ["/bin/sh", "-c"]
|
|
args:
|
|
- |
|
|
IDX=$(hostname | sed 's/mpc-node-//')
|
|
NODE_NAME="node${IDX}"
|
|
echo "Setting up identity for ${NODE_NAME}"
|
|
mkdir -p /app/identity
|
|
cp /config/config.yaml /app/config.yaml
|
|
cp /config/peers.json /app/peers.json
|
|
# Copy ALL node identities (needed for verifying peer messages)
|
|
for i in 0 1 2 3 4; do
|
|
cp /config/node${i}_identity.json /app/identity/node${i}_identity.json
|
|
done
|
|
# Copy own private key
|
|
cp /keys/${NODE_NAME}_private.key /app/identity/${NODE_NAME}_private.key
|
|
chmod 600 /app/identity/${NODE_NAME}_private.key
|
|
echo "Identity setup complete for ${NODE_NAME}"
|
|
volumeMounts:
|
|
- name: app-dir
|
|
mountPath: /app
|
|
- name: mpc-config
|
|
mountPath: /config
|
|
- name: mpc-keys
|
|
mountPath: /keys
|
|
containers:
|
|
- name: mpc
|
|
image: ghcr.io/luxfi/mpc:latest
|
|
securityContext:
|
|
allowPrivilegeEscalation: false
|
|
readOnlyRootFilesystem: true
|
|
capabilities:
|
|
drop: ["ALL"]
|
|
command: ["/bin/sh", "-c"]
|
|
args:
|
|
- |
|
|
IDX=$(hostname | sed 's/mpc-node-//')
|
|
NODE_NAME="node${IDX}"
|
|
echo "Starting MPC node: ${NODE_NAME}"
|
|
cd /app && exec mpcd start -n "${NODE_NAME}"
|
|
ports:
|
|
- containerPort: 8080
|
|
name: http
|
|
- containerPort: 9090
|
|
name: grpc
|
|
env:
|
|
- name: LOG_LEVEL
|
|
value: info
|
|
- name: ZAPDB_PASSWORD
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: bridge-secrets
|
|
key: mpc-db-password
|
|
- name: MPC_THRESHOLD
|
|
value: "3"
|
|
- name: MPC_TOTAL_NODES
|
|
value: "5"
|
|
volumeMounts:
|
|
- name: app-dir
|
|
mountPath: /app
|
|
- name: mpc-data
|
|
mountPath: /data
|
|
- name: tmp
|
|
mountPath: /tmp
|
|
resources:
|
|
requests:
|
|
memory: "256Mi"
|
|
cpu: "250m"
|
|
limits:
|
|
memory: "512Mi"
|
|
cpu: "500m"
|
|
volumes:
|
|
- name: app-dir
|
|
emptyDir: {}
|
|
- name: tmp
|
|
emptyDir:
|
|
sizeLimit: 50Mi
|
|
- name: mpc-config
|
|
configMap:
|
|
name: mpc-config
|
|
- name: mpc-keys
|
|
secret:
|
|
secretName: mpc-identity-keys
|
|
volumeClaimTemplates:
|
|
- metadata:
|
|
name: mpc-data
|
|
spec:
|
|
accessModes: ["ReadWriteOnce"]
|
|
resources:
|
|
requests:
|
|
storage: 20Gi
|
|
---
|
|
apiVersion: v1
|
|
kind: Service
|
|
metadata:
|
|
name: mpc-node
|
|
namespace: lux-bridge
|
|
spec:
|
|
selector:
|
|
app: mpc-node
|
|
clusterIP: None
|
|
ports:
|
|
- port: 9651
|
|
targetPort: 9651
|
|
name: zap
|
|
- port: 8080
|
|
targetPort: 8080
|
|
name: api
|
|
---
|
|
# MPC API service — bridge-server uses MPC_URL=http://mpc-api-svc.lux-bridge.svc:8081
|
|
#
|
|
# targetPort MUST be 9800: mpcd's API listener is `mpcd start --api :9800`
|
|
# (cmd/mpcd/main.go, --api-listen). Nothing has ever bound :8080 in the pod —
|
|
# `netstat -ltn` inside mpc-node-0 shows 7301/9800/9653/9651 only. Because the
|
|
# StatefulSet declares no readinessProbe, kube still published all 3 pods as
|
|
# ready endpoints on the dead port, so the Service looked healthy while every
|
|
# keygen dial hung until timeout.
|
|
apiVersion: v1
|
|
kind: Service
|
|
metadata:
|
|
name: mpc-api-svc
|
|
namespace: lux-bridge
|
|
spec:
|
|
selector:
|
|
app: mpc-node
|
|
ports:
|
|
- port: 8081
|
|
targetPort: 9800
|
|
name: api
|
|
---
|
|
# Bridge Server Deployment
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: bridge-server
|
|
namespace: lux-bridge
|
|
spec:
|
|
replicas: 2
|
|
selector:
|
|
matchLabels:
|
|
app: bridge-server
|
|
template:
|
|
metadata:
|
|
labels:
|
|
app: bridge-server
|
|
spec:
|
|
containers:
|
|
- name: bridge
|
|
image: ghcr.io/luxfi/bridge-server:latest
|
|
ports:
|
|
- containerPort: 3000
|
|
name: http
|
|
env:
|
|
- name: NODE_ENV
|
|
value: production
|
|
- name: PORT
|
|
value: "3000"
|
|
- name: POSTGRES_URL
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: bridge-secrets
|
|
key: database-url
|
|
- name: NODE_ID
|
|
valueFrom:
|
|
fieldRef:
|
|
fieldPath: metadata.name
|
|
- name: MPC_THRESHOLD
|
|
value: "3"
|
|
- name: MPC_TOTAL_NODES
|
|
value: "5"
|
|
- name: MPC_KEY_PREFIX
|
|
value: bridge/mpc
|
|
- name: MPC_API_URL
|
|
value: http://mpc-api-svc.lux-bridge.svc:8081
|
|
- name: MPC_API_TOKEN
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: bridge-secrets
|
|
key: mpc-api-token
|
|
- name: MPC_WALLET_ID
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: bridge-secrets
|
|
key: mpc-wallet-id
|
|
- name: BRIDGE_FEE_COLLECTOR
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: bridge-secrets
|
|
key: fee-collector-address
|
|
livenessProbe:
|
|
httpGet:
|
|
path: /health
|
|
port: 3000
|
|
initialDelaySeconds: 30
|
|
periodSeconds: 10
|
|
readinessProbe:
|
|
httpGet:
|
|
path: /health
|
|
port: 3000
|
|
initialDelaySeconds: 10
|
|
periodSeconds: 5
|
|
resources:
|
|
requests:
|
|
memory: "512Mi"
|
|
cpu: "500m"
|
|
limits:
|
|
memory: "1Gi"
|
|
cpu: "1000m"
|
|
---
|
|
apiVersion: v1
|
|
kind: Service
|
|
metadata:
|
|
name: bridge-server
|
|
namespace: lux-bridge
|
|
spec:
|
|
selector:
|
|
app: bridge-server
|
|
ports:
|
|
- port: 3000
|
|
targetPort: 3000
|
|
name: http
|
|
type: ClusterIP
|
|
---
|
|
# Bridge UI Deployment — Vite SPA served by ghcr.io/hanzoai/spa on :80.
|
|
# BRIDGE_* env documents the build-time inlined config; for true
|
|
# per-env values the image is built with those VITE_* vars baked in.
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: bridge-ui
|
|
namespace: lux-bridge
|
|
spec:
|
|
replicas: 2
|
|
selector:
|
|
matchLabels:
|
|
app: bridge-ui
|
|
template:
|
|
metadata:
|
|
labels:
|
|
app: bridge-ui
|
|
spec:
|
|
containers:
|
|
- name: ui
|
|
image: ghcr.io/luxfi/bridge-ui:latest
|
|
ports:
|
|
- containerPort: 80
|
|
name: http
|
|
env:
|
|
- name: BRIDGE_API_HOST
|
|
value: https://bridge-api.lux.network
|
|
- name: BRIDGE_ENV
|
|
value: mainnet
|
|
- name: BRIDGE_CLIENT_ID
|
|
value: lux-bridge
|
|
- name: BRIDGE_IAM_ORG
|
|
value: lux-network
|
|
resources:
|
|
requests:
|
|
memory: "256Mi"
|
|
cpu: "250m"
|
|
limits:
|
|
memory: "512Mi"
|
|
cpu: "500m"
|
|
---
|
|
apiVersion: v1
|
|
kind: Service
|
|
metadata:
|
|
name: bridge-ui
|
|
namespace: lux-bridge
|
|
spec:
|
|
selector:
|
|
app: bridge-ui
|
|
ports:
|
|
- port: 80
|
|
targetPort: 80
|
|
name: http
|
|
type: ClusterIP
|
|
---
|
|
# PostgreSQL StatefulSet
|
|
apiVersion: apps/v1
|
|
kind: StatefulSet
|
|
metadata:
|
|
name: postgres
|
|
namespace: lux-bridge
|
|
spec:
|
|
serviceName: postgres
|
|
replicas: 1
|
|
selector:
|
|
matchLabels:
|
|
app: postgres
|
|
template:
|
|
metadata:
|
|
labels:
|
|
app: postgres
|
|
spec:
|
|
containers:
|
|
- name: postgres
|
|
image: ghcr.io/hanzoai/sql:latest
|
|
ports:
|
|
- containerPort: 5432
|
|
name: postgres
|
|
env:
|
|
- name: POSTGRES_USER
|
|
value: bridge
|
|
- name: POSTGRES_PASSWORD
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: bridge-secrets
|
|
key: postgres-password
|
|
- name: POSTGRES_DB
|
|
value: bridge
|
|
volumeMounts:
|
|
- name: postgres-data
|
|
mountPath: /var/lib/postgresql/data
|
|
livenessProbe:
|
|
exec:
|
|
command: ["pg_isready", "-U", "bridge"]
|
|
initialDelaySeconds: 30
|
|
periodSeconds: 10
|
|
volumeClaimTemplates:
|
|
- metadata:
|
|
name: postgres-data
|
|
spec:
|
|
accessModes: ["ReadWriteOnce"]
|
|
resources:
|
|
requests:
|
|
storage: 50Gi
|
|
---
|
|
apiVersion: v1
|
|
kind: Service
|
|
metadata:
|
|
name: postgres
|
|
namespace: lux-bridge
|
|
spec:
|
|
selector:
|
|
app: postgres
|
|
ports:
|
|
- port: 5432
|
|
targetPort: 5432
|
|
---
|
|
# bridge-secrets is managed externally via KMS (kms.hanzo.ai).
|
|
# Secrets stored in KMS: BRIDGE_DATABASE_URL, BRIDGE_DB_PASSWORD, MPC_DB_PASSWORD
|
|
# Apply with:
|
|
# kubectl create secret generic bridge-secrets -n lux-bridge \
|
|
# --from-literal="database-url=$(kms get BRIDGE_DATABASE_URL)" \
|
|
# --from-literal="postgres-password=$(kms get BRIDGE_DB_PASSWORD)" \
|
|
# --from-literal="mpc-db-password=$(kms get MPC_DB_PASSWORD)" \
|
|
# --dry-run=client -o yaml | kubectl apply -f -
|
|
# DO NOT add secret values here — never commit credentials to git.
|
|
---
|
|
# PersistentVolumeClaim for KV store
|
|
apiVersion: v1
|
|
kind: PersistentVolumeClaim
|
|
metadata:
|
|
name: kv-pvc
|
|
namespace: lux-bridge
|
|
spec:
|
|
accessModes:
|
|
- ReadWriteOnce
|
|
resources:
|
|
requests:
|
|
storage: 10Gi
|
|
---
|
|
# Ingress
|
|
apiVersion: networking.k8s.io/v1
|
|
kind: Ingress
|
|
metadata:
|
|
name: bridge-ingress
|
|
namespace: lux-bridge
|
|
annotations:
|
|
cert-manager.io/cluster-issuer: letsencrypt-prod
|
|
spec:
|
|
ingressClassName: ingress
|
|
tls:
|
|
- hosts:
|
|
- bridge.lux.network
|
|
- bridge-api.lux.network
|
|
secretName: bridge-lux-tls
|
|
- hosts:
|
|
- bridge.zoo.ngo
|
|
secretName: bridge-zoo-tls
|
|
- hosts:
|
|
- bridge.hanzo.ai
|
|
secretName: bridge-hanzo-tls
|
|
- hosts:
|
|
- bridge.pars.network
|
|
secretName: bridge-pars-tls
|
|
- hosts:
|
|
- bridge.spc.network
|
|
secretName: bridge-spc-tls
|
|
rules:
|
|
# Lux Network (primary)
|
|
- host: bridge.lux.network
|
|
http:
|
|
paths:
|
|
- path: /v1/
|
|
pathType: Prefix
|
|
backend:
|
|
service:
|
|
name: opnet-watcher
|
|
port:
|
|
number: 8090
|
|
- path: /
|
|
pathType: Prefix
|
|
backend:
|
|
service:
|
|
name: bridge-ui
|
|
port:
|
|
number: 80
|
|
- host: bridge-api.lux.network
|
|
http:
|
|
paths:
|
|
- path: /
|
|
pathType: Prefix
|
|
backend:
|
|
service:
|
|
name: bridge-server
|
|
port:
|
|
number: 3000
|
|
# Zoo — white-label
|
|
- host: bridge.zoo.ngo
|
|
http:
|
|
paths:
|
|
- path: /v1/
|
|
pathType: Prefix
|
|
backend:
|
|
service:
|
|
name: opnet-watcher
|
|
port:
|
|
number: 8090
|
|
- path: /
|
|
pathType: Prefix
|
|
backend:
|
|
service:
|
|
name: bridge-ui
|
|
port:
|
|
number: 80
|
|
# Hanzo — white-label
|
|
- host: bridge.hanzo.ai
|
|
http:
|
|
paths:
|
|
- path: /v1/
|
|
pathType: Prefix
|
|
backend:
|
|
service:
|
|
name: opnet-watcher
|
|
port:
|
|
number: 8090
|
|
- path: /
|
|
pathType: Prefix
|
|
backend:
|
|
service:
|
|
name: bridge-ui
|
|
port:
|
|
number: 80
|
|
# Pars — white-label
|
|
- host: bridge.pars.network
|
|
http:
|
|
paths:
|
|
- path: /v1/
|
|
pathType: Prefix
|
|
backend:
|
|
service:
|
|
name: opnet-watcher
|
|
port:
|
|
number: 8090
|
|
- path: /
|
|
pathType: Prefix
|
|
backend:
|
|
service:
|
|
name: bridge-ui
|
|
port:
|
|
number: 80
|
|
# SPC — white-label
|
|
- host: bridge.spc.network
|
|
http:
|
|
paths:
|
|
- path: /v1/
|
|
pathType: Prefix
|
|
backend:
|
|
service:
|
|
name: opnet-watcher
|
|
port:
|
|
number: 8090
|
|
- path: /
|
|
pathType: Prefix
|
|
backend:
|
|
service:
|
|
name: bridge-ui
|
|
port:
|
|
number: 80
|
|
---
|
|
# Bridge Tenant ConfigMap — loaded from manifests/tenants/*.yaml
|
|
# One key per tenant manifest. opnet-watcher reads BRIDGE_TENANT_DIR.
|
|
apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: bridge-tenants
|
|
namespace: lux-bridge
|
|
data:
|
|
lux.yaml: |
|
|
id: lux
|
|
name: "Lux Network"
|
|
hostnames: ["bridge.lux.network", "bridge.lux.io"]
|
|
home_chain_id: 96369
|
|
supported_chains: [lux-c, ethereum, base, opnet, solana, ton]
|
|
teleporter_addresses:
|
|
"96369": "kms://teleport/lux-c/teleporter"
|
|
"1": "kms://teleport/lux-c/teleporter-eth"
|
|
"8453": "kms://teleport/lux-c/teleporter-eth"
|
|
"4294967299": "kms://teleport/lux-c/teleporter-btc"
|
|
"1399811149": "kms://teleport/lux-c/teleporter-sol"
|
|
"1414483791": "kms://teleport/lux-c/teleporter-ton"
|
|
branding:
|
|
logo_url: "/static/lux/logo.svg"
|
|
primary_color: "#E84142"
|
|
theme: dark
|
|
features: {swap: true, yield: true, perps: true}
|
|
zoo.yaml: |
|
|
id: zoo
|
|
name: "Zoo Network"
|
|
hostnames: ["bridge.zoo.ngo"]
|
|
home_chain_id: 200200
|
|
supported_chains: [lux-c, ethereum, base, solana]
|
|
teleporter_addresses:
|
|
"96369": "kms://teleport/lux-c/teleporter"
|
|
"1": "kms://teleport/lux-c/teleporter-eth"
|
|
"8453": "kms://teleport/lux-c/teleporter-eth"
|
|
"1399811149": "kms://teleport/lux-c/teleporter-sol"
|
|
branding:
|
|
logo_url: "/static/zoo/logo.svg"
|
|
primary_color: "#10B981"
|
|
theme: dark
|
|
features: {swap: true, yield: true, perps: false}
|
|
hanzo.yaml: |
|
|
id: hanzo
|
|
name: "Hanzo Network"
|
|
hostnames: ["bridge.hanzo.ai"]
|
|
home_chain_id: 36963
|
|
supported_chains: [lux-c, ethereum, base, opnet]
|
|
teleporter_addresses:
|
|
"96369": "kms://teleport/lux-c/teleporter"
|
|
"1": "kms://teleport/lux-c/teleporter-eth"
|
|
"8453": "kms://teleport/lux-c/teleporter-eth"
|
|
"4294967299": "kms://teleport/lux-c/teleporter-btc"
|
|
branding:
|
|
logo_url: "/static/hanzo/logo.svg"
|
|
primary_color: "#6366F1"
|
|
theme: dark
|
|
features: {swap: true, yield: true, perps: true}
|
|
pars.yaml: |
|
|
id: pars
|
|
name: "Pars Network"
|
|
hostnames: ["bridge.pars.network"]
|
|
home_chain_id: 494949
|
|
supported_chains: [lux-c, ethereum, base]
|
|
teleporter_addresses:
|
|
"96369": "kms://teleport/lux-c/teleporter"
|
|
"1": "kms://teleport/lux-c/teleporter-eth"
|
|
"8453": "kms://teleport/lux-c/teleporter-eth"
|
|
branding:
|
|
logo_url: "/static/pars/logo.svg"
|
|
primary_color: "#F59E0B"
|
|
theme: light
|
|
features: {swap: true, yield: false, perps: false}
|
|
spc.yaml: |
|
|
id: spc
|
|
name: "SPC Network"
|
|
hostnames: ["bridge.spc.network"]
|
|
home_chain_id: 36911
|
|
supported_chains: [lux-c, ethereum, base]
|
|
teleporter_addresses:
|
|
"96369": "kms://teleport/lux-c/teleporter"
|
|
"1": "kms://teleport/lux-c/teleporter-eth"
|
|
"8453": "kms://teleport/lux-c/teleporter-eth"
|
|
branding:
|
|
logo_url: "/static/spc/logo.svg"
|
|
primary_color: "#3B82F6"
|
|
theme: dark
|
|
features: {swap: true, yield: false, perps: false}
|
|
---
|
|
# Bridge Chain ConfigMap — loaded from manifests/chains/*.yaml
|
|
# One key per chain manifest. opnet-watcher reads BRIDGE_CHAIN_DIR.
|
|
apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: bridge-chains
|
|
namespace: lux-bridge
|
|
data:
|
|
lux-c.yaml: |
|
|
chain_id: 96369
|
|
name: "Lux C-Chain"
|
|
class: lux_native
|
|
tier: yield_enabled
|
|
assets:
|
|
- ticker: LUX
|
|
decimals: 18
|
|
recipient_encoding: evm_address
|
|
wrapper: {symbol: LUX, contract: "token/LUX.sol", decimals: 18}
|
|
finality: {mode: instant, confirmations: 1}
|
|
ethereum.yaml: |
|
|
chain_id: 1
|
|
name: "Ethereum"
|
|
class: evm
|
|
tier: yield_enabled
|
|
assets:
|
|
- ticker: ETH
|
|
decimals: 18
|
|
recipient_encoding: evm_address
|
|
wrapper: {symbol: LETH, contract: "liquid/tokens/LETH.sol", decimals: 18}
|
|
- ticker: USDC
|
|
decimals: 6
|
|
recipient_encoding: evm_address
|
|
wrapper: {symbol: LUSD, contract: "liquid/tokens/LUSD.sol", decimals: 18}
|
|
- ticker: USDT
|
|
decimals: 6
|
|
recipient_encoding: evm_address
|
|
wrapper: {symbol: LUSD, contract: "liquid/tokens/LUSD.sol", decimals: 18}
|
|
- ticker: DAI
|
|
decimals: 18
|
|
recipient_encoding: evm_address
|
|
wrapper: {symbol: LUSD, contract: "liquid/tokens/LUSD.sol", decimals: 18}
|
|
finality: {mode: slot_finalized, confirmations: 64}
|
|
base.yaml: |
|
|
chain_id: 8453
|
|
name: "Base"
|
|
class: evm
|
|
tier: yield_enabled
|
|
assets:
|
|
- ticker: ETH
|
|
decimals: 18
|
|
recipient_encoding: evm_address
|
|
wrapper: {symbol: LETH, contract: "liquid/tokens/LETH.sol", decimals: 18}
|
|
- ticker: USDC
|
|
decimals: 6
|
|
recipient_encoding: evm_address
|
|
wrapper: {symbol: LUSD, contract: "liquid/tokens/LUSD.sol", decimals: 18}
|
|
finality: {mode: block_depth, confirmations: 12}
|
|
opnet.yaml: |
|
|
chain_id: 4294967299
|
|
name: "OP_NET"
|
|
class: bitcoin_script
|
|
tier: yield_enabled
|
|
assets:
|
|
- ticker: BTC
|
|
decimals: 8
|
|
recipient_encoding: bech32
|
|
wrapper: {symbol: LBTC, contract: "liquid/tokens/LBTC.sol", decimals: 18}
|
|
finality: {mode: block_depth, confirmations: 6}
|
|
solana.yaml: |
|
|
chain_id: 1399811149
|
|
name: "Solana"
|
|
class: account_native
|
|
tier: locale_only
|
|
assets:
|
|
- ticker: SOL
|
|
decimals: 9
|
|
recipient_encoding: base58
|
|
wrapper: {symbol: LSOL, contract: "liquid/tokens/LSOL.sol", decimals: 18}
|
|
finality: {mode: slot_finalized, confirmations: 32}
|
|
ton.yaml: |
|
|
chain_id: 1414483791
|
|
name: "TON"
|
|
class: account_native
|
|
tier: locale_only
|
|
assets:
|
|
- ticker: TON
|
|
decimals: 9
|
|
recipient_encoding: raw_bytes
|
|
wrapper: {symbol: LTON, contract: "liquid/tokens/LTON.sol", decimals: 18}
|
|
finality: {mode: block_depth, confirmations: 1}
|
|
---
|
|
# OPNET Watcher ConfigMap
|
|
apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: opnet-watcher-config
|
|
namespace: lux-bridge
|
|
data:
|
|
config.yaml: |
|
|
lux_rpc: https://api.lux.network/v1/chain/C/rpc
|
|
zoo_rpc: https://api.zoo.network/v1/chain/C/rpc
|
|
opnet_rpc: https://opnet.lux.network/rpc
|
|
teleporter_address: ""
|
|
lux_chain_id: 96369
|
|
zoo_chain_id: 200200
|
|
opnet_chain_id: 4294967299
|
|
poll_interval_seconds: 12
|
|
confirmations: 6
|
|
health_port: 8080
|
|
---
|
|
# OPNET Watcher Deployment
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: opnet-watcher
|
|
namespace: lux-bridge
|
|
spec:
|
|
replicas: 1
|
|
selector:
|
|
matchLabels:
|
|
app: opnet-watcher
|
|
template:
|
|
metadata:
|
|
labels:
|
|
app: opnet-watcher
|
|
spec:
|
|
containers:
|
|
- name: opnet-watcher
|
|
image: ghcr.io/luxfi/opnet-watcher:latest
|
|
args: ["--config", "/config/config.yaml"]
|
|
ports:
|
|
- containerPort: 8080
|
|
name: health
|
|
- containerPort: 8090
|
|
name: api
|
|
env:
|
|
- name: MPC_API_URL
|
|
value: http://mpc-api-svc.lux-bridge.svc:8081
|
|
- name: MPC_API_TOKEN
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: bridge-secrets
|
|
key: mpc-api-token
|
|
- name: KMS_KEY_SHARES
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: opnet-watcher-secrets
|
|
key: kms-key-shares
|
|
- name: BRIDGE_TENANT_DIR
|
|
value: /etc/bridge/tenants
|
|
- name: BRIDGE_CHAIN_DIR
|
|
value: /etc/bridge/chains
|
|
volumeMounts:
|
|
- name: config
|
|
mountPath: /config
|
|
readOnly: true
|
|
- name: tenants
|
|
mountPath: /etc/bridge/tenants
|
|
readOnly: true
|
|
- name: chains
|
|
mountPath: /etc/bridge/chains
|
|
readOnly: true
|
|
livenessProbe:
|
|
httpGet:
|
|
path: /health
|
|
port: 8090
|
|
initialDelaySeconds: 10
|
|
periodSeconds: 15
|
|
readinessProbe:
|
|
httpGet:
|
|
path: /health
|
|
port: 8090
|
|
initialDelaySeconds: 5
|
|
periodSeconds: 10
|
|
resources:
|
|
requests:
|
|
memory: "128Mi"
|
|
cpu: "100m"
|
|
limits:
|
|
memory: "256Mi"
|
|
cpu: "250m"
|
|
volumes:
|
|
- name: config
|
|
configMap:
|
|
name: opnet-watcher-config
|
|
- name: tenants
|
|
configMap:
|
|
name: bridge-tenants
|
|
- name: chains
|
|
configMap:
|
|
name: bridge-chains
|
|
---
|
|
# opnet-watcher-secrets is managed externally via KMS (kms.hanzo.ai).
|
|
# Apply with:
|
|
# kubectl create secret generic opnet-watcher-secrets -n lux-bridge \
|
|
# --from-literal="kms-key-shares=$(kms get OPNET_WATCHER_KMS_KEY_SHARES)" \
|
|
# --dry-run=client -o yaml | kubectl apply -f -
|
|
# DO NOT add secret values here -- never commit keys to git.
|
|
---
|
|
apiVersion: v1
|
|
kind: Service
|
|
metadata:
|
|
name: opnet-watcher
|
|
namespace: lux-bridge
|
|
spec:
|
|
selector:
|
|
app: opnet-watcher
|
|
ports:
|
|
- port: 8080
|
|
targetPort: 8080
|
|
name: health
|
|
- port: 8090
|
|
targetPort: 8090
|
|
name: api |