Tron(波场)实践篇
参考文档
官方文档:https://github.com/tronprotocol/Documentation/tree/master/%E4%B8%AD%E6%96%87%E6%96%87%E6%A1%A3
TronLink官方文档:https://developers.tron.network/docs/wallet-integration
TronWeb官方文档:https://developers.tron.network/docs/tron-web-intro
共识机制(POW、POS、DPOS、PBFT及POP)才是区块链的灵魂:https://baijiahao.baidu.com/s?id=1596184609683656426&wfr=spider&for=pc
依赖环境
由于Tron与eth相似,所以大部分可以参考Web3js。同时,会针对Tran的一些特点做出相对应的拓展。
接下来列出Tron使用到的相关技术和插件:
- 操作系统:Mac
- 编辑器:Vscode
- 开发语言:Typescript
- 合约语言:Solidity
- 第三方库:tron-web.js https://github.com/tronprotocol/tron-web
- Chrome插件-TronLink
安装钱包插件
1. 下载插件
下载地址:
https://chrome.google.com/webstore/detail/tronlink/ibnejdfjmmkpcnlpebklmnkoeoihofec
2. 设置密码、保存助记词
助记词最好保存到本地,忘了还可以凭借助记词找回账号。
账号信息点击Export
按钮即可看到密钥和助记词
3. 切换到设置界面,然后切换到测试网的配置
Settings -> Node selection -> Shasta Testnet
切换网络4. 获取trx
获取地址:
https://www.trongrid.io/shasta/#request
复制插件Accounts
界面的账号地址,然后粘贴到输入框,然后点击SUBMIT
按钮。
合约部署
获取TRX:https://www.trongrid.io/shasta/#request
查看账号信息:https://tronscan.org/#/account
API地址:https://api.shasta.trongrid.io
参考:https://github.com/Tronbox-boxes/metacoin-box
ps: 下载后需要删除
package-lock.json
文件
官方文档参考:https://developers.tron.network/docs/tron-box-contract-deployment
步骤:
1. 下载代码
git clone https://github.com/Tronbox-boxes/metacoin-box
2. 修改tronbox.js
配置
参数fee_limit
设置的值相对大一些,部署的时候就不会因为部署费用问题而导致部署失败。
...
consume_user_resource_percent: 0,
fee_limit: 1000000000,
...
3. 删除package-lock.json
文件,并初始化
若初始化失败,只可以执行npm install
多次,如果不行,可以打开vpn
cd metacoin-box/
rm package-lock.json
npm cache clean --force
npm install
4. 创建.env
文件
.env
文件:
PK=<你的密钥>
NODE=https://api.shasta.trongrid.io
NETWORK=shasta
5. 编译和部署
执行:
source .env
rm -rf ./build
tronbox compile
tronbox migrate --network $NETWORK
6. 调用合约
首先初始化:
npm install fs --save-dev
npm install tronweb --save-dev
编写index.js
:
const fs = require('fs');
const TronWeb = require('tronweb');
const HttpProvider = TronWeb.providers.HttpProvider;
const fullNode = new HttpProvider(process.env.NODE);
const solidityNode = new HttpProvider(process.env.NODE);
const eventServer = process.env.NODE;
const privateKey = process.env.PK;
const tronWeb = new TronWeb(
fullNode,
solidityNode,
eventServer,
privateKey
);
const contrctJson = JSON.parse(fs.readFileSync('./build/contracts/Migrations.json', 'utf8'));
const address = contrctJson['networks']['*'].address;
(async () => {
try {
let contract = await tronWeb.contract().at(address);
let param = {
feeLimit: 1000000000,
callValue: 0,
shouldPollResponse: true
};
let result = await contract.setCompleted(1).send(param);
console.log('result: ', result);
} catch(e){
console.error(e);
}
console.log('complement.');
})();
代码参考
nodejs - tronweb
const TronWeb = require('tronweb');
const HttpProvider = TronWeb.providers.HttpProvider;
const fullNode = new HttpProvider('https://api.trongrid.io');
const solidityNode = new HttpProvider('https://api.trongrid.io');
const eventServer = 'https://api.trongrid.io/';
const privateKey = 'da14...9f0d0';
const tronWeb = new TronWeb(
fullNode,
solidityNode,
eventServer,
privateKey
);
TronLink插件用法:
window.onload = function() {
if (!window.tronWeb) {
const HttpProvider = TronWeb.providers.HttpProvider;
const fullNode = new HttpProvider('https://api.trongrid.io');
const solidityNode = new HttpProvider('https://api.trongrid.io');
const eventServer = 'https://api.trongrid.io/';
const tronWeb = new TronWeb(
fullNode,
solidityNode,
eventServer,
);
window.tronWeb = tronWeb;
}
};
获取余额:
var balance = await tronWeb.trx.getBalance(userAddress);
发送交易:
tronWeb.transactionBuilder.sendTrx(
"TXPHCzmAmjyERtWES6EXTYqUPfJfQSzp2m",
100,
"TZDCUCy3Wn1HhJVseANdrhzqDYCTEue8xT"
);
发送Token:
tronWeb.transactionBuilder.sendToken(
"TXPHCzmAmjyERtWES6EXTYqUPfJfQSzp2m",
100,
"WIN",
"TCanwMYEkP1e6ZWSA2gdU6jDEm1TxWMYQF"
);
提现:
tronWeb.transactionBuilder.withdrawBlockRewards(
"TXPHCzmAmjyERtWES6EXTYqUPfJfQSzp2m"
);
获取账号信息:
tronWeb.trx.getAccount("TNDFkUNA2TukukC1Moeqj61pAS53NFchGF");
获取带宽:
tronWeb.trx.getBandwidth("TNDFkUNA2TukukC1Moeqj61pAS53NFchGF");
获取账号资源:
tronWeb.trx.getAccountResources("TXPHCzmAmjyERtWES6EXTYqUPfJfQSzp2m");
初始化合约对象:
const priceOracle =
tronWeb.contract(
contract["PriceOracle.sol:PriceOracle"].abi,
contract["PriceOracle.sol:PriceOracle"].address
);
添加监听事件:
priceOracle["PriceUpdate"]().watch((err, {result}) => {
if (err) return console.error('Failed to bind event listener:', err);
console.log(result);
});
转码与编码:
tronWeb.toUtf8("74657374")
result = "test"
tronWeb.toHex("test")
result = "74657374"
判断是否连接:
tronWeb.isConnected()
合约方法调用:
Use call to execute a pure
or view
smart contract method
let abi = [...];
let contract = await tronWeb.contract({abi});
let result = await contract.["合约方法名称"](<合约参数>).call();
Use send to execute a non-pure
or modify
smart contract method
let result = await contract.calculateValue(5).send({
feeLimit:10000,
callValue:10000,
shouldPollResponse:true
});
绑定合约:
async function triggercontract(){
let contractInstance = await tronWeb.contract().at("contract address in hex string");
//watch event if there is
contractInstance["event_name"]().watch(function(err, res) {
console.log("error " + err);
console.log('eventResult:',res);
});
let args = {
callValue:0,
shouldPollResponse: true
}
let result = await contractInstance.function_name(para1,para2,...).send(args);
}
遇到的问题
1. bytes32
编码问题
由于合约中部分字段类型为bytes32
,调用合约的时候直接报错了
解决方法:
调用Tronweb.sha3
即可将字符串转化为bytes32
类型。
let args = {
callValue:0,
shouldPollResponse: true
}
var contractInstance = tronWeb.contract().at(address);
contractInstance['funcName'](tronWeb.sha3(param1)).send(args);
2. 合约调用回滚
回滚的话只要是因为设置得参数不符合要求,要看具体情况,这里说其中的一种:
如果调用合约方法时需要支付TRX
,则需要设置callValue
。
加入调用合约需要支付0.0001 TRX
,调用方法为func
:
let args = {
callValue:tronWeb.toSun(0.0001),
shouldPollResponse: true,
feeLimit: 1000000000
}
var contractInstance = tronWeb.contract().at(address);
await contractInstance.func(tronWeb.sha3(param1)).send(args);
3. 部署合约失败
可能原因:
- 费用不足
-
Solidity
版本问题
-
目前部署时有提示:
Uncaught TypeError: Cannot read property 'Error'
从错误并不能看出什么,但是合约版本设置不正确会导致这个问题。
从合约例子来看,可以使用0.4.23
版本
-
Solidity
中的library
单独作为合约文件时出现的问题
-
Uncaught TypeError: Cannot read property 'foreach'
inline
修饰时,json
文件api
为空数组,将inline
转化为public
即可。
function sub(uint256 a, uint256 b) inline pure {
...
}
4. tronWeb
的API
地址:
https://developers.tron.network/v3.0/reference#wallets-accounts
只看到了英文的地址,并且官方API索引做得太差了,要找到这个地址还是比较困难的。
5. 关于编码转换
工具地址:
https://tronscan.org/#/tools/tron-convert-tool
选择Base58Check_HexString
,输入地址,然后点击Decode
或者Encode
代码中转换地址:
tronWeb.address.fromHex/tronWeb.address.toHex
6. 如何计算energy
和BandWidth
计算工具:
https://tronstation.io/energycalc
7. 如何查询测试网的交易记录
查询网址:
https://shasta.tronscan.org
输入自己的账号地址即可