【以太坊开发重磅推荐】基于ethers.js库同时兼容实现MetaMask钱包和独立的HDWallet钱包代码总结(真比web3.js强大不知道多少倍)

时间:2024-04-02 16:31:10

 ethers.js官方推荐的MetaMask操作:https://docs.ethers.io/ethers.js/html/cookbook-providers.html?highlight=metamask#metamask

【以太坊开发重磅推荐】基于ethers.js库同时兼容实现MetaMask钱包和独立的HDWallet钱包代码总结(真比web3.js强大不知道多少倍)

Providers.js(最终要选择MetaMask还是ethers选择的提供者) 

//Providers.js(最终要选择MetaMask还是ethers选择的提供者)

import { ethers } from 'ethers';

export default class Providers {

    static isMetaMaskProvider () {
        return Boolean( window.web3 && window.web3.currentProvider );
    }

    static createProvider () {
        if (Providers.isMetaMaskProvider()) {
            // 基于浏览器插件MetaMask插件节点
            return new ethers.providers.Web3Provider( window.web3.currentProvider );
        } else {
            // InfuraProvider基于infura.io账号链接后面的Token令牌和network【ropsten是3】
            // return new ethers.providers.InfuraProvider(
            //     3, 'ea9fcb17397d4e2994424dcd677d2a2f' );
            // 基于infura.io平台的ropsten测试节点(链接必须是https开头,否则会链接失败)
            // JsonRpcProvider是基于url来连接!
            return new ethers.providers.JsonRpcProvider(
                'https://ropsten.infura.io/v3/ea9fcb17397d4e2994424dcd677d2a2f');
        }
    }
}

 MetamaskWallet.js(MetaMask浏览器钱包)

//MetamaskWallet.js(MetaMask浏览器钱包)

import Providers from '@/modules/icowallet/Providers';

export default class MetamaskWallet {
    constructor () {
        this.initProvider();
        this.signer = this.provider.getSigner();
    }

    initProvider () {
        if (!Providers.isMetaMaskProvider()) {
            throw Error( '您正在使用当前离线钱包,暂时不能使用MetaMask钱包或先退出当前离线钱包!' );
        }
        this.provider = this.provider = Providers.createProvider();
        console.log( '您正在使用的是MetaMask浏览器钱包!!!' );
    }
}

/EthersWallet.js(ethers.js创建或导入钱包) 



import { Wallet } from 'ethers';
import Providers from './Providers.js';

export default class EthersWallet {
    constructor () {
        this.initProvider();
    }

    initProvider () {
        if (Providers.isMetaMaskProvider()) {
            throw Error( '浏览器已经提供了MetaMask钱包,不能再创建其他离线钱包了!' );
        }
        this.provider = this.provider = Providers.createProvider();
        console.log( '您正在使用的是离线钱包!!!' );
    }

    // 私钥生成钱包!
    generate_private_key_wallet ( private_key ) {
        return new Wallet( private_key, this.provider );
    }

    // 助记词生成钱包!
    generate_mnemonric_wallet ( mnemonric, path = `m/44'/60'/0'/0/0` ) {
        // 必须连接provider才是活跃钱包
        return Wallet.fromMnemonic( mnemonric, path ).connect( this.provider );
    }

    // keystore.json文件生成钱包
    async generate_keystore_wallet ( keystore_json_string, password, progressCallback = null ) {
        // 必须连接provider才是活跃钱包
        let off_wallet = await Wallet.fromEncryptedJson( keystore_json_string, password, progressCallback );
        return off_wallet.connect( this.provider );
    }

    // 随机创建一个钱包
    create_new_wallet () {
        return Wallet.createRandom().connect( this.provider );
    }
}


BassContract.js(所有的合约都继承于此,开始于合约交互) 

import EthersWallet from './EthersWallet';
import MetamaskWallet from './MetamaskWallet';
import Providers from '@/modules/icowallet/Providers';
import { ethers } from 'ethers';

export default class BassContract {
    constructor ( mnemonric ) {
        this.initWallet( mnemonric );
        // 务必注意:钱包是实现了Signer接口,所以active_wallet中的一些属性是signer没有的【比如address属性】
        // 所以在后续实例中,只能调用Signer共有的方法,以免出错!【获取地址用getAddress()方法】
        this.active_WalletOrSigner = this.signer || this.active_wallet;
    }

    initWallet ( mnemonric ) {
        if (Providers.isMetaMaskProvider()) {
            // 确定是MetaMask钱包
            this.signer = new MetamaskWallet().signer;
            console.log( 'MetaMask之this.signer', this.signer );
        } else {
            // 确定是Ethers自己创建或助记词导入的钱包!
            this.active_wallet = new EthersWallet().generate_mnemonric_wallet( mnemonric );
            console.log( 'ethers钱包之active_wallet接口', this.active_wallet );
        }
    }

    createContract ( abi_data, bytecode ) {
        return new ethers.ContractFactory( abi_data, bytecode, this.active_WalletOrSigner );
    }

    createContractInstance ( contract_address, abi_data ) {
        return new ethers.Contract( contract_address, abi_data, this.active_WalletOrSigner );
    }
}

 

最后:务必注意:this.active_WalletOrSigner要么是基于MetaMask的签名,要么是自定义的钱包,二者的属性和方法共用了Signer,也有不同之处,一定要注意!