# Task 3: Off-Chain Transaction Mirroring Service - Implementation Guide **Date**: 2025-01-18 **Status**: ⏳ TEMPLATE CREATED **Priority**: πŸ”΄ CRITICAL ## Overview Off-chain service to monitor ChainID 138 transactions and mirror them to TransactionMirror contract on Ethereum Mainnet. ## Architecture ``` β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ ChainID 138 RPC β”‚ β”‚ (Blockchain) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ Monitor transactions β”‚ Extract transaction data β”‚ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ Transaction Mirroring β”‚ β”‚ Service β”‚ β”‚ (Off-chain Service) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ β”‚ β”‚ Batch transactions β”‚ Submit to Mainnet β”‚ β–Ό β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β” β”‚ TransactionMirrorβ”‚ β”‚ (Mainnet) β”‚ β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜ ``` ## Service Requirements ### 1. ChainID 138 Transaction Monitoring - Monitor new transactions on ChainID 138 - Extract transaction data: - Transaction hash - From address - To address - Value transferred - Block number - Block timestamp - Gas used - Success status - Transaction data (if any) ### 2. Transaction Batching - Collect transactions into batches - Respect `MAX_BATCH_SIZE = 100` limit - Batch transactions by block or time window - Prepare batch data for submission ### 3. TransactionMirror Interaction - Submit `mirrorTransaction()` for single transactions - Submit `mirrorTransactionsBatch()` for batches - Handle batch size limits - Monitor transaction success/failure - Retry on failure with exponential backoff ### 4. Replay Protection - Track which transactions have been mirrored - Check if transaction already mirrored - Skip already-mirrored transactions ### 5. Monitoring and Logging - Log all transaction mirroring - Monitor submission success rate - Alert on failures - Track mirroring frequency ## Contract Interface ### TransactionMirror Contract **Address**: `0x4CF42c4F1dBa748601b8938be3E7ABD732E87cE9` **Function 1**: `mirrorTransaction(...)` ```solidity function mirrorTransaction( bytes32 txHash, address from, address to, uint256 value, uint256 blockNumber, uint256 blockTimestamp, uint256 gasUsed, bool success, bytes memory data ) external whenNotPaused ``` **Function 2**: `mirrorTransactionsBatch(...)` ```solidity function mirrorTransactionsBatch( MirroredTransaction[] memory transactions ) external whenNotPaused ``` **Maximum Batch Size**: 100 transactions ## Implementation Template ### Node.js/TypeScript Implementation ```typescript import { ethers } from 'ethers'; import { TransactionMirror__factory } from './contracts'; interface MirroredTransaction { txHash: string; from: string; to: string; value: bigint; blockNumber: number; blockTimestamp: number; gasUsed: bigint; success: boolean; data: string; } class TransactionMirroringService { private chain138Provider: ethers.Provider; private mainnetProvider: ethers.Provider; private mainnetWallet: ethers.Wallet; private mirrorContract: TransactionMirror; private transactionQueue: MirroredTransaction[] = []; private readonly MAX_BATCH_SIZE = 100; constructor( chain138Rpc: string, mainnetRpc: string, privateKey: string ) { this.chain138Provider = new ethers.JsonRpcProvider(chain138Rpc); this.mainnetProvider = new ethers.JsonRpcProvider(mainnetRpc); this.mainnetWallet = new ethers.Wallet(privateKey, this.mainnetProvider); this.mirrorContract = TransactionMirror__factory.connect( '0x4CF42c4F1dBa748601b8938be3E7ABD732E87cE9', this.mainnetWallet ); } async monitorTransactions() { // Monitor new blocks this.chain138Provider.on('block', async (blockNumber) => { await this.processBlockTransactions(blockNumber); }); } async processBlockTransactions(blockNumber: number) { const block = await this.chain138Provider.getBlock(blockNumber, true); if (!block.transactions || block.transactions.length === 0) { return; } for (const txHash of block.transactions) { await this.processTransaction(txHash.toString(), blockNumber, block.timestamp || 0n); } } async processTransaction(txHash: string, blockNumber: number, blockTimestamp: bigint) { // 1. Get transaction details const tx = await this.chain138Provider.getTransaction(txHash); const receipt = await this.chain138Provider.getTransactionReceipt(txHash); if (!tx || !receipt) { return; } // 2. Check if already mirrored (optional - can track in database) // const alreadyMirrored = await this.checkMirrored(txHash); // if (alreadyMirrored) return; // 3. Create mirrored transaction object const mirroredTx: MirroredTransaction = { txHash: txHash, from: tx.from, to: tx.to || '0x0000000000000000000000000000000000000000', value: tx.value, blockNumber: blockNumber, blockTimestamp: Number(blockTimestamp), gasUsed: receipt.gasUsed, success: receipt.status === 1, data: tx.data }; // 4. Add to queue this.transactionQueue.push(mirroredTx); // 5. Submit batch if queue is full if (this.transactionQueue.length >= this.MAX_BATCH_SIZE) { await this.submitBatch(); } } async submitBatch() { if (this.transactionQueue.length === 0) { return; } // Take up to MAX_BATCH_SIZE transactions const batch = this.transactionQueue.splice(0, this.MAX_BATCH_SIZE); try { const tx = await this.mirrorContract.mirrorTransactionsBatch(batch); await tx.wait(); console.log(`Mirrored ${batch.length} transactions`); } catch (error) { console.error(`Failed to mirror batch: ${error}`); // Put transactions back in queue for retry this.transactionQueue.unshift(...batch); // Implement retry logic with exponential backoff } } // Periodic batch submission (if queue not full) async startPeriodicSubmission(intervalMs: number = 60000) { setInterval(async () => { if (this.transactionQueue.length > 0) { await this.submitBatch(); } }, intervalMs); } } ``` ## Deployment Steps 1. **Set up service environment**: ```bash npm install ethers@^6.0.0 npm install dotenv ``` 2. **Configure environment variables**: ```bash CHAIN138_RPC_URL=https://rpc-http-pub.d-bis.org MAINNET_RPC_URL=https://eth.llamarpc.com PRIVATE_KEY= MIRROR_ADDRESS=0x4CF42c4F1dBa748601b8938be3E7ABD732E87cE9 BATCH_INTERVAL_MS=60000 ``` 3. **Implement replay protection** (optional - can use database) 4. **Test service locally**: - Test transaction monitoring - Test batch creation - Test Mainnet submission 5. **Deploy service**: - Deploy to server/container - Set up monitoring - Configure alerts ## Alternative: Single Transaction Mirroring If batch processing is not needed, use `mirrorTransaction()` for individual transactions: ```typescript async mirrorSingleTransaction(tx: MirroredTransaction) { try { const txResponse = await this.mirrorContract.mirrorTransaction( tx.txHash, tx.from, tx.to, tx.value, tx.blockNumber, tx.blockTimestamp, tx.gasUsed, tx.success, tx.data ); await txResponse.wait(); console.log(`Mirrored transaction: ${tx.txHash}`); } catch (error) { console.error(`Failed to mirror transaction: ${error}`); } } ``` ## Next Steps 1. **Set up ChainID 138 transaction monitoring** 2. **Implement transaction data extraction** 3. **Implement batching logic** 4. **Set up service infrastructure** 5. **Test with testnet/mainnet** 6. **Deploy and monitor** --- **Status**: ⏳ **TEMPLATE CREATED - AWAITING IMPLEMENTATION**