Trezor

如何為 Trezor 硬體錢包創建簽名者?

  • February 15, 2021

我正在嘗試為 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);
   };
}

引用自:https://ethereum.stackexchange.com/questions/63275