# 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=<wallet-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**
