Files
bridge/app/server
zeekay 46defa98ed feat(app/server): native Lux IAM + KMS + MPC clients — m-chain wired (no env-var stubs)
User asked for native ~/work/lux/mpc + ~/work/lux/kms integration and
'pure b-chain/m-chain via mpc/kms software frontend'. Delivers the
canonical-Lux-services HTTP clients on the bridge backend.

Three new client modules in app/server/src/clients/:

  lux-iam.ts   LuxIAMClient — OAuth2 client_credentials minter against
               Lux IAM (https://iam.lux.network). Per-audience cache
               with early refresh; one cache slot per (aud=lux-kms,
               aud=lux-mpc) downstream service. invalidate() on 401.
               Mirrors ~/work/lux/kms/pkg/iamclient/client.go in TS.

  lux-kms.ts   LuxKMSClient.getSecret(path) — reads from ~/work/lux/kms
               (https://kms.lux.network) at
               /v1/kms/orgs/{org}/secrets/{path...}. Bearer JWT auth via
               LuxIAMClient. Unwraps either raw text/* or JSON envelope
               { value | secret } responses. KMSError carries httpStatus
               + path for the caller to switch on.

  lux-mpc.ts   LuxMPCClient — the canonical m-chain entrypoint. Speaks
               the same wire protocol as ~/work/lux/kms/pkg/mpc/client.go
               (~/work/lux/mpc/cmd/mpcd HTTP API). Methods:
                 keygen({ vaultId, name, keyType, protocol })
                          → POST /v1/vaults/{id}/wallets (DKG)
                 sign({ walletId, keyType, message })
                          → POST /v1/transactions  (type=sign,
                            base64 payload)
                 status()  → GET /v1/status
               Supports the full Lux protocol set: cggmp21 / frost /
               bls / sr25519 / doerner / pulsar / corona / magnetar.
               Per-call 120s timeout matches mpcd's threshold ceiling.

────────────────────────────────────────────────────────────────────────
 fetchCosignerSecret — now KMS-backed
────────────────────────────────────────────────────────────────────────
domain/cosigners.ts::fetchCosignerSecret routes through LuxKMSClient
when LUX_KMS_URL + LUX_IAM_* are set. Path layout:

  utila:      bridge/cosigners/utila/{envSafe(org_id)}/sa_pem
  fireblocks: bridge/cosigners/fireblocks/{envSafe(api_key)}/secret_pem

404 from KMS → quietly falls back to UTILA_COSIGNER_PEM__/
FIREBLOCKS_COSIGNER_PEM__ env vars (dev-only). Any other KMS error is
rethrown so the dispatcher surfaces it as a 'failed' (retryable)
CosignResult. _resetKmsClientForTests() lets tests rebuild the cached
client after mutating process.env.

────────────────────────────────────────────────────────────────────────
 docs/LLM.md
────────────────────────────────────────────────────────────────────────
- New 'Native Lux services' section: documents IAM + KMS + MPC env
  config and the audience scoping. Production MUST set the LUX_KMS_*
  block; env-var fallback is dev-only.
- New 'Lux software frontends' section: lists the three operator UIs
  (~/work/lux/mpc/dashboard Next.js, ~/work/lux/kms/frontend Vite) and
  notes the f-chain frontend does NOT exist yet.
- New 'f-chain frontend — what it would look like' section: scaffolds
  the proposed @luxfi/fchain-dashboard layout (cluster status, pubkey
  registry, encrypt-session history, reshare history, health probe)
  with the exact /v1/fhe/* endpoints each widget would consume. Note
  that the bridge tenant's TRANSFERS panel currently surfaces per-swap
  fchain attestation status (no separate UI needed for that scope).

────────────────────────────────────────────────────────────────────────
 tests — 18 new
────────────────────────────────────────────────────────────────────────
  + clients/__tests__/lux-iam.test.ts  (7 cases)
  + clients/__tests__/lux-kms.test.ts  (6 cases)
  + clients/__tests__/lux-mpc.test.ts  (8 cases — keygen / sign / status
                                                 / 401 invalidate / abort)
  + domain/__tests__/cosigners-kms-secret-fetch.test.ts  (7 cases —
        KMS happy path, env-var fallback, 404 fallthrough, 5xx propagate,
        cloud_hsm/fchain defensive guard)

Updated two pre-existing tests (cosigners-utila + cosigners-fireblocks
env-var-missing cases) to match the new 'cosigner secret unavailable'
error string from the refactored fetchCosignerSecret.

────────────────────────────────────────────────────────────────────────
 final counts
────────────────────────────────────────────────────────────────────────
  pkg/bridge SDK:    58 / 58
  app/server:        95 → 123 (+28)
  Typecheck:         clean

  Every cosigner adapter (utila / fireblocks / gcp_kms / aws_kms /
  azure_key_vault / vault_transit / fchain) is a real network call.
  fetchCosignerSecret routes through real Lux KMS.
  Native m-chain signing wired via LuxMPCClient (caller integration in
  domain/mpc-modern.ts is the next planned step — clients are now in
  place and tested).
2026-05-23 17:06:17 -07:00
..
2024-11-27 16:41:55 +08:00
2024-11-24 23:08:28 -06:00
2024-11-27 16:41:55 +08:00
2025-08-03 15:52:32 -05:00

bridge/server

The Lux Bridge Server is an API server that facilitates communication with Multi-Party Computation (MPC) nodes and manages asset swaps.

Prerequisites

•	Node.js: Version 20 or higher.
•	pnpm: Version 9.10.0 or higher.
•	Docker: Ensure Docker is installed and running.
•	Kubernetes: Access to a Kubernetes cluster for deployment.

Installation

1.	Clone the Repository:

git clone https://github.com/luxfi/bridge.git

2.	Install Dependencies:

pnpm install (from root or any project subdir)

Development

  • go into server dir

    cd server

  • generate prisma artifacts

    pnpx prisma generate

  • set up prisma to use sqlite

    in prisma/schema.prisma

datasource db {
  //provider  = "postgresql"
  provider  = "sqlite"
  url       = env("POSTGRES_URL")
  directUrl = env("POSTGRES_URL")
}
  • set env variable to point to sqlite

    in .env

    POSTGRESQL_URL=file:./dev.sqlite

  • create the local sqlite instance

    pnpx prisma db push

  • Start the dev server

    pnpm dev

This command uses nodemon to watch for file changes and restarts the server automatically.

[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): src/**/*
[nodemon] watching extensions: ts,js
[nodemon] starting `node -r tsconfig-paths/register -r ts-node/register ./src/server.ts`
>> Server is Running At: Port 5000

Building the Project

•	Build the Project:

pnpm build

This command compiles TypeScript files, resolves module aliases, and generates the Prisma client.

Docker Operations

•	Build Docker Image:

pnpm docker:build

This command builds the Docker image using Buildx for the linux/amd64 platform.

•	Log in to GitHub Container Registry:

pnpm docker:login

Ensure that the environment variables GH_USER and GH_TOKEN are set with your GitHub username and personal access token, respectively.

•	Push Docker Image:

pnpm docker:push

This command pushes the Docker image to the GitHub Container Registry.

Kubernetes Deployment

•	Apply Kubernetes Configuration:

pnpm k8s:apply

This command applies the Kubernetes deployment and service configurations located in the k8s directory.

•	Scale Deployment:

pnpm k8s:scale

Set the REPLICAS environment variable to the desired number of replicas before running this command.

•	Create Kubernetes Secret:

pnpm k8s:create-secret

Ensure the POSTGRESQL_URL environment variable is set with your PostgreSQL connection string.

•	Restart Deployment:

pnpm k8s:restart

•	Check Deployment Status:

pnpm k8s:status

This command retrieves the status of deployments, services, and pods labeled app=bridge-server.

Linting and Formatting

•	Lint Code:

pnpm lint

•	Format Code:

pnpm format

Environment Variables

The server utilizes environment variables for configuration. Create a .env file in the server directory with the following variables:

POSTGRESQL_URL=your_postgres_connection_string GH_USER=your_github_username GH_TOKEN=your_github_token REPLICAS=number_of_replicas LUX_SIGNER=

Ensure that sensitive information is kept secure and not committed to version control.