+ Connect Your Wallet +
++ To start bridging G$ tokens across chains, please connect your + wallet first. +
+diff --git a/.gitleaks.toml b/.gitleaks.toml new file mode 100644 index 0000000..515ef3b --- /dev/null +++ b/.gitleaks.toml @@ -0,0 +1,10 @@ +# Gitleaks configuration +# Used by Sourcery AI and other secret scanners + +# The hex strings in constants.ts are public blockchain contract addresses, +# not API keys or secrets. They are viewable on-chain by anyone. +[[allowlist]] +description = "Public blockchain contract addresses (not secrets)" +paths = [ + '''packages/bridging-sdk/src/constants\.ts''', +] diff --git a/apps/demo-bridging-app/index.html b/apps/demo-bridging-app/index.html new file mode 100644 index 0000000..c793fa0 --- /dev/null +++ b/apps/demo-bridging-app/index.html @@ -0,0 +1,14 @@ + + +
+ + + ++ Seamlessly convert between Fuse G$ tokens to Celo and vice versa, + enabling versatile use of G$ tokens across various platforms and + ecosystems. +
++ To start bridging G$ tokens across chains, please connect your + wallet first. +
+Protocol Fee: 0.10% of bridged G$ amount
+Provider: {BRIDGE_PROTOCOLS[defaultProtocol]}
+ {fee && ( ++ Bridge fee (pre-execution): {parseFloat(fee.formatted.split(" ")[0]).toFixed(10)} {SUPPORTED_CHAINS[fromChain].name} +
+ )} +Select source and destination chains to see fee estimates.
++ Bridging from {SUPPORTED_CHAINS[fromChain].name} to{" "} + {SUPPORTED_CHAINS[toChain].name} +
+Loading fee...
+ ) : axelarError ? ( +Error loading fee
+ ) : axelarFeeDisplay ? ( ++ {axelarFeeDisplay.amount.toFixed(6)} {axelarFeeDisplay.token} +
+ {amount && ( ++ Total: {getTotalCost("AXELAR").toFixed(6)} {axelarFeeDisplay.token} +
+ )} +No route available
+ )} +Loading fee...
+ ) : lzError ? ( +Error loading fee
+ ) : lzFeeDisplay ? ( ++ {lzFeeDisplay.amount.toFixed(6)} {lzFeeDisplay.token} +
+ {amount && ( ++ Total: {getTotalCost("LAYERZERO").toFixed(6)} {lzFeeDisplay.token} +
+ )} +No route available
+ )} +• Secure cross-chain communication
+• Gas refunds supported
+• Explorer: axelarscan.io
+• Ultra-light node endpoints
+• Custom adapter parameters
+• Explorer: layerzeroscan.com
++ No recent bridge transactions found +
++ Make sure your wallet is connected to see your bridge transactions +
+Loading SDK...
+ if (error) returnError: {error}
+ if (!sdk) returnSDK not initialized
+ + const handleBridge = async () => { + try { + const feeEstimate = await sdk.estimateFee(1, "LAYERZERO") + const receipt = await sdk.bridgeTo( + "0xRecipientAddress", + 1, // Ethereum mainnet + 1000000000000000000n, // 1 G$ + "LAYERZERO", + feeEstimate.fee + ) + + console.log("Bridge successful:", receipt.transactionHash) + } catch (error) { + console.error("Bridge failed:", error) + } + } + + return +} +``` + +## Core Concepts + +### Decimal Handling + +The SDK handles different decimal precision across chains: + +- **Celo/XDC**: 18 decimals +- **Ethereum/Fuse**: 2 decimals + +**Important**: Bridge operations use native token decimals, while limit checks use 18-decimal normalized amounts. + +```typescript +import { normalizeAmount, denormalizeAmount } from "@goodsdks/bridging-sdk" + +// For bridging from Celo (18 decimals) to Ethereum (2 decimals) +const bridgeAmount = 1000000000000000000n // 1 G$ in Celo decimals +const normalizedAmount = normalizeAmount(bridgeAmount, 42220) // Convert to 18 decimals +const ethereumAmount = denormalizeAmount(normalizedAmount, 1) // Convert to 2 decimals +``` + +### Fee Estimation + +Fees are estimated using the GoodServer API and must be covered by `msg.value`: + +```typescript +const feeEstimate = await sdk.estimateFee(targetChainId, "AXELAR") +console.log(`Fee: ${feeEstimate.feeInNative}`) // e.g., "4.8367843657257685 Celo" + +// The fee must be provided as msg.value in the bridge transaction +await sdk.bridgeTo(recipient, targetChainId, amount, "AXELAR", feeEstimate.fee) +``` + +### Transaction Tracking + +Track bridge transactions across chains: + +```typescript +// Get transaction status +const status = await sdk.getTransactionStatus(txHash, "AXELAR") +console.log("Status:", status.status) // "pending" | "completed" | "failed" + +// Get explorer link +const explorerLink = sdk.getExplorerLink(txHash, "AXELAR") +console.log("Explorer:", explorerLink) // https://axelarscan.io/gmp/0x... + +// Get bridge history +const requests = await sdk.getBridgeRequests(userAddress) +const executed = await sdk.getExecutedTransfers(userAddress) +``` + +## API Reference + +### BridgingSDK Class + +#### Constructor + +```typescript +new BridgingSDK(publicClient, walletClient?, chainId?) +``` + +#### Methods + +##### `canBridge(from, amount, targetChainId)` + +Checks if an address can bridge a specified amount to a target chain. + +```typescript +const result = await sdk.canBridge( + "0xUserAddress", + 1000000000000000000n, + 1 // Ethereum mainnet +) +// Returns: { isWithinLimit: boolean, error?: string } +``` + +##### `estimateFee(targetChainId, protocol)` + +Estimates the fee for bridging to a target chain using a specific protocol. + +```typescript +const estimate = await sdk.estimateFee(1, "AXELAR") +// Returns: { fee: bigint, feeInNative: string, protocol: "AXELAR" } +``` + +##### `bridgeTo(target, targetChainId, amount, protocol, msgValue?)` + +Generic bridge method that automatically handles fee estimation and validation. + +```typescript +const receipt = await sdk.bridgeTo( + "0xRecipientAddress", + 1, // Ethereum mainnet + 1000000000000000000n, // 1 G$ + "AXELAR", + feeEstimate.fee // Optional, will be estimated if not provided +) +``` + +##### `bridgeToWithLz(target, targetChainId, amount, adapterParams?, msgValue?)` + +Bridge using LayerZero with custom adapter parameters. + +```typescript +const receipt = await sdk.bridgeToWithLz( + "0xRecipientAddress", + 1, // Ethereum mainnet + 1000000000000000000n, // 1 G$ + "0x000100000000000000000000000000000000000000000000000000000000000000060000", // Custom adapter params + feeEstimate.fee +) +``` + +##### `bridgeToWithAxelar(target, targetChainId, amount, gasRefundAddress?, msgValue?)` + +Bridge using Axelar with optional gas refund address. + +```typescript +const receipt = await sdk.bridgeToWithAxelar( + "0xRecipientAddress", + 1, // Ethereum mainnet + 1000000000000000000n, // 1 G$ + "0xRefundAddress", // Optional gas refund address + feeEstimate.fee +) +``` + +##### `getBridgeRequests(address, options?)` + +Fetches BridgeRequest events for an address. + +```typescript +const requests = await sdk.getBridgeRequests("0xUserAddress", { + fromBlock: 5000000n, + limit: 100 +}) +``` + +##### `getExecutedTransfers(address, options?)` + +Fetches ExecutedTransfer events for an address. + +```typescript +const executed = await sdk.getExecutedTransfers("0xUserAddress", { + fromBlock: 5000000n, + limit: 100 +}) +``` + +##### `getTransactionStatus(txHash, protocol)` + +Gets the status of a bridge transaction. + +```typescript +const status = await sdk.getTransactionStatus( + "0xTransactionHash", + "AXELAR" +) +// Returns: { status: "pending" | "completed" | "failed", srcTxHash?, dstTxHash?, timestamp?, error? } +``` + +##### `getExplorerLink(txHash, protocol)` + +Generates an explorer link for a bridge transaction. + +```typescript +const link = sdk.getExplorerLink("0xTransactionHash", "LAYERZERO") +// Returns: "https://layerzeroscan.com/tx/0xTransactionHash" +``` + +### React Hooks + +#### `useBridgingSDK()` + +Hook for accessing the BridgingSDK instance. + +```tsx +const { sdk, loading, error } = useBridgingSDK() +``` + +#### `useBridgeFee(fromChainId, toChainId, protocol)` + +Hook for getting fee estimates. + +```tsx +const { fee, loading, error } = useBridgeFee(42220, 1, "AXELAR") +``` + +#### `useBridgeTransactionStatus(txHash, protocol)` + +Hook for tracking transaction status. + +```tsx +const { status, loading, error } = useBridgeTransactionStatus("0xHash", "AXELAR") +``` + +### Utility Functions + +#### Decimal Conversion + +```typescript +import { + normalizeAmount, + denormalizeAmount, + formatAmount, + parseAmount +} from "@goodsdks/bridging-sdk" + +// Convert between native and normalized decimals +const normalized = normalizeAmount(amount, fromChainId) +const denormalized = denormalizeAmount(normalized, toChainId) + +// Format for display +const formatted = formatAmount(1000000000000000000n, 18) // "1.0" + +// Parse user input +const parsed = parseAmount("1.5", 18) // 1500000000000000000n +``` + +#### Fee Management + +```typescript +import { + validateFeeCoverage, + validateSufficientBalance, + formatFee +} from "@goodsdks/bridging-sdk" + +// Validate fee coverage +const validation = validateFeeCoverage(msgValue, requiredFee) + +// Validate sufficient balance +const balanceCheck = validateSufficientBalance( + userBalance, + bridgeAmount, + fee +) + +// Format for display +const formatted = formatFee(fee, chainId) +``` + +#### Transaction Tracking + +```typescript +import { + pollTransactionStatus, + formatTimestamp, + getTimeElapsed, + getStatusLabel +} from "@goodsdks/bridging-sdk" + +// Poll until completion +const finalStatus = await pollTransactionStatus( + txHash, + "AXELAR", + (status) => console.log("Status update:", status) +) + +// Format for display +const timestamp = formatTimestamp(status.timestamp) +const elapsed = getTimeElapsed(status.timestamp) +const label = getStatusLabel(status) +``` + +## Supported Chains + +| Chain | Chain ID | Decimals | Native Currency | +|-------|-----------|----------|-----------------| +| Celo | 42220 | 18 | CELO | +| Ethereum | 1 | 2 | ETH | +| Fuse | 122 | 2 | FUSE | +| XDC | 50 | 18 | XDC | + +## Bridge Protocols + +### Axelar +- Secure cross-chain communication +- Gas refunds supported +- Explorer: https://axelarscan.io + +### LayerZero +- Ultra-light node endpoints +- Custom adapter parameters +- Explorer: https://layerzeroscan.com + +## Error Handling + +The SDK provides detailed error messages for common issues: + +```typescript +try { + await sdk.bridgeTo(recipient, targetChain, amount, "AXELAR") +} catch (error) { + if (error.message.includes("Insufficient fee")) { + // Handle insufficient fee + } else if (error.message.includes("limit")) { + // Handle limit exceeded + } else if (error.message.includes("balance")) { + // Handle insufficient balance + } +} +``` + +## Best Practices + +1. **Always estimate fees before bridging** +2. **Validate user balance includes both amount and fees** +3. **Handle decimal conversions properly** +4. **Track transaction status for user feedback** +5. **Provide explorer links for transparency** + +## Demo Application + +See the demo application at `apps/demo-bridging-app` for a complete implementation example. + +## Contributing + +Please read our [Contributing Guidelines](https://github.com/GoodDollar/GoodSDKs/blob/main/CONTRIBUTING.md) for details. + +## License + +This project is licensed under the MIT License. See the [LICENSE](https://github.com/GoodDollar/GoodSDKs/blob/main/LICENSE) file for details. \ No newline at end of file diff --git a/packages/bridging-sdk/package.json b/packages/bridging-sdk/package.json new file mode 100644 index 0000000..4c0ae82 --- /dev/null +++ b/packages/bridging-sdk/package.json @@ -0,0 +1,43 @@ +{ + "name": "@goodsdks/bridging-sdk", + "version": "1.0.5", + "type": "module", + "scripts": { + "build": "tsup --clean", + "dev": "tsc --watch", + "bump": "yarn version patch && yarn build && git add package.json && git commit -m \"version bump\"" + }, + "main": "./dist/index.cjs", + "module": "./dist/index.js", + "types": "./dist/index.d.ts", + "exports": { + "import": { + "types": "./dist/index.d.ts", + "import": "./dist/index.js" + }, + "require": { + "types": "./dist/index.d.cts", + "require": "./dist/index.cjs" + } + }, + "files": [ + "dist", + "src" + ], + "devDependencies": { + "@repo/typescript-config": "workspace:*", + "@types/react": "^18", + "react": "^18", + "typescript": "latest", + "viem": "latest", + "wagmi": "latest" + }, + "peerDependencies": { + "react": "*", + "viem": "*", + "wagmi": "*" + }, + "dependencies": { + "tsup": "^8.3.5" + } +} diff --git a/packages/bridging-sdk/src/abi.ts b/packages/bridging-sdk/src/abi.ts new file mode 100644 index 0000000..347ae90 --- /dev/null +++ b/packages/bridging-sdk/src/abi.ts @@ -0,0 +1,1111 @@ +export const MESSAGE_PASSING_BRIDGE_ABI = [ + { + "inputs": [ + { "internalType": "address", "name": "axlGateway", "type": "address" }, + { "internalType": "address", "name": "axlGasReceiver", "type": "address" }, + { "internalType": "address", "name": "lzEndpoint", "type": "address" }, + { "internalType": "bool", "name": "isTestnet", "type": "bool" } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { "internalType": "uint256", "name": "requestId", "type": "uint256" } + ], + "name": "ALREADY_EXECUTED", + "type": "error" + }, + { "inputs": [], "name": "AlreadyInitialized", "type": "error" }, + { + "inputs": [{ "internalType": "string", "name": "", "type": "string" }], + "name": "BRIDGE_LIMITS", + "type": "error" + }, + { + "inputs": [ + { "internalType": "address", "name": "lzEndpoint", "type": "address" } + ], + "name": "INVALID_ENDPOINT", + "type": "error" + }, + { + "inputs": [ + { "internalType": "bytes", "name": "_srcAddress", "type": "bytes" } + ], + "name": "INVALID_SENDER", + "type": "error" + }, + { + "inputs": [ + { "internalType": "address", "name": "target", "type": "address" }, + { "internalType": "uint256", "name": "chainId", "type": "uint256" } + ], + "name": "INVALID_TARGET_OR_CHAINID", + "type": "error" + }, + { "inputs": [], "name": "InvalidAddress", "type": "error" }, + { "inputs": [], "name": "InvalidAddressString", "type": "error" }, + { + "inputs": [ + { "internalType": "uint256", "name": "required", "type": "uint256" }, + { "internalType": "uint256", "name": "sent", "type": "uint256" } + ], + "name": "LZ_FEE", + "type": "error" + }, + { "inputs": [], "name": "MISSING_FEE", "type": "error" }, + { + "inputs": [ + { "internalType": "address", "name": "sender", "type": "address" } + ], + "name": "NOT_GUARDIAN", + "type": "error" + }, + { "inputs": [], "name": "NotApprovedByGateway", "type": "error" }, + { "inputs": [], "name": "TRANSFER", "type": "error" }, + { "inputs": [], "name": "TRANSFER_FROM", "type": "error" }, + { + "inputs": [ + { "internalType": "uint256", "name": "chainId", "type": "uint256" } + ], + "name": "UNSUPPORTED_CHAIN", + "type": "error" + }, + { + "inputs": [ + { "internalType": "address", "name": "token", "type": "address" } + ], + "name": "WRONG_TOKEN", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "previousAdmin", + "type": "address" + }, + { + "indexed": false, + "internalType": "address", + "name": "newAdmin", + "type": "address" + } + ], + "name": "AdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "beacon", + "type": "address" + } + ], + "name": "BeaconUpgraded", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "targetChainId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "normalizedAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "timestamp", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "enum MessagePassingBridge.BridgeService", + "name": "bridge", + "type": "uint8" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "BridgeRequest", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "normalizedAmount", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "fee", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "sourceChainId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "enum MessagePassingBridge.BridgeService", + "name": "bridge", + "type": "uint8" + }, + { + "indexed": true, + "internalType": "uint256", + "name": "id", + "type": "uint256" + } + ], + "name": "ExecutedTransfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "sourceChainId", + "type": "uint256" + }, + { + "indexed": false, + "internalType": "address", + "name": "sourceAddress", + "type": "address" + } + ], + "name": "FalseSender", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint8", + "name": "version", + "type": "uint8" + } + ], + "name": "Initialized", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint16", + "name": "_srcChainId", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "_srcAddress", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "_nonce", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "_payload", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "_reason", + "type": "bytes" + } + ], + "name": "MessageFailed", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint16", + "name": "_srcChainId", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "_srcAddress", + "type": "bytes" + }, + { + "indexed": false, + "internalType": "uint64", + "name": "_nonce", + "type": "uint64" + }, + { + "indexed": false, + "internalType": "bytes32", + "name": "_payloadHash", + "type": "bytes32" + } + ], + "name": "RetryMessageSuccess", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint16", + "name": "_dstChainId", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint16", + "name": "_type", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "uint256", + "name": "_minDstGas", + "type": "uint256" + } + ], + "name": "SetMinDstGas", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "precrime", + "type": "address" + } + ], + "name": "SetPrecrime", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint16", + "name": "_remoteChainId", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "_path", + "type": "bytes" + } + ], + "name": "SetTrustedRemote", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint16", + "name": "_remoteChainId", + "type": "uint16" + }, + { + "indexed": false, + "internalType": "bytes", + "name": "_remoteAddress", + "type": "bytes" + } + ], + "name": "SetTrustedRemoteAddress", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "implementation", + "type": "address" + } + ], + "name": "Upgraded", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_PAYLOAD_SIZE_LIMIT", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "TESTNET", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "address", "name": "", "type": "address" }], + "name": "accountsDailyLimit", + "outputs": [ + { "internalType": "uint256", "name": "lastTransferReset", "type": "uint256" }, + { "internalType": "uint256", "name": "bridged24Hours", "type": "uint256" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "avatar", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "bridgeDailyLimit", + "outputs": [ + { "internalType": "uint256", "name": "lastTransferReset", "type": "uint256" }, + { "internalType": "uint256", "name": "bridged24Hours", "type": "uint256" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "bridgeFees", + "outputs": [ + { "internalType": "uint256", "name": "minFee", "type": "uint256" }, + { "internalType": "uint256", "name": "maxFee", "type": "uint256" }, + { "internalType": "uint256", "name": "fee", "type": "uint256" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "bridgeLimits", + "outputs": [ + { "internalType": "uint256", "name": "dailyLimit", "type": "uint256" }, + { "internalType": "uint256", "name": "txLimit", "type": "uint256" }, + { "internalType": "uint256", "name": "accountDailyLimit", "type": "uint256" }, + { "internalType": "uint256", "name": "minAmount", "type": "uint256" }, + { "internalType": "bool", "name": "onlyWhitelisted", "type": "bool" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "target", "type": "address" }, + { "internalType": "uint256", "name": "targetChainId", "type": "uint256" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" }, + { + "internalType": "enum MessagePassingBridge.BridgeService", + "name": "bridge", + "type": "uint8" + } + ], + "name": "bridgeTo", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "target", "type": "address" }, + { "internalType": "uint256", "name": "targetChainId", "type": "uint256" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" } + ], + "name": "bridgeToWithAxelar", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "target", "type": "address" }, + { "internalType": "uint256", "name": "targetChainId", "type": "uint256" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" } + ], + "name": "bridgeToWithLz", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "target", "type": "address" }, + { "internalType": "uint256", "name": "targetChainId", "type": "uint256" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" }, + { "internalType": "bytes", "name": "adapterParams", "type": "bytes" } + ], + "name": "bridgeToWithLzAdapterParams", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "from", "type": "address" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" } + ], + "name": "canBridge", + "outputs": [ + { "internalType": "bool", "name": "isWithinLimit", "type": "bool" }, + { "internalType": "string", "name": "error", "type": "string" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "currentId", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "dao", + "outputs": [ + { "internalType": "contract Controller", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "name": "disabledSourceBridges", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint16", "name": "_dstChainId", "type": "uint16" }, + { "internalType": "address", "name": "_fromAddress", "type": "address" }, + { "internalType": "address", "name": "_toAddress", "type": "address" }, + { "internalType": "uint256", "name": "_normalizedAmount", "type": "uint256" }, + { "internalType": "bool", "name": "_useZro", "type": "bool" }, + { "internalType": "bytes", "name": "_adapterParams", "type": "bytes" } + ], + "name": "estimateSendFee", + "outputs": [ + { "internalType": "uint256", "name": "nativeFee", "type": "uint256" }, + { "internalType": "uint256", "name": "zroFee", "type": "uint256" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "commandId", "type": "bytes32" }, + { "internalType": "string", "name": "sourceChain", "type": "string" }, + { "internalType": "string", "name": "sourceAddress", "type": "string" }, + { "internalType": "bytes", "name": "payload", "type": "bytes" } + ], + "name": "execute", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32", "name": "commandId", "type": "bytes32" }, + { "internalType": "string", "name": "sourceChain", "type": "string" }, + { "internalType": "string", "name": "sourceAddress", "type": "string" }, + { "internalType": "bytes", "name": "payload", "type": "bytes" }, + { "internalType": "string", "name": "tokenSymbol", "type": "string" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" } + ], + "name": "executeWithToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "name": "executedRequests", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint16", "name": "", "type": "uint16" }, + { "internalType": "bytes", "name": "", "type": "bytes" }, + { "internalType": "uint64", "name": "", "type": "uint64" } + ], + "name": "failedMessages", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "faucet", + "outputs": [ + { "internalType": "contract IFaucet", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint16", "name": "_srcChainId", "type": "uint16" }, + { "internalType": "bytes", "name": "_srcAddress", "type": "bytes" } + ], + "name": "forceResumeReceive", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "gasService", + "outputs": [ + { "internalType": "contract IAxelarGasService", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "gateway", + "outputs": [ + { "internalType": "contract IAxelarGateway", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint16", "name": "_version", "type": "uint16" }, + { "internalType": "uint16", "name": "_chainId", "type": "uint16" }, + { "internalType": "address", "name": "", "type": "address" }, + { "internalType": "uint256", "name": "_configType", "type": "uint256" } + ], + "name": "getConfig", + "outputs": [{ "internalType": "bytes", "name": "", "type": "bytes" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint16", "name": "_remoteChainId", "type": "uint16" } + ], + "name": "getTrustedRemoteAddress", + "outputs": [{ "internalType": "bytes", "name": "", "type": "bytes" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "guardian", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract INameService", + "name": "nameService", + "type": "address" + }, + { + "components": [ + { "internalType": "uint256", "name": "dailyLimit", "type": "uint256" }, + { "internalType": "uint256", "name": "txLimit", "type": "uint256" }, + { + "internalType": "uint256", + "name": "accountDailyLimit", + "type": "uint256" + }, + { "internalType": "uint256", "name": "minAmount", "type": "uint256" }, + { "internalType": "bool", "name": "onlyWhitelisted", "type": "bool" } + ], + "internalType": "struct MessagePassingBridge.BridgeLimits", + "name": "limits", + "type": "tuple" + }, + { + "components": [ + { "internalType": "uint256", "name": "minFee", "type": "uint256" }, + { "internalType": "uint256", "name": "maxFee", "type": "uint256" }, + { "internalType": "uint256", "name": "fee", "type": "uint256" } + ], + "internalType": "struct MessagePassingBridge.BridgeFees", + "name": "fees", + "type": "tuple" + } + ], + "name": "initialize", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "isClosed", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint16", "name": "_srcChainId", "type": "uint16" }, + { "internalType": "bytes", "name": "_srcAddress", "type": "bytes" } + ], + "name": "isTrustedRemote", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "name": "lzChainIdsMapping", + "outputs": [{ "internalType": "uint16", "name": "", "type": "uint16" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lzEndpoint", + "outputs": [ + { + "internalType": "contract ILayerZeroEndpointUpgradeable", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "lzEndpoint_", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint16", "name": "_srcChainId", "type": "uint16" }, + { "internalType": "bytes", "name": "_srcAddress", "type": "bytes" }, + { "internalType": "uint64", "name": "_nonce", "type": "uint64" }, + { "internalType": "bytes", "name": "_payload", "type": "bytes" } + ], + "name": "lzReceive", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint16", "name": "", "type": "uint16" }, + { "internalType": "uint16", "name": "", "type": "uint16" } + ], + "name": "minDstGasLookup", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "nameService", + "outputs": [ + { "internalType": "contract INameService", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "nativeToken", + "outputs": [ + { "internalType": "contract IGoodDollar", "name": "", "type": "address" } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint16", "name": "_srcChainId", "type": "uint16" }, + { "internalType": "bytes", "name": "_srcAddress", "type": "bytes" }, + { "internalType": "uint64", "name": "_nonce", "type": "uint64" }, + { "internalType": "bytes", "name": "_payload", "type": "bytes" } + ], + "name": "nonblockingLzReceive", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "from", "type": "address" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" }, + { "internalType": "bytes", "name": "data", "type": "bytes" } + ], + "name": "onTokenTransfer", + "outputs": [{ "internalType": "bool", "name": "", "type": "bool" }], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [{ "internalType": "bool", "name": "isPaused", "type": "bool" }], + "name": "pauseBridge", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "uint16", "name": "", "type": "uint16" }], + "name": "payloadSizeLimitLookup", + "outputs": [{ "internalType": "uint256", "name": "", "type": "uint256" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "precrime", + "outputs": [{ "internalType": "address", "name": "", "type": "address" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "proxiableUUID", + "outputs": [{ "internalType": "bytes32", "name": "", "type": "bytes32" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint16", "name": "_srcChainId", "type": "uint16" }, + { "internalType": "bytes", "name": "_srcAddress", "type": "bytes" }, + { "internalType": "uint64", "name": "_nonce", "type": "uint64" }, + { "internalType": "bytes", "name": "_payload", "type": "bytes" } + ], + "name": "retryMessage", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { "internalType": "uint256", "name": "minFee", "type": "uint256" }, + { "internalType": "uint256", "name": "maxFee", "type": "uint256" }, + { "internalType": "uint256", "name": "fee", "type": "uint256" } + ], + "internalType": "struct MessagePassingBridge.BridgeFees", + "name": "fees", + "type": "tuple" + } + ], + "name": "setBridgeFees", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "components": [ + { "internalType": "uint256", "name": "dailyLimit", "type": "uint256" }, + { "internalType": "uint256", "name": "txLimit", "type": "uint256" }, + { + "internalType": "uint256", + "name": "accountDailyLimit", + "type": "uint256" + }, + { "internalType": "uint256", "name": "minAmount", "type": "uint256" }, + { "internalType": "bool", "name": "onlyWhitelisted", "type": "bool" } + ], + "internalType": "struct MessagePassingBridge.BridgeLimits", + "name": "limits", + "type": "tuple" + } + ], + "name": "setBridgeLimits", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint16", "name": "_version", "type": "uint16" }, + { "internalType": "uint16", "name": "_chainId", "type": "uint16" }, + { "internalType": "uint256", "name": "_configType", "type": "uint256" }, + { "internalType": "bytes", "name": "_config", "type": "bytes" } + ], + "name": "setConfig", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "bytes32[]", "name": "bridgeKeys", "type": "bytes32[]" }, + { "internalType": "bool[]", "name": "disabled", "type": "bool[]" } + ], + "name": "setDisabledBridges", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IFaucet", + "name": "_faucet", + "type": "address" + } + ], + "name": "setFaucet", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_guardian", "type": "address" } + ], + "name": "setGuardian", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint16", "name": "_dstChainId", "type": "uint16" }, + { "internalType": "uint16", "name": "_packetType", "type": "uint16" }, + { "internalType": "uint256", "name": "_minGas", "type": "uint256" } + ], + "name": "setMinDstGas", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint16", "name": "_dstChainId", "type": "uint16" }, + { "internalType": "uint256", "name": "_size", "type": "uint256" } + ], + "name": "setPayloadSizeLimit", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "_precrime", "type": "address" } + ], + "name": "setPrecrime", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "uint16", "name": "_version", "type": "uint16" }], + "name": "setReceiveVersion", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "uint16", "name": "_version", "type": "uint16" }], + "name": "setSendVersion", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "uint16", "name": "_srcChainId", "type": "uint16" }, + { "internalType": "bytes", "name": "_path", "type": "bytes" } + ], + "name": "setTrustedRemote", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint16", + "name": "_remoteChainId", + "type": "uint16" + }, + { "internalType": "bytes", "name": "_remoteAddress", "type": "bytes" } + ], + "name": "setTrustedRemoteAddress", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "newOwner", "type": "address" } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [{ "internalType": "uint16", "name": "", "type": "uint16" }], + "name": "trustedRemoteLookup", + "outputs": [{ "internalType": "bytes", "name": "", "type": "bytes" }], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "updateAvatar", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + } + ], + "name": "upgradeTo", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newImplementation", + "type": "address" + }, + { "internalType": "bytes", "name": "data", "type": "bytes" } + ], + "name": "upgradeToAndCall", + "outputs": [], + "stateMutability": "payable", + "type": "function" + }, + { + "inputs": [ + { "internalType": "address", "name": "token", "type": "address" }, + { "internalType": "uint256", "name": "amount", "type": "uint256" } + ], + "name": "withdraw", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + } +] as const diff --git a/packages/bridging-sdk/src/constants.ts b/packages/bridging-sdk/src/constants.ts new file mode 100644 index 0000000..c988a5a --- /dev/null +++ b/packages/bridging-sdk/src/constants.ts @@ -0,0 +1,100 @@ +import type { BridgeChain, BridgeProtocol } from "./types" + +// Public on-chain GoodDollar (G$) token contract addresses — not secrets +export const SUPPORTED_CHAINS: Record