咸鱼

咸鱼是以盐腌渍后,晒干的鱼

0%

13、Android通过web3j交易代币

测试“生成合约的Java代码”环境

下载web3j-3.4.0
解压目录

1
2
3
4
5
.
├── bin
│   ├── web3j
│   └── web3j.bat
└── lib

进入bin目录,编写一个测试合约代码 SimpleStorage.sol

1
2
3
4
5
6
7
8
9
10
11
pragma solidity ^0.4.17;

contract SimpleStorage {
uint storedData;
function set(uint x) public {
storedData = x;
}
function get() public view returns (uint) {
return storedData;
}
}

执行以下命令

1
2
3
4
$ npm install -g solc@0.4.17
$ solcjs SimpleStorage.sol --optimize --bin --abi

$ ./web3j solidity generate SimpleStorage_sol_SimpleStorage.bin SimpleStorage_sol_SimpleStorage.abi -o ./ -p com.github.contract

如果生成成功的话,在目录下就有代码文件了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
package com.github.contract;

import java.math.BigInteger;
import java.util.Arrays;
import java.util.Collections;
import org.web3j.abi.TypeReference;
import org.web3j.abi.datatypes.Function;
import org.web3j.abi.datatypes.Type;
import org.web3j.abi.datatypes.generated.Uint256;
import org.web3j.crypto.Credentials;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.core.RemoteCall;
import org.web3j.protocol.core.methods.response.TransactionReceipt;
import org.web3j.tx.Contract;
import org.web3j.tx.TransactionManager;

/**
* <p>Auto generated code.
* <p><strong>Do not modify!</strong>
* <p>Please use the <a href="https://docs.web3j.io/command_line.html">web3j command line tools</a>,
* or the org.web3j.codegen.SolidityFunctionWrapperGenerator in the
* <a href="https://github.com/web3j/web3j/tree/master/codegen">codegen module</a> to update.
*
* <p>Generated with web3j version 3.4.0.
*/
public class SimpleStorage_sol_SimpleStorage extends Contract {
private static final String BINARY = "608060405234801561001057600080fd5b5060be8061001f6000396000f3fe6080604052348015600f57600080fd5b5060043610604e577c0100000000000000000000000000000000000000000000000000000000600035046360fe47b1811460535780636d4ce63c14606f575b600080fd5b606d60048036036020811015606757600080fd5b50356087565b005b6075608c565b60408051918252519081900360200190f35b600055565b6000549056fea165627a7a72305820e5e4aaf9332912cc735c414d20ef297bee7a95d95f6c63801cb3c4c94a6542cd0029";

public static final String FUNC_SET = "set";

public static final String FUNC_GET = "get";

protected SimpleStorage_sol_SimpleStorage(String contractAddress, Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) {
super(BINARY, contractAddress, web3j, credentials, gasPrice, gasLimit);
}

protected SimpleStorage_sol_SimpleStorage(String contractAddress, Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) {
super(BINARY, contractAddress, web3j, transactionManager, gasPrice, gasLimit);
}

public RemoteCall<TransactionReceipt> set(BigInteger x) {
final Function function = new Function(
FUNC_SET,
Arrays.<Type>asList(new org.web3j.abi.datatypes.generated.Uint256(x)),
Collections.<TypeReference<?>>emptyList());
return executeRemoteCallTransaction(function);
}

public RemoteCall<BigInteger> get() {
final Function function = new Function(FUNC_GET,
Arrays.<Type>asList(),
Arrays.<TypeReference<?>>asList(new TypeReference<Uint256>() {}));
return executeRemoteCallSingleValueReturn(function, BigInteger.class);
}

public static RemoteCall<SimpleStorage_sol_SimpleStorage> deploy(Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) {
return deployRemoteCall(SimpleStorage_sol_SimpleStorage.class, web3j, credentials, gasPrice, gasLimit, BINARY, "");
}

public static RemoteCall<SimpleStorage_sol_SimpleStorage> deploy(Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) {
return deployRemoteCall(SimpleStorage_sol_SimpleStorage.class, web3j, transactionManager, gasPrice, gasLimit, BINARY, "");
}

public static SimpleStorage_sol_SimpleStorage load(String contractAddress, Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit) {
return new SimpleStorage_sol_SimpleStorage(contractAddress, web3j, credentials, gasPrice, gasLimit);
}

public static SimpleStorage_sol_SimpleStorage load(String contractAddress, Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit) {
return new SimpleStorage_sol_SimpleStorage(contractAddress, web3j, transactionManager, gasPrice, gasLimit);
}
}

生成合约Java代码

确定环境搭建好了之后,就可以将我们的合约进行生成Java代码了

进入合约的目录,执行命令生成bin和abi文件

1
2
3
4
5
6
7
.
├── Migrations.sol
├── StandardToken.sol
├── TeaToken.sol
└── Token.sol

$ solcjs *.sol --optimize --bin --abi

为了减少路径的输入,我把所有的bin和abi文件拷贝到web3j目录下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
$ cd web3j-3.4.0/bin
$ tree
.
├── Migrations_sol_Migrations.abi
├── Migrations_sol_Migrations.bin
├── StandardToken_sol_StandardToken.abi
├── StandardToken_sol_StandardToken.bin
├── TeaToken_sol_TeaToken.abi
├── TeaToken_sol_TeaToken.bin
├── Token_sol_Token.abi
├── Token_sol_Token.bin
├── web3j
└── web3j.bat
$ ./web3j solidity generate TeaToken_sol_TeaToken.bin TeaToken_sol_TeaToken.abi -o ./ -p com.github.contract

_ _____ _ _
| | |____ (_) (_)
__ _____| |__ / /_ _ ___
\ \ /\ / / _ \ '_ \ \ \ | | | / _ \
\ V V / __/ |_) |.___/ / | _ | || (_) |
\_/\_/ \___|_.__/ \____/| |(_)|_| \___/
_/ |
|__/

Generating com.github.contract.TeaToken_sol_TeaToken ... File written to .
.
├── com
│   └── github
│   └── contract
│   └── TeaToken_sol_TeaToken.java
├── Migrations_sol_Migrations.abi
├── Migrations_sol_Migrations.bin
├── StandardToken_sol_StandardToken.abi
├── StandardToken_sol_StandardToken.bin
├── TeaToken_sol_TeaToken.abi
├── TeaToken_sol_TeaToken.bin
├── Token_sol_Token.abi
├── Token_sol_Token.bin
├── web3j
└── web3j.bat

将生成的 TeaToken_sol_TeaToken.java 拷贝到Android项目

调用合约代码

注意:合约要预先部署好,下面这是在Java、Android上部署合约的代码,一般不会再Android App上部署合约,可以用Java程序或者truffle来部署合约。

部署合约的账号拥有所有的代币,可以通过转账发给其他账户。

1
TeaToken_sol_TeaToken contract = TeaToken_sol_TeaToken.deploy(web3j, credentials1, GAS_PRICE, GAS_LIMIT).send();

代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public void testTransferSmartContracts() throws ExecutionException, InterruptedException {

//合约地址
final String contractAddress = "0x6bee29c36f1633db9c4dfb4e445fccd8c4dd8023";

EthCoinbase coinbase = web3j.ethCoinbase().sendAsync().get();
final String coinbaseAddress = coinbase.getAddress();
final String formKey = "58e7f34b59a828d1dc37a97a921b55de0cb8cedea91b1e09b490f39264b151ce";
//签名
Credentials credentials = Credentials.create(formKey);
//收款地址
final String toAddress = "0x9958eC47C8286DC89F5CbCbD842458bD43540a7D";

//通过合约地址加载合约
TeaToken_sol_TeaToken contract = TeaToken_sol_TeaToken.load(contractAddress,web3j,credentials,GAS_PRICE, GAS_LIMIT);
BigInteger totalSupply = contract.totalSupply().sendAsync().get();
Log.e(TAG, "totalSupply = "+ totalSupply );
BigInteger balanceOf = contract.balanceOf(coinbaseAddress).sendAsync().get();
Log.e(TAG, "balanceOf = "+ balanceOf );

TransactionReceipt transactionReceipt = contract.transfer(toAddress,new BigInteger("10000000000000000000")).sendAsync().get();
Log.e(TAG, "Status = "+transactionReceipt.getStatus());
Log.e(TAG, "GasUsed = "+transactionReceipt.getGasUsed());
Log.e(TAG, "TransactionHash = "+transactionReceipt.getTransactionHash());

Log.e(TAG, "BlockHash = "+transactionReceipt.getBlockHash());
Log.e(TAG, "BlockNumberRaw = "+transactionReceipt.getBlockNumberRaw());
Log.e(TAG, "BlockNumber = "+transactionReceipt.getBlockNumber());
}

运行Android日志

1
2
3
4
5
6
7
8
totalSupply = 10000000000000000000000
balanceOf = 10000000000000000000000
Status = 0x1
GasUsed = 51511
TransactionHash = 0x9389ffcc09dd8d17023e49f5487b95e41ff537a83282a85abc606da7ab99d37c
BlockHash = 0x1447cbd6e36dca635a5cce39d35d3cafc7bd3b6b57d53fc338968b14c172019e
BlockNumberRaw = 0x7
BlockNumber = 7

运行Canache日志

1
2
3
4
5
[上午11:08:06]   Transaction: 0x9389ffcc09dd8d17023e49f5487b95e41ff537a83282a85abc606da7ab99d37c
[上午11:08:06] Gas usage: 51511
[上午11:08:06] Block Number: 7
[上午11:08:06] Block Time: Sat Dec 29 2018 11:08:06 GMT+0800 (中国标准时间)
[上午11:08:06] eth_getTransactionReceipt

好了,后续的功能一样的,可以查询账号余额等。