给Metamask连接Ledger硬件钱包 添加自选派生路径功能
一个Web3热钱包,或者硬件钱包,可以有很多个地址,事实上钱包真正储存的只有一个root key,生成给我们使用的地址都是按照BIP44标准,从root key指定派生路径来计算生成。
派生路径规则
Metamask使用的路径是m/44’/60’/0’/0/x,第一个地址是m/44’/60’/0’/0/0,第二个地址是m/44’/60’/0’/0/1。
而Ledger Live使用的路径是m/44’/60’/x’/0/0,第一个地址是m/44’/60’/0’/0/0,第二个地址是m/44’/60’/1’/0/0。
44后面那个数字是指coin,60是Ethereum,EVM一般用的都是这种,0是Bitcoin,其他coin也会有其他的代号。
需求
最近在做一个个人项目,需要给每个用户分配一个地址,中心化托管,出于安全考虑需要使用硬件钱包,但总不能每个用户都独立一个硬件钱包,肯定需要统一到一个硬件钱包来管理,于是想出使用m/44’/60’/0’/0/x来实现,x代表用户ID,这样就可以一个硬件钱包支持多个用户了。
但这样如果想要操作某个用户的地址就很麻烦,在Metamask里连接Ledger硬件钱包,导入地址,只能逐页翻,每页固定只有5个地址,每次翻页都需要从钱包读取比较慢,如果需要翻到用户ID对应的地址,效率非常低。

Metamask钱包插件二次开发
于是改动Metamask源码,来支持手动输入ID直接翻到对应页,以及每页改成10个地址。 git clone Metamask源码 https://github.com/MetaMask/metamask-extension 基于v10.23.2来二次开发
-
先加一个输入框,和把原来的逐页翻页按钮换成跳转按钮,并且新增setPage()计算从ID换成页数,一页10个地址

-
改成展示全地址方便对比,以及编号不要+1,从0开始,符合m/44’/60’/0’/0/x路径直观标识。修改了间距和颜色方便观看

-
仿照goToPreviousPage(),新增一个goToAnyPage(),供第一步的按钮点击会调用,直接翻到pageNo而不是+1或者-1

-
上一步的getPage(),会到connectHardware()连接硬件钱包去读取地址,由于页数原来只会传-1 +1,而我们传了pageNo,可以是任何正整数,所以需要补充处理pageNo为其他正整数时的情况,调用keyring的getAnyPage()

-
keyring实际为另一个依赖包eth-ledger-bridge-keyring,负责通过HID协议和Ledger硬件交互,具体依赖包路径在node_modules@metamask\eth-ledger-bridge-keyring\index.js,这个库本身没有getAnyPage()函数,需要我们自己实现,我们在index.js里添加,另外需要把
this.perPage = 5改成10,用来定义每页的地址数量,否则页数该对应的地址路径计算会不正确getAnyPage (page) { this.page = page return this.__getPage(0) }
最终效果图

大功告成!