From 5a8e3a7222df9a27c9913ba12d49d83189ca9ef1 Mon Sep 17 00:00:00 2001 From: AZ Date: Sat, 24 Dec 2016 14:36:44 +0100 Subject: [PATCH] WIP (once again) --- src/main/java/jota/IotaAPIProxy.java | 187 ++++++++++++----------- src/main/java/jota/utils/Converter.java | 2 +- src/test/java/jota/IotaAPIProxyTest.java | 7 +- 3 files changed, 104 insertions(+), 92 deletions(-) diff --git a/src/main/java/jota/IotaAPIProxy.java b/src/main/java/jota/IotaAPIProxy.java index d9c50c2..80b920c 100644 --- a/src/main/java/jota/IotaAPIProxy.java +++ b/src/main/java/jota/IotaAPIProxy.java @@ -26,13 +26,13 @@ import java.util.concurrent.TimeUnit; /** * IotaAPIProxy Builder. Usage: - * + *

* IotaApiProxy api = IotaApiProxy.Builder * .protocol("http") * .nodeAddress("localhost") * .port(12345) * .build(); - * + *

* GetNodeInfoResponse response = api.getNodeInfo(); * * @author davassi @@ -174,9 +174,9 @@ public class IotaAPIProxy { final Call res = service.getBalances(IotaGetBalancesRequest.createIotaGetBalancesRequest(threshold, addresses)); return wrapCheckedException(res).body(); } - + public GetBalancesResponse getBalances(Integer threshold, List addresses) { - return getBalances(threshold, addresses.toArray(new String[] {})); + return getBalances(threshold, addresses.toArray(new String[]{})); } public InterruptAttachingToTangleResponse interruptAttachingToTangle() { @@ -215,7 +215,7 @@ public class IotaAPIProxy { public GetNewAddressResponse getNewAddress(final String seed, final int index, final boolean checksum, final int total, final boolean returnAll) { final List allAddresses = new ArrayList<>(); - + // If total number of addresses to generate is supplied, simply generate // and return the list of all addresses if (total != 0) { @@ -227,10 +227,10 @@ public class IotaAPIProxy { // No total provided: Continue calling findTransactions to see if address was // already created if null, return list of addresses for (int i = index; ; i++) { - - final String newAddress = IotaAPIUtils.newAddress(seed, i, checksum); + + final String newAddress = IotaAPIUtils.newAddress(seed, i, checksum); final FindTransactionResponse response = findTransactionsByAddresses(new String[]{newAddress}); - + allAddresses.add(newAddress); if (response.getHashes().length == 0) { break; @@ -239,9 +239,9 @@ public class IotaAPIProxy { // If !returnAll return only the last address that was generated if (!returnAll) { - allAddresses.subList(0, allAddresses.size()-1).clear(); + allAddresses.subList(0, allAddresses.size() - 1).clear(); } - return GetNewAddressResponse.create(allAddresses); + return GetNewAddressResponse.create(allAddresses); } /* @@ -263,14 +263,13 @@ public class IotaAPIProxy { broadcastBundle getAccountData */ - + /** - * * @param trytes * @return a StoreTransactionsResponse */ - public StoreTransactionsResponse broadcastAndStore(final String ... trytes) { - + public StoreTransactionsResponse broadcastAndStore(final String... trytes) { + try { broadcastTransactions(trytes); } catch (Exception e) { @@ -279,31 +278,32 @@ public class IotaAPIProxy { } return storeTransactions(trytes); } - + /** * Facade method: Gets transactions to approve, attaches to Tangle, broadcasts and stores + * * @param {array} trytes - * @param {int} depth - * @param {int} minWeightMagnitude + * @param {int} depth + * @param {int} minWeightMagnitude * @return */ - public List sendTrytes(final String trytes, final int minWeightMagnitude) { - + public List sendTrytes(final String[] trytes, final int minWeightMagnitude) { + final GetTransactionsToApproveResponse txs = getTransactionsToApprove(minWeightMagnitude); - + // attach to tangle - do pow final GetAttachToTangleResponse res = attachToTangle(txs.getTrunkTransaction(), txs.getBranchTransaction(), minWeightMagnitude, trytes); - + try { broadcastAndStore(res.getTrytes()); } catch (Exception e) { log.error("Impossible to sendTrytes, aborting.", e); throw new IllegalStateException("sendTrytes Illegal state Exception"); } - + //return Arrays.stream(res.getTrytes()).map(Converter::transactionObject).collect(Collectors.toList()); final List trx = new ArrayList<>(); - + for (final String tx : Arrays.asList(res.getTrytes())) { trx.add(Converter.transactionObject(tx)); } @@ -311,15 +311,15 @@ public class IotaAPIProxy { } /** - * Wrapper function for getTrytes and transactionObjects - * gets the trytes and transaction object from a list of transaction hashes - * - * @method getTransactionsObjects - * @param {array} hashes - * @return - * @returns {function} callback - * @returns {object} success - **/ + * Wrapper function for getTrytes and transactionObjects + * gets the trytes and transaction object from a list of transaction hashes + * + * @param {array} hashes + * @return + * @method getTransactionsObjects + * @returns {function} callback + * @returns {object} success + **/ public List getTransactionsObjects(String[] hashes) { if (!InputValidator.isArrayOfHashes(hashes)) { @@ -327,9 +327,9 @@ public class IotaAPIProxy { } final GetTrytesResponse trytesResponse = getTrytes(hashes); - + final List trxs = new ArrayList<>(); - + for (final String tryte : trytesResponse.getTrytes()) { trxs.add(Converter.transactionObject(tryte)); } @@ -357,18 +357,18 @@ public class IotaAPIProxy { } /** - * Prepares transfer by generating bundle, finding and signing inputs - * - * @method prepareTransfers - * @param {string} seed - * @param {object} transfers - * @param {object} options - * @property {array} inputs Inputs used for signing. Needs to have correct keyIndex and address value - * @property {string} address Remainder address - * @param {function} callback - * @return - * @returns {array} trytes Returns bundle trytes - **/ + * Prepares transfer by generating bundle, finding and signing inputs + * + * @param {string} seed + * @param {object} transfers + * @param {object} options + * @param {function} callback + * @return + * @method prepareTransfers + * @property {array} inputs Inputs used for signing. Needs to have correct keyIndex and address value + * @property {string} address Remainder address + * @returns {array} trytes Returns bundle trytes + **/ public List prepareTransfers(final String seed, final List transfers, String remainder, List inputs) { // Input validation of transfers object @@ -379,7 +379,7 @@ public class IotaAPIProxy { // Create a new bundle final Bundle bundle = new Bundle(); final List signatureFragments = new ArrayList<>(); - + int totalValue = 0; String tag; @@ -399,7 +399,7 @@ public class IotaAPIProxy { // While there is still a message, copy it while (!msgCopy.isEmpty()) { - + String fragment = StringUtils.substring(msgCopy, 0, 2187); msgCopy = StringUtils.substring(msgCopy, 2187, msgCopy.length()); @@ -443,7 +443,7 @@ public class IotaAPIProxy { // Case 1: user provided inputs // Validate the inputs by calling getBalances - if (!inputs.isEmpty()) { + if (inputs != null && !inputs.isEmpty()) { // Get list if addresses of the provided inputs List inputsAddresses = new ArrayList<>(); @@ -453,10 +453,11 @@ public class IotaAPIProxy { GetBalancesResponse resbalances = getBalances(100, inputsAddresses); String[] balances = resbalances.getBalances(); - + List confirmedInputs = new ArrayList<>(); - int totalBalance = 0; int i = 0; + int totalBalance = 0; + int i = 0; for (String balance : balances) { long thisBalance = Integer.parseInt(balance); totalBalance += thisBalance; @@ -496,24 +497,31 @@ public class IotaAPIProxy { List trxb = bundle.getTransactions(); List bundleTrytes = new ArrayList<>(); for (Transaction tx : trxb) { - jota.utils.IotaAPIUtils.transactionTrytes(tx); + bundleTrytes.add(jota.utils.IotaAPIUtils.transactionTrytes(tx)); } Collections.reverse(bundleTrytes); return bundleTrytes; } } - + + public Transaction[] sendTransfer(String seed, int depth, int minWeightMagnitude, Transfer[] transactions, Input[] inputs, String address) { + + List trytes = prepareTransfers(seed, Arrays.asList(transactions), address, Arrays.asList(inputs)); + List trxs = sendTrytes(trytes.toArray(new String[trytes.size()]), minWeightMagnitude); + return trxs.toArray(new Transaction[trxs.size()]); + } + /** - * Gets the inputs of a seed - * - * @method getInputs - * @param {string} seed - * @param {object} options - * @property {int} start Starting key index - * @property {int} end Ending key index - * @property {int} threshold Min balance required - * @param {function} callback - **/ + * Gets the inputs of a seed + * + * @param {string} seed + * @param {object} options + * @param {function} callback + * @method getInputs + * @property {int} start Starting key index + * @property {int} end Ending key index + * @property {int} threshold Min balance required + **/ public GetBalancesAndFormatResponse getInputs(final String seed, final List balances, int start, int end, int threshold) { // validate the seed @@ -566,18 +574,19 @@ public class IotaAPIProxy { // If threshold defined, keep track of whether reached or not // else set default to true - boolean thresholdReached = threshold != 0 ? false : true; int i = -1; - + boolean thresholdReached = threshold != 0 ? false : true; + int i = -1; + List inputs = new ArrayList<>(); long totalBalance = 0; - + for (String address : addresses) { - + long balance = Long.parseLong(balances.get(++i)); - + if (balance > 0) { - final Input newEntry = new Input(address, balance, start+i); - + final Input newEntry = new Input(address, balance, start + i); + inputs.add(newEntry); // Increase totalBalance of all aggregated inputs totalBalance += balance; @@ -591,31 +600,31 @@ public class IotaAPIProxy { if (thresholdReached) { return GetBalancesAndFormatResponse.create(inputs, totalBalance); - } + } throw new IllegalStateException("Not enough balance"); } /** - * Gets the associated bundle transactions of a single transaction - * Does validation of signatures, total sum as well as bundle order + * Gets the associated bundle transactions of a single transaction + * Does validation of signatures, total sum as well as bundle order * - * @method getBundle - * @param {string} transaction Hash of a tail transaction - * @returns {list} bundle Transaction objects + * @param {string} transaction Hash of a tail transaction + * @method getBundle + * @returns {list} bundle Transaction objects **/ public GetBundleResponse getBundle(String transaction) { return null; //IotaAPIUtils.getBundle(transaction); } /** - * Replays a transfer by doing Proof of Work again + * Replays a transfer by doing Proof of Work again * - * @method replayBundle - * @param {string} tail - * @param {int} depth - * @param {int} minWeightMagnitude - * @param {function} callback - * @returns {object} analyzed Transaction objects + * @param {string} tail + * @param {int} depth + * @param {int} minWeightMagnitude + * @param {function} callback + * @method replayBundle + * @returns {object} analyzed Transaction objects **/ public List replayTransfer(String transaction, int depth, int minWeightMagnitude) { @@ -628,16 +637,16 @@ public class IotaAPIProxy { bundleTrytes.add(IotaAPIUtils.transactionTrytes(element)); } - return sendTrytes(bundleTrytes.get(0), minWeightMagnitude); + return sendTrytes(bundleTrytes.toArray(new String[bundleTrytes.size()]), minWeightMagnitude); } /** - * Wrapper function for getNodeInfo and getInclusionStates + * Wrapper function for getNodeInfo and getInclusionStates * - * @method getLatestInclusion - * @param {array} hashes - * @returns {function} callback - * @returns {array} state + * @param {array} hashes + * @method getLatestInclusion + * @returns {function} callback + * @returns {array} state **/ public GetInclusionStateResponse getLatestInclusion(String[] hashes) { GetNodeInfoResponse getNodeInfoResponse = getNodeInfo(); diff --git a/src/main/java/jota/utils/Converter.java b/src/main/java/jota/utils/Converter.java index ec85c8f..5e76567 100644 --- a/src/main/java/jota/utils/Converter.java +++ b/src/main/java/jota/utils/Converter.java @@ -143,7 +143,7 @@ public class Converter { remainder = MIN_TRIT_VALUE; absoluteValue++; } - destination[offset + i] = remainder; + destination[offset +i ] = remainder; } if (value < 0) { diff --git a/src/test/java/jota/IotaAPIProxyTest.java b/src/test/java/jota/IotaAPIProxyTest.java index ffb52ac..6202ba6 100644 --- a/src/test/java/jota/IotaAPIProxyTest.java +++ b/src/test/java/jota/IotaAPIProxyTest.java @@ -13,6 +13,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertThat; /** @@ -161,8 +162,10 @@ public class IotaAPIProxyTest { @Test public void shouldPrepareTransfer() { List transfers = new ArrayList<>(); - transfers.add(new jota.model.Transfer(TEST_ADDRESS_WITH_CHECKSUM, 0, TEST_MESSAGE, TEST_TAG)); - proxy.prepareTransfers(TEST_SEED, transfers, null, null); + transfers.add(new jota.model.Transfer("SEOOMCIJRDPDYDXVMUVUJPUGMNO9GGKYRTQZYPUXBKTBFWMMGXCLYPASCXF9DXEXZBVXZYZOPVGGDHJFJ", 1, TEST_MESSAGE, TEST_TAG)); + List trytes = proxy.prepareTransfers("IHDEENZYITYVYSPKAURUZAQKGVJEREFDJMYTANNXXGPZ9GJWTEOJJ9IPMXOGZNQLSNMFDSQOTZAEETUEA", transfers, null, null); + assertNotNull(trytes); + assertThat(trytes.isEmpty(), Is.is(false)); } @Test