区块链钱包开发(十五)—— 构建交易控制器(TransactionController)

前言

Metamask中控制器众多(50个左右),我们不可能一一介绍,从本章开始我们会选择性的讲解几个最核心的控制器实现,这一章我们讲交易控制器TransactionController,也是最核心的控制器。

源码:github.com/MetaMask/co...

1. 交易控制器概述

TransactionController是MetaMask的核心控制器,负责管理所有交易相关的操作,包括:

  • 交易的创建、签名、发布
  • 交易状态的跟踪和更新
  • 交易历史的维护
  • 多链交易的支持
  • 交易模拟和安全检查

2. 核心架构组件

2.1 主要组件

  • TransactionController: 主控制器,协调所有交易操作
  • PendingTransactionTracker: 跟踪待处理交易状态
  • MultichainTrackingHelper: 多链交易跟踪助手
  • TransactionPoller: 交易轮询器
  • IncomingTransactionHelper: 入账交易助手

2.2 状态管理

typescript 复制代码
interface TransactionControllerState {
  transactions: TransactionMeta[];           // 所有交易列表
  transactionBatches: TransactionBatchMeta[]; // 批量交易
  methodData: Record<string, MethodData>;    // 方法数据缓存
  lastFetchedBlockNumbers: { [key: string]: number | string }; // 最后获取的区块号
  submitHistory: SubmitHistoryEntry[];       // 提交历史
}

3. 交易流程详解

当用户发起转账交易,会调用交易的入口函数addTransaction

js 复制代码
// 伪代码

async addTransaction(txParams: TransactionParams, options) {
  // ===== 第一阶段:交易创建 =====
  
  // 1. 创建交易元数据
  const transactionMeta = {
    actionId: options.actionId, // 操作唯一标识,防止重复请求,确保幂等性
    status: TransactionStatus.unapproved,
    txParams: txParams,
    chainId: options.networkClientId,
    networkClientId: options.networkClientId,
    origin: options.origin,
    time: Date.now(),
  };

  // 2. 添加到状态
  this.update((state) => {
    state.transactions.push(transactionMeta);
  });

  // 3. 发布未批准交易事件
  this.messagingSystem.publish('unapprovedTransactionAdded', transactionMeta);

  // ===== 第二阶段:模拟交易 =====
  
  // 4. 执行交易模拟,调用模拟API,获取余额变化、gas费用等信息
  await this.#updateSimulationData(transactionMeta);
  

  // ===== 第三阶段:用户批准 =====
  
  // 5. 等待用户批准
  if (options.requireApproval !== false) {
    await this.#requestApproval(transactionMeta);
  }

  // ===== 第四阶段:交易发布 =====
  
  // 6. 签名交易
  const signedTx = await this.#signTransaction(transactionMeta);
  
  // 7. 发布到区块链
  const hash = await this.#publishTransaction(signedTx);
  
  // 8. 更新状态为已提交
  this.#updateTransaction(transactionMeta.id, {
    status: TransactionStatus.submitted,
    hash: hash,
    submittedTime: Date.now()
  });

  // ===== 第五阶段:交易跟踪 =====
  
  // 9. 创建待处理交易跟踪器
  const pendingTracker = new PendingTransactionTracker({
    provider: this.#getProvider(),
    transactionMeta: transactionMeta,
    onTransactionConfirmed: (txMeta) => {
      // 伪代码:交易确认回调
      this.#updateTransaction(txMeta.id, {
        status: TransactionStatus.confirmed,
        txReceipt: txMeta.txReceipt
      });
      this.messagingSystem.publish('transactionConfirmed', txMeta);
    }
  });

  // 10. 开始跟踪交易状态
  pendingTracker.startTracking();

  return {
    result: Promise.resolve(hash),
    transactionMeta: transactionMeta
  };
}

4. 关键概念解析

4.1 交易状态流转

typescript 复制代码
enum TransactionStatus {
  unapproved = 'unapproved',    // 未批准
  approved = 'approved',        // 已批准
  signed = 'signed',           // 已签名
  submitted = 'submitted',     // 已提交
  confirmed = 'confirmed',     // 已确认
  failed = 'failed',           // 失败
  dropped = 'dropped',         // 已丢弃
  rejected = 'rejected'        // 已拒绝
}

4.2 交易模拟机制

MetaMask使用专用的模拟API进行交易模拟:

typescript 复制代码
// 模拟API调用
const simulationResult = await fetch('https://tx-sentinel-{0}.api.cx.metamask.io/', {
  method: 'POST',
  body: JSON.stringify({
    method: 'infura_simulateTransactions',
    params: [txParams]
  })
});

相比标准的eth_calleth_estimateGas,MetaMask的模拟API提供:

  • 更详细的余额变化信息
  • 安全风险检测
  • 更丰富的交易分析数据

5. 多链支持架构

5.1 MultichainTrackingHelper

负责管理多链交易的跟踪:

typescript 复制代码
class MultichainTrackingHelper {
  #trackingMap: Map<NetworkClientId, {
    nonceTracker: NonceTracker;
    pendingTransactionTracker: PendingTransactionTracker;
  }> = new Map();
  
  // 为每个网络客户端创建独立的跟踪器
  #startTrackingByNetworkClientId(networkClientId: NetworkClientId) {
    const trackers = this.#trackingMap.get(networkClientId);
    if (trackers) {
      return;
    }
    
    // 创建该链的跟踪器
    const pendingTransactionTracker = this.#createPendingTransactionTracker({
      provider,
      blockTracker,
      chainId,
      networkClientId,
    });
    
    this.#trackingMap.set(networkClientId, {
      nonceTracker,
      pendingTransactionTracker,
    });
  }
}

5.2 网络状态监听

typescript 复制代码
// 监听网络状态变化,自动管理跟踪器
this.messagingSystem.subscribe('NetworkController:stateChange', () => {
  this.#refreshTrackingMap(networkClients);
});

6. 交易跟踪机制

6.1 PendingTransactionTracker

负责跟踪待处理交易的状态变化:

typescript 复制代码
class PendingTransactionTracker {
  // 启动跟踪
  startIfPendingTransactions = () => {
    const pendingTransactions = this.#getPendingTransactions();
    if (pendingTransactions.length) {
      this.#start(pendingTransactions);
    } else {
      this.stop();
    }
  };
  
  // 轮询检查交易状态
  async #checkTransactions() {
    const pendingTransactions = this.#getPendingTransactions();
    for (const txMeta of pendingTransactions) {
      await this.#checkTransaction(txMeta);
    }
  }
}

6.2 事件驱动架构

typescript 复制代码
// 监听交易状态变化事件
pendingTransactionTracker.hub.on('transaction-confirmed', (txMeta) => {
  this.#onConfirmedTransaction(txMeta);
});

pendingTransactionTracker.hub.on('transaction-failed', (txMeta, error) => {
  this.#failTransaction(txMeta, error);
});

7. 安全机制

  • 交易参数验证
  • Gas费用合理性检查
  • 合约交互风险检测(通过PPOM)
  • 钓鱼网站防护(通过电鱼网站控制器)

8. 高级功能

8.1 交易加速和取消

typescript 复制代码
// 交易加速
async speedUpTransaction(transactionId: string, gasValues) {
  return this.#retryTransaction({
    transactionId,
    gasValues,
    label: 'speedup',
    rate: SPEEDUP_RATE,
    transactionType: TransactionType.retry,
  });
}

// 交易取消
async stopTransaction(transactionId: string, gasValues) {
  return this.#retryTransaction({
    transactionId,
    gasValues,
    label: 'cancel',
    rate: CANCEL_RATE,
    transactionType: TransactionType.cancel,
    prepareTransactionParams: (txParams) => {
      delete txParams.data;
      txParams.to = txParams.from;
      txParams.value = '0x0';
    },
  });
}

8.2 批量交易支持

typescript 复制代码
// 批量交易处理
async addTransactionBatch(request: TransactionBatchRequest) {
  const { transactions, options } = request;
  const batchId = generateBatchId();
  
  const batchMeta = {
    id: batchId,
    transactions: [],
    status: TransactionStatus.unapproved,
  };
  
  // 处理批量交易
  for (const txParams of transactions) {
    const result = await this.addTransaction(txParams, {
      ...options,
      batchId,
    });
    batchMeta.transactions.push(result.transactionMeta);
  }
  
  return { batchId, transactions: batchMeta.transactions };
}

9. 性能优化

9.1 交易历史管理

typescript 复制代码
// 限制交易历史数量
const transactionHistoryLimit = 1000;
if (state.transactions.length > transactionHistoryLimit) {
  state.transactions = state.transactions.slice(-transactionHistoryLimit);
}

9.2 缓存机制

  • 方法数据缓存
  • 区块号缓存
  • Gas费用缓存

10. 总结

TransactionController是MetaMask的核心组件,通过模块化设计实现了:

  • 多链支持: 通过MultichainTrackingHelper管理多链交易
  • 状态管理: 完整的状态流转和事件通知机制
  • 安全防护: 多层次的安全检查和风险防护
  • 性能优化: 智能缓存和历史管理
  • 扩展性: 钩子机制支持自定义逻辑

这个架构设计使得MetaMask能够安全、高效地处理各种复杂的交易场景,为用户提供可靠的区块链交互体验。

sequenceDiagram participant UI as 用户界面 participant TC as TransactionController participant PTT as PendingTransactionTracker participant BC as 区块链 UI->>TC: addTransaction TC->>TC: 创建交易元数据 TC->>UI: unapprovedTransactionAdded UI->>TC: 用户批准 TC->>TC: #processApproval TC->>BC: 发布交易 TC->>UI: transactionSubmitted PTT->>BC: 轮询交易收据 BC->>PTT: 返回收据 PTT->>TC: transaction-confirmed TC->>TC: #onConfirmedTransaction TC->>UI: transactionConfirmed TC->>UI: transactionStatusUpdated

学习交流请添加vx: gh313061

下期预告: 构建网络控制器(NetworkController)

相关推荐
YSGZJJ2 小时前
股指期货合约是个啥?怎么玩?
区块链
数据与人工智能律师2 小时前
刑法视野下的虚拟财产属性争议:法律风险与市场潜力解析
大数据·网络·人工智能·云计算·区块链
追梦人物2 小时前
Uniswap 手续费和协议费机制剖析
前端·后端·区块链
余_弦6 小时前
区块链钱包开发(十六)—— 构建网络控制器(NetworkController)
区块链·以太坊
一眼万年0413 小时前
Ethereum: 专为区块链定制了一个完善的数据存储系统
区块链·以太坊
Sui_Network2 天前
Walrus 与 Pipe Network 集成,提升多链带宽并降低延迟
人工智能·web3·区块链·智能合约·量子计算
idaretobe2 天前
宝龙地产债务化解解决方案二:基于资产代币化与轻资产转型的战略重构
人工智能·web3·去中心化·区块链·智能合约·信任链
小明的小名叫小明3 天前
区块链技术原理(1) -密码学
区块链·密码学·哈希算法
元宇宙时间3 天前
引领GameFi 2.0新范式:D.Plan携手顶级财经媒体启动“龙珠创意秀”
人工智能·web3·区块链