Tron(波场)实践篇

logo

参考文档

官方文档: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使用到的相关技术和插件:

安装钱包插件

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

合约部署

获取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. 部署合约失败

可能原因:

    1. 费用不足
    1. Solidity版本问题

目前部署时有提示:

Uncaught TypeError: Cannot read property 'Error'

从错误并不能看出什么,但是合约版本设置不正确会导致这个问题。

从合约例子来看,可以使用0.4.23版本

    1. 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. 如何计算energyBandWidth

计算工具:
https://tronstation.io/energycalc

7. 如何查询测试网的交易记录

查询网址:
https://shasta.tronscan.org

输入自己的账号地址即可

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容