使用 Java 和 web3j 进行 Token 开发[概述][译]

  • Tiny熊
  • 更新于 2020-04-27 00:08
  • 阅读 3216

学习使用 web3j 部署ERC20 以及与合约进行交互。

题外话, 翻译这篇文章是因为看到 CSDN 公众号这篇外行翻译。 (get balance: 获取账号余额被翻译为取得平衡,transaction 交易翻译为事务 , 等等), CSDN 用自己的流量优势不知道坑了多少开发者。

为了创作本文,我们创建的名为JavaToken的基本ERC20智能合约,可以在此处找到代码。 我们将使用这个代码库进行演示,请先 Git Clone到本地进行后续操作! 我们使用Truffle创建的本地Ganache Testnet网络来部署和运行这个合约。

我(原作者)最近写了一篇有关开始使用Android进行以太坊开发的文章,其中演示了如何在Android中设置web3j以及如何进行以太币转账。发布后收到读者留言想看看如何使用web3j与自定义ERC20 Token进行交互,因此有了今天这篇文章。

步骤0.9: 生成智能合约Java包装(Wrapper)

这个0.9 步是获取智能合约的一个Java包装器。之所以是 0.9步,是因为从技术上讲,如果合约已经部署,则可以不需要,但在之后与合约进行交互时,使用Wrapper将使事情会更容易。

为了生成Wrapper, 需要先使用Solidity编译器编译Solidity合约。如果你使用的是Truffle,则只需在JavaToken代码库的Truffle目录中运行以下命令编译即可:

为此,请先使用Solidity编译器编译Solidity合约。如果你使用的是Truffle,则只需在JavaToken存储库的Truffle目录中运行以下命令即可:

truffle compile

接着,安装web3j命令行:

Mac/Linux平台用户:

curl -L get.web3j.io | sh

Windows平台用户:

Set-ExecutionPolicy Bypass -Scope Process -Force; iex ((New-Object System.Net.WebClient).DownloadString('https://raw.githubusercontent.com/web3j/web3j-installer/master/installer.ps1'))

一切安装就绪之后,运行以下代码:

web3j truffle generate Truffle/build/contracts/JavaToken.json -o src -p com.javaToken

在JavaToken目录下,将为JavaToken智能合约生成一个Wrapper,让之后和以太坊交互时更加容易。

步骤 1: 合约部署

为了部署Token,需要进行一些配置,并调用deploy()方法。

// The Ganache TestNet listens at port 7545
Web3j w3 = Web3j.build(new HttpService("HTTP://127.0.0.1:7545"));
String privateKey = "你的私钥";
Credentials credentials = Credentials.create(privateKey);
// 初始发行量
BigInteger initialSupply = BigInteger.valueOf(100000);

JavaToken javaToken = JavaToken.deploy(w3, credentials, new DefaultGasProvider(), initialSupply).send()

这样就部署好了一个全新的以太坊Token!

此外,如果你仅仅是需要和一个已经部署的合约交互, 只需要使用下面的代码加载它:

// The Ganache TestNet listens at port 7545
Web3j w3 = Web3j.build(new HttpService("HTTP://127.0.0.1:7545"));
String privateKey = "你的私钥";
Credentials credentials = Credentials.create(privateKey);
String contractAddress = "合约地址";

JavaToken javaToken = JavaToken.load(contractAddress,w3,credentials,new DefaultGasProvider());

步骤 2: 获取余额

根据合约的代买,合约的部署者拥有所有的发行的 token。让我们检查一下部署者账号余额时候正确。如果我们从0.9步开始使用Wrapper,那么很简单:

// With java wrapper
BigInteger balance = javaToken.balanceOf(credentials.getAddress()).send()

// Without java wrapper
String contractAddress = "YourDeployedContractAddress";

// Define the function we want to invoke from the smart contract
Function function = new Function("balanceOf", Arrays.asList(new Address(credentials.getAddress())),
                                 Arrays.asList(new TypeReference<Uint256>() {}));

// Encode it for the contract to understand
String encodedFunction = FunctionEncoder.encode(function);

/*
Send the request and wait for the response using eth call since
it's a read only transaction with no cost associated
*/
EthCall response = w3.ethCall(
  Transaction.createEthCallTransaction(credentials.getAddress(), contractAddress, encodedFunction),
  DefaultBlockParameterName.LATEST).send();

balance = Numeric.toBigInt(response.getValue());

要不能,会有一点复杂:

  1. 首先需要手动输入调用合约函数的详细信息, 如这里函数名是balanceOf、账号地址作为参数,返回一个uint256类型的作为余额;
  2. 然后对这些数据进行一个编码连同调用信息(谁发起、调用哪个合约)一起打包为交易。
  3. 最后,我们将十六进制结果解码为一个BigInteger类型。

现在,我们有了100000个 JavaToken。让我们发送一些给朋友!

步骤 3: Token 转账

同样,使用 wrapper 和不使用 wrapper 之间的差异非常明显:

String addressTo = "YourFriendsAddress";
BigInteger amount = BigInteger.valueOf(500);

// 使用 wrapper
TransactionReceipt receipt = javaToken.transfer(addressTo,amount).send();

// Without java wrapper

// 定义想要调用的函数
Function function = new Function("transfer", Arrays.asList(new Address(addressTo), new Uint256(amount)),  Collections.emptyList());

// 编码,以便合约可以理解调用哪个函数
String encodedFunction = FunctionEncoder.encode(function);

/*
Need to use a TransactionManager here since transfer actually alters the state of the blockchain and credentials are therefore relevant
*/
TransactionManager transactionManager = new FastRawTransactionManager(w3, credentials);

// Send the transaction off using transactionManager and wait for the hash
String transactionHash = transactionManager.sendTransaction(DefaultGasProvider.GAS_PRICE,
                                                            DefaultGasProvider.GAS_LIMIT, contractAddress, encodedFunction,
                                                            BigInteger.ZERO).getTransactionHash();

// 获取交易收据
Optional<TransactionReceipt> transactionReceipt =
  w3.ethGetTransactionReceipt(transactionHash).send().getTransactionReceipt();
if(transactionReceipt.isEmpty())
  receipt = null;
else
  receipt = transactionReceipt.get();

不是wrapper时,现在有一点不同,这次需要更改区块链状态而不仅仅是读取数据,因此需要证明是谁发起的交易。

以同样的方式创建一个函数对象。尽管智能合约transfer函数返回的是布尔值,但我们在这里不需要使用,因为得通过交易收据检查交易是否成功,因此我们将返回值指定为一个空列表。接下来,我们创建一个交易管理器(TransactionManager)。

这个区别很关键, 管理器使用签名作为参数,说明是我们发起的交易(和上面balanceOf不同),最后通过检查交易收据确认交易是否成功。

结论

通过这篇文章学习了使用 web3j 部署ERC20, 相关的所有代码在: https://github.com/nschapeler/JavaToken

英文原文

登链社区 - 高质量的区块链技术文章集中地。

点赞 1
收藏 2
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

1 条评论

请先 登录 后评论
Tiny熊
Tiny熊
0x1231...6564
登链社区发起人 登链团队对 DEFI 应用有深刻的理解和丰富的开发经验,如果你有开发、审计、培训合作等需求, 加我微信:xlbxiong 。 咨询问题在问答区提问即可,微信好友太多,不看问题,请凉解~