要用区块链,所以从新梳理了一下代码,把版本问题确认下,顺便开启区块链的技术主题;
下面说明下环境与代码。主要使用的Node.js编程环境与geth私有以太坊节点。本文不依赖框架,把基础技术说明白,再来说框架。
环境
- 主要包含:
- node: 12.16.1
- geth: 1.8.3
- solc: 0.6.4 (实际代码中我们使用的是0.5.0)
- web3: 1.2.6
node.js
C:\01works\08eth\ethnodes\codes>node --version
v12.16.1
geth
C:\01works\08eth\ethnodes\codes>geth version
Geth
Version: 1.8.3-stable
Git Commit: 329ac18ef617d0238f71637bffe78f028b0f13f7
Architecture: amd64
Protocol Versions: [63 62]
Network Id: 1
Go Version: go1.10
Operating System: windows
GOPATH=
GOROOT=C:\go
solc
C:\01works\08eth\ethnodes\codes>npm view solc
solc@0.6.4 | MIT | deps: 8 | versions: 70
Solidity compiler
https://github.com/ethereum/solc-js#readme
bin: solcjs
dist
.tarball: https://registry.npm.taobao.org/solc/download/solc-0.6.4.tgz
.shasum: 4b0f11fccd6f5ef9802c6bb1c007abb16881c2ca
dependencies:
command-exists: ^1.2.8 fs-extra: ^0.30.0 memorystream: ^0.3.1 semver: ^5.5.0
commander: 3.0.2 js-sha3: 0.8.0 require-from-string: ^2.0.0 tmp: 0.0.33
maintainers:
- chriseth <c@ethdev.com>
- d11e9 <d11e9@turkd.net>
dist-tags:
latest: 0.6.4 series0.4: 0.4.26 series0.5: 0.5.17
published 2 weeks ago by chriseth <chris@ethereum.org>
web3
C:\01works\08eth\ethnodes\codes>npm view web3
web3@1.2.6 | LGPL-3.0 | deps: 8 | versions: 117
Ethereum JavaScript API
https://github.com/ethereum/web3.js#readme
dist
.tarball: https://registry.npm.taobao.org/web3/download/web3-1.2.6.tgz
.shasum: c497dcb14cdd8d6d9fb6b445b3b68ff83f8ccf68
dependencies:
@types/node: ^12.6.1 web3-core: 1.2.6 web3-eth: 1.2.6 web3-shh: 1.2.6
web3-bzz: 1.2.6 web3-eth-personal: 1.2.6 web3-net: 1.2.6 web3-utils: 1.2.6
maintainers:
- frozeman <fabian@frozeman.de>
- nivida <samuel@ethereum.org>
dist-tags:
latest: 1.2.6 next: 2.0.0-alpha.1
published a month ago by nivida <samuel@ethereum.org>
代码实现
编译智能合约
- 使用编译后的两个结果:
- bin
- abi
var path = require('path');
var fs = require('fs');
var solc = require('solc');
// 获取智能合约的绝对路径
var contract_path = path.resolve('contract1_base.sol');
// console.log("合同路径: " + contract_path);
// 读取合约内容
var contract_source = fs.readFileSync(contract_path, 'utf-8');
// console.log(contract_source)
// 编译
var contract_json = JSON.stringify({
language: 'Solidity',
sources: {
'contract1_base.sol': { // 指明编译的文件名
content: contract_source, // solidity 源代码
},
},
settings: { // 自定义编译输出的格式。以下选择输出全部结果。
outputSelection: {
'*': {
'*': [ '*' ]
}
}
},
});
var contract_compiled = solc.compile(contract_json);
// console.log(contract_compiled);
// 注意: solc的版本。
var contract_obj = JSON.parse(contract_compiled);
var ou = contract_obj.contracts['contract1_base.sol']['Contrac_Base'];
// ABI
console.log(ou.abi);
// BIN
console.log(ou.evm.bytecode.object);
部署智能合约
- 记录一下合同地址,下面查询使用
const path = require('path');
const fs = require('fs');
const solc = require('solc');
const Web3 = require("web3");
const web3 = new Web3();
web3.setProvider(new Web3.providers.HttpProvider("http://localhost:9999"));
// 获取智能合约的绝对路径
var contract_path = path.resolve('contract1_base.sol');
// console.log("合同路径: " + contract_path);
// 读取合约内容
var contract_source = fs.readFileSync(contract_path, 'utf-8');
// console.log(contract_source)
// 编译
var contract_json = JSON.stringify({
language: 'Solidity',
sources: {
'contract1_base.sol': { // 指明编译的文件名
content: contract_source, // solidity 源代码
},
},
settings: { // 自定义编译输出的格式。以下选择输出全部结果。
outputSelection: {
'*': {
'*': [ '*' ]
}
}
},
});
var contract_compiled = solc.compile(contract_json);
// console.log(contract_compiled);
// 注意: solc的版本。
var contract_obj = JSON.parse(contract_compiled);
var ou = contract_obj.contracts['contract1_base.sol']['Contrac_Base'];
var abi = ou.abi;
var bytecode = ou.evm.bytecode.object;
// 部署合约前的准备
web3.eth.getAccounts().then(function(accouts_){
accounts = accouts_;
new web3.eth.Contract(abi).deploy(
{
data: '0x' + bytecode, // 需要注意 字节码需要添加 '0x' 不然会有各种错误
arguments: [] // 此处是参数列表
}
).send(
{
from: accounts[0],
gas: '4712388',
gasPrice: '1000000'
}
)
.on(
'transactionHash',
function (hash) {
console.log("交易Hash:" + hash)
}
)
.on(
'receipt',
function (receipt) {
console.log("交易收据:" , receipt);
}
)
// .on( // 不注释会抑制调用
// 'confirmation',
// function (confirmationNumber, receipt) {
// console.log( "交易确认:" + confirmationNumber);
// }
// )
.on(
'error',
function(error){
console.log("错误:" + error);
}
)
.then(
function(newContractInstance){ // 部署成功,返回一个新的合同实例,包含合同的部署地址
console.log("合同地址:" + newContractInstance.options.address)
}
)
});
查询智能合约
- 使用call,不修改区块数据,所以不需要发起一个交易执行。
const path = require('path');
const fs = require('fs');
const solc = require('solc');
const Web3 = require("web3");
const web3 = new Web3();
web3.setProvider(new Web3.providers.HttpProvider("http://localhost:9999"));
// 获取智能合约的绝对路径
var contract_path = path.resolve('contract1_base.sol');
// console.log("合同路径: " + contract_path);
// 读取合约内容
var contract_source = fs.readFileSync(contract_path, 'utf-8');
// console.log(contract_source)
// 编译
var contract_json = JSON.stringify({
language: 'Solidity',
sources: {
'contract1_base.sol': { // 指明编译的文件名
content: contract_source, // solidity 源代码
},
},
settings: { // 自定义编译输出的格式。以下选择输出全部结果。
outputSelection: {
'*': {
'*': [ '*' ]
}
}
},
});
var contract_compiled = solc.compile(contract_json);
// console.log(contract_compiled);
// 注意: solc的版本。
var contract_obj = JSON.parse(contract_compiled);
var ou = contract_obj.contracts['contract1_base.sol']['Contrac_Base'];
var abi = ou.abi;
var bytecode = ou.evm.bytecode.object;
// 部署合约前的准备(这个地址来自部署合约程序的输出,也可以使用api获取。
contract_addr = '0x44823446fb1daF884Bf4C3a92F86Ece06F87326D';
web3.eth.getAccounts().then(function(accouts_){
accounts = accouts_;
new web3.eth.Contract(abi, contract_addr)
.methods
.getAge()
.call(
{
from: accounts[0]
}
)
.then(
function(result){
console.log(result);
}
);
});
执行智能合约交易
- 需要修该数据,就必须发起一个交易。
const path = require('path');
const fs = require('fs');
const solc = require('solc');
const Web3 = require("web3");
const web3 = new Web3();
web3.setProvider(new Web3.providers.HttpProvider("http://localhost:9999"));
// 获取智能合约的绝对路径
var contract_path = path.resolve('contract1_base.sol');
// console.log("合同路径: " + contract_path);
// 读取合约内容
var contract_source = fs.readFileSync(contract_path, 'utf-8');
// console.log(contract_source)
// 编译
var contract_json = JSON.stringify({
language: 'Solidity',
sources: {
'contract1_base.sol': { // 指明编译的文件名
content: contract_source, // solidity 源代码
},
},
settings: { // 自定义编译输出的格式。以下选择输出全部结果。
outputSelection: {
'*': {
'*': [ '*' ]
}
}
},
});
var contract_compiled = solc.compile(contract_json);
// console.log(contract_compiled);
// 注意: solc的版本。
var contract_obj = JSON.parse(contract_compiled);
var ou = contract_obj.contracts['contract1_base.sol']['Contrac_Base'];
var abi = ou.abi;
var bytecode = ou.evm.bytecode.object;
// 部署合约前的准备
contract_addr = '0x44823446fb1daF884Bf4C3a92F86Ece06F87326D';
web3.eth.getAccounts().then(function(accouts_){
accounts = accouts_;
new web3.eth.Contract(abi, contract_addr)
.methods
.setAge(128)
.send(
{
from: accounts[0],
gas: '4712388',
gasPrice: '1000000'
}
)
.on(
'transactionHash',
function (hash) {
console.log("交易Hash:" + hash);
}
)
.on(
'receipt',
function (receipt) {
console.log("交易收据:" , receipt);
}
)
.on(
'error',
function(error){
console.log("错误:" + error);
}
)
.then(
function(contract_instance){ // 部署成功,返回一个新的合同实例,包含合同的部署地址
// 只有调用deploy函数后,才返回合同实例。合同交易是不会返回的。
console.log("合同地址:" + contract_instance)
var keys = Object.getOwnPropertyNames(contract_instance);
console.log(keys);
for(var k in contract_instance){
console.log(k + ":" + contract_instance[k]);
}
new web3.eth.Contract(abi, contract_addr)
.methods.getAge()
.call(
{
from: accounts[0]
}
)
.then(
function(result){
console.log(result);
}
)
}
)
});
- 说明:
- 后面几个代码中的合约地址,在部署的时候得到的。可以使用代码或者geth控制终端得到。
网友评论