| 知乎專欄 | 多維度架構 | | | 微信號 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' ] } }