diff --git a/src/main/java/com/nynja/walletservice/controller/WalletController.java b/src/main/java/com/nynja/walletservice/controller/WalletController.java index 2f407cce1ca0f2b10121b8f9e49bc1bf510f6ab3..c61710ca9041ac7034115045c64f97740a885942 100644 --- a/src/main/java/com/nynja/walletservice/controller/WalletController.java +++ b/src/main/java/com/nynja/walletservice/controller/WalletController.java @@ -38,6 +38,10 @@ public class WalletController { @ApiResponse(code = 200, message = RETRIEVED) @PostMapping(API_VERSION + "/scan-single-account") public CompletableFuture>> scanSingleAccount(@Valid @RequestBody AccountScanDto dto) { - return handleAndRespondAsync(() -> walletService.scanSingleAccount(dto.getPublicKey(), dto.getChainCode())); + return handleAndRespondAsync(() -> walletService.scanSingleAccount( + dto.getPublicKey(), + dto.getChainCode(), + dto.getChainId() + )); } } diff --git a/src/main/java/com/nynja/walletservice/service/WalletService.java b/src/main/java/com/nynja/walletservice/service/WalletService.java index e4f413fa60abff7cca32f8ced8ba3e3431a4a624..7ca8c2f6c05da1e9ffa1c0d131f603fa6a50c7d0 100644 --- a/src/main/java/com/nynja/walletservice/service/WalletService.java +++ b/src/main/java/com/nynja/walletservice/service/WalletService.java @@ -55,7 +55,7 @@ public class WalletService { } return Optional.ofNullable(seed.getSeedBytes()) - .map(bytes -> scanAccounts(deriveCoinPath(HDKeyDerivation.createMasterPrivateKey(bytes), dto.getCurrency()))) + .map(bytes -> scanAccounts(deriveCoinPath(HDKeyDerivation.createMasterPrivateKey(bytes), dto.getCurrency()), dto.getChainId())) .map(AddressesWithTxDto::new) .orElseThrow(() -> new RuntimeException("Error reading mnemonic bytes. Reason: the number is null.")); } @@ -64,7 +64,7 @@ public class WalletService { * Concurrent implementation of the BIP-44 Account discovery algorithm: * https://github.com/bitcoin/bips/blob/master/bip-0044.mediawiki#account-discovery */ - private Map> scanAccounts(DeterministicKey coinKey) { + private Map> scanAccounts(DeterministicKey coinKey, String chainId) { int accountNumber = 0; Map> accountToAddresses = new HashMap<>(); ExecutorService ec = Executors.newFixedThreadPool(configValues.getPoolSize()); @@ -74,7 +74,7 @@ public class WalletService { do { DeterministicKey externalChainKey = deriveNonHardened(coinKey.derive(accountNumber), EXTERNAL_CHAIN); - List results = performSearch(cs, externalChainKey); + List results = performSearch(cs, externalChainKey, chainId); mergeResults(accountToAddresses, accountNumber, results); } while (isNotEmpty(accountToAddresses.get(accountNumber++))); @@ -85,7 +85,7 @@ public class WalletService { return accountToAddresses; } - public List scanSingleAccount(String pub, String chainCode) { + public List scanSingleAccount(String pub, String chainCode, String chainId) { Objects.requireNonNull(pub, "Public key should not be null"); Objects.requireNonNull(chainCode, "Chain code should not be null"); @@ -98,13 +98,13 @@ public class WalletService { Base64.getDecoder().decode(chainCode) ); - return performSearch(cs, externalChainKey); + return performSearch(cs, externalChainKey, chainId); } finally { ec.shutdown(); } } - private List performSearch(CompletionService cs, DeterministicKey externalChainKey) { + private List performSearch(CompletionService cs, DeterministicKey externalChainKey, String chainId) { List addresses = new LinkedList<>(); int firstIdx = 0, lastIdx = BIP44_GAP; int[] counter = {0}; @@ -114,7 +114,7 @@ public class WalletService { List results = new ArrayList<>(BIP44_GAP - counter[0]); for (int childIndex = firstIdx; childIndex < lastIdx; childIndex++) { - futureTasks.add(cs.submit(searchJob(externalChainKey, childIndex))); + futureTasks.add(cs.submit(searchJob(externalChainKey, childIndex, chainId))); } handleSearchResults(futureTasks, results, cs); @@ -132,15 +132,14 @@ public class WalletService { return addresses; } - private Callable searchJob(DeterministicKey externalChainKey, int childIndex) { + private Callable searchJob(DeterministicKey externalChainKey, int childIndex, String chainId) { return () -> { String address = prepareETHAddress(deriveNonHardened(externalChainKey, childIndex)); return new ScanJobResult( childIndex, address, - //TODO Handle chainId - etherScanConsumer.getTxHistory(address, "", null, "1", "1", null).getResult() + etherScanConsumer.getTxHistory(address, chainId, null, "1", "1", null).getResult() ); }; } diff --git a/src/test/java/com/nynja/walletservice/controller/EthereumControllerTest.java b/src/test/java/com/nynja/walletservice/controller/EthereumControllerTest.java index 1f9a51f925e0f707adeea7e9ccfb65cc9e83ed6a..b187b6dd427537a14abd14383b4c269ea43698da 100644 --- a/src/test/java/com/nynja/walletservice/controller/EthereumControllerTest.java +++ b/src/test/java/com/nynja/walletservice/controller/EthereumControllerTest.java @@ -35,7 +35,7 @@ import static org.springframework.test.web.servlet.result.MockMvcResultMatchers. @RunWith(SpringRunner.class) public class EthereumControllerTest { - static final String RINKEBY_CHAIN_ID = "4"; + public static final String RINKEBY_CHAIN_ID = "4"; static final String TEST_ADDRESS = "0x9028B59227c5EDdA388f04cef5e43020fEd1E73a"; private static final String TEST_ADDRESS_PK = "3f5890282cc3b4eb8350823a1d1e950f7ba036b98cf074f299e1a9d09db196ca"; diff --git a/src/test/java/com/nynja/walletservice/service/WalletServiceTest.java b/src/test/java/com/nynja/walletservice/service/WalletServiceTest.java index 464caee3d14988f33c85b3247beac509c997e473..7ce15da9893b82ef0f6b5a7bb1d795e07512718c 100644 --- a/src/test/java/com/nynja/walletservice/service/WalletServiceTest.java +++ b/src/test/java/com/nynja/walletservice/service/WalletServiceTest.java @@ -16,6 +16,7 @@ import org.springframework.test.context.junit4.SpringRunner; import java.util.ArrayList; import java.util.List; +import static com.nynja.walletservice.controller.EthereumControllerTest.RINKEBY_CHAIN_ID; import static com.nynja.walletservice.service.WalletService.BIP44_GAP; import static org.junit.Assert.assertEquals; import static org.mockito.BDDMockito.given; @@ -74,7 +75,7 @@ public class WalletServiceTest { }); //when - List result = walletService.scanSingleAccount(PUB, CHAIN_CODE); + List result = walletService.scanSingleAccount(PUB, CHAIN_CODE, RINKEBY_CHAIN_ID); //The test data implies that there will be transaction history only for 0th and 2th addresses //This means that there will be 23 requests to the block-explorer to reach the BIP-44 gap and stop the discovery @@ -90,7 +91,7 @@ public class WalletServiceTest { .willReturn(emptyResponse); //when - List result = walletService.scanSingleAccount(PUB, CHAIN_CODE); + List result = walletService.scanSingleAccount(PUB, CHAIN_CODE, RINKEBY_CHAIN_ID); then(etherScanConsumer).should(times(BIP44_GAP)) .getTxHistory(anyString(), anyString(), anyString(), anyString(), anyString(), any());