/** * @file bridge-handler.ts * @notice Bridge handler for EVM to XRPL transfers */ import { ethers } from 'ethers'; import { XRPLConnector, XRPLTransferRequest } from './xrpl-connector'; import { WorkflowEngine, TransferStatus } from '../../orchestration/bridge/workflow-engine'; export interface BridgeHandlerConfig { xrplConfig: { server: string; account: string; secret: string; }; evmProvider: ethers.Provider; escrowVaultAddress: string; escrowVaultAbi: any[]; workflowEngine: WorkflowEngine; } export class XRPLBridgeHandler { private xrplConnector: XRPLConnector; private provider: ethers.Provider; private escrowVault: ethers.Contract; private workflowEngine: WorkflowEngine; constructor(config: BridgeHandlerConfig) { this.xrplConnector = new XRPLConnector(config.xrplConfig); this.provider = config.evmProvider; this.escrowVault = new ethers.Contract( config.escrowVaultAddress, config.escrowVaultAbi, config.evmProvider ); this.workflowEngine = config.workflowEngine; } /** * Handle bridge transfer from EVM to XRPL */ async handleTransfer( transferId: string, destinationAddress: string, amount: string, destinationTag?: number ): Promise<{ txHash: string; ledgerIndex: number }> { // Get transfer from escrow vault const transfer = await this.escrowVault.getTransfer(transferId); // Verify transfer status const status = this.workflowEngine.getStatus(transferId); if (status !== TransferStatus.ROUTE_SELECTED) { throw new Error(`Invalid transfer status: ${status}`); } // Convert amount to XRP drops (assuming 1:1 ratio, adjust as needed) // For native ETH, convert wei to XRP drops // For ERC-20, use token decimals const xrpAmount = this.convertToXRP(transfer.asset, transfer.amount.toString()); // Prepare XRPL payment const xrplRequest: XRPLTransferRequest = { destination: destinationAddress, amount: XRPLConnector.xrpToDrops(xrpAmount), destinationTag, memo: `Bridge transfer ${transferId}` }; // Execute XRPL payment const result = await this.xrplConnector.sendPayment(xrplRequest); // Update workflow status await this.workflowEngine.markDestinationSent(transferId, { xrplTxHash: result.txHash }); // Wait for finality await this.xrplConnector.waitForFinality(result.ledgerIndex); // Confirm finality await this.workflowEngine.confirmFinality(transferId); await this.workflowEngine.completeTransfer(transferId); return { txHash: result.txHash, ledgerIndex: result.ledgerIndex }; } /** * Convert EVM amount to XRP * This is a simplified conversion - in production, use price oracles */ private convertToXRP(asset: string, amount: string): string { // For native ETH (address(0)), convert wei to XRP // This is a placeholder - use actual price oracle in production if (asset === ethers.ZeroAddress) { // 1 ETH = 1 XRP (placeholder - use oracle) const ethAmount = ethers.formatEther(amount); return ethAmount; } // For ERC-20 tokens, use token decimals and conversion rate // This is a placeholder - implement proper conversion return ethers.formatEther(amount); } /** * Handle refund (if transfer fails) */ async handleRefund(transferId: string): Promise { // Refund logic would be handled by the escrow vault // This is just a placeholder for XRPL-specific refund handling await this.workflowEngine.initiateRefund(transferId); } /** * Get XRPL account balance */ async getBalance(): Promise { const balance = await this.xrplConnector.getBalance(); return XRPLConnector.dropsToXrp(balance); } /** * Verify XRPL transaction */ async verifyTransaction(txHash: string): Promise { const status = await this.xrplConnector.getTransactionStatus(txHash); return status.validated && status.result === 'tesSUCCESS'; } }