知乎專欄 | 多維度架構 | | | 微信號 netkiller-ebook | | | QQ群:128659835 請註明“讀者” |
解鎖賬號
> personal.unlockAccount(eth.accounts[0], "netkiller",5000) true > miner.stop() true > miner.start(2)
編譯只能合約
solc --bin --abi --optimize -o ./output helloworld.sol
var Web3 = require("web3"); var fs = require ('fs'); var web3 = new Web3("http://localhost:8545"); var abi = JSON.parse(fs.readFileSync('output/Netkiller.abi')); var bin = '0x'+fs.readFileSync('output/Netkiller.bin').toString(); var myContract = new web3.eth.Contract(abi, null, { from: '0x5c18a33DF2cc41a1bedDC91133b8422e89f041B7' }); myContract.deploy({ data: bin }).send({ from: '0x5c18a33DF2cc41a1bedDC91133b8422e89f041B7', gas: 1500000, gasPrice: '30000000000000' }).then(function(newContractInstance){ console.log(newContractInstance.options.address) });
var fs = require('fs'); var net = require('net'); var Web3 = require("web3"); var fs = require ('fs'); var web3 = new Web3("http://localhost:8545"); var abi = JSON.parse(fs.readFileSync('NetkillerAdvancedToken.abi')); var bin = '0x'+fs.readFileSync('NetkillerAdvancedToken.bin').toString(); var address = '0x22c57F0537414FD95b9f0f08f1E51d8b96F14029'; var myContract = new web3.eth.Contract(abi, null, {from: address}); var options = { data: bin, arguments: [100000000, 'Netkiller Test Coin', 'NTC', 18] }; web3.eth.getGasPrice().then(function(gasPrice){ myContract.deploy(options).estimateGas(function(err, gas){ console.log(gas); web3.eth.personal.unlockAccount(req.body.from, req.body.password).then(function(error){ myContract.deploy(options).send({ from: address, gas: gas, gasPrice: gasPrice }).then(function(newContractInstance){ console.log(newContractInstance.options.address) }); }); }); });
部署智能合約,你可以使用錢包部署,也可以使用Truffer部署,不管你採用什麼方式,最終我們需要合約地址。
pragma solidity ^0.4.18; contract MetaCoin { mapping (address => uint) balances; event Transfer(address indexed _from, address indexed _to, uint256 _value); function MetaCoin() public { balances[tx.origin] = 10000; } function sendCoin(address receiver, uint amount) public returns(bool sufficient) { if (balances[msg.sender] < amount) return false; balances[msg.sender] -= amount; balances[receiver] += amount; Transfer(msg.sender, receiver, amount); return true; } function getBalanceInEth(address addr) public view returns(uint){ return convert(getBalance(addr),2); } function getBalance(address addr) public view returns(uint) { return balances[addr]; } function convert(uint amount,uint conversionRate) public pure returns (uint convertedAmount) { return amount * conversionRate; } }
這裡使用 Truffle 部署
neo@MacBook-Pro ~/ethereum/truffle % truffle compile --all Compiling ./contracts/MetaCoin.sol... Writing artifacts to ./build/contracts neo@MacBook-Pro ~/ethereum/truffle % truffle migrate --reset Using network 'development'. Running migration: 5_initial_migration.js Deploying MetaCoin... ... 0x9c006b398733a1d8679cbb00493ca75ff063f51c34521ae67a70523deeebf9c4 MetaCoin: 0xfb88de099e13c3ed21f80a7a1e49f8caecf10df6 Saving successful migration to network... ... 0x755a48ef99e488d7cf8460d718773a5afe73f760fb87697e51c40f3e6086f10b Saving artifacts...
得到合約地址 MetaCoin: 0xfb88de099e13c3ed21f80a7a1e49f8caecf10df6
編譯合約獲得 abi 介面
neo@MacBook-Pro ~/ethereum/truffle % solc --bin --abi --optimize -o ./output contracts/MetaCoin.sol neo@MacBook-Pro ~/ethereum/truffle % cat output/MetaCoin.abi [{"constant":true,"inputs":[{"name":"addr","type":"address"}],"name":"getBalanceInEth","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"receiver","type":"address"},{"name":"amount","type":"uint256"}],"name":"sendCoin","outputs":[{"name":"sufficient","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"amount","type":"uint256"},{"name":"conversionRate","type":"uint256"}],"name":"convert","outputs":[{"name":"convertedAmount","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"addr","type":"address"}],"name":"getBalance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":true,"name":"_to","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Transfer","type":"event"}]
var Web3 = require("web3"); // 創建web3對象 var web3 = new Web3("http://localhost:9545"); // 合約ABI var abi = [{"constant":true,"inputs":[{"name":"addr","type":"address"}],"name":"getBalanceInEth","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"receiver","type":"address"},{"name":"amount","type":"uint256"}],"name":"sendCoin","outputs":[{"name":"sufficient","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"amount","type":"uint256"},{"name":"conversionRate","type":"uint256"}],"name":"convert","outputs":[{"name":"convertedAmount","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"addr","type":"address"}],"name":"getBalance","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_from","type":"address"},{"indexed":true,"name":"_to","type":"address"},{"indexed":false,"name":"_value","type":"uint256"}],"name":"Transfer","type":"event"}]; // 合約地址 var address = "0xfb88de099e13c3ed21f80a7a1e49f8caecf10df6"; var tokenContract = new web3.eth.Contract(abi, address); // 調用函數 tokenContract.methods.getBalance("0x627306090abab3a6e1400e9345bc60c78a8bef57").call(null,function(error,result){ console.log("getBalance "+result); }); tokenContract.methods.getBalanceInEth("0x627306090abab3a6e1400e9345bc60c78a8bef57").call(null,function(error,result){ console.log("getBalanceInEth "+result); }); tokenContract.methods.getBalance("0xf17f52151ebef6c7334fad080c5704d77216b732").call(null,function(error,result){ console.log("getBalance 2 "+result); }); tokenContract.methods.sendCoin("0xf17f52151ebef6c7334fad080c5704d77216b732",387).send({from: '0x627306090abab3a6e1400e9345bc60c78a8bef57'}) .on('transactionHash', function(hash){ }).on('confirmation', function(confirmationNumber, receipt){ }).on('receipt', function(receipt){ // receipt example console.log(receipt); //查詢這裡可以得到結果 }).on('error', console.error); // If a out of gas error, the second parameter is the receipt.
運行結果
getBalance 10000 getBalanceInEth 20000 getBalance 2 0 { transactionHash: '0x0f7514413865219d70873634c00d1b4746c5faa436283786f5414b483b6d6333', transactionIndex: 0, blockHash: '0x5a7662d14f78b6b4d64b05c0ec1e1e641bd39440467f0476409f4e49c21f287a', blockNumber: 11, gasUsed: 51024, cumulativeGasUsed: 51024, contractAddress: null, status: 1, events: { Transfer: { logIndex: 0, transactionIndex: 0, transactionHash: '0x0f7514413865219d70873634c00d1b4746c5faa436283786f5414b483b6d6333', blockHash: '0x5a7662d14f78b6b4d64b05c0ec1e1e641bd39440467f0476409f4e49c21f287a', blockNumber: 11, address: '0xFB88dE099e13c3ED21F80a7a1E49f8CAEcF10df6', type: 'mined', id: 'log_8b567824', returnValues: [Result], event: 'Transfer', signature: '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef', raw: [Object] } } }
再次運行
getBalance 9613 getBalanceInEth 19226 getBalance 2 387 { transactionHash: '0x6d33487d9067494288190f7a64b3118c20560479e01afe8d53e37ca46a6001e4', transactionIndex: 0, blockHash: '0x28f6d416c68dbbd698d1a0b0fdc4ce842694d82318a38ea6395413fd15397642', blockNumber: 12, gasUsed: 36024, cumulativeGasUsed: 36024, contractAddress: null, status: 1, events: { Transfer: { logIndex: 0, transactionIndex: 0, transactionHash: '0x6d33487d9067494288190f7a64b3118c20560479e01afe8d53e37ca46a6001e4', blockHash: '0x28f6d416c68dbbd698d1a0b0fdc4ce842694d82318a38ea6395413fd15397642', blockNumber: 12, address: '0xFB88dE099e13c3ED21F80a7a1E49f8CAEcF10df6', type: 'mined', id: 'log_e5cfee46', returnValues: [Result], event: 'Transfer', signature: '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef', raw: [Object] } } }
第二次運行會打印出賬號2的餘額
代碼優化,由於開發階段 abi 介面經常變化,從 solc 編譯的abi 檔案中直接讀取最為方便。
const fs = require ('fs'); var Web3 = require("web3"); var web3 = new Web3("http://localhost:9545"); var abi = JSON.parse(fs.readFileSync('MetaCoin.abi')); var address = "0xfb88de099e13c3ed21f80a7a1e49f8caecf10df6"; var tokenContract = new web3.eth.Contract(abi, address); tokenContract.methods.getBalance("0x627306090abab3a6e1400e9345bc60c78a8bef57").call(null,function(error,result){ console.log("getBalance "+result); });
下面以ERC20代幣為例演示事件如何工作
neo@MacBook-Pro ~/ethereum/web3 % cat event.js fs = require('fs'); var net = require('net'); var Web3 = require('web3'); var web3 = new Web3('/Users/neo/Library/Ethereum/geth.ipc', net); console.log(web3.version) const abi = fs.readFileSync('output/TokenERC20.abi', 'utf-8'); const contractAddress = "0x70682386d0dE84B1e549DC3c4305CCB2D261b2a8"; const coinbase = "0xB94054c174995AE2A9E7fcf6c7924635FBa8ECF7"; const toAddress = "0xf56b81a2bcb964D2806071e9Be4289A5559BB0fA"; balanceWei = web3.eth.getBalance(coinbase); console.log(balanceWei); const contract = new web3.eth.Contract(JSON.parse(abi), contractAddress, { from: coinbase , gas: 100000}); contract.events.Transfer({ fromBlock: 0, toBlock:'latest' }, function(error, event){ console.log(event); }) .on('data', function(event){ console.log(event); // same results as the optional callback above }) .on('changed', function(event){ // remove event from local database }) .on('error', console.error);
運行後程序不會退出,會源源不斷的打印出每筆交易
neo@MacBook-Pro ~/ethereum/web3 % node event.js { address: '0x70682386d0dE84B1e549DC3c4305CCB2D261b2a8', blockNumber: 0, transactionHash: '0x0000000000000000000000000000000000000000000000000000000000000000', transactionIndex: 0, blockHash: '0x0000000000000000000000000000000000000000000000000000000000000000', logIndex: 0, removed: false, id: 'log_247b1779', returnValues: Result { '0': '0xB94054c174995AE2A9E7fcf6c7924635FBa8ECF7', '1': '0xf56b81a2bcb964D2806071e9Be4289A5559BB0fA', '2': '10000000', from: '0xB94054c174995AE2A9E7fcf6c7924635FBa8ECF7', to: '0xf56b81a2bcb964D2806071e9Be4289A5559BB0fA', value: '10000000' }, event: 'Transfer', signature: '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef', raw: { data: '0x0000000000000000000000000000000000000000000000000000000000989680', topics: [ '0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef', '0x000000000000000000000000b94054c174995ae2a9e7fcf6c7924635fba8ecf7', '0x000000000000000000000000f56b81a2bcb964d2806071e9be4289a5559bb0fa' ] } }