知乎专栏 | 多维度架构 |
解锁账号
> 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' ] } }