Wallet-Core 类比 MetaMask/Rainbow,有点类似于 React 类比 Vue,也算是 FP 和 OOP 路线在钱包上的差异体现。
框架类比
React 的心智模型
UI 是副作用受上下文托管的纯函数,是执行上下文(数据) 在这一刻的 渲染纯函数 运行结果,改变数据的行为本质是用动作纯函数去修改上下文然后重新执行渲染纯函数。
Vue 的心智模型
UI 是拥有数据与行为且自响应式的对象,是对这个对象的观察结果。
钱包架构心智模型
Wallet-Core (FP 风格)
钱包是 DB 中的数据(执行上下文) 在这一刻的渲染结果,并且提供了一系列柯里化方式注入 DB 实例的动作纯函数来改变 DB 中的数据。
┌──────────────────────────────────────────────┐
│ 动作函数(database) ──→ DB ──→ Observable │
│ ↑ ↓ │
│ └────── UI 触发 ←─── UI 渲染 │
└──────────────────────────────────────────────┘
MetaMask & Rainbow (OOP 风格)
钱包是拥有数据与行为的内存对象,UI 和持久化存储是对这个对象里数据的观察结果。
┌──────────────────────────────────────────────┐
│ 对象方法 ──→ 内存状态 ──→ 观察者响应 │
│ ↑ ↓ │
│ └────── UI 触发 ←─── UI 渲染 │
│ ↓ │
│ 持久化存储 │
└──────────────────────────────────────────────┘
架构实现差异
虽然 MetaMask 和 Rainbow 的心智模型相同,但在架构实现上有明显差异:
MetaMask (Controller 聚合 + Messenger)
经典 OOP Controller 聚合模式,设计了一套消息总线机制来同步数据与 UI 状态、串联各个 Controller、同时实现跨端复用。
┌─────────────────────────────────────────────────────────┐
│ ComposableController │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ Accounts │ │ Network │ │ Transaction │ ... │
│ │ Controller │ │ Controller │ │ Controller │ │
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │ │
│ └───────────────┼───────────────┘ │
│ ▼ │
│ Messenger │
│ (Actions + Events Bus) │
└─────────────────────────────────────────────────────────┘
Rainbow (React Store 模式单体应用)
强耦合单体应用设计,代码比 MetaMask 简洁的多,但跨端只能共用逻辑库。
┌─────────────────────────────────────────────────────────┐
│ React App │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ wallets │ │ assets │ │ swaps │ ... │
│ │ Store │ │ Store │ │ Store │ │
│ └──────┬──────┘ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │ │
│ └───────────────┼───────────────┘ │
│ ▼ │
│ React Hooks (useStore) │
│ + subscribeWithSelector │
└─────────────────────────────────────────────────────────┘
| 对比项 | MetaMask | Rainbow |
|---|---|---|
| 代码复用 | 能共用钱包对象,跨端只需处理 UI 层和持久层 | 跨端只能共用逻辑包 |
| 代码复杂度 | 较重 | 轻量的多 |
| 性能优化 | 一般 | 更容易把性能做到极致 |
| 上手难度 | 较高 | 更好上手维护 |
优缺点对比
Wallet-Core (FP 风格)
✅ 优点
- 通过 DB 天然可以保证事务级原子性,天然支持复杂查询,不需要自己在持久化(DB 就是唯一信源,没有状态同步的问题)、Schema 变更上面做处理
- FP 模式很容易写测试、找问题,一旦上手结构很清晰
- 跨端使用体验完全一致,也不用自己做额外处理
❌ 缺点
- 完全依赖 DB 本身的能力,如果选型的 RXDB 在跨端上有问题,自己完全没法处理
- 没有一个内存级的对象实例,如果存在那种不停的、超快速写入钱包相关数据的场景,性能就存在瓶颈,得自己整个内存 Cache 层
- 心智模型方面 FP 模式有理解和上手成本,就像 React 之于 Vue
- 市面上没有其他钱包是这么干的
MetaMask & Rainbow (OOP 风格)
✅ 优点
- 心智模型上符合直觉,好上手
- 存在一个内存级的对象实例,如果存在那种不停的、超快速写入钱包相关数据的场景,只要处理好持久化写入层的通道,完全没有性能瓶颈
❌ 缺点
- 为了持久化和跨端需要额外写好多东西,总线过多事件时的顺序与幂等处理等等
- 不易调试追踪问题,写测试需要 mock 太多东西