首先放上官方API:https://web3js.readthedocs.io/en/1.0/index.html
思路:
1、先用truffle创建一个以太坊智能合约项目,部署在ganache测试网络。
2、用npm创建另外一个项目,使用web3和智能合约交互
创建truffle项目:
1、mkdir truffle_test & cd truffle test
2、初始化:truffle init
3、编写智能合约,在contracts文件夹下新建智能合约:Data.sol:(功能:存、取一个字符串)
pragma solidity ^0.4.17;
contract Data{
string public data;
function Data()public{
data = "init data";
}
function setData(string str) public payable{
data = str;
}
function getData() public view returns (string) {
return data;
}
}
4、编译:truffle compile
5、部署在测试网络上
(1)打开ganache
(2)修改migrations文件夹下的部署配置
var Migrations = artifacts.require("./Migrations.sol");
var Data = artifacts.require("./Data.sol");
module.exports = function(deployer) {
deployer.deploy(Migrations);
deployer.deploy(Data);
};
(3)修改truffle.js配置文件,添加连接网络信息:
module.exports = {
networks: {
development: {
host: "localhost",
port: 7545,
network_id: "*"
}
}
};
(4)执行truffle migrate(如果执行失败,可以试试truffle migrate --reset)
现在truffle项目已经做好,接下来使用web3和智能合约进行交互。
web3与智能合约交互
添加web3到项目中:
1、mkdir web3test & cd web3test
2、初始化 npm init
3、下载web3.js到项目中:
npm install web3 --save
以上命令会将web3.js下载到web3test/node_modules目录下,其中--save
参数会web3.js添加到package.json配置文件中。
4、创建web3对象
要使用web3.js与区块链交互,需要先创建web3对象,然后连接到以太坊节点。
在web3test目录下新建index.js文件,在其中输入以下代码:
var Web3 = require("web3");
var web3 = new Web3();
web3.setProvider(new Web3.providers.HttpProvider("http://localhost:7545"));
5、获取已部署的智能合约实例
var abi = [{"constant":true,"inputs":[],"name":"getData","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"str","type":"string"}],"name":"setData","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"data","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"}];
var address = '0x345ca3e014aaf5dca488057592ee47305d9b3e10';
var data = new web3.eth.Contract(abi,address);
其中abi是truffle项目中build目录下Data.json文件中的abi,复制过来即可。address是合约部署的地址。通过abi和合约地址就可以获取合约的实例data。下面就可以通过data来调用合约里面的内容了。
6、调用合约函数
data.methods.getData().call(null,function(error, result){
console.log("the data:"+result);
});
data.methods.setData("hello blockchain").send({from: '0x627306090abaB3A6e1400e9345bC60c78a8BEf57'}).on('transactionHash', function(hash){
console.log("hash:", hash);
data.methods.getData().call(null,function(error, result){
console.log("the data:"+result);
});
});
call()和send()的作用可以从官方文档中查看。send里面的from是发送交易的地址,这里我写的是ganache中第0个账户的地址。
以上的执行结果是:
the data:init data
the data:hello blockchain
hash: 0x86a8674614c5ac4772cdf3aba6bf2786d366460bb524e49b8012b5dbe89b64dd
参考文章:http://dophin459.coding.me/posts/9cc80f82/
==================进阶:web3+ipfs=========================
思路:
由于往区块链存储数据是有代价,所以不应该将大量的数据上传。可以将数据存储在ipfs上面得到一个hash值,将hash存储在区块链上,大大减少存储量。
1、存数据:从本地获取文件,上传到ipfs上面,得到文件的hash值,将hash值存储在区块链上
2、取数据:从区块链获取hash值,根据hash从ipfs上读取数据,保存在本地
项目流程:
mkdir test_eth_ipfs & cd test_eth_ipfs
truffle项目创建和上面例子一样,重新执行一遍即可。
还是在test_eth_ipfs这个目录中继续操作:
1、npm init
2、导入web3接口(使用web30.20.1版本,因为在使用1.0版本是有些错误一直调不出来,干脆还是用0.20版本吧)
npm install [email protected] --save
3、导入ipfs接口
npm install ipfs-api --save
4、创建一个对ipfs操作的js文件,方便下面操作
const ipfsAPI = require('ipfs-api');
const ipfs = ipfsAPI({host: 'localhost', port:'5001', protocal: 'http'});
exports.add = function(buffer){
return new Promise(function(resolve, reject){
try {
ipfs.add(buffer, function(err, files){
if(err || typeof files == 'undefined'){
reject(err);
}else{
resolve(files[0].hash);
}
})
} catch (e) {
reject(e);
}
})
}
exports.get = function(hash){
return new Promise(function(resolve, reject){
try {
ipfs.get(hash, function(err, files){
if(err || typeof files == 'undefined'){
reject(err);
}else{
resolve(files[0].content);
}
})
} catch (e) {
reject(e);
}
})
}
5、创建index.js文件,实现智能合约和web3+ipfs交互
var ipfsFile = require("./ipfsFile");
var fs = require('fs');
//var data = artifacts.require("dataOperator");
var contract = require('truffle-contract');
var Web3 = require('web3');
var web3 = new Web3();
var provider = new Web3.providers.HttpProvider('http://localhost:7545');
web3.setProvider(provider);
let addPath = './storage/add/file1';
let getPath = './storage/get/file2';
let buff = fs.readFileSync(addPath);
var contractJSON = JSON.parse(fs.readFileSync("./build/contracts/dataOperator.json"));
var contract_abi = contractJSON.abi;
var data = contract(contractJSON);
data.setProvider(provider);
var data_instance;
var eth_accounts;
web3.eth.getAccounts(function(err, accounts){
if(err){
console.log(err);
}
eth_accounts = accounts;
data.deployed()
.then(function(instance){
data_instance = instance;
}).then(function(){
return ipfsFile.add(buff);
}).then(function(hash){
console.log('hash1', hash);
data_instance.setData(hash,{from:eth_accounts[0]});
}).then(function(){
return data_instance.getData();
}).then(function(hash){
console.log('hash2',hash);
return ipfsFile.get(hash);
}).then(function(data_info){
fs.writeFileSync(getPath, data_info);
console.log('data_info:',data_info.toString('utf-8'));
}).catch(function(err){
console.log(err);
})
})
6、运行:
ipfs daemon(启动ipfs)
node index
console中会输出两个相同的hash值,然后/storage/get中会出现一个与/storage/set中一样的文件