Alaya JS SDK 快速入门教程(三):智能合约 | 技术云图

fffmCQ.jpg

Alaya JS SDK 快速入门教程(三):智能合约 | 技术云图

本教程从alaya js sdk的安装开始,分别讲述了连接Alaya网络并执行基本查询、转账及签名操作及智能合约交互的相关内容。本教程力求翔实地展现了Alaya Js Sdk的使用方法,让开发者能够快速入门Alaya Js Sdk。

智能合约

在明白了如何进行签名之后,我们就可以再深一步地了解如何使用智能合约了。

注:这里并不讨论如何编写智能合约,只讨论如何使用js sdk进行智能合约的相关操作。本教程以solidity合约为例。

在使用alaya sdk与智能合约产生交互之前,我们先明确一点,那就是alaya sdk能做什么?

alaya sdk可以编译智能合约吗?不能,现阶段,alaya的智能合约可以通过使用alaya-truffle,PlatONStudio来进行编译,具体请参照:EVM智能合约 · Alaya

alaya sdk可以部署智能合约吗?可以!后面我们就细讲一下如何用alaya sdk部署智能合约。

alaya sdk可以与智能合约交互吗?当然可以!这个是alaya sdk的主要功能之一。

智能合约部署

在智能合约部署之前,需要对智能合约进行编译,具体的编译方式可以参照:

https://alaya.network/alaya-devdocs/zh-CN/Solidity_Getting_started#编译helloworld合约

同时经过测试,使用下面的链接进行编译:

https://remix.ethereum.org/

在alaya网络上也能正常运行。编译后会获得abi和bytecode,这些内容在后面的代码中会用到。由于本教程覆盖范围问题,所以不对编译过程作更详细的介绍,本教程中使用[EVM智能合约·Alaya](/alaya-devdocs/zh-CN/Solidity_Getting_started#创建helloworld合约)此创建的HelloWorld合约。

编译后的两个变量分别如下:

letbytecode="0x608060405234801561001057600080fd5b5061036b806100206000396000f3fe608060405234801561001057600080fd5b50600436106100365760003560e01c806317d7de7c1461003b578063c47f0027146100b8575b600080fd5b61004361015e565b6040805160208082528351818301528351919283929083019185019080838360005b8381101561007d578181015183820152602001610065565b50505050905090810190601f1680156100aa5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b610043600480360360208110156100ce57600080fd5b8101906020810181356401000000008111156100e957600080fd5b8201836020820111156100fb57600080fd5b8035906020019184600183028401116401000000008311171561011d57600080fd5b91908080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152509295506101f5945050505050565b60008054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156101ea5780601f106101bf576101008083540402835291602001916101ea565b820191906000526020600020905b8154815290600101906020018083116101cd57829003601f168201915b505050505090505b90565b805160609061020b90600090602085019061029e565b506000805460408051602060026001851615610100026000190190941693909304601f810184900484028201840190925281815292918301828280156102925780601f1061026757610100808354040283529160200191610292565b820191906000526020600020905b81548152906001019060200180831161027557829003601f168201915b50505050509050919050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106102df57805160ff191683800117855561030c565b8280016001018555821561030c579182015b8281111561030c5782518255916020019190600101906102f1565b5061031892915061031c565b5090565b6101f291905b80821115610318576000815560010161032256fea265627a7a72315820087868e5d428c0270af7145556516942e16a5db5ec467f7dcdca4cfa9ec099bc64736f6c63430005110032";letabi=[{"constant":false,"inputs":[{"internalType":"string","name":"_name","type":"string"}],"name":"setName","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"getName","outputs":[{"internalType":"string","name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"}];

为了缩减代码长度,后续代码中可能会对直接使用这两个变量而不再另外对其进行赋值。

智能合约部署操作其实非常简单,和之前的转账操作非常类似,也遵循生成交易->签名->发送交易的顺序。下面我们就直接看一下代码吧!

varWeb3a=require("web3");varAlayaAccounts=require("web3/packages/web3-eth-accounts");asyncfunctionmain(){letweb3a=newWeb3a('http://47.241.91.2:6789');letbytecode="";//!!!!将主网的私钥写到代码上并分享给别人是非常危险的操作!!!!//addressfortheprivatekeybelow:atp1sznvsju6gjy3kmgnfgm526jf6e8x83twuctefhvarprivateKey="0x5ae02064df442340f861136acbfc4bd62b3d48393903bd6aac77ce0e7aaa9e5e";varchainId=201030;//201018formainnetvaract=newAlayaAccounts(web3a.currentProvider,"atp");act=act.privateKeyToAccount(privateKey);letfrom=act.address;letnonce=web3a.utils.numberToHex(awaitweb3a.platon.getTransactionCount(from));letgasPrice=awaitweb3a.platon.getGasPrice();lettx={from:from,chainId:chainId,gasPrice:gasPrice,nonce:nonce,data:bytecode};//评估此交易所需要的交易费用letgas=awaitweb3a.platon.estimateGas(tx);tx.gas=gas;//签名交易letsignTx=awaitact.signTransaction(tx);//发送交易letreceipt=awaitweb3a.platon.sendSignedTransaction(signTx.rawTransaction);console.log("Thereceiptofthetransactionis:"+JSON.stringify(receipt));}main();

注意:上述代码不可直接运行,代码中使用了bytecode变量但未对其进行赋值,需要对bytecode变量进行赋值后使用。

是不是对这个交易非常熟悉,和之前转账交易最大两点不同是:

没有了to和value两个值

增加了data值,data中存储bytecode

与智能合约交互

与智能合约的交互是一种经常会遇到的操作,但实际上网络上能将其说明白的,特别是在使用公共节点时将其说明白的教程并不多。我们在看其他教程会产生一种疑问,那就是我不需要privateKey就可以与智能合约进行交互吗?

这个问题的答案其实是不确定的,由于我们与智能合约的交互通常有两种方式,一是call,二是send。

| call

有时,我们只需要从区块链上查询一些数据,并不会改变区块链的状态,这时我们就可以使用call的方式来与区块链交互。由于我们没有对区块链进行改变,所以不需要付gas,也不需要私钥签名,所以使用起来非常方便。

varWeb3a=require("web3");asyncfunctionmain(){letweb3a=newWeb3a('http://47.241.91.2:6789');//我已经部署好的智能合约的地址letcontractAddress="atp1pcvx85klajfw9mvy3tf07acmqxaek5nanuy5t6";console.log("contractaddress:"+contractAddress);letabi=[];//构建一个合约对象letcontract=newweb3a.platon.Contract(abi,contractAddress);letname=awaitcontract.methods.getName().call();console.log("namebeforechange:"+name);}main();

注意:上述代码不可直接运行,代码中使用了abi变量但未对其进行赋值,需要对abi变量进行赋值后使用。

大家可以看到,call的形式非常简单,甚至都不需要私钥,就能直接从区块链上查询信息。如果你使用我的合约地址,你会从区块链上查询到name为rileyge,如果你使用自己新部署的合约,那么name为空。

| send

注意,send只是一种叫法,实际上后面你会看到,在下面的代码中我们并没有用到send函数。什么时候要采用send的方式与区块链进行交互呢?简单地说就是当操作需要改变区块链的状态时,就需要采用send的方式来与区块链进行交互。此时必须对交易进行签名并付gas。

如果你在其他地方看到类似的教程,你会发现他们使用的都是解锁的账号。根据我们前面所说,解锁账号一般只在私有节点或者有相关钱包时使用,而一般的nodejs程序是不会使用钱包的(当然也可以使用),那么如何使用没有解锁的账号与智能合约以send的方式交互呢?

还是之前的套路:生成交易->签名->发送交易。交易如何生成是此交易重点。

varWeb3a=require("web3");varAlayaAccounts=require("web3/packages/web3-eth-accounts");asyncfunctionmain(){letweb3a=newWeb3a('http://47.241.91.2:6789');//!!!!将主网的私钥写到代码上并分享给别人是非常危险的操作!!!!//addressfortheprivatekeybelow:atp1sznvsju6gjy3kmgnfgm526jf6e8x83twuctefhvarprivateKey="0x5ae02064df442340f861136acbfc4bd62b3d48393903bd6aac77ce0e7aaa9e5e";varchainId=201030;//201018formainnetvaract=newAlayaAccounts(web3a.currentProvider,"atp");act=act.privateKeyToAccount(privateKey);letfrom=act.address;letgasPrice=awaitweb3a.platon.getGasPrice();//之前已经部署好的智能合约letcontractAddress="atp1pcvx85klajfw9mvy3tf07acmqxaek5nanuy5t6";letabi=[];letcontract=newweb3a.platon.Contract(abi,contractAddress);letname=awaitcontract.methods.getName().call();console.log("namebeforechange:"+name);lettrans=contract.methods.setName("rileyge");letoptions={to:trans._parent._address,//也可以使用contractAddressdata:trans.encodeABI(),//abi的构造方法可以参照gas:awaittrans.estimateGas({from:from}),gasPrice:gasPrice,chainId:chainId}signTx=awaitact.signTransaction(options);//发送交易receipt=awaitweb3a.platon.sendSignedTransaction(signTx.rawTransaction);name=awaitcontract.methods.getName().call();console.log("nameafterchange:"+name);}main();

注意:上述代码不可直接运行,代码中使用了abi变量但未对其进行赋值,需要对abi变量进行赋值后使用。

如果使用已经部署好的智能合约,需要将setName函数中的变量修改后再看效果。上面一段代码有好几处需要注意的点,都集中在options这个变量中。

trans变量是我们通过Contract这个类构造的关于setName这个方法的交易。这个交易的具体用处下面几点有说明。

to设置为智能合约的地址,这个十分好理解。

data里面其实是将函数名及变量进行了abi编码,是个比较复杂的过程,具体编码方式函数ABI编码规则 (github.com)。不过好在alaya sdk已经帮我们处理好了这些,只要调用encodeABI()函数就行。

最后一个问题应该属于alaya sdk的一个bug,我已经在alaya sdk的chainId和前缀冲突 · Issue #61 · PlatONnetwork/client-sdk-js (github.com)中详细说明了问题,并提供了一种暂时的解决方案。

交易构建小结:

交易构建时常用的量有:from,to,value,gas,gasPrice,data,chainId等。其实在很多地方一些变量都是有默认值 的,如gas和gasPrice。所以如果你看到哪些交易构建时没有设置这个变量,也不要奇怪。

这些变量中chainId是一个比较有趣的变量。此变量一定要设置,而且千万不能设置错误。这个变量的出现其实是了避免在不同的链上进行重放攻击的。

data变量的构建是构建交易的重点,一些复杂的交易都是将数据以某种编码形式放到了data中。

alaya sdk与智能合约的交互是不是也很简单?其他更多的内容就自己再去探索吧!

总结

本教程到此暂时就结束了,关于alaya js sdk还有在浏览器中使用、与内置合约交互两大块内容。但由于现在alaya js sdk可能会进行版本更新,更新后对上述两种操作的影响会比较大,所以暂时搁置上述两项内容教程的编写。待升级完成后再进行编写。

特别鸣谢本教程贡献者@RileyGe

声明:该文观点仅代表作者本人,与炒币网无关。炒币网系信息发布平台,仅提供信息存储空间服务。对所包含内容的准确性、可靠性或者完整性不提供任何明示或暗示的保证,并不对文章观点负责。 提示:投资有风险,入市须谨慎。本资讯仅供参阅,不作为投资理财建议。

发表评论

登录后才能评论