如何使用java监听Erc20Token交易

你可以在web3j库的帮助下使用java轻松监听以太坊交易,但此库无法监听Erc20 Token交易。

要监听Erc20Token交易,你必须使用在合约(token)创建时的token封装类。我假设你已经使用最少的功能部署了合约,因此你的封装类看起来像这样:

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.bolenum.util;

import java.io.IOException;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util...;

import org.web3j.abi.EventEncoder;
import org.web3j.abi...
import org.web3j.crypto.Credentials;
import org.web3j.protocol.Web3j;
import org.web3j.protocol...;
import org.web3j.tx.Contract;
import org.web3j.tx.TransactionManager;

import rx.Observable;
import rx.functions.Func1;

...

public final class Erc20TokenWrapper extends Contract {

private static final String BINARY = "contract binary key";

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

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

public List<TransferEventResponse> getTransferEvents(TransactionReceipt transactionReceipt) {
...
return responses;
}

public Observable<TransferEventResponse> transferEventObservable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) {
...
}

...

public Uint256 balanceOf(Address _owner) throws IOException {
Function function = new Function("balanceOf",
Arrays.<Type>asList(_owner),
Arrays.<TypeReference<?>>asList(new TypeReference<Uint256>() {}));
return executeCallSingleValueReturn(function);
}

...

public TransactionReceipt transfer(Address _to, Uint256 _amount) throws IOException, TransactionException {
Function function = new Function("transfer", Arrays.<Type>asList(_to, _amount), Collections.<TypeReference<?>>emptyList());
return executeTransaction(function);
}

...

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

public static class TransferEventResponse {
public Address _from;
public Address _to;
public Uint256 _value;
public String _transactionHash;
}

...
}

现在你必须使用这个类函数来加载合约然后监听交易。使用下面的代码加载和监听交易:

1
2
3
4
5
6
7
8
9
10
11
Web3j web3j = Web3j.build(new HttpService("url of your ethereum blockchain"))    
ClientTransactionManager transactionManager = new ClientTransactionManager(web3j,
"your deployed contract addess");
Erc20TokenWrapper token = Erc20TokenWrapper.load("your deployed contract addess", web3j, transactionManager,
Contract.GAS_PRICE, Contract.GAS_LIMIT);
token.transferEventObservable(DefaultBlockParameterName.EARLIEST, DefaultBlockParameterName.LATEST)
.subscribe(tx -> {
String toAddress = tx._to.getValue();
String fromAddress = tx._from.getValue();
String txHash = tx._transactionHash.getValue();
}

如果你已经部署了合约,它由第三人部署,那么你可以直接使用我的包装类,只需更改你可以从https://etherscan.io/tokens很容易获得的二进制密钥。

结论:因此你可以将此代码用于任何token的监听交易。此代码为你提供addressfromAddresstransactionHash。所以这些东西你可以根据你的要求使用,你可以将它们保存在你的数据库中,或者你只保存地址是你的钱包地址的交易。

谢谢,我希望这会有所帮助。

如果希望快速进行web3j、java、以太坊开发,那请看我们精心打造的教程: java以太坊开发教程,主要是针对java和android程序员进行区块链以太坊开发的web3j详解。

其他以太坊教程如下:

  • 以太坊入门教程,主要介绍智能合约与dapp应用开发,适合入门。
  • 以太坊开发进阶教程,主要是介绍使用node.js、mongodb、区块链、ipfs实现去中心化电商DApp实战,适合进阶。
  • python以太坊,主要是针对python工程师使用web3.py进行区块链以太坊开发的详解。
  • php以太坊,主要是介绍使用php进行智能合约开发交互,进行账号创建、交易、转账、代币开发以及过滤器和事件等内容。
  • C#以太坊,主要讲解如何使用C#开发基于.Net的以太坊应用,包括账户管理、状态与交易、智能合约开发与交互、过滤器和事件等。

汇智网原创翻译,转载请标明出处。这里是原文

完整代码如下:

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
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
package com.bolenum.util;

import java.io.IOException;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.Future;

import org.web3j.abi.EventEncoder;
import org.web3j.abi.EventValues;
import org.web3j.abi.FunctionEncoder;
import org.web3j.abi.TypeReference;
import org.web3j.abi.datatypes.Address;
import org.web3j.abi.datatypes.Event;
import org.web3j.abi.datatypes.Function;
import org.web3j.abi.datatypes.Type;
import org.web3j.abi.datatypes.Utf8String;
import org.web3j.abi.datatypes.generated.Uint256;
import org.web3j.abi.datatypes.generated.Uint8;
import org.web3j.crypto.Credentials;
import org.web3j.protocol.Web3j;
import org.web3j.protocol.core.DefaultBlockParameter;
import org.web3j.protocol.core.RemoteCall;
import org.web3j.protocol.core.methods.request.EthFilter;
import org.web3j.protocol.core.methods.response.Log;
import org.web3j.protocol.core.methods.response.TransactionReceipt;
import org.web3j.protocol.exceptions.TransactionException;
import org.web3j.tx.Contract;
import org.web3j.tx.TransactionManager;

import rx.Observable;
import rx.functions.Func1;

/**
* Auto generated code.<br>
* <strong>Do not modify!</strong><br>
* Please use the <a href="https://docs.web3j.io/command_line.html">web3j command line tools</a>, or {@link org.web3j.codegen.SolidityFunctionWrapperGenerator} to update.
*
* <p>Generated with web3j version 2.3.1.
*/
public final class Erc20TokenWrapper extends Contract {

private static final String BINARY = "contract binary key";

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

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

public List<TransferEventResponse> getTransferEvents(TransactionReceipt transactionReceipt) {
final Event event = new Event("Transfer",
Arrays.<TypeReference<?>>asList(new TypeReference<Address>() {}, new TypeReference<Address>() {}),
Arrays.<TypeReference<?>>asList(new TypeReference<Uint256>() {}));
List<EventValues> valueList = extractEventParameters(event, transactionReceipt);
ArrayList<TransferEventResponse> responses = new ArrayList<TransferEventResponse>(valueList.size());
for (EventValues eventValues : valueList) {
TransferEventResponse typedResponse = new TransferEventResponse();
typedResponse._from = (Address) eventValues.getIndexedValues().get(0);
typedResponse._to = (Address) eventValues.getIndexedValues().get(1);
typedResponse._value = (Uint256) eventValues.getNonIndexedValues().get(0);
responses.add(typedResponse);
}
return responses;
}

public Observable<TransferEventResponse> transferEventObservable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) {
final Event event = new Event("Transfer",
Arrays.<TypeReference<?>>asList(new TypeReference<Address>() {}, new TypeReference<Address>() {}),
Arrays.<TypeReference<?>>asList(new TypeReference<Uint256>() {}));
EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress());
filter.addSingleTopic(EventEncoder.encode(event));
return web3j.ethLogObservable(filter).map(new Func1<Log, TransferEventResponse>() {
@Override
public TransferEventResponse call(Log log) {
EventValues eventValues = extractEventParameters(event, log);
TransferEventResponse typedResponse = new TransferEventResponse();
typedResponse._from = (Address) eventValues.getIndexedValues().get(0);
typedResponse._to = (Address) eventValues.getIndexedValues().get(1);
typedResponse._value = (Uint256) eventValues.getNonIndexedValues().get(0);
typedResponse._transactionHash = log.getTransactionHash();
return typedResponse;
}
});
}

public List<ApprovalEventResponse> getApprovalEvents(TransactionReceipt transactionReceipt) {
final Event event = new Event("Approval",
Arrays.<TypeReference<?>>asList(new TypeReference<Address>() {}, new TypeReference<Address>() {}),
Arrays.<TypeReference<?>>asList(new TypeReference<Uint256>() {}));
List<EventValues> valueList = extractEventParameters(event, transactionReceipt);
ArrayList<ApprovalEventResponse> responses = new ArrayList<ApprovalEventResponse>(valueList.size());
for (EventValues eventValues : valueList) {
ApprovalEventResponse typedResponse = new ApprovalEventResponse();
typedResponse._owner = (Address) eventValues.getIndexedValues().get(0);
typedResponse._spender = (Address) eventValues.getIndexedValues().get(1);
typedResponse._value = (Uint256) eventValues.getNonIndexedValues().get(0);
responses.add(typedResponse);
}
return responses;
}

public Observable<ApprovalEventResponse> approvalEventObservable(DefaultBlockParameter startBlock, DefaultBlockParameter endBlock) {
final Event event = new Event("Approval",
Arrays.<TypeReference<?>>asList(new TypeReference<Address>() {}, new TypeReference<Address>() {}),
Arrays.<TypeReference<?>>asList(new TypeReference<Uint256>() {}));
EthFilter filter = new EthFilter(startBlock, endBlock, getContractAddress());
filter.addSingleTopic(EventEncoder.encode(event));
return web3j.ethLogObservable(filter).map(new Func1<Log, ApprovalEventResponse>() {
@Override
public ApprovalEventResponse call(Log log) {
EventValues eventValues = extractEventParameters(event, log);
ApprovalEventResponse typedResponse = new ApprovalEventResponse();
typedResponse._owner = (Address) eventValues.getIndexedValues().get(0);
typedResponse._spender = (Address) eventValues.getIndexedValues().get(1);
typedResponse._value = (Uint256) eventValues.getNonIndexedValues().get(0);
typedResponse._transactionHash = log.getTransactionHash();
return typedResponse;
}
});
}

public Future<Utf8String> name() throws IOException {
Function function = new Function("name",
Arrays.<Type>asList(),
Arrays.<TypeReference<?>>asList(new TypeReference<Utf8String>() {}));
return executeCallSingleValueReturn(function);
}

public TransactionReceipt approve(Address _spender, Uint256 _amount) throws IOException, TransactionException {
Function function = new Function("approve", Arrays.<Type>asList(_spender, _amount), Collections.<TypeReference<?>>emptyList());
return executeTransaction(function);
}

public Future<Uint256> totalSupply() throws IOException {
Function function = new Function("totalSupply",
Arrays.<Type>asList(),
Arrays.<TypeReference<?>>asList(new TypeReference<Uint256>() {}));
return executeCallSingleValueReturn(function);
}

public TransactionReceipt transferFrom(Address _from, Address _to, Uint256 _amount) throws IOException, TransactionException {
Function function = new Function("transferFrom", Arrays.<Type>asList(_from, _to, _amount), Collections.<TypeReference<?>>emptyList());
return executeTransaction(function);
}

public Uint8 decimals() throws IOException {
Function function = new Function("decimals",
Arrays.<Type>asList(),
Arrays.<TypeReference<?>>asList(new TypeReference<Uint8>() {}));
return executeCallSingleValueReturn(function);
}

public Uint256 balanceOf(Address _owner) throws IOException {
Function function = new Function("balanceOf",
Arrays.<Type>asList(_owner),
Arrays.<TypeReference<?>>asList(new TypeReference<Uint256>() {}));
return executeCallSingleValueReturn(function);
}

public Future<Address> owner() throws IOException {
Function function = new Function("owner",
Arrays.<Type>asList(),
Arrays.<TypeReference<?>>asList(new TypeReference<Address>() {}));
return executeCallSingleValueReturn(function);
}

public Future<Utf8String> symbol() throws IOException {
Function function = new Function("symbol",
Arrays.<Type>asList(),
Arrays.<TypeReference<?>>asList(new TypeReference<Utf8String>() {}));
return executeCallSingleValueReturn(function);
}

public TransactionReceipt transfer(Address _to, Uint256 _amount) throws IOException, TransactionException {
Function function = new Function("transfer", Arrays.<Type>asList(_to, _amount), Collections.<TypeReference<?>>emptyList());
return executeTransaction(function);
}

public Future<Uint256> allowance(Address _owner, Address _spender) throws IOException {
Function function = new Function("allowance",
Arrays.<Type>asList(_owner, _spender),
Arrays.<TypeReference<?>>asList(new TypeReference<Uint256>() {}));
return executeCallSingleValueReturn(function);
}

public static RemoteCall<Erc20TokenWrapper> deploy(Web3j web3j, Credentials credentials, BigInteger gasPrice, BigInteger gasLimit, BigInteger initialWeiValue, Uint256 totalSupply, Utf8String tokenName, Uint8 decimalUnits, Utf8String tokenSymbol) {
String encodedConstructor = FunctionEncoder.encodeConstructor(Arrays.<Type>asList(totalSupply, tokenName, decimalUnits, tokenSymbol));
return deployRemoteCall(Erc20TokenWrapper.class, web3j, credentials, gasPrice, gasLimit, BINARY, encodedConstructor, initialWeiValue);
}

public static RemoteCall<Erc20TokenWrapper> deploy(Web3j web3j, TransactionManager transactionManager, BigInteger gasPrice, BigInteger gasLimit, BigInteger initialWeiValue, Uint256 totalSupply, Utf8String tokenName, Uint8 decimalUnits, Utf8String tokenSymbol) {
String encodedConstructor = FunctionEncoder.encodeConstructor(Arrays.<Type>asList(totalSupply, tokenName, decimalUnits, tokenSymbol));
return deployRemoteCall(Erc20TokenWrapper.class, web3j, transactionManager, gasPrice, gasLimit, BINARY, encodedConstructor, initialWeiValue);
}

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

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

public static class TransferEventResponse {
public Address _from;

public Address _to;

public Uint256 _value;

public String _transactionHash;
}

public static class ApprovalEventResponse {
public Address _owner;

public Address _spender;

public Uint256 _value;

public String _transactionHash;
}
}