This commit is contained in:
2025-12-24 14:19:52 -08:00
parent 35e29ca539
commit 669f68438a
65 changed files with 4822 additions and 410 deletions
+63
View File
@@ -0,0 +1,63 @@
name: Deploy Docs to GitHub Pages
on:
push:
branches:
- main
paths:
- 'docs/**'
- '.github/workflows/docs.yml'
workflow_dispatch:
permissions:
contents: read
pages: write
id-token: write
concurrency:
group: pages
cancel-in-progress: false
jobs:
build:
runs-on: ubuntu-latest
defaults:
run:
working-directory: docs
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
cache-dependency-path: docs/package-lock.json
- name: Setup Pages
uses: actions/configure-pages@v4
- name: Install dependencies
run: npm ci
- name: Build
run: npm run build
env:
GITHUB_PAGES: true
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
path: docs/out
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
needs: build
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4
+8
View File
@@ -78,3 +78,11 @@ postgres-data/
# Migration artifacts
migration-config.json
docker-compose.cgg21mp.yml
AGENTS.md
CLAUDE.md
GEMINI.md
GROK.md
QWEN.md
+1 -1
View File
@@ -1 +1 @@
docs/LLM.md
LLM.md
+1 -1
View File
@@ -1 +1 @@
docs/LLM.md
LLM.md
+1 -1
View File
@@ -1 +1 @@
docs/LLM.md
LLM.md
@@ -8,7 +8,7 @@ import useSWR from "swr"
import { useAccount } from "wagmi"
import { useSettings } from "@/context/settings"
import BridgeApiClient, { type Campaign, type Leaderboard, type Reward } from "@/lib/BridgeApiClient"
import BridgeRPCClient, { type Campaign, type Leaderboard, type Reward } from "@/lib/BridgeRPCClient"
import { ApiResponse } from "@/Models/ApiResponse"
import { RewardsComponentLeaderboardSkeleton } from "../../Skeletons"
@@ -32,7 +32,7 @@ const Component: React.FC<{
setOpenTopModal(true)
}
const apiClient = new BridgeApiClient()
const apiClient = new BridgeRPCClient()
const { data: leaderboardData, isLoading } = useSWR<ApiResponse<Leaderboard>>(`/campaigns/${campaign?.id}/leaderboard`, apiClient.fetcher, { dedupingInterval: 60000 })
const { data: rewardsData, isLoading: rewardsIsLoading } = useSWR<ApiResponse<Reward>>(`/campaigns/${campaign.id}/rewards/${address}`, apiClient.fetcher, { dedupingInterval: 60000 })
const leaderboard = leaderboardData?.data
@@ -10,8 +10,8 @@ import { Progress } from "@hanzo/ui/primitives";
import { useSettings } from "@/context/settings"
import BackgroundField from "../../backgroundField";
import type { Campaign, Reward, RewardPayout } from "@/lib/BridgeApiClient"
import BridgeApiClient from "@/lib/BridgeApiClient"
import type { Campaign, Reward, RewardPayout } from "@/lib/BridgeRPCClient"
import BridgeRPCClient from "@/lib/BridgeRPCClient"
import { RewardsComponentSkeleton } from "../../Skeletons"
import { ApiResponse } from "@/Models/ApiResponse"
import ClickTooltip from "../../Tooltips/ClickTooltip"
@@ -26,7 +26,7 @@ const Rewards: React.FC<{
const settings = useSettings()
const { networks } = settings
const { address } = useAccount();
const apiClient = new BridgeApiClient()
const apiClient = new BridgeRPCClient()
const { data: rewardsData, isLoading: rewardsIsLoading } = useSWR<ApiResponse<Reward>>(`/campaigns/${campaign.id}/rewards/${address}`, apiClient.fetcher, { dedupingInterval: 60000 })
const { data: payoutsData, isLoading: payoutsIsLoading } = useSWR<ApiResponse<RewardPayout[]>>(`/campaigns/${campaign.id}/payouts/${address}`, apiClient.fetcher, { dedupingInterval: 60000 })
@@ -9,7 +9,7 @@ import useSWR from 'swr'
import { LinkElement } from '@hanzo/ui/primitives'
import { useSettings } from '@/context/settings'
import BridgeApiClient, { type Campaign } from '@/lib/BridgeApiClient'
import BridgeRPCClient, { type Campaign } from '@/lib/BridgeRPCClient'
import { type ApiResponse } from '@/Models/ApiResponse'
import RainbowKit from '../../Swap/Withdraw/Wallet/RainbowKit'
@@ -34,7 +34,7 @@ const CampaignDetails: React.FC<{
const { isConnected } = useAccount();
// :aa Shouldn't this be loaded server-side in the parent page??
const apiClient = new BridgeApiClient()
const apiClient = new BridgeRPCClient()
const { data: campaignsData, isLoading } = useSWR<ApiResponse<Campaign[]>>('/campaigns', apiClient.fetcher)
const campaign = campaignsData?.data?.find((c) => (c.name === campaignName))
@@ -5,7 +5,7 @@ import useSWR from 'swr'
import { Gift } from 'lucide-react'
import { ApiResponse } from '@/Models/ApiResponse'
import BridgeApiClient, { type Campaign } from '@/lib/BridgeApiClient'
import BridgeRPCClient, { type Campaign } from '@/lib/BridgeRPCClient'
import { useSettings } from '@/context/settings'
import SpinIcon from '../icons/spinIcon'
@@ -16,7 +16,7 @@ import type { CryptoNetwork } from '@/Models/CryptoNetwork'
const Rewards = () => {
const { networks } = useSettings()
const apiClient = new BridgeApiClient()
const apiClient = new BridgeRPCClient()
const { data: campaignsData, isLoading } = useSWR<ApiResponse<Campaign[]>>('/campaigns', apiClient.fetcher)
const campaigns = campaignsData?.data
+1 -1
View File
@@ -1,5 +1,5 @@
import { RadioGroup } from "@headlessui/react";
import { SwapType } from "../lib/BridgeApiClient";
import { SwapType } from "../lib/BridgeRPCClient";
import { classNames } from "./utils/classNames";
export interface NavRadioOption {
@@ -1,7 +1,7 @@
import { SwapStatus } from '../../Models/SwapStatus'
import {
type SwapItem,
} from '@/lib/BridgeApiClient'
} from '@/lib/BridgeRPCClient'
export default function StatusIcon({
swap,
@@ -8,7 +8,7 @@ import KnownInternalNames from '../../lib/knownIds'
import { SwapDetailsComponentSkeleton } from '../Skeletons'
import { ExternalLink } from 'lucide-react'
import { type FC } from 'react'
import { type SwapItem, TransactionType } from '../../lib/BridgeApiClient'
import { type SwapItem, TransactionType } from '../../lib/BridgeRPCClient'
import { useSettings } from '@/context/settings'
import type { CryptoNetwork, NetworkCurrency } from '@/Models/CryptoNetwork'
@@ -10,7 +10,7 @@ import { classNames } from '../utils/classNames'
import { useSearchParams, useRouter, usePathname } from 'next/navigation'
import { ArrowRight, ChevronRight, Eye, RefreshCcw, Scroll } from 'lucide-react'
import BridgeApiClient, { type SwapItem, SwapStatusInNumbers, TransactionType } from '@/lib/BridgeApiClient'
import BridgeRPCClient, { type SwapItem, SwapStatusInNumbers, TransactionType } from '@/lib/BridgeRPCClient'
import Modal from '@/components/modal/modal'
import SpinIcon from '@/components/icons/spinIcon'
import StatusIcon from '@/components/SwapHistory/StatusIcons'
@@ -65,7 +65,7 @@ function TransactionsHistory() {
} = await axios.get(
`${process.env.NEXT_PUBLIC_BACKEND_API}/api/swaps?${!showAllSwaps ? `page=${page}` : ''}${
status ? `&status=${status}` : ''
}&version=${BridgeApiClient.apiVersion}&teleport=${useTeleporter}&pageSize=${PAGE_SIZE}`
}&version=${BridgeRPCClient.apiVersion}&teleport=${useTeleporter}&pageSize=${PAGE_SIZE}`
)
return {
data: data,
@@ -6,7 +6,7 @@ import toast from 'react-hot-toast'
import { useAuthDataUpdate, useAuthState, UserType } from '@/context/authContext'
import { useTimerState } from '@/context/timerContext'
import BridgeApiClient from '@/lib/BridgeApiClient'
import BridgeRPCClient from '@/lib/BridgeRPCClient'
import BridgeAuthApiClient from '@/lib/userAuthApiClient'
import { type AuthConnectResponse } from '@/Models/BridgeAuth'
@@ -91,7 +91,7 @@ const VerifyEmailCode: React.FC<{
return
}
var apiAuthClient = new BridgeAuthApiClient()
var apiClient = new BridgeApiClient()
var apiClient = new BridgeRPCClient()
const res = await apiAuthClient.connectAsync(tempEmail, values.Code)
updateAuthData(res)
await onSuccessfullVerify(res)
+1 -1
View File
@@ -59,7 +59,7 @@ const GlobalFooter = () => {
</Link>
</div>
<p className="text-center text-xs text-muted-2 leading-6">
&copy; {new Date().getFullYear()} Lux Partners Limited. All rights reserved.
&copy; {new Date().getFullYear()} Lux Industries Inc. All rights reserved.
</p>
</div>
<div className="flex space-x-6">
@@ -7,7 +7,7 @@ import React, {
} from 'react'
import { type Partner } from '@/Models/Partner'
import { type AddressBookItem } from '@/lib/BridgeApiClient'
import { type AddressBookItem } from '@/lib/BridgeRPCClient'
import { isValidAddress } from '@/lib/addressValidator'
import Image from 'next/image'
import KnownInternalNames from '@/lib/knownIds'
@@ -7,7 +7,7 @@ import React, {
} from 'react'
import { type Partner } from '@/Models/Partner'
import { type AddressBookItem } from '@/lib/BridgeApiClient'
import { type AddressBookItem } from '@/lib/BridgeRPCClient'
import { isValidAddress } from '@/lib/addressValidator'
import Image from 'next/image'
import KnownInternalNames from '@/lib/knownIds'
+2 -2
View File
@@ -1,5 +1,5 @@
import toast from "react-hot-toast";
import BridgeApiClient, { type SwapItem } from "../lib/BridgeApiClient";
import BridgeRPCClient, { type SwapItem } from "../lib/BridgeRPCClient";
import { type Wallet } from "../stores/walletStore";
// import useTON from "../lib/wallets/ton/useTON";
import useEVM from "../lib/wallets/evm/useEVM";
@@ -45,7 +45,7 @@ function useWallet() {
);
try {
if (swap?.source_exchange) {
const apiClient = new BridgeApiClient();
const apiClient = new BridgeRPCClient();
await apiClient.DisconnectExchangeAsync(swap.id, "coinbase");
} else {
await provider?.disconnectWallet();
File diff suppressed because it is too large Load Diff
@@ -3,7 +3,7 @@ import { QueryParams } from "../Models/QueryParams";
import { isValidAddress } from "./addressValidator";
import { FilterDestinationLayers, FilterSourceLayers } from "../util/settingsHelper";
import { BridgeAppSettings } from "../Models/BridgeAppSettings";
import { type SwapItem } from "./BridgeApiClient";
import { type SwapItem } from "./BridgeRPCClient";
export function generateSwapInitialValues(settings: BridgeAppSettings, queryParams: QueryParams): SwapFormValues {
const { destAddress, amount, asset, from, to, lockAsset } = queryParams
+1 -1
View File
@@ -1,7 +1,7 @@
import { ERC20TokenType, ETHTokenType, Link, type LinkResults } from '@imtbl/imx-sdk'
import { type NetworkCurrency } from '../Models/CryptoNetwork'
import KnownInternalNames from './knownIds'
import { type SwapItem } from './BridgeApiClient'
import { type SwapItem } from './BridgeRPCClient'
import NetworkSettings from './NetworkSettings'
export default class ImtblClient {
+1 -1
View File
@@ -1,5 +1,5 @@
import { SwapStatus } from "../../Models/SwapStatus"
import { type SwapItem, TransactionStatus, TransactionType } from "../../lib/BridgeApiClient"
import { type SwapItem, TransactionStatus, TransactionType } from "../../lib/BridgeRPCClient"
export const swap: SwapItem = {
"id": "39dbe478-5a7d-427c-b316-cc8c362ec010",
+1 -1
View File
@@ -3,7 +3,7 @@ import {
type SwapItem,
TransactionStatus,
TransactionType,
} from "../lib/BridgeApiClient";
} from "../lib/BridgeRPCClient";
import { SwapStatus } from "../Models/SwapStatus";
import {
type SwapData,
+1 -1
View File
@@ -14,7 +14,7 @@ export default [
},
{
name: "author",
content: 'Lux Partners Limited',
content: 'Lux Industries Inc',
},
{
name: "keywords",
+1 -1
View File
@@ -63,7 +63,7 @@ const Footer: React.FC = () => (
<footer className="flex flex-row justify-between text-muted-2 overflow-hidden py-6 w-full px-6 lg:px-8 mt-auto">
<div className="mt-3 md:mt-0">
<p className="text-center text-xs leading-6 cursor-default">
&copy; {new Date().getFullYear()} Lux Partners Limited. All rights reserved.
&copy; {new Date().getFullYear()} Lux Industries Inc. All rights reserved.
</p>
</div>
<div className="flex justify-center mt-3 md:mt-0 gap-6">
+280 -344
View File
@@ -1,350 +1,286 @@
# Lux Network MPC Bridge Architecture
# Lux Bridge - AI Assistant Knowledge Base
This document provides a comprehensive overview of the Lux Network MPC Bridge project, its components, and how they interact. This document distinguishes between **current implementation** and **planned features**.
**Last Updated**: 2024-11-12
**Project**: Lux Bridge
**Organization**: Lux Network
## Project Overview
The Lux Network Bridge is a decentralized cross-chain bridge that uses Multi-Party Computation (MPC) to enable secure asset transfers between different blockchain networks. The bridge consists of several key components:
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.
## Architecture Summary
### Core Technology Stack
- **MPC Framework**: 2-of-3 threshold signature scheme using `github.com/luxfi/mpc`
- **Frontend**: Next.js 14 with TypeScript, React 18, TailwindCSS
- **Backend**: Node.js API server with Express
- **Smart Contracts**: Solidity (OpenZeppelin), deployed on multiple chains
- **Infrastructure**: Docker, Kubernetes, PostgreSQL, NATS, Consul, Vault (KMS)
- **Authentication**: Lux ID (Casdoor) for unified auth
### System Architecture
```
Bridge UI → Bridge Server → MPC Nodes → Blockchain Networks
↓
KMS + Lux ID + NATS + Consul
```
### MPC Network Configuration
- **Node Count**: 3 nodes (2-of-3 threshold)
- **Ports**:
- HTTP API: 6000-6002
- gRPC: 9090-9092
- NATS: 4223
- Consul: 8501
- **Security**: TLS 1.3, mutual authentication, HSM integration
## Supported Networks & Assets
### Blockchain Networks (15+)
**Layer 1**: Lux, Ethereum, BSC, Polygon, Avalanche, 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, AVAX
**Wrapped Assets**: ZETH, ZBNB, ZPOL, ZAVAX, 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 :3000
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 UI: `cd app/bridge && pnpm dev`
### 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: 3000
- Bridge API: 5000
- 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
- **Location**: `/Users/z/work/lux/bridge/docs/content/docs/index.mdx`
- **Build**: `cd docs && npm run build`
- **View**: `cd docs && npm run dev` → http://localhost:3001
- **Status**: ✅ Built successfully (November 2024)
### Key Documentation Files
- `docs/MPC-GO-INTEGRATION.md` - MPC setup and configuration
- `docs/LUX-ID-INTEGRATION.md` - Authentication integration
- `docs/DEPLOYMENT.md` - Production deployment guide
- `docs/MIGRATION-TO-GO-MPC.md` - Migration from Docker to Go
## Recent Updates
### November 2024
- Created comprehensive documentation in `/docs/content/docs/index.mdx`
- Built documentation site with Nextra theme
- Documented complete API reference
- Added security best practices section
- Created integration guide with code examples
- Added deployment guide for local and production
- Updated LLM.md with full bridge information
## 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.
1. **Smart Contracts**: EVM-compatible contracts deployed on various networks
2. **MPC Nodes**: Distributed nodes that use threshold signatures for secure transaction signing
3. **Bridge UI**: Web interface for users to initiate cross-chain transfers
4. **Backend Services**: APIs and services that coordinate the bridge operations
5. **Blockchain Monitors**: Services that monitor different blockchains (EVM and non-EVM) for events
## Project Structure
The project is organized as a monorepo with the following main directories:
- `app/`: Frontend applications
- `bridge/`: Main bridge UI application (Next.js)
- `bridge3/`: New version of the bridge UI
- `explorer/`: Block explorer UI
- `server/`: Backend API services
- `contracts/`: Smart contracts for the bridge
- `contracts/`: Solidity smart contracts for various chains
- `ignition/`: Deployment modules for the contracts
- `scripts/`: Utility scripts for contract interactions
- `mpc-nodes/`: MPC node implementation
- `docker/`: Docker configuration for running MPC nodes
- `k8s.examples/`: Kubernetes deployment examples
- `pkg/`: Shared packages and utilities
- `core/`: Core shared types and utilities
- `settings/`: Configuration settings
- `utila/`: Utility functions and helpers
- `docs/`: Documentation and guides
- `unified-mpc-library.md`: Details on planned MPC implementation
- `utxo-guide.md`: Guide for planned UTXO-based chain integration
- `eddsa-guide.md`: Guide for planned EdDSA signature implementation
## 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
---
## Key Components
### Smart Contracts
The bridge uses several key smart contracts:
1. **Bridge.sol**: The main contract that handles the teleport operations, including minting, burning, and vault interactions.
2. **ERC20B.sol**: Bridgeable ERC20 token implementation that supports the bridge-specific operations.
3. **LuxVault.sol**: Vault contract that securely holds tokens during the bridging process.
4. **ETHVault.sol**: Specialized vault for handling native ETH.
The contracts support multiple blockchain networks, including:
- Ethereum (mainnet and testnets)
- BSC (Binance Smart Chain)
- Lux Network
- Zoo Network
- Base
- Polygon
- Avalanche
- XRP Ledger (XRPL)
- Many other EVM-compatible chains
### MPC Nodes
The MPC (Multi-Party Computation) nodes are a distributed network of servers that collectively sign transactions without any single node having access to the complete private key. Key features:
1. **Decentralized oracle operations using MPC**
2. **Decentralized permissioning using MPC**
3. **Zero-knowledge transactions**: Signers don't know details about assets being teleported
4. **Multi-chain monitoring**: Nodes monitor various blockchains, including both EVM-compatible chains (like Ethereum, Binance Smart Chain, etc.) and non-EVM chains (like XRP Ledger)
The MPC nodes are containerized using Docker and can be deployed on Kubernetes clusters for production environments.
#### Current MPC Implementation
- **CGGMP20 Protocol**: The bridge currently uses the CGGMP20 protocol for ECDSA threshold signatures
- **ECDSA Support**: Only ECDSA is currently supported, which works with all EVM-compatible chains
#### Planned MPC Enhancements
- **DKLs23 Protocol**: Being evaluated as a possible future update for improved efficiency and security
- **EdDSA Support**: Planned implementation of EdDSA for supporting non-EVM chains like Solana
- **Unified MPC Library**: A planned abstraction layer to unify ECDSA and EdDSA implementations behind a common API
### Bridge UI
The bridge UI is a Next.js application that provides:
1. **Swap interface**: Allows users to initiate cross-chain transfers
2. **Network selection**: Support for multiple source and destination networks
3. **Token selection**: Support for various tokens on each network
4. **Wallet integration**: Connection to various wallets (EVM, Solana, etc.)
5. **Transaction history**: View and track past transactions
## Bridge Workflow
The bridge operates through the following workflow:
1. **User initiates a transfer**:
- User connects their wallet to the bridge UI
- Selects source network, token, amount, destination network, and address
- Confirms the transaction
2. **Source chain operations**:
- If using a wrapped token: Burns the token on the source chain
- If using a native token: Locks the token in the vault
3. **MPC node validation**:
- MPC nodes monitor the source chain for bridge events
- For EVM chains, nodes look for BridgeBurned or VaultDeposit events
- For XRPL, nodes look for Payment transactions to the teleporter address
- Validate the transaction and collectively sign the approval
- No single node has the complete private key
4. **Destination chain operations**:
- If minting a wrapped token: Creates new tokens on the destination chain
- If releasing a native token: Releases tokens from the vault
- Transfers to the recipient address
5. **Transaction completion**:
- User receives tokens on the destination chain
- UI updates to show transaction status
## MPC Implementation (Current & Planned)
### Current Implementation
The current MPC implementation focuses on ECDSA threshold signatures using the CGGMP20 protocol:
1. **CGGMP20 Protocol**:
- Secure threshold ECDSA signatures
- Based on Castagnos and Laguillaumie's encryption scheme
- Efficient distributed key generation and signing
2. **Key Features**:
- Distributed key generation
- Threshold signatures (t-of-n)
- No trusted dealer required
- Asynchronous communication between nodes
3. **Supported Chains**:
- All EVM-compatible chains
- XRPL (using ECDSA)
### Planned Enhancements
The following enhancements are planned for future development:
1. **DKLs23 Protocol Evaluation**:
- Newer protocol being evaluated for possible implementation
- Improved efficiency and security properties
- Potential replacement or alternative to CGGMP20
2. **EdDSA Support** (Planned):
- Implementation of threshold EdDSA signatures
- Support for chains like Solana that use Ed25519 signatures
- Integration with existing MPC infrastructure
3. **Unified MPC Library** (Planned):
- Abstraction layer to unify ECDSA and EdDSA implementations
- Common API for different signature schemes
- Simplified integration of new blockchains
4. **UTXO Support** (Planned):
- Support for UTXO-based blockchains like Bitcoin
- UTXO management and transaction building
- Integration with MPC signing
## Development Environment
The project uses:
- **Node.js v20+**: JavaScript runtime
- **pnpm**: Package manager (v9.15.0+)
- **Next.js**: React framework for the UI
- **TypeScript**: For type-safe code
- **Hardhat**: Ethereum development environment for contracts
- **Docker/Kubernetes**: For containerization and deployment of MPC nodes
## Running Locally
To run the bridge locally:
1. Install `pnpm`: https://pnpm.io/installation
2. Install dependencies: `pnpm install`
3. Run the bridge UI: `pnpm dev`
## Supported Chains and Networks
### Currently Supported
- **EVM-Compatible**:
- Ethereum (Chain ID: 1)
- Binance Smart Chain (Chain ID: 56)
- Polygon (Chain ID: 137)
- Optimism (Chain ID: 10)
- Arbitrum One (Chain ID: 42161)
- Celo (Chain ID: 42220)
- Base (Chain ID: 8453)
- Avalanche (Chain ID: 43114)
- Zora (Chain ID: 7777777)
- Blast (Chain ID: 81457)
- Linea (Chain ID: 59144)
- Fantom (Chain ID: 250)
- Aurora (Chain ID: 1313161554)
- Gnosis (Chain ID: 100)
- Lux Network (Chain ID: 96369)
- Zoo Network (Chain ID: 200200)
- **Non-EVM Chains**:
- XRP Ledger (XRPL) Mainnet
### Planned Support
- **Non-EVM Chains**:
- Solana (pending EdDSA implementation)
- Bitcoin (pending UTXO implementation)
- Avalanche X-Chain (pending UTXO implementation)
For the most up-to-date list and configuration, refer to the settings file at:
`/mpc-nodes/docker/common/node/src/config/settings.ts`
## Architecture Decisions
### MPC Over Traditional Multi-sig
The bridge uses MPC for enhanced security compared to traditional multi-signature approaches:
- No single entity can compromise the bridge
- Private keys never exist in complete form
- Decentralized validation of cross-chain transfers
### Vault System
The vault system allows for:
- Secure custody of assets during the bridge process
- Efficient asset management across chains
- Fee collection mechanism for bridge operations
### Modular Design
The project's modular architecture enables:
- Easy addition of new blockchain networks
- Support for different token types
- Scalable infrastructure to handle increasing loads
## Security Considerations
The bridge implements multiple security measures:
1. **Threshold Signatures**: Requires a minimum number of MPC nodes to sign transactions
2. **Transaction Replay Protection**: Prevents replay attacks
3. **Fee Mechanisms**: Discourages spam and funds system maintenance
4. **Validation Checks**: Ensures transactions meet all requirements before execution
## Adding New Chains
### Adding a New EVM Chain
To add a new EVM-compatible chain to the bridge, follow these steps:
1. **Update Configuration**:
- Edit the configuration file at `/mpc-nodes/docker/common/node/src/config/settings.ts`
- Add a new entry to the `MAIN_NETWORKS` or `TEST_NETWORKS` array with the following information:
- `display_name`: User-friendly name of the network
- `internal_name`: Unique identifier for the network
- `is_testnet`: Boolean indicating if it's a testnet
- `chain_id`: The numeric chain ID
- `teleporter`: Address of the teleporter contract on this chain
- `vault`: Address of the vault contract on this chain
- `node`: RPC endpoint URL for this chain
- `currencies`: Array of supported tokens on this chain
2. **Deploy Smart Contracts**:
- Deploy the Bridge.sol contract on the new chain
- Deploy the ERC20B.sol contract for bridgeable tokens
- Deploy the LuxVault.sol or ETHVault.sol as needed
- Update the configuration with the new contract addresses
3. **Update Swap Pairs**:
- Add entries to the `SWAP_PAIRS` object to define which tokens on the new chain can be swapped with tokens on other chains
4. **Testing**:
- Test transactions from the new chain to existing chains
- Test transactions from existing chains to the new chain
- Verify that tokens can be correctly bridged in both directions
### Adding a Non-EVM Blockchain (Future)
Adding a non-EVM blockchain would require additional custom implementation (planned features):
1. **Update Configuration**:
- Similar to EVM chains, add the configuration to the settings file
- Specify blockchain-specific parameters (like node endpoints and teleporter addresses)
2. **Implement Blockchain Monitors**:
- In the MPC node, add specialized monitoring for the blockchain events
- For XRPL, the implementation looks for Payment transactions to the teleporter address
- For Solana (planned), would need to monitor for specific program events
3. **Add Transaction Validation**:
- Implement chain-specific validation of transactions
- For XRPL, validate that the transaction is of type "Payment"
- For Solana (planned), would need to validate program invocations
4. **Add Chain Libraries**:
- Import and use chain-specific libraries for interacting with the blockchain
- For XRPL, this includes the `xrpl` library
- For Solana (planned), would need to use the `@solana/web3.js` library
5. **Implement Signature Generation**:
- Add support for generating signatures for minting tokens on destination chains
- For EdDSA chains like Solana (planned), would need to implement EdDSA threshold signatures
6. **Update UI**:
- Add support in the UI for connecting to the new blockchain's wallets
- Update network selection to include the new blockchain
7. **Testing**:
- Test transactions from the new blockchain to existing chains
- Test transactions from existing chains to the new blockchain
- Verify that tokens can be correctly bridged in both directions
## Future Roadmap (Planned Features)
### EdDSA Support
Implementation of Edwards-curve Digital Signature Algorithm (EdDSA) threshold signatures to support chains like Solana:
1. **Protocol Selection**: Evaluation and selection of an appropriate EdDSA threshold signature protocol
2. **Integration with Existing MPC Framework**: Extending the current MPC framework to support EdDSA
3. **Key Generation**: Implementation of distributed key generation for EdDSA
4. **Signature Generation**: Implementation of threshold signatures for EdDSA
5. **Chain Integration**: Support for Solana and other EdDSA-based chains
### UTXO Support
Implementation of support for UTXO-based blockchains like Bitcoin and Avalanche X-Chain:
1. **UTXO Management**: Tracking and management of UTXOs
2. **Transaction Building**: Creation of UTXO-based transactions
3. **MPC Integration**: Using the existing MPC infrastructure for signing UTXO transactions
4. **Monitoring**: Tracking UTXO-based blockchain for events
5. **Sweeping**: Implementation of UTXO sweeping for efficient management
### DKLs23 Protocol Evaluation
Evaluation and potential implementation of the DKLs23 protocol for improved efficiency and security:
1. **Performance Analysis**: Comparison with the current CGGMP20 implementation
2. **Security Analysis**: Evaluation of security properties
3. **Implementation**: Development of a DKLs23-based threshold signature scheme
4. **Integration**: Integration with the existing MPC infrastructure
5. **Testing**: Comprehensive testing to ensure reliability and security
**Note**: This file serves as the single source of truth for all AI assistants working on this project.
+840
View File
@@ -0,0 +1,840 @@
---
title: Lux Bridge Documentation
description: Comprehensive documentation for the Lux Bridge - a decentralized cross-chain bridge using Multi-Party Computation (MPC) for secure asset transfers
---
# Lux Bridge Documentation
## 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. Built on a foundation of cryptographic security and distributed consensus, the bridge provides a robust solution for interoperability in the multi-chain ecosystem.
## Architecture & Design
### Core Components
The Lux Bridge architecture consists of several interconnected layers:
```
┌─────────────────────────────────────────────────────────────┐
│ Bridge UI │
│ (React/Next.js Frontend) │
└──────────────────────────┬──────────────────────────────────┘
│
┌──────────────────────────▼──────────────────────────────────┐
│ Bridge Server │
│ (API & Business Logic) │
└──────────────────────────┬──────────────────────────────────┘
│
┌──────────────────────────▼──────────────────────────────────┐
│ MPC Node Network │
│ (3-node threshold signature) │
└──────────────────────────┬──────────────────────────────────┘
│
┌──────────────────────────▼──────────────────────────────────┐
│ Infrastructure Services │
│ (KMS, Lux ID, NATS, Consul, PostgreSQL) │
└──────────────────────────┬──────────────────────────────────┘
│
┌──────────────────────────▼──────────────────────────────────┐
│ Blockchain Networks │
│ (Lux, Ethereum, BSC, Polygon, Arbitrum, zkSync, etc) │
└─────────────────────────────────────────────────────────────┘
```
### Multi-Party Computation (MPC)
The bridge employs a 2-of-3 threshold signature scheme using MPC technology:
- **Distributed Key Generation**: Private keys are never fully reconstructed
- **Threshold Signatures**: Any 2 of 3 nodes can sign transactions
- **No Single Point of Failure**: Compromise of one node doesn't affect security
- **Cryptographic Validation**: All operations verified through zero-knowledge proofs
### Security Model
#### Byzantine Fault Tolerance
The MPC network tolerates up to 1 malicious node while maintaining security and liveness. The system employs:
- **Consensus Protocol**: BFT consensus for transaction agreement
- **Signature Threshold**: 2-of-3 nodes required for valid signatures
- **Key Rotation**: Periodic key refresh to maintain forward secrecy
- **Slashing Conditions**: Economic penalties for malicious behavior
#### Cryptographic Primitives
- **ECDSA**: For Ethereum-compatible chains
- **Ed25519**: For high-performance chains
- **BLS**: For aggregated signatures
- **Post-Quantum**: ML-DSA ready for quantum resistance
## Supported Chains & Assets
### Supported Blockchains
#### Layer 1 Networks
- **Lux Network** (Native)
- **Ethereum** (ETH)
- **BNB Smart Chain** (BSC)
- **Polygon** (MATIC)
- **Avalanche** (AVAX)
- **Fantom** (FTM)
#### Layer 2 Networks
- **Arbitrum One**
- **Optimism**
- **zkSync Era**
- **Polygon zkEVM**
- **Base**
- **Blast**
#### Other Networks
- **TON (The Open Network)**
- **Solana** (Coming Soon)
- **Cosmos Hub** (Via IBC)
### Supported Assets
#### Stablecoins
- **USDT** (Tether)
- **USDC** (USD Coin)
- **DAI** (MakerDAO)
- **ZUSD** (Zoo USD)
#### Native Tokens
- **LUX** (Lux Network)
- **ETH** (Ethereum)
- **BNB** (BNB Chain)
- **MATIC** (Polygon)
- **AVAX** (Avalanche)
#### Wrapped Assets
- **ZETH** (Wrapped ETH)
- **ZBNB** (Wrapped BNB)
- **ZPOL** (Wrapped MATIC)
- **ZAVAX** (Wrapped AVAX)
- **ZTON** (Wrapped TON)
## Asset Locking & Minting Mechanisms
### Lock-and-Mint Model
The bridge operates on a lock-and-mint mechanism:
1. **Source Chain**: Assets are locked in secure vault contracts
2. **MPC Validation**: Transfer is validated by MPC network
3. **Destination Chain**: Equivalent wrapped tokens are minted
4. **Redemption**: Wrapped tokens can be burned to unlock original assets
### Vault Architecture
```solidity
interface IVault {
function deposit(address token, uint256 amount) external;
function withdraw(address token, uint256 amount, bytes calldata signature) external;
function getBalance(address token) external view returns (uint256);
}
```
Each supported chain has dedicated vault contracts:
- **LuxVault**: Main vault for Lux Network
- **ETHVault**: Ethereum mainnet vault
- **BSCVault**: BNB Smart Chain vault
- **ZooVault**: Multi-asset aggregated vault
### Wrapped Token Standard
All wrapped tokens follow the ERC20B standard with additional bridging capabilities:
```solidity
interface IERC20B is IERC20 {
function mint(address to, uint256 amount) external;
function burn(uint256 amount) external;
function burnFrom(address from, uint256 amount) external;
}
```
## Cross-Chain Message Passing
### Message Protocol
The bridge implements a universal message passing protocol:
```typescript
interface CrossChainMessage {
sourceChain: ChainId;
destChain: ChainId;
nonce: bigint;
sender: Address;
recipient: Address;
payload: Bytes;
signatures: MPCSignature[];
}
```
### Message Flow
1. **Initiation**: User initiates transfer on source chain
2. **Event Emission**: Bridge contract emits transfer event
3. **Oracle Detection**: MPC nodes detect and validate event
4. **Consensus**: Nodes reach consensus on transfer validity
5. **Signature Generation**: Threshold signature created
6. **Relay**: Signed message relayed to destination chain
7. **Execution**: Destination contract validates and executes
## Fee Structure
### Base Fees
| Operation | Fee | Description |
|-----------|-----|-------------|
| Bridge Transfer | 0.3% | Percentage of transfer amount |
| Minimum Fee | $1.00 | Minimum fee per transaction |
| Maximum Fee | $500 | Cap on single transaction fee |
### Dynamic Fee Components
- **Gas Fee**: Actual gas cost on destination chain
- **MPC Operation Fee**: Fixed fee for MPC validation
- **Liquidity Fee**: Variable based on pool depth
- **Network Congestion**: Surge pricing during high load
### Fee Distribution
- **40%**: MPC Node Operators
- **30%**: Liquidity Providers
- **20%**: Protocol Treasury
- **10%**: Insurance Fund
## API Reference
### REST API Endpoints
#### Bridge Status
```http
GET /api/v1/status
```
Returns current bridge operational status and health metrics.
#### Supported Chains
```http
GET /api/v1/chains
```
Returns list of supported blockchain networks.
#### Supported Assets
```http
GET /api/v1/assets
```
Returns list of supported tokens and assets.
#### Get Quote
```http
POST /api/v1/quote
Content-Type: application/json
{
"sourceChain": "ethereum",
"destChain": "lux",
"asset": "USDT",
"amount": "1000.00"
}
```
#### Initiate Transfer
```http
POST /api/v1/transfer
Content-Type: application/json
{
"sourceChain": "ethereum",
"destChain": "lux",
"asset": "USDT",
"amount": "1000.00",
"recipient": "0x...",
"signature": "0x..."
}
```
#### Transfer Status
```http
GET /api/v1/transfer/{transferId}
```
### WebSocket API
#### Subscribe to Transfer Updates
```javascript
ws.send(JSON.stringify({
type: 'subscribe',
channel: 'transfer',
transferId: '0x...'
}));
```
#### Receive Status Updates
```javascript
ws.on('message', (data) => {
const update = JSON.parse(data);
// Handle transfer status update
});
```
## Integration Guide
### Smart Contract Integration
#### 1. Install Dependencies
```bash
npm install @luxfi/bridge-contracts
```
#### 2. Import Bridge Interface
```solidity
pragma solidity ^0.8.20;
import "@luxfi/bridge-contracts/interfaces/IBridge.sol";
contract MyContract {
IBridge public bridge;
constructor(address _bridge) {
bridge = IBridge(_bridge);
}
function bridgeAssets(
address token,
uint256 amount,
uint256 destChainId,
address recipient
) external {
IERC20(token).approve(address(bridge), amount);
bridge.deposit(token, amount, destChainId, recipient);
}
}
```
### JavaScript/TypeScript SDK
#### Installation
```bash
npm install @luxfi/bridge-sdk
```
#### Basic Usage
```typescript
import { LuxBridge, ChainId } from '@luxfi/bridge-sdk';
// Initialize bridge
const bridge = new LuxBridge({
rpcUrl: 'https://api.lux.network',
privateKey: process.env.PRIVATE_KEY
});
// Get supported chains
const chains = await bridge.getSupportedChains();
// Get quote for transfer
const quote = await bridge.getQuote({
sourceChain: ChainId.ETHEREUM,
destChain: ChainId.LUX,
asset: 'USDT',
amount: '1000.00'
});
// Execute transfer
const transfer = await bridge.transfer({
sourceChain: ChainId.ETHEREUM,
destChain: ChainId.LUX,
asset: 'USDT',
amount: '1000.00',
recipient: '0x...'
});
// Monitor transfer status
bridge.on('transfer', transfer.id, (status) => {
console.log('Transfer status:', status);
});
```
#### Advanced Features
```typescript
// Batch transfers
const transfers = await bridge.batchTransfer([
{ asset: 'USDT', amount: '100', recipient: '0x...' },
{ asset: 'ETH', amount: '0.5', recipient: '0x...' }
]);
// Custom slippage tolerance
const transfer = await bridge.transfer({
// ... transfer params
slippageTolerance: 0.5 // 0.5%
});
// Gas price optimization
const transfer = await bridge.transfer({
// ... transfer params
gasStrategy: 'fast' // 'slow', 'normal', 'fast'
});
```
## Deployment Guide
### Prerequisites
- Node.js v20+
- pnpm v9.15.0+
- Go 1.22+ (for MPC tools)
- Docker & Docker Compose
- PostgreSQL 15+
- Vault (HashiCorp) for KMS
### Local Deployment
#### 1. Clone Repository
```bash
git clone https://github.com/luxfi/bridge
cd bridge
```
#### 2. Install Dependencies
```bash
# Install JavaScript dependencies
pnpm install
# Install MPC tools
make install-mpc
```
#### 3. Configure Environment
```bash
# Copy example environment
cp .env.example .env
# Edit configuration
vim .env
```
Required environment variables:
```env
# Network Configuration
NETWORK=testnet
CHAIN_ID=31337
# Database
DATABASE_URL=postgresql://user:pass@localhost:5433/bridge
# MPC Configuration
MPC_NODE_COUNT=3
MPC_THRESHOLD=2
# KMS Configuration
VAULT_ADDR=http://localhost:8200
VAULT_TOKEN=your-token
# Lux ID (Authentication)
CASDOOR_ENDPOINT=http://localhost:8000
```
#### 4. Start Infrastructure
```bash
# Start all services
make up
# Or start individually
docker-compose up -d postgres
docker-compose up -d vault
docker-compose up -d casdoor
docker-compose up -d nats
docker-compose up -d consul
```
#### 5. Initialize MPC Network
```bash
# Generate MPC keys
make generate-mpc-keys
# Start MPC nodes
make start-mpc-nodes
```
#### 6. Deploy Smart Contracts
```bash
# Deploy to local network
cd contracts
npx hardhat run scripts/deploy.js --network localhost
# Deploy to testnet
npx hardhat run scripts/deploy.js --network testnet
```
#### 7. Start Bridge Services
```bash
# Start API server
cd app/server
pnpm dev
# Start UI (in another terminal)
cd app/bridge
pnpm dev
```
### Production Deployment
#### Kubernetes Deployment
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: lux-bridge
spec:
replicas: 3
selector:
matchLabels:
app: lux-bridge
template:
metadata:
labels:
app: lux-bridge
spec:
containers:
- name: bridge-api
image: luxfi/bridge-api:latest
ports:
- containerPort: 5000
env:
- name: NODE_ENV
value: production
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: bridge-secrets
key: database-url
```
#### Docker Compose Production
```yaml
version: '3.8'
services:
bridge-api:
image: luxfi/bridge-api:latest
environment:
NODE_ENV: production
networks:
- bridge-network
deploy:
replicas: 3
restart_policy:
condition: on-failure
mpc-node:
image: luxfi/mpc-node:latest
environment:
NODE_ENV: production
networks:
- bridge-network
deploy:
replicas: 3
```
#### High Availability Setup
1. **Database**: PostgreSQL with streaming replication
2. **MPC Nodes**: Geographic distribution across regions
3. **Load Balancing**: HAProxy or nginx for API endpoints
4. **Monitoring**: Prometheus + Grafana stack
5. **Backup**: Regular snapshots of vault data
## Security Best Practices
### Smart Contract Security
#### Audit Requirements
- Formal verification of critical functions
- Multiple independent security audits
- Bug bounty program with rewards up to $100,000
- Continuous monitoring and incident response
#### Access Control
```solidity
contract Bridge is AccessControl {
bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE");
bytes32 public constant OPERATOR_ROLE = keccak256("OPERATOR_ROLE");
modifier onlyAdmin() {
require(hasRole(ADMIN_ROLE, msg.sender), "Not admin");
_;
}
modifier onlyOperator() {
require(hasRole(OPERATOR_ROLE, msg.sender), "Not operator");
_;
}
}
```
#### Pausability
```solidity
contract Bridge is Pausable {
function pause() external onlyAdmin {
_pause();
}
function unpause() external onlyAdmin {
_unpause();
}
function deposit() external whenNotPaused {
// Bridge logic
}
}
```
### MPC Security
#### Key Management
- Hardware Security Modules (HSM) for key storage
- Key rotation every 30 days
- Threshold key generation ceremony
- Secure multiparty computation protocols
#### Node Security
- TLS 1.3 for all communications
- Mutual TLS authentication between nodes
- Rate limiting and DDoS protection
- Regular security updates and patches
#### Monitoring & Alerting
```yaml
alerts:
- name: MPCNodeDown
condition: up{job="mpc-node"} == 0
for: 5m
severity: critical
- name: HighErrorRate
condition: rate(errors_total[5m]) > 0.05
severity: warning
- name: UnauthorizedAccess
condition: unauthorized_requests_total > 10
severity: critical
```
### Operational Security
#### Infrastructure Hardening
- Disable unnecessary services
- Regular security patching
- Network segmentation
- Firewall rules and IP whitelisting
#### Secrets Management
```bash
# Store secrets in Vault
vault kv put secret/bridge/api \
database_url="postgresql://..." \
jwt_secret="..." \
mpc_key="..."
# Rotate secrets regularly
vault kv metadata put -mount=secret \
-max-versions=5 \
-delete-version-after=30d \
bridge/api
```
#### Incident Response Plan
1. **Detection**: Automated monitoring and alerting
2. **Assessment**: Severity classification (P1-P4)
3. **Containment**: Pause bridge if necessary
4. **Eradication**: Fix vulnerability
5. **Recovery**: Resume operations
6. **Lessons Learned**: Post-mortem analysis
### User Security Guidelines
#### Wallet Security
- Use hardware wallets for large transfers
- Verify recipient addresses on multiple channels
- Enable 2FA on exchange accounts
- Use dedicated bridge addresses
#### Transaction Verification
- Always verify transaction details before signing
- Check fee amounts are reasonable
- Confirm destination chain and address
- Monitor transaction status
#### Phishing Protection
- Only use official bridge URLs
- Verify SSL certificates
- Never share private keys or seed phrases
- Report suspicious activities
## Monitoring & Analytics
### Metrics Collection
The bridge exposes Prometheus metrics:
```prometheus
# Bridge metrics
bridge_transfers_total{chain="ethereum",status="success"} 1234
bridge_transfer_volume_usd{chain="ethereum",asset="USDT"} 1000000
bridge_transfer_latency_seconds{chain="ethereum",percentile="p99"} 45.2
# MPC metrics
mpc_signature_generation_seconds{node="0"} 2.3
mpc_node_uptime_seconds{node="0"} 86400
mpc_consensus_rounds_total{status="success"} 5678
# System metrics
process_cpu_seconds_total 123.45
process_resident_memory_bytes 234567890
http_request_duration_seconds{endpoint="/transfer",percentile="p95"} 0.234
```
### Dashboards
Grafana dashboards for monitoring:
- Bridge Overview: Transfer volumes, success rates, fees
- MPC Network: Node health, consensus metrics, key operations
- Performance: Latency, throughput, error rates
- Security: Failed authentications, suspicious activities
### Logging
Structured logging with correlation IDs:
```json
{
"timestamp": "2024-11-12T10:30:45Z",
"level": "info",
"service": "bridge-api",
"correlationId": "abc-123",
"event": "transfer_initiated",
"data": {
"transferId": "0x...",
"sourceChain": "ethereum",
"destChain": "lux",
"asset": "USDT",
"amount": "1000.00"
}
}
```
## Troubleshooting
### Common Issues
#### Transfer Stuck in Pending
1. Check MPC node status: `lux-mpc-cli status`
2. Verify transaction on source chain explorer
3. Check for sufficient gas on destination chain
4. Review logs for error messages
#### MPC Node Not Responding
1. Check node health: `curl http://localhost:6000/health`
2. Verify network connectivity
3. Check NATS message queue status
4. Restart node if necessary: `make restart-mpc-node-0`
#### High Latency
1. Monitor network conditions
2. Check database performance
3. Review MPC consensus rounds
4. Scale infrastructure if needed
### Debug Commands
```bash
# Check bridge status
curl http://localhost:5000/api/v1/status
# View MPC logs
tail -f logs/mpc-node-*.log
# Database queries
psql -U bridge -d bridge -c "SELECT * FROM transfers WHERE status='pending';"
# NATS monitoring
nats-top -s localhost:4223
# Consul services
consul catalog services
```
## Governance & Upgrades
### Governance Model
The Lux Bridge is governed by LUX token holders through:
- **Proposal Submission**: 10,000 LUX minimum
- **Voting Period**: 7 days
- **Quorum**: 4% of circulating supply
- **Execution Delay**: 2 days (timelock)
### Upgrade Process
1. **Proposal**: Submit upgrade proposal with specifications
2. **Review**: Technical and security review
3. **Testing**: Deploy on testnet
4. **Voting**: Community governance vote
5. **Timelock**: 48-hour delay before execution
6. **Deployment**: Coordinated upgrade across infrastructure
### Emergency Procedures
In case of critical vulnerabilities:
1. Pause bridge operations
2. Emergency multisig (3-of-5) can execute fixes
3. Post-incident governance vote for ratification
4. Compensation for affected users if applicable
## Resources & Support
### Documentation
- [GitHub Repository](https://github.com/luxfi/bridge)
- [API Documentation](https://docs.lux.network/bridge/api)
- [Smart Contract Documentation](https://docs.lux.network/bridge/contracts)
- [Video Tutorials](https://youtube.com/luxnetwork)
### Community
- [Discord](https://discord.gg/luxnetwork)
- [Telegram](https://t.me/luxnetwork)
- [Twitter](https://twitter.com/luxnetwork)
- [Forum](https://forum.lux.network)
### Support
- Technical Support: [email protected]
- Security Issues: [email protected]
- Business Inquiries: [email protected]
### Bug Bounty Program
- Critical: Up to $100,000
- High: Up to $25,000
- Medium: Up to $5,000
- Low: Up to $1,000
Report vulnerabilities to: [email protected]
---
*Last Updated: November 2024*
*Version: 1.0.0*
+5
View File
@@ -0,0 +1,5 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />
// NOTE: This file should not be edited
// see https://nextjs.org/docs/pages/building-your-application/configuring/typescript for more information.
+20
View File
@@ -0,0 +1,20 @@
const withNextra = require('nextra')({
theme: 'nextra-theme-docs',
themeConfig: './theme.config.tsx',
defaultShowCopyCode: true,
mdxOptions: {
remarkPlugins: [],
rehypePlugins: [],
},
})
module.exports = withNextra({
reactStrictMode: true,
swcMinify: true,
output: 'export',
images: {
unoptimized: true,
},
basePath: process.env.GITHUB_PAGES ? '/bridge' : '',
assetPrefix: process.env.GITHUB_PAGES ? '/bridge/' : '',
})
+1
View File
@@ -0,0 +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="/bridge/_next/static/css/83ce42764a171fc6.css" as="style"/><link rel="stylesheet" href="/bridge/_next/static/css/83ce42764a171fc6.css" data-n-g=""/><noscript data-n-css=""></noscript><script defer="" nomodule="" src="/bridge/_next/static/chunks/polyfills-42372ed130431b0a.js"></script><script src="/bridge/_next/static/chunks/webpack-abd991c5840a0e22.js" defer=""></script><script src="/bridge/_next/static/chunks/framework-64ad27b21261a9ce.js" defer=""></script><script src="/bridge/_next/static/chunks/main-fbce30a623cb8c9a.js" defer=""></script><script src="/bridge/_next/static/chunks/pages/_app-26f5890917895004.js" defer=""></script><script src="/bridge/_next/static/chunks/pages/_error-7a92967bea80186d.js" defer=""></script><script src="/bridge/_next/static/iGOSXVPr-sBS_hhOM0Cnj/_buildManifest.js" defer=""></script><script src="/bridge/_next/static/iGOSXVPr-sBS_hhOM0Cnj/_ssgManifest.js" defer=""></script></head><body><div id="__next"><div style="font-family:system-ui,&quot;Segoe UI&quot;,Roboto,Helvetica,Arial,sans-serif,&quot;Apple Color Emoji&quot;,&quot;Segoe UI Emoji&quot;;height:100vh;text-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center"><div style="line-height:48px"><style>body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}</style><h1 class="next-error-h1" style="display:inline-block;margin:0 20px 0 0;padding-right:23px;font-size:24px;font-weight:500;vertical-align:top">404</h1><div style="display:inline-block"><h2 style="font-size:14px;font-weight:400;line-height:28px">This page could not be found<!-- -->.</h2></div></div></div></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{"statusCode":404}},"page":"/_error","query":{},"buildId":"iGOSXVPr-sBS_hhOM0Cnj","assetPrefix":"/bridge","nextExport":true,"isFallback":false,"gip":true,"scriptLoader":[]}</script></body></html>
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -0,0 +1 @@
{"/":{"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":{}}}
@@ -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()}]);
@@ -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
@@ -0,0 +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="/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))}();
File diff suppressed because one or more lines are too long
@@ -0,0 +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: }/*
! 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}.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))}
@@ -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();
@@ -0,0 +1 @@
self.__SSG_MANIFEST=new Set,self.__SSG_MANIFEST_CB&&self.__SSG_MANIFEST_CB();
+702
View File
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+34
View File
@@ -0,0 +1,34 @@
{
"name": "@luxfi/bridge-docs",
"version": "1.0.0",
"description": "Documentation site for Lux Bridge",
"scripts": {
"dev": "next dev -p 3001",
"build": "next build",
"start": "next start -p 3001",
"lint": "next lint"
},
"dependencies": {
"@mdx-js/loader": "^3.0.0",
"@mdx-js/react": "^3.0.0",
"@next/mdx": "^14.0.3",
"gray-matter": "^4.0.3",
"next": "^14.0.3",
"nextra": "^2.13.2",
"nextra-theme-docs": "^2.13.2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"rehype-highlight": "^7.0.0",
"remark-gfm": "^4.0.0"
},
"devDependencies": {
"@types/mdx": "^2.0.10",
"@types/node": "^20.10.0",
"@types/react": "^18.2.42",
"@types/react-dom": "^18.2.17",
"autoprefixer": "^10.4.16",
"postcss": "^8.4.32",
"tailwindcss": "^3.3.6",
"typescript": "^5.3.2"
}
}
+6
View File
@@ -0,0 +1,6 @@
import type { AppProps } from 'next/app'
import '../styles/globals.css'
export default function App({ Component, pageProps }: AppProps) {
return <Component {...pageProps} />
}
+34
View File
@@ -0,0 +1,34 @@
{
"index": {
"title": "Home",
"type": "page"
},
"docs": {
"title": "Documentation",
"type": "page"
},
"-- API": {
"type": "separator",
"title": "API"
},
"api": {
"title": "API Reference",
"href": "/docs#api-reference"
},
"-- Guides": {
"type": "separator",
"title": "Guides"
},
"integration": {
"title": "Integration Guide",
"href": "/docs#integration-guide"
},
"deployment": {
"title": "Deployment Guide",
"href": "/docs#deployment-guide"
},
"security": {
"title": "Security",
"href": "/docs#security-best-practices"
}
}
+3
View File
@@ -0,0 +1,3 @@
import Index from '../content/docs/index.mdx'
<Index />
+73
View File
@@ -0,0 +1,73 @@
# Lux Bridge Documentation
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
- [Architecture & Design](/docs) - Learn about the bridge architecture
- [API Reference](/docs#api-reference) - Integrate with the bridge
- [Deployment Guide](/docs#deployment-guide) - Deploy your own instance
- [Security Best Practices](/docs#security-best-practices) - Keep your bridge secure
## What is Lux Bridge?
The Lux Bridge is a decentralized cross-chain bridge that enables:
- **Secure Asset Transfers** - Transfer tokens between 15+ blockchain networks
- **Multi-Party Computation** - 2-of-3 threshold signatures for maximum security
- **Universal Message Passing** - Send arbitrary messages across chains
- **Low Fees** - Competitive 0.3% bridge fee with caps
- **Fast Finality** - Transfers complete in minutes, not hours
## Supported Networks
### Layer 1
- Lux Network
- Ethereum
- BNB Smart Chain
- Polygon
- Avalanche
- Fantom
### Layer 2
- Arbitrum One
- Optimism
- zkSync Era
- Polygon zkEVM
- Base
- Blast
## Getting Started
```bash
# Clone the repository
git clone https://github.com/luxfi/bridge
cd bridge
# Install dependencies
pnpm install
# Start local development
make up
make start-mpc-nodes
cd app/bridge && pnpm dev
```
Visit [http://localhost:3000](http://localhost:3000) to see the bridge UI.
## Documentation Structure
- **[Complete Documentation](/docs)** - Full technical documentation
- **[Integration Examples](/docs#integration-guide)** - Code examples and SDKs
- **[API Reference](/docs#api-reference)** - REST and WebSocket APIs
- **[Security](/docs#security-best-practices)** - Security guidelines
## Need Help?
- Join our [Discord](https://discord.gg/luxnetwork)
- Follow us on [Twitter](https://twitter.com/luxnetwork)
- Email support: [email protected]
---
*Version 1.0.0 - November 2024*
+6
View File
@@ -0,0 +1,6 @@
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}
+53
View File
@@ -0,0 +1,53 @@
@tailwind base;
@tailwind components;
@tailwind utilities;
: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));
}
/* Custom styles for documentation */
.nextra-content {
@apply max-w-6xl;
}
pre {
@apply overflow-x-auto;
}
code {
@apply text-sm;
}
/* Table styles */
table {
@apply w-full border-collapse;
}
th {
@apply border-b-2 border-gray-300 dark:border-gray-700 p-2 text-left;
}
td {
@apply border-b border-gray-200 dark:border-gray-800 p-2;
}
+29
View File
@@ -0,0 +1,29 @@
/** @type {import('tailwindcss').Config} */
module.exports = {
content: [
'./pages/**/*.{js,ts,jsx,tsx,mdx}',
'./components/**/*.{js,ts,jsx,tsx,mdx}',
'./content/**/*.{js,ts,jsx,tsx,mdx}',
'./theme.config.tsx',
],
theme: {
extend: {
colors: {
primary: {
50: '#eff6ff',
100: '#dbeafe',
200: '#bfdbfe',
300: '#93c5fd',
400: '#60a5fa',
500: '#3b82f6',
600: '#2563eb',
700: '#1d4ed8',
800: '#1e40af',
900: '#1e3a8a',
},
},
},
},
plugins: [],
darkMode: 'class',
}
+52
View File
@@ -0,0 +1,52 @@
import React from 'react'
import { DocsThemeConfig } from 'nextra-theme-docs'
const config: DocsThemeConfig = {
logo: <span>Lux Bridge</span>,
project: {
link: 'https://github.com/luxfi/bridge',
},
chat: {
link: 'https://discord.gg/luxnetwork',
},
docsRepositoryBase: 'https://github.com/luxfi/bridge/tree/main/docs',
footer: {
text: 'Lux Bridge Documentation',
},
head: (
<>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta property="og:title" content="Lux Bridge Documentation" />
<meta property="og:description" content="Comprehensive documentation for the Lux Bridge - a decentralized cross-chain bridge using MPC" />
</>
),
sidebar: {
titleComponent({ title, type }) {
if (type === 'separator') {
return <span className="cursor-default">{title}</span>
}
return <>{title}</>
},
defaultMenuCollapseLevel: 1,
toggleButton: true,
},
toc: {
backToTop: true,
},
navigation: {
prev: true,
next: true,
},
darkMode: true,
primaryHue: 200,
banner: {
key: 'bridge-v1',
text: (
<a href="https://lux.network" target="_blank">
🚀 Lux Bridge v1.0 is now live! Learn more →
</a>
),
},
}
export default config
+35
View File
@@ -0,0 +1,35 @@
{
"compilerOptions": {
"target": "ES2022",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": false,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"plugins": [
{
"name": "next"
}
],
"paths": {
"@/*": ["./*"]
}
},
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx",
"**/*.js",
"**/*.jsx",
"**/*.mdx",
".next/types/**/*.ts"
],
"exclude": ["node_modules"]
}
+43
View File
@@ -0,0 +1,43 @@
{
"name": "@luxfi/threshold",
"version": "1.0.0",
"description": "T-Chain (ThresholdVM) SDK for MPC threshold signatures",
"publishConfig": {
"registry": "https://registry.npmjs.org/",
"access": "public",
"scope": "@luxfi"
},
"author": "Lux Industries, Inc.",
"license": "BSD-3-Clause",
"repository": {
"type": "git",
"url": "git+https://github.com/luxfi/bridge.git",
"directory": "pkg/threshold"
},
"keywords": [
"mpc",
"threshold",
"signature",
"blockchain",
"lux"
],
"scripts": {
"build": "tsc --project tsconfig.json && tsc --project tsconfig.cjs.json",
"prepublishOnly": "npm run build",
"test": "vitest run",
"lat": "npm show @luxfi/threshold version",
"pub": "npm publish"
},
"exports": {
".": {
"import": "./dist/esm/index.js",
"require": "./dist/cjs/index.js"
}
},
"types": "./dist/esm/index.d.ts",
"dependencies": {},
"devDependencies": {
"typescript": "^5.7.2",
"vitest": "^2.1.0"
}
}
+185
View File
@@ -0,0 +1,185 @@
// Copyright (C) 2019-2025, Lux Industries, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
import { describe, it, expect, vi, beforeEach } from 'vitest'
import { ThresholdClient } from './client'
import type { KeygenResponse, SignatureResponse } from './types'
describe('ThresholdClient', () => {
let client: ThresholdClient
beforeEach(() => {
client = new ThresholdClient({
endpoint: 'http://localhost:9650/ext/bc/T',
chainId: 'test-chain',
})
})
describe('constructor', () => {
it('should create client with options', () => {
expect(client).toBeInstanceOf(ThresholdClient)
})
})
describe('keygen', () => {
it('should call keygen with chain', async () => {
const mockResponse: KeygenResponse = {
sessionId: 'sess-123',
keyId: 'key-1',
protocol: 'lss',
status: 'pending',
threshold: 2,
totalParties: 3,
startedAt: Date.now(),
}
global.fetch = vi.fn().mockResolvedValue({
ok: true,
json: () => Promise.resolve({ jsonrpc: '2.0', id: 1, result: mockResponse }),
})
const result = await client.keygen({ keyId: 'key-1', chain: 'ethereum' })
expect(result.keyId).toBe('key-1')
expect(result.protocol).toBe('lss')
})
it('should call keygen with protocol', async () => {
const mockResponse: KeygenResponse = {
sessionId: 'sess-456',
keyId: 'frost-key',
protocol: 'frost',
status: 'pending',
threshold: 2,
totalParties: 3,
startedAt: Date.now(),
}
global.fetch = vi.fn().mockResolvedValue({
ok: true,
json: () => Promise.resolve({ jsonrpc: '2.0', id: 1, result: mockResponse }),
})
const result = await client.keygen({ keyId: 'frost-key', protocol: 'frost' })
expect(result.protocol).toBe('frost')
})
})
describe('keygenForChain', () => {
it('should be a convenience wrapper', async () => {
const mockResponse: KeygenResponse = {
sessionId: 'sess-789',
keyId: 'sol-key',
protocol: 'frost',
status: 'pending',
threshold: 2,
totalParties: 3,
startedAt: Date.now(),
}
global.fetch = vi.fn().mockResolvedValue({
ok: true,
json: () => Promise.resolve({ jsonrpc: '2.0', id: 1, result: mockResponse }),
})
const result = await client.keygenForChain('sol-key', 'solana')
expect(result.keyId).toBe('sol-key')
expect(result.protocol).toBe('frost')
})
})
describe('sign', () => {
it('should request signature', async () => {
const mockResponse = {
sessionId: 'sign-123',
keyId: 'key-1',
status: 'pending',
createdAt: Date.now(),
expiresAt: Date.now() + 60000,
}
global.fetch = vi.fn().mockResolvedValue({
ok: true,
json: () => Promise.resolve({ jsonrpc: '2.0', id: 1, result: mockResponse }),
})
const result = await client.sign({
keyId: 'key-1',
messageHash: '0x1234567890abcdef',
})
expect(result.sessionId).toBe('sign-123')
expect(result.status).toBe('pending')
})
})
describe('signAndWait', () => {
it('should sign and poll for completion', async () => {
const signResponse = {
sessionId: 'sign-456',
keyId: 'key-1',
status: 'pending',
createdAt: Date.now(),
expiresAt: Date.now() + 60000,
}
const sigResponse: SignatureResponse = {
sessionId: 'sign-456',
status: 'completed',
signature: '0xabcdef',
r: '0x123',
s: '0x456',
v: 27,
completedAt: Date.now(),
}
let callCount = 0
global.fetch = vi.fn().mockImplementation(() => {
callCount++
if (callCount === 1) {
return Promise.resolve({
ok: true,
json: () => Promise.resolve({ jsonrpc: '2.0', id: 1, result: signResponse }),
})
}
return Promise.resolve({
ok: true,
json: () => Promise.resolve({ jsonrpc: '2.0', id: 2, result: sigResponse }),
})
})
const result = await client.signAndWait({
keyId: 'key-1',
messageHash: '0xabcdef',
})
expect(result.status).toBe('completed')
expect(result.signature).toBe('0xabcdef')
})
})
describe('error handling', () => {
it('should throw on RPC error', async () => {
global.fetch = vi.fn().mockResolvedValue({
ok: true,
json: () =>
Promise.resolve({
jsonrpc: '2.0',
id: 1,
error: { code: -32600, message: 'Invalid request' },
}),
})
await expect(client.keygen({ keyId: 'key-1' })).rejects.toThrow('RPC error')
})
it('should throw on HTTP error', async () => {
global.fetch = vi.fn().mockResolvedValue({
ok: false,
status: 500,
statusText: 'Internal Server Error',
})
await expect(client.keygen({ keyId: 'key-1' })).rejects.toThrow('HTTP 500')
})
})
})
+364
View File
@@ -0,0 +1,364 @@
// Copyright (C) 2019-2025, Lux Industries, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
import type {
ThresholdClientOptions,
KeygenRequest,
KeygenResponse,
SignRequest,
SignResponse,
SignatureResponse,
KeyInfo,
ChainConfig,
ProtocolInfo,
Chain,
Protocol,
JsonRpcRequest,
JsonRpcResponse,
ReshareRequest,
RefreshRequest,
SessionInfo,
SessionListOptions,
NetworkStats,
QuotaInfo,
HealthStatus,
ThresholdInfo,
} from './types'
/**
* T-Chain (ThresholdVM) client for MPC threshold signatures
*
* @example
* ```ts
* const client = new ThresholdClient({ endpoint: 'http://localhost:9650/ext/bc/T' })
*
* // Generate key by chain (auto-selects protocol)
* const keygen = await client.keygen({ keyId: 'my-key', chain: 'ethereum' })
*
* // Or by explicit protocol
* const keygen2 = await client.keygen({ keyId: 'frost-key', protocol: 'frost' })
*
* // Sign a message
* const sign = await client.sign({ keyId: 'my-key', messageHash: '0x...' })
* const sig = await client.waitForSignature(sign.sessionId)
* ```
*/
export class ThresholdClient {
private endpoint: string
private chainId: string
private timeout: number
private requestId = 0
constructor(options: ThresholdClientOptions) {
this.endpoint = options.endpoint
this.chainId = options.chainId ?? 'unknown'
this.timeout = options.timeout ?? 30000
}
// ===========================================================================
// Key Generation
// ===========================================================================
/**
* Initiate key generation on T-Chain
* Specify chain for auto protocol selection, or protocol for explicit selection
*/
async keygen(req: KeygenRequest): Promise<KeygenResponse> {
return this.call<KeygenResponse>('threshold_keygen', {
keyId: req.keyId,
chain: req.chain,
protocol: req.protocol,
threshold: req.threshold,
totalParties: req.totalParties,
requestedBy: this.chainId,
})
}
/**
* Convenience method for chain-based key generation
*/
async keygenForChain(keyId: string, chain: Chain): Promise<KeygenResponse> {
return this.keygen({ keyId, chain })
}
/**
* Get keygen session status
*/
async getKeygenStatus(sessionId: string): Promise<KeygenResponse> {
return this.call<KeygenResponse>('threshold_getKeygenStatus', { sessionId })
}
/**
* Wait for keygen to complete
*/
async waitForKeygen(sessionId: string, timeoutMs = 60000): Promise<KeygenResponse> {
const deadline = Date.now() + timeoutMs
const pollInterval = 500
while (Date.now() < deadline) {
const status = await this.getKeygenStatus(sessionId)
if (status.status === 'completed') {
return status
}
if (status.status === 'failed') {
throw new Error(`Keygen failed: ${status.error}`)
}
await this.sleep(pollInterval)
}
throw new Error('Keygen timed out')
}
// ===========================================================================
// Signing
// ===========================================================================
/**
* Request a signature from T-Chain
*/
async sign(req: SignRequest): Promise<SignResponse> {
return this.call<SignResponse>('threshold_sign', {
keyId: req.keyId,
messageHash: req.messageHash,
messageType: req.messageType ?? 'raw',
requestingChain: this.chainId,
})
}
/**
* Get signature result
*/
async getSignature(sessionId: string): Promise<SignatureResponse> {
return this.call<SignatureResponse>('threshold_getSignature', { sessionId })
}
/**
* Wait for signature to complete
*/
async waitForSignature(sessionId: string, timeoutMs = 30000): Promise<SignatureResponse> {
const deadline = Date.now() + timeoutMs
const pollInterval = 100
while (Date.now() < deadline) {
const sig = await this.getSignature(sessionId)
if (sig.status === 'completed') {
return sig
}
if (sig.status === 'failed') {
throw new Error(`Signing failed: ${sig.error}`)
}
await this.sleep(pollInterval)
}
throw new Error('Signing timed out')
}
/**
* Sign and wait for completion
*/
async signAndWait(req: SignRequest, timeoutMs = 30000): Promise<SignatureResponse> {
const resp = await this.sign(req)
return this.waitForSignature(resp.sessionId, timeoutMs)
}
// ===========================================================================
// Key Management
// ===========================================================================
/**
* Get key information
*/
async getKey(keyId: string): Promise<KeyInfo> {
return this.call<KeyInfo>('threshold_getKey', { keyId })
}
/**
* List all keys
*/
async listKeys(): Promise<KeyInfo[]> {
return this.call<KeyInfo[]>('threshold_listKeys', {})
}
/**
* Get public key for a key ID
*/
async getPublicKey(keyId: string): Promise<string> {
const result = await this.call<{ publicKey: string }>('threshold_getPublicKey', { keyId })
return result.publicKey
}
/**
* Get address for a key ID (chain-specific derivation)
*/
async getAddress(keyId: string): Promise<string> {
const result = await this.call<{ address: string }>('threshold_getAddress', { keyId })
return result.address
}
/**
* Reshare key with new party set
*/
async reshare(req: ReshareRequest): Promise<KeygenResponse> {
return this.call<KeygenResponse>('threshold_reshare', req)
}
/**
* Refresh key shares (proactive security)
*/
async refresh(req: RefreshRequest): Promise<KeygenResponse> {
return this.call<KeygenResponse>('threshold_refresh', req)
}
/**
* Batch sign multiple messages
*/
async batchSign(keyId: string, messageHashes: string[]): Promise<string[]> {
const result = await this.call<{ sessionIds: string[] }>('threshold_batchSign', {
keyId,
messageHashes,
})
return result.sessionIds
}
// ===========================================================================
// Session Management
// ===========================================================================
/**
* List sessions
*/
async getSessions(opts?: SessionListOptions): Promise<SessionInfo[]> {
return this.call<SessionInfo[]>('threshold_getSessions', opts ?? {})
}
/**
* Cancel a session
*/
async cancelSession(sessionId: string): Promise<boolean> {
const result = await this.call<{ cancelled: boolean }>('threshold_cancelSession', { sessionId })
return result.cancelled
}
// ===========================================================================
// Network Info & Health
// ===========================================================================
/**
* Get network info
*/
async getInfo(): Promise<ThresholdInfo> {
return this.call<ThresholdInfo>('threshold_getInfo', {})
}
/**
* Get network statistics
*/
async getStats(): Promise<NetworkStats> {
return this.call<NetworkStats>('threshold_getStats', {})
}
/**
* Get quota info for a chain
*/
async getQuota(chainId?: string): Promise<QuotaInfo> {
return this.call<QuotaInfo>('threshold_getQuota', { chainId: chainId ?? this.chainId })
}
/**
* Health check
*/
async health(): Promise<HealthStatus> {
return this.call<HealthStatus>('threshold_health', {})
}
/**
* Check if ready
*/
async isReady(): Promise<boolean> {
try {
const health = await this.health()
return health.ready
} catch {
return false
}
}
// ===========================================================================
// Protocol & Chain Info
// ===========================================================================
/**
* Get supported chains and their configurations
*/
async getSupportedChains(): Promise<ChainConfig[]> {
return this.call<ChainConfig[]>('threshold_getSupportedChains', {})
}
/**
* Get protocol information
*/
async getProtocolInfo(): Promise<ProtocolInfo[]> {
return this.call<ProtocolInfo[]>('threshold_getProtocolInfo', {})
}
/**
* Get chain configuration
*/
async getChainConfig(chain: Chain): Promise<ChainConfig> {
return this.call<ChainConfig>('threshold_getChainConfig', { chain })
}
/**
* Resolve protocol for a chain
*/
async resolveProtocol(chain: Chain, protocol?: Protocol): Promise<Protocol> {
return this.call<Protocol>('threshold_resolveProtocol', { chain, protocol })
}
// ===========================================================================
// Internal
// ===========================================================================
private async call<T>(method: string, params: unknown): Promise<T> {
const request: JsonRpcRequest = {
jsonrpc: '2.0',
id: ++this.requestId,
method,
params,
}
const controller = new AbortController()
const timeoutId = setTimeout(() => controller.abort(), this.timeout)
try {
const response = await fetch(this.endpoint, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(request),
signal: controller.signal,
})
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`)
}
const json = (await response.json()) as JsonRpcResponse<T>
if (json.error) {
throw new Error(`RPC error ${json.error.code}: ${json.error.message}`)
}
return json.result as T
} finally {
clearTimeout(timeoutId)
}
}
private sleep(ms: number): Promise<void> {
return new Promise(resolve => setTimeout(resolve, ms))
}
}
+73
View File
@@ -0,0 +1,73 @@
// Copyright (C) 2019-2025, Lux Industries, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
/**
* @luxfi/threshold - T-Chain (ThresholdVM) SDK
*
* TypeScript SDK for interacting with T-Chain MPC threshold signatures.
*
* @example
* ```ts
* import { ThresholdClient } from '@luxfi/threshold'
*
* const client = new ThresholdClient({
* endpoint: 'http://localhost:9650/ext/bc/T'
* })
*
* // Generate key for Ethereum (auto-selects LSS protocol)
* const keygen = await client.keygen({ keyId: 'eth-key', chain: 'ethereum' })
* const result = await client.waitForKeygen(keygen.sessionId)
*
* // Generate key for Solana (auto-selects FROST protocol)
* const solKeygen = await client.keygen({ keyId: 'sol-key', chain: 'solana' })
*
* // Sign with a key
* const sig = await client.signAndWait({
* keyId: 'eth-key',
* messageHash: '0x...',
* messageType: 'eth_sign'
* })
* ```
*
* @packageDocumentation
*/
export { ThresholdClient } from './client'
export type {
// Client options
ThresholdClientOptions,
// Protocol types
Protocol,
Chain,
ProtocolInfo,
ChainConfig,
// Keygen
KeygenRequest,
KeygenResponse,
// Sign
SignRequest,
SignResponse,
SignatureResponse,
// Key management
KeyInfo,
ReshareRequest,
RefreshRequest,
// Session management
SessionInfo,
SessionListOptions,
// Network info
NetworkStats,
QuotaInfo,
HealthStatus,
ThresholdInfo,
// JSON-RPC
JsonRpcRequest,
JsonRpcResponse,
} from './types'
+215
View File
@@ -0,0 +1,215 @@
// Copyright (C) 2019-2025, Lux Industries, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
// T-Chain (ThresholdVM) Types
/** Supported MPC protocols */
export type Protocol = 'lss' | 'cggmp21' | 'frost' | 'bls' | 'corona'
/** Supported blockchain chains */
export type Chain =
| 'ethereum' | 'bitcoin' | 'solana' | 'xrpl' | 'lux'
| 'bsc' | 'polygon' | 'base' | 'ton' | 'near' | 'aptos' | 'sui' | 'cardano'
/** Keygen request parameters */
export interface KeygenRequest {
/** Unique key identifier */
keyId: string
/** Target chain (auto-selects protocol) */
chain?: Chain
/** Explicit protocol selection */
protocol?: Protocol
/** Signature threshold (t in t-of-n) */
threshold?: number
/** Total parties (n in t-of-n) */
totalParties?: number
}
/** Keygen response */
export interface KeygenResponse {
sessionId: string
keyId: string
protocol: Protocol
status: 'pending' | 'running' | 'completed' | 'failed'
threshold: number
totalParties: number
publicKey?: string
startedAt: number
completedAt?: number
error?: string
}
/** Sign request parameters */
export interface SignRequest {
/** Key ID to sign with */
keyId: string
/** Message hash to sign (hex encoded) */
messageHash: string
/** Message type for EVM compatibility */
messageType?: 'raw' | 'eth_sign' | 'typed_data'
}
/** Sign session response */
export interface SignResponse {
sessionId: string
keyId: string
status: 'pending' | 'signing' | 'completed' | 'failed'
createdAt: number
expiresAt: number
}
/** Completed signature */
export interface SignatureResponse {
sessionId: string
status: 'completed' | 'failed'
/** Full signature (hex) */
signature?: string
/** ECDSA r component (hex) */
r?: string
/** ECDSA s component (hex) */
s?: string
/** ECDSA recovery id */
v?: number
/** Parties that participated */
signerParties?: string[]
completedAt?: number
error?: string
}
/** Key information */
export interface KeyInfo {
keyId: string
protocol: Protocol
chain?: Chain
publicKey: string
threshold: number
totalParties: number
generation: number
createdAt: number
lastUsed?: number
}
/** Chain configuration */
export interface ChainConfig {
chain: Chain
defaultProtocol: Protocol
signatureType: 'ecdsa' | 'eddsa' | 'schnorr'
curve: string
altProtocols: Protocol[]
}
/** Protocol information */
export interface ProtocolInfo {
name: Protocol
description: string
supportedCurves: string[]
supportsReshare: boolean
supportsRefresh: boolean
isPostQuantum: boolean
keySize: number
signatureSize: number
}
/** Reshare request */
export interface ReshareRequest {
keyId: string
newPartyIds: string[]
newThreshold: number
}
/** Refresh request */
export interface RefreshRequest {
keyId: string
}
/** Batch sign request */
export interface BatchSignRequest {
keyId: string
messageHashes: string[]
}
/** Session info */
export interface SessionInfo {
sessionId: string
type: 'keygen' | 'sign' | 'reshare' | 'refresh'
keyId: string
status: 'pending' | 'running' | 'completed' | 'failed'
requestingChain?: string
createdAt: number
expiresAt?: number
completedAt?: number
error?: string
}
/** Session list options */
export interface SessionListOptions {
chainId?: string
status?: string
limit?: number
}
/** Network stats */
export interface NetworkStats {
totalKeys: number
totalSignatures: number
activeSessions: number
uptime: number
}
/** Quota info */
export interface QuotaInfo {
chainId: string
dailyLimit: number
used: number
remaining: number
resetsAt: number
}
/** Health status */
export interface HealthStatus {
healthy: boolean
ready: boolean
version: string
uptime: number
}
/** Threshold info */
export interface ThresholdInfo {
version: string
networkId: string
chainId: string
supportedProtocols: Protocol[]
supportedChains: Chain[]
maxActiveSessions: number
currentSessions: number
}
/** T-Chain client options */
export interface ThresholdClientOptions {
/** T-Chain RPC endpoint */
endpoint: string
/** Requesting chain ID */
chainId?: string
/** Request timeout in ms */
timeout?: number
}
/** JSON-RPC request */
export interface JsonRpcRequest {
jsonrpc: '2.0'
id: number
method: string
params: unknown
}
/** JSON-RPC response */
export interface JsonRpcResponse<T> {
jsonrpc: '2.0'
id: number
result?: T
error?: {
code: number
message: string
data?: unknown
}
}
+7
View File
@@ -0,0 +1,7 @@
{
"extends": "./tsconfig.json",
"compilerOptions": {
"module": "CommonJS",
"outDir": "./dist/cjs"
}
}
+18
View File
@@ -0,0 +1,18 @@
{
"compilerOptions": {
"target": "ES2020",
"module": "ESNext",
"moduleResolution": "node",
"declaration": true,
"declarationMap": true,
"sourceMap": true,
"outDir": "./dist/esm",
"rootDir": "./src",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true
},
"include": ["src/**/*"],
"exclude": ["node_modules", "dist", "**/*.test.ts"]
}
+11
View File
@@ -0,0 +1,11 @@
// Copyright (C) 2019-2025, Lux Industries, Inc. All rights reserved.
// See the file LICENSE for licensing terms.
import { defineConfig } from 'vitest/config'
export default defineConfig({
test: {
globals: true,
environment: 'node',
},
})
+297 -36
View File
@@ -55,10 +55,10 @@ importers:
dependencies:
'@eth-optimism/contracts-ts':
specifier: ^0.15.0
version: 0.15.0(34f030d2ed323f78be8b2b21bd7390d7)
version: 0.15.0(yi3anhbuujv26dssci7jqe6fp4)
'@hanzo/auth':
specifier: 'catalog:'
version: 2.5.2(27e824a0c09c8092aa97dbf48fafa45d)
version: 2.5.2(wkyb74ra2jmi57cji7wrlawzum)
'@hanzo/ui':
specifier: 4.2.0
version: 4.2.0(@hookform/[email protected]([email protected]([email protected])))(@types/[email protected])(@types/[email protected])([email protected])([email protected])([email protected]([email protected]))([email protected])([email protected]([email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected]))([email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected]([email protected]))([email protected])([email protected]([email protected](@swc/[email protected](@swc/[email protected]))(@types/[email protected])([email protected])))([email protected])([email protected])
@@ -76,7 +76,7 @@ importers:
version: 1.4.13(@babel/[email protected])(@react-native-async-storage/[email protected]([email protected](@babel/[email protected])(@babel/[email protected](@babel/[email protected]))(@types/[email protected])([email protected])([email protected])([email protected])))([email protected])([email protected])([email protected])
'@luxfi/ui':
specifier: 5.4.1
version: 5.4.1(301454696a92411efb184a2d85c0af85)
version: 5.4.1(px6id3wphxuup2cr65g4ubf3v4)
'@metamask/jazzicon':
specifier: ^2.0.0
version: 2.0.0
@@ -686,10 +686,10 @@ importers:
dependencies:
'@hanzo/auth':
specifier: 'catalog:'
version: 2.5.2(50044b4065d82c97fe38f30ed14476d1)
version: 2.5.2(hbthe6k7s2d53tf3xeoft4ahza)
'@hanzo/commerce':
specifier: 'catalog:'
version: 7.3.4(f29346bd531566445db2133214d0b4e9)
version: 7.3.4(abnvx4oqfkb2cbpf2vp7zuzosy)
react:
specifier: 'catalog:'
version: 18.3.1
@@ -701,6 +701,15 @@ importers:
specifier: 'catalog:'
version: 5.7.2
pkg/threshold:
devDependencies:
typescript:
specifier: ^5.7.2
version: 5.7.2
vitest:
specifier: ^2.1.0
version: 2.1.9(@types/[email protected])([email protected])
pkg/ui:
dependencies:
ethers:
@@ -6220,6 +6229,35 @@ packages:
'@vercel/[email protected]':
resolution: {integrity: sha512-2qtvcBJ1bGY0dYGYh3iM7yGKkk971FujLEDXzuW5wcZsPr1GSEjO/w2iSr3qve6nDDtBImsGoDEnus5FI4+fIw==}
'@vitest/[email protected]':
resolution: {integrity: sha512-UJCIkTBenHeKT1TTlKMJWy1laZewsRIzYighyYiJKZreqtdxSos/S1t+ktRMQWu2CKqaarrkeszJx1cgC5tGZw==}
'@vitest/[email protected]':
resolution: {integrity: sha512-tVL6uJgoUdi6icpxmdrn5YNo3g3Dxv+IHJBr0GXHaEdTcw3F+cPKnsXFhli6nO+f/6SDKPHEK1UN+k+TQv0Ehg==}
peerDependencies:
msw: ^2.4.9
vite: ^5.0.0
peerDependenciesMeta:
msw:
optional: true
vite:
optional: true
'@vitest/[email protected]':
resolution: {integrity: sha512-KhRIdGV2U9HOUzxfiHmY8IFHTdqtOhIzCpd8WRdJiE7D/HUcZVD0EgQCVjm+Q9gkUXWgBvMmTtZgIG48wq7sOQ==}
'@vitest/[email protected]':
resolution: {integrity: sha512-ZXSSqTFIrzduD63btIfEyOmNcBmQvgOVsPNPe0jYtESiXkhd8u2erDLnMxmGrDCwHCCHE7hxwRDCT3pt0esT4g==}
'@vitest/[email protected]':
resolution: {integrity: sha512-oBO82rEjsxLNJincVhLhaxxZdEtV0EFHMK5Kmx5sJ6H9L183dHECjiefOAdnqpIgT5eZwT04PoggUnW88vOBNQ==}
'@vitest/[email protected]':
resolution: {integrity: sha512-E1B35FwzXXTs9FHNK6bDszs7mtydNi5MIfUWpceJ8Xbfb1gBMscAnwLbEu+B44ed6W3XjL9/ehLPHR1fkf1KLQ==}
'@vitest/[email protected]':
resolution: {integrity: sha512-v0psaMSkNJ3A2NMrUEHFRzJtDPFn+/VWZ5WxImB21T9fjucJRmS7xCS3ppEnARb9y11OAzaD+P2Ps+b+BGX5iQ==}
'@wagmi/[email protected]':
resolution: {integrity: sha512-wzxp9f9PtSUFjDUP/QDjc1t7HON4D8wrVKsw35ejdO8hToDpx1gU9lwH/47Zo/1zExGezQc392sjoHSszYd7OA==}
peerDependencies:
@@ -6881,6 +6919,10 @@ packages:
[email protected]:
resolution: {integrity: sha512-eLHpSK/Y4nhMJ07gDaAzoX/XAKS8PSaojml3M0DM4JpV1LAi5JOJ/p6H/XWrl8L+DzVEvVCW1z3vWAaB9oTsQw==}
[email protected]:
resolution: {integrity: sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==}
engines: {node: '>=12'}
[email protected]:
resolution: {integrity: sha512-c27loCv9QkZinsa5ProX751khO9DJl/AcB5c2KNtA6NRvHKS0PgLfcftz72KVq504vB0Gku5s2kUZzDBvQWvHg==}
engines: {node: '>=4'}
@@ -7369,6 +7411,10 @@ packages:
[email protected]:
resolution: {integrity: sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==}
[email protected]:
resolution: {integrity: sha512-4zNhdJD/iOjSH0A05ea+Ke6MU5mmpQcbQsSOkgdaUMJ9zTlDTD/GYlwohmIE2u0gaxHYiVHEn1Fw9mZ/ktJWgw==}
engines: {node: '>=18'}
[email protected]:
resolution: {integrity: sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==}
engines: {node: '>=8'}
@@ -7397,6 +7443,10 @@ packages:
[email protected]:
resolution: {integrity: sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==}
[email protected]:
resolution: {integrity: sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==}
engines: {node: '>= 16'}
[email protected]:
resolution: {integrity: sha512-J/NdY2WvIx654cc6LWSq/IYFFCUf75fFTgwzFnmbqyORH4MwgiQCgswLLKBGzmsyTI5V7i5bp/So6sMbDWhedg==}
@@ -8174,6 +8224,10 @@ packages:
babel-plugin-macros:
optional: true
[email protected]:
resolution: {integrity: sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==}
engines: {node: '>=6'}
[email protected]:
resolution: {integrity: sha512-ZIwpnevOurS8bpT4192sqAowWM76JDKSHYzMLty3BZGSswgq6pBaH3DhCSW5xVAZICZyKdOBPjwww5wfgT/6PA==}
engines: {node: '>= 0.4'}
@@ -9086,6 +9140,10 @@ packages:
resolution: {integrity: sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==}
engines: {node: '>=6'}
[email protected]:
resolution: {integrity: sha512-knvyeauYhqjOYvQ66MznSMs83wmHrCycNEN6Ao+2AeYEfxUIkuiVxdEa1qlGEPK+We3n0THiDciYSsCcgW/DoA==}
engines: {node: '>=12.0.0'}
[email protected]:
resolution: {integrity: sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==}
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
@@ -10880,6 +10938,9 @@ packages:
resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==}
hasBin: true
[email protected]:
resolution: {integrity: sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ==}
[email protected]:
resolution: {integrity: sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==}
@@ -12172,6 +12233,10 @@ packages:
[email protected]:
resolution: {integrity: sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==}
[email protected]:
resolution: {integrity: sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ==}
engines: {node: '>= 14.16'}
[email protected]:
resolution: {integrity: sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==}
engines: {node: '>=0.12'}
@@ -13594,6 +13659,9 @@ packages:
resolution: {integrity: sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==}
engines: {node: '>= 0.4'}
[email protected]:
resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==}
[email protected]:
resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==}
@@ -13732,6 +13800,9 @@ packages:
resolution: {integrity: sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==}
engines: {node: '>=10'}
[email protected]:
resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==}
[email protected]:
resolution: {integrity: sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==}
@@ -13747,6 +13818,9 @@ packages:
resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==}
engines: {node: '>= 0.8'}
[email protected]:
resolution: {integrity: sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg==}
[email protected]:
resolution: {integrity: sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==}
engines: {node: '>= 0.4'}
@@ -14136,10 +14210,28 @@ packages:
[email protected]:
resolution: {integrity: sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA==}
[email protected]:
resolution: {integrity: sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==}
[email protected]:
resolution: {integrity: sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==}
[email protected]:
resolution: {integrity: sha512-Zc+8eJlFMvgatPZTl6A9L/yht8QqdmUNtURHaKZLmKBE12hNPSrqNkUp2cs3M/UKmNVVAMFQYSjYIVHDjW5zew==}
engines: {node: '>=12.0.0'}
[email protected]:
resolution: {integrity: sha512-Zba82s87IFq9A9XmjiX5uZA/ARWDrB03OHlq+Vw1fSdt0I+4/Kutwy8BP4Y/y/aORMo61FQ0vIb5j44vSo5Pkg==}
engines: {node: ^18.0.0 || >=20.0.0}
[email protected]:
resolution: {integrity: sha512-weEDEq7Z5eTHPDh4xjX789+fHfF+P8boiFB+0vbWzpbnbsEr/GRaohi/uMKxg8RZMXnl1ItAi/IUHWMsjDV7kQ==}
engines: {node: '>=14.0.0'}
[email protected]:
resolution: {integrity: sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==}
engines: {node: '>=14.0.0'}
[email protected]:
resolution: {integrity: sha512-nZD7m9iCPC5g0pYmcaxogYKggSfLsdxl8of3Q/oIbqCqLLIO9IAF0GWjX1z9NZRHPiXv8Wex4yDCaZsgEw0Y8w==}
engines: {node: '>=14.14'}
@@ -14856,6 +14948,11 @@ packages:
engines: {node: ^18.0.0 || >=20.0.0}
hasBin: true
[email protected]:
resolution: {integrity: sha512-AM9aQ/IPrW/6ENLQg3AGY4K1N2TGZdR5e4gu/MmmR2xR3Ll1+dib+nook92g4TV3PXVyeyxdWwtaCAiUL0hMxA==}
engines: {node: ^18.0.0 || >=20.0.0}
hasBin: true
[email protected]:
resolution: {integrity: sha512-gEIbKfJzSEv0yR3XS2QEocKetONoWkbROj6hGx0FHM18qKUojhvcokQsxQx5nMkelZq2n37zbSGCJn+FSODSjA==}
peerDependencies:
@@ -14895,6 +14992,31 @@ packages:
terser:
optional: true
[email protected]:
resolution: {integrity: sha512-MSmPM9REYqDGBI8439mA4mWhV5sKmDlBKWIYbA3lRb2PTHACE0mgKwA8yQ2xq9vxDTuk4iPrECBAEW2aoFXY0Q==}
engines: {node: ^18.0.0 || >=20.0.0}
hasBin: true
peerDependencies:
'@edge-runtime/vm': '*'
'@types/node': ^18.0.0 || >=20.0.0
'@vitest/browser': 2.1.9
'@vitest/ui': 2.1.9
happy-dom: '*'
jsdom: '*'
peerDependenciesMeta:
'@edge-runtime/vm':
optional: true
'@types/node':
optional: true
'@vitest/browser':
optional: true
'@vitest/ui':
optional: true
happy-dom:
optional: true
jsdom:
optional: true
[email protected]:
resolution: {integrity: sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w==}
@@ -15326,6 +15448,11 @@ packages:
engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0}
hasBin: true
[email protected]:
resolution: {integrity: sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==}
engines: {node: '>=8'}
hasBin: true
[email protected]:
resolution: {integrity: sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A==}
engines: {node: '>= 12.0.0'}
@@ -17009,7 +17136,7 @@ snapshots:
dependencies:
levn: 0.4.1
'@eth-optimism/[email protected](34f030d2ed323f78be8b2b21bd7390d7)':
'@eth-optimism/[email protected](yi3anhbuujv26dssci7jqe6fp4)':
dependencies:
'@testing-library/react': 14.3.1([email protected]([email protected]))([email protected])
react: 18.3.1
@@ -17757,24 +17884,7 @@ snapshots:
protobufjs: 7.4.0
yargs: 17.7.2
'@hanzo/[email protected](27e824a0c09c8092aa97dbf48fafa45d)':
dependencies:
'@hanzo/ui': 4.2.0(@hookform/[email protected]([email protected]([email protected])))(@types/[email protected])(@types/[email protected])([email protected])([email protected])([email protected]([email protected]))([email protected])([email protected]([email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected]))([email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected]([email protected]))([email protected])([email protected]([email protected](@swc/[email protected](@swc/[email protected]))(@types/[email protected])([email protected])))([email protected])([email protected])
'@hookform/resolvers': 3.9.1([email protected]([email protected]))
firebase: 10.12.0(@react-native-async-storage/[email protected]([email protected](@babel/[email protected])(@babel/[email protected](@babel/[email protected]))(@types/[email protected])([email protected])([email protected])([email protected])))
firebase-admin: 12.7.0
lucide-react: 0.307.0([email protected])
mobx: 6.13.5
mobx-react-lite: 4.1.0([email protected])([email protected]([email protected]))([email protected](@babel/[email protected])(@babel/[email protected](@babel/[email protected]))(@types/[email protected])([email protected])([email protected])([email protected]))([email protected])
next: 14.2.16(@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected])
react: 18.3.1
react-hook-form: 7.54.2([email protected])
zod: 3.24.1
transitivePeerDependencies:
- encoding
- supports-color
'@hanzo/[email protected](50044b4065d82c97fe38f30ed14476d1)':
'@hanzo/[email protected](hbthe6k7s2d53tf3xeoft4ahza)':
dependencies:
'@hanzo/ui': 4.4.1(@hookform/[email protected]([email protected]([email protected])))(@types/[email protected])(@types/[email protected])([email protected])([email protected])([email protected]([email protected]))([email protected])([email protected]([email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected]))([email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected]([email protected]))([email protected])([email protected]([email protected](@swc/[email protected](@swc/[email protected]))(@types/[email protected])([email protected])))([email protected])([email protected])
'@hookform/resolvers': 3.9.1([email protected]([email protected]))
@@ -17791,15 +17901,32 @@ snapshots:
- encoding
- supports-color
'@hanzo/[email protected](cde5211da0f3560591d3609eca7d7328)':
'@hanzo/[email protected](wkyb74ra2jmi57cji7wrlawzum)':
dependencies:
'@hanzo/auth': 2.5.2(27e824a0c09c8092aa97dbf48fafa45d)
'@hanzo/ui': 4.2.0(@hookform/[email protected]([email protected]([email protected])))(@types/[email protected])(@types/[email protected])([email protected])([email protected])([email protected]([email protected]))([email protected])([email protected]([email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected]))([email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected]([email protected]))([email protected])([email protected]([email protected](@swc/[email protected](@swc/[email protected]))(@types/[email protected])([email protected])))([email protected])([email protected])
'@hookform/resolvers': 3.9.1([email protected]([email protected]))
firebase: 10.12.0(@react-native-async-storage/[email protected]([email protected](@babel/[email protected])(@babel/[email protected](@babel/[email protected]))(@types/[email protected])([email protected])([email protected])([email protected])))
firebase-admin: 12.7.0
lucide-react: 0.307.0([email protected])
mobx: 6.13.5
mobx-react-lite: 4.1.0([email protected])([email protected]([email protected]))([email protected](@babel/[email protected])(@babel/[email protected](@babel/[email protected]))(@types/[email protected])([email protected])([email protected])([email protected]))([email protected])
next: 14.2.16(@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected])
react: 18.3.1
react-hook-form: 7.54.2([email protected])
zod: 3.24.1
transitivePeerDependencies:
- encoding
- supports-color
'@hanzo/[email protected](abnvx4oqfkb2cbpf2vp7zuzosy)':
dependencies:
'@hanzo/auth': 2.5.2(hbthe6k7s2d53tf3xeoft4ahza)
'@hanzo/ui': 4.4.1(@hookform/[email protected]([email protected]([email protected])))(@types/[email protected])(@types/[email protected])([email protected])([email protected])([email protected]([email protected]))([email protected])([email protected]([email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected]))([email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected]([email protected]))([email protected])([email protected]([email protected](@swc/[email protected](@swc/[email protected]))(@types/[email protected])([email protected])))([email protected])([email protected])
'@hookform/resolvers': 3.9.1([email protected]([email protected]))
'@radix-ui/react-radio-group': 1.2.2(@types/[email protected])(@types/[email protected])([email protected]([email protected]))([email protected])
ethers: 6.13.4([email protected])([email protected])
firebase: 10.12.0(@react-native-async-storage/[email protected]([email protected](@babel/[email protected])(@babel/[email protected](@babel/[email protected]))(@types/[email protected])([email protected])([email protected])([email protected])))
lucide-react: 0.307.0([email protected])
lucide-react: 0.456.0([email protected])
mobx: 6.13.5
mobx-react-lite: 4.1.0([email protected])([email protected]([email protected]))([email protected](@babel/[email protected])(@babel/[email protected](@babel/[email protected]))(@types/[email protected])([email protected])([email protected])([email protected]))([email protected])
mobx-utils: 6.1.0([email protected])
@@ -17816,15 +17943,15 @@ snapshots:
- debug
- utf-8-validate
'@hanzo/[email protected](f29346bd531566445db2133214d0b4e9)':
'@hanzo/[email protected](ywtcqmtupb2lcax2n5vadtce64)':
dependencies:
'@hanzo/auth': 2.5.2(50044b4065d82c97fe38f30ed14476d1)
'@hanzo/ui': 4.4.1(@hookform/[email protected]([email protected]([email protected])))(@types/[email protected])(@types/[email protected])([email protected])([email protected])(lucide-react@0.456.0([email protected]))([email protected])([email protected]([email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected]))([email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected]([email protected]))([email protected])([email protected]([email protected](@swc/[email protected](@swc/[email protected]))(@types/node@22.10.3)([email protected])))([email protected])([email protected])
'@hanzo/auth': 2.5.2(wkyb74ra2jmi57cji7wrlawzum)
'@hanzo/ui': 4.2.0(@hookform/[email protected]([email protected]([email protected])))(@types/[email protected])(@types/[email protected])([email protected])([email protected])(lucide-react@0.307.0([email protected]))([email protected])([email protected]([email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected]))([email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected]([email protected]))([email protected])([email protected]([email protected](@swc/[email protected](@swc/[email protected]))(@types/node@20.17.11)([email protected])))([email protected])([email protected])
'@hookform/resolvers': 3.9.1([email protected]([email protected]))
'@radix-ui/react-radio-group': 1.2.2(@types/[email protected])(@types/[email protected])([email protected]([email protected]))([email protected])
ethers: 6.13.4([email protected])([email protected])
firebase: 10.12.0(@react-native-async-storage/[email protected]([email protected](@babel/[email protected])(@babel/[email protected](@babel/[email protected]))(@types/[email protected])([email protected])([email protected])([email protected])))
lucide-react: 0.456.0([email protected])
lucide-react: 0.307.0([email protected])
mobx: 6.13.5
mobx-react-lite: 4.1.0([email protected])([email protected]([email protected]))([email protected](@babel/[email protected])(@babel/[email protected](@babel/[email protected]))(@types/[email protected])([email protected])([email protected])([email protected]))([email protected])
mobx-utils: 6.1.0([email protected])
@@ -18455,10 +18582,10 @@ snapshots:
transitivePeerDependencies:
- react-dom
'@luxfi/[email protected](301454696a92411efb184a2d85c0af85)':
'@luxfi/[email protected](px6id3wphxuup2cr65g4ubf3v4)':
dependencies:
'@hanzo/auth': 2.5.2(27e824a0c09c8092aa97dbf48fafa45d)
'@hanzo/commerce': 7.3.4(cde5211da0f3560591d3609eca7d7328)
'@hanzo/auth': 2.5.2(wkyb74ra2jmi57cji7wrlawzum)
'@hanzo/commerce': 7.3.4(ywtcqmtupb2lcax2n5vadtce64)
'@hanzo/ui': 4.2.0(@hookform/[email protected]([email protected]([email protected])))(@types/[email protected])(@types/[email protected])([email protected])([email protected])([email protected]([email protected]))([email protected])([email protected]([email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected]))([email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected]))([email protected]([email protected]))([email protected]([email protected]))([email protected])([email protected]([email protected](@swc/[email protected](@swc/[email protected]))(@types/[email protected])([email protected])))([email protected])([email protected])
'@hookform/resolvers': 3.9.1([email protected]([email protected]))
'@next/third-parties': 14.2.22([email protected](@babel/[email protected])(@opentelemetry/[email protected])([email protected]([email protected]))([email protected]))([email protected])
@@ -20337,7 +20464,7 @@ snapshots:
metro-core: 0.81.0
node-fetch: 2.7.0
readline: 1.3.0
semver: 7.6.3
semver: 7.7.2
transitivePeerDependencies:
- '@babel/core'
- '@babel/preset-env'
@@ -23330,6 +23457,46 @@ snapshots:
json-schema-to-ts: 1.6.4
ts-morph: 12.0.0
'@vitest/[email protected]':
dependencies:
'@vitest/spy': 2.1.9
'@vitest/utils': 2.1.9
chai: 5.3.3
tinyrainbow: 1.2.0
'@vitest/[email protected]([email protected](@types/[email protected])([email protected]))':
dependencies:
'@vitest/spy': 2.1.9
estree-walker: 3.0.3
magic-string: 0.30.17
optionalDependencies:
vite: 5.4.11(@types/[email protected])([email protected])
'@vitest/[email protected]':
dependencies:
tinyrainbow: 1.2.0
'@vitest/[email protected]':
dependencies:
'@vitest/utils': 2.1.9
pathe: 1.1.2
'@vitest/[email protected]':
dependencies:
'@vitest/pretty-format': 2.1.9
magic-string: 0.30.17
pathe: 1.1.2
'@vitest/[email protected]':
dependencies:
tinyspy: 3.0.2
'@vitest/[email protected]':
dependencies:
'@vitest/pretty-format': 2.1.9
loupe: 3.2.1
tinyrainbow: 1.2.0
'@wagmi/[email protected](@react-native-async-storage/[email protected]([email protected](@babel/[email protected])(@babel/[email protected](@babel/[email protected]))(@types/[email protected])([email protected])([email protected])([email protected])))(@types/[email protected])([email protected])([email protected])([email protected])([email protected])([email protected]([email protected])([email protected])([email protected])([email protected]))([email protected])':
dependencies:
'@coinbase/wallet-sdk': 3.9.3
@@ -24992,6 +25159,8 @@ snapshots:
object.assign: 4.1.7
util: 0.12.5
[email protected]: {}
[email protected]:
dependencies:
tslib: 2.3.0
@@ -25586,6 +25755,14 @@ snapshots:
[email protected]: {}
[email protected]:
dependencies:
assertion-error: 2.0.1
check-error: 2.1.1
deep-eql: 5.0.2
loupe: 3.2.1
pathval: 2.0.1
[email protected]:
dependencies:
ansi-styles: 4.3.0
@@ -25608,6 +25785,8 @@ snapshots:
[email protected]: {}
[email protected]: {}
[email protected]:
dependencies:
functional-red-black-tree: 1.0.1
@@ -26482,6 +26661,8 @@ snapshots:
[email protected]: {}
[email protected]: {}
[email protected]:
dependencies:
array-buffer-byte-length: 1.0.2
@@ -27779,6 +27960,8 @@ snapshots:
[email protected]: {}
[email protected]: {}
[email protected]:
dependencies:
'@jest/expect-utils': 29.7.0
@@ -30026,6 +30209,8 @@ snapshots:
dependencies:
js-tokens: 4.0.0
[email protected]: {}
[email protected]:
dependencies:
tslib: 2.3.0
@@ -31939,6 +32124,8 @@ snapshots:
[email protected]: {}
[email protected]: {}
[email protected]:
dependencies:
create-hash: 1.2.0
@@ -32844,7 +33031,7 @@ snapshots:
react-refresh: 0.14.2
regenerator-runtime: 0.13.11
scheduler: 0.24.0-canary-efb381bbf-20230505
semver: 7.6.3
semver: 7.7.2
stacktrace-parser: 0.1.10
whatwg-fetch: 3.6.20
ws: 6.2.3([email protected])([email protected])
@@ -33713,6 +33900,8 @@ snapshots:
side-channel-map: 1.0.1
side-channel-weakmap: 1.0.2
[email protected]: {}
[email protected]: {}
[email protected]: {}
@@ -33872,6 +34061,8 @@ snapshots:
dependencies:
escape-string-regexp: 2.0.0
[email protected]: {}
[email protected]: {}
[email protected]:
@@ -33882,6 +34073,8 @@ snapshots:
[email protected]: {}
[email protected]: {}
[email protected]:
dependencies:
es-errors: 1.3.0
@@ -34422,11 +34615,21 @@ snapshots:
[email protected]: {}
[email protected]: {}
[email protected]: {}
[email protected]:
dependencies:
fdir: 6.4.2([email protected])
picomatch: 4.0.2
[email protected]: {}
[email protected]: {}
[email protected]: {}
[email protected]: {}
[email protected]: {}
@@ -35127,6 +35330,24 @@ snapshots:
- supports-color
- terser
[email protected](@types/[email protected])([email protected]):
dependencies:
cac: 6.7.14
debug: 4.4.0([email protected])
es-module-lexer: 1.6.0
pathe: 1.1.2
vite: 5.4.11(@types/[email protected])([email protected])
transitivePeerDependencies:
- '@types/node'
- less
- lightningcss
- sass
- sass-embedded
- stylus
- sugarss
- supports-color
- terser
[email protected]([email protected])([email protected](@types/[email protected])([email protected])):
dependencies:
debug: 4.4.0([email protected])
@@ -35148,6 +35369,41 @@ snapshots:
fsevents: 2.3.3
terser: 5.37.0
[email protected](@types/[email protected])([email protected]):
dependencies:
'@vitest/expect': 2.1.9
'@vitest/mocker': 2.1.9([email protected](@types/[email protected])([email protected]))
'@vitest/pretty-format': 2.1.9
'@vitest/runner': 2.1.9
'@vitest/snapshot': 2.1.9
'@vitest/spy': 2.1.9
'@vitest/utils': 2.1.9
chai: 5.3.3
debug: 4.4.0([email protected])
expect-type: 1.3.0
magic-string: 0.30.17
pathe: 1.1.2
std-env: 3.10.0
tinybench: 2.9.0
tinyexec: 0.3.2
tinypool: 1.1.1
tinyrainbow: 1.2.0
vite: 5.4.11(@types/[email protected])([email protected])
vite-node: 2.1.9(@types/[email protected])([email protected])
why-is-node-running: 2.3.0
optionalDependencies:
'@types/node': 22.10.3
transitivePeerDependencies:
- less
- lightningcss
- msw
- sass
- sass-embedded
- stylus
- sugarss
- supports-color
- terser
[email protected]: {}
[email protected]: {}
@@ -36153,6 +36409,11 @@ snapshots:
dependencies:
isexe: 2.0.0
[email protected]:
dependencies:
siginfo: 2.0.0
stackback: 0.0.2
[email protected]:
dependencies:
logform: 2.7.0