mirror of
https://github.com/luxfi/bridge.git
synced 2026-09-24 00:26:46 +00:00
Add docs
This commit is contained in:
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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,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)
|
||||
|
||||
@@ -59,7 +59,7 @@ const GlobalFooter = () => {
|
||||
</Link>
|
||||
</div>
|
||||
<p className="text-center text-xs text-muted-2 leading-6">
|
||||
© {new Date().getFullYear()} Lux Partners Limited. All rights reserved.
|
||||
© {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'
|
||||
|
||||
@@ -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,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,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",
|
||||
|
||||
@@ -3,7 +3,7 @@ import {
|
||||
type SwapItem,
|
||||
TransactionStatus,
|
||||
TransactionType,
|
||||
} from "../lib/BridgeApiClient";
|
||||
} from "../lib/BridgeRPCClient";
|
||||
import { SwapStatus } from "../Models/SwapStatus";
|
||||
import {
|
||||
type SwapData,
|
||||
|
||||
@@ -14,7 +14,7 @@ export default [
|
||||
},
|
||||
{
|
||||
name: "author",
|
||||
content: 'Lux Partners Limited',
|
||||
content: 'Lux Industries Inc',
|
||||
},
|
||||
{
|
||||
name: "keywords",
|
||||
|
||||
@@ -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">
|
||||
© {new Date().getFullYear()} Lux Partners Limited. All rights reserved.
|
||||
© {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
@@ -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.
|
||||
|
||||
@@ -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*
|
||||
Vendored
+5
@@ -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.
|
||||
@@ -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/' : '',
|
||||
})
|
||||
@@ -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,"Segoe UI",Roboto,Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";height:100vh;text-align:center;display:flex;flex-direction:column;align-items:center;justify-content:center"><div style="line-height:48px"><style>body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}</style><h1 class="next-error-h1" style="display:inline-block;margin:0 20px 0 0;padding-right:23px;font-size:24px;font-weight:500;vertical-align:top">404</h1><div style="display:inline-block"><h2 style="font-size:14px;font-weight:400;line-height:28px">This page could not be found<!-- -->.</h2></div></div></div></div><script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{"statusCode":404}},"page":"/_error","query":{},"buildId":"iGOSXVPr-sBS_hhOM0Cnj","assetPrefix":"/bridge","nextExport":true,"isFallback":false,"gip":true,"scriptLoader":[]}</script></body></html>
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
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();
|
||||
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,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"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
import type { AppProps } from 'next/app'
|
||||
import '../styles/globals.css'
|
||||
|
||||
export default function App({ Component, pageProps }: AppProps) {
|
||||
return <Component {...pageProps} />
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
import Index from '../content/docs/index.mdx'
|
||||
|
||||
<Index />
|
||||
@@ -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*
|
||||
@@ -0,0 +1,6 @@
|
||||
module.exports = {
|
||||
plugins: {
|
||||
tailwindcss: {},
|
||||
autoprefixer: {},
|
||||
},
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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',
|
||||
}
|
||||
@@ -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
|
||||
@@ -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"]
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
@@ -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')
|
||||
})
|
||||
})
|
||||
})
|
||||
@@ -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))
|
||||
}
|
||||
}
|
||||
@@ -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'
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"module": "CommonJS",
|
||||
"outDir": "./dist/cjs"
|
||||
}
|
||||
}
|
||||
@@ -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"]
|
||||
}
|
||||
@@ -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',
|
||||
},
|
||||
})
|
||||
Generated
+297
-36
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user