学习使用 web3j 部署ERC20 以及与合约进行交互。
题外话, 翻译这篇文章是因为看到 CSDN 公众号这篇外行翻译。 (
get balance
: 获取账号余额被翻译为取得平衡,transaction
交易翻译为事务 , 等等), CSDN 用自己的流量优势不知道坑了多少开发者。
为了创作本文,我们创建的名为JavaToken的基本ERC20智能合约,可以在此处找到代码。 我们将使用这个代码库进行演示,请先 Git Clone到本地进行后续操作! 我们使用Truffle创建的本地Ganache Testnet网络来部署和运行这个合约。
我(原作者)最近写了一篇有关开始使用Android进行以太坊开发的文章,其中演示了如何在Android中设置web3j以及如何进行以太币转账。发布后收到读者留言想看看如何使用web3j与自定义ERC20 Token进行交互,因此有了今天这篇文章。
这个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,让之后和以太坊交互时更加容易。
为了部署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());
根据合约的代买,合约的部署者拥有所有的发行的 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());
要不能,会有一点复杂:
现在,我们有了100000个 JavaToken。让我们发送一些给朋友!
同样,使用 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
登链社区 - 高质量的区块链技术文章集中地。
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!