1. 程式人生 > >005 以太坊錢包開發-賬戶轉賬

005 以太坊錢包開發-賬戶轉賬

賬戶轉賬主要分為兩部分:
* 根據 privateKeykeystore 獲取賬戶私鑰及地址
* 通過私鑰簽名交易實現轉賬

通過 privateKey 獲取賬戶私鑰及地址

通過呼叫 web3.eth.accounts.privateKeyToAccount(privateKey) 就可以通過私鑰獲取相應的使用者資訊。

async getAccountByPrivatekey(ctx) {

        let returnResult = {
            code: 0,
            msg: '成功!',
            data: {}
} const data = ctx.request.body const privateKey = data.privateKey // 根據私鑰獲取使用者地址 const account = web3.eth.accounts.privateKeyToAccount(privateKey) // 查詢賬戶的餘額 const balance = await web3.eth.getBalance(account.address) const ethNum = web3.utils.fromWei(balance, 'ether') returnResult.data
.address = account.address
returnResult.data.privateKey = account.privateKey returnResult.data.balance = ethNum ctx.body = returnResult },

通過 keystore 獲取賬戶私鑰及地址

通過讀取 keystore 裡面儲存的JSON資料及密碼,通過呼叫 web3.eth.accounts.decrypt(keystoreStr,password) 可以獲取使用者的私鑰及地址。

async getAccountByKeystore(ctx) {

        let
returnResult = { code: 0, msg: '成功!', data: {} } const data = ctx.request.body; // 獲取上傳檔案 const keystoreFile = ctx.request.files.file const filePath = keystoreFile.path // 獲取 keystore 裡面的json字串 const keystoreStr = await fileUtil.readFile(filePath) // 獲取賬戶的密碼 const password = data.password // 獲取賬戶的資訊地址及私鑰 const account = web3.eth.accounts.decrypt(keystoreStr,password) const balance = await web3.eth.getBalance(account.address) const ethNum = web3.utils.fromWei(balance, 'ether') returnResult.data.address = account.address returnResult.data.privateKey = account.privateKey returnResult.data.balance = ethNum ctx.body = returnResult }

獲取 keystore 裡面的json字串,程式碼實現:

    readFile(fPath) {
        return new Promise(function (resolve, reject) {
            fs.readFile(fPath, 'utf-8', function(err, data) {
                if (err) reject(err);
                else resolve(data);
            });
        });
    }

上傳keystore檔案

頁面通過 ajax 上傳檔案,需要構建 FormData,頁面上傳檔案的js 程式碼如下

function unlockByKeystore() {
        var formData = new FormData();
        formData.append('file', $('#file')[0].files[0]);
        formData.append('password', $('#pwd').val());

        $.ajax({
            url: '/account/keystore',
            type: 'POST',
            cache: false,
            data: formData,
            processData: false,
            contentType: false
        }).done(function(res) {
            console.log(res)
            if (res.code == 0) {
                const result = res.data
                const address = result.address
                const balance = result.balance
                const privateKey = result.privateKey

                $("#balanceDiv").html(balance+' ETH')
                $("#addressDiv").html(address)
                $("#currAccount").val(address)
                $("#currAccountKey").val(privateKey)
            }
        }).fail(function(res) {});
    }

傳送交易

傳送交易主要分為以下幾點:
* 構建賬單資料
* 用私鑰對帳單資料進行簽名
* 通過web3.eth.sendSignedTransaction 傳送簽名的交易。

 async sendTransaction (ctx) {
        let returnResult = {
            code: 0,
            msg: '成功!',
            data: {}
        }

        const data = ctx.request.body

        const currentAccount = data.currAccount
        const privateKey = data.privateKey
        const reciptAccount = data.reciptAccount
        const txValue = data.txValue
        // 獲取指定賬戶地址的交易數
        let nonce = await web3.eth.getTransactionCount(currentAccount);

        // 將 ether 轉為 wei
        let value = web3.utils.toWei(txValue,'ether');

        // 獲取當前gasprice
        let gasPrice = await web3.eth.getGasPrice();

        // 以太幣轉賬引數    
        let txParms = {
            from: currentAccount,
            to: reciptAccount,
            nonce: nonce,
            gasPrice: gasPrice,
            data: '0x00', // 當使用代幣轉賬或者合約呼叫時
            value: value // value 是轉賬金額
        }
        // 獲取一下預估gas
        let gas = await web3.eth.estimateGas(txParms);
        txParms.gas = gas;
        // 用金鑰對賬單進行簽名
        let signTx = await web3.eth.accounts.signTransaction(txParms,privateKey)

        // 將簽過名的賬單進行傳送
        try {
            await web3.eth.sendSignedTransaction(signTx.rawTransaction, function(error, hash){
                if (!error) {
                    returnResult.data.hash = hash
                } else {
                    returnResult.code = "101"
                    returnResult.msg = "失敗!"
                    returnResult.data.error = error.message

                }
            })
        } catch (error) {
            console.log(error)
        }

        ctx.body = returnResult
    }

修改路由檔案

修改 routers/index.js 新增如下內容:

const transactionController = require("../controllers/transaction")

...

router.post('/account/privatekey',accountController.getAccountByPrivatekey)
router.post('/account/keystore',accountController.getAccountByKeystore)

router.get('/transaction', transactionController.transaction)
router.post('/transaction/send', transactionController.sendTransaction)

執行專案

啟動私鏈網路

使用 geth 啟動私有網路

$ geth --datadir ~/privatechain/data0 --networkid 110  --rpc console

開啟本地挖礦

miner.start()

啟動專案

$ cd myWallet
$ node index.js

原始碼下載

關注公眾號
關注公眾號