Trezor
如何為 Trezor 硬體錢包創建簽名者?
我正在嘗試為 Trezor 硬體錢包創建一個簽名者。
我正在使用庫 ethers.js
對於 Metamask 錢包,這就是我創建簽名者的方式:
export const createMetamaskSigner = async () => { let networkId = Number(window.web3.version.network) let provider = new providers.Web3Provider(window.web3.currentProvider, { chainId: networkId }) let signer = provider.getSigner() addMethodsToSigner(signer) let address = await signer.getAddress() window.signer = { instance: signer, type: 'metamask' } return { address, networkId } }
如果是 Trezor 硬體錢包,我該怎麼做?
謝謝
這就是我在項目中所做的:
您需要實現簽名者介面:https ://docs.ethers.io/ethers.js/html/api-wallet.html#signer-api
為了實現 Trezor 硬體錢包的這個介面,你需要使用這個庫https://github.com/trezor/connect
它具有以下功能:
https://github.com/trezor/connect/blob/develop/docs/methods/ethereumSignTransaction.md
https://github.com/trezor/connect/blob/develop/docs/methods/signMessage.md
**注意:**有些函式帶有“ethereum”前綴。如果您正在為乙太坊創建簽名者,則應該使用它們。
函式signTransaction(無前綴)用於比特幣。一開始我很困惑,因為比特幣和乙太坊的參數完全不同。
在此處查看討論以獲取更多詳細資訊:https ://github.com/ethers-io/ethers.js/issues/118#issuecomment-443574917
範常式式碼:
import { Signer, providers, utils } from 'ethers'; import TrezorConnect from 'trezor-connect'; import { NETWORK_URL } from '../../../config/url'; import { addMethodsToSigner } from './index'; const defaultDPath = "m/44'/60'/0'/0"; export class TrezorSigner extends Signer { constructor(path = defaultDPath) { super(); const networkId = 8888; this.provider = new providers.JsonRpcProvider(NETWORK_URL, { chainId: networkId }); this.address = null; window.signer = { instance: this, type: 'hardwareWallet' }; addMethodsToSigner(this); } getPublicKey = async (path = defaultDPath) => { this.path = path; let result = await TrezorConnect.getPublicKey({ path }); if (result.success) { return result.payload; } console.log(result); throw new Error(result.payload.error); }; getAddress = () => { return this.address; }; setAddress = (address) => { this.address = address; } signMessage = async message => { return new Promise(async (resolve, reject) => { let result = await TrezorConnect.ethereumSignMessage({ path: this.path + '/0', message }); if (result.success) { resolve(result.payload.signature); } else { console.error('Error:', result.payload.error); // error message reject(result.payload.error); } }); }; sign = async (transaction) => { if (transaction.value) { transaction.value = utils.hexlify(transaction.value); } if (transaction.gasPrice) { transaction.gasPrice = utils.hexlify(transaction.gasPrice); } if (transaction.gasLimit) { transaction.gasLimit = utils.hexlify(transaction.gasLimit); } transaction.nonce = utils.hexlify( await this.provider.getTransactionCount(this.address) ); let result = await TrezorConnect.ethereumSignTransaction({ path: this.path + '/0', transaction }); if (result.success) { let sig = { v: parseInt(result.payload.v.substring(2), 16), r: result.payload.r, s: result.payload.s }; let serializedTransaction = await utils.serializeTransaction( transaction, sig ); return serializedTransaction; } throw new Error(result.payload.error); }; sendTransaction = async (transaction) => { if (Promise.resolve(transaction.to) === transaction.to) { transaction.to = await transaction.to; } if (!transaction.value) { transaction.value = utils.parseEther('0.0'); } let signedTx = await this.sign(transaction); return this.provider.sendTransaction(signedTx); }; }