当用户在 dApp 中点击“Connect Wallet”或发起交易时,钱包需要接收、校验、处理这些请求并返回结果。本文档说明 Mega Wallet 为什么要重构这部分架构,以及重构后是如何设计的。
现有架构
整体流程
dApp 调用 window.ethereum.request()
│
▼
┌─────────────────────────────────────────────────────────┐
│ Provider(mega-wallet-provider) │
│ │
│ ProvideEvm → MetaMaskInpageProvider → BaseProvider │
│ │ │
│ └── 通过 globalThis.$jsBridge 发送请求 │
└────────────────────────────┬────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ Service(mega-wallet/packages/service) │
│ │
│ service.dApp.request.handleRequest(request) │
│ │ │
│ ▼ │
│ ┌─────────────────────────────────────────────────┐ │
│ │ const handler = getHandler(base, service) │ │
│ │ → new EvmHandler(service) │ │
│ │ │ │
│ │ handler[method](request) │ │
│ │ → 直接调用对应方法 │ │
│ │ → 没有的方法走 handler.request() fallback │ │
│ └─────────────────────────────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────┘
核心代码
request.ts
async handleRequest(request: JsonRpcRequest) {
const req = this.addRequest(request)
try {
await this.service.dApp.connection.connect(req)
const { result, error } = await this.#handlerCall(req)
// ...
} catch (error) {
return { error }
}
}
async #handlerCall(request: TRequest) {
const handler = getHandler(request.base, this.service)
const method = handler[request.request.method] || handler.request
return await method.call(handler, request)
}
handler/evm.ts
class EvmHandler extends BaseHandler {
async eth_requestAccounts(request: TRequest) {
const { result } = await this.service.ui.showConfirmation(request, wallet)
this.emit('connect', { chainId, isConnected: true })
this.emit('accountsChanged', [address])
return this.service.dApp.request.updateRequest({ ...request, result: [result.address] })
}
async personal_sign(request: TRequest) {
if (address.toLowerCase() !== this.wallet.address.toLowerCase()) {
throw new Error('Invalid params')
}
return this.#signMessage(request, rawMsg, type)
}
}
现有架构的场景问题
场景 1:实现细粒度权限控制(CAIP-25)
背景:用户连接 dApp 后,dApp 可以请求签名、发交易。但有些用户只想授权“查看地址”,不想授权“签名”。这需要实现 CAIP-25 权限系统。
需求:
eth_accounts需要accounts权限personal_sign需要sign权限eth_sendTransaction需要transact权限
如果要改:
方案 A:在每个 Handler 方法里加检查
class EvmHandler extends BaseHandler {
async personal_sign(request: TRequest) {
if (!this.hasPermission(request.origin, 'sign')) {
throw new Error('No sign permission')
}
// ... 原有逻辑
}
async eth_sendTransaction(request: TRequest) {
if (!this.hasPermission(request.origin, 'transact')) {
throw new Error('No transact permission')
}
}
// 还有 eth_signTypedData, eth_signTypedData_v3, eth_signTypedData_v4... 每个都要加
}
方案 B:在 handleRequest 里加映射表
async handleRequest(request) {
const permissionMap = {
personal_sign: 'sign',
eth_signTypedData: 'sign',
eth_sendTransaction: 'transact',
// ... 几十个方法
}
const requiredPermission = permissionMap[method]
if (requiredPermission && !this.hasPermission(origin, requiredPermission)) {
if (method === 'eth_accounts') return { result: [] } // 不同方法不同处理
return { error: 'Unauthorized' }
}
}
问题:
- 方案 A 需要改几十个方法,容易漏
- 方案 B 在 handleRequest 里堆积 if-else
- 不同方法的 missingBehavior 不同(有的抛错,有的返回空数组),逻辑分散
场景 2:防止重复弹窗堆积
背景:dApp 可能短时间内发送大量请求,导致用户界面被弹窗淹没。比如 MetaMask 卡顿时经常出现十几个待处理的弹窗请求列表;恶意 dApp 也可能利用这种方式进行钓鱼攻击。
需求:相同的 Approval 请求不应重复弹窗,新请求应等待已有弹窗的结果。
如果要改:
export default class DAppRequest {
private pendingApprovals = new Map<string, Promise<unknown>>()
async handleRequest(request) {
const approvalMethods = ['eth_requestAccounts', 'personal_sign', 'eth_sendTransaction', ...]
if (approvalMethods.includes(method)) {
const key = this.#makeKey(req)
const existing = this.pendingApprovals.get(key)
if (existing) return existing
const promise = this.#handlerCall(req).finally(() => {
this.pendingApprovals.delete(key)
})
this.pendingApprovals.set(key, promise)
return promise
}
return this.#handlerCall(req)
}
}
问题:
- 需要在 handleRequest 里维护
pendingApprovals状态 - 需要手动维护
approvalMethods列表,新增方法时容易遗漏 - 去重逻辑与业务逻辑耦合在一起
- 难以单独测试
- 更根本的问题:原架构没有统一的方式区分“需要用户确认的请求”和“可以直接返回的请求”,这个判断分散在各个 Handler 方法内部(通过是否调用
showConfirmation来决定)
场景 3:钱包锁定状态处理
背景:用户可以设置钱包自动锁定。锁定后,不同的 RPC 方法应该有不同的行为:
eth_chainId→ 正常返回(不需要解锁)eth_accounts→ 返回空数组(不暴露地址)personal_sign→ 等待用户解锁后继续
如果要改:
方案 A:在每个 Handler 方法里加检查
class EvmHandler extends BaseHandler {
async eth_accounts(request: TRequest) {
if (this.service.wallet.isLocked) {
return { result: [] } // 返回空数组
}
// ... 原有逻辑
}
async personal_sign(request: TRequest) {
if (this.service.wallet.isLocked) {
await this.service.wallet.waitForUnlock() // 等待解锁
}
// ... 原有逻辑
}
async eth_chainId(request: TRequest) {
// 不需要检查锁定状态
return { result: this.chainId }
}
}
方案 B:在 handleRequest 里加映射表
async handleRequest(request) {
const lockBehavior = {
eth_accounts: 'returnEmpty',
personal_sign: 'waitUnlock',
eth_chainId: 'allow',
// ... 几十个方法
}
if (this.service.wallet.isLocked) {
const behavior = lockBehavior[method]
if (behavior === 'returnEmpty') return { result: [] }
if (behavior === 'waitUnlock') await this.service.wallet.waitForUnlock()
// else allow
}
}
问题:
- 方案 A 需要在每个方法里加检查,容易漏
- 方案 B 在 handleRequest 里堆积逻辑,和权限检查、去重逻辑混在一起
- 不同方法的 lockBehavior 不同(allow/returnValue/wait/reject),逻辑分散
场景 4:添加新链(如 Bitcoin)
背景:现有架构通过 getHandler(base, service) 选择 Handler,添加新链需要改多个地方。
如果要改:
// 1. 新建 handler/btc.ts
class BtcHandler extends BaseHandler {
async bitcoin_connect(request) { ... }
async bitcoin_signPsbt(request) { ... }
}
// 2. 修改 handler/index.ts
const HandlerMap = { evm: EvmHandler, sol: SolHandler, btc: BtcHandler }
export const providerTypeMap = { 'mega-provider-btc': 'btc' }
// 3. 新建 Provider 包(mega-wallet-provider/packages/btc/)
// 4. 修改 types: TNetworkBase = 'evm' | 'sol' | 'btc'
// 5. 找到所有按 base 分支的地方...
问题:
- 需要修改多个文件(handler、types、Provider 包)
- Handler 类要实现所有方法
- 权限检查要在每个方法里加(参考场景 1)
- 容易漏掉某个地方
重构后的架构
整体设计
dApp 调用 window.ethereum.request()
│
▼
┌─────────────────────────────────────────────────────────┐
│ Provider(packages/provider) │
│ │
│ EthereumProvider / SolanaProvider │
│ │ │
│ └── 通过 Transport 抽象发送请求 │
│ ├── MobileTransport (Mobile WebView) │
│ ├── DesktopTransport (Desktop Electron) │
│ ├── ExtensionInpageTransport (Inpage) │
│ └── ExtensionContentTransport (Content) │
└────────────────────────────┬────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────┐
│ rpc-engine(packages/rpc-engine) │
│ │
│ rpcEngine.handle(request, context) │
│ │ │
│ ┌────────┴────────────────────────────────────┐ │
│ │ Middleware Pipeline │ │
│ │ │ │
│ │ logger → permissionGuard → dedupe → │ │
│ │ lockGuard → executor │ │
│ └────────┬────────────────────────────────────┘ │
│ │ │
│ ┌─────┼─────────────────────┐ │
│ ▼ ▼ ▼ │
│ handlers onApproval RPC Proxy │
│ (即时返回) (需用户确认) (转发到节点) │
└─────────────────────────────────────────────────────────┘
rpc-engine 核心设计
1. 中间件管道(Middleware Pipeline)
// engine.ts
const middleware = [
loggerMiddleware, // 日志记录
permissionGuardMiddleware, // 权限检查
dedupe.middleware, // 请求去重
lockGuardMiddleware, // 锁定状态检查
executorMiddleware // 执行请求
]
const engine = JsonRpcEngineV2.create({ middleware })
每个中间件职责单一,可独立测试、可插拔。
2. 方法配置(声明式)
// chainConfigs/eip155/index.ts
const config: Record<string, MethodConfig> = {
eth_accounts: {
requiresPermission: {
scope: PermissionScope.Accounts,
missingBehavior: { returnValue: [] }
},
lockBehavior: { returnValue: [] }
},
personal_sign: {
requiresPermission: { scope: PermissionScope.Sign },
requestCategory: RequestCategory.RequiresApproval
},
eth_chainId: {
lockBehavior: LockBehavior.Allow
}
}
3. 请求分类
| 类型 | 说明 | 判断条件 | 示例 |
|---|---|---|---|
| handlers | 钱包内部处理 | handlers[method] 存在 |
eth_chainId, eth_accounts |
| onApproval | 需用户确认 | requestCategory === RequiresApproval |
personal_sign, eth_sendTransaction |
| RPC Proxy | 转发到节点 | 以上都不满足 | eth_getBalance, eth_call |
4. 遵循 CAIP 标准的异构链模块化
整体架构遵循 CAIP (Chain Agnostic Improvement Proposal) 标准规范,支持异构链钱包:
| CAIP 标准 | 名称 | 用途 | 使用位置 |
|---|---|---|---|
| CAIP-2 | 区块链标识 | 链 ID 格式 namespace:reference |
RpcContext、ChainModule |
| CAIP-10 | 账户标识 | 账户格式 namespace:reference:address |
SessionScope |
| CAIP-25 | 权限请求 | 权限 scope 模型 (accounts/sign/transact) | permissionGuard 中间件 |
链标识示例 (CAIP-2):
- EVM:
eip155:1(Ethereum),eip155:137(Polygon) - Solana:
solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp(Mainnet) - Bitcoin:
bip122:000000000019d6689c085ae165831e93(Mainnet)
type ChainModule<Provider = unknown> = {
namespace: string
info: WalletInfo
createProvider: (transport: Transport) => Provider
expose: (options: ExposeOptions<Provider>) => () => void // 返回 cleanup
}
// 每个链在 index.ts 中定义 ChainModule
// chains/ethereum/index.ts
export const ethereumChainModule: ChainModule<EthereumProvider> = {
namespace: 'eip155',
info: EthereumProvider.info,
createProvider: (transport) => createEthereumProvider({ transport }),
expose: (options) => exposeEthereumProvider(options)
}
// 使用
const providers = initializeProviders({
targetWindow: window,
transport,
chains: [ethereumChainModule, solanaChainModule]
})
重构后的场景解决
场景 1:实现细粒度权限控制(CAIP-25)
解决方式:通过方法配置声明权限,permissionGuard 中间件自动处理。
配置声明:
// chainConfigs/eip155/index.ts
eth_accounts: {
requiresPermission: { scope: PermissionScope.Accounts, missingBehavior: { returnValue: [] } }
},
personal_sign: {
requiresPermission: { scope: PermissionScope.Sign },
requestCategory: RequestCategory.RequiresApproval
}
中间件自动检查:
// middlewares/permissionGuard.ts
const methodConfig = getMethodConfig(namespace, method)
const requiredScope = getPermissionScope(methodConfig?.requiresPermission)
if (!requiredScope) return next()
if (hasPermission({ origin, scope: requiredScope })) return next()
if (methodConfig?.requiresPermission?.missingBehavior?.returnValue !== undefined) {
return methodConfig.requiresPermission.missingBehavior.returnValue
}
throw providerErrors.unauthorized(`Requires "${requiredScope}" permission`)
如果要加新方法的权限:只需在配置文件加一行。
| 对比项 | 现有架构 | 重构后 |
|---|---|---|
| 改动位置 | 每个 Handler 方法 或 handleRequest | 配置文件一处 |
| 新增方法 | 手动加检查,容易漏 | 加配置,中间件自动生效 |
| missingBehavior | 分散在各处的 if-else | 配置声明,统一处理 |
场景 2:防止重复弹窗堆积
解决方式:独立的 dedupe 中间件。
// middlewares/dedupe.ts
const APPROVAL_METHODS = new Set(['eth_requestAccounts', 'personal_sign', ...])
export function createDedupeMiddleware() {
const pending = new Map<string, Promise<unknown>>()
return createMiddleware(async ({ request, context, next }) => {
if (APPROVAL_METHODS.has(method)) {
const key = `${origin}:${caip2}:${method}`
const existing = pending.get(key)
if (existing) return existing
const promise = next().finally(() => pending.delete(key))
pending.set(key, promise)
return promise
}
return next()
})
}
如果要调整去重逻辑:只改这一个中间件文件。
| 对比项 | 现有架构 | 重构后 |
|---|---|---|
| 代码位置 | 混在 handleRequest 业务逻辑里 | 独立中间件文件 |
| 可测试性 | 需要 mock 整个 Service | 中间件可独立测试 |
| 扩展 | 改 handleRequest | 修改中间件或配置 |
场景 3:钱包锁定状态处理
解决方式:通过方法配置声明 lockBehavior,lockGuard 中间件自动处理。
配置声明:
// chainConfigs/eip155/index.ts
eth_chainId: {
lockBehavior: LockBehavior.Allow // 锁定时也允许
},
eth_accounts: {
lockBehavior: { returnValue: [] } // 锁定时返回空数组
},
personal_sign: {
lockBehavior: LockBehavior.WaitForUnlock, // 等待解锁
requestCategory: RequestCategory.RequiresApproval
}
中间件自动检查:
// middlewares/lockGuard.ts
const methodConfig = getMethodConfig(namespace, method)
const lockBehavior = methodConfig?.lockBehavior
if (!isLocked()) return next()
if (lockBehavior === LockBehavior.Allow) return next()
if (lockBehavior?.returnValue !== undefined) return lockBehavior.returnValue
if (lockBehavior === LockBehavior.WaitForUnlock) {
await waitForUnlock()
return next()
}
throw providerErrors.unauthorized('Wallet is locked')
如果要改某个方法的锁定行为:只需在配置文件改一行。
| 对比项 | 现有架构 | 重构后 |
|---|---|---|
| 改动位置 | 每个 Handler 方法 或 handleRequest | 配置文件一处 |
| 新增方法 | 手动加检查,容易漏 | 加配置,中间件自动生效 |
| 多种行为 | if-else 分支 | 枚举值声明,统一处理 |
场景 4:添加新链(如 Bitcoin)
解决方式:ChainModule + 方法配置。
- 添加方法配置:
// chainConfigs/bitcoin/index.ts
const config = {
bitcoin_connect: { requestCategory: RequestCategory.RequiresApproval },
bitcoin_signPsbt: {
requiresPermission: { scope: PermissionScope.Transact },
requestCategory: RequestCategory.RequiresApproval
}
}
- 实现 ChainModule:
// chains/bitcoin/index.ts
export const bitcoinChainModule: ChainModule<BitcoinProvider> = {
namespace: 'bitcoin',
info: BitcoinProvider.info,
createProvider: (transport) => new BitcoinProvider({ transport }),
expose: ({ targetWindow, provider }) => {
targetWindow.bitcoin = provider
return () => delete targetWindow.bitcoin
}
}
- 注册到 Engine:
createRPCEngine({
chains: {
bitcoin: { handlers: bitcoinHandlers, onApproval: handleBitcoinApproval }
}
})
如果要加新链:按模块添加,位置明确。
| 对比项 | 现有架构 | 重构后 |
|---|---|---|
| 权限检查 | 每个 Handler 方法里加 | 配置声明,自动生效 |
| 中间件复用 | 没有中间件 | logger/dedupe/lockGuard 自动应用 |
| 修改点 | 多个分散的文件 | 按模块组织,位置明确 |
其他钱包的 RPC 处理架构
MetaMask
MetaMask 使用 @metamask/json-rpc-engine 中间件架构处理 dApp 请求,设计思路与 Mega 的 rpc-engine 类似:
- 请求经过中间件链(权限检查、日志等)
- 方法配置声明式管理
Mega rpc-engine 参考了 MetaMask 的中间件设计,但针对多链场景做了扩展(CAIP-2 链标识、按 namespace 组织配置)。
Rainbow
Rainbow 是纯 React Native 钱包(全 JS/TS,用 zustand 管理状态),没有独立的 RPC 中间件架构:
- 单链为主 — 只支持 EVM,不需要异构链的方法配置管理
- 权限模型简单 — 只用 WalletConnect 通信,依赖 WalletConnect 本身的会话管理
- 直接处理 — RPC 请求在 WalletConnect 回调里直接处理(
onSessionRequest),用硬编码的SUPPORTED_SIGNING_METHODS列表区分方法类型
没有中间件架构意味着:权限检查、方法路由等逻辑直接写在请求处理函数里,代码相对简单但扩展性有限。
如果要加,WalletConnect 应该接在哪层
WalletConnect 与 Transport 平级,直接调用 rpcEngine.handle():
内置浏览器 dApp ───▶ Transport ───┐
│
▼
rpc-engine.handle()
▲
│
外部 dApp ─────────▶ WalletConnect ─┘
// service/dapp/walletconnect.ts
onSessionRequest = async (event: WCSessionRequest) => {
const { chainId, request } = event.params
const result = await this.service.rpcEngine.handle(request, {
origin: session.peer.metadata.url,
caip2: chainId,
namespace: chainId.split(':')[0]
})
await this.client.respondSessionRequest({ topic, response: { id, result } })
}
好处:复用所有中间件(权限、去重、锁定检查),CAIP-2 原生兼容。
Provider 包的改进
对比现有架构(mega-wallet-provider、mega-wallet-js-bridge)和 MetaMask Provider,重构后的 @megaeth-labs/provider 包有以下改进:
1. Transport 内聚
现有架构:
- Provider 和 JS Bridge 分离在两个包
- 需要单独维护两个包的依赖和版本
- 通信方式硬编码在各平台 Bridge 里,支持新平台要改两个包
// Provider 依赖全局 bridge
class ProviderDelegate extends ProviderBase {
delegateRequest = async (payload, cb) => {
return this.bridgeRequest(payload, cb)
}
}
// 各平台继承实现,硬编码平台 API
class MobileInjectJsBridge extends JsBridge {
sendData(message: string) {
globalThis.ReactNativeWebView.postMessage(message)
}
}
重构后的架构:
- Transport 是 provider 包的内部实现(
src/transport/) - 一个包搞定,减少依赖复杂度
- 支持多平台:Provider 只依赖 Transport 接口,不同平台实现不同 Transport
// Transport 接口统一
interface Transport {
connect(): Promise<void>
disconnect(): Promise<void>
isConnected(): boolean
getConnectionState(): TransportState
request(args: RequestArguments, options?: TransportRequestOptions): Promise<unknown>
on(event: string, listener: (...args: unknown[]) => void): void
removeListener(event: string, listener: (...args: unknown[]) => void): void
}
// 不同平台,同一个 Provider,不同 Transport
const transport = new MobileTransport() // Mobile WebView
const transport = new DesktopTransport() // Desktop Electron
const transport = new ExtensionInpageTransport() // Extension Inpage
const provider = new EthereumProvider({ transport })
| 对比项 | 现有架构 | 重构后的架构 |
|---|---|---|
| 新增平台 | 改两个包 + Provider 继承链 | 实现一个 Transport 类 |
| 代码复用 | Provider 逻辑重复 | 同一个 Provider,不同 Transport |
| 测试 | Mock 全局对象 | Mock Transport 接口 |
2. 移除复杂继承链
MetaMask Provider 的问题:
- 代码过重,继承链深达 4 层
- 只支持 EVM,不支持异构链(Solana 等)
现有架构(基于 MetaMask):
// 4 层继承,改底层影响所有上层
class ProviderEvm extends MetaMaskInpageProvider { }
class MetaMaskInpageProvider extends AbstractStreamProvider { }
class AbstractStreamProvider extends BaseProvider { }
class BaseProvider extends ProviderDelegate { }
继承链带来的问题:
- 每层都有自己的状态(
_state、#chainId、#selectedAddress、#networkVersion) _handleChainChanged在不同层有不同实现,调用顺序复杂- 子类需要调用
super._handleChainChanged()保证行为正确 - 新增功能需要考虑在哪一层实现
重构后的架构:
// 单一类,组合优于继承
class EthereumProvider extends EventEmitter {
#transport: Transport
#state: EthereumProviderState
}
3. 支持异构链(CAIP-25 / CAIP-217)
MetaMask Provider:只支持 EVM,无法扩展到其他链。
重构后的架构:遵循 CAIP-25(Wallet Request/Respond)和 CAIP-217(Multi-Chain Authorization)标准,ChainModule 插件化支持 EVM + Solana + 更多链。
// chains/ethereum/index.ts
export const ethereumChainModule: ChainModule<EthereumProvider> = {
namespace: 'eip155', // CAIP-2 namespace
info: EthereumProvider.info,
createProvider: (transport) => createEthereumProvider({ transport }),
expose: (options) => exposeEthereumProvider(options) // window.ethereum + EIP-6963
}
// chains/solana/index.ts
export const solanaChainModule: ChainModule<SolanaProvider> = {
namespace: 'solana', // CAIP-2 namespace
info: SolanaProvider.info,
createProvider: (transport) => new SolanaProvider({ transport }),
expose: (options) => exposeSolanaProvider(options) // window.solana + Wallet Standard
}
// 初始化时按需加载
initializeProviders({
transport,
chains: [ethereumChainModule, solanaChainModule]
})
4. 事件处理标准化(CAIP-311 / CAIP-319)
现有架构:
- 自定义事件格式
- 不同链的事件处理方式不一致
- MetaMask 只支持 EVM 事件
重构后的架构:
- 遵循 CAIP-311(
wallet_sessionChanged):会话整体变更(连接/断开、切换账户/链) - 遵循 CAIP-319(
wallet_notify):链特定通知 - 多个 Provider(EVM / Solana)共用同一个 Transport,通过 CAIP-2 scope 过滤
// Transport 发出标准化事件(CAIP-311)
Transport.emit('sessionChanged', {
sessionScopes: {
"eip155:1": { accounts: ["eip155:1:0x..."] }, // CAIP-10 账户格式
"solana:mainnet": { accounts: ["solana:mainnet:ABC..."] }
}
})
// 各 Provider 按 CAIP-2 scope 过滤
EthereumProvider → isEip155Scope() → emit('accountsChanged')
SolanaProvider → isSolanaScope() → emit('accountChanged')
// EthereumProvider 解析 CAIP-311 sessionScopes
#onSessionChanged = (params) => {
const { sessionScopes } = params
const parsed = EthereumProviderState.parseSessionScopes(sessionScopes)
if (parsed) {
this.#applyChainChanged(parsed.chainId)
this.#applyAccountsChanged(parsed.accounts)
}
}
5. Timeout 配置标准化
现有架构:
- Timeout 硬编码在各处
- 不同方法没有区分超时时间
重构后的架构:
Provider 和 rpc-engine 使用分层超时策略,Provider 超时略长于 rpc-engine,确保 rpc-engine 先超时并返回明确错误,而非 Transport 层断开:
| 层 | 配置 | Approval | Normal | Readonly |
|---|---|---|---|---|
| rpc-engine | DEFAULT_TIMEOUTS |
5 min | 30s | 30s |
| Provider | PROVIDER_TIMEOUTS |
5.5 min | 35s | 35s |
Provider 根据方法类型自动选择超时:
const config = getMethodConfig('eip155', method) // 从 rpc-engine 获取方法配置
switch (config?.requestCategory) {
case RequestCategory.RequiresApproval:
return PROVIDER_TIMEOUTS.approvalTimeoutMs // 需审批 5.5min
case RequestCategory.Readonly:
return PROVIDER_TIMEOUTS.readonlyTimeoutMs // 只读 35s
default:
return PROVIDER_TIMEOUTS.normalTimeoutMs // 普通 35s
}
总结
| 改进点 | 现有架构问题 | 重构后的架构方案 |
|---|---|---|
| 通信层 | 分包 + 硬编码 | Transport 接口内聚 |
| 继承链 | 4 层深继承 | 单层组合 |
| 多链支持 | 仅 EVM | ChainModule 插件化(CAIP-25/217) |
| 事件格式 | 自定义 | CAIP-311/319 标准 |
| 超时配置 | 硬编码 | 与 rpc-engine 联动,分层超时 |