Skip to content

Commit ca4b7d5

Browse files
committed
Refactoring of token transfers
- Inclusion of tokenID in Erc721 transfers - Support for Erc1155 transfers
1 parent a1cfd6f commit ca4b7d5

12 files changed

+362
-18
lines changed

Diff for: src/main/java/io/api/etherscan/core/IAccountApi.java

+55
Original file line numberDiff line numberDiff line change
@@ -137,4 +137,59 @@ public interface IAccountApi {
137137
*/
138138
@NotNull
139139
List<Block> minedBlocks(String address) throws ApiException;
140+
141+
@NotNull
142+
List<TxErc20> erc20Transfers(String address) throws ApiException;
143+
144+
@NotNull
145+
List<TxErc20> erc20Transfers(String address, long startBlock) throws ApiException;
146+
147+
/**
148+
* All ERC-20 token txs for given address
149+
*
150+
* @param address get txs for
151+
* @param startBlock tx from this blockNumber
152+
* @param endBlock tx to this blockNumber
153+
* @return txs for address
154+
* @throws ApiException parent exception class
155+
*/
156+
@NotNull
157+
List<TxErc20> erc20Transfers(String address, long startBlock, long endBlock) throws ApiException;
158+
159+
@NotNull
160+
List<TxErc721> erc721Transfers(String address) throws ApiException;
161+
162+
@NotNull
163+
List<TxErc721> erc721Transfers(String address, long startBlock) throws ApiException;
164+
165+
/**
166+
* All ERC-721 (NFT) token txs for given address
167+
*
168+
* @param address get txs for
169+
* @param startBlock tx from this blockNumber
170+
* @param endBlock tx to this blockNumber
171+
* @return txs for address
172+
* @throws ApiException parent exception class
173+
*/
174+
@NotNull
175+
List<TxErc721> erc721Transfers(String address, long startBlock, long endBlock) throws ApiException;
176+
177+
@NotNull
178+
List<TxErc1155> erc1155Transfers(String address) throws ApiException;
179+
180+
@NotNull
181+
List<TxErc1155> erc1155Transfers(String address, long startBlock) throws ApiException;
182+
183+
/**
184+
* All ERC-1155 token txs for given address
185+
*
186+
* @param address get txs for
187+
* @param startBlock tx from this blockNumber
188+
* @param endBlock tx to this blockNumber
189+
* @return txs for address
190+
* @throws ApiException parent exception class
191+
*/
192+
@NotNull
193+
List<TxErc1155> erc1155Transfers(String address, long startBlock, long endBlock) throws ApiException;
194+
140195
}

Diff for: src/main/java/io/api/etherscan/core/impl/AccountApiProvider.java

+67
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ public class AccountApiProvider extends BasicProvider implements IAccountApi {
3535
private static final String ACT_TX_INTERNAL_ACTION = ACT_PREFIX + "txlistinternal";
3636
private static final String ACT_TX_TOKEN_ACTION = ACT_PREFIX + "tokentx";
3737
private static final String ACT_TX_NFT_TOKEN_ACTION = ACT_PREFIX + "tokennfttx";
38+
private static final String ACT_TX_1155_TOKEN_ACTION = ACT_PREFIX + "token1155tx";
3839
private static final String ACT_MINED_ACTION = ACT_PREFIX + "getminedblocks";
3940

4041
private static final String BLOCK_TYPE_PARAM = "&blocktype=blocks";
@@ -265,4 +266,70 @@ public List<Block> minedBlocks(final String address) throws ApiException {
265266

266267
return getRequestUsingOffset(urlParams, BlockResponseTO.class);
267268
}
269+
270+
@NotNull
271+
@Override
272+
public List<TxErc20> erc20Transfers(String address) throws ApiException {
273+
return erc20Transfers(address, MIN_START_BLOCK);
274+
}
275+
276+
@NotNull
277+
@Override
278+
public List<TxErc20> erc20Transfers(String address, long startBlock) throws ApiException {
279+
return erc20Transfers(address, startBlock, MAX_END_BLOCK);
280+
}
281+
282+
@NotNull
283+
@Override
284+
public List<TxErc20> erc20Transfers(String address, long startBlock, long endBlock) throws ApiException {
285+
return getTokenTransfers(address, startBlock, endBlock, ACT_TX_TOKEN_ACTION, TxErc20ResponseTO.class);
286+
}
287+
288+
@NotNull
289+
@Override
290+
public List<TxErc721> erc721Transfers(String address) throws ApiException {
291+
return erc721Transfers(address, MIN_START_BLOCK);
292+
}
293+
294+
@NotNull
295+
@Override
296+
public List<TxErc721> erc721Transfers(String address, long startBlock) throws ApiException {
297+
return erc721Transfers(address, startBlock, MAX_END_BLOCK);
298+
}
299+
300+
@NotNull
301+
@Override
302+
public List<TxErc721> erc721Transfers(String address, long startBlock, long endBlock) throws ApiException {
303+
return getTokenTransfers(address, startBlock, endBlock, ACT_TX_NFT_TOKEN_ACTION, TxErc721ResponseTO.class);
304+
}
305+
306+
@NotNull
307+
@Override
308+
public List<TxErc1155> erc1155Transfers(String address) throws ApiException {
309+
return erc1155Transfers(address, MIN_START_BLOCK);
310+
}
311+
312+
@NotNull
313+
@Override
314+
public List<TxErc1155> erc1155Transfers(String address, long startBlock) throws ApiException {
315+
return erc1155Transfers(address, startBlock, MAX_END_BLOCK);
316+
}
317+
318+
@NotNull
319+
@Override
320+
public List<TxErc1155> erc1155Transfers(String address, long startBlock, long endBlock) throws ApiException {
321+
return getTokenTransfers(address, startBlock, endBlock, ACT_TX_1155_TOKEN_ACTION, TxErc1155ResponseTO.class);
322+
}
323+
324+
@NotNull
325+
private <T extends BaseTxToken, R extends BaseListResponseTO<T>> List<T> getTokenTransfers(String address, long startBlock, long endBlock, String tokenAction, Class<R> responseTOClass) throws ApiException {
326+
BasicUtils.validateAddress(address);
327+
final BlockParam blocks = BasicUtils.compensateBlocks(startBlock, endBlock);
328+
329+
final String offsetParam = PAGE_PARAM + "%s" + OFFSET_PARAM + OFFSET_MAX;
330+
final String blockParam = START_BLOCK_PARAM + blocks.start() + END_BLOCK_PARAM + blocks.end();
331+
final String urlParams = tokenAction + offsetParam + ADDRESS_PARAM + address + blockParam + SORT_ASC_PARAM;
332+
333+
return getRequestUsingOffset(urlParams, responseTOClass);
334+
}
268335
}
+59
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package io.api.etherscan.model;
2+
3+
public abstract class BaseTxToken extends BaseTx {
4+
5+
private long nonce;
6+
private String blockHash;
7+
private String tokenName;
8+
private String tokenSymbol;
9+
private int transactionIndex;
10+
private long gasPrice;
11+
private long cumulativeGasUsed;
12+
private long confirmations;
13+
14+
public long getNonce() {
15+
return nonce;
16+
}
17+
18+
public String getBlockHash() {
19+
return blockHash;
20+
}
21+
22+
public String getTokenName() {
23+
return tokenName;
24+
}
25+
26+
public String getTokenSymbol() {
27+
return tokenSymbol;
28+
}
29+
30+
public int getTransactionIndex() {
31+
return transactionIndex;
32+
}
33+
34+
public long getGasPrice() {
35+
return gasPrice;
36+
}
37+
38+
public long getCumulativeGasUsed() {
39+
return cumulativeGasUsed;
40+
}
41+
42+
public long getConfirmations() {
43+
return confirmations;
44+
}
45+
46+
@Override
47+
public String toString() {
48+
return "BaseTxToken{" +
49+
"nonce=" + nonce +
50+
", blockHash='" + blockHash + '\'' +
51+
", tokenName='" + tokenName + '\'' +
52+
", tokenSymbol='" + tokenSymbol + '\'' +
53+
", transactionIndex=" + transactionIndex +
54+
", gasPrice=" + gasPrice +
55+
", cumulativeGasUsed=" + cumulativeGasUsed +
56+
", confirmations=" + confirmations +
57+
'}' + super.toString();
58+
}
59+
}

Diff for: src/main/java/io/api/etherscan/model/TxErc1155.java

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package io.api.etherscan.model;
2+
3+
import java.math.BigInteger;
4+
5+
public class TxErc1155 extends BaseTxToken {
6+
7+
private BigInteger tokenID;
8+
private BigInteger tokenValue;
9+
10+
public BigInteger getTokenID() {
11+
return tokenID;
12+
}
13+
14+
public BigInteger getTokenValue() {
15+
return tokenValue;
16+
}
17+
18+
@Override
19+
public String toString() {
20+
return "TxErc1155{" +
21+
"tokenID=" + tokenID +
22+
", tokenValue=" + tokenValue +
23+
'}' + super.toString();
24+
}
25+
}

Diff for: src/main/java/io/api/etherscan/model/TxErc20.java

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
package io.api.etherscan.model;
2+
3+
import java.math.BigInteger;
4+
5+
public class TxErc20 extends BaseTxToken {
6+
7+
private BigInteger tokenDecimal;
8+
9+
public BigInteger getTokenDecimal() {
10+
return tokenDecimal;
11+
}
12+
13+
@Override
14+
public String toString() {
15+
return "TxErc20{" +
16+
"tokenDecimal=" + tokenDecimal +
17+
'}' + super.toString();
18+
}
19+
}

Diff for: src/main/java/io/api/etherscan/model/TxErc721.java

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package io.api.etherscan.model;
2+
3+
import java.math.BigInteger;
4+
5+
public class TxErc721 extends BaseTxToken {
6+
7+
private BigInteger tokenID;
8+
private BigInteger tokenDecimal;
9+
10+
public BigInteger getTokenID() {
11+
return tokenID;
12+
}
13+
14+
public BigInteger getTokenDecimal() {
15+
return tokenDecimal;
16+
}
17+
18+
@Override
19+
public String toString() {
20+
return "TxErc721{" +
21+
"tokenID=" + tokenID +
22+
", tokenDecimal=" + tokenDecimal +
23+
'}' + super.toString();
24+
}
25+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package io.api.etherscan.model.utility;
2+
3+
import io.api.etherscan.model.TxErc1155;
4+
5+
public class TxErc1155ResponseTO extends BaseListResponseTO<TxErc1155> {
6+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package io.api.etherscan.model.utility;
2+
3+
import io.api.etherscan.model.TxErc20;
4+
5+
public class TxErc20ResponseTO extends BaseListResponseTO<TxErc20> {
6+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
package io.api.etherscan.model.utility;
2+
3+
import io.api.etherscan.model.TxErc721;
4+
5+
public class TxErc721ResponseTO extends BaseListResponseTO<TxErc721> {
6+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package io.api.etherscan.account;
2+
3+
import io.api.ApiRunner;
4+
import io.api.etherscan.error.InvalidAddressException;
5+
import io.api.etherscan.model.TxErc1155;
6+
import org.jetbrains.annotations.NotNull;
7+
import org.junit.Test;
8+
9+
import java.util.List;
10+
11+
public class AccountErc1155TransferTest extends ApiRunner {
12+
13+
@Test
14+
public void correct() {
15+
List<TxErc1155> txs = getApi().account().erc1155Transfers("0xE4C8324534C0C6bCA174Cd0F02fAC9889C36bA59");
16+
assertNotNull(txs);
17+
assertFalse(txs.isEmpty());
18+
assertTxs(txs);
19+
assertNotEquals(0, txs.get(0).getGasPrice());
20+
assertNotEquals(-1, txs.get(0).getNonce());
21+
22+
assertNotNull(txs.get(0).toString());
23+
assertNotEquals(txs.get(0).toString(), txs.get(1).toString());
24+
25+
assertNotEquals(txs.get(0), txs.get(1));
26+
assertNotEquals(txs.get(0).hashCode(), txs.get(1).hashCode());
27+
28+
assertEquals(txs.get(1), txs.get(1));
29+
assertEquals(txs.get(1).hashCode(), txs.get(1).hashCode());
30+
}
31+
32+
@Test
33+
public void correctStartBlock() {
34+
List<TxErc1155> txs = getApi().account().erc1155Transfers("0xE4C8324534C0C6bCA174Cd0F02fAC9889C36bA59", 14275897);
35+
assertNotNull(txs);
36+
assertFalse(txs.isEmpty());
37+
assertTxs(txs);
38+
}
39+
40+
@Test
41+
public void correctStartBlockEndBlock() {
42+
List<TxErc1155> txs = getApi().account().erc1155Transfers("0xE4C8324534C0C6bCA174Cd0F02fAC9889C36bA59", 14275897, 15148929);
43+
assertNotNull(txs);
44+
assertEquals(11, txs.size());
45+
assertTxs(txs);
46+
}
47+
48+
@Test(expected = InvalidAddressException.class)
49+
public void invalidParamWithError() {
50+
getApi().account().erc1155Transfers("0x6ec53A8fBa6358d59B3C4476D82cc60A2B0FaD7");
51+
}
52+
53+
@Test
54+
public void correctParamWithEmptyExpectedResult() {
55+
List<TxErc1155> txs = getApi().account().erc1155Transfers("0x31ec53A8fBa6358d59B3C4476D82cc60A2B0FaD7");
56+
assertNotNull(txs);
57+
assertTrue(txs.isEmpty());
58+
}
59+
60+
private void assertTxs(List<TxErc1155> txs) {
61+
txs.forEach(this::asserTx);
62+
}
63+
64+
private void asserTx(@NotNull TxErc1155 tx) {
65+
assertNotNull(tx.getBlockHash());
66+
assertNotNull(tx.getTokenName());
67+
assertNotNull(tx.getTokenSymbol());
68+
assertNotNull(tx.getFrom());
69+
assertNotNull(tx.getTo());
70+
assertNotNull(tx.getTimeStamp());
71+
assertNotNull(tx.getTokenID());
72+
assertNotNull(tx.getTokenValue());
73+
assertNotEquals(-1, (tx.getConfirmations()));
74+
assertNotNull(tx.getGasUsed());
75+
assertNotEquals(-1, tx.getCumulativeGasUsed());
76+
assertNotEquals(-1, tx.getTransactionIndex());
77+
}
78+
}

0 commit comments

Comments
 (0)