bridge: sync latest — docs trim, tenant config, internal broadcast/substrate/txassembler fixes (#406)

Squash of the local main lineage onto the canonical origin/main. Net tree only
(62 files): stale docs pages removed, tenant config + tests updated, minor Go
fixes, refreshed opnet-watcher build. No third-party white-label branding in
code or history.

Co-authored-by: Hanzo Dev <[email protected]>
This commit is contained in:
2026-07-07 12:39:25 -07:00
committed by GitHub
co-authored by Hanzo Dev
parent 9357ed7b07
commit fd3bc75a29
62 changed files with 851 additions and 955 deletions
+1 -1
View File
@@ -20,7 +20,7 @@ env:
jobs: jobs:
build: build:
runs-on: [self-hosted, linux, amd64] runs-on: evo
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: docker/setup-buildx-action@v3 - uses: docker/setup-buildx-action@v3
+1 -1
View File
@@ -26,7 +26,7 @@ jobs:
publish: publish:
# Self-hosted org runner. GitHub-hosted runners are not authorised for # Self-hosted org runner. GitHub-hosted runners are not authorised for
# this org's billing plan. # this org's billing plan.
runs-on: [self-hosted, linux, amd64] runs-on: evo
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: with:
+1 -1
View File
@@ -22,7 +22,7 @@ permissions:
jobs: jobs:
goreleaser: goreleaser:
runs-on: [self-hosted, linux, amd64] runs-on: evo
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
with: with:
-86
View File
@@ -1,86 +0,0 @@
# Bridge Brand Audit (luxfi/bridge)
## Rule
`luxfi/bridge` is the Lux-branded cross-chain bridge. ONLY the Lux brand
ships from this repo. Source/destination chain identity for bridge
endpoints (chain names, chain logos, network metadata) is legitimate
network data and is kept. Foreign-org bridge brands (Hanzo, Zoo, Pars,
SPC) live in their own repos as thin shims that consume `@luxfi/bridge`.
## Findings
### Kept (chain identity / Lux's own wrapped-asset brand)
- `app/server/src/domain/settings/{mainnet,testnet,devnet}/networks.ts`:
~60 token entries with finance-domain wrapped-asset names (BTC, ETH,
Dollar wrappers). These are **Lux's own wrapped-asset brand** (the
Lux-issued wrapped version of asset X bridged to Lux C-Chain).
Confirmed via `manifests/schema.yaml:171` and per-token logos served
from `cdn.lux.network/bridge/currencies/lux/*.svg`. Kept.
- `manifests/tenants/lux.yaml`: the Lux tenant manifest. Kept.
- `manifests/chains/*` and chain references to ethereum, base, solana,
ton, opnet: source/destination network identity for bridge endpoints.
Kept.
### Removed (foreign-brand tenant data in a Lux repo)
- `manifests/tenants/hanzo.yaml` — Hanzo tenant manifest with Hanzo
logo path, Hanzo color (`#6366F1`), Hanzo name. Belongs in
`hanzoai/bridge-shim` (if Hanzo ever ships a bridge tenant), not
here.
- `manifests/tenants/zoo.yaml` — Zoo tenant manifest with Zoo logo
path, Zoo color (`#10B981`), Zoo Labs Foundation copy. Belongs in
`zooai/bridge-shim`.
- `manifests/tenants/pars.yaml` — Pars tenant manifest.
- `manifests/tenants/spc.yaml` — SPC tenant manifest.
### Rewritten (cross-brand strategy copy)
- `REQUIREMENTS.md` §1, §2, §3, §8 (Phase 2), §9 (Phase 3), §10, §11:
removed every foreign-brand tenant mention, removed Phase 2
Zoo-tenant stand-up tasks, removed Hanzo-as-tenant deliverables,
removed `@zooai/brand` / `@hanzoai/brand` publication tasks. The
doc now scopes tenant work to Lux only and the embed target to
`luxfi/exchange` only. Foreign-brand tenant repos are out-of-scope
for this codebase.
- `docs/LLM.md` (symlinked as CLAUDE.md, AGENTS.md, QWEN.md,
GEMINI.md per repo convention): removed the architecture diagram
legend pointing at `@zooai/brand` / `@hanzoai/brand` and the
"Hanzo-side bridge" section that advocated adding Hanzo tenants
under `app/`. Replaced with an explicit "foreign-brand tenants live
in their own repos" rule.
### Untouched (correct as-is)
- `docs/LLM.md` ZAP-naming rule: explicitly forbids `@hanzoai/zap-*`
variants of the brand-neutral wire codec. That's the right
anti-cross-brand stance — kept.
- All chain RPC config, teleporter contracts, and primary-network
metadata: bridge endpoint identity, not org brand.
## Actions
1. `git rm` the four foreign tenant manifests.
2. Edit REQUIREMENTS.md and docs/LLM.md to scope tenant work to Lux.
3. Add `app/bridge/public/.well-known/bridge.json` declaring Lux brand
identity, peers `[]` (federation discovery at runtime via
ConfigMap), capabilities `["bridge", "mpc"]`, apiVersion `"1"`.
## Verification
```
rg '@hanzoai|@zooai/brand|Hanzo AI Inc|Zoo Labs Foundation|Pars Network Foundation' \
--type-add 'web:*.{json,ts,tsx,js,jsx,md,yaml,yml,html}' -tweb .
```
Only remaining hits (post-cleanup): the brand-neutral ZAP rule in
docs/LLM.md (`@hanzoai/zap-*` is explicitly forbidden), which is the
correct anti-cross-brand guard.
## Follow-ups
- Add a CI lint that fails the build if `manifests/tenants/*.yaml`
contains anything other than `lux.yaml`.
- Federation peer discovery to live in a runtime ConfigMap consumed by
bridge-server at boot; UI reads peer list from `/v1/bridge/peers`.
-1
View File
@@ -1 +0,0 @@
docs/LLM.md
+670
View File
@@ -0,0 +1,670 @@
# Lux Bridge
**Project**: Lux Bridge
**Organization**: Lux Network
## Project Overview
The Lux Bridge is a decentralized cross-chain bridge infrastructure that enables secure, trustless asset transfers between multiple blockchain networks using Multi-Party Computation (MPC) technology. It serves as the primary interoperability layer for the Lux ecosystem, connecting 15+ blockchain networks.
## Package layout — public vs internal
Two scopes, one canonical SDK entrypoint. Downstream consumers (Lux, Hanzo,
Zoo, any white-label) import `@luxfi/bridge` and nothing else.
| Path | npm name | Scope | Published |
|---|---|---|---|
| `pkg/bridge/` | `@luxfi/bridge` | public SDK | pending — see §Publishing |
| `pkg/core/` | `@luxfi/core` | public shared types | yes (last 10.0.5, 2025-05-09) |
| `pkg/threshold/` | `@luxfi/threshold` | public MPC SDK | pending — see §Publishing |
| `pkg/utila/` | `@luxfi/utila` | public utila client | yes (last 3.0.0, 2024-11-21) |
| `pkg/settings/` | `@luxbridge/settings` | private workspace | no |
| `pkg/ui/` | `@luxbridge/ui-automation` | private workspace | no |
| `app/bridge/` | `@luxbridge/lux-tenant` | private workspace | no |
| `app/explorer/` | `@luxbridge/explorer` | private workspace; **migration to `ghcr.io/luxfi/explorer` planned** — see §Explorer migration | no |
| `app/server/` | `@luxbridge/server` | private workspace | no |
Rules:
- `@luxfi/bridge` is the ONLY package consumers import. It re-exports
`mountBridge`, `Bridge`, and the config/brand types. Internals are hidden.
- `@luxbridge/*` packages are workspace-only. They are not published and must
not be imported by anything outside this repo.
- `@luxfi/{core,threshold,utila}` are generic Lux building-block libraries —
bridge-agnostic, may be reused elsewhere in the Lux ecosystem.
### Canonical brand sourcing — `@luxfi/brand` is the only source
Every Lux-ecosystem tenant app — bridge, exchange, id, pay, etc. — pulls
its brand identity from **one** package: `@luxfi/brand` (source repo:
`~/work/lux/brand`). No Lux-specific brand strings, colors, logos, or
support email addresses are baked into the SDK or any other downstream
artefact.
How the bridge tenant does it (`app/bridge/src/bridge.config.ts`):
```ts
import luxBrandJson from '@luxfi/brand/brand.json'
const { shortName, primaryColor, supportEmail } = luxBrandJson.brand
export const bridgeConfig: BridgeConfig = {
apiHost: env('BRIDGE_API_HOST', 'https://api.bridge.lux.network')!,
brand: {
name: `${shortName ?? 'Lux'} Bridge`, // composed at runtime
primaryColor: primaryColor ?? '#000000',
supportEmail: supportEmail ?? '[email protected]',
},
// …
}
```
Rules:
- The **SDK** (`pkg/bridge/`) is **jurisdiction-neutral**. It declares
*no* Lux-specific brand. Tenants supply brand at mount time via
`BridgeConfig.brand`. The SDK has no direct dependency on
`@luxfi/brand` — that'd be a layering violation (Zoo, Hanzo, or any
white-label tenant must be able to consume `@luxfi/bridge` without
pulling Lux brand metadata into their bundle).
- **App-specific endpoints** (`api.bridge.lux.network`, `docs.lux.network/bridge`)
belong to the bridge product and are independent of `@luxfi/brand`'s
`appDomain` (`lux.exchange` — that's the exchange product's domain).
- **SSR / no-window fallbacks** in the SDK derive from `cfg.apiHost`
rather than hardcoding a Lux URL — see `deriveAppOrigin` in
`pkg/bridge/src/app/lib/wagmi-config.ts`.
Other Lux apps follow the same pattern: `~/work/lux/exchange` reads
the full brand block; `~/work/lux/id` reads `name` + `primaryColor` +
`appDomain`; etc. If you find a hardcoded brand string in any Lux app,
it's a leak — file it as a follow-up issue and route the value through
`@luxfi/brand`.
### History — what got folded together
- **`app/bridge3/`** (formerly `@luxbridge/app-v3`) was **folded into
`pkg/bridge/src/app/`** at commit `abed909` ("feat(pkg/bridge): inline
bridge UI under src/app/", phase 1.5). The old lazy-loaded workspace
cycle that produced the blank-page bug is gone. `Bridge.tsx` no longer
references any sibling workspace package.
- **`app/bridge/`** was collapsed to a single canonical tenant build at
`6bc55b2` ("phase2-r2: collapse to canonical app/bridge tenant"). It is
now `@luxbridge/lux-tenant` (~120 LOC: `bridge.config.ts`, `main.tsx`,
`index.html` + Vite config), not the multi-variant Next.js app shown in
stale diagrams.
## SDK mount pattern
```ts
import { mountBridge } from '@luxfi/bridge'
mountBridge({
config: {
apiHost: 'https://api.bridge.lux.network',
env: 'mainnet',
brand: { name: 'Lux Bridge', primaryColor: '#0066ff' },
},
})
```
Mirrors `mountExchange` from the upstream exchange SDK. One declarative entry,
build-time brand config, no hostname detection inside the SDK.
## Publishing
`.github/workflows/publish.yml` fires on `v*` tag push, runs on the
self-hosted `lux-build` runner. Runs `pnpm publish -r --access public
--no-git-checks` — pnpm walks the workspace, skips `private: true`
packages, and publishes any `@luxfi/*` package whose version is not yet
on npmjs.org. Bump versions in PRs; tag once merged.
**Status as of 2026-05-22**: the workflow is wired and hardened (fail-fast
on missing `NPM_TOKEN`/`NODE_AUTH_TOKEN`; token baked into the
`NPM_CONFIG_USERCONFIG` path because pnpm doesn't expand `${VAR}` in
.npmrc) but `@luxfi/bridge` and `@luxfi/threshold` are still 404 on
npmjs.org. Confirmed by `@luxfi/core` 10.0.5 and `@luxfi/utila` 3.0.0
both pre-dating every `v1.1.x` tag — no v1.1.x release has ever shipped
to npm. Most likely missing `NPM_TOKEN` secret on the `luxfi/bridge` repo
(Settings → Secrets and variables → Actions) OR an unavailable
`lux-build` runner pool. The v1.1.10 fail-fast guard will surface either
clearly on the next run.
## Explorer migration
`app/explorer/` (`@luxbridge/explorer`, Next.js standalone) is on a
deprecation path. The canonical replacement is **`ghcr.io/luxfi/explorer`**
— a single Go binary at `~/work/lux/explorer` that:
- Indexes EVM chains via [`luxfi/indexer`](https://github.com/luxfi/indexer)
- Exposes per-chain GraphQL via [`luxfi/graph`](https://github.com/luxfi/graph)
- Serves the embedded SPA from [`luxfi/explore`](https://github.com/luxfi/explore) via `go:embed`
Routes (served from one binary, port-flexible):
| Path | Purpose |
|---|---|
| `/` | SPA (embedded; SPA-routing fallback) |
| `/envs.js` | Runtime `window.ENV = {…}` |
| `/v1/indexer/{slug}/*` | Per-chain explorer REST API |
| `/v1/graph/{slug}/{subgraph}/graphql` | Per-chain, per-subgraph GraphQL |
| `/v1/explorer/realtime` | WebSocket realtime hub |
Migration plan: deploy `luxfi/explorer` alongside `app/explorer/`,
hostname-cutover (`bridge-explorer.lux.network`) on K8s, delete the
Next.js app after one-week soak.
The bridge backend (`app/server/`) does not depend on `app/explorer/`;
the migration is UI-only.
## Architecture Summary
### Core Technology Stack
- **SDK**: `@luxfi/bridge` — TypeScript source-published; React 18 + Tamagui
(`@hanzo/gui` v7 + `@hanzogui/*` peer-optional primitives); wagmi 2 + viem 2
+ `@tanstack/react-query` 5 for wallet; `@luxfi/threshold` for native MPC
threshold sign sessions
- **Tenant apps**: Vite + React 18.3.1 (`app/bridge/` = `@luxbridge/lux-tenant`,
`app/explorer/` = `@luxbridge/explorer`)
- **Backend**: Node.js + Express + Prisma (`app/server/` = bridge API at
`api.bridge.lux.network`)
- **MPC Framework**: 2-of-3 threshold signature scheme using `github.com/luxfi/mpc`
(Go); client-side session helper via `@luxfi/threshold` (TS)
- **Smart Contracts**: Solidity (OpenZeppelin), deployed on multiple chains
- **Infrastructure**: Docker, Kubernetes, PostgreSQL, NATS, Consul, Vault (KMS)
- **Authentication**: Lux ID (Casdoor) for unified auth
- **Runtime config**: `window.__ENV` (templated from `BRIDGE_*` env at container
boot by nginx docker-entrypoint) with build-time `import.meta.env.VITE_*`
fallback. One image, N envs.
### System Architecture
```
┌──────────────────────────────────┐
Tenant app │ @luxfi/bridge (pkg/bridge/) │
(app/bridge/, │ exports: Bridge, mountBridge, │
app/explorer/) │ BridgeConfig, types │
imports SDK + │ │
brand: │ Bridge UI is INLINED at │
@luxfi/bridge ─▶ │ pkg/bridge/src/app/ │
@luxfi/brand │ (no @luxbridge/app-v3, no │
│ workspace cycle, no lazy load) │
│ │
│ Direct deps: │
│ @hanzo/gui, @luxfi/threshold, │
│ wagmi, viem, react-query │
└─────────────┬────────────────────┘
│
┌────────────────┴─────────────────┐
▼ ▼
┌───────────────────────┐ ┌──────────────────────┐
│ app/server │ │ @luxfi/threshold │
│ Bridge API │ │ MPC threshold SDK │
│ Express + Prisma │ │ (consumed by BOTH │
│ api.bridge.lux.network│ │ SDK + server) │
└──────────┬────────────┘ └──────────┬───────────┘
│ │
▼ ▼
┌─────────────────────┐ ┌──────────────────┐
│ b-chain │ │ m-chain (public │
│ Lux primary network │ │ MPC, m-chain) │
│ consensus + state │ │ │
└─────────────────────┘ │ + optional │
│ private cluster │
│ (treasury fees) │
│ │
│ + optional │
│ layered cosign: │
│ Utila │
│ Fireblocks │
└──────────────────┘
```
### MPC Network Configuration
- **Node Count**: 3 nodes (2-of-3 threshold) on m-chain (public MPC)
- **Ports**:
- HTTP API: 6000-6002
- gRPC: 9090-9092
- NATS: 4223
- Consul: 8501
- **Security**: TLS 1.3, mutual authentication, HSM integration
- **Protocols**: `cggmp21` (default), `frost`, `bls`, `doerner` (classical);
`pulsar` (MLWE), `corona` (RLWE), `magnetar` (lattice research variant) —
PQ-safe, leaderless, permissionless-safe by design.
### Standalone mode — running the bridge without the Lux platform
The bridge can boot with the absolute minimum: Postgres + bridge-server +
bridge-ui. Every other Lux service (IAM / KMS / m-chain MPC / cosigners)
is **optional at runtime** — the backend graceful-degrades when the
corresponding env block is unset and picks up the integration the moment
the block appears.
```
docker compose -f compose.standalone.yml up --build
# bridge UI http://localhost:3001
# bridge API http://localhost:5000/healthz
# postgres localhost:5433 (user=bridge, pass=bridge, db=bridge)
```
What's intentionally NOT in `compose.standalone.yml` (but is in
`compose.local.yml`):
| Service | Why standalone can skip it |
|---|---|
| Casdoor (Lux ID) | bridge does not require auth in dev mode |
| Vault (KMS) | `fetchCosignerSecret` falls back to env-var pattern when `BRIDGE_KMS_URL` is unset |
| NATS | only `mpc-service.ts` consumes it; backend logs a warn and skips its initialise() |
| Consul | same — `mpc-service.ts` only |
| 3-node MPC cluster | `LuxMPCClient` is constructed on demand; native MPC sign requires it but cosigner-layered swaps don't |
To enable any of the optional layers, set the matching env block on the
`bridge-server` service in `compose.standalone.yml` (commented stubs are
already there). The bridge picks them up on next request — no restart
required for cosigner config, only `BRIDGE_MPC_URL` requires a restart (cached at server start).
### ZAP serialization — canonical home is `~/work/zap`, npm scope `@zap-proto`
The bridge currently uses plain JSON over HTTP for every wire call (mpcd,
KMS, IAM, cosigner adapters, f-chain). It does **not** depend on any
binary RPC codec. If a future surface needs Cap'n-Proto-style binary
RPC (e.g. mpcd → bridge events stream), use **ZAP** — the canonical
Lux / Hanzo zero-copy app protocol.
| Aspect | Canonical |
|---|---|
| Source repo | **`~/work/zap`** (not `~/work/lux/zap` or `~/work/hanzo/zap` — those are forks / legacy clones being consolidated upstream) |
| GitHub org | `zap-proto` |
| npm scope | `@zap-proto/*` |
| TS package | `@zap-proto/zap` (lives at `~/work/zap/zap-js`) — pure-TS codec, no third-party Cap'n Proto deps. The package.json once listed `capnp-es` in `dependencies` but no source file imports it; that dep is stale and slated for removal in the next ZAP TS publish |
| WASM binding | `@zap-proto/wasm` (`~/work/zap/zap-wasm`) |
| Go / Rust | wire-compatible siblings; same ZAP framing |
**Rules for the bridge** (and any other downstream consumer):
- **Never `pnpm add capnp-es`** to add binary RPC. If we need Cap'n-Proto-
style framing, use `@zap-proto/zap` (pure TS, no third-party dep).
The whole point of ZAP is to be brand-neutral and wire-compatible
across Go / Rust / TS without pulling in the upstream Cap'n Proto JS
ecosystem.
- The `@zap-proto/*` scope is brand-neutral. Don't publish `@luxfi/zap-*`
or `@hanzoai/zap-*` variants — they'd fork the wire format and break
cross-stack RPC.
- Source of truth for the wire format: `~/work/zap/README.md` (Go) +
`~/work/zap/zap-js/src/protocol.ts` (TS). Match either.
### Foreign-brand bridge tenants — out of this repo
The canonical Lux cross-chain bridge protocol lives at `~/work/lux/teleport`
(Warp 2.0 envelopes + m-chain custody, LP-021v2 / LP-7330). The
user-facing UI + SDK is `~/work/lux/bridge` (this repo) and ships ONE
Lux-branded tenant (`app/bridge/`). Foreign-brand bridge surfaces
(Hanzo, Zoo, Pars, third-party) MUST live in their own repos and own
their brand assets there — typically a thin shim repo (e.g.
`zooai/bridge-shim`) that consumes `@luxfi/bridge` plus its own brand
package. No foreign-brand tenant manifests, logos, or color tokens
belong in `luxfi/bridge`. The SDK is the integration point; tenants
are thin and live where their brand lives.
### Native Lux services — m-chain (MPC) + KMS + f-chain
The bridge backend talks to the canonical Lux ecosystem services via
HTTP clients in `app/server/src/clients/`:
- **`lux-iam.ts`** — `LuxIAMClient.mint(audience)` mints OAuth2
`client_credentials` JWTs against Lux IAM (`https://iam.lux.network`).
Per-audience cache with early refresh. The bridge mints one token for
`aud=lux-kms` and another for `aud=lux-mpc`; both rotate independently.
- **`lux-kms.ts`** — `LuxKMSClient.getSecret(path)` reads from
`~/work/lux/kms` (`https://kms.lux.network`). Bearer JWT auth, path
layout `bridge/cosigners/{utila|fireblocks}/{publicId}/{sa_pem|secret_pem}`.
Replaces every env-var fallback in `domain/cosigners.ts::fetchCosignerSecret`.
- **`lux-mpc.ts`** — `LuxMPCClient.keygen({...})` / `.sign({...})` /
`.status()` against `mpcd` (`https://mpc.lux.network`). This is THE
m-chain entrypoint — the canonical Lux MPC daemon at `~/work/lux/mpc`,
speaking the same wire protocol as the Go client at
`~/work/lux/kms/pkg/mpc/client.go`. Supports the full Lux protocol set
(CGGMP21 / FROST / BLS / SR25519 / Pulsar / Corona / Magnetar / Doerner).
Per-call 120s timeout matches mpcd's threshold-completion ceiling.
Configuration via env (bridge backend startup):
```
BRIDGE_IAM_ISSUER https://iam.lux.network
BRIDGE_KMS_URL https://kms.lux.network
BRIDGE_KMS_ORG lux
BRIDGE_IAM_CLIENT_ID lux-bridge
BRIDGE_IAM_CLIENT_SECRET (from KMS at boot OR --kms-bootstrap-secret)
BRIDGE_MPC_URL https://mpc.lux.network
```
When `BRIDGE_KMS_URL` is unset (local dev), `fetchCosignerSecret` falls
back to per-tenant env vars. Production deployments MUST set the KMS
env block — env-var fallback is dev-only.
### Lux software frontends (administrative UIs)
Three Lux ecosystem services ship their own administrative UIs separate
from the bridge tenant SDK:
| Service | Frontend repo / path | Stack | Domain |
|---|---|---|---|
| **m-chain (mpcd)** | `~/work/lux/mpc/dashboard/` (`@luxfi/mpc-dashboard`) | Next.js 15 + React 19 + zustand | `mpc.lux.network/dashboard` |
| **KMS** | `~/work/lux/kms/frontend/` (`@hanzo/kms-frontend`) | Vite + React | `kms.lux.network` |
| **f-chain (fhed)** | **DOES NOT EXIST** — see below | — | — |
The bridge does **not** embed these dashboards; they're separate
operator surfaces.
### f-chain frontend — what it would look like
`~/work/lux/fhe` (the FHE daemon `fhed`) currently has no dedicated UI.
The bridge tenant's `TRANSFERS` panel surfaces per-swap f-chain
attestation status (a `CosignerStep` row when the bridge backend
processes a swap with `fchain: { publicUrl, scheme }` config), but
that's per-bridge-tenant, not a cluster-wide operator surface.
A standalone f-chain dashboard, when built, would mirror the
mpc-dashboard layout and surface:
1. **Cluster status** — `GET /v1/fhe/cluster/status`: peer count, FHE
scheme registry, share health per node.
2. **Public key registry** — `GET /v1/fhe/publickey`: published FHE
public keys per scheme (CKKS / BGV / BFV), with an export button.
3. **Encryption sessions** — recent `/v1/fhe/encrypt` calls and their
ciphertext bindings (txHash → ciphertext_hex), filterable by
requesting service (bridge / pay / id / ...).
4. **Reshare history** — `/v1/fhe/cluster/reshare` events.
5. **Health probe** — `GET /v1/fhe/health` rolled up to per-node status.
Recommended scaffold (when scheduled):
```
~/work/lux/fhe/dashboard/ # new Next.js app, mirror of mpc/dashboard
package.json @luxfi/fchain-dashboard
app/ # Next.js app router
components/cluster/ # ClusterStatus, PeerList
components/keys/ # PublicKeyRegistry, ExportButton
components/sessions/ # EncryptHistory, CiphertextViewer
lib/fchain-client.ts # mirrors lux-mpc.ts / lux-kms.ts shape
```
### Optional layered cosigners (since SDK v1.0.3)
External MPC custodians can be layered ON TOP of the native threshold network
as additional cosigners. The bridge backend enforces 2-of-2 (native + layered)
before releasing settlement. Use when tenants are already on Utila or
Fireblocks for institutional custody and need regulated-cosigner gating
without giving up the native threshold property.
Browser SDK declares config only; the secret half (Utila JWT / Fireblocks
secret key) lives on `app/server/` (sourced from KMS at boot). No secret
material is ever shipped in the page bundle.
```ts
mountBridge({
config: {
apiHost: 'https://api.bridge.lux.network',
env: 'mainnet',
mpc: {
publicUrl: 'https://mpc.lux.network',
protocol: 'cggmp21',
// optional — layered cosigner #1
utila: { orgId: 'tenant-x', clientId: 'lux-bridge' },
// optional — layered cosigner #2 (both may be enabled together)
fireblocks: { apiKey: 'pub-key-id', vaultAccountId: '0' },
},
},
})
```
Per-swap, the SDK forwards a `cosigners[]` array of public identifiers
(`orgId`, `clientId`, `apiKey`, vault ids) to `POST /api/swaps`. The
backend pairs each entry with a KMS-held secret and completes the cosign
on behalf of the tenant.
## Supported Networks & Assets
### Blockchain Networks (15+)
**Layer 1**: Lux, Ethereum, BSC, Polygon, Fantom
**Layer 2**: Arbitrum, Optimism, zkSync Era, Polygon zkEVM, Base, Blast
**Other**: TON, Solana (coming soon), Cosmos (via IBC)
### Supported Assets
**Stablecoins**: USDT, USDC, DAI, ZUSD
**Native Tokens**: LUX, ETH, BNB, MATIC
**Wrapped Assets**: ZETH, ZBNB, ZPOL, ZTON (ERC20B standard)
## Key Smart Contracts
### Core Contracts
- `Bridge.sol` - Main bridge contract with deposit/withdraw logic
- `LuxVault.sol` - Asset vault for Lux Network
- `ETHVault.sol` - Ethereum vault contract
- `ZooVault.sol` - Multi-asset aggregated vault
- `LERC4626.sol` - Tokenized vault shares
### Wrapped Token Contracts (ERC20B)
All wrapped tokens follow the ERC20B standard with mint/burn capabilities:
- Location: `/contracts/contracts/zoo/`
- Examples: Z.sol, ZETH.sol, ZUSD.sol, ZBNB.sol
## API Endpoints
### REST API (Port 5000)
- `GET /api/v1/status` - Bridge operational status
- `GET /api/v1/chains` - Supported blockchains
- `GET /api/v1/assets` - Supported tokens
- `POST /api/v1/quote` - Get transfer quote
- `POST /api/v1/transfer` - Initiate transfer
- `GET /api/v1/transfer/{id}` - Transfer status
### WebSocket API
- Subscribe to transfer updates
- Real-time status notifications
- Event streaming for bridge operations
## Essential Commands
### Development
```bash
# Clone and install
git clone https://github.com/luxfi/bridge
cd bridge
pnpm install
# Install MPC tools
make install-mpc
# Start infrastructure
make up
# Start MPC nodes
make start-mpc-nodes
# Start services
cd app/bridge && pnpm dev # UI on :3001
cd app/server && pnpm dev # API on :5000
```
### Infrastructure Management
```bash
# Infrastructure
make up # Start all infra services
make down # Stop all services
make logs # View aggregated logs
# MPC Operations
make start-mpc-nodes # Start 3-node MPC network
make stop-mpc-nodes # Stop MPC nodes
make generate-mpc-keys # Generate new MPC keys
lux-mpc-cli status # Check MPC status
# Development
pnpm dev # Start development servers
pnpm build # Build for production
pnpm test # Run test suite
pnpm lint # Run linters
# Deployment
make deploy-testnet # Deploy to testnet
make deploy-mainnet # Deploy to mainnet
```
## Architecture
The bridge uses a multi-layered architecture:
1. **Presentation Layer**: React/Next.js UI for user interaction
2. **API Layer**: Node.js server handling business logic
3. **MPC Layer**: Distributed nodes for threshold signatures
4. **Blockchain Layer**: Smart contracts on multiple chains
5. **Infrastructure Layer**: Supporting services (DB, messaging, KMS)
### Data Flow
1. User initiates transfer on source chain
2. Bridge contract locks assets in vault
3. Event emitted and detected by MPC nodes
4. MPC nodes reach consensus and generate signature
5. Signed message relayed to destination chain
6. Destination contract mints wrapped tokens
7. User receives tokens on destination chain
## Key Technologies
- **Multi-Party Computation (MPC)**: Distributed key management
- **Threshold Signatures**: 2-of-3 security model
- **Smart Contracts**: Solidity with OpenZeppelin
- **Message Queue**: NATS for inter-node communication
- **Service Discovery**: Consul for dynamic configuration
- **Key Management**: HashiCorp Vault
- **Authentication**: Casdoor (Lux ID)
- **Database**: PostgreSQL for state management
- **Container Orchestration**: Docker/Kubernetes
## Development Workflow
### Local Development
1. Start infrastructure: `make up`
2. Initialize MPC network: `make start-mpc-nodes`
3. Deploy contracts: `cd contracts && npx hardhat deploy`
4. Start API server: `cd app/server && pnpm dev`
5. Start tenant UI: `cd app/bridge && pnpm dev` (Vite on :3001)
6. SDK dev: edit `pkg/bridge/src/` — tenant Vite picks up changes live
through the workspace symlink. No publish needed for local iteration.
### Testing
- Unit tests: `pnpm test:unit`
- Integration tests: `pnpm test:integration`
- Contract tests: `cd contracts && npx hardhat test`
- E2E tests: `pnpm test:e2e`
### Deployment
1. Build artifacts: `pnpm build`
2. Deploy contracts: `make deploy-{network}`
3. Update configuration
4. Deploy services via CI/CD
5. Verify deployment: `make verify-deployment`
## Configuration
### Environment Variables
```env
# Network
NETWORK=mainnet|testnet|local
CHAIN_ID=31337
# Database
DATABASE_URL=postgresql://user:pass@localhost:5433/bridge
# MPC
MPC_NODE_COUNT=3
MPC_THRESHOLD=2
# KMS (Vault)
VAULT_ADDR=http://localhost:8200
VAULT_TOKEN=<token>
# Authentication (Lux ID)
CASDOOR_ENDPOINT=http://localhost:8000
```
### Service Ports
- Bridge UI (tenant `app/bridge/`): **3001** (Vite dev/preview server)
- Bridge API (`app/server/`): 5000 (Express)
- Bridge explorer (`app/explorer/`, legacy): 3002 (Next.js)
- Bridge explorer (`ghcr.io/luxfi/explorer`, replacement): port-flexible
- MPC Nodes: 6000-6002 (HTTP), 9090-9092 (gRPC)
- PostgreSQL: 5433 (bridge), 5434 (auth)
- Vault (KMS): 8200
- Lux ID: 8000
- NATS: 4223
- Consul: 8501
## Security Best Practices
1. **Never commit secrets** - Use environment variables
2. **Validate all inputs** - Prevent injection attacks
3. **Use secure communication** - TLS 1.3 everywhere
4. **Implement rate limiting** - Prevent DDoS
5. **Regular security audits** - Contract and code reviews
6. **Monitor everything** - Logs, metrics, alerts
7. **Incident response plan** - Be prepared for emergencies
## Monitoring & Debugging
### Health Checks
- Bridge API: `curl http://localhost:5000/health`
- MPC Nodes: `curl http://localhost:6000/health`
- Infrastructure: `http://localhost:8501/ui` (Consul)
### Debugging Commands
```bash
# Check MPC status
lux-mpc-cli status --url http://localhost:6000
# View logs
tail -f logs/mpc-node-*.log
# Database queries
psql $DATABASE_URL -c "SELECT * FROM transfers WHERE status='pending';"
# NATS monitoring
nats-top -s localhost:4223
```
## Documentation
### Comprehensive Documentation Site (Nextra)
- **Location**: `~/work/lux/bridge/docs/` (Next.js + Nextra)
- **Pages**: `docs/pages/*.mdx`
- **Build**: `cd docs && pnpm install && pnpm build`
- **Dev**: `cd docs && pnpm dev` → http://localhost:3000
### Key Documentation Files
- `docs/LLM.md` — this file, canonical AI/onboarding doc (single source of truth)
- `docs/LUX-ID-INTEGRATION.md` — Casdoor-based unified auth integration
- `pkg/bridge/README.md` — consumer-facing SDK docs (`mountBridge`, `BridgeConfig`)
- Top-level `README.md` — quick-start + architecture pointer (kept consistent with this file)
The legacy migration .md files (BRIDGE-STATUS, LOCAL-SETUP, the four MPC
migration notes, DEPLOYMENT, CI-CD-DOCKER-IMAGES) were deleted in v1.1.12
(commit `b04e805`, issue #391) — they described an architecture from
before the SDK rationalization and confused new readers. Migration
history lives in `git log` and the GH release notes.
## Context for All AI Assistants
This file (`LLM.md`) is symlinked as:
- `AGENTS.md`
- `CLAUDE.md`
- `QWEN.md`
- `GEMINI.md`
All files reference the same knowledge base. Updates here propagate to all AI systems.
## Rules for AI Assistants
1. **ALWAYS** update LLM.md with significant discoveries
2. **NEVER** commit symlinked files (AGENTS.md, CLAUDE.md, etc.) - they're in .gitignore
3. **NEVER** create random summary files - update THIS file
---
**Note**: This file serves as the single source of truth for all AI assistants working on this project.
+2 -4
View File
@@ -170,10 +170,8 @@ make down # Stop infrastructure
- [`docs/LLM.md`](docs/LLM.md) — canonical AI/onboarding doc: architecture, - [`docs/LLM.md`](docs/LLM.md) — canonical AI/onboarding doc: architecture,
package layout, MPC topology, runtime config, publishing status, layered package layout, MPC topology, runtime config, publishing status, layered
cosigners, explorer migration plan cosigners, explorer migration plan
- Nextra docs site under [`docs/`](docs/) — `pnpm --filter @luxfi/bridge-docs build` - [`docs/LUX-ID-INTEGRATION.md`](docs/LUX-ID-INTEGRATION.md) — Lux ID
builds the public site (Home / Architecture / Integrations / Operator Runbook / (Casdoor) auth integration
Deploy Guide / Lux ID). Sources live at `docs/content/docs/*.mdx`, pages at
`docs/pages/*.mdx`.
- [`pkg/bridge/README.md`](pkg/bridge/README.md) — consumer-facing SDK - [`pkg/bridge/README.md`](pkg/bridge/README.md) — consumer-facing SDK
README (`mountBridge`, `BridgeConfig`, all config blocks) README (`mountBridge`, `BridgeConfig`, all config blocks)
+4 -8
View File
@@ -106,12 +106,8 @@ bridge/
│ package.json + content/docs/*.mdx). The legacy loose │ package.json + content/docs/*.mdx). The legacy loose
│ top-level *.md set (BRIDGE-STATUS, LOCAL-SETUP, │ top-level *.md set (BRIDGE-STATUS, LOCAL-SETUP,
│ DEPLOYMENT, CI-CD-DOCKER-IMAGES, the MPC-* set) was │ DEPLOYMENT, CI-CD-DOCKER-IMAGES, the MPC-* set) was
│ deleted in the merge from main (R5). The remaining │ deleted in the merge from main (R5). Only LLM.md
│ loose docs (INTEGRATIONS, LUX-ID-INTEGRATION, the │ and LUX-ID-INTEGRATION.md remain at docs/ root.
│ operator-* set) were folded into content/docs/ in
│ v1.1.13 (issue #391 follow-up). Only LLM.md
│ remains at docs/ root because AGENTS.md / CLAUDE.md
│ symlink to it.
├── config/mpc/config.yaml Private MPC cluster config. ├── config/mpc/config.yaml Private MPC cluster config.
├── k8s/mpc-deployment.yaml Public MPC (m-chain) deployment manifests. ├── k8s/mpc-deployment.yaml Public MPC (m-chain) deployment manifests.
└── REQUIREMENTS.md This document. └── REQUIREMENTS.md This document.
@@ -139,7 +135,7 @@ Notable removals from prior drafts:
| Server-side cosigner glue | **Merged** — `app/server/src/domain/cosigners.ts` + Fireblocks/native tests. End-to-end soak against a real Utila/Fireblocks tenant still pending. | `app/server/` | | Server-side cosigner glue | **Merged** — `app/server/src/domain/cosigners.ts` + Fireblocks/native tests. End-to-end soak against a real Utila/Fireblocks tenant still pending. | `app/server/` |
| Lux tenant app (`app/bridge/`) | `@luxbridge/lux-tenant` v1.0.0 — thin shell | This repo | | Lux tenant app (`app/bridge/`) | `@luxbridge/lux-tenant` v1.0.0 — thin shell | This repo |
| Zoo tenant app | Pending — needs new tenant repo (see §10) | TBD | | Zoo tenant app | Pending — needs new tenant repo (see §10) | TBD |
| White-label tenant backend wire-up | Later | After Lux/Zoo tenants ship | | Additional white-label backend wire-up | Later | After Lux/Zoo tenants ship |
### 5.3 SDK public API surface (verified against `pkg/bridge/src/index.ts`) ### 5.3 SDK public API surface (verified against `pkg/bridge/src/index.ts`)
@@ -286,7 +282,7 @@ Status of original Phase 1 line items:
| 1.2 | Commit the in-flight SDK edits that resolved the `@luxbridge/app` workspace cycle. | ✅ — see Phase 1.5 history note in `pkg/bridge/src/Bridge.tsx`. | | 1.2 | Commit the in-flight SDK edits that resolved the `@luxbridge/app` workspace cycle. | ✅ — see Phase 1.5 history note in `pkg/bridge/src/Bridge.tsx`. |
| 1.3 | Run the SDK end-to-end against Lux testnet. | 🟡 — verify on current branch before mainnet cutover. | | 1.3 | Run the SDK end-to-end against Lux testnet. | 🟡 — verify on current branch before mainnet cutover. |
| 1.4 | Deploy the Lux tenant app to `bridge.lux.network`. | 🟡 — `app/bridge/` shape is final (`Dockerfile`, `docker-entrypoint.sh`, `__ENV.js` template all merged); deploy pipeline TBC. | | 1.4 | Deploy the Lux tenant app to `bridge.lux.network`. | 🟡 — `app/bridge/` shape is final (`Dockerfile`, `docker-entrypoint.sh`, `__ENV.js` template all merged); deploy pipeline TBC. |
| 1.5 | Refresh / fold the legacy `docs/*.md` (`BRIDGE-STATUS`, `LOCAL-SETUP`, etc.). | ✅ — legacy migration set deleted in v1.1.12; remaining loose docs (`INTEGRATIONS`, `LUX-ID-INTEGRATION`, operator runbooks) folded into `docs/content/docs/*.mdx` and surfaced as Nextra pages in v1.1.13 (issue #391). Only `docs/LLM.md` remains at docs root as the symlink target for `AGENTS.md`. | | 1.5 | Refresh / fold the legacy `docs/*.md` (`BRIDGE-STATUS`, `LOCAL-SETUP`, etc.). | ✅ — the loose top-level set was deleted in the merge from main; only `docs/LLM.md` and `docs/LUX-ID-INTEGRATION.md` remain at docs root, and active docs now live under `docs/content/docs/`. |
| 1.6 | Keep `pkg/bridge/README.md` accurate (it was updated through R2/R3). | ✅ — consumer-facing README documents `Bridge`, `mountBridge`, `applyBrandMetadata`, `getConfig`, `setConfig`. | | 1.6 | Keep `pkg/bridge/README.md` accurate (it was updated through R2/R3). | ✅ — consumer-facing README documents `Bridge`, `mountBridge`, `applyBrandMetadata`, `getConfig`, `setConfig`. |
**Acceptance criteria** (recheck before sign-off): **Acceptance criteria** (recheck before sign-off):
+1 -1
View File
@@ -13,7 +13,7 @@
// DELETE /v1/kms/orgs/{org}/secrets/{path...} — delete a secret (admin) // DELETE /v1/kms/orgs/{org}/secrets/{path...} — delete a secret (admin)
// //
// Auth: Bearer JWT with `aud` claim matching the bridge's tenant id // Auth: Bearer JWT with `aud` claim matching the bridge's tenant id
// (e.g. `liquidity-bd`, `lux-bridge`). Token is minted by Lux IAM via // (e.g. `acme-bd`, `lux-bridge`). Token is minted by Lux IAM via
// `IAMClient.mint('kms')` and cached for its TTL. // `IAMClient.mint('kms')` and cached for its TTL.
// //
// All secrets returned are STRINGS (PEM, JSON, bytes — caller decides // All secrets returned are STRINGS (PEM, JSON, bytes — caller decides
+2 -2
View File
@@ -40,8 +40,8 @@ import (
// pool size. The InMemoryStore path keeps the same shape in a map // pool size. The InMemoryStore path keeps the same shape in a map
// so unit tests don't need a disk store. // so unit tests don't need a disk store.
// //
// Brand: the pool is a Lux-network surface (the bridge itself ships // Brand: the pool is a Lux-network surface. No white-label brand
// in ~/work/lux/bridge). // references.
// ============================================================================= // =============================================================================
// Persistence interface // Persistence interface
+5 -15
View File
@@ -1,4 +1,4 @@
# Lux Bridge - AI Assistant Knowledge Base # Lux Bridge
**Project**: Lux Bridge **Project**: Lux Bridge
**Organization**: Lux Network **Organization**: Lux Network
@@ -10,7 +10,7 @@ The Lux Bridge is a decentralized cross-chain bridge infrastructure that enables
## Package layout — public vs internal ## Package layout — public vs internal
Two scopes, one canonical SDK entrypoint. Downstream consumers (Lux, Hanzo, Two scopes, one canonical SDK entrypoint. Downstream consumers (Lux, Hanzo,
Zoo, any white-label tenant) import `@luxfi/bridge` and nothing else. Zoo, any white-label) import `@luxfi/bridge` and nothing else.
| Path | npm name | Scope | Published | | Path | npm name | Scope | Published |
|---|---|---|---| |---|---|---|---|
@@ -149,9 +149,7 @@ Routes (served from one binary, port-flexible):
Migration plan: deploy `luxfi/explorer` alongside `app/explorer/`, Migration plan: deploy `luxfi/explorer` alongside `app/explorer/`,
hostname-cutover (`bridge-explorer.lux.network`) on K8s, delete the hostname-cutover (`bridge-explorer.lux.network`) on K8s, delete the
Next.js app after one-week soak. Same pattern as a `graphprotocol/graph-node` Next.js app after one-week soak.
→ embedded Go explorer cutover (replacing a Next.js indexer UI with the
single-binary `luxfi/explorer` over `luxfi/indexer` + `luxfi/graph`).
The bridge backend (`app/server/`) does not depend on `app/explorer/`; The bridge backend (`app/server/`) does not depend on `app/explorer/`;
the migration is UI-only. the migration is UI-only.
@@ -676,12 +674,7 @@ nats-top -s localhost:4223
### Key Documentation Files ### Key Documentation Files
- `docs/LLM.md` — this file, canonical AI/onboarding doc (single source of truth) - `docs/LLM.md` — this file, canonical AI/onboarding doc (single source of truth)
- `docs/content/docs/index.mdx` — Architecture page (deep-dive served at `/docs`) - `docs/LUX-ID-INTEGRATION.md` — Casdoor-based unified auth integration
- `docs/content/docs/integrations.mdx` — Go-side operator integration guide
- `docs/content/docs/lux-id-integration.mdx` — Casdoor-based unified auth integration
- `docs/content/docs/operator-runbook.mdx` — `cmd/bridge` runtime operations
- `docs/content/docs/operator-deploy.mdx` — production deploy to `bridge.lux.network`
- `docs/pages/*.mdx` — thin Nextra page wrappers that surface the content above
- `pkg/bridge/README.md` — consumer-facing SDK docs (`mountBridge`, `BridgeConfig`) - `pkg/bridge/README.md` — consumer-facing SDK docs (`mountBridge`, `BridgeConfig`)
- Top-level `README.md` — quick-start + architecture pointer (kept consistent with this file) - Top-level `README.md` — quick-start + architecture pointer (kept consistent with this file)
@@ -689,10 +682,7 @@ The legacy migration .md files (BRIDGE-STATUS, LOCAL-SETUP, the four MPC
migration notes, DEPLOYMENT, CI-CD-DOCKER-IMAGES) were deleted in v1.1.12 migration notes, DEPLOYMENT, CI-CD-DOCKER-IMAGES) were deleted in v1.1.12
(commit `b04e805`, issue #391) — they described an architecture from (commit `b04e805`, issue #391) — they described an architecture from
before the SDK rationalization and confused new readers. Migration before the SDK rationalization and confused new readers. Migration
history lives in `git log` and the GH release notes. The remaining loose history lives in `git log` and the GH release notes.
`.md` files at `docs/` root were folded into the Nextra `content/docs/`
tree in v1.1.13 (issue #391 follow-up) — only `docs/LLM.md` remains
loose because it's the symlink target for `AGENTS.md` / `CLAUDE.md`.
## Context for All AI Assistants ## Context for All AI Assistants
+1 -1
View File
@@ -1 +1 @@
<!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><title>404: This page could not be found</title><meta name="next-head-count" content="3"/><link rel="preload" href="/_next/static/css/f996cf9b737d77f6.css" as="style"/><link rel="stylesheet" href="/_next/static/css/f996cf9b737d77f6.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/_next/static/chunks/polyfills-42372ed130431b0a.js"></script><script src="/_next/static/chunks/webpack-6ef43a8d4a395f49.js" defer=""></script><script src="/_next/static/chunks/framework-0cbe3b56a5f66701.js" defer=""></script><script src="/_next/static/chunks/main-35d29b002b9b8976.js" defer=""></script><script src="/_next/static/chunks/pages/_app-048d9d4ed025df82.js" defer=""></script><script src="/_next/static/chunks/pages/_error-16075e78949bdb8e.js" defer=""></script><script src="/_next/static/hnS4DkNCR004by-hexIXU/_buildManifest.js" defer=""></script><script src="/_next/static/hnS4DkNCR004by-hexIXU/_ssgManifest.js" defer=""></script></head><body><div id="__next"><div style="font-family:system-ui,&quot;Segoe UI&quot;,Roboto,Helvetica,Arial,sans-serif,&quot;Apple Color Emoji&quot;,&quot;Segoe UI Emoji&quot;;height:100vh;text-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center"><div style="line-height:48px"><style>body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}</style><h1 class="next-error-h1" style="display:inline-block;margin:0 20px 0 0;padding-right:23px;font-size:24px;font-weight:500;vertical-align:top">404</h1><div style="display:inline-block"><h2 style="font-size:14px;font-weight:400;line-height:28px">This page could not be found<!-- -->.</h2></div></div></div></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{"statusCode":404}},"page":"/_error","query":{},"buildId":"hnS4DkNCR004by-hexIXU","nextExport":true,"isFallback":false,"gip":true,"scriptLoader":[]}</script></body></html> <!DOCTYPE html><html><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width"/><title>404: This page could not be found</title><meta name="next-head-count" content="3"/><link rel="preload" href="/bridge/_next/static/css/83ce42764a171fc6.css" as="style"/><link rel="stylesheet" href="/bridge/_next/static/css/83ce42764a171fc6.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/bridge/_next/static/chunks/polyfills-42372ed130431b0a.js"></script><script src="/bridge/_next/static/chunks/webpack-abd991c5840a0e22.js" defer=""></script><script src="/bridge/_next/static/chunks/framework-64ad27b21261a9ce.js" defer=""></script><script src="/bridge/_next/static/chunks/main-fbce30a623cb8c9a.js" defer=""></script><script src="/bridge/_next/static/chunks/pages/_app-26f5890917895004.js" defer=""></script><script src="/bridge/_next/static/chunks/pages/_error-7a92967bea80186d.js" defer=""></script><script src="/bridge/_next/static/iGOSXVPr-sBS_hhOM0Cnj/_buildManifest.js" defer=""></script><script src="/bridge/_next/static/iGOSXVPr-sBS_hhOM0Cnj/_ssgManifest.js" defer=""></script></head><body><div id="__next"><div style="font-family:system-ui,&quot;Segoe UI&quot;,Roboto,Helvetica,Arial,sans-serif,&quot;Apple Color Emoji&quot;,&quot;Segoe UI Emoji&quot;;height:100vh;text-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center"><div style="line-height:48px"><style>body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}</style><h1 class="next-error-h1" style="display:inline-block;margin:0 20px 0 0;padding-right:23px;font-size:24px;font-weight:500;vertical-align:top">404</h1><div style="display:inline-block"><h2 style="font-size:14px;font-weight:400;line-height:28px">This page could not be found<!-- -->.</h2></div></div></div></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{"statusCode":404}},"page":"/_error","query":{},"buildId":"iGOSXVPr-sBS_hhOM0Cnj","assetPrefix":"/bridge","nextExport":true,"isFallback":false,"gip":true,"scriptLoader":[]}</script></body></html>
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
{"/docs":{"title":"Docs","data":{}},"/integrations":{"title":"Integrations","data":{}},"/":{"title":"Lux Bridge Documentation","data":{"":"Welcome to the documentation for the Lux Bridge — a decentralized cross-chain\nbridge using Multi-Party Computation (MPC) for secure, trustless asset transfers\nacross 15+ blockchain networks.","quick-links#Quick Links":"Architecture — System design, MPC model, packages, and components\nIntegrations — Add a new source chain (Go-side plugin guide)\nOperator Runbook — Run the unified cmd/bridge daemon\nDeploy Guide — Production deploy to bridge.lux.network\nLux ID — Casdoor-based unified auth","what-is-lux-bridge#What is Lux Bridge?":"The Lux Bridge enables:\nSecure asset transfers — move tokens between 15+ chains with 2-of-3 threshold signatures\nMulti-Party Computation — distributed key generation, no single point of failure\nPost-quantum-safe option — lattice-based MPC protocols (pulsar, corona, magnetar)\nOptional layered cosigners — Utila or Fireblocks on top of native MPC\nUniversal message passing — arbitrary cross-chain messages, not just token transfers\nLow fees & fast finality — competitive bridge fee with caps, minutes not hours","supported-networks#Supported Networks":"","layer-1#Layer 1":"Lux Network\nEthereum\nBNB Smart Chain\nPolygon\nAvalanche\nFantom","layer-2#Layer 2":"Arbitrum One\nOptimism\nzkSync Era\nPolygon zkEVM\nBase\nBlast","getting-started#Getting Started":"The bridge ships as a single Go binary (cmd/bridge) that embeds the SPA and\nserves both the UI and the native /v1/bridge/* API on one port.\n# Pull and run the unified bridge image\ndocker run --rm -p 8080:8080 \\\n -v $(pwd)/networks.yaml:/etc/bridge/networks.yaml \\\n ghcr.io/luxfi/bridge:latest\nVisit http://localhost:8080 for the bridge UI; the\nnative API is at http://localhost:8080/v1/bridge.For SDK consumers (Lux, Hanzo, Zoo, white-label tenants), import the public\n@luxfi/bridge package and call mountBridge(...) — see the pkg/bridge\nREADME for tenant usage.For local dev (workspace install, watcher fleet, tenant SPAs), see the top-level\nREADME.md.","canonical-ai--onboarding-doc#Canonical AI / Onboarding Doc":"The single source of truth for the architecture and conventions of this repo\nis docs/LLM.md. It\nis consumed verbatim by AI assistants (via AGENTS.md symlink) and is the\nfirst thing a new contributor should read.","need-help#Need Help?":"Join our Discord\nFollow us on Twitter\nEmail support: [email protected]\nDocs last refreshed in v1.1.12 — see issue #391."}},"/lux-id-integration":{"title":"Lux Id Integration","data":{}},"/operator-deploy":{"title":"Operator Deploy","data":{}},"/operator-runbook":{"title":"Operator Runbook","data":{}}} {"/":{"title":"Lux Bridge Documentation","data":{"":"Welcome to the comprehensive documentation for the Lux Bridge - a decentralized cross-chain bridge infrastructure using Multi-Party Computation (MPC) for secure asset transfers.","quick-links#Quick Links":"Architecture & Design - Learn about the bridge architecture\nAPI Reference - Integrate with the bridge\nDeployment Guide - Deploy your own instance\nSecurity Best Practices - Keep your bridge secure","what-is-lux-bridge#What is Lux Bridge?":"The Lux Bridge is a decentralized cross-chain bridge that enables:\nSecure Asset Transfers - Transfer tokens between 15+ blockchain networks\nMulti-Party Computation - 2-of-3 threshold signatures for maximum security\nUniversal Message Passing - Send arbitrary messages across chains\nLow Fees - Competitive 0.3% bridge fee with caps\nFast Finality - Transfers complete in minutes, not hours","supported-networks#Supported Networks":"","layer-1#Layer 1":"Lux Network\nEthereum\nBNB Smart Chain\nPolygon\nAvalanche\nFantom","layer-2#Layer 2":"Arbitrum One\nOptimism\nzkSync Era\nPolygon zkEVM\nBase\nBlast","getting-started#Getting Started":"# Clone the repository\ngit clone https://github.com/luxfi/bridge\ncd bridge\n# Install dependencies\npnpm install\n# Start local development\nmake up\nmake start-mpc-nodes\ncd app/bridge && pnpm dev\nVisit http://localhost:3000 to see the bridge UI.","documentation-structure#Documentation Structure":"Complete Documentation - Full technical documentation\nIntegration Examples - Code examples and SDKs\nAPI Reference - REST and WebSocket APIs\nSecurity - Security guidelines","need-help#Need Help?":"Join our Discord\nFollow us on Twitter\nEmail support: [email protected]\nVersion 1.0.0 - November 2024"}},"/docs":{"title":"Docs","data":{}}}
@@ -1 +0,0 @@
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[888],{5731:function(n,u,t){(window.__NEXT_P=window.__NEXT_P||[]).push(["/_app",function(){return t(2484)}])},2484:function(n,u,t){"use strict";t.r(u),t.d(u,{default:function(){return _}});var r=t(2676);function _(n){let{Component:u,pageProps:t}=n;return(0,r.jsx)(u,{...t})}t(3272)},3272:function(){}},function(n){var u=function(u){return n(n.s=u)};n.O(0,[774,179],function(){return u(5731),u(5566)}),_N_E=n.O()}]);
@@ -0,0 +1 @@
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[888],{6840:function(n,u,t){(window.__NEXT_P=window.__NEXT_P||[]).push(["/_app",function(){return t(9645)}])},9645:function(n,u,t){"use strict";t.r(u),t.d(u,{default:function(){return _}});var r=t(5893);function _(n){let{Component:u,pageProps:t}=n;return(0,r.jsx)(u,{...t})}t(3434)},3434:function(){}},function(n){var u=function(u){return n(n.s=u)};n.O(0,[774,179],function(){return u(6840),u(3079)}),_N_E=n.O()}]);
@@ -1 +0,0 @@
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[820],{8162:function(n,_,u){(window.__NEXT_P=window.__NEXT_P||[]).push(["/_error",function(){return u(9451)}])}},function(n){n.O(0,[888,774,179],function(){return n(n.s=8162)}),_N_E=n.O()}]);
@@ -0,0 +1 @@
(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[820],{1981:function(n,_,u){(window.__NEXT_P=window.__NEXT_P||[]).push(["/_error",function(){return u(2111)}])}},function(n){n.O(0,[888,774,179],function(){return n(n.s=1981)}),_N_E=n.O()}]);
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
!function(){"use strict";var t,e,n,r,o,u,f={},i={};function c(t){var e=i[t];if(void 0!==e)return e.exports;var n=i[t]={exports:{}},r=!0;try{f[t].call(n.exports,n,n.exports,c),r=!1}finally{r&&delete i[t]}return n.exports}c.m=f,t=[],c.O=function(e,n,r,o){if(n){o=o||0;for(var u=t.length;u>0&&t[u-1][2]>o;u--)t[u]=t[u-1];t[u]=[n,r,o];return}for(var f=1/0,u=0;u<t.length;u++){for(var n=t[u][0],r=t[u][1],o=t[u][2],i=!0,l=0;l<n.length;l++)f>=o&&Object.keys(c.O).every(function(t){return c.O[t](n[l])})?n.splice(l--,1):(i=!1,o<f&&(f=o));if(i){t.splice(u--,1);var a=r();void 0!==a&&(e=a)}}return e},c.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return c.d(e,{a:e}),e},n=Object.getPrototypeOf?function(t){return Object.getPrototypeOf(t)}:function(t){return t.__proto__},c.t=function(t,r){if(1&r&&(t=this(t)),8&r||"object"==typeof t&&t&&(4&r&&t.__esModule||16&r&&"function"==typeof t.then))return t;var o=Object.create(null);c.r(o);var u={};e=e||[null,n({}),n([]),n(n)];for(var f=2&r&&t;"object"==typeof f&&!~e.indexOf(f);f=n(f))Object.getOwnPropertyNames(f).forEach(function(e){u[e]=function(){return t[e]}});return u.default=function(){return t},c.d(o,u),o},c.d=function(t,e){for(var n in e)c.o(e,n)&&!c.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:e[n]})},c.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||Function("return this")()}catch(t){if("object"==typeof window)return window}}(),c.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},c.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},c.p="/_next/",r={272:0},c.O.j=function(t){return 0===r[t]},o=function(t,e){var n,o,u=e[0],f=e[1],i=e[2],l=0;if(u.some(function(t){return 0!==r[t]})){for(n in f)c.o(f,n)&&(c.m[n]=f[n]);if(i)var a=i(c)}for(t&&t(e);l<u.length;l++)o=u[l],c.o(r,o)&&r[o]&&r[o][0](),r[o]=0;return c.O(a)},(u=self.webpackChunk_N_E=self.webpackChunk_N_E||[]).forEach(o.bind(null,0)),u.push=o.bind(null,u.push.bind(u))}(); !function(){"use strict";var t,e,n,r,o,u,f={},i={};function c(t){var e=i[t];if(void 0!==e)return e.exports;var n=i[t]={exports:{}},r=!0;try{f[t].call(n.exports,n,n.exports,c),r=!1}finally{r&&delete i[t]}return n.exports}c.m=f,t=[],c.O=function(e,n,r,o){if(n){o=o||0;for(var u=t.length;u>0&&t[u-1][2]>o;u--)t[u]=t[u-1];t[u]=[n,r,o];return}for(var f=1/0,u=0;u<t.length;u++){for(var n=t[u][0],r=t[u][1],o=t[u][2],i=!0,l=0;l<n.length;l++)f>=o&&Object.keys(c.O).every(function(t){return c.O[t](n[l])})?n.splice(l--,1):(i=!1,o<f&&(f=o));if(i){t.splice(u--,1);var a=r();void 0!==a&&(e=a)}}return e},c.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return c.d(e,{a:e}),e},n=Object.getPrototypeOf?function(t){return Object.getPrototypeOf(t)}:function(t){return t.__proto__},c.t=function(t,r){if(1&r&&(t=this(t)),8&r||"object"==typeof t&&t&&(4&r&&t.__esModule||16&r&&"function"==typeof t.then))return t;var o=Object.create(null);c.r(o);var u={};e=e||[null,n({}),n([]),n(n)];for(var f=2&r&&t;"object"==typeof f&&!~e.indexOf(f);f=n(f))Object.getOwnPropertyNames(f).forEach(function(e){u[e]=function(){return t[e]}});return u.default=function(){return t},c.d(o,u),o},c.d=function(t,e){for(var n in e)c.o(e,n)&&!c.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:e[n]})},c.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||Function("return this")()}catch(t){if("object"==typeof window)return window}}(),c.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},c.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},c.p="/bridge/_next/",r={272:0},c.O.j=function(t){return 0===r[t]},o=function(t,e){var n,o,u=e[0],f=e[1],i=e[2],l=0;if(u.some(function(t){return 0!==r[t]})){for(n in f)c.o(f,n)&&(c.m[n]=f[n]);if(i)var a=i(c)}for(t&&t(e);l<u.length;l++)o=u[l],c.o(r,o)&&r[o]&&r[o][0](),r[o]=0;return c.O(a)},(u=self.webpackChunk_N_E=self.webpackChunk_N_E||[]).forEach(o.bind(null,0)),u.push=o.bind(null,u.push.bind(u))}();
@@ -1,3 +1,3 @@
*,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }/* *,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:rgba(59,130,246,.5);--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }/*
! tailwindcss v3.4.19 | MIT License | https://tailwindcss.com ! tailwindcss v3.4.18 | MIT License | https://tailwindcss.com
*/*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.container{width:100%}@media (min-width:640px){.container{max-width:640px}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1536px){.container{max-width:1536px}}.static{position:static}.table{display:table}.cursor-default{cursor:default}:root{--foreground-rgb:0,0,0;--background-start-rgb:214,219,220;--background-end-rgb:255,255,255}@media (prefers-color-scheme:dark){:root{--foreground-rgb:255,255,255;--background-start-rgb:0,0,0;--background-end-rgb:0,0,0}}body{color:rgb(var(--foreground-rgb));background:linear-gradient(to bottom,transparent,rgb(var(--background-end-rgb))) rgb(var(--background-start-rgb))}.nextra-content{max-width:72rem}pre{overflow-x:auto}code{font-size:.875rem;line-height:1.25rem}table{width:100%;border-collapse:collapse}th{border-bottom-width:2px;--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity,1));padding:.5rem;text-align:left}th:is(.dark *){--tw-border-opacity:1;border-color:rgb(55 65 81/var(--tw-border-opacity,1))}td{border-bottom-width:1px;--tw-border-opacity:1;border-color:rgb(229 231 235/var(--tw-border-opacity,1));padding:.5rem}td:is(.dark *){--tw-border-opacity:1;border-color:rgb(31 41 55/var(--tw-border-opacity,1))} */*,:after,:before{box-sizing:border-box;border:0 solid #e5e7eb}:after,:before{--tw-content:""}:host,html{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:ui-sans-serif,system-ui,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,pre,samp{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dd,dl,figure,h1,h2,h3,h4,h5,h6,hr,p,pre{margin:0}fieldset{margin:0}fieldset,legend{padding:0}menu,ol,ul{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}[role=button],button{cursor:pointer}:disabled{cursor:default}audio,canvas,embed,iframe,img,object,svg,video{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.cursor-default{cursor:default}:root{--foreground-rgb:0,0,0;--background-start-rgb:214,219,220;--background-end-rgb:255,255,255}@media (prefers-color-scheme:dark){:root{--foreground-rgb:255,255,255;--background-start-rgb:0,0,0;--background-end-rgb:0,0,0}}body{color:rgb(var(--foreground-rgb));background:linear-gradient(to bottom,transparent,rgb(var(--background-end-rgb))) rgb(var(--background-start-rgb))}.nextra-content{max-width:72rem}pre{overflow-x:auto}code{font-size:.875rem;line-height:1.25rem}table{width:100%;border-collapse:collapse}th{border-bottom-width:2px;--tw-border-opacity:1;border-color:rgb(209 213 219/var(--tw-border-opacity,1));padding:.5rem;text-align:left}th:is(.dark *){--tw-border-opacity:1;border-color:rgb(55 65 81/var(--tw-border-opacity,1))}td{border-bottom-width:1px;--tw-border-opacity:1;border-color:rgb(229 231 235/var(--tw-border-opacity,1));padding:.5rem}td:is(.dark *){--tw-border-opacity:1;border-color:rgb(31 41 55/var(--tw-border-opacity,1))}
@@ -1 +0,0 @@
self.__BUILD_MANIFEST=function(s,e){return{__rewrites:{afterFiles:[],beforeFiles:[],fallback:[]},"/":[s,e,"static/chunks/pages/index-3bf3b207735030b4.js"],"/_error":["static/chunks/pages/_error-16075e78949bdb8e.js"],"/docs":[s,e,"static/chunks/pages/docs-466447c1ad6de50a.js"],"/integrations":[s,e,"static/chunks/pages/integrations-f872cba62b0fc5f9.js"],"/lux-id-integration":[s,e,"static/chunks/pages/lux-id-integration-6eb74f531b98099a.js"],"/operator-deploy":[s,e,"static/chunks/pages/operator-deploy-73009920c9da835b.js"],"/operator-runbook":[s,e,"static/chunks/pages/operator-runbook-3a9641fa02470965.js"],sortedPages:["/","/_app","/_error","/docs","/integrations","/lux-id-integration","/operator-deploy","/operator-runbook"]}}("static/css/1b75bb7537b53e78.css","static/chunks/455-d1a02f1720f55d00.js"),self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB();
@@ -0,0 +1 @@
self.__BUILD_MANIFEST=function(s,c){return{__rewrites:{afterFiles:[],beforeFiles:[],fallback:[]},"/":[s,c,"static/chunks/pages/index-9752e4304f4a93c9.js"],"/_error":["static/chunks/pages/_error-7a92967bea80186d.js"],"/docs":[s,c,"static/chunks/pages/docs-7da2b52f0db4c35e.js"],sortedPages:["/","/_app","/_error","/docs"]}}("static/css/1b75bb7537b53e78.css","static/chunks/73-514932006b9ea973.js"),self.__BUILD_MANIFEST_CB&&self.__BUILD_MANIFEST_CB();
+25 -37
View File
File diff suppressed because one or more lines are too long
+32 -35
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+22 -28
View File
@@ -4,37 +4,31 @@
"type": "page" "type": "page"
}, },
"docs": { "docs": {
"title": "Architecture", "title": "Documentation",
"type": "page" "type": "page"
}, },
"integrations": { "-- API": {
"title": "Integrations",
"type": "page"
},
"operator-runbook": {
"title": "Operator Runbook",
"type": "page"
},
"operator-deploy": {
"title": "Deploy Guide",
"type": "page"
},
"lux-id-integration": {
"title": "Lux ID",
"type": "page"
},
"-- External": {
"type": "separator", "type": "separator",
"title": "External" "title": "API"
}, },
"llm": { "api": {
"title": "LLM Knowledge Base", "title": "API Reference",
"href": "https://github.com/luxfi/bridge/blob/main/docs/LLM.md", "href": "/docs#api-reference"
"newWindow": true
}, },
"github": { "-- Guides": {
"title": "GitHub ↗", "type": "separator",
"href": "https://github.com/luxfi/bridge", "title": "Guides"
"newWindow": true },
"integration": {
"title": "Integration Guide",
"href": "/docs#integration-guide"
},
"deployment": {
"title": "Deployment Guide",
"href": "/docs#deployment-guide"
},
"security": {
"title": "Security",
"href": "/docs#security-best-practices"
} }
} }
+29 -37
View File
@@ -1,27 +1,23 @@
# Lux Bridge Documentation # Lux Bridge Documentation
Welcome to the documentation for the **Lux Bridge** — a decentralized cross-chain Welcome to the comprehensive documentation for the Lux Bridge - a decentralized cross-chain bridge infrastructure using Multi-Party Computation (MPC) for secure asset transfers.
bridge using Multi-Party Computation (MPC) for secure, trustless asset transfers
across 15+ blockchain networks.
## Quick Links ## Quick Links
- [Architecture](/docs) — System design, MPC model, packages, and components - [Architecture & Design](/docs) - Learn about the bridge architecture
- [Integrations](/integrations) — Add a new source chain (Go-side plugin guide) - [API Reference](/docs#api-reference) - Integrate with the bridge
- [Operator Runbook](/operator-runbook) — Run the unified `cmd/bridge` daemon - [Deployment Guide](/docs#deployment-guide) - Deploy your own instance
- [Deploy Guide](/operator-deploy) — Production deploy to `bridge.lux.network` - [Security Best Practices](/docs#security-best-practices) - Keep your bridge secure
- [Lux ID](/lux-id-integration) — Casdoor-based unified auth
## What is Lux Bridge? ## What is Lux Bridge?
The Lux Bridge enables: The Lux Bridge is a decentralized cross-chain bridge that enables:
- **Secure asset transfers** — move tokens between 15+ chains with 2-of-3 threshold signatures - **Secure Asset Transfers** - Transfer tokens between 15+ blockchain networks
- **Multi-Party Computation** — distributed key generation, no single point of failure - **Multi-Party Computation** - 2-of-3 threshold signatures for maximum security
- **Post-quantum-safe option** — lattice-based MPC protocols (`pulsar`, `corona`, `magnetar`) - **Universal Message Passing** - Send arbitrary messages across chains
- **Optional layered cosigners** — Utila or Fireblocks on top of native MPC - **Low Fees** - Competitive 0.3% bridge fee with caps
- **Universal message passing** — arbitrary cross-chain messages, not just token transfers - **Fast Finality** - Transfers complete in minutes, not hours
- **Low fees & fast finality** — competitive bridge fee with caps, minutes not hours
## Supported Networks ## Supported Networks
@@ -43,32 +39,28 @@ The Lux Bridge enables:
## Getting Started ## Getting Started
The bridge ships as a single Go binary (`cmd/bridge`) that embeds the SPA and
serves both the UI and the native `/v1/bridge/*` API on one port.
```bash ```bash
# Pull and run the unified bridge image # Clone the repository
docker run --rm -p 8080:8080 \ git clone https://github.com/luxfi/bridge
-v $(pwd)/networks.yaml:/etc/bridge/networks.yaml \ cd bridge
ghcr.io/luxfi/bridge:latest
# Install dependencies
pnpm install
# Start local development
make up
make start-mpc-nodes
cd app/bridge && pnpm dev
``` ```
Visit [http://localhost:8080](http://localhost:8080) for the bridge UI; the Visit [http://localhost:3000](http://localhost:3000) to see the bridge UI.
native API is at [http://localhost:8080/v1/bridge](http://localhost:8080/v1/bridge).
For SDK consumers (Lux, Hanzo, Zoo, white-label tenants), import the public ## Documentation Structure
`@luxfi/bridge` package and call `mountBridge(...)` — see the [`pkg/bridge`
README](https://github.com/luxfi/bridge/tree/main/pkg/bridge) for tenant usage.
For local dev (workspace install, watcher fleet, tenant SPAs), see the top-level - **[Complete Documentation](/docs)** - Full technical documentation
[`README.md`](https://github.com/luxfi/bridge/blob/main/README.md). - **[Integration Examples](/docs#integration-guide)** - Code examples and SDKs
- **[API Reference](/docs#api-reference)** - REST and WebSocket APIs
## Canonical AI / Onboarding Doc - **[Security](/docs#security-best-practices)** - Security guidelines
The single source of truth for the architecture and conventions of this repo
is [`docs/LLM.md`](https://github.com/luxfi/bridge/blob/main/docs/LLM.md). It
is consumed verbatim by AI assistants (via `AGENTS.md` symlink) and is the
first thing a new contributor should read.
## Need Help? ## Need Help?
@@ -78,4 +70,4 @@ first thing a new contributor should read.
--- ---
*Docs last refreshed in v1.1.12 — see issue #391.* *Version 1.0.0 - November 2024*
-3
View File
@@ -1,3 +0,0 @@
import Page from '../content/docs/integrations.mdx'
<Page />
-3
View File
@@ -1,3 +0,0 @@
import Page from '../content/docs/lux-id-integration.mdx'
<Page />
-3
View File
@@ -1,3 +0,0 @@
import Page from '../content/docs/operator-deploy.mdx'
<Page />
-3
View File
@@ -1,3 +0,0 @@
import Page from '../content/docs/operator-runbook.mdx'
<Page />
+1 -2
View File
@@ -1,7 +1,6 @@
// Playwright config for the @luxfi/bridge tenant SPA. // Playwright config for the @luxfi/bridge tenant SPA.
// //
// One config, four environments. Mirrors the pattern from the liquidity // One config, four environments (E2E_ENV=dev|test|main, default `local`).
// universe e2e suite (E2E_ENV=dev|test|main, default `local`).
// //
// local: spins up `vite preview` on :3001 from app/bridge/dist // local: spins up `vite preview` on :3001 from app/bridge/dist
// (so `pnpm build` in app/bridge must have run first; the preview // (so `pnpm build` in app/bridge must have run first; the preview
+1 -1
View File
@@ -27,7 +27,7 @@
// extrinsic into its mempool" — NOT "finalized". The destination // extrinsic into its mempool" — NOT "finalized". The destination
// confirmation loop (a separate concern) polls block inclusion. // confirmation loop (a separate concern) polls block inclusion.
// //
// Brand: Lux Network surface only. // Brand: Lux Network surface — no white-label brand references.
package broadcast package broadcast
+1 -1
View File
@@ -25,7 +25,7 @@
// Trust model: this is leaf code with no network IO. Tested against // Trust model: this is leaf code with no network IO. Tested against
// known-good vectors from the Polkadot JS SDK + substrate runtime. // known-good vectors from the Polkadot JS SDK + substrate runtime.
// //
// Brand: Lux Network surface only. // Brand: Lux Network surface — no white-label brand references.
// //
// References: // References:
// - SCALE spec: https://docs.substrate.io/reference/scale-codec/ // - SCALE spec: https://docs.substrate.io/reference/scale-codec/
+1 -1
View File
@@ -37,7 +37,7 @@
// indices are pinned per-network in PerDOTNetwork — operator // indices are pinned per-network in PerDOTNetwork — operator
// updates them if a runtime upgrade renumbers the pallet. // updates them if a runtime upgrade renumbers the pallet.
// //
// Brand: Lux Network surface only. // Brand: Lux Network surface — no white-label brand references.
package txassembler package txassembler
+8 -8
View File
@@ -133,8 +133,8 @@ data:
<div class="protocol"><h3>FROST</h3><div class="proto-type">Threshold Schnorr / EdDSA</div><p>2-round signing with hedged deterministic nonces. Ed25519 for Solana and TON. BIP-340 Taproot for Bitcoin.</p></div> <div class="protocol"><h3>FROST</h3><div class="proto-type">Threshold Schnorr / EdDSA</div><p>2-round signing with hedged deterministic nonces. Ed25519 for Solana and TON. BIP-340 Taproot for Bitcoin.</p></div>
<div class="protocol"><h3>LSSS</h3><div class="proto-type">Linear Secret Sharing</div><p>Dynamic resharing without key reconstruction. Transition t-of-n configurations with zero downtime and generation rollback.</p></div> <div class="protocol"><h3>LSSS</h3><div class="proto-type">Linear Secret Sharing</div><p>Dynamic resharing without key reconstruction. Transition t-of-n configurations with zero downtime and generation rollback.</p></div>
<div class="protocol"><h3>TFHE</h3><div class="proto-type">Threshold Homomorphic Encryption</div><p>Multi-party threshold decryption with homomorphic operations. Confidential compute on encrypted data.</p></div> <div class="protocol"><h3>TFHE</h3><div class="proto-type">Threshold Homomorphic Encryption</div><p>Multi-party threshold decryption with homomorphic operations. Confidential compute on encrypted data.</p></div>
<div class="protocol"><h3>Corona</h3><div class="proto-type">Post-Quantum Lattice</div><p>Module-LWE threshold signatures at 128/192/256-bit security levels. Protection against quantum adversaries.</p></div> <div class="protocol"><h3>Ringtail</h3><div class="proto-type">Post-Quantum Lattice</div><p>Module-LWE threshold signatures at 128/192/256-bit security levels. Protection against quantum adversaries.</p></div>
<div class="protocol"><h3>Quasar</h3><div class="proto-type">Hybrid BLS + Post-Quantum</div><p>Combines BLS12-381 pairing-based signatures with Corona lattice for immediate and future-proof security.</p></div> <div class="protocol"><h3>Quasar</h3><div class="proto-type">Hybrid BLS + Post-Quantum</div><p>Combines BLS12-381 pairing-based signatures with Ringtail lattice for immediate and future-proof security.</p></div>
<div class="protocol"><h3>BLS</h3><div class="proto-type">Aggregate Signatures</div><p>BLS12-381 pairing-based threshold signatures with efficient aggregation. Compatible with consensus systems.</p></div> <div class="protocol"><h3>BLS</h3><div class="proto-type">Aggregate Signatures</div><p>BLS12-381 pairing-based threshold signatures with efficient aggregation. Compatible with consensus systems.</p></div>
<div class="protocol"><h3>Doerner</h3><div class="proto-type">Optimized 2-of-2 ECDSA</div><p>Constant-time 2-party ECDSA at ~5ms signing. Specialized for peer-to-peer custody workflows.</p></div> <div class="protocol"><h3>Doerner</h3><div class="proto-type">Optimized 2-of-2 ECDSA</div><p>Constant-time 2-party ECDSA at ~5ms signing. Specialized for peer-to-peer custody workflows.</p></div>
</div> </div>
@@ -148,7 +148,7 @@ data:
<div class="features"> <div class="features">
<div class="feature"><h3>Configurable Threshold</h3><p>Any t-of-n scheme: 3-of-5, 3-of-5, 5-of-9, or any custom configuration. Byzantine-resilient majority.</p></div> <div class="feature"><h3>Configurable Threshold</h3><p>Any t-of-n scheme: 3-of-5, 3-of-5, 5-of-9, or any custom configuration. Byzantine-resilient majority.</p></div>
<div class="feature"><h3>Dynamic Resharing</h3><p>Add or remove signing parties without changing public keys or addresses. Zero-downtime key rotation.</p></div> <div class="feature"><h3>Dynamic Resharing</h3><p>Add or remove signing parties without changing public keys or addresses. Zero-downtime key rotation.</p></div>
<div class="feature"><h3>Post-Quantum Security</h3><p>Corona lattice-based and Quasar hybrid schemes provide protection against future quantum computer attacks.</p></div> <div class="feature"><h3>Post-Quantum Security</h3><p>Ringtail lattice-based and Quasar hybrid schemes provide protection against future quantum computer attacks.</p></div>
<div class="feature"><h3>Confidential Compute</h3><p>TFHE threshold homomorphic encryption enables computation on encrypted data. Private policy evaluation.</p></div> <div class="feature"><h3>Confidential Compute</h3><p>TFHE threshold homomorphic encryption enables computation on encrypted data. Private policy evaluation.</p></div>
<div class="feature"><h3>Zero-Knowledge Proofs</h3><p>17 ZK proof systems including Paillier multiplication, Pedersen-Rabin, Schnorr proofs, and range proofs.</p></div> <div class="feature"><h3>Zero-Knowledge Proofs</h3><p>17 ZK proof systems including Paillier multiplication, Pedersen-Rabin, Schnorr proofs, and range proofs.</p></div>
<div class="feature"><h3>Multi-Chain Bridge</h3><p>Secures the Lux Bridge across 15+ blockchain networks. Threshold-signed cross-chain transactions.</p></div> <div class="feature"><h3>Multi-Chain Bridge</h3><p>Secures the Lux Bridge across 15+ blockchain networks. Threshold-signed cross-chain transactions.</p></div>
@@ -202,7 +202,7 @@ data:
<div class="features"> <div class="features">
<div class="feature"><h3>No Single Point of Failure</h3><p>Private keys are never reconstructed. Threshold parties hold shares that are individually useless.</p></div> <div class="feature"><h3>No Single Point of Failure</h3><p>Private keys are never reconstructed. Threshold parties hold shares that are individually useless.</p></div>
<div class="feature"><h3>Identifiable Aborts</h3><p>CGGMP21 identifies the exact cheating party in a failed signing session. Automated fault recovery.</p></div> <div class="feature"><h3>Identifiable Aborts</h3><p>CGGMP21 identifies the exact cheating party in a failed signing session. Automated fault recovery.</p></div>
<div class="feature"><h3>Proactive Security</h3><p>LSSS share refresh and Corona proactive rotation ensure long-term security. Generation-based key lifecycle.</p></div> <div class="feature"><h3>Proactive Security</h3><p>LSSS share refresh and Ringtail proactive rotation ensure long-term security. Generation-based key lifecycle.</p></div>
<div class="feature"><h3>Encrypted Storage</h3><p>All key shares encrypted at rest with AES-256. Optional KMS integration for hardware-backed encryption.</p></div> <div class="feature"><h3>Encrypted Storage</h3><p>All key shares encrypted at rest with AES-256. Optional KMS integration for hardware-backed encryption.</p></div>
</div> </div>
</div> </div>
@@ -367,8 +367,8 @@ data:
<div class="protocol"><h3>FROST</h3><div class="proto-type">Threshold Schnorr / EdDSA</div><p>2-round signing with hedged deterministic nonces. Ed25519 for Solana and TON. BIP-340 Taproot for Bitcoin.</p></div> <div class="protocol"><h3>FROST</h3><div class="proto-type">Threshold Schnorr / EdDSA</div><p>2-round signing with hedged deterministic nonces. Ed25519 for Solana and TON. BIP-340 Taproot for Bitcoin.</p></div>
<div class="protocol"><h3>LSSS</h3><div class="proto-type">Linear Secret Sharing</div><p>Dynamic resharing without key reconstruction. Transition t-of-n configurations with zero downtime.</p></div> <div class="protocol"><h3>LSSS</h3><div class="proto-type">Linear Secret Sharing</div><p>Dynamic resharing without key reconstruction. Transition t-of-n configurations with zero downtime.</p></div>
<div class="protocol"><h3>TFHE</h3><div class="proto-type">Threshold Homomorphic Encryption</div><p>Multi-party threshold decryption with homomorphic operations. Confidential compute on encrypted data.</p></div> <div class="protocol"><h3>TFHE</h3><div class="proto-type">Threshold Homomorphic Encryption</div><p>Multi-party threshold decryption with homomorphic operations. Confidential compute on encrypted data.</p></div>
<div class="protocol"><h3>Corona</h3><div class="proto-type">Post-Quantum Lattice</div><p>Module-LWE threshold signatures at 128/192/256-bit security levels. Protection against quantum adversaries.</p></div> <div class="protocol"><h3>Ringtail</h3><div class="proto-type">Post-Quantum Lattice</div><p>Module-LWE threshold signatures at 128/192/256-bit security levels. Protection against quantum adversaries.</p></div>
<div class="protocol"><h3>Quasar</h3><div class="proto-type">Hybrid BLS + Post-Quantum</div><p>Combines BLS12-381 pairing-based signatures with Corona lattice for immediate and future-proof security.</p></div> <div class="protocol"><h3>Quasar</h3><div class="proto-type">Hybrid BLS + Post-Quantum</div><p>Combines BLS12-381 pairing-based signatures with Ringtail lattice for immediate and future-proof security.</p></div>
<div class="protocol"><h3>BLS</h3><div class="proto-type">Aggregate Signatures</div><p>BLS12-381 pairing-based threshold signatures with efficient aggregation. Compatible with consensus systems.</p></div> <div class="protocol"><h3>BLS</h3><div class="proto-type">Aggregate Signatures</div><p>BLS12-381 pairing-based threshold signatures with efficient aggregation. Compatible with consensus systems.</p></div>
<div class="protocol"><h3>Doerner</h3><div class="proto-type">Optimized 2-of-2 ECDSA</div><p>Constant-time 2-party ECDSA at ~5ms signing. Specialized for peer-to-peer custody workflows.</p></div> <div class="protocol"><h3>Doerner</h3><div class="proto-type">Optimized 2-of-2 ECDSA</div><p>Constant-time 2-party ECDSA at ~5ms signing. Specialized for peer-to-peer custody workflows.</p></div>
</div> </div>
@@ -382,7 +382,7 @@ data:
<div class="features"> <div class="features">
<div class="feature"><h3>Configurable Threshold</h3><p>Any t-of-n scheme: 3-of-5, 3-of-5, 5-of-9, or any custom configuration. Byzantine-resilient majority.</p></div> <div class="feature"><h3>Configurable Threshold</h3><p>Any t-of-n scheme: 3-of-5, 3-of-5, 5-of-9, or any custom configuration. Byzantine-resilient majority.</p></div>
<div class="feature"><h3>Dynamic Resharing</h3><p>Add or remove signing parties without changing public keys or addresses. Zero-downtime key rotation.</p></div> <div class="feature"><h3>Dynamic Resharing</h3><p>Add or remove signing parties without changing public keys or addresses. Zero-downtime key rotation.</p></div>
<div class="feature"><h3>Post-Quantum Security</h3><p>Corona lattice-based and Quasar hybrid schemes provide protection against future quantum computer attacks.</p></div> <div class="feature"><h3>Post-Quantum Security</h3><p>Ringtail lattice-based and Quasar hybrid schemes provide protection against future quantum computer attacks.</p></div>
<div class="feature"><h3>Confidential Compute</h3><p>TFHE threshold homomorphic encryption enables computation on encrypted data. Private policy evaluation.</p></div> <div class="feature"><h3>Confidential Compute</h3><p>TFHE threshold homomorphic encryption enables computation on encrypted data. Private policy evaluation.</p></div>
<div class="feature"><h3>Zero-Knowledge Proofs</h3><p>17 ZK proof systems including Paillier multiplication, Pedersen-Rabin, Schnorr proofs, and range proofs.</p></div> <div class="feature"><h3>Zero-Knowledge Proofs</h3><p>17 ZK proof systems including Paillier multiplication, Pedersen-Rabin, Schnorr proofs, and range proofs.</p></div>
<div class="feature"><h3>Multi-Chain Bridge</h3><p>Secures the Pars Bridge across 15+ blockchain networks. Threshold-signed cross-chain transactions.</p></div> <div class="feature"><h3>Multi-Chain Bridge</h3><p>Secures the Pars Bridge across 15+ blockchain networks. Threshold-signed cross-chain transactions.</p></div>
@@ -436,7 +436,7 @@ data:
<div class="features"> <div class="features">
<div class="feature"><h3>No Single Point of Failure</h3><p>Private keys are never reconstructed. Threshold parties hold shares that are individually useless.</p></div> <div class="feature"><h3>No Single Point of Failure</h3><p>Private keys are never reconstructed. Threshold parties hold shares that are individually useless.</p></div>
<div class="feature"><h3>Identifiable Aborts</h3><p>CGGMP21 identifies the exact cheating party in a failed signing session. Automated fault recovery.</p></div> <div class="feature"><h3>Identifiable Aborts</h3><p>CGGMP21 identifies the exact cheating party in a failed signing session. Automated fault recovery.</p></div>
<div class="feature"><h3>Proactive Security</h3><p>LSSS share refresh and Corona proactive rotation ensure long-term security. Generation-based key lifecycle.</p></div> <div class="feature"><h3>Proactive Security</h3><p>LSSS share refresh and Ringtail proactive rotation ensure long-term security. Generation-based key lifecycle.</p></div>
<div class="feature"><h3>Encrypted Storage</h3><p>All key shares encrypted at rest with AES-256. Optional KMS integration for hardware-backed encryption.</p></div> <div class="feature"><h3>Encrypted Storage</h3><p>All key shares encrypted at rest with AES-256. Optional KMS integration for hardware-backed encryption.</p></div>
</div> </div>
</div> </div>
Binary file not shown.
+1 -1
View File
@@ -15,7 +15,7 @@
// - No central authority. Chain + asset lists are static client-side data // - No central authority. Chain + asset lists are static client-side data
// today; in production the bridge backend serves them, but the trust // today; in production the bridge backend serves them, but the trust
// model is the same — the user signs every transfer via threshold MPC. // model is the same — the user signs every transfer via threshold MPC.
// - PQ-safe. The signing layer uses Corona-lattice + ECDSA-CMP hybrid; // - PQ-safe. The signing layer uses Ringtail-lattice + ECDSA-CMP hybrid;
// nothing in this file makes a classical-only assumption. Wagmi handles // nothing in this file makes a classical-only assumption. Wagmi handles
// the user leg (classical secp256k1); MPC handles the bridge leg (any // the user leg (classical secp256k1); MPC handles the bridge leg (any
// protocol cfg.mpc.protocol specifies). // protocol cfg.mpc.protocol specifies).
+1 -1
View File
@@ -13,7 +13,7 @@
// `@luxfi/threshold` SDK — separate trust domain, separate signer. // `@luxfi/threshold` SDK — separate trust domain, separate signer.
// - PQ-safe at the bridge boundary: even if the user's wallet uses // - PQ-safe at the bridge boundary: even if the user's wallet uses
// classical secp256k1, the bridge-side signature can be post-quantum // classical secp256k1, the bridge-side signature can be post-quantum
// (Pulsar / Corona) because the two legs are independent. // (Ringtail / Pulsar / Corona) because the two legs are independent.
// //
// DEV mode: // DEV mode:
// When `import.meta.env.DEV` is true AND no wagmi connector is available // When `import.meta.env.DEV` is true AND no wagmi connector is available
+1 -1
View File
@@ -5,7 +5,7 @@
// at runtime — Phase 3 R2 swaps this for `useAssets(chainId)`. // at runtime — Phase 3 R2 swaps this for `useAssets(chainId)`.
// //
// PQ-safe note: asset symbols are surface-only labels. All signing is done // PQ-safe note: asset symbols are surface-only labels. All signing is done
// by the SDK's MPC layer (Corona + ECDSA hybrid) — not by anything in // by the SDK's MPC layer (Ringtail + ECDSA hybrid) — not by anything in
// this file. The asset list is data, not trust. // this file. The asset list is data, not trust.
import { ASSET_LOGOS } from './logos' import { ASSET_LOGOS } from './logos'
+9 -9
View File
@@ -43,8 +43,8 @@ type Config struct {
Network NetworkConfig `yaml:"network"` Network NetworkConfig `yaml:"network"`
// IAM points the bridge at the tenant's IAM (hanzo.id, lux.id, // IAM points the bridge at the tenant's IAM (hanzo.id, lux.id,
// zoo.id, pars.id, ...). Per the IAM SSO requirement the bridge // zoo.id, pars.id, ...). Per the IAM SSO requirement
// MUST NOT ship local auth — it federates to IAM only. // the bridge MUST NOT ship local auth — it federates to IAM only.
IAM IAMConfig `yaml:"iam"` IAM IAMConfig `yaml:"iam"`
// KMS points the bridge at the tenant's KMS (kms.hanzo.ai, // KMS points the bridge at the tenant's KMS (kms.hanzo.ai,
@@ -72,7 +72,7 @@ type Config struct {
// SupportedChains is the allowlist of chain families the daemon // SupportedChains is the allowlist of chain families the daemon
// will mount handlers for. Anything not in this list will not have // will mount handlers for. Anything not in this list will not have
// a release-pool, will not appear in /v1/bridge/networks, and will // a release-pool, will not appear in /v1/bridge/networks, and will
// refuse swap creates. Subset of {eth,btc,sol,ton,xrp,dot, // refuse swap creates. Subset of {eth,btc,sol,ton,xrp,dot,liquid,
// hanzo,zoo,pars,spc,lux}. // hanzo,zoo,pars,spc,lux}.
SupportedChains []string `yaml:"supportedChains"` SupportedChains []string `yaml:"supportedChains"`
@@ -92,7 +92,7 @@ type Config struct {
// Domain is the public DNS host the SPA + API serve on. The // Domain is the public DNS host the SPA + API serve on. The
// frontend uses this to compute absolute URLs in og:metadata; the // frontend uses this to compute absolute URLs in og:metadata; the
// k8s IngressRoute uses it as the Host() match. Example: // k8s IngressRoute uses it as the Host() match. Example:
// "bridge.lux.network" / "bridge.hanzo.network". // "bridge.zoo.network" / "bridge.hanzo.network".
Domain string `yaml:"domain"` Domain string `yaml:"domain"`
// ReleasePool is the per-family wallet-pool configuration (size + // ReleasePool is the per-family wallet-pool configuration (size +
@@ -114,11 +114,11 @@ type Config struct {
// the daemon's log "service" tag. // the daemon's log "service" tag.
type BrandConfig struct { type BrandConfig struct {
// Name is the human-readable brand label shown in the SPA header. // Name is the human-readable brand label shown in the SPA header.
// Example: "Lux Bridge", "Hanzo Bridge", "Zoo Bridge". // Example: "Lux Bridge", "Liquid Bridge", "Hanzo Bridge".
Name string `yaml:"name"` Name string `yaml:"name"`
// Slug is the machine-readable form used as the daemon's log // Slug is the machine-readable form used as the daemon's log
// service tag and the embedded app's framework AppName. Lowercase // service tag and the embedded app's framework AppName. Lowercase
// hyphenated. Example: "lux-bridge", "hanzo-bridge". // hyphenated. Example: "lux-bridge", "liquid-bridge", "hanzo-bridge".
Slug string `yaml:"slug"` Slug string `yaml:"slug"`
// PrimaryColor is the hex code (#rrggbb) the SPA themes off. // PrimaryColor is the hex code (#rrggbb) the SPA themes off.
PrimaryColor string `yaml:"primaryColor"` PrimaryColor string `yaml:"primaryColor"`
@@ -174,7 +174,7 @@ type MPCConfig struct {
// "http://mpc-node-0.mpc-node-headless.{tenant}-mpc.svc:9800". // "http://mpc-node-0.mpc-node-headless.{tenant}-mpc.svc:9800".
URL string `yaml:"url"` URL string `yaml:"url"`
// OrgID is the tenant identifier the MPC daemon multiplexes // OrgID is the tenant identifier the MPC daemon multiplexes
// keygen by. Example: "bridge", "hanzo-bridge". // keygen by. Example: "bridge", "liquid-bridge".
OrgID string `yaml:"orgID"` OrgID string `yaml:"orgID"`
// DashboardURL is the MPC dashboard API base URL — the v2026-05 // DashboardURL is the MPC dashboard API base URL — the v2026-05
// daemon serves /v1/mpc/sign there. // daemon serves /v1/mpc/sign there.
@@ -220,7 +220,7 @@ type FamilyPoolConfig struct {
// Known chain families. Anything in SupportedChains MUST be a member. // Known chain families. Anything in SupportedChains MUST be a member.
var supportedChainSet = map[string]struct{}{ var supportedChainSet = map[string]struct{}{
"eth": {}, "btc": {}, "sol": {}, "ton": {}, "xrp": {}, "dot": {}, "eth": {}, "btc": {}, "sol": {}, "ton": {}, "xrp": {}, "dot": {},
"hanzo": {}, "zoo": {}, "pars": {}, "spc": {}, "lux": {}, "liquid": {}, "hanzo": {}, "zoo": {}, "pars": {}, "spc": {}, "lux": {},
} }
// Known PQ profile values. // Known PQ profile values.
@@ -347,7 +347,7 @@ func (c *Config) Validate() error {
// SupportedChains: non-empty + every entry must be in the known set. // SupportedChains: non-empty + every entry must be in the known set.
if len(c.SupportedChains) == 0 { if len(c.SupportedChains) == 0 {
errs = append(errs, "supportedChains: required (at least one of eth,btc,sol,ton,xrp,dot,hanzo,zoo,pars,spc,lux)") errs = append(errs, "supportedChains: required (at least one of eth,btc,sol,ton,xrp,dot,liquid,hanzo,zoo,pars,spc,lux)")
} else { } else {
seen := map[string]struct{}{} seen := map[string]struct{}{}
for _, ch := range c.SupportedChains { for _, ch := range c.SupportedChains {
+2 -2
View File
@@ -126,7 +126,7 @@ func TestSupportedChainsSubset(t *testing.T) {
func TestSupportedChainsAllowedSet(t *testing.T) { func TestSupportedChainsAllowedSet(t *testing.T) {
// Every value in the spec'd allowed set must validate. // Every value in the spec'd allowed set must validate.
for _, chain := range []string{"eth", "btc", "sol", "ton", "xrp", "dot", "hanzo", "zoo", "pars", "spc", "lux"} { for _, chain := range []string{"eth", "btc", "sol", "ton", "xrp", "dot", "liquid", "hanzo", "zoo", "pars", "spc", "lux"} {
t.Run(chain, func(t *testing.T) { t.Run(chain, func(t *testing.T) {
c := validMinimal() c := validMinimal()
c.SupportedChains = []string{chain} c.SupportedChains = []string{chain}
@@ -254,7 +254,7 @@ func TestSlugFormat(t *testing.T) {
} }
}) })
} }
good := []string{"a", "ab", "lux-bridge", "hanzo-bridge", "zoo-bridge", "tenant1"} good := []string{"a", "ab", "lux-bridge", "hanzo-bridge", "liquid-bridge", "tenant1"}
for _, s := range good { for _, s := range good {
t.Run("ok-"+s, func(t *testing.T) { t.Run("ok-"+s, func(t *testing.T) {
c := validMinimal() c := validMinimal()
+3 -3
View File
@@ -6,8 +6,8 @@
# supportedChains + ingress + basket allowlist all come from this file # supportedChains + ingress + basket allowlist all come from this file
# — flag-driven defaults stay available as overrides. # — flag-driven defaults stay available as overrides.
# #
# White-label shim repos (liquidity/bridge, hanzo/bridge-shim, # White-label shim repos (hanzo/bridge-shim, zoo/bridge-shim,
# zoo/bridge-shim, pars/bridge-shim) each ship their own tenant.yaml # pars/bridge-shim) each ship their own tenant.yaml
# and import luxfi/bridge as the upstream OSS dep. See those shim # and import luxfi/bridge as the upstream OSS dep. See those shim
# repos for production examples. # repos for production examples.
@@ -42,7 +42,7 @@ network:
# #
# Federated identity binding. Required — the bridge MUST NOT ship local # Federated identity binding. Required — the bridge MUST NOT ship local
# auth. Every authenticated route resolves identity via the tenant's IAM # auth. Every authenticated route resolves identity via the tenant's IAM
# (hanzo.id, lux.id, zoo.id, pars.id, liquidity.id). # (hanzo.id, lux.id, zoo.id, pars.id).
iam: iam:
endpoint: "https://lux.id" endpoint: "https://lux.id"
clientID: "lux-bridge" clientID: "lux-bridge"