比特币钱包生态有多土狗:从开始到放弃

如果你正在开发一个比特币 dApp,你可能已经发现了,比特币社区的生态实在是太土狗了。

最简单的例子就是比特币钱包,大家似乎热衷于给其他人制定标准,但大家似乎又不热衷于实现这个标准。

"标准"?什么标准?

让例子更详细一点:

WBIPs:制定标准的人自己都不遵守

Leather 和 Xverse 搞了一个 WBIPs ,说是要制定一个统一的比特币钱包 API 标准,但:

signPsbt 的 finalize 参数

signPsbt 标准里定义了 finalize 参数,但两个发起者都没实现:

钱包自动发现机制的实现完全不对啊老师

WBIP004 定义了钱包插件的自动发现机制,第一步是往 wbip_providers 里注入钱包 provider。

但实际上 Xverse 和 Leather 都是往 window.btc_providers 里注入的:

另外两个主流钱包根本不 care

更不用说实际上占有大量流量的 UniSatOKX Wallet 似乎对支持 WBIPs 没有丝毫兴趣。

sats-connect:标准之上的标准

然后在 WBIPs 之外,Xverse 还搞了一个 sats-connect ,似乎想在 WBIPs 之外再扩展一些自己的 API ,实现一套标准之上的标准。

这不算差,尤其是它还兼容了 UniSat API 。Magic Eden 还号称 "兼容 sats-connect"。

"这听起来简直太棒了!sats-connect 简直就是版本答案!世界救主!",对吧?你肯定是这么想的。

不过完美世界的上空"还剩下两朵小小的乌云":

  1. sats-connect 不支持 OKX Wallet(虽然 OKX Wallet 的 API 现在已经迁移到和 UniSat 兼容了,但 sats-connect 没办法自动发现它)
  2. Magic Eden 的自动发现跟的是另一个标准ExodusMovement/bitcoin-wallet-standard,而不是 WBIPs 标准。所以你没办法靠 sats-connect 来自动发现它。

等下,又来一个标准?

"等下卧槽,这个 ExodusMovement/bitcoin-wallet-standard 又是个什么标准?我 TM 从来没听说过啊!"

对的,在我尝试集成 Magic Eden 之前,我也没听说过,现在我听说了,你也听说了。

更多 Fun Facts

噢,还有一个 "fun fact" ,如果你的用户同时安装了 Xverse 和 Magic Eden ,而且你没有处理好,那么你的用户在点击连接钱包时,可能会随机收到来自两个中其中一个钱包的确认请求,人生真是处处充满惊喜。

噢,再加一个 "fun fact" ,Magic Eden 虽然号称 "兼容 sats-connect",但实际上它兼容的是旧版本的 API

来点示例代码

你可能会觉得那大不了我就自己在项目里都集成一遍呗。那让我们来看看为了实现一个简单的连接钱包功能,代码的差异:

// UniSat - 直接调用 window 对象
const unisatResponse = await window.unisat.requestAccounts();

// Leather - 又是另一套 API
const leatherResponse = await window.LeatherProvider.request("getAddresses");

// Xverse - 来自官方文档
import { request } from "sats-connect";
const xverseResponse = await request("getAddresses", null);

// Magic Eden - 来自官方文档
import { getAddress, AddressPurpose, BitcoinNetworkType } from "sats-connect";
await getAddress({
  getProvider: getBtcProvider,
  payload: {
    purposes: [AddressPurpose.Ordinals, AddressPurpose.Payment],
    message: "Address for receiving Ordinals and payments",
    network: {
      type: BitcoinNetworkType.Mainnet,
    },
  },
  onFinish: (response) => {
    console.log("onFinish response, ", response.addresses);
    connectionStatus?.setAccounts(response.addresses as unknown as Account[]);
  },
  onCancel: () => {
    alert("Request canceled");
  },
});

四个钱包,四种写法。

如果你得在你的项目里集成 6 个钱包呢?恭喜你,你会需要把我上面提到的问题都过一遍,和我一起愉快地浪费掉一大把人生的时间。

总结一下

"去他妈的傻逼比特币钱包生态,太他妈土狗了!",你/我心想。

所以我写了一个库

所以我写了一个 bitcoin-wallet-connector ,可以让其他人少浪费一点时间在这些破事上。

下一篇文章我会详细介绍这个库的使用方法和设计理念。如果你已经等不及了,可以先看看: