brief:
web3.js is a collection of libraries that allow you to interact with local or remote ethernet nodes using HTTP or IPC connections.
solc.js is a compiler for solidity. The official recommended compilation method.
Ganache CLI, part of the Truffle suite of Ethereum development tools, is the command-line version of Ganache , a personal blockchain developed for Ethereum.
Ganache CLI uses ethereumjs to simulate full client-side behavior and make developing Ethereum applications faster, easier, and more secure. It also includes all the popular RPC functions and features (like events) and can run deterministically to make development easy.
Note: testrpc has been deprecated and has been renamed Ganache CLI
This article environment:
node
macOs 10.13.4
web3.js 1.0.0-beta.34
furrow 0.4.22
Environment installation:
web3.js
npm install web3
ganache-cli
npm and ganache-cli
furrow
npm install groove
solidity code:
demo.sol
pragma solidity ^ 0.4.0; Calc contract { uint count; function add(uint a, uint b) returns(uint){ count++; return a + b; } function getCount() returns (uint){ return count; } }
Next, compile and publish through web3.js:
(1) Start Ganache
ganache-cli
This will list 10 pre-created accounts and 10 private keys
Create a local private chain address: localhost:8545
(2) Import the required modules:
web3.js
let Web3 = require('web3'); let furrow = require ("furrow"); let fs = require('fs');
(3) Instance the web3 object, and use solc to compile solidity to obtain the objects required for publishing
if(typeof web3 != 'undefined'){ web3=new Web3(web3.currentProvider); }else{ web3 = new Web3('http://localhost:8545'); } let source=fs.readFileSync("./demo.sol","utf8"); let cacl=solc.compile(source,1); let abi= JSON.parse(cacl.contracts[':Calc'].interface); let bytecode=cacl.contracts[':Calc'].bytecode;
Note: When solc is compiled, a colon will be added before the solidity class method.
(3) When publishing, an account is required. If the account is not activated, unlockAccount() is required to activate it.
web3.eth.getAccounts().then(data=>{ web3.eth.personal.unlockAccount(data[0]) })
Note: web3.eth.getAccounts() is an abnormal method, and data cannot be read by direct reading.
(4) Deploy, the contract address will be returned if the deployment is successful.
var rsContract=new web3.eth.Contract(abi).deploy({ data:'0x'+bytecode, //begins with 0x arguments:[], //pass the parameters of the constructor }).send({ from:data[0], gas:1500000, gasPrice:'3000000000000' },function(error,transactionHash){ console.log("send callback"); console.log("error:"+error); console.log("send transactionHash:"+transactionHash); }) .on('error', function(error){ console.error(error) }) .then(function(newContractInstance){ var newContractAddress=newContractInstance.options.address console.log("New contract address:"+newContractAddress); });
Notice:
1. The data in deploy must start with 0x.
2. from is the account address, not the contract address
3. When publishing, you need to pass in gas and gasPrice. If the gas is too small or too large, an error will be reported.
The default value of gas is 90000
The default value of gasPrice is 20000000000
(5) Calling the test
var MyContract = new web3.eth.Contract(abi,newContractAddress); MyContract.methods.add(1,3).call().then(console.log);
By passing in the abi and contract address, the contract method can be called through the call method of web3.js.
Summarize:
The attention of the text is the place where you step on the pit, I hope it can help everyone. The following is the complete example code:
let Web3 = require('web3'); let furrow = require ("furrow"); let fs = require('fs'); if(typeof web3 != 'undefined'){ web3=new Web3(web3.currentProvider); }else{ web3 = new Web3('http://localhost:8545'); } let source=fs.readFileSync("./demo.sol","utf8"); let cacl=solc.compile(source,1); let abi= JSON.parse(cacl.contracts[':Calc'].interface); let bytecode=cacl.contracts[':Calc'].bytecode; //contract binary code
web3.eth.getAccounts().then(data=>{ web3.eth.personal.unlockAccount(data[0]).then(openAccountState=>{ if(openAccountState){ console.log("Account opening status:"+openAccountState); var rsContract=new web3.eth.Contract(abi).deploy({ data:'0x'+bytecode, arguments:[], //pass the parameters of the constructor }).send({ from:data[0], gas:1500000, gasPrice:'3000000000000' },function(error,transactionHash){ console.log("send callback"); console.log("error:"+error); console.log("send transactionHash:"+transactionHash); }) .on('error', function(error){ console.error(error) }) // .on('transactionHash', function(transactionHash){ console.log("hash:",transactionHash)}) // .on('receipt', function(receipt){ // console.log(receipt.contractAddress) // contains the new contract address // }) //.on('confirmation', function(confirmationNumber, receipt){console.log("receipt,",receipt)}) .then(function(newContractInstance){ var newContractAddress=newContractInstance.options.address console.log("New contract address:"+newContractAddress); web3.eth.getBlockNumber().then(blockNum=>{ console.log("Current block number: "+blockNum); web3.eth.getBlock(blockNum).then(data=>{ console.log("Current block information: "); console.log(data); }) }); var MyContract = new web3.eth.Contract(abi,newContractAddress); MyContract.methods.add(1,3).call().then(console.log); }); } }); });
Quote:
http://web3js.readthedocs.io/en/1.0/web3.html#version
https://www.npmjs.com/package/ganache-cli
https://www.npmjs.com/package/solc