DApp创建本地钱包并实现签名转账(BSC,Polygon,ETH)
1. 项目准备
- 安装ether.js
npm install --save ethers
引入ether.js:的三种方法
- es3:
var ethers = require(‘ethers’);
- es5/es6
const ethers = require(‘ethers’);
- javascript/typescript es6
import ethers from ‘ethers’;
2. 钱包相关概念
这里默认为你已经了解 地址、密码、私钥、助记词、Keystore 之间的关系,所以不再过多介绍,只列出他们之间的关联:
地址 = 银行卡号
密码 = 银行卡密码
私钥 = 银行卡号+密码
助记词 = 银行卡号+密码
Keystore = 加密私钥
Keystore + 密码 = 私钥
3.随机创建一个钱包
使用到的ethers的Wallet类:
ethers.Wallet.createRandom()
createRandom 返回一个带有随机私钥的新钱包,由加密安全的熵源生成。如果当前环境没有安全的熵源,则会抛出错误。
使用此方法创建的钱包将具有助记词
createNewWallet() {
let walletRandom = ethers.Wallet.createRandom()
// 钱包助记词对象
let mnemonic = walletRandom.mnemonic
//钱包助记词单词
let phrase = mnemonic.phrase
//path: "m/44'/60'/0'/0/0",
let path = mnemonic.path
//钱包地址
let address = walletRandom.address
//钱包公钥
let publicKey = walletRandom.publicKey
//钱包私钥
let privateKey = walletRandom.privateKey
//通过用户设置的密码生成keystore文件
let password = "123456"
walletRandom.encrypt(password).then((keystory_string) => {
let keystory_json = JSON.parse(keystory_string)
//钱包的keystore字符串
this.keystory = keystory_string
console.log(keystory_json)
})
//可以通过AES对称加密把钱包的助记词加密存储在本地
let encryptPassword = "1234qwer"
let encryptedPhrase = encryption(phrase, encryptPassword)
console.log('加密后的助记词:', encryptedPhrase)
let decryptedPhrase = decryption(encryptedPhrase, encryptPassword)
console.log('解密后的助记词:', decryptedPhrase)
}
import * as CryptoJS from 'crypto-js'
//数据对称加密
function encryption(data, password) {
let encrypted = CryptoJS.AES.encrypt(data, password);
return encrypted.toString()
}
//数据解密
function decryption(encrypted, password) {
let decrypted = CryptoJS.AES.decrypt(encrypted, password);
return decrypted.toString(CryptoJS.enc.Utf8);
}
4.根据助记词导入钱包
ethers.Wallet.fromMnemonic( mnemonic [ , path , [ wordlist ] ] ) ⇒ Wallet
从助记短语中创建实例。
如果没有指定path,则使用以太坊的默认path路径(如m/44’/60’/0’/0/0).
如果不指定wordlist,则使用English Wordlist。
async createWalletByPhrase() {
//默认路径
let path = ethers.utils.defaultPath
//要导入的钱包助记词
let phrase =
'able fee damage express dilemma visit fine claim similar attract awkward market'
let mnemonic = ethers.Wallet.fromMnemonic(phrase)
//钱包私钥
let privateKey = mnemonic.privateKey
//通过钱包私钥创建钱包实例
let wallet = new ethers.Wallet(privateKey)
//钱包公钥
let publicKey = wallet.publicKey
//钱包地址
let address = wallet.address
//通过用户设置的密码生成keystore文件
let password = "123456"
wallet.encrypt(password).then((keystory_string) => {
let keystory_json = JSON.parse(keystory_string)
let keystory = keystory_string
console.log(keystory_json)
})
}
5.根据keystore导入钱包
ethers.Wallet.fromEncryptedJson( json , password [ , progress ] ) ⇒ Promise< Wallet >source
从加密的JSON钱包创建一个实例。
如果提供了进度,它将在解密期间被调用,其值介于0到1之间,表示一个完成进度。
createWalletByKeystory() {
//要导入的钱包keystore
let keystory =
'{"address":"df9e902814baba3ddc6b4a1ac9db11bc79eda07f","id":"60db3db5-ef64-400a-b25e-3615a9bdfa24","version":3,"crypto":{"cipher":"aes-128-ctr","cipherparams":{"iv":"f4c7ece791d112dc408537203aa2bb10"},"ciphertext":"acba3333e3d7078e2186ebd561c28bf0e4a8c105e4b1eec40bec20616441cc31","kdf":"scrypt","kdfparams":{"salt":"f1e8acd43868559c1ecda1c9b31489efd12f6c7c9302710b957a3b779dd6ec54","n":131072,"dklen":32,"p":1,"r":8},"mac":"e466473ae761f98b1f26354e27305ce23e41b5d5c8a5674b65675bdfbf848718"},"x-ethers":{"client":"ethers.js","gethFilename":"UTC--2023-03-25T03-36-38.0Z--df9e902814baba3ddc6b4a1ac9db11bc79eda07f","mnemonicCounter":"e4482220566b9a9f9d821c1352d1708f","mnemonicCiphertext":"7357682acae64479641611e17e1c6473","path":"m/44'/60'/0'/0/0","locale":"en","version":"0.1"}}'
//改keystore创建时使用的密码
let password = "123456"
ethers.Wallet.fromEncryptedJson(keystory, password).then((wallet) => {
console.log('wallet实例:', wallet)
//钱包地址
let address = wallet.address
//钱包公钥
let publicKey = wallet.publicKey
//钱包私钥
let privateKey = wallet.privateKey
//默认的路径
let path = ethers.utils.defaultPath
})
}
6.签名转账
async sendTransaction() {
//ETH
// let network = 'goerli'
// let contractAddress = ''
//Polygon
// let network = 'maticmum'
// let contractAddress = ''
//BSC
// let network = 'https://bsc-dataseed.binance.org/'
let network = 'https://data-seed-prebsc-1-s1.binance.org:8545/'
let contractAddress = ''
//使用Infura作为RPC使用
//let projectId = ''
// let provider = new ethers.providers.InfuraProvider(network, projectId)
let provider = new ethers.providers.JsonRpcProvider(network);
let privateKey = '0x0fb9146e20a3bd3497b47de967316c8aa7f83818ddc62429a24774f0df1f8065'
let wallet = new ethers.Wallet(privateKey, provider)
// let balance = await wallet.getBalance('latest')
// console.log('余额:', balance)
// console.log('余额:', ethers.utils.formatEther(balance))
// console.log(await wallet.getChainId())
// return
/**
//ETH转账
let tx = {
to: '',
value: ethers.utils.parseEther('0.001'),
chainId: ethers.BigNumber.from('5').toHexString()
}
let res = await wallet.sendTransaction(tx)
console.log(res)
*/
/**
*
//使用signers进行ERC20转账
let contract = new ethers.Contract(contractAddress, GBK.abi, wallet)
console.log(contract)
let balance = await contract.balanceOf(wallet.address)
balance = ethers.utils.formatEther(balance)
console.log(balance)
let res = await contract.transfer('', ethers.utils.parseUnits('1'))
console.log(res)
*/
}