1. 程式人生 > >【以太坊開發】如何開發一個編譯以太坊智能合約並且發布的平臺(二)

【以太坊開發】如何開發一個編譯以太坊智能合約並且發布的平臺(二)

vid new 有一個 tran slim ole https parse 交易

接上一章的內容,這篇介紹 deploy相關和結果演示。

deploy一個合約的過程中,需要計算發布的消耗和nonce值。

當進行每筆交易時,發送人設定Gas Limit 和Gas Price,將 Gas Limit*Gas Price ,就得到了ETH交易傭金的成本。

nonce:以太坊要求一個賬戶的每筆交易有一個連續的計數。每個節點將根據計數順序嚴格執行來自一個用戶的交易。

app.js中有下面兩個函數:

var web3 = new Web3(new Web3.providers.HttpProvider("http://localhost:8545"));

function etherSpentInPendingTransactions(address, callback)
{
    web3.currentProvider.sendAsync({
          method: 
"txpool_content", params: [], jsonrpc: "2.0", id: new Date().getTime() }, function (error, result) { console.log(result) if(typeof(result.result.pending)!="undefined" && result.result.pending) { if(result.result.pending[address]) {
var txns = result.result.pending[address]; var cost = new BigNumber(0); for(var txn in txns) { cost = cost.add((new BigNumber(parseInt(txns[txn].value))).add((new BigNumber(parseInt(txns[txn].gas))).mul(new BigNumber(parseInt(txns[txn].gasPrice))))); } callback(
null, web3.fromWei(cost, "ether")); } else { callback(null, "0"); } } else { callback(null, "0"); } }) }

上面函數的流程:

1 使用sendAsync異步調用JSON PRC,調用的方法是 :txpool_content,這個方法用於查詢交易池中待處理的交易,返回的結果屬性有pending和queqed。想了解這個函數可以查看:https://github.com/ethereum/go-ethereum/wiki/Management-APIs#txpool_content

2 通過返回結果的屬性 pending和賬戶的地址獲取所以交易:

var txns = result.result.pending[address];對交易的結果進行循環,累加每個交易的value和gas消耗,就是所有將要打包到下個塊的交易的總消耗。

在介紹一下getNonce函數:
function getNonce(address, callback)
{
    web3.eth.getTransactionCount(address, function(error, result){
        var txnsCount = result;

        web3.currentProvider.sendAsync({
              method: "txpool_content",
              params: [],
              jsonrpc: "2.0",
              id: new Date().getTime()
        }, function (error, result) {
            if(result.result.pending)
            {
                if(result.result.pending[address])
                {
                    txnsCount = txnsCount + Object.keys(result.result.pending[address]).length;
                    callback(null, txnsCount);
                }
                else
                {
                    callback(null, txnsCount);
                }
            }
            else
            {
                callback(null, txnsCount);
            }
        })
    })
}

eth中每個交易的nonce是累加的,它是把挖出的交易總數和待定的交易總數加起來得到的。

所以對於deploy函數來說,只需要利用上面兩個函數構造交易的消耗cost和nonce值然後調用sendRawTranstaction,當然還需要對交易簽署,需要提供秘鑰,所以界面設計也會需要賬戶秘鑰。代碼如下:

app.get("/deploy", function(req, res){
    var code = req.query.code;
    var arguments = JSON.parse(req.query.arguments);
    var address = req.query.address;

    var output = solc.compile(code, 1);

    var contracts = output.contracts;

    for(var contractName in contracts)
    {
        var abi = JSON.parse(contracts[contractName].interface);
        var byteCode = contracts[contractName].bytecode;

        var contract = web3.eth.contract(abi);

        var data = contract.new.getData.call(null, ...arguments, {
            data: byteCode
        });
        console.log(data);
        console.log(web3.eth.defaultAccount)
        var gasRequired = web3.eth.estimateGas({
            from:address,
            data: "0x" + data
        });

        web3.eth.getBalance(address, function(error, balance){
            var etherAvailable = web3.fromWei(balance, "ether");
            etherSpentInPendingTransactions(address, function(error, balance){
                etherAvailable = etherAvailable.sub(balance)
                if(etherAvailable.gte(web3.fromWei(new BigNumber(web3.eth.gasPrice).mul(gasRequired), "ether")))
                {
                    getNonce(address, function(error, nonce){
                        var rawTx = {
                            gasPrice: web3.toHex(web3.eth.gasPrice),
                            gasLimit: web3.toHex(gasRequired),
                            from: address,
                            nonce: web3.toHex(nonce),
                            data: "0x" + data
                        };

                        var privateKey = ethereumjsUtil.toBuffer(req.query.key, ‘hex‘);
                        var tx = new ethereumjsTx(rawTx);
                        tx.sign(privateKey);

                        web3.eth.sendRawTransaction("0x" + tx.serialize().toString(‘hex‘), function(err, hash) {
                            res.send({result: {
                                hash: hash,
                            }});
                        });
                    })
                }
                else
                {
                    res.send({error: "Insufficient Balance"});
                }
            })
        })

        break;
    }
})

到這裏基本流程已經很清晰了。具體的代碼可以到git上下載:https://github.com/figo050518/deployContract

配置app.js的web3地址。

進入項目根目錄 執行 npm install

node app.js 啟動前端服務。

我定義的端口是7070。下面是筆者執行的截圖:

技術分享圖片

到這裏就完成了一個編譯 部署合約的平臺,前端頁面沒有過多介紹,讀者可以看下源碼。

【以太坊開發】如何開發一個編譯以太坊智能合約並且發布的平臺(二)