mirror of
https://github.com/luxfi/bridge.git
synced 2026-09-24 00:26:46 +00:00
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:
committed by
GitHub
co-authored by
Hanzo Dev
parent
9357ed7b07
commit
fd3bc75a29
@@ -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
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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`.
|
|
||||||
@@ -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.
|
||||||
@@ -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
@@ -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):
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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
@@ -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
@@ -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,"Segoe UI",Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";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,"Segoe UI",Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";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
+1
-1
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
@@ -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))}();
|
||||||
+2
-2
@@ -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
File diff suppressed because one or more lines are too long
+32
-35
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
@@ -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
@@ -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*
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
import Page from '../content/docs/integrations.mdx'
|
|
||||||
|
|
||||||
<Page />
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
import Page from '../content/docs/lux-id-integration.mdx'
|
|
||||||
|
|
||||||
<Page />
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
import Page from '../content/docs/operator-deploy.mdx'
|
|
||||||
|
|
||||||
<Page />
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
import Page from '../content/docs/operator-runbook.mdx'
|
|
||||||
|
|
||||||
<Page />
|
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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/
|
||||||
|
|||||||
@@ -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
|
||||||
|
|
||||||
|
|||||||
@@ -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.
@@ -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).
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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'
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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
@@ -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"
|
||||||
|
|||||||
Reference in New Issue
Block a user