Initial commit

This commit is contained in:
defiQUG
2026-01-01 08:04:06 -08:00
commit d0bc005be1
75 changed files with 15082 additions and 0 deletions

58
packages/bridge/README.md Normal file
View File

@@ -0,0 +1,58 @@
# @dbis-thirdweb/bridge
Bridge routes and execution for Chain 138.
## Usage
### Get Supported Routes
```typescript
import { getSupportedRoutes, isRouteSupported } from '@dbis-thirdweb/bridge';
const routes = getSupportedRoutes();
const isSupported = isRouteSupported(1, 138); // Ethereum to Chain 138
```
### Generate Bridge Quote
```typescript
import { generateBridgeQuote, getAllBridgeableTokens } from '@dbis-thirdweb/bridge';
import { ethers } from 'ethers';
const tokens = getAllBridgeableTokens();
const nativeToken = tokens.find(t => t.isNative);
const quote = await generateBridgeQuote({
fromChainId: 1,
toChainId: 138,
token: nativeToken!,
amount: ethers.utils.parseEther('0.1'),
slippageBps: 50, // 0.5%
});
```
### Execute Bridge
```typescript
import { executeBridge, getBridgeStatus } from '@dbis-thirdweb/bridge';
const status = await executeBridge(quote, signer, provider);
// Poll for status
const finalStatus = await getBridgeStatus(status.sourceTxHash, provider);
```
## Features
- Canonical chain mapping for Chain 138
- Supported routes configuration
- Token lists (native, wrapped, stablecoins)
- Quote generation with slippage protection
- Bridge execution helpers
- Status tracking and finality checks
## Notes
- This implementation uses simplified bridge logic
- In production, integrate with thirdweb Bridge SDK or bridge provider APIs
- Token addresses need to be configured for Chain 138's actual deployed tokens

View File

@@ -0,0 +1,38 @@
{
"name": "@dbis-thirdweb/bridge",
"version": "0.1.0",
"description": "Bridge routes and execution for Chain 138",
"type": "module",
"main": "./dist/index.js",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.js"
}
},
"scripts": {
"build": "tsup src/index.ts --format cjs,esm --dts",
"lint": "eslint src",
"test": "echo \"No tests yet\""
},
"keywords": [
"thirdweb",
"bridge",
"chain-138",
"cross-chain"
],
"author": "",
"license": "MIT",
"dependencies": {
"@dbis-thirdweb/chain": "workspace:*",
"@thirdweb-dev/sdk": "^4.0.0",
"ethers": "^5.7.0"
},
"devDependencies": {
"@types/node": "^20.0.0",
"tsup": "^8.0.0",
"typescript": "^5.0.0"
}
}

View File

@@ -0,0 +1,90 @@
import type { Signer, providers } from 'ethers';
import type { BridgeQuote, BridgeStatus } from './types';
import { validateQuote } from './quote';
/**
* Execute bridge transaction
* Note: This is a simplified implementation. In production, you'd use thirdweb Bridge SDK
* or a bridge provider's SDK/API
*/
export async function executeBridge(
quote: BridgeQuote,
signer: Signer,
provider: providers.Provider
): Promise<BridgeStatus> {
// Validate quote
if (!validateQuote(quote)) {
throw new Error('Invalid bridge quote');
}
// In production, this would:
// 1. Use thirdweb Bridge SDK: await bridge.bridge(quote)
// 2. Or call bridge provider API
// 3. Or interact with bridge contract directly
// Simplified implementation - send native transfer as placeholder
// This should be replaced with actual bridge contract interaction
const tx = await signer.sendTransaction({
to: quote.token.address,
value: quote.amount,
// Bridge contract would have specific data/contract interaction here
});
// Wait for transaction
const receipt = await provider.waitForTransaction(tx.hash, 1);
if (!receipt || receipt.status !== 1) {
throw new Error('Bridge transaction failed');
}
return {
sourceTxHash: receipt.transactionHash,
status: 'processing', // Would track through bridge provider to get final status
step: 'Transaction confirmed on source chain',
sourceBlockNumber: receipt.blockNumber,
};
}
/**
* Get bridge status (polling for destination chain confirmation)
*/
export async function getBridgeStatus(
sourceTxHash: string,
provider: providers.Provider
): Promise<BridgeStatus> {
// In production, this would query the bridge provider API or monitor on-chain events
const receipt = await provider.getTransactionReceipt(sourceTxHash);
if (!receipt) {
return {
sourceTxHash,
status: 'pending',
step: 'Waiting for source chain confirmation',
};
}
// Simplified - in production, you'd check bridge provider for destination chain status
return {
sourceTxHash,
status: receipt.status === 1 ? 'processing' : 'failed',
step: receipt.status === 1
? 'Processing bridge - waiting for destination chain'
: 'Bridge transaction failed',
sourceBlockNumber: receipt.blockNumber,
};
}
/**
* Check finality threshold for Chain 138
*/
export const FINALITY_THRESHOLD_BLOCKS = 1; // Adjust based on Chain 138's finality rules
/**
* Check if bridge transaction has reached finality
*/
export async function checkFinality(
blockNumber: number,
currentBlockNumber: number
): Promise<boolean> {
return currentBlockNumber >= blockNumber + FINALITY_THRESHOLD_BLOCKS;
}

View File

@@ -0,0 +1,5 @@
export * from './types';
export * from './routes';
export * from './tokenLists';
export * from './quote';
export * from './execution';

View File

@@ -0,0 +1,75 @@
import type { providers } from 'ethers';
import { ethers } from 'ethers';
import type { BridgeQuote, BridgeableToken } from './types';
import { isRouteSupported } from './routes';
import { chain138 } from '@dbis-thirdweb/chain';
/**
* Generate bridge quote
* Note: This is a simplified implementation. In production, you'd call a bridge provider API
*/
export async function generateBridgeQuote(params: {
fromChainId: number;
toChainId: number;
token: BridgeableToken;
amount: bigint;
provider?: providers.Provider;
slippageBps?: number; // Basis points (e.g., 100 = 1%)
}): Promise<BridgeQuote> {
const { fromChainId, toChainId, token, amount, slippageBps = 50 } = params;
// Validate route
if (!isRouteSupported(fromChainId, toChainId)) {
throw new Error(`Bridge route from ${fromChainId} to ${toChainId} is not supported`);
}
// Simplified quote calculation
// In production, this would call a bridge provider API (e.g., thirdweb Bridge API, Socket, etc.)
const bridgeFeeBps = 10; // 0.1% fee (simplified)
const fee = (amount * BigInt(bridgeFeeBps)) / BigInt(10000);
const estimatedOutput = amount - fee;
// Apply slippage protection
const minimumOutput = (estimatedOutput * BigInt(10000 - slippageBps)) / BigInt(10000);
// Estimated time (simplified - actual time depends on bridge provider and chains)
const estimatedTimeSeconds = 300; // 5 minutes default
return {
fromChainId,
toChainId,
token,
amount,
estimatedOutput,
fee,
estimatedTimeSeconds,
minimumOutput,
};
}
/**
* Validate bridge quote
*/
export function validateQuote(quote: BridgeQuote): boolean {
const amount = typeof quote.amount === 'bigint' ? quote.amount : BigInt(quote.amount.toString());
const estimatedOutput = typeof quote.estimatedOutput === 'bigint' ? quote.estimatedOutput : BigInt(quote.estimatedOutput.toString());
const minimumOutput = typeof quote.minimumOutput === 'bigint' ? quote.minimumOutput : BigInt(quote.minimumOutput.toString());
if (amount <= 0n) {
return false;
}
if (estimatedOutput <= 0n) {
return false;
}
if (minimumOutput > estimatedOutput) {
return false;
}
if (!isRouteSupported(quote.fromChainId, quote.toChainId)) {
return false;
}
return true;
}

View File

@@ -0,0 +1,59 @@
import { chain138 } from '@dbis-thirdweb/chain';
import type { BridgeRoute, BridgeableToken } from './types';
/**
* Native token for Chain 138
*/
export const chain138NativeToken: BridgeableToken = {
address: '0x0000000000000000000000000000000000000000',
symbol: 'ETH',
name: 'Ether',
decimals: 18,
isNative: true,
};
/**
* Canonical chain mapping: supported source chains for bridging to Chain 138
* Add chain IDs that you want to support bridging FROM
*/
export const SUPPORTED_SOURCE_CHAINS = [
1, // Ethereum Mainnet
5, // Goerli
137, // Polygon
80001, // Mumbai
// Add more chains as needed
];
/**
* Get supported bridge routes TO Chain 138
*/
export function getSupportedRoutes(): BridgeRoute[] {
return SUPPORTED_SOURCE_CHAINS.map((fromChainId) => ({
fromChainId,
toChainId: chain138.chainId,
tokens: [chain138NativeToken], // Add more tokens as needed
active: true,
}));
}
/**
* Check if a route is supported
*/
export function isRouteSupported(fromChainId: number, toChainId: number): boolean {
return (
toChainId === chain138.chainId &&
SUPPORTED_SOURCE_CHAINS.includes(fromChainId)
);
}
/**
* Get route for specific chain pair
*/
export function getRoute(fromChainId: number, toChainId: number): BridgeRoute | null {
if (!isRouteSupported(fromChainId, toChainId)) {
return null;
}
const routes = getSupportedRoutes();
return routes.find((r) => r.fromChainId === fromChainId) || null;
}

View File

@@ -0,0 +1,50 @@
import type { BridgeableToken } from './types';
import { chain138NativeToken } from './routes';
/**
* Token lists for Chain 138 bridging
*/
/**
* Native and wrapped tokens
*/
export const nativeTokens: BridgeableToken[] = [
chain138NativeToken,
// Add WETH if it exists on Chain 138
// {
// address: '0x...',
// symbol: 'WETH',
// name: 'Wrapped Ether',
// decimals: 18,
// isNative: false,
// },
];
/**
* Stablecoins (add actual addresses when available)
*/
export const stablecoins: BridgeableToken[] = [
// Example structure - fill in with actual Chain 138 token addresses
// {
// address: '0x...',
// symbol: 'USDC',
// name: 'USD Coin',
// decimals: 6,
// isNative: false,
// },
];
/**
* All bridgeable tokens for Chain 138
*/
export function getAllBridgeableTokens(): BridgeableToken[] {
return [...nativeTokens, ...stablecoins];
}
/**
* Find token by address
*/
export function findToken(address: string): BridgeableToken | undefined {
const tokens = getAllBridgeableTokens();
return tokens.find((token) => token.address.toLowerCase() === address.toLowerCase());
}

View File

@@ -0,0 +1,141 @@
import type { BigNumberish } from 'ethers';
/**
* Supported token for bridging
*/
export interface BridgeableToken {
/**
* Token address (native token uses zero address)
*/
address: string;
/**
* Token symbol
*/
symbol: string;
/**
* Token name
*/
name: string;
/**
* Token decimals
*/
decimals: number;
/**
* Token logo URL (optional)
*/
logoURI?: string;
/**
* Whether this is the native token
*/
isNative: boolean;
}
/**
* Bridge route between two chains
*/
export interface BridgeRoute {
/**
* Source chain ID
*/
fromChainId: number;
/**
* Destination chain ID (should be 138 for Chain 138)
*/
toChainId: number;
/**
* Supported tokens on this route
*/
tokens: BridgeableToken[];
/**
* Whether route is currently active
*/
active: boolean;
}
/**
* Bridge quote
*/
export interface BridgeQuote {
/**
* Source chain ID
*/
fromChainId: number;
/**
* Destination chain ID
*/
toChainId: number;
/**
* Token being bridged
*/
token: BridgeableToken;
/**
* Amount to bridge (in token units)
*/
amount: BigNumberish;
/**
* Estimated output amount (in token units)
*/
estimatedOutput: BigNumberish;
/**
* Bridge fee (in token units)
*/
fee: BigNumberish;
/**
* Estimated time in seconds
*/
estimatedTimeSeconds: number;
/**
* Minimum output amount (slippage protection)
*/
minimumOutput: BigNumberish;
}
/**
* Bridge transaction status
*/
export interface BridgeStatus {
/**
* Transaction hash on source chain
*/
sourceTxHash: string;
/**
* Transaction hash on destination chain (when available)
*/
destinationTxHash?: string;
/**
* Current status
*/
status: 'pending' | 'processing' | 'completed' | 'failed';
/**
* Current step description
*/
step: string;
/**
* Block number on source chain
*/
sourceBlockNumber?: number;
/**
* Block number on destination chain (when available)
*/
destinationBlockNumber?: number;
}

View File

@@ -0,0 +1,12 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "./dist",
"rootDir": "./src",
"composite": false
},
"include": ["src/**/*"],
"references": [
{ "path": "../chain" }
]
}