Providers.js(最终要选择MetaMask还是 ethers 选择的提供者)
//Providers.js(最终要选择<a href="http://jinwei.fun/mdzztag/metamask" title="查看更多关于 MetaMask 的文章" target="_blank">MetaMask</a>还是 ethers 选择的提供者)
import { ethers } from 'ethers';
export default class Providers {
static is<a href="http://jinwei.fun/mdzztag/metamask" title="查看更多关于 MetaMask 的文章" target="_blank">MetaMask</a>Provider () {
return Boolean( window.web3 && window.web3.currentProvider );
}
static createProvider () {
if (Providers.is<a href="http://jinwei.fun/mdzztag/metamask" title="查看更多关于 MetaMask 的文章" target="_blank">MetaMask</a>Provider()) {
// 基于浏览器插件<a href="http://jinwei.fun/mdzztag/metamask" title="查看更多关于 MetaMask 的文章" target="_blank">MetaMask</a>插件节点
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,也有不同之处,一定要注意!