Skip to content

浏览器插件钱包技术实现

本文档介绍浏览器插件钱包的技术架构,包括多链账户体系、Keyring 密钥管理、DApp Provider 注入、交易签名全链路等核心实现。


一、架构总览

1.1 三大运行环境

浏览器插件钱包运行在三个独立环境中,各司其职:

浏览器插件架构

状态更新 sendUpdate

backgroundConnect API 调用

JSON-RPC Stream

响应结果

Background 环境
后台常驻服务

UI 环境
用户界面渲染

Inpage 环境
DApp 页面注入

环境职责关键能力
Background私钥存储、签名执行、网络请求、钓鱼拦截插件 Storage、后台常驻运行时
UI页面渲染、用户交互浏览器 Webview
Inpage (DApp)向 DApp 页面注入 Provider 对象插件代码注入能力

1.2 全链路架构

从区块链节点到用户界面的完整链路:

客户端层

服务层

数据层

区块链层

全节点
自建/第三方

签名 SDK
多链签名管理

链上解析
轻量解析/合约解析

数仓服务
UTXO/Gas/广播/NFT

后端服务
交易记录/资产查询

浏览器插件
UI + Background

各层职责

层级模块说明
区块链节点全节点自建节点确保数据未被篡改
签名 SDK各链私钥生成、地址生成、交易签名
数据解析轻量解析快速解析关键链上数据(交易、事件)
合约解析DeFi 智能合约项目解析
数仓UTXOBTC NFT 的 UTXO 信息和 pending 交易
Gas从解析层和 mempool 获取 Gas 等级
广播记录交易广播结果

二、账户体系

2.1 多链钱包 SDK 注册

每条链的账户创建、公钥生成、地址生成、签名操作均由独立的 SDK 完成:

registerWallet()

BtcWallet

EthWallet

SolanaWallet

TronWallet

AptosWallet

...更多链

注册模式统一为 (currency, WalletInstance) 映射:

javascript
// 钱包 SDK 配置
const wallets = [
  { currency: Currency.BTC, wallet: BtcWallet },
  { currency: Currency.ETH, wallet: EthWallet },
  { currency: Currency.SOL, wallet: SolanaWallet },
  // ...
];

// 统一注册
const registerWallet = (wallets, register) => {
  wallets.forEach(({ currency, wallet: Wallet, hook }) => {
    hook && hook();
    register(currency, new Wallet());
  });
};

2.2 Keyring 密钥管理

Keyring 是密钥管理的核心模块,负责 HD 派生路径配置和多链密钥的统一管理:

助记词 / 私钥

KeyringController

HDKeyring
助记词派生

SimpleKeyring
私钥导入

EthereumHDKeyring

BtcHDKeyring

SolanaHDKeyring

DefaultHDKeyring

EthereumSimpleKeyring

BtcSimpleKeyring

DefaultSimpleKeyring

派生路径配置示例(BTC)

地址类型派生路径说明
SegWit Nested (P2SH)m/49'/0'/0'/0/{index}兼容性好
SegWit Native (Bech32)m/84'/0'/0'/0/{index}推荐
Taprootm/86'/0'/0'/0/{index}最新标准

测试网使用 coin_type = 1(如 m/84'/1'/0'/0/{index})。

Keyring 查找逻辑

javascript
// 根据链名称获取 HDKeyring 类
const getHDKeyringByChain = (baseChain, coinType) => {
  if (typeof coinType === 'undefined') {
    throw new Error(`Cannot find HDKeyring for chain: ${baseChain}`);
  }
  return hdKeyringMap[baseChain] || hdKeyringMap.default;
};

2.3 网络配置

每条链需要配置三个核心标识:

配置项说明示例
coinId链的唯一数字标识BTC: 1, SOL: 1800, TRX: 14
localType链的字符串标识'bitcoin', 'solana', 'tron'
RPC 信息节点连接配置chainId, rpcUrl, symbol, explorerUrl

网络配置包含完整的链元数据:

javascript
{
  baseChain: 'bitcoin',
  chainId: 0,
  chainName: 'Bitcoin',
  coinId: 1,
  coinType: 0,
  decimalNum: 8,
  symbol: 'BTC',
  localType: 'bitcoin',
  providerType: 'bitcoin',
  // ...
}

三、转账模块

3.1 发送交易

发送交易由三个核心页面组成,每条链独立实现:

选择收款地址
AddressPage

输入金额
AmountPage

交易确认
ConfirmPage

Gas 估算

SDK 签名

广播上链

路由配置:通过 configs 匹配链类型,动态加载对应组件:

javascript
// 根据 baseCoinId 和 coinId 匹配对应链的发送页面
const config = configs.find(({ match }) => {
  return match(baseCoinId, coinId, protocolId);
});

const { AddressPage, AmountPage, ConfirmPage } = config.pages;

3.2 接收资产

相对简单的模块,由 symbol(币种)、chainName(链名)、address(地址)组成收款码页面。

3.3 交易历史

标准的订单 CRUD 操作,从后端服务读取和更新交易记录。


四、DApp 交互

4.1 Provider 注入

浏览器插件通过 Inpage 脚本向每个 DApp 页面注入 Provider 对象,使 DApp 能与钱包通信:

BackgroundJSON-RPC StreamInpage ProviderDApp 网页BackgroundJSON-RPC StreamInpage ProviderDApp 网页插件加载时注入 Provider注入 window.bitcoin / window.ethereum 等调用 Provider 方法序列化为 JSON-RPC 请求转发到 Background执行业务逻辑返回结果反序列化响应返回给 DApp

每条链的 Provider 独立创建

javascript
// 创建 Bitcoin Provider
const createBitcoinInpageProvider = () => {
  const BaseBitcoinInpageProvider = createBaseBitcoinInpageProvider({
    providerType: PROVIDER_BITCOIN,
    localType: BITCOIN
  });

  return class BitcoinInpageProvider extends BaseBitcoinInpageProvider {
    constructor(connectionStream, { jsonRpcStreamName, logger, provider }) {
      super(connectionStream, { jsonRpcStreamName, logger, provider });
      provider.bitcoin = this;  // 挂载到 window 对象
    }
  };
};

4.2 Middleware 路由

Provider 的 RPC 请求通过 Middleware 路由到对应的处理函数:

DApp RPC 请求

Provider Middleware

bitcoinMiddleware

ethereumMiddleware

solanaMiddleware

...其他链

签名类方法
signMessage / signPsbt

查询类方法
getBalance / getPublicKey

交易类方法
send / sendPsbt

BTC Middleware 支持的 RPC 方法

方法类别说明
getPublicKey查询获取地址公钥
getCompressedPublicKey查询获取压缩公钥
validateAddress查询验证 BTC 地址
getBalance查询获取余额
getInscriptions查询获取 Ordinals 铭文
signMessage签名消息签名
signPsbt / signPsbts签名PSBT 签名(单/批量)
send / sendBtc交易发送 BTC
sendPsbt交易发送已签名 PSBT
pushTx / pushPsbt广播广播原始交易
mint / inscribe铭文BRC-20/Runes Mint
watchAsset资产添加自定义 Token

4.3 签名与广播

DApp 交易签名后的处理流程:

后端 APIDApp HandlerBackground插件 UIDApp后端 APIDApp HandlerBackground插件 UIDApp签名后处理发起交易请求弹出确认窗口用户确认签名确认结果执行签名逻辑计算 txHash广播交易(postTx)广播结果更新请求状态为 Submitted返回 txHash

签名后数据处理关键步骤

  1. 使用 SDK 计算 txHash
  2. 构建广播参数(from、to、coinAmount、signedTx 等)
  3. 根据交易来源选择广播接口(DApp / DEX)
  4. 更新 DApp 请求状态

4.4 BTC 铭文操作(Mint / Etch)

BTC 铭文操作(BRC-20、Runes)有独立的签名流程:

DApp 输入参数

解析铭文数据
type / tick / amount

获取 UTXO

构建签名数据
inputs + outputs + runeData

估算手续费
estimateFee()

SDK 签名
signTransaction()

输出统一结构

commitTx

revealTxs

commitTxFee / revealTxFees

Runes Mint 签名数据结构

javascript
const signData = {
  type: 'RUNEMAIN',
  inputs: utxo.map(item => ({
    ...item,
    privateKey,
    publicKey,
    address,
  })),
  outputs: [{
    address,
    amount: outValue,
    data: inscriptions[0],
  }],
  runeData: {
    etching: null,
    useDefaultOutput: false,
    defaultOutput: 0,
    burn: false,
    mint: true,
    mintNum: inscriptions.length,
  },
  feePerB: satBytes,
};

五、UI 层模块划分

5.1 页面模块结构

pages/

home/
首页 · 解锁 · 引导

crypto/
转账 · 交易

dapp-connect/
DApp 交互

wallet/
钱包管理

setting/
设置中心

convenient-tools/
便捷工具

address/ 地址簿

manage/ 币管理

trade/ 发送·接收·历史

dex/ Swap 入口

DappEntry/ 入口处理

confirm-transaction/ 交易确认

permissions-connect/ 授权弹窗

各链处理
evm/solana/cosmos/sui/...

import/ 钱包导入

mpc/ MPC 钱包

manage/ 钱包管理

SafetyLevel/ 安全等级

WalletBackUp/ 备份

password/ 密码管理

5.2 DApp 交易确认

DApp 交易确认采用类型转发模式,根据链和方法动态路由到对应 UI 组件:

javascript
// 根据请求类型路由到对应确认页面
switch (method) {
  case BTCRequestEnum.SIGN_MESSAGE:
    return <SignMessage unapproved={unapproved} />;
  case BTCRequestEnum.MINT:
    return <Mint unapproved={unapproved} />;
  case BTCRequestEnum.WATCHASSET:
    return <WatchAsset unapproved={unapproved} />;
  // ...
}

每个 DApp API 接口的支持程度不同,各页面自行控制错误提示和功能限制:

条件处理
MPC 钱包 + Runes Etch不支持,显示错误提示
硬件钱包部分操作暂不支持
UTXO 不足显示手续费错误

六、状态管理

6.1 Redux 架构

插件使用 Redux 管理全局状态:

dispatch action

useSelector

sendUpdate

UI 组件

Redux Store

ducks/
Reducers 模块

selectors/
派生数据

Background

模块说明
ducks/Redux reducer 模块化拆分
selectors/派生数据计算(类似 Vuex getters)
contexts/React Context 补充共享状态
hooks/封装业务逻辑的自定义 hooks

6.2 BG-UI 通信

Background 和 UI 之间通过适配层通信,业务逻辑对底层通信方式无感知:

Background 模块backgroundConnectUI 模块Background 模块backgroundConnectUI 模块调用钱包方法转发请求(Chrome Runtime API)执行业务逻辑sendUpdate 通知状态变化更新 Redux Store

七、多链支持策略

7.1 新链接入清单

接入一条新链需要完成以下模块的配置:

接入新链

1. 注册钱包 SDK

2. 配置 Keyring 派生路径

3. 配置网络标识
coinId / localType

4. 配置兜底 RPC

5. 创建 Provider
(DApp 注入)

6. 配置 Middleware
(RPC 路由)

7. 实现转账页面
地址/金额/确认

8. 实现 DApp Handler
(签名广播)

7.2 目前支持的链生态

生态代表链签名算法
EVMEthereum, Polygon, BSC, ArbitrumECDSA secp256k1
BTCBitcoin (主网/测试网/Signet)ECDSA secp256k1
SVMSolanaEd25519
TronTRONECDSA secp256k1
MoveAptos, SuiEd25519 / secp256k1
CosmosCosmos Hub, Osmosissecp256k1
OthersCardano, Stacks, StarkNet各自签名算法

总结

浏览器插件钱包的核心架构围绕 Background(后台服务)+ UI(用户界面)+ Inpage(DApp 注入) 三大运行环境构建:

  1. 账户体系:通过统一的钱包 SDK 注册和 Keyring 密钥管理,支持数十条链的密钥派生和签名
  2. DApp 交互:通过 Provider 注入 + Middleware 路由 + Handler 处理的三层架构,实现多链 RPC 方法的统一管理
  3. 状态管理:Redux + backgroundConnect 的通信适配层,使 BG-UI 跨进程通信对业务透明
  4. 可扩展性:新链接入只需按标准化流程配置 SDK → Keyring → Provider → Middleware → UI 页面