diff --git a/jota/src/main/java/jota/IotaAPI.java b/jota/src/main/java/jota/IotaAPI.java index 7ee7c16..9cc2c3a 100644 --- a/jota/src/main/java/jota/IotaAPI.java +++ b/jota/src/main/java/jota/IotaAPI.java @@ -1,8 +1,7 @@ package jota; -import com.google.gson.Gson; import jota.dto.response.*; -import jota.error.*; +import jota.error.ArgumentException; import jota.model.*; import jota.pow.ICurl; import jota.pow.SpongeFactory; @@ -13,16 +12,19 @@ import org.slf4j.LoggerFactory; import java.util.*; +import static jota.utils.Constants.*; + + /** * IotaAPI Builder. Usage: *

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

- * GetNodeInfoResponse response = api.getNodeInfo(); + * {@code IotaApiProxy api = IotaApiProxy.Builder} + * {@code .protocol("http")} + * {@code .nodeAddress("localhost")} + * {@code .port(12345)} + * {@code .build();} + * + * {@code GetNodeInfoResponse response = api.getNodeInfo();} * * @author davassi */ @@ -47,14 +49,9 @@ public class IotaAPI extends IotaAPICore { * @param total Total number of addresses to generate. * @param returnAll If true, it returns all addresses which were deterministically generated (until findTransactions returns null). * @return An array of strings with the specifed number of addresses. - * @throws InvalidAddressException is thrown when the specified address is not an valid address. - * @throws InvalidSecurityLevelException is thrown when the specified security level is not valid. + * @throws ArgumentException is thrown when the specified input is not valid. */ - public GetNewAddressResponse getNewAddress(final String seed, int security, final int index, final boolean checksum, final int total, final boolean returnAll) throws InvalidSecurityLevelException, InvalidAddressException { - - if (security < 1) { - throw new InvalidSecurityLevelException(); - } + public GetNewAddressResponse getNewAddress(final String seed, int security, final int index, final boolean checksum, final int total, final boolean returnAll) throws ArgumentException { StopWatch stopWatch = new StopWatch(); @@ -99,31 +96,20 @@ public class IotaAPI extends IotaAPICore { * @param end Ending key index. * @param inclusionStates If true, it gets the inclusion states of the transfers. * @return Bundle of transfers. - * @throws InvalidAddressException is thrown when the specified address is not an valid address. - * @throws ArgumentException is thrown when an invalid argument is provided. - * @throws InvalidBundleException is thrown if an invalid bundle was found or provided. - * @throws InvalidSignatureException is thrown when an invalid signature is encountered. - * @throws NoNodeInfoException is thrown when its not possible to get node info. - * @throws NoInclusionStatesException when it not possible to get a inclusion state. - * @throws InvalidSecurityLevelException is thrown when the specified security level is not valid. + * @throws ArgumentException is thrown when the specified input is not valid. */ - public GetTransferResponse getTransfers(String seed, int security, Integer start, Integer end, Boolean inclusionStates) throws ArgumentException, InvalidBundleException, InvalidSignatureException, NoNodeInfoException, NoInclusionStatesException, InvalidSecurityLevelException, InvalidAddressException { - StopWatch stopWatch = new StopWatch(); + public GetTransferResponse getTransfers(String seed, int security, Integer start, Integer end, Boolean inclusionStates) throws ArgumentException { + // validate seed if ((!InputValidator.isValidSeed(seed))) { - throw new IllegalStateException("Invalid Seed"); + throw new IllegalStateException(INVALID_SEED_INPUT_ERROR); } - if (security < 1) { - throw new InvalidSecurityLevelException(); - } - - start = start == null ? 0 : start; - if (start > end || end > (start + 500)) { - throw new ArgumentException(); + throw new ArgumentException(INVALID_INPUT_ERROR); } - StopWatch sw = new StopWatch(); + + StopWatch stopWatch = new StopWatch(); GetNewAddressResponse gnr = getNewAddress(seed, security, start, false, end, true); if (gnr != null && gnr.getAddresses() != null) { @@ -139,15 +125,11 @@ public class IotaAPI extends IotaAPICore { * @param addresses List of addresses. * @param inclusionStates If true, it gets the inclusion states of the transfers. * @return A Transaction objects. - * @throws ArgumentException is thrown when an invalid argument is provided. - * @throws InvalidBundleException is thrown if an invalid bundle was found or provided. - * @throws InvalidSignatureException is thrown when an invalid signature is encountered. - * @throws NoNodeInfoException is thrown when its not possible to get node info. - * @throws NoInclusionStatesException when it not possible to get a inclusion state. + * @throws ArgumentException is thrown when the specified input is not valid. */ - public Bundle[] bundlesFromAddresses(String[] addresses, final Boolean inclusionStates) throws ArgumentException, InvalidBundleException, InvalidSignatureException, NoNodeInfoException, NoInclusionStatesException { + public Bundle[] bundlesFromAddresses(String[] addresses, final Boolean inclusionStates) throws ArgumentException { - List trxs = findTransactionObjects(addresses); + List trxs = findTransactionObjectsByAddresses(addresses); // set of tail transactions List tailTransactions = new ArrayList<>(); List nonTailBundleHashes = new ArrayList<>(); @@ -180,13 +162,9 @@ public class IotaAPI extends IotaAPICore { // of the tail transactions, and thus the bundles GetInclusionStateResponse gisr = null; if (tailTxArray.length != 0 && inclusionStates) { - try { gisr = getLatestInclusion(tailTxArray); - } catch (IllegalAccessError ignored) { - throw new NoInclusionStatesException(); - } if (gisr == null || gisr.getStates() == null || gisr.getStates().length == 0) { - throw new NoInclusionStatesException(); + throw new IllegalStateException(GET_INCLUSION_STATE_RESPONSE_ERROR); } } final GetInclusionStateResponse finalInclusionStates = gisr; @@ -210,8 +188,8 @@ public class IotaAPI extends IotaAPICore { finalBundles.add(gbr); } // If error returned from getBundle, simply ignore it because the bundle was most likely incorrect - } catch (InvalidBundleException | ArgumentException | InvalidSignatureException e) { - log.warn("GetBundleError: ", e); + } catch (ArgumentException e) { + log.warn(GET_BUNDLE_RESPONSE_ERROR); } } }); @@ -229,15 +207,18 @@ public class IotaAPI extends IotaAPICore { * * @param trytes The trytes. * @return A StoreTransactionsResponse. - * @throws BroadcastAndStoreException is thrown if its not possible to broadcast and store. + * @throws ArgumentException is thrown when the specified input is not valid. */ - public StoreTransactionsResponse broadcastAndStore(final String... trytes) throws BroadcastAndStoreException { + public StoreTransactionsResponse broadcastAndStore(final String... trytes) throws ArgumentException { + + if (!InputValidator.isArrayOfAttachedTrytes(trytes)) { + throw new ArgumentException(INVALID_TRYTES_INPUT_ERROR); + } try { broadcastTransactions(trytes); } catch (Exception e) { - log.error("Impossible to broadcastAndStore, aborting.", e); - throw new BroadcastAndStoreException(); + throw new ArgumentException(e.toString()); } return storeTransactions(trytes); } @@ -249,18 +230,17 @@ public class IotaAPI extends IotaAPICore { * @param depth The depth. * @param minWeightMagnitude The minimum weight magnitude. * @return Transactions objects. - * @throws InvalidTrytesException is thrown when invalid trytes is provided. + * @throws ArgumentException is thrown when invalid trytes is provided. */ - public List sendTrytes(final String[] trytes, final int depth, final int minWeightMagnitude) throws InvalidTrytesException { + public List sendTrytes(final String[] trytes, final int depth, final int minWeightMagnitude) throws ArgumentException { final GetTransactionsToApproveResponse txs = getTransactionsToApprove(depth); // attach to tangle - do pow - System.out.println(new Gson().toJson(txs)); final GetAttachToTangleResponse res = attachToTangle(txs.getTrunkTransaction(), txs.getBranchTransaction(), minWeightMagnitude, trytes); try { broadcastAndStore(res.getTrytes()); - } catch (BroadcastAndStoreException e) { + } catch (ArgumentException e) { return new ArrayList<>(); } @@ -279,10 +259,10 @@ public class IotaAPI extends IotaAPICore { * @param hashes The hashes * @return Transaction objects. **/ - public List getTransactionsObjects(String[] hashes) { + public List findTransactionsObjectsByHashes(String[] hashes) throws ArgumentException { if (!InputValidator.isArrayOfHashes(hashes)) { - throw new IllegalStateException("Not an Array of Hashes: " + Arrays.toString(hashes)); + throw new IllegalStateException(INVALID_HASHES_INPUT_ERROR); } final GetTrytesResponse trytesResponse = getTrytes(hashes); @@ -297,83 +277,99 @@ public class IotaAPI extends IotaAPICore { /** * Wrapper function for findTransactions, getTrytes and transactionObjects. - * Returns the transactionObject of a transaction hash. The input can be a valid findTransactions input. + * Returns the transactionObject of a transaction hash. The input can be a list of valid addresses. * - * @param input The inputs. + * @param addresses The addresses. * @return Transactions. **/ - public List findTransactionObjects(String[] input) { - FindTransactionResponse ftr = findTransactions(input, null, null, null); + public List findTransactionObjectsByAddresses(String[] addresses) throws ArgumentException { + List addressesWithoutChecksum = new ArrayList<>(); + + for (String address : addresses) { + String addressO = Checksum.removeChecksum(address); + addressesWithoutChecksum.add(addressO); + } + + FindTransactionResponse ftr = findTransactions(addressesWithoutChecksum.toArray(new String[]{}), null, null, null); if (ftr == null || ftr.getHashes() == null) return new ArrayList<>(); // get the transaction objects of the transactions - return getTransactionsObjects(ftr.getHashes()); + return findTransactionsObjectsByHashes(ftr.getHashes()); } /** * Wrapper function for findTransactions, getTrytes and transactionObjects. - * Returns the transactionObject of a transaction hash. The input can be a valid. - * findTransactions input + * Returns the transactionObject of a transaction hash. The input can be a list of valid tags. * - * @param input The inputs. + * @param tags The tags. * @return Transactions. **/ - public List findTransactionObjectsByBundle(String[] input) { - FindTransactionResponse ftr = findTransactions(null, null, null, input); + public List findTransactionObjectsByTag(String[] tags) throws ArgumentException { + FindTransactionResponse ftr = findTransactions(null, tags, null, null); + if (ftr == null || ftr.getHashes() == null) + return new ArrayList<>(); + // get the transaction objects of the transactions + return findTransactionsObjectsByHashes(ftr.getHashes()); + } + + /** + * Wrapper function for findTransactions, getTrytes and transactionObjects. + * Returns the transactionObject of a transaction hash. The input can be a list of valid approvees. + * + * @param approvees The approvees. + * @return Transactions. + **/ + public List findTransactionObjectsByApprovees(String[] approvees) throws ArgumentException { + FindTransactionResponse ftr = findTransactions(null, null, approvees, null); + if (ftr == null || ftr.getHashes() == null) + return new ArrayList<>(); + // get the transaction objects of the transactions + return findTransactionsObjectsByHashes(ftr.getHashes()); + } + + /** + * Wrapper function for findTransactions, getTrytes and transactionObjects. + * Returns the transactionObject of a transaction hash. The input can be a list of valid bundles. + * findTransactions input + * + * @param bundles The bundles. + * @return Transactions. + **/ + public List findTransactionObjectsByBundle(String[] bundles) throws ArgumentException { + FindTransactionResponse ftr = findTransactions(null, null, null, bundles); if (ftr == null || ftr.getHashes() == null) return new ArrayList<>(); // get the transaction objects of the transactions - return getTransactionsObjects(ftr.getHashes()); + return findTransactionsObjectsByHashes(ftr.getHashes()); } /** * Prepares transfer by generating bundle, finding and signing inputs. * - * @param seed 81-tryte encoded address of recipient. - * @param security The security level of private key / seed. - * @param transfers Array of transfer objects. - * @param remainder If defined, this address will be used for sending the remainder value (of the inputs) to. - * @param inputs The inputs. - * @return Returns bundle trytes. - * @throws InvalidAddressException is thrown when the specified address is not an valid address. - * @throws NotEnoughBalanceException is thrown when a transfer fails because their is not enough balance to perform the transfer. - * @throws InvalidSecurityLevelException is thrown when the specified security level is not valid. - * @throws InvalidTransferException is thrown when an invalid transfer is provided. - */ - public List prepareTransfers(String seed, int security, final List transfers, String remainder, List inputs) throws NotEnoughBalanceException, InvalidSecurityLevelException, InvalidAddressException, InvalidTransferException { - return prepareTransfers(seed, security, transfers, remainder, inputs, true); - } - - /** - * Prepares transfer by generating bundle, finding and signing inputs. - * - * @param seed 81-tryte encoded address of recipient. + * @param seed Tryte-encoded private key / seed. * @param security The security level of private key / seed. * @param transfers Array of transfer objects. * @param remainder If defined, this address will be used for sending the remainder value (of the inputs) to. * @param inputs The inputs. * @param validateInputs whether or not to validate the balances of the provided inputs * @return Returns bundle trytes. - * @throws InvalidAddressException is thrown when the specified address is not an valid address. - * @throws NotEnoughBalanceException is thrown when a transfer fails because their is not enough balance to perform the transfer. - * @throws InvalidSecurityLevelException is thrown when the specified security level is not valid. - * @throws InvalidTransferException is thrown when an invalid transfer is provided. + * @throws ArgumentException is thrown when the specified input is not valid. */ - public List prepareTransfers(String seed, int security, final List transfers, String remainder, List inputs, boolean validateInputs) throws NotEnoughBalanceException, InvalidSecurityLevelException, InvalidAddressException, InvalidTransferException { - - // Input validation of transfers object - if (!InputValidator.isTransfersCollectionValid(transfers)) { - throw new InvalidTransferException(); - } + public List prepareTransfers(String seed, int security, final List transfers, String remainder, List inputs, boolean validateInputs) throws ArgumentException { // validate seed if ((!InputValidator.isValidSeed(seed))) { - throw new IllegalStateException("Invalid Seed"); + throw new IllegalStateException(INVALID_SEED_INPUT_ERROR); } if (security < 1) { - throw new InvalidSecurityLevelException(); + throw new ArgumentException(INVALID_SECURITY_LEVEL_INPUT_ERROR); + } + + // Input validation of transfers object + if (!InputValidator.isTransfersCollectionValid(transfers)) { + throw new ArgumentException(INVALID_TRANSFERS_INPUT_ERROR); } // Create a new bundle @@ -382,55 +378,58 @@ public class IotaAPI extends IotaAPICore { long totalValue = 0; String tag = ""; - // Iterate over all transfers, get totalValue // and prepare the signatureFragments, message and tag for (final Transfer transfer : transfers) { - // If address with checksum then remove checksum - if (Checksum.isAddressWithChecksum(transfer.getAddress())) + // remove the checksum of the address if provided + if (Checksum.isValidChecksum(transfer.getAddress())) { transfer.setAddress(Checksum.removeChecksum(transfer.getAddress())); + } int signatureMessageLength = 1; // If message longer than 2187 trytes, increase signatureMessageLength (add 2nd transaction) - if (transfer.getMessage().length() > 2187) { + if (transfer.getMessage().length() > Constants.MESSAGE_LENGTH) { // Get total length, message / maxLength (2187 trytes) - signatureMessageLength += Math.floor(transfer.getMessage().length() / 2187); + signatureMessageLength += Math.floor(transfer.getMessage().length() / Constants.MESSAGE_LENGTH); String msgCopy = transfer.getMessage(); // 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()); + String fragment = StringUtils.substring(msgCopy, 0, Constants.MESSAGE_LENGTH); + msgCopy = StringUtils.substring(msgCopy, Constants.MESSAGE_LENGTH, msgCopy.length()); // Pad remainder of fragment - fragment = StringUtils.rightPad(fragment, 2187, '9'); + fragment = StringUtils.rightPad(fragment, Constants.MESSAGE_LENGTH, '9'); signatureFragments.add(fragment); } } else { // Else, get single fragment with 2187 of 9's trytes - String fragment = StringUtils.substring(transfer.getMessage(), 0, 2187); - - fragment = StringUtils.rightPad(fragment, 2187, '9'); + String fragment = transfer.getMessage(); + if (transfer.getMessage().length() < Constants.MESSAGE_LENGTH) { + fragment = StringUtils.rightPad(fragment, Constants.MESSAGE_LENGTH, '9'); + } signatureFragments.add(fragment); } + tag = transfer.getTag(); + + // pad for required 27 tryte length + if (transfer.getTag().length() < Constants.TAG_LENGTH) { + tag = StringUtils.rightPad(tag, Constants.TAG_LENGTH, '9'); + } + + // get current timestamp in seconds long timestamp = (long) Math.floor(Calendar.getInstance().getTimeInMillis() / 1000); - // If no tag defined, get 27 tryte tag. - tag = transfer.getTag().isEmpty() ? "999999999999999999999999999" : transfer.getTag(); - - // Pad for required 27 tryte length - tag = StringUtils.rightPad(tag, 27, '9'); - // Add first entry to the bundle bundle.addEntry(signatureMessageLength, transfer.getAddress(), transfer.getValue(), tag, timestamp); // Sum up total value @@ -439,14 +438,14 @@ public class IotaAPI extends IotaAPICore { // Get inputs if we are sending tokens if (totalValue != 0) { - if (!validateInputs) - return addRemainder(seed, security, inputs, bundle, tag, totalValue, remainder, signatureFragments); + // Case 1: user provided inputs // Validate the inputs by calling getBalances - if (!validateInputs) - return addRemainder(seed, security, inputs, bundle, tag, totalValue, remainder, signatureFragments); if (inputs != null && !inputs.isEmpty()) { + if (!validateInputs) { + return addRemainder(seed, security, inputs, bundle, tag, totalValue, remainder, signatureFragments); + } // Get list if addresses of the provided inputs List inputsAddresses = new ArrayList<>(); for (final Input i : inputs) { @@ -479,7 +478,7 @@ public class IotaAPI extends IotaAPICore { // Return not enough balance error if (totalValue > totalBalance) { - throw new IllegalStateException("Not enough balance"); + throw new IllegalStateException(NOT_ENOUGH_BALANCE_ERROR); } return addRemainder(seed, security, confirmedInputs, bundle, tag, totalValue, remainder, signatureFragments); @@ -493,7 +492,7 @@ public class IotaAPI extends IotaAPICore { @SuppressWarnings("unchecked") GetBalancesAndFormatResponse newinputs = getInputs(seed, security, 0, 0, totalValue); // If inputs with enough balance - return addRemainder(seed, security, newinputs.getInput(), bundle, tag, totalValue, remainder, signatureFragments); + return addRemainder(seed, security, newinputs.getInputs(), bundle, tag, totalValue, remainder, signatureFragments); } } else { @@ -520,27 +519,27 @@ public class IotaAPI extends IotaAPICore { * @param start Starting key index. * @param end Ending key index. * @param threshold Min balance required. - * @throws InvalidAddressException is thrown when the specified address is not an valid address. - * @throws InvalidSecurityLevelException is thrown when the specified security level is not valid. + * @throws ArgumentException is thrown when the specified input is not valid. **/ - public GetBalancesAndFormatResponse getInputs(String seed, int security, int start, int end, long threshold) throws InvalidSecurityLevelException, InvalidAddressException { - StopWatch stopWatch = new StopWatch(); + public GetBalancesAndFormatResponse getInputs(String seed, int security, int start, int end, long threshold) throws ArgumentException { // validate the seed if ((!InputValidator.isValidSeed(seed))) { - throw new IllegalStateException("Invalid Seed"); + throw new IllegalStateException(INVALID_SEED_INPUT_ERROR); } if (security < 1) { - throw new InvalidSecurityLevelException(); + throw new ArgumentException(INVALID_SECURITY_LEVEL_INPUT_ERROR); } // If start value bigger than end, return error // or if difference between end and start is bigger than 500 keys if (start > end || end > (start + 500)) { - throw new IllegalStateException("Invalid inputs provided"); + throw new IllegalStateException(INVALID_INPUT_ERROR); } + StopWatch stopWatch = new StopWatch(); + // Case 1: start and end // // If start and end is defined by the user, simply iterate through the keys @@ -555,7 +554,7 @@ public class IotaAPI extends IotaAPICore { allAddresses.add(address); } - return getBalanceAndFormat(allAddresses, threshold, start, end, stopWatch, security); + return getBalanceAndFormat(allAddresses, threshold, start, stopWatch, security); } // Case 2: iterate till threshold || end // @@ -564,7 +563,7 @@ public class IotaAPI extends IotaAPICore { // We then do getBalance, format the output and return it else { final GetNewAddressResponse res = getNewAddress(seed, security, start, false, 0, true); - return getBalanceAndFormat(res.getAddresses(), threshold, start, end, stopWatch, security); + return getBalanceAndFormat(res.getAddresses(), threshold, start, stopWatch, security); } } @@ -574,16 +573,15 @@ public class IotaAPI extends IotaAPICore { * @param addresses The addresses. * @param threshold Min balance required. * @param start Starting key index. - * @param end Ending key index. * @param stopWatch the stopwatch. * @param security The security level of private key / seed. * @return Inputs object. - * @throws InvalidSecurityLevelException is thrown when the specified security level is not valid. + * @throws ArgumentException is thrown when the specified security level is not valid. **/ - public GetBalancesAndFormatResponse getBalanceAndFormat(final List addresses, long threshold, int start, int end, StopWatch stopWatch, int security) throws InvalidSecurityLevelException { + public GetBalancesAndFormatResponse getBalanceAndFormat(final List addresses, long threshold, int start, StopWatch stopWatch, int security) throws ArgumentException, IllegalStateException { if (security < 1) { - throw new InvalidSecurityLevelException(); + throw new ArgumentException(INVALID_SECURITY_LEVEL_INPUT_ERROR); } GetBalancesResponse getBalancesResponse = getBalances(100, addresses); @@ -618,7 +616,7 @@ public class IotaAPI extends IotaAPICore { if (thresholdReached) { return GetBalancesAndFormatResponse.create(inputs, totalBalance, stopWatch.getElapsedTimeMili()); } - throw new IllegalStateException("Not enough balance"); + throw new IllegalStateException(NOT_ENOUGH_BALANCE_ERROR); } /** @@ -627,18 +625,21 @@ public class IotaAPI extends IotaAPICore { * * @param transaction The transaction encoded in trytes. * @return an array of bundle, if there are multiple arrays it means that there are conflicting bundles. - * @throws ArgumentException is thrown when an invalid argument is provided. - * @throws InvalidBundleException is thrown if an invalid bundle was found or provided. - * @throws InvalidSignatureException is thrown when an invalid signature is encountered. + * @throws ArgumentException is thrown when the specified input is not valid. */ - public GetBundleResponse getBundle(String transaction) throws ArgumentException, InvalidBundleException, InvalidSignatureException { - StopWatch stopWatch = new StopWatch(); + public GetBundleResponse getBundle(String transaction) throws ArgumentException { + + if (!InputValidator.isHash(transaction)) { + throw new ArgumentException(INVALID_HASHES_INPUT_ERROR); + } Bundle bundle = traverseBundle(transaction, null, new Bundle()); if (bundle == null) { - throw new ArgumentException("Unknown Bundle"); + throw new ArgumentException(INVALID_BUNDLE_ERROR); } + StopWatch stopWatch = new StopWatch(); + long totalSum = 0; String bundleHash = bundle.getTransactions().get(0).getBundle(); @@ -653,11 +654,10 @@ public class IotaAPI extends IotaAPICore { totalSum += bundleValue; if (i != bundle.getTransactions().get(i).getCurrentIndex()) { - throw new ArgumentException("Invalid Bundle"); + throw new ArgumentException(INVALID_BUNDLE_ERROR); } String trxTrytes = trx.toTrytes().substring(2187, 2187 + 162); - //System.out.println("Bundlesize "+bundle.getTransactions().size()+" "+trxTrytes); // Absorb bundle hash + value + timestamp + lastIndex + currentIndex trytes. curl.absorb(Converter.trits(trxTrytes)); // Check if input transaction @@ -682,17 +682,19 @@ public class IotaAPI extends IotaAPICore { } // Check for total sum, if not equal 0 return error - if (totalSum != 0) throw new InvalidBundleException("Invalid Bundle Sum"); + if (totalSum != 0) + throw new ArgumentException(INVALID_BUNDLE_SUM_ERROR); int[] bundleFromTrxs = new int[243]; curl.squeeze(bundleFromTrxs); String bundleFromTxString = Converter.trytes(bundleFromTrxs); // Check if bundle hash is the same as returned by tx object - if (!bundleFromTxString.equals(bundleHash)) throw new InvalidBundleException("Invalid Bundle Hash"); + if (!bundleFromTxString.equals(bundleHash)) + throw new ArgumentException(INVALID_BUNDLE_HASH_ERROR); // Last tx in the bundle should have currentIndex === lastIndex bundle.setLength(bundle.getTransactions().size()); if (!(bundle.getTransactions().get(bundle.getLength() - 1).getCurrentIndex() == (bundle.getTransactions().get(bundle.getLength() - 1).getLastIndex()))) - throw new InvalidBundleException("Invalid Bundle"); + throw new ArgumentException(INVALID_BUNDLE_ERROR); // Validate the signatures for (Signature aSignaturesToValidate : signaturesToValidate) { @@ -700,7 +702,8 @@ public class IotaAPI extends IotaAPICore { String address = aSignaturesToValidate.getAddress(); boolean isValidSignature = new Signing(customCurl.clone()).validateSignatures(address, signatureFragments, bundleHash); - if (!isValidSignature) throw new InvalidSignatureException(); + if (!isValidSignature) + throw new ArgumentException(INVALID_SIGNATURES_ERROR); } return GetBundleResponse.create(bundle.getTransactions(), stopWatch.getElapsedTimeMili()); @@ -719,18 +722,13 @@ public class IotaAPI extends IotaAPICore { * @param end Ending key index. * @param inclusionStates If true, it gets the inclusion states of the transfers. * @param threshold Min balance required. - * @throws InvalidBundleException is thrown if an invalid bundle was found or provided. - * @throws ArgumentException is thrown when an invalid argument is provided. - * @throws InvalidSignatureException is thrown when an invalid signature is encountered. - * @throws InvalidTrytesException is thrown when invalid trytes is provided. - * @throws InvalidSecurityLevelException is thrown when the specified security level is not valid. - * @throws InvalidAddressException is thrown when the specified address is not an valid address. - * @throws NoInclusionStatesException is thrown when it not possible to get a inclusion state. - * @throws NoNodeInfoException is thrown when its not possible to get node info. + * @throws ArgumentException is thrown when the specified input is not valid. */ - public GetAccountDataResponse getAccountData(String seed, int security, int index, boolean checksum, int total, boolean returnAll, int start, int end, boolean inclusionStates, long threshold) - throws InvalidBundleException, ArgumentException, InvalidSignatureException, - InvalidTrytesException, InvalidSecurityLevelException, InvalidAddressException, NoInclusionStatesException, NoNodeInfoException { + public GetAccountDataResponse getAccountData(String seed, int security, int index, boolean checksum, int total, boolean returnAll, int start, int end, boolean inclusionStates, long threshold) throws ArgumentException { + + if (start > end || end > (start + 1000)) { + throw new ArgumentException(INVALID_INPUT_ERROR); + } StopWatch stopWatch = new StopWatch(); @@ -738,7 +736,7 @@ public class IotaAPI extends IotaAPICore { GetTransferResponse gtr = getTransfers(seed, security, start, end, inclusionStates); GetBalancesAndFormatResponse gbr = getInputs(seed, security, start, end, threshold); - return GetAccountDataResponse.create(gna.getAddresses(), gtr.getTransfers(), gbr.getTotalBalance(), stopWatch.getElapsedTimeMili()); + return GetAccountDataResponse.create(gna.getAddresses(), gtr.getTransfers(), gbr.getInputs(), gbr.getTotalBalance(), stopWatch.getElapsedTimeMili()); } /** @@ -748,12 +746,14 @@ public class IotaAPI extends IotaAPICore { * @param depth The depth. * @param minWeightMagnitude The minimum weight magnitude. * @return Analyzed Transaction objects. - * @throws InvalidBundleException is thrown if an invalid bundle was found or provided. - * @throws ArgumentException is thrown when an invalid argument is provided. - * @throws InvalidSignatureException is thrown when an invalid signature is encountered. - * @throws InvalidTransferException is thrown when an invalid transfer is provided. + * @throws ArgumentException is thrown when the specified input is not valid. */ - public ReplayBundleResponse replayBundle(String transaction, int depth, int minWeightMagnitude) throws InvalidBundleException, ArgumentException, InvalidSignatureException, InvalidTrytesException { + public ReplayBundleResponse replayBundle(String transaction, int depth, int minWeightMagnitude) throws ArgumentException { + + if (!InputValidator.isHash(transaction)) { + throw new ArgumentException(INVALID_TAIL_HASH_INPUT_ERROR); + } + StopWatch stopWatch = new StopWatch(); List bundleTrytes = new ArrayList<>(); @@ -786,11 +786,9 @@ public class IotaAPI extends IotaAPICore { * * @param hashes The hashes. * @return Inclusion state. - * @throws NoNodeInfoException is thrown when its not possible to get node info. */ - public GetInclusionStateResponse getLatestInclusion(String[] hashes) throws NoNodeInfoException { + public GetInclusionStateResponse getLatestInclusion(String[] hashes) throws ArgumentException { GetNodeInfoResponse getNodeInfoResponse = getNodeInfo(); - if (getNodeInfoResponse == null) throw new NoNodeInfoException(); String[] latestMilestone = {getNodeInfoResponse.getLatestSolidSubtangleMilestone()}; @@ -806,36 +804,26 @@ public class IotaAPI extends IotaAPICore { * @param minWeightMagnitude The minimum weight magnitude. * @param transfers Array of transfer objects. * @param inputs List of inputs used for funding the transfer. - * @param remainderAddress If defined, this remainderAddress will be used for sending the remainder value (of the inputs) to. - * @return Array of Transaction objects. - * @throws InvalidAddressException is thrown when the specified remainderAddress is not an valid remainderAddress. - * @throws NotEnoughBalanceException is thrown when a transfer fails because their is not enough balance to perform the transfer. - * @throws InvalidSecurityLevelException is thrown when the specified security level is not valid. - * @throws InvalidTrytesException is thrown when invalid trytes is provided. - * @throws InvalidAddressException is thrown when the specified remainderAddress is not an valid remainderAddress. - * @throws InvalidTransferException is thrown when an invalid transfer is provided. + * @param remainderAddress If defined, this remainderAddress will be used for sending the remainder value (of the inputs) to. + * @param validateInputs Whether or not to validate the balances of the provided inputs + * @return Array of valid Transaction objects. + * @throws ArgumentException is thrown when the specified input is not valid. */ - public SendTransferResponse sendTransfer(String seed, int security, int depth, int minWeightMagnitude, final List transfers, Input[] inputs, String remainderAddress) throws NotEnoughBalanceException, InvalidSecurityLevelException, InvalidTrytesException, InvalidAddressException, InvalidTransferException { - - if (security < 1) { - throw new InvalidSecurityLevelException(); - } + public SendTransferResponse sendTransfer(String seed, int security, int depth, int minWeightMagnitude, final List transfers, List inputs, String remainderAddress, boolean validateInputs) throws ArgumentException { StopWatch stopWatch = new StopWatch(); - List trytes = prepareTransfers(seed, security, transfers, remainderAddress, inputs == null ? null : Arrays.asList(inputs)); + List trytes = prepareTransfers(seed, security, transfers, remainderAddress, inputs, validateInputs); List trxs = sendTrytes(trytes.toArray(new String[trytes.size()]), depth, minWeightMagnitude); Boolean[] successful = new Boolean[trxs.size()]; for (int i = 0; i < trxs.size(); i++) { - final FindTransactionResponse response = findTransactionsByBundles(trxs.get(i).getBundle()); - successful[i] = response.getHashes().length != 0; } - return SendTransferResponse.create(successful, stopWatch.getElapsedTimeMili()); + return SendTransferResponse.create(trxs, successful, stopWatch.getElapsedTimeMili()); } /** @@ -847,7 +835,7 @@ public class IotaAPI extends IotaAPICore { * @param bundleHash The bundle hashes. * @param bundle List of bundles to be populated. * @return Transaction objects. - * @throws ArgumentException is thrown when an invalid argument is provided. + * @throws ArgumentException is thrown when an invalid input is provided. */ public Bundle traverseBundle(String trunkTx, String bundleHash, Bundle bundle) throws ArgumentException { GetTrytesResponse gtr = getTrytes(trunkTx); @@ -855,16 +843,16 @@ public class IotaAPI extends IotaAPICore { if (gtr != null) { if (gtr.getTrytes().length == 0) { - throw new ArgumentException("Bundle transactions not visible"); + throw new ArgumentException(INVALID_BUNDLE_ERROR); } Transaction trx = new Transaction(gtr.getTrytes()[0], customCurl.clone()); if (trx.getBundle() == null) { - throw new ArgumentException("Invalid trytes, could not create object"); + throw new ArgumentException(INVALID_TRYTES_INPUT_ERROR); } // If first transaction to search is not a tail, return error if (bundleHash == null && trx.getCurrentIndex() != 0) { - throw new ArgumentException("Invalid tail transaction supplied."); + throw new ArgumentException(INVALID_TAIL_HASH_INPUT_ERROR); } // If no bundle hash, define it if (bundleHash == null) { @@ -886,7 +874,7 @@ public class IotaAPI extends IotaAPICore { // Continue traversing with new trunkTx return traverseBundle(trunkTx, bundleHash, bundle); } else { - throw new ArgumentException("Get Trytes Response was null"); + throw new ArgumentException(GET_TRYTES_RESPONSE_ERROR); } } @@ -899,38 +887,24 @@ public class IotaAPI extends IotaAPICore { * @param inputAddress Array of input addresses as well as the securitySum. * @param remainderAddress Has to be generated by the cosigners before initiating the transfer, can be null if fully spent. * @return Bundle of transaction objects. - * @throws InvalidBundleException is thrown if an invalid bundle was found or provided. - * @throws InvalidAddressException is thrown when the specified address is not an valid address. + * @throws ArgumentException is thrown when an invalid argument is provided. + * @throws IllegalStateException is thrown when a transfer fails because their is not enough balance to perform the transfer. */ public List initiateTransfer(int securitySum, final String inputAddress, String remainderAddress, - final List transfers, boolean testMode) throws InvalidAddressException, InvalidBundleException, InvalidTransferException { + final List transfers, boolean testMode) throws ArgumentException { - // If message or tag is not supplied, provide it - // Also remove the checksum of the address if it's there + // validate input address + if (!InputValidator.isAddress(inputAddress)) + throw new ArgumentException(INVALID_ADDRESSES_INPUT_ERROR); - for (Transfer transfer : transfers) { - - transfer.setMessage(transfer.getMessage().isEmpty() ? StringUtils.rightPad(transfer.getMessage(), 2187, '9') : transfer.getMessage()); - transfer.setTag(transfer.getTag().isEmpty() ? StringUtils.rightPad(transfer.getTag(), 27, '9') : transfer.getTag()); - - if (Checksum.isValidChecksum(transfer.getAddress())) { - transfer.setAddress(Checksum.removeChecksum(transfer.getAddress())); - } + // validate remainder address + if (remainderAddress != null && !InputValidator.isAddress(remainderAddress)) { + throw new ArgumentException(INVALID_ADDRESSES_INPUT_ERROR); } // Input validation of transfers object if (!InputValidator.isTransfersCollectionValid(transfers)) { - throw new InvalidTransferException(); - } - - // validate input address - - if (!InputValidator.isAddress(inputAddress)) - throw new InvalidAddressException(); - - // validate remainder address - if (remainderAddress != null && !InputValidator.isAddress(remainderAddress)) { - throw new InvalidBundleException(); + throw new ArgumentException(INVALID_TRANSFERS_INPUT_ERROR); } // Create a new bundle @@ -945,50 +919,57 @@ public class IotaAPI extends IotaAPICore { // and prepare the signatureFragments, message and tag for (final Transfer transfer : transfers) { + // remove the checksum of the address if provided + if (Checksum.isValidChecksum(transfer.getAddress())) { + transfer.setAddress(Checksum.removeChecksum(transfer.getAddress())); + } + int signatureMessageLength = 1; - // If message longer than 2187 trytes, increase signatureMessageLength (add 2nd transaction) - if (transfer.getMessage().length() > 2187) { + // If message longer than 2187 trytes, increase signatureMessageLength (add next transaction) + if (transfer.getMessage().length() > Constants.MESSAGE_LENGTH) { // Get total length, message / maxLength (2187 trytes) - signatureMessageLength += Math.floor(transfer.getMessage().length() / 2187); + signatureMessageLength += Math.floor(transfer.getMessage().length() / Constants.MESSAGE_LENGTH); String msgCopy = transfer.getMessage(); // 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()); + String fragment = StringUtils.substring(msgCopy, 0, Constants.MESSAGE_LENGTH); + msgCopy = StringUtils.substring(msgCopy, Constants.MESSAGE_LENGTH, msgCopy.length()); // Pad remainder of fragment - fragment = StringUtils.rightPad(fragment, 2187, '9'); + fragment = StringUtils.rightPad(fragment, Constants.MESSAGE_LENGTH, '9'); signatureFragments.add(fragment); } } else { - // Else, get single fragment with 2187 of 9's trytes - String fragment = StringUtils.substring(transfer.getMessage(), 0, 2187); + String fragment = transfer.getMessage(); - fragment = StringUtils.rightPad(fragment, 2187, '9'); + if (transfer.getMessage().length() < Constants.MESSAGE_LENGTH) { + fragment = StringUtils.rightPad(fragment, Constants.MESSAGE_LENGTH, '9'); + } signatureFragments.add(fragment); } + tag = transfer.getTag(); + + // pad for required 27 tryte length + if (transfer.getTag().length() < Constants.TAG_LENGTH) { + tag = StringUtils.rightPad(tag, Constants.TAG_LENGTH, '9'); + } + // get current timestamp in seconds long timestamp = (long) Math.floor(Calendar.getInstance().getTimeInMillis() / 1000); - // If no tag defined, get 27 tryte tag. - tag = transfer.getTag().isEmpty() ? StringUtils.rightPad(transfer.getTag(), 27, '9') : transfer.getTag(); - - // Pad for required 27 tryte length - tag = StringUtils.rightPad(tag, 27, '9'); - // Add first entry to the bundle bundle.addEntry(signatureMessageLength, transfer.getAddress(), transfer.getValue(), tag, timestamp); // Sum up total value @@ -998,7 +979,7 @@ public class IotaAPI extends IotaAPICore { // Get inputs if we are sending tokens if (totalValue != 0) { - GetBalancesResponse balancesResponse = getBalances(100, new String[]{inputAddress}); + GetBalancesResponse balancesResponse = getBalances(100, Collections.singletonList(inputAddress)); String[] balances = balancesResponse.getBalances(); long totalBalance = 0; @@ -1026,7 +1007,7 @@ public class IotaAPI extends IotaAPICore { } // Return not enough balance error if (totalValue > totalBalance) { - throw new IllegalStateException("Not enough balance"); + throw new IllegalStateException(NOT_ENOUGH_BALANCE_ERROR); } // If there is a remainder value @@ -1037,7 +1018,7 @@ public class IotaAPI extends IotaAPICore { // Remainder bundle entry if necessary if (remainderAddress == null) { - throw new IllegalStateException("No remainder address defined"); + throw new IllegalStateException(NO_REMAINDER_ADDRESS_ERROR); } bundle.addEntry(1, remainderAddress, remainder, tag, timestamp); @@ -1048,33 +1029,11 @@ public class IotaAPI extends IotaAPICore { return bundle.getTransactions(); } else { - throw new RuntimeException("Invalid value transfer: the transfer does not require a signature."); + throw new RuntimeException(INVALID_VALUE_TRANSFER_ERROR); } } - /** - * @param hash The hash. - * @return A bundle. - * @throws ArgumentException is thrown when an invalid argument is provided. - */ - public String findTailTransactionHash(String hash) throws ArgumentException { - GetTrytesResponse gtr = getTrytes(hash); - - if (gtr == null) throw new ArgumentException("Invalid hash"); - - if (gtr.getTrytes().length == 0) { - throw new ArgumentException("Bundle transactions not visible"); - } - - Transaction trx = new Transaction(gtr.getTrytes()[0], customCurl.clone()); - if (trx.getBundle() == null) { - throw new ArgumentException("Invalid trytes, could not create object"); - } - if (trx.getCurrentIndex() == 0) return trx.getHash(); - else return findTailTransactionHash(trx.getBundle()); - } - /** * @param seed Tryte-encoded seed. * @param security The security level of private key / seed. @@ -1084,9 +1043,8 @@ public class IotaAPI extends IotaAPICore { * @param totalValue The total value. * @param remainderAddress If defined, this address will be used for sending the remainder value (of the inputs) to. * @param signatureFragments The signature fragments. - * @throws NotEnoughBalanceException is thrown when a transfer fails because their is not enough balance to perform the transfer. - * @throws InvalidSecurityLevelException is thrown when the specified security level is not valid. - * @throws InvalidAddressException is thrown when the specified address is not an valid address. + * @throws ArgumentException is thrown when an invalid argument is provided. + * @throws IllegalStateException is thrown when a transfer fails because their is not enough balance to perform the transfer. */ public List addRemainder(final String seed, final int security, @@ -1095,7 +1053,7 @@ public class IotaAPI extends IotaAPICore { final String tag, final long totalValue, final String remainderAddress, - final List signatureFragments) throws NotEnoughBalanceException, InvalidSecurityLevelException, InvalidAddressException { + final List signatureFragments) throws ArgumentException { long totalTransferValue = totalValue; for (int i = 0; i < inputs.size(); i++) { @@ -1139,7 +1097,7 @@ public class IotaAPI extends IotaAPICore { totalTransferValue -= thisBalance; } } - throw new NotEnoughBalanceException(); + throw new IllegalStateException(NOT_ENOUGH_BALANCE_ERROR); } public static class Builder extends IotaAPICore.Builder { diff --git a/jota/src/main/java/jota/IotaAPICommands.java b/jota/src/main/java/jota/IotaAPICommands.java index fe66f1b..55de26e 100644 --- a/jota/src/main/java/jota/IotaAPICommands.java +++ b/jota/src/main/java/jota/IotaAPICommands.java @@ -2,50 +2,42 @@ package jota; /** * IOTA's node command list - *

- * 'params' is not currently used. + * */ public enum IotaAPICommands { - GET_NODE_INFO("getNodeInfo", 0), - GET_NEIGHBORS("getNeighbors", 0), - ADD_NEIGHBORS("addNeighbors", 1), - REMOVE_NEIGHBORS("removeNeighbors", 1), - GET_TIPS("getTips", 0), - FIND_TRANSACTIONS("findTransactions", 1), - GET_TRYTES("getTrytes", 0), - GET_INCLUSIONS_STATES("getInclusionStates", 0), - GET_BALANCES("getBalances", 0), - GET_TRANSACTIONS_TO_APPROVE("getTransactionsToApprove", 0), - ATTACH_TO_TANGLE("attachToTangle", 0), - INTERRUPT_ATTACHING_TO_TANGLE("interruptAttachingToTangle", 0), - BROADCAST_TRANSACTIONS("broadcastTransactions", 0), - STORE_TRANSACTIONS("storeTransactions", 0); + GET_NODE_INFO("getNodeInfo"), + GET_NEIGHBORS("getNeighbors"), + ADD_NEIGHBORS("addNeighbors"), + REMOVE_NEIGHBORS("removeNeighbors"), + GET_TIPS("getTips"), + FIND_TRANSACTIONS("findTransactions"), + GET_TRYTES("getTrytes"), + GET_INCLUSIONS_STATES("getInclusionStates"), + GET_BALANCES("getBalances"), + GET_TRANSACTIONS_TO_APPROVE("getTransactionsToApprove"), + ATTACH_TO_TANGLE("attachToTangle"), + INTERRUPT_ATTACHING_TO_TANGLE("interruptAttachingToTangle"), + BROADCAST_TRANSACTIONS("broadcastTransactions"), + STORE_TRANSACTIONS("storeTransactions"); private String command; - private int params; /** - * @param command - * @param params + * Initializes a new instance of the IotaAPICommands class. */ - IotaAPICommands(String command, int params) { + IotaAPICommands(String command) { this.command = command; - this.params = params; } /** - * @return + * Gets the command. + * + * @return The command. */ public String command() { return command; } - /** - * @return - */ - public int params() { - return params; - } } diff --git a/jota/src/main/java/jota/IotaAPICore.java b/jota/src/main/java/jota/IotaAPICore.java index 3aa82a9..39a0329 100644 --- a/jota/src/main/java/jota/IotaAPICore.java +++ b/jota/src/main/java/jota/IotaAPICore.java @@ -2,9 +2,9 @@ package jota; import jota.dto.request.*; import jota.dto.response.*; -import jota.error.InvalidApiVersionException; -import jota.error.InvalidTrytesException; +import jota.error.ArgumentException; import jota.model.Transaction; +import jota.utils.Checksum; import jota.utils.InputValidator; import okhttp3.Interceptor; import okhttp3.OkHttpClient; @@ -19,10 +19,13 @@ import retrofit2.converter.gson.GsonConverterFactory; import java.io.BufferedReader; import java.io.FileReader; import java.io.IOException; +import java.util.ArrayList; import java.util.List; import java.util.Properties; import java.util.concurrent.TimeUnit; +import static jota.utils.Constants.*; + /** * This class provides access to the Iota core API * @@ -53,29 +56,27 @@ public class IotaAPICore { postConstruct(); } - /** - * @param call - * @param - * @return - */ protected static Response wrapCheckedException(final Call call) { try { final Response res = call.execute(); + String error = ""; + + if (res.errorBody() != null) { + error = res.errorBody().string(); + } + if (res.code() == 400) { - if (res.errorBody().string().contains("Invalid API Version")) { - try { - throw new InvalidApiVersionException(); - } catch (InvalidApiVersionException e) { - e.printStackTrace(); - } - } else { - throw new IllegalAccessError("400 " + res.errorBody().string()); + try { + throw new ArgumentException(error); + } catch (ArgumentException e) { + e.printStackTrace(); } + } else if (res.code() == 401) { - throw new IllegalAccessError("401 " + res.errorBody().string()); + throw new IllegalAccessError("401 " + error); } else if (res.code() == 500) { - throw new IllegalAccessError("500 " + res.errorBody().string()); + throw new IllegalAccessError("500 " + error); } return res; } catch (IOException e) { @@ -85,11 +86,6 @@ public class IotaAPICore { } - /** - * @param env - * @param def - * @return - */ private static String env(String env, String def) { final String value = System.getenv(env); if (value == null) { @@ -101,7 +97,7 @@ public class IotaAPICore { } /** - * added header for IRI 1.4.1 + * added header for IRI */ private void postConstruct() { @@ -138,31 +134,62 @@ public class IotaAPICore { log.debug("Jota-API Java proxy pointing to node url: '{}'", nodeUrl); } + /** + * Get the node information. + * + * @return The information about the node. + */ public GetNodeInfoResponse getNodeInfo() { final Call res = service.getNodeInfo(IotaCommandRequest.createNodeInfoRequest()); return wrapCheckedException(res).body(); } + /** + * Get the list of neighbors from the node. + * + * @return The set of neighbors the node is connected with. + */ public GetNeighborsResponse getNeighbors() { final Call res = service.getNeighbors(IotaCommandRequest.createGetNeighborsRequest()); return wrapCheckedException(res).body(); } + /** + * Add a list of neighbors to the node. + * + * @param uris The list of URI elements. + */ public AddNeighborsResponse addNeighbors(String... uris) { final Call res = service.addNeighbors(IotaNeighborsRequest.createAddNeighborsRequest(uris)); return wrapCheckedException(res).body(); } + /** + * Removes a list of neighbors from the node. + * + * @param uris The list of URI elements. + */ public RemoveNeighborsResponse removeNeighbors(String... uris) { final Call res = service.removeNeighbors(IotaNeighborsRequest.createRemoveNeighborsRequest(uris)); return wrapCheckedException(res).body(); } + /** + * Get the list of latest tips (unconfirmed transactions). + * + * @return The the list of tips. + */ public GetTipsResponse getTips() { final Call res = service.getTips(IotaCommandRequest.createGetTipsRequest()); return wrapCheckedException(res).body(); } + + /** + * Find the transactions which match the specified input + * + * @return The transaction hashes which are returned depend on the input. + */ public FindTransactionResponse findTransactions(String[] addresses, String[] tags, String[] approvees, String[] bundles) { final IotaFindTransactionsRequest findTransRequest = IotaFindTransactionsRequest @@ -176,55 +203,156 @@ public class IotaAPICore { return wrapCheckedException(res).body(); } - public FindTransactionResponse findTransactionsByAddresses(final String... addresses) { - return findTransactions(addresses, null, null, null); + /** + * Find the transactions by addresses + * + * @param addresses A List of addresses. + * @return The transaction hashes which are returned depend on the input. + */ + public FindTransactionResponse findTransactionsByAddresses(final String... addresses) throws ArgumentException { + List addressesWithoutChecksum = new ArrayList<>(); + + for (String address : addresses) { + String addressO = Checksum.removeChecksum(address); + addressesWithoutChecksum.add(addressO); + } + + return findTransactions(addressesWithoutChecksum.toArray(new String[addressesWithoutChecksum.size()]), null, null, null); } + /** + * Find the transactions by bundles + * + * @param bundles A List of bundles. + * @return The transaction hashes which are returned depend on the input. + */ public FindTransactionResponse findTransactionsByBundles(final String... bundles) { return findTransactions(null, null, null, bundles); } + /** + * Find the transactions by approvees + * + * @param approvees A List of approvess. + * @return The transaction hashes which are returned depend on the input. + */ public FindTransactionResponse findTransactionsByApprovees(final String... approvees) { return findTransactions(null, null, approvees, null); } + + /** + * Find the transactions by digests + * + * @param digests A List of digests. + * @return The transaction hashes which are returned depend on the input. + */ public FindTransactionResponse findTransactionsByDigests(final String... digests) { return findTransactions(null, digests, null, null); } - public GetInclusionStateResponse getInclusionStates(String[] transactions, String[] tips) { + + /** + * Get the inclusion states of a set of transactions. This is for determining if a transaction was accepted and confirmed by the network or not. + * Search for multiple tips (and thus, milestones) to get past inclusion states of transactions. + * + * @param transactions The ist of transactions you want to get the inclusion state for. + * @param tips ThelList of tips (including milestones) you want to search for the inclusion state. + * @return The inclusion states of a set of transactions. + */ + public GetInclusionStateResponse getInclusionStates(String[] transactions, String[] tips) throws ArgumentException { + + if (!InputValidator.isArrayOfHashes(transactions)) { + throw new ArgumentException(INVALID_HASHES_INPUT_ERROR); + } + + if (!InputValidator.isArrayOfHashes(tips)) { + throw new ArgumentException(INVALID_HASHES_INPUT_ERROR); + } + + final Call res = service.getInclusionStates(IotaGetInclusionStateRequest .createGetInclusionStateRequest(transactions, tips)); return wrapCheckedException(res).body(); } - public GetTrytesResponse getTrytes(String... hashes) { + /** + * Returns the raw trytes data of a transaction. + * + * @param hashes The of transaction hashes of which you want to get trytes from. + * @return The the raw transaction data (trytes) of a specific transaction. + */ + public GetTrytesResponse getTrytes(String... hashes) throws ArgumentException { + + if (!InputValidator.isArrayOfHashes(hashes)) { + throw new ArgumentException(INVALID_HASHES_INPUT_ERROR); + } + final Call res = service.getTrytes(IotaGetTrytesRequest.createGetTrytesRequest(hashes)); return wrapCheckedException(res).body(); } + /** + * Tip selection which returns trunkTransaction and branchTransaction. The input value is the latest coordinator milestone, as provided through the getNodeInfo API call. + * + * @param depth The number of bundles to go back to determine the transactions for approval. + * @return The Tip selection which returns trunkTransaction and branchTransaction + */ public GetTransactionsToApproveResponse getTransactionsToApprove(Integer depth) { final Call res = service.getTransactionsToApprove(IotaGetTransactionsToApproveRequest.createIotaGetTransactionsToApproveRequest(depth)); return wrapCheckedException(res).body(); } - public GetBalancesResponse getBalances(Integer threshold, String[] addresses) { + /** + * Similar to getInclusionStates. + * + * @param threshold The confirmation threshold, should be set to 100. + * @param addresses The array list of addresses you want to get the confirmed balance from. + * @return The confirmed balance which a list of addresses have at the latest confirmed milestone. + */ + private GetBalancesResponse getBalances(Integer threshold, String[] addresses) { 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[]{})); + /** + * Similar to getInclusionStates. + * + * @param threshold The confirmation threshold, should be set to 100. + * @param addresses The list of addresses you want to get the confirmed balance from. + * @return The confirmed balance which a list of addresses have at the latest confirmed milestone. + */ + public GetBalancesResponse getBalances(Integer threshold, List addresses) throws ArgumentException { + + List addressesWithoutChecksum = new ArrayList<>(); + + for (String address : addresses) { + String addressO = Checksum.removeChecksum(address); + addressesWithoutChecksum.add(addressO); + } + return getBalances(threshold, addressesWithoutChecksum.toArray(new String[]{})); } - public InterruptAttachingToTangleResponse interruptAttachingToTangle() { - final Call res = service.interruptAttachingToTangle(IotaCommandRequest.createInterruptAttachToTangleRequest()); - return wrapCheckedException(res).body(); - } + /** + * Attaches the specified transactions (trytes) to the Tangle by doing Proof of Work. + * + * @param trunkTransaction The trunk transaction to approve. + * @param branchTransaction The branch transaction to approve. + * @param minWeightMagnitude The Proof of Work intensity. + * @param trytes A List of trytes (raw transaction data) to attach to the tangle. + */ + public GetAttachToTangleResponse attachToTangle(String trunkTransaction, String branchTransaction, Integer minWeightMagnitude, String... trytes) throws ArgumentException { + + if (!InputValidator.isHash(trunkTransaction)) { + throw new ArgumentException(INVALID_HASHES_INPUT_ERROR); + } + + if (!InputValidator.isHash(branchTransaction)) { + throw new ArgumentException(INVALID_HASHES_INPUT_ERROR); + } - public GetAttachToTangleResponse attachToTangle(String trunkTransaction, String branchTransaction, Integer minWeightMagnitude, String... trytes) throws InvalidTrytesException { if (!InputValidator.isArrayOfTrytes(trytes)) { - throw new InvalidTrytesException(); + throw new ArgumentException(INVALID_TRYTES_INPUT_ERROR); } if (localPoW != null) { @@ -249,29 +377,66 @@ public class IotaAPICore { return wrapCheckedException(res).body(); } + /** + * Interrupts and completely aborts the attachToTangle process. + */ + public InterruptAttachingToTangleResponse interruptAttachingToTangle() { + final Call res = service.interruptAttachingToTangle(IotaCommandRequest.createInterruptAttachToTangleRequest()); + return wrapCheckedException(res).body(); + } + + /** + * Broadcast a list of transactions to all neighbors. The input trytes for this call are provided by attachToTangle. + * + * @param trytes The list of raw data of transactions to be rebroadcast. + */ + public BroadcastTransactionsResponse broadcastTransactions(String... trytes) throws ArgumentException { + + if (!InputValidator.isArrayOfAttachedTrytes(trytes)) { + throw new ArgumentException(INVALID_ATTACHED_TRYTES_INPUT_ERROR); + } + + final Call res = service.broadcastTransactions(IotaBroadcastTransactionRequest.createBroadcastTransactionsRequest(trytes)); + return wrapCheckedException(res).body(); + } + + /** + * Store transactions into the local storage. The trytes to be used for this call are returned by attachToTangle. + * + * @param trytes The list of raw data of transactions to be rebroadcast. + */ public StoreTransactionsResponse storeTransactions(String... trytes) { final Call res = service.storeTransactions(IotaStoreTransactionsRequest.createStoreTransactionsRequest(trytes)); return wrapCheckedException(res).body(); } - public BroadcastTransactionsResponse broadcastTransactions(String... trytes) { - final Call res = service.broadcastTransactions(IotaBroadcastTransactionRequest.createBroadcastTransactionsRequest(trytes)); - return wrapCheckedException(res).body(); - } - + /** + * Gets the protocol. + * + * @return The protocol to use when connecting to the remote node. + */ public String getProtocol() { return protocol; } + /** + * Gets the host. + * + * @return The host you want to connect to. + */ public String getHost() { return host; } + /** + * Gets the port. + * + * @return The port of the host you want to connect to. + */ public String getPort() { return port; } - @SuppressWarnings("unchecked") public static class Builder> { String protocol, host, port; IotaLocalPoW localPoW; @@ -332,37 +497,21 @@ public class IotaAPICore { return (T) this; } - /** - * @param host - * @return - */ public T host(String host) { this.host = host; return (T) this; } - /** - * @param port - * @return - */ public T port(String port) { this.port = port; return (T) this; } - /** - * @param protocol - * @return - */ public T protocol(String protocol) { this.protocol = protocol; return (T) this; } - /** - * @param localPoW - * @return - */ public T localPoW(IotaLocalPoW localPoW) { this.localPoW = localPoW; return (T) this; diff --git a/jota/src/main/java/jota/IotaAPIService.java b/jota/src/main/java/jota/IotaAPIService.java index 2946307..344a4ef 100644 --- a/jota/src/main/java/jota/IotaAPIService.java +++ b/jota/src/main/java/jota/IotaAPIService.java @@ -18,42 +18,40 @@ public interface IotaAPIService { String USER_AGENT_HEADER = "User-Agent: JOTA-API wrapper"; /** - * Returns information about your node. + * Returns information about the node. *

- * curl http://localhost:14265 -X POST -H 'Content-Type: application/json' - * -d '{"command": "getNodeInfo"}' - * - * @return a {@code NodeInfoResponse} object, if succesfull. + * {@code curl http://localhost:14265 -X POST -H 'X-IOTA-API-Version: 1.4.1' -H 'Content-Type: application/json'} + * {@code -d '{"command": "getNodeInfo"}'} */ @Headers({CONTENT_TYPE_HEADER, USER_AGENT_HEADER}) @POST("./") Call getNodeInfo(@Body IotaCommandRequest request); /** - * Get the list of latest tips (unconfirmed transactions). + * Get the list of neighbors from the node. *

- * curl http://localhost:14265 -X POST -H 'Content-Type: application/json' - * -d '{"command": "getNeighbors"}' + * {@code curl http://localhost:14265 -X POST -H 'X-IOTA-API-Version: 1.4.1' -H 'Content-Type: application/json'} + * {@code -d '{"command": "getNeighbors"}'} */ @Headers({CONTENT_TYPE_HEADER, USER_AGENT_HEADER}) @POST("./") Call getNeighbors(@Body IotaCommandRequest request); /** - * Add a list of neighbors to your node. + * Add a list of neighbors to the node. *

- * curl http://localhost:14265 -X POST -H 'Content-Type: application/json' - * -d '{"command": "addNeighbors", "uris": ["udp://8.8.8.8:14265", "udp://8.8.8.5:14265"]}' + * {@code curl http://localhost:14265 -X POST -H 'X-IOTA-API-Version: 1.4.1' -H 'Content-Type: application/json'} + * {@code -d '{"command": "addNeighbors", "uris": ["udp://8.8.8.8:14265", "udp://8.8.8.5:14265"]}'} */ @Headers({CONTENT_TYPE_HEADER, USER_AGENT_HEADER}) @POST("./") Call addNeighbors(@Body IotaNeighborsRequest request); /** - * Removes a list of neighbors to your node. + * Removes a list of neighbors from the node. *

- * curl http://localhost:14265 -X POST -H 'Content-Type: application/json' - * -d '{"command": "removeNeighbors", "uris": ["udp://8.8.8.8:14265", "udp://8.8.8.5:14265"]}' + * {@code curl http://localhost:14265 -X POST -H 'X-IOTA-API-Version: 1.4.1' -H 'Content-Type: application/json'} + * {@code -d '{"command": "removeNeighbors", "uris": ["udp://8.8.8.8:14265", "udp://8.8.8.5:14265"]}'} */ @Headers({CONTENT_TYPE_HEADER, USER_AGENT_HEADER}) @POST("./") @@ -62,18 +60,18 @@ public interface IotaAPIService { /** * Get the list of latest tips (unconfirmed transactions). *

- * curl http://localhost:14265 -X POST -H 'Content-Type: application/json' - * -d '{"command": "getTips"}' + * {@code curl http://localhost:14265 -X POST -H 'X-IOTA-API-Version: 1.4.1' -H 'Content-Type: application/json'} + * {@code -d '{"command": "getTips"}'} */ @Headers({CONTENT_TYPE_HEADER, USER_AGENT_HEADER}) @POST("./") Call getTips(@Body IotaCommandRequest request); /** - * Find the transactions which match the specified input and return + * Find the transactions which match the specified input and return. *

- * curl http://localhost:14265 \ -X POST \ -H 'Content-Type: application/json' \ - * -d '{"command": "findTransactions", "addresses": ["RVORZ9SIIP9RCYMREUIXXVPQIPHVCNPQ9HZWYKFWYWZRE9JQKG9REPKIASHUUECPSQO9JT9XNMVKWYGVAZETAIRPTM"]}' + * {@code curl http://localhost:14265 -X POST -H 'X-IOTA-API-Version: 1.4.1' -H 'Content-Type: application/json'} + * {@code -d '{"command": "findTransactions", "addresses": ["RVORZ9SIIP9RCYMREUIXXVPQIPHVCNPQ9HZWYKFWYWZRE9JQKG9REPKIASHUUECPSQO9JT9XNMVKWYGVAZETAIRPTM"]}'} */ @Headers({CONTENT_TYPE_HEADER, USER_AGENT_HEADER}) @POST("./") @@ -81,10 +79,11 @@ public interface IotaAPIService { /** - * Get the inclusion states of a set of transactions. This is for determining if a transaction was accepted and confirmed by the network or not. You can search for multiple tips (and thus, milestones) to get past inclusion states of transactions. + * Get the inclusion states of a set of transactions. This is for determining if a transaction was accepted and confirmed by the network or not. + * You can search for multiple tips (and thus, milestones) to get past inclusion states of transactions. *

- * curl http://localhost:14265 -X POST -H 'Content-Type: application/json' - * -d '{"command": "getInclusionStates", "transactions"Q9HZWYKFWYWZRE9JQKG9REPKIASHUUECPSQO9JT9XNMVKWYGVAZETAIRPTM"], "tips" : []}' + * {@code curl http://localhost:14265 -X POST -H 'Content-Type: application/json'} + * {@code -d '{"command": "getInclusionStates", "transactions"Q9HZWYKFWYWZRE9JQKG9REPKIASHUUECPSQO9JT9XNMVKWYGVAZETAIRPTM"], "tips" : []}'} */ @Headers({CONTENT_TYPE_HEADER, USER_AGENT_HEADER}) @POST("./") @@ -93,18 +92,19 @@ public interface IotaAPIService { /** * Returns the raw trytes data of a transaction. *

- * curl http://localhost:14265 -X POST -H 'Content-Type: application/json' - * -d '{"command": "getTrytes", "hashes": ["OAATQS9VQLSXCLDJVJJVYUGONXAXOFMJOZNSYWRZSWECMXAQQURHQBJNLD9IOFEPGZEPEMPXCIVRX9999"]}' + * {@code curl http://localhost:14265 -X POST -H 'X-IOTA-API-Version: 1.4.1' -H 'Content-Type: application/json'} + * {@code -d '{"command": "getTrytes", "hashes": ["OAATQS9VQLSXCLDJVJJVYUGONXAXOFMJOZNSYWRZSWECMXAQQURHQBJNLD9IOFEPGZEPEMPXCIVRX9999"]}'} */ @Headers({CONTENT_TYPE_HEADER, USER_AGENT_HEADER}) @POST("./") Call getTrytes(@Body IotaGetTrytesRequest request); /** - * Tip selection which returns trunkTransaction and branchTransaction. The input value is the latest coordinator milestone, as provided through the getNodeInfo API call. + * Tip selection which returns trunkTransaction and branchTransaction. + * The input value is the latest coordinator milestone, as provided through the getNodeInfo API call. *

- * curl http://localhost:14265 -X POST -H 'Content-Type: application/json' - * -d '{"command": "getTransactionsToApprove", "depth": 27}' + * {@code curl http://localhost:14265 -X POST -H 'X-IOTA-API-Version: 1.4.1' -H 'Content-Type: application/json'} + * {@code -d '{"command": "getTransactionsToApprove", "depth": 27}'} */ @Headers({CONTENT_TYPE_HEADER, USER_AGENT_HEADER}) @POST("./") @@ -113,8 +113,8 @@ public interface IotaAPIService { /** * It returns the confirmed balance which a list of addresses have at the latest confirmed milestone. *

- * curl http://localhost:14265 -X POST -H 'Content-Type: application/json' - * -d '{"command": "getBalances", "addresses": ["HBBYKAKTILIPVUKFOTSLHGENPTXYBNKXZFQFR9VQFWNBMTQNRVOUKPVPRNBSZVVILMAFBKOTBLGLWLOHQ"], "threshold": 100}' + * {@code curl http://localhost:14265 -X POST -H 'X-IOTA-API-Version: 1.4.1' -H 'Content-Type: application/json'} + * {@code -d '{"command": "getBalances", "addresses": ["HBBYKAKTILIPVUKFOTSLHGENPTXYBNKXZFQFR9VQFWNBMTQNRVOUKPVPRNBSZVVILMAFBKOTBLGLWLOHQ"], "threshold": 100}'} */ @Headers({CONTENT_TYPE_HEADER, USER_AGENT_HEADER}) @POST("./") @@ -123,8 +123,8 @@ public interface IotaAPIService { /** * Attaches the specified transactions (trytes) to the Tangle by doing Proof of Work. *

- * curl http://localhost:14265 -X POST -H 'Content-Type: application/json' - * -d '{"command": "attachToTangle", "trunkTransaction": "JVMTDGDPDFYHMZPMWEKKANBQSLSDTIIHAYQUMZOKHXXXGJHJDQPOMDOMNRDKYCZRUFZROZDADTHZC9999", "branchTransaction": "P9KFSJVGSPLXAEBJSHWFZLGP9GGJTIO9YITDEHATDTGAFLPLBZ9FOFWWTKMAZXZHFGQHUOXLXUALY9999", "minWeightMagnitude": 18, "trytes": ["TRYTVALUEHERE"]}' + * {@code curl http://localhost:14265 -X POST -H 'X-IOTA-API-Version: 1.4.1' -H 'Content-Type: application/json'} + * {@code -d '{"command": "attachToTangle", "trunkTransaction": "JVMTDGDPDFYHMZPMWEKKANBQSLSDTIIHAYQUMZOKHXXXGJHJDQPOMDOMNRDKYCZRUFZROZDADTHZC9999", "branchTransaction": "P9KFSJVGSPLXAEBJSHWFZLGP9GGJTIO9YITDEHATDTGAFLPLBZ9FOFWWTKMAZXZHFGQHUOXLXUALY9999", "minWeightMagnitude": 18, "trytes": ["TRYTVALUEHERE"]}'} */ @Headers({CONTENT_TYPE_HEADER, USER_AGENT_HEADER}) @POST("./") @@ -133,8 +133,8 @@ public interface IotaAPIService { /** * Interrupts and completely aborts the attachToTangle process. *

- * curl http://localhost:14265 -X POST -H 'Content-Type: application/json' - * -d '{"command": "interruptAttachingToTangle" } + * {@code curl http://localhost:14265 -X POST -H 'X-IOTA-API-Version: 1.4.1' -H 'Content-Type: application/json'} + * {@code -d '{"command": "interruptAttachingToTangle"}'} */ @Headers({CONTENT_TYPE_HEADER, USER_AGENT_HEADER}) @POST("./") @@ -143,8 +143,8 @@ public interface IotaAPIService { /** * Broadcast a list of transactions to all neighbors. The input trytes for this call are provided by attachToTangle. *

- * curl http://localhost:14265 -X POST -H 'Content-Type: application/json' - * -d '{"command": "broadcastTransactions", "trytes": ["BYSWEAUTWXHXZ9YBZISEK9LUHWGMHXCGEVNZHRLUWQFCUSDXZHOFHWHL9MQPVJXXZLIXPXPXF9KYEREFSKCPKYIIKPZVLHUTDFQKKVVBBN9ATTLPCNPJDWDEVIYYLGPZGCWXOBDXMLJC9VO9QXTTBLAXTTBFUAROYEGQIVB9MJWJKXJMCUPTWAUGFZBTZCSJVRBGMYXTVBDDS9MYUJCPZ9YDWWQNIPUAIJXXSNLKUBSCOIJPCLEFPOXFJREXQCUVUMKSDOVQGGHRNILCO9GNCLWFM9APMNMWYASHXQAYBEXF9QRIHIBHYEJOYHRQJAOKAQ9AJJFQ9WEIWIJOTZATIBOXQLBMIJU9PCGBLVDDVFP9CFFSXTDUXMEGOOFXWRTLFGV9XXMYWEMGQEEEDBTIJ9OJOXFAPFQXCDAXOUDMLVYRMRLUDBETOLRJQAEDDLNVIRQJUBZBO9CCFDHIX9MSQCWYAXJVWHCUPTRSXJDESISQPRKZAFKFRULCGVRSBLVFOPEYLEE99JD9SEBALQINPDAZHFAB9RNBH9AZWIJOTLBZVIEJIAYGMC9AZGNFWGRSWAXTYSXVROVNKCOQQIWGPNQZKHUNODGYADPYLZZZUQRTJRTODOUKAOITNOMWNGHJBBA99QUMBHRENGBHTH9KHUAOXBVIVDVYYZMSEYSJWIOGGXZVRGN999EEGQMCOYVJQRIRROMPCQBLDYIGQO9AMORPYFSSUGACOJXGAQSPDY9YWRRPESNXXBDQ9OZOXVIOMLGTSWAMKMTDRSPGJKGBXQIVNRJRFRYEZ9VJDLHIKPSKMYC9YEGHFDS9SGVDHRIXBEMLFIINOHVPXIFAZCJKBHVMQZEVWCOSNWQRDYWVAIBLSCBGESJUIBWZECPUCAYAWMTQKRMCHONIPKJYYTEGZCJYCT9ABRWTJLRQXKMWY9GWZMHYZNWPXULNZAPVQLPMYQZCYNEPOCGOHBJUZLZDPIXVHLDMQYJUUBEDXXPXFLNRGIPWBRNQQZJSGSJTTYHIGGFAWJVXWL9THTPWOOHTNQWCNYOYZXALHAZXVMIZE9WMQUDCHDJMIBWKTYH9AC9AFOT9DPCADCV9ZWUTE9QNOMSZPTZDJLJZCJGHXUNBJFUBJWQUEZDMHXGBPTNSPZBR9TGSKVOHMOQSWPGFLSWNESFKSAZY9HHERAXALZCABFYPOVLAHMIHVDBGKUMDXC9WHHTIRYHZVWNXSVQUWCR9M9RAGMFEZZKZ9XEOQGOSLFQCHHOKLDSA9QCMDGCGMRYJZLBVIFOLBIJPROKMHOYTBTJIWUZWJMCTKCJKKTR9LCVYPVJI9AHGI9JOWMIWZAGMLDFJA9WU9QAMEFGABIBEZNNAL9OXSBFLOEHKDGHWFQSHMPLYFCNXAAZYJLMQDEYRGL9QKCEUEJ9LLVUOINVSZZQHCIKPAGMT9CAYIIMTTBCPKWTYHOJIIY9GYNPAJNUJ9BKYYXSV9JSPEXYMCFAIKTGNRSQGUNIYZCRT9FOWENSZQPD9ALUPYYAVICHVYELYFPUYDTWUSWNIYFXPX9MICCCOOZIWRNJIDALWGWRATGLJXNAYTNIZWQ9YTVDBOFZRKO9CFWRPAQQRXTPACOWCPRLYRYSJARRKSQPR9TCFXDVIXLP9XVL99ERRDSOHBFJDJQQGGGCZNDQ9NYCTQJWVZIAELCRBJJFDMCNZU9FIZRPGNURTXOCDSQGXTQHKHUECGWFUUYS9J9NYQ9U9P9UUP9YMZHWWWCIASCFLCMSKTELZWUGCDE9YOKVOVKTAYPHDF9ZCCQAYPJIJNGSHUIHHCOSSOOBUDOKE9CJZGYSSGNCQJVBEFTZFJ9SQUHOASKRRGBSHWKBCBWBTJHOGQ9WOMQFHWJVEG9NYX9KWBTCAIXNXHEBDIOFO9ALYMFGRICLCKKLG9FOBOX9PDWNQRGHBKHGKKRLWTBEQMCWQRLHAVYYZDIIPKVQTHYTWQMTOACXZOQCDTJTBAAUWXSGJF9PNQIJ9AJRUMUVCPWYVYVARKR9RKGOUHHNKNVGGPDDLGKPQNOYHNKAVVKCXWXOQPZNSLATUJT9AUWRMPPSWHSTTYDFAQDXOCYTZHOYYGAIM9CELMZ9AZPWB9MJXGHOKDNNSZVUDAGXTJJSSZCPZVPZBYNNTUQABSXQWZCHDQSLGK9UOHCFKBIBNETK999999999999999999999999999999999999999999999999999999999999999999999999999999999NOXDXXKUDWLOFJLIPQIBRBMGDYCPGDNLQOLQS99EQYKBIU9VHCJVIPFUYCQDNY9APGEVYLCENJIOBLWNB999999999XKBRHUD99C99999999NKZKEKWLDKMJCI9N9XQOLWEPAYWSH9999999999999999999999999KDDTGZLIPBNZKMLTOLOXQVNGLASESDQVPTXALEKRMIOHQLUHD9ELQDBQETS9QFGTYOYWLNTSKKMVJAUXSIROUICDOXKSYZTDPEDKOQENTJOWJONDEWROCEJIEWFWLUAACVSJFTMCHHXJBJRKAAPUDXXVXFWP9X9999IROUICDOXKSYZTDPEDKOQENTJOWJONDEWROCEJIEWFWLUAACVSJFTMCHHXJBJRKAAPUDXXVXFWP9X9999"]} + * {@code curl http://localhost:14265 -X POST -H 'X-IOTA-API-Version: 1.4.1' -H 'Content-Type: application/json'} + * {@code -d '{"command": "broadcastTransactions", "trytes": ["BYSWEAUTWXHXZ9YBZISEK9LUHWGMHXCGEVNZHRLUWQFCUSDXZHOFHWHL9MQPVJXXZLIXPXPXF9KYEREFSKCPKYIIKPZVLHUTDFQKKVVBBN9ATTLPCNPJDWDEVIYYLGPZGCWXOBDXMLJC9VO9QXTTBLAXTTBFUAROYEGQIVB9MJWJKXJMCUPTWAUGFZBTZCSJVRBGMYXTVBDDS9MYUJCPZ9YDWWQNIPUAIJXXSNLKUBSCOIJPCLEFPOXFJREXQCUVUMKSDOVQGGHRNILCO9GNCLWFM9APMNMWYASHXQAYBEXF9QRIHIBHYEJOYHRQJAOKAQ9AJJFQ9WEIWIJOTZATIBOXQLBMIJU9PCGBLVDDVFP9CFFSXTDUXMEGOOFXWRTLFGV9XXMYWEMGQEEEDBTIJ9OJOXFAPFQXCDAXOUDMLVYRMRLUDBETOLRJQAEDDLNVIRQJUBZBO9CCFDHIX9MSQCWYAXJVWHCUPTRSXJDESISQPRKZAFKFRULCGVRSBLVFOPEYLEE99JD9SEBALQINPDAZHFAB9RNBH9AZWIJOTLBZVIEJIAYGMC9AZGNFWGRSWAXTYSXVROVNKCOQQIWGPNQZKHUNODGYADPYLZZZUQRTJRTODOUKAOITNOMWNGHJBBA99QUMBHRENGBHTH9KHUAOXBVIVDVYYZMSEYSJWIOGGXZVRGN999EEGQMCOYVJQRIRROMPCQBLDYIGQO9AMORPYFSSUGACOJXGAQSPDY9YWRRPESNXXBDQ9OZOXVIOMLGTSWAMKMTDRSPGJKGBXQIVNRJRFRYEZ9VJDLHIKPSKMYC9YEGHFDS9SGVDHRIXBEMLFIINOHVPXIFAZCJKBHVMQZEVWCOSNWQRDYWVAIBLSCBGESJUIBWZECPUCAYAWMTQKRMCHONIPKJYYTEGZCJYCT9ABRWTJLRQXKMWY9GWZMHYZNWPXULNZAPVQLPMYQZCYNEPOCGOHBJUZLZDPIXVHLDMQYJUUBEDXXPXFLNRGIPWBRNQQZJSGSJTTYHIGGFAWJVXWL9THTPWOOHTNQWCNYOYZXALHAZXVMIZE9WMQUDCHDJMIBWKTYH9AC9AFOT9DPCADCV9ZWUTE9QNOMSZPTZDJLJZCJGHXUNBJFUBJWQUEZDMHXGBPTNSPZBR9TGSKVOHMOQSWPGFLSWNESFKSAZY9HHERAXALZCABFYPOVLAHMIHVDBGKUMDXC9WHHTIRYHZVWNXSVQUWCR9M9RAGMFEZZKZ9XEOQGOSLFQCHHOKLDSA9QCMDGCGMRYJZLBVIFOLBIJPROKMHOYTBTJIWUZWJMCTKCJKKTR9LCVYPVJI9AHGI9JOWMIWZAGMLDFJA9WU9QAMEFGABIBEZNNAL9OXSBFLOEHKDGHWFQSHMPLYFCNXAAZYJLMQDEYRGL9QKCEUEJ9LLVUOINVSZZQHCIKPAGMT9CAYIIMTTBCPKWTYHOJIIY9GYNPAJNUJ9BKYYXSV9JSPEXYMCFAIKTGNRSQGUNIYZCRT9FOWENSZQPD9ALUPYYAVICHVYELYFPUYDTWUSWNIYFXPX9MICCCOOZIWRNJIDALWGWRATGLJXNAYTNIZWQ9YTVDBOFZRKO9CFWRPAQQRXTPACOWCPRLYRYSJARRKSQPR9TCFXDVIXLP9XVL99ERRDSOHBFJDJQQGGGCZNDQ9NYCTQJWVZIAELCRBJJFDMCNZU9FIZRPGNURTXOCDSQGXTQHKHUECGWFUUYS9J9NYQ9U9P9UUP9YMZHWWWCIASCFLCMSKTELZWUGCDE9YOKVOVKTAYPHDF9ZCCQAYPJIJNGSHUIHHCOSSOOBUDOKE9CJZGYSSGNCQJVBEFTZFJ9SQUHOASKRRGBSHWKBCBWBTJHOGQ9WOMQFHWJVEG9NYX9KWBTCAIXNXHEBDIOFO9ALYMFGRICLCKKLG9FOBOX9PDWNQRGHBKHGKKRLWTBEQMCWQRLHAVYYZDIIPKVQTHYTWQMTOACXZOQCDTJTBAAUWXSGJF9PNQIJ9AJRUMUVCPWYVYVARKR9RKGOUHHNKNVGGPDDLGKPQNOYHNKAVVKCXWXOQPZNSLATUJT9AUWRMPPSWHSTTYDFAQDXOCYTZHOYYGAIM9CELMZ9AZPWB9MJXGHOKDNNSZVUDAGXTJJSSZCPZVPZBYNNTUQABSXQWZCHDQSLGK9UOHCFKBIBNETK999999999999999999999999999999999999999999999999999999999999999999999999999999999NOXDXXKUDWLOFJLIPQIBRBMGDYCPGDNLQOLQS99EQYKBIU9VHCJVIPFUYCQDNY9APGEVYLCENJIOBLWNB999999999XKBRHUD99C99999999NKZKEKWLDKMJCI9N9XQOLWEPAYWSH9999999999999999999999999KDDTGZLIPBNZKMLTOLOXQVNGLASESDQVPTXALEKRMIOHQLUHD9ELQDBQETS9QFGTYOYWLNTSKKMVJAUXSIROUICDOXKSYZTDPEDKOQENTJOWJONDEWROCEJIEWFWLUAACVSJFTMCHHXJBJRKAAPUDXXVXFWP9X9999IROUICDOXKSYZTDPEDKOQENTJOWJONDEWROCEJIEWFWLUAACVSJFTMCHHXJBJRKAAPUDXXVXFWP9X9999"]}'} */ @Headers({CONTENT_TYPE_HEADER, USER_AGENT_HEADER}) @POST("./") @@ -153,8 +153,8 @@ public interface IotaAPIService { /** * Store transactions into the local storage. The trytes to be used for this call are returned by attachToTangle. *

- * curl http://localhost:14265 -X POST -H 'Content-Type: application/json' - * -d '{"command": "storeTransactions", "trytes": ["BYSWEAUTWXHXZ9YBZISEK9LUHWGMHXCGEVNZHRLUWQFCUSDXZHOFHWHL9MQPVJXXZLIXPXPXF9KYEREFSKCPKYIIKPZVLHUTDFQKKVVBBN9ATTLPCNPJDWDEVIYYLGPZGCWXOBDXMLJC9VO9QXTTBLAXTTBFUAROYEGQIVB9MJWJKXJMCUPTWAUGFZBTZCSJVRBGMYXTVBDDS9MYUJCPZ9YDWWQNIPUAIJXXSNLKUBSCOIJPCLEFPOXFJREXQCUVUMKSDOVQGGHRNILCO9GNCLWFM9APMNMWYASHXQAYBEXF9QRIHIBHYEJOYHRQJAOKAQ9AJJFQ9WEIWIJOTZATIBOXQLBMIJU9PCGBLVDDVFP9CFFSXTDUXMEGOOFXWRTLFGV9XXMYWEMGQEEEDBTIJ9OJOXFAPFQXCDAXOUDMLVYRMRLUDBETOLRJQAEDDLNVIRQJUBZBO9CCFDHIX9MSQCWYAXJVWHCUPTRSXJDESISQPRKZAFKFRULCGVRSBLVFOPEYLEE99JD9SEBALQINPDAZHFAB9RNBH9AZWIJOTLBZVIEJIAYGMC9AZGNFWGRSWAXTYSXVROVNKCOQQIWGPNQZKHUNODGYADPYLZZZUQRTJRTODOUKAOITNOMWNGHJBBA99QUMBHRENGBHTH9KHUAOXBVIVDVYYZMSEYSJWIOGGXZVRGN999EEGQMCOYVJQRIRROMPCQBLDYIGQO9AMORPYFSSUGACOJXGAQSPDY9YWRRPESNXXBDQ9OZOXVIOMLGTSWAMKMTDRSPGJKGBXQIVNRJRFRYEZ9VJDLHIKPSKMYC9YEGHFDS9SGVDHRIXBEMLFIINOHVPXIFAZCJKBHVMQZEVWCOSNWQRDYWVAIBLSCBGESJUIBWZECPUCAYAWMTQKRMCHONIPKJYYTEGZCJYCT9ABRWTJLRQXKMWY9GWZMHYZNWPXULNZAPVQLPMYQZCYNEPOCGOHBJUZLZDPIXVHLDMQYJUUBEDXXPXFLNRGIPWBRNQQZJSGSJTTYHIGGFAWJVXWL9THTPWOOHTNQWCNYOYZXALHAZXVMIZE9WMQUDCHDJMIBWKTYH9AC9AFOT9DPCADCV9ZWUTE9QNOMSZPTZDJLJZCJGHXUNBJFUBJWQUEZDMHXGBPTNSPZBR9TGSKVOHMOQSWPGFLSWNESFKSAZY9HHERAXALZCABFYPOVLAHMIHVDBGKUMDXC9WHHTIRYHZVWNXSVQUWCR9M9RAGMFEZZKZ9XEOQGOSLFQCHHOKLDSA9QCMDGCGMRYJZLBVIFOLBIJPROKMHOYTBTJIWUZWJMCTKCJKKTR9LCVYPVJI9AHGI9JOWMIWZAGMLDFJA9WU9QAMEFGABIBEZNNAL9OXSBFLOEHKDGHWFQSHMPLYFCNXAAZYJLMQDEYRGL9QKCEUEJ9LLVUOINVSZZQHCIKPAGMT9CAYIIMTTBCPKWTYHOJIIY9GYNPAJNUJ9BKYYXSV9JSPEXYMCFAIKTGNRSQGUNIYZCRT9FOWENSZQPD9ALUPYYAVICHVYELYFPUYDTWUSWNIYFXPX9MICCCOOZIWRNJIDALWGWRATGLJXNAYTNIZWQ9YTVDBOFZRKO9CFWRPAQQRXTPACOWCPRLYRYSJARRKSQPR9TCFXDVIXLP9XVL99ERRDSOHBFJDJQQGGGCZNDQ9NYCTQJWVZIAELCRBJJFDMCNZU9FIZRPGNURTXOCDSQGXTQHKHUECGWFUUYS9J9NYQ9U9P9UUP9YMZHWWWCIASCFLCMSKTELZWUGCDE9YOKVOVKTAYPHDF9ZCCQAYPJIJNGSHUIHHCOSSOOBUDOKE9CJZGYSSGNCQJVBEFTZFJ9SQUHOASKRRGBSHWKBCBWBTJHOGQ9WOMQFHWJVEG9NYX9KWBTCAIXNXHEBDIOFO9ALYMFGRICLCKKLG9FOBOX9PDWNQRGHBKHGKKRLWTBEQMCWQRLHAVYYZDIIPKVQTHYTWQMTOACXZOQCDTJTBAAUWXSGJF9PNQIJ9AJRUMUVCPWYVYVARKR9RKGOUHHNKNVGGPDDLGKPQNOYHNKAVVKCXWXOQPZNSLATUJT9AUWRMPPSWHSTTYDFAQDXOCYTZHOYYGAIM9CELMZ9AZPWB9MJXGHOKDNNSZVUDAGXTJJSSZCPZVPZBYNNTUQABSXQWZCHDQSLGK9UOHCFKBIBNETK999999999999999999999999999999999999999999999999999999999999999999999999999999999NOXDXXKUDWLOFJLIPQIBRBMGDYCPGDNLQOLQS99EQYKBIU9VHCJVIPFUYCQDNY9APGEVYLCENJIOBLWNB999999999XKBRHUD99C99999999NKZKEKWLDKMJCI9N9XQOLWEPAYWSH9999999999999999999999999KDDTGZLIPBNZKMLTOLOXQVNGLASESDQVPTXALEKRMIOHQLUHD9ELQDBQETS9QFGTYOYWLNTSKKMVJAUXSIROUICDOXKSYZTDPEDKOQENTJOWJONDEWROCEJIEWFWLUAACVSJFTMCHHXJBJRKAAPUDXXVXFWP9X9999IROUICDOXKSYZTDPEDKOQENTJOWJONDEWROCEJIEWFWLUAACVSJFTMCHHXJBJRKAAPUDXXVXFWP9X9999"]}' + * {@code curl http://localhost:14265 -X POST -H 'X-IOTA-API-Version: 1.4.1' -H 'Content-Type: application/json'} + * {@code -d '{"command": "storeTransactions", "trytes": ["BYSWEAUTWXHXZ9YBZISEK9LUHWGMHXCGEVNZHRLUWQFCUSDXZHOFHWHL9MQPVJXXZLIXPXPXF9KYEREFSKCPKYIIKPZVLHUTDFQKKVVBBN9ATTLPCNPJDWDEVIYYLGPZGCWXOBDXMLJC9VO9QXTTBLAXTTBFUAROYEGQIVB9MJWJKXJMCUPTWAUGFZBTZCSJVRBGMYXTVBDDS9MYUJCPZ9YDWWQNIPUAIJXXSNLKUBSCOIJPCLEFPOXFJREXQCUVUMKSDOVQGGHRNILCO9GNCLWFM9APMNMWYASHXQAYBEXF9QRIHIBHYEJOYHRQJAOKAQ9AJJFQ9WEIWIJOTZATIBOXQLBMIJU9PCGBLVDDVFP9CFFSXTDUXMEGOOFXWRTLFGV9XXMYWEMGQEEEDBTIJ9OJOXFAPFQXCDAXOUDMLVYRMRLUDBETOLRJQAEDDLNVIRQJUBZBO9CCFDHIX9MSQCWYAXJVWHCUPTRSXJDESISQPRKZAFKFRULCGVRSBLVFOPEYLEE99JD9SEBALQINPDAZHFAB9RNBH9AZWIJOTLBZVIEJIAYGMC9AZGNFWGRSWAXTYSXVROVNKCOQQIWGPNQZKHUNODGYADPYLZZZUQRTJRTODOUKAOITNOMWNGHJBBA99QUMBHRENGBHTH9KHUAOXBVIVDVYYZMSEYSJWIOGGXZVRGN999EEGQMCOYVJQRIRROMPCQBLDYIGQO9AMORPYFSSUGACOJXGAQSPDY9YWRRPESNXXBDQ9OZOXVIOMLGTSWAMKMTDRSPGJKGBXQIVNRJRFRYEZ9VJDLHIKPSKMYC9YEGHFDS9SGVDHRIXBEMLFIINOHVPXIFAZCJKBHVMQZEVWCOSNWQRDYWVAIBLSCBGESJUIBWZECPUCAYAWMTQKRMCHONIPKJYYTEGZCJYCT9ABRWTJLRQXKMWY9GWZMHYZNWPXULNZAPVQLPMYQZCYNEPOCGOHBJUZLZDPIXVHLDMQYJUUBEDXXPXFLNRGIPWBRNQQZJSGSJTTYHIGGFAWJVXWL9THTPWOOHTNQWCNYOYZXALHAZXVMIZE9WMQUDCHDJMIBWKTYH9AC9AFOT9DPCADCV9ZWUTE9QNOMSZPTZDJLJZCJGHXUNBJFUBJWQUEZDMHXGBPTNSPZBR9TGSKVOHMOQSWPGFLSWNESFKSAZY9HHERAXALZCABFYPOVLAHMIHVDBGKUMDXC9WHHTIRYHZVWNXSVQUWCR9M9RAGMFEZZKZ9XEOQGOSLFQCHHOKLDSA9QCMDGCGMRYJZLBVIFOLBIJPROKMHOYTBTJIWUZWJMCTKCJKKTR9LCVYPVJI9AHGI9JOWMIWZAGMLDFJA9WU9QAMEFGABIBEZNNAL9OXSBFLOEHKDGHWFQSHMPLYFCNXAAZYJLMQDEYRGL9QKCEUEJ9LLVUOINVSZZQHCIKPAGMT9CAYIIMTTBCPKWTYHOJIIY9GYNPAJNUJ9BKYYXSV9JSPEXYMCFAIKTGNRSQGUNIYZCRT9FOWENSZQPD9ALUPYYAVICHVYELYFPUYDTWUSWNIYFXPX9MICCCOOZIWRNJIDALWGWRATGLJXNAYTNIZWQ9YTVDBOFZRKO9CFWRPAQQRXTPACOWCPRLYRYSJARRKSQPR9TCFXDVIXLP9XVL99ERRDSOHBFJDJQQGGGCZNDQ9NYCTQJWVZIAELCRBJJFDMCNZU9FIZRPGNURTXOCDSQGXTQHKHUECGWFUUYS9J9NYQ9U9P9UUP9YMZHWWWCIASCFLCMSKTELZWUGCDE9YOKVOVKTAYPHDF9ZCCQAYPJIJNGSHUIHHCOSSOOBUDOKE9CJZGYSSGNCQJVBEFTZFJ9SQUHOASKRRGBSHWKBCBWBTJHOGQ9WOMQFHWJVEG9NYX9KWBTCAIXNXHEBDIOFO9ALYMFGRICLCKKLG9FOBOX9PDWNQRGHBKHGKKRLWTBEQMCWQRLHAVYYZDIIPKVQTHYTWQMTOACXZOQCDTJTBAAUWXSGJF9PNQIJ9AJRUMUVCPWYVYVARKR9RKGOUHHNKNVGGPDDLGKPQNOYHNKAVVKCXWXOQPZNSLATUJT9AUWRMPPSWHSTTYDFAQDXOCYTZHOYYGAIM9CELMZ9AZPWB9MJXGHOKDNNSZVUDAGXTJJSSZCPZVPZBYNNTUQABSXQWZCHDQSLGK9UOHCFKBIBNETK999999999999999999999999999999999999999999999999999999999999999999999999999999999NOXDXXKUDWLOFJLIPQIBRBMGDYCPGDNLQOLQS99EQYKBIU9VHCJVIPFUYCQDNY9APGEVYLCENJIOBLWNB999999999XKBRHUD99C99999999NKZKEKWLDKMJCI9N9XQOLWEPAYWSH9999999999999999999999999KDDTGZLIPBNZKMLTOLOXQVNGLASESDQVPTXALEKRMIOHQLUHD9ELQDBQETS9QFGTYOYWLNTSKKMVJAUXSIROUICDOXKSYZTDPEDKOQENTJOWJONDEWROCEJIEWFWLUAACVSJFTMCHHXJBJRKAAPUDXXVXFWP9X9999IROUICDOXKSYZTDPEDKOQENTJOWJONDEWROCEJIEWFWLUAACVSJFTMCHHXJBJRKAAPUDXXVXFWP9X9999"]}'} */ @Headers({CONTENT_TYPE_HEADER, USER_AGENT_HEADER}) @POST("./") diff --git a/jota/src/main/java/jota/dto/request/IotaAttachToTangleRequest.java b/jota/src/main/java/jota/dto/request/IotaAttachToTangleRequest.java index 5dba481..6e7fe01 100644 --- a/jota/src/main/java/jota/dto/request/IotaAttachToTangleRequest.java +++ b/jota/src/main/java/jota/dto/request/IotaAttachToTangleRequest.java @@ -4,7 +4,7 @@ import jota.IotaAPICommands; /** * This class represents the core API request 'attachToTangle'. - *

+ * * It is used to attach trytes to the tangle. **/ public class IotaAttachToTangleRequest extends IotaCommandRequest { diff --git a/jota/src/main/java/jota/dto/request/IotaBroadcastTransactionRequest.java b/jota/src/main/java/jota/dto/request/IotaBroadcastTransactionRequest.java index e09afc0..61d27cd 100644 --- a/jota/src/main/java/jota/dto/request/IotaBroadcastTransactionRequest.java +++ b/jota/src/main/java/jota/dto/request/IotaBroadcastTransactionRequest.java @@ -4,7 +4,7 @@ import jota.IotaAPICommands; /** * This class represents the core API request 'broadcastTransaction'. - *

+ * * Broadcast a list of transactions to all neighbors. The input trytes for this call are provided by attachToTangle **/ public class IotaBroadcastTransactionRequest extends IotaCommandRequest { diff --git a/jota/src/main/java/jota/dto/request/IotaCommandRequest.java b/jota/src/main/java/jota/dto/request/IotaCommandRequest.java index f99628d..26c5432 100644 --- a/jota/src/main/java/jota/dto/request/IotaCommandRequest.java +++ b/jota/src/main/java/jota/dto/request/IotaCommandRequest.java @@ -10,7 +10,7 @@ public class IotaCommandRequest { final String command; /** - * @param command + * Initializes a new instance of the IotaCommandRequest class. */ protected IotaCommandRequest(IotaAPICommands command) { this.command = command.command(); diff --git a/jota/src/main/java/jota/dto/request/IotaStoreTransactionsRequest.java b/jota/src/main/java/jota/dto/request/IotaStoreTransactionsRequest.java index 7e774b7..1662d9a 100644 --- a/jota/src/main/java/jota/dto/request/IotaStoreTransactionsRequest.java +++ b/jota/src/main/java/jota/dto/request/IotaStoreTransactionsRequest.java @@ -4,7 +4,7 @@ import jota.IotaAPICommands; /** * This class represents the core API request 'getTransactionsToApprove'. - *

+ * * It stores transactions into the local storage. The trytes to be used for this call are returned by attachToTangle. **/ public class IotaStoreTransactionsRequest extends IotaCommandRequest { diff --git a/jota/src/main/java/jota/dto/response/GetAccountDataResponse.java b/jota/src/main/java/jota/dto/response/GetAccountDataResponse.java index 27ee80a..a4fffda 100644 --- a/jota/src/main/java/jota/dto/response/GetAccountDataResponse.java +++ b/jota/src/main/java/jota/dto/response/GetAccountDataResponse.java @@ -1,6 +1,7 @@ package jota.dto.response; import jota.model.Bundle; +import jota.model.Input; import java.util.List; @@ -11,16 +12,18 @@ public class GetAccountDataResponse extends AbstractResponse { private List addresses; private Bundle[] transferBundle; + private List inputs; private long balance; /** * Initializes a new instance of the GetAccountDataResponse class. */ - public static GetAccountDataResponse create(List addresses, Bundle[] transferBundle, long balance, long duration) { + public static GetAccountDataResponse create(List addresses, Bundle[] transferBundle, List inputs, long balance, long duration) { GetAccountDataResponse res = new GetAccountDataResponse(); res.addresses = addresses; res.transferBundle = transferBundle; + res.inputs = inputs; res.balance = balance; res.setDuration(duration); return res; @@ -44,6 +47,15 @@ public class GetAccountDataResponse extends AbstractResponse { return transferBundle; } + /** + * Gets the inputs. + * + * @return The inputs. + */ + public List getInput() { + return inputs; + } + /** * Gets the balance. * diff --git a/jota/src/main/java/jota/dto/response/GetBalancesAndFormatResponse.java b/jota/src/main/java/jota/dto/response/GetBalancesAndFormatResponse.java index 2d41d6d..819cf9f 100644 --- a/jota/src/main/java/jota/dto/response/GetBalancesAndFormatResponse.java +++ b/jota/src/main/java/jota/dto/response/GetBalancesAndFormatResponse.java @@ -9,16 +9,16 @@ import java.util.List; **/ public class GetBalancesAndFormatResponse extends AbstractResponse { - private List input; + private List inputs; private long totalBalance; /** * Initializes a new instance of the GetBalancesAndFormatResponse class. */ - public static GetBalancesAndFormatResponse create(List inputs, long totalBalance2, long duration) { + public static GetBalancesAndFormatResponse create(List inputs, long totalBalance, long duration) { GetBalancesAndFormatResponse res = new GetBalancesAndFormatResponse(); - res.setInput(inputs); - res.setTotalBalance(totalBalance2); + res.inputs = inputs; + res.totalBalance = totalBalance; res.setDuration(duration); return res; } @@ -28,8 +28,8 @@ public class GetBalancesAndFormatResponse extends AbstractResponse { * * @return The transactions. */ - public List getInput() { - return input; + public List getInputs() { + return inputs; } /** @@ -37,8 +37,8 @@ public class GetBalancesAndFormatResponse extends AbstractResponse { * * @param input The input. */ - public void setInput(List input) { - this.input = input; + public void setInputs(List input) { + this.inputs = inputs; } /** diff --git a/jota/src/main/java/jota/dto/response/GetNodeInfoResponse.java b/jota/src/main/java/jota/dto/response/GetNodeInfoResponse.java index d9e75ad..132a455 100644 --- a/jota/src/main/java/jota/dto/response/GetNodeInfoResponse.java +++ b/jota/src/main/java/jota/dto/response/GetNodeInfoResponse.java @@ -23,7 +23,7 @@ public class GetNodeInfoResponse extends AbstractResponse { private int transactionsToRequest; /** - * Name of the IOTA software you're currently using (IRI stands for Initial Reference Implementation). + * The name of the IOTA software the node currently running (IRI stands for Initial Reference Implementation). * * @return appName */ @@ -32,9 +32,9 @@ public class GetNodeInfoResponse extends AbstractResponse { } /** - * The version of the IOTA software you're currently running. + * The version of the IOTA software the node currently running. * - * @return The version of the IOTA software you're currently running. + * @return The version of the IOTA software the node currently running. */ public String getAppVersion() { return appVersion; @@ -50,9 +50,9 @@ public class GetNodeInfoResponse extends AbstractResponse { } /** - * Available cores on your machine for JRE. + * Available cores on the node currently running. * - * @return Available cores on your machine for JRE. + * @return Available cores on the machine for JRE. */ public Integer getJreAvailableProcessors() { return jreAvailableProcessors; @@ -105,7 +105,7 @@ public class GetNodeInfoResponse extends AbstractResponse { /** * The latest milestone which is solid and is used for sending transactions. - * For a milestone to become solid your local node must basically approve the subtangle of coordinator-approved transactions, + * For a milestone to become solid the local node must basically approve the subtangle of coordinator-approved transactions, * and have a consistent view of all referenced transactions. * * @return The latest milestone which is solid and is used for sending transactions. @@ -124,9 +124,9 @@ public class GetNodeInfoResponse extends AbstractResponse { } /** - * Number of neighbors you are directly connected with. + * Number of neighbors the node connected with. * - * @return Number of neighbors you are directly connected with. + * @return Number of neighbors the node connected with. */ public int getNeighbors() { return neighbors; diff --git a/jota/src/main/java/jota/dto/response/GetTransferResponse.java b/jota/src/main/java/jota/dto/response/GetTransferResponse.java index bc3060c..f065ee5 100644 --- a/jota/src/main/java/jota/dto/response/GetTransferResponse.java +++ b/jota/src/main/java/jota/dto/response/GetTransferResponse.java @@ -15,6 +15,7 @@ public class GetTransferResponse extends AbstractResponse { public static GetTransferResponse create(Bundle[] transferBundle, long duration) { GetTransferResponse res = new GetTransferResponse(); res.transferBundle = transferBundle; + res.setDuration(duration); return res; } diff --git a/jota/src/main/java/jota/dto/response/SendTransferResponse.java b/jota/src/main/java/jota/dto/response/SendTransferResponse.java index 7e29653..19eda85 100644 --- a/jota/src/main/java/jota/dto/response/SendTransferResponse.java +++ b/jota/src/main/java/jota/dto/response/SendTransferResponse.java @@ -1,22 +1,47 @@ package jota.dto.response; +import jota.model.Transaction; + +import java.util.ArrayList; +import java.util.List; + /** * Response of api request 'sendTransfer'. **/ public class SendTransferResponse extends AbstractResponse { + private List transactions = new ArrayList<>(); private Boolean[] successfully; /** * Initializes a new instance of the SendTransferResponse class. */ - public static SendTransferResponse create(Boolean[] successfully, long duration) { + public static SendTransferResponse create(List transactions, Boolean[] successfully, long duration) { SendTransferResponse res = new SendTransferResponse(); + res.transactions = transactions; res.successfully = successfully; res.setDuration(duration); return res; } + /** + * Gets the transactions. + * + * @return The transactions. + */ + public List getTransactions() { + return transactions; + } + + /** + * Sets the transactions. + * + * @param transactions The transactions. + */ + public void setTransactions(List transactions) { + this.transactions = transactions; + } + /** * Gets the successfully. * @@ -34,5 +59,4 @@ public class SendTransferResponse extends AbstractResponse { public void setSuccessfully(Boolean[] successfully) { this.successfully = successfully; } - } diff --git a/jota/src/main/java/jota/error/BroadcastAndStoreException.java b/jota/src/main/java/jota/error/BroadcastAndStoreException.java deleted file mode 100644 index 8ad2c20..0000000 --- a/jota/src/main/java/jota/error/BroadcastAndStoreException.java +++ /dev/null @@ -1,16 +0,0 @@ -package jota.error; - -/** - * This exceptions occurs if its not possible to broadcast and store. - * - * @author Adrian - */ -public class BroadcastAndStoreException extends BaseException { - - /** - * Initializes a new instance of the BroadcastAndStoreException. - */ - public BroadcastAndStoreException() { - super("Impossible to broadcastAndStore, aborting."); - } -} \ No newline at end of file diff --git a/jota/src/main/java/jota/error/InvalidAddressException.java b/jota/src/main/java/jota/error/InvalidAddressException.java deleted file mode 100644 index 9c6b591..0000000 --- a/jota/src/main/java/jota/error/InvalidAddressException.java +++ /dev/null @@ -1,16 +0,0 @@ -package jota.error; - -/** - * This exception occurs when an invalid address is provided. - * - * @author Adrian - */ -public class InvalidAddressException extends BaseException { - - /** - * Initializes a new instance of the InvalidAddressException. - */ - public InvalidAddressException() { - super("Invalid Address!"); - } -} diff --git a/jota/src/main/java/jota/error/InvalidApiVersionException.java b/jota/src/main/java/jota/error/InvalidApiVersionException.java deleted file mode 100644 index e5776af..0000000 --- a/jota/src/main/java/jota/error/InvalidApiVersionException.java +++ /dev/null @@ -1,16 +0,0 @@ -package jota.error; - - /** - * This exception occurs when invalid api version is provided. - * - * @author pinpong - */ - public class InvalidApiVersionException extends BaseException { - - /** - * Initializes a new instance of the InvalidApiVersionException. - */ - public InvalidApiVersionException() { - super("Invalid api version"); - } -} diff --git a/jota/src/main/java/jota/error/InvalidBundleException.java b/jota/src/main/java/jota/error/InvalidBundleException.java deleted file mode 100644 index 55da93b..0000000 --- a/jota/src/main/java/jota/error/InvalidBundleException.java +++ /dev/null @@ -1,23 +0,0 @@ -package jota.error; - -/** - * This exceptions occurs if an invalid bundle was found or provided. - * - * @author Adrian - */ -public class InvalidBundleException extends BaseException { - - /** - * Initializes a new instance of the InvalidBundleException. - */ - public InvalidBundleException() { - super("Invalid Bundle"); - } - - /** - * Initializes a new instance of the InvalidBundleException. - */ - public InvalidBundleException(String msg) { - super(msg); - } -} diff --git a/jota/src/main/java/jota/error/InvalidSecurityLevelException.java b/jota/src/main/java/jota/error/InvalidSecurityLevelException.java deleted file mode 100644 index b48e6af..0000000 --- a/jota/src/main/java/jota/error/InvalidSecurityLevelException.java +++ /dev/null @@ -1,16 +0,0 @@ -package jota.error; - -/** - * This exception occurs when an invalid security level is provided. - * - * @author pinpong - */ -public class InvalidSecurityLevelException extends BaseException { - - /** - * Initializes a new instance of the InvalidSecurityLevelException. - */ - public InvalidSecurityLevelException() { - super("Invalid security level"); - } -} diff --git a/jota/src/main/java/jota/error/InvalidSignatureException.java b/jota/src/main/java/jota/error/InvalidSignatureException.java deleted file mode 100644 index 79944ea..0000000 --- a/jota/src/main/java/jota/error/InvalidSignatureException.java +++ /dev/null @@ -1,16 +0,0 @@ -package jota.error; - -/** - * This exception occurs when an invalid signature is encountered. - * - * @author Adrian - */ -public class InvalidSignatureException extends BaseException { - - /** - * Initializes a new instance of the InvalidSignatureException. - */ - public InvalidSignatureException() { - super("Invalid Signatures!"); - } -} diff --git a/jota/src/main/java/jota/error/InvalidTransferException.java b/jota/src/main/java/jota/error/InvalidTransferException.java deleted file mode 100644 index 0da3d9b..0000000 --- a/jota/src/main/java/jota/error/InvalidTransferException.java +++ /dev/null @@ -1,16 +0,0 @@ -package jota.error; - -/** - * This exception occurs when an invalid transfer is provided. - * - * @author pinpong - */ -public class InvalidTransferException extends BaseException { - - /** - * Initializes a new instance of the InvalidTransferException. - */ - public InvalidTransferException() { - super("Invalid Transfer!"); - } -} diff --git a/jota/src/main/java/jota/error/InvalidTrytesException.java b/jota/src/main/java/jota/error/InvalidTrytesException.java deleted file mode 100644 index de97ff0..0000000 --- a/jota/src/main/java/jota/error/InvalidTrytesException.java +++ /dev/null @@ -1,16 +0,0 @@ -package jota.error; - -/** - * This exception occurs when invalid trytes is provided. - * - * @author Adrian - */ -public class InvalidTrytesException extends BaseException { - - /** - * Initializes a new instance of the InvalidTrytesException. - */ - public InvalidTrytesException() { - super("Invalid input trytes"); - } -} \ No newline at end of file diff --git a/jota/src/main/java/jota/error/NoInclusionStatesException.java b/jota/src/main/java/jota/error/NoInclusionStatesException.java deleted file mode 100644 index 65dd2d4..0000000 --- a/jota/src/main/java/jota/error/NoInclusionStatesException.java +++ /dev/null @@ -1,16 +0,0 @@ -package jota.error; - -/** - * This exception occurs when it not possible to get a inclusion state. - * - * @author Adrian - */ -public class NoInclusionStatesException extends BaseException { - - /** - * Initializes a new instance of the NoInclusionStatesException. - */ - public NoInclusionStatesException() { - super("No inclusion states for the provided seed"); - } -} diff --git a/jota/src/main/java/jota/error/NoNodeInfoException.java b/jota/src/main/java/jota/error/NoNodeInfoException.java deleted file mode 100644 index fba5f37..0000000 --- a/jota/src/main/java/jota/error/NoNodeInfoException.java +++ /dev/null @@ -1,16 +0,0 @@ -package jota.error; - -/** - * This exception occurs when its not possible to get node info. - * - * @author Adrian - */ -public class NoNodeInfoException extends BaseException { - - /** - * Initializes a new instance of the NoNodeInfoException. - */ - public NoNodeInfoException() { - super("Node info could not be retrieved"); - } -} \ No newline at end of file diff --git a/jota/src/main/java/jota/error/NotEnoughBalanceException.java b/jota/src/main/java/jota/error/NotEnoughBalanceException.java deleted file mode 100644 index 3abe9f8..0000000 --- a/jota/src/main/java/jota/error/NotEnoughBalanceException.java +++ /dev/null @@ -1,21 +0,0 @@ -package jota.error; - -/** - * This exception occurs when a transfer fails because their is not enough balance to perform the transfer. - * - * @author Adrian - */ -public class NotEnoughBalanceException extends BaseException { - - /** - * Serial version UID - */ - private static final long serialVersionUID = -3807270816402226476L; - - /** - * Initializes a new instance of the NotEnoughBalanceException. - */ - public NotEnoughBalanceException() { - super("Not enough balance"); - } -} diff --git a/jota/src/main/java/jota/model/Bundle.java b/jota/src/main/java/jota/model/Bundle.java index 40c0e42..3ed3840 100644 --- a/jota/src/main/java/jota/model/Bundle.java +++ b/jota/src/main/java/jota/model/Bundle.java @@ -123,14 +123,14 @@ public class Bundle implements Comparable { normalizedBundleValue = normalizedBundle(hashInTrytes); boolean foundValue = false; - for (int i = 0; i < normalizedBundleValue.length; i++) { - if (normalizedBundleValue[i] == 13) { - foundValue = true; - obsoleteTagTrits = Converter.trits(this.getTransactions().get(0).getObsoleteTag()); - Converter.increment(obsoleteTagTrits, 81); - this.getTransactions().get(0).setObsoleteTag(Converter.trytes(obsoleteTagTrits)); + for (int aNormalizedBundleValue : normalizedBundleValue) { + if (aNormalizedBundleValue == 13) { + foundValue = true; + obsoleteTagTrits = Converter.trits(this.getTransactions().get(0).getObsoleteTag()); + Converter.increment(obsoleteTagTrits, 81); + this.getTransactions().get(0).setObsoleteTag(Converter.trytes(obsoleteTagTrits)); + } } - } valid = !foundValue; } while (!valid); @@ -148,7 +148,7 @@ public class Bundle implements Comparable { public void addTrytes(List signatureFragments) { String emptySignatureFragment = ""; String emptyHash = EMPTY_HASH; - long emptyTimestamp = 999999999l; + long emptyTimestamp = 999999999L; emptySignatureFragment = StringUtils.rightPad(emptySignatureFragment, 2187, '9'); diff --git a/jota/src/main/java/jota/model/Transaction.java b/jota/src/main/java/jota/model/Transaction.java index cedce1f..716c5f0 100644 --- a/jota/src/main/java/jota/model/Transaction.java +++ b/jota/src/main/java/jota/model/Transaction.java @@ -423,7 +423,7 @@ public class Transaction { this.tag = this.tag != null && !this.tag.isEmpty() ? this.tag : this.obsoleteTag; - String trx = this.getSignatureFragments() + return this.getSignatureFragments() + this.getAddress() + Converter.trytes(valueTrits) + this.getObsoleteTag() @@ -438,7 +438,6 @@ public class Transaction { + Converter.trytes(attachmentTimestampLowerBoundTrits) + Converter.trytes(attachmentTimestampUpperBoundTrits) + this.getNonce(); - return trx; } /** diff --git a/jota/src/main/java/jota/model/Transfer.java b/jota/src/main/java/jota/model/Transfer.java index 545e6e0..0b33b1b 100644 --- a/jota/src/main/java/jota/model/Transfer.java +++ b/jota/src/main/java/jota/model/Transfer.java @@ -29,7 +29,16 @@ public class Transfer { this.value = value; this.message = message; this.tag = tag; + } + /** + * Initializes a new instance of the Transfer class. + */ + public Transfer(String address, long value) { + this.address = address; + this.value = value; + this.message = ""; + this.tag = ""; } /** @@ -118,7 +127,7 @@ public class Transfer { /** * Set the timestamp. * - * @param timestamp The timestamp. + * @param timestamp The timestamp in seconds. */ public void setTimestamp(String timestamp) { this.timestamp = timestamp; @@ -154,7 +163,7 @@ public class Transfer { /** * Set the message. * - * @param message The message. + * @param message The message trytes encoded. */ public void setMessage(String message) { this.message = message; @@ -172,7 +181,7 @@ public class Transfer { /** * Set the tag. * - * @param tag The tag. + * @param tag The tag max 27 trytes encoded. */ public void setTag(String tag) { this.tag = tag; diff --git a/jota/src/main/java/jota/pow/JCurl.java b/jota/src/main/java/jota/pow/JCurl.java index 4096ec8..88c1a69 100644 --- a/jota/src/main/java/jota/pow/JCurl.java +++ b/jota/src/main/java/jota/pow/JCurl.java @@ -8,7 +8,7 @@ import java.util.NoSuchElementException; /** * (c) 2016 Come-from-Beyond - *

+ * * JCurl belongs to the sponge function family. */ public class JCurl implements ICurl { diff --git a/jota/src/main/java/jota/pow/Kerl.java b/jota/src/main/java/jota/pow/Kerl.java index c916060..9c4cdef 100644 --- a/jota/src/main/java/jota/pow/Kerl.java +++ b/jota/src/main/java/jota/pow/Kerl.java @@ -40,8 +40,8 @@ public class Kerl extends JCurl { private static int sum(int[] toSum) { int sum = 0; - for (int i = 0; i < toSum.length; i++) { - sum += toSum[i]; + for (int aToSum : toSum) { + sum += aToSum; } return sum; } diff --git a/jota/src/main/java/jota/utils/Checksum.java b/jota/src/main/java/jota/utils/Checksum.java index 08107ca..463da6c 100644 --- a/jota/src/main/java/jota/utils/Checksum.java +++ b/jota/src/main/java/jota/utils/Checksum.java @@ -1,10 +1,12 @@ package jota.utils; -import jota.error.InvalidAddressException; +import jota.error.ArgumentException; import jota.pow.ICurl; import jota.pow.JCurl; import jota.pow.SpongeFactory; +import static jota.utils.Constants.INVALID_ADDRESSES_INPUT_ERROR; + /** * This class defines utility methods to add/remove the checksum to/from an address. * @@ -17,9 +19,9 @@ public class Checksum { * * @param address The address without checksum. * @return The address with the appended checksum. - * @throws InvalidAddressException is thrown when the specified address is not an valid address. + * @throws ArgumentException is thrown when the specified address is not an valid address. **/ - public static String addChecksum(String address) throws InvalidAddressException { + public static String addChecksum(String address) throws ArgumentException { InputValidator.checkAddress(address); String addressWithChecksum = address; addressWithChecksum += calculateChecksum(address); @@ -31,15 +33,15 @@ public class Checksum { * * @param address The address with checksum. * @return The address without checksum. - * @throws InvalidAddressException is thrown when the specified address is not an address with checksum. + * @throws ArgumentException is thrown when the specified address is not an address with checksum. **/ - public static String removeChecksum(String address) throws InvalidAddressException { + public static String removeChecksum(String address) throws ArgumentException { if (isAddressWithChecksum(address)) { return removeChecksumFromAddress(address); } else if (isAddressWithoutChecksum(address)) { return address; } - throw new InvalidAddressException(); + throw new ArgumentException(INVALID_ADDRESSES_INPUT_ERROR); } private static String removeChecksumFromAddress(String addressWithChecksum) { @@ -51,35 +53,33 @@ public class Checksum { * * @param addressWithChecksum The address with checksum. * @return true if the specified address with checksum has a valid checksum [the specified address with checksum]; otherwise, false. - * @throws InvalidAddressException is thrown when the specified address is not an valid address. + * @throws ArgumentException is thrown when the specified address is not an valid address. **/ - public static boolean isValidChecksum(String addressWithChecksum) throws InvalidAddressException { + public static boolean isValidChecksum(String addressWithChecksum) throws ArgumentException { String addressWithoutChecksum = removeChecksum(addressWithChecksum); String addressWithRecalculateChecksum = addressWithoutChecksum += calculateChecksum(addressWithoutChecksum); return addressWithRecalculateChecksum.equals(addressWithChecksum); } - /** - * Check if specified address is a address with checksum. + * Check if specified address is an address with checksum. * * @param address The address to check. * @return true if the specified address is with checksum ; otherwise, false. - * @throws InvalidAddressException is thrown when the specified address is not an valid address + * @throws ArgumentException is thrown when the specified address is not an valid address. **/ - public static boolean isAddressWithChecksum(String address) throws InvalidAddressException { + public static boolean isAddressWithChecksum(String address) throws ArgumentException { return InputValidator.checkAddress(address) && address.length() == Constants.ADDRESS_LENGTH_WITH_CHECKSUM; } - /** - * check if specified address is a address + * Check if specified address is an address without checksum. * - * @param address address - * @return boolean - * @throws InvalidAddressException is thrown when the specified address is not an valid address + * @param address The address to check. + * @return true if the specified address is without checksum ; otherwise, false. + * @throws ArgumentException is thrown when the specified address is not an valid address. **/ - public static boolean isAddressWithoutChecksum(String address) throws InvalidAddressException { + public static boolean isAddressWithoutChecksum(String address) throws ArgumentException { return InputValidator.checkAddress(address) && address.length() == Constants.ADDRESS_LENGTH_WITHOUT_CHECKSUM; } @@ -90,7 +90,6 @@ public class Checksum { int[] checksumTrits = new int[JCurl.HASH_LENGTH]; curl.squeeze(checksumTrits); String checksum = Converter.trytes(checksumTrits); - String checksumPrt = checksum.substring(72, 81); - return checksumPrt; + return checksum.substring(72, 81); } } diff --git a/jota/src/main/java/jota/utils/Constants.java b/jota/src/main/java/jota/utils/Constants.java index 5781486..8fcf759 100644 --- a/jota/src/main/java/jota/utils/Constants.java +++ b/jota/src/main/java/jota/utils/Constants.java @@ -26,4 +26,37 @@ public class Constants { * The length of an address with checksum */ public static int ADDRESS_LENGTH_WITH_CHECKSUM = 90; + + /** + * The length of an message + */ + public static int MESSAGE_LENGTH = 2187; + + /** + * The length of an tag + */ + public static int TAG_LENGTH = 27; + + public static final String INVALID_TRYTES_INPUT_ERROR = "Invalid trytes provided."; + public static final String INVALID_HASHES_INPUT_ERROR = "Invalid hashes provided."; + public static final String INVALID_TAIL_HASH_INPUT_ERROR = "Invalid tail hash provided."; + public static final String INVALID_SEED_INPUT_ERROR = "Invalid seed provided."; + public static final String INVALID_SECURITY_LEVEL_INPUT_ERROR = "Invalid security level provided."; + public static final String INVALID_ATTACHED_TRYTES_INPUT_ERROR = "Invalid attached trytes provided."; + public static final String INVALID_TRANSFERS_INPUT_ERROR = "Invalid transfers provided."; + public static final String INVALID_ADDRESSES_INPUT_ERROR = "Invalid addresses provided."; + public static final String INVALID_INPUT_ERROR = "Invalid input provided."; + + public static final String INVALID_BUNDLE_ERROR = "Invalid bundle."; + public static final String INVALID_BUNDLE_SUM_ERROR = "Invalid bundle sum."; + public static final String INVALID_BUNDLE_HASH_ERROR = "Invalid bundle hash."; + public static final String INVALID_SIGNATURES_ERROR = "Invalid signatures."; + public static final String INVALID_VALUE_TRANSFER_ERROR = "Invalid value transfer: the transfer does not require a signature."; + + public static final String NOT_ENOUGH_BALANCE_ERROR = "Not enough balance."; + public static final String NO_REMAINDER_ADDRESS_ERROR = "No remainder address defined."; + + public static final String GET_TRYTES_RESPONSE_ERROR = "Get trytes response was null."; + public static final String GET_BUNDLE_RESPONSE_ERROR = "Get bundle response was null."; + public static final String GET_INCLUSION_STATE_RESPONSE_ERROR = "Get inclusion state response was null."; } diff --git a/jota/src/main/java/jota/utils/InputValidator.java b/jota/src/main/java/jota/utils/InputValidator.java index 025254f..052c34c 100644 --- a/jota/src/main/java/jota/utils/InputValidator.java +++ b/jota/src/main/java/jota/utils/InputValidator.java @@ -1,11 +1,14 @@ package jota.utils; -import jota.error.InvalidAddressException; +import jota.error.ArgumentException; import jota.model.Transfer; import org.apache.commons.lang3.math.NumberUtils; import java.util.List; +import static jota.utils.Constants.INVALID_ADDRESSES_INPUT_ERROR; +import static jota.utils.Constants.INVALID_TRANSFERS_INPUT_ERROR; + /** * This class provides methods to validate the parameters of different iota API methods. * @@ -24,16 +27,31 @@ public class InputValidator { address.length() == Constants.ADDRESS_LENGTH_WITH_CHECKSUM) && isTrytes(address, address.length()); } + /** + * Determines whether the specified addresses are valid. + * + * @param addresses The address list to validate. + * @return true if the specified addresses are valid; otherwise, false. + **/ + public static boolean isAddressesCollectionValid(final List addresses) throws ArgumentException { + for (final String address : addresses) { + if (!checkAddress(address)) { + return false; + } + } + return true; + } + /** * Checks whether the specified address is an address and throws and exception if the address is invalid. * * @param address The address to validate. * @return true if the specified string is an address; otherwise, false. - * @throws InvalidAddressException is thrown when the specified address is not an valid address. + * @throws ArgumentException is thrown when the specified input is not valid. **/ - public static boolean checkAddress(String address) throws InvalidAddressException { + public static boolean checkAddress(String address) throws ArgumentException { if (!isAddress(address)) { - throw new InvalidAddressException(); + throw new ArgumentException(INVALID_ADDRESSES_INPUT_ERROR); } return true; } @@ -67,7 +85,7 @@ public class InputValidator { * @return true the specified string represents an integer value; otherwise, false. **/ public static boolean isValue(final String value) { - return NumberUtils.isNumber(value); + return NumberUtils.isCreatable(value); } /** @@ -117,7 +135,12 @@ public class InputValidator { * @param transfers The transfers list to validate. * @return true if the specified transfers are valid; otherwise, false. **/ - public static boolean isTransfersCollectionValid(final List transfers) { + public static boolean isTransfersCollectionValid(final List transfers) throws ArgumentException { + + // Input validation of transfers object + if (transfers == null || transfers.isEmpty()) { + throw new ArgumentException(INVALID_TRANSFERS_INPUT_ERROR); + } for (final Transfer transfer : transfers) { if (!isValidTransfer(transfer)) { @@ -127,6 +150,7 @@ public class InputValidator { return true; } + /** * Determines whether the specified transfer is valid. * @@ -135,21 +159,25 @@ public class InputValidator { **/ public static boolean isValidTransfer(final Transfer transfer) { + if (transfer == null) { + return false; + } + if (!isAddress(transfer.getAddress())) { return false; } - // Check if message is correct trytes of any length - if (!isTrytes(transfer.getMessage(), 0)) { + // Check if message is correct trytes encoded of any length + if (transfer.getMessage() == null || !isTrytes(transfer.getMessage(), transfer.getMessage().length())) { return false; } - if (null == transfer.getTag() || transfer.getTag().isEmpty()) { - return true; - } else { - // Check if tag is correct trytes of {0,27} trytes - return isTrytes(transfer.getTag(), 27); + // Check if tag is correct trytes encoded and not longer than 27 trytes + if (transfer.getTag() == null || !isTrytes(transfer.getTag(), transfer.getTag().length()) || transfer.getTag().length() > Constants.TAG_LENGTH) { + return false; } + + return true; } /** @@ -161,4 +189,57 @@ public class InputValidator { public static boolean isValidSeed(String seed) { return isTrytes(seed, seed.length()); } + + /** + * Checks if input is correct hashes. + * + * @param hashes The hashes list to validate. + * @return true if the specified hashes are valid; otherwise, false. + **/ + public static boolean isHashes(List hashes) { + for (String hash : hashes) { + if (!isTrytes(hash, 81)) { + return false; + } + } + return true; + } + + /** + * Checks if input is correct hash. + * + * @param hash The hash to validate. + * @return true if the specified hash are valid; otherwise, false. + **/ + public static boolean isHash(String hash) { + if (!isTrytes(hash, 81)) { + return false; + } + return true; + } + + /** + * Checks if attached trytes if last 241 trytes are non-zero + * + * @param trytes The trytes. + * @return true if the specified trytes are valid; otherwise, false. + **/ + public static boolean isArrayOfAttachedTrytes(String[] trytes) { + + for (String tryteValue : trytes) { + + // Check if correct 2673 trytes + if (!isTrytes(tryteValue, 2673)) { + return false; + } + + String lastTrytes = tryteValue.substring(2673 - (3 * 81)); + + if (lastTrytes.matches("[9]+")) { + return false; + } + } + + return true; + } } diff --git a/jota/src/main/java/jota/utils/IotaAPIUtils.java b/jota/src/main/java/jota/utils/IotaAPIUtils.java index 4d17712..52883a5 100644 --- a/jota/src/main/java/jota/utils/IotaAPIUtils.java +++ b/jota/src/main/java/jota/utils/IotaAPIUtils.java @@ -1,7 +1,6 @@ package jota.utils; -import jota.error.InvalidAddressException; -import jota.error.InvalidSecurityLevelException; +import jota.error.ArgumentException; import jota.model.Bundle; import jota.model.Input; import jota.model.Transaction; @@ -12,6 +11,8 @@ import java.util.Arrays; import java.util.Collections; import java.util.List; +import static jota.utils.Constants.INVALID_SECURITY_LEVEL_INPUT_ERROR; + /** * Client Side computation service. * @@ -28,10 +29,14 @@ public class IotaAPIUtils { * @param checksum The adds 9-tryte address checksum * @param curl The curl instance. * @return An String with address. - * @throws InvalidAddressException is thrown when the specified address is not an valid address. - * @throws InvalidSecurityLevelException is thrown when the specified security level is not valid. + * @throws ArgumentException is thrown when the specified input is not valid. */ - public static String newAddress(String seed, int security, int index, boolean checksum, ICurl curl) throws InvalidAddressException, InvalidSecurityLevelException { + public static String newAddress(String seed, int security, int index, boolean checksum, ICurl curl) throws ArgumentException { + + if (security < 1) { + throw new ArgumentException(INVALID_SECURITY_LEVEL_INPUT_ERROR); + } + Signing signing = new Signing(curl); final int[] key = signing.key(Converter.trits(seed), index, security); final int[] digests = signing.digests(key); @@ -48,7 +53,7 @@ public class IotaAPIUtils { public static List signInputsAndReturn(final String seed, final List inputs, final Bundle bundle, - final List signatureFragments, ICurl curl) throws InvalidSecurityLevelException { + final List signatureFragments, ICurl curl) throws ArgumentException { bundle.finalize(curl); bundle.addTrytes(signatureFragments); diff --git a/jota/src/main/java/jota/utils/Multisig.java b/jota/src/main/java/jota/utils/Multisig.java index dd554f4..96e0474 100644 --- a/jota/src/main/java/jota/utils/Multisig.java +++ b/jota/src/main/java/jota/utils/Multisig.java @@ -1,6 +1,6 @@ package jota.utils; -import jota.error.InvalidSecurityLevelException; +import jota.error.ArgumentException; import jota.model.Bundle; import jota.pow.ICurl; import jota.pow.SpongeFactory; @@ -36,9 +36,9 @@ public class Multisig { * @param security Secuirty level of private key / seed. * @param index Key index to start search from. If the index is provided, the generation of the address is not deterministic. * @return trytes - * @throws InvalidSecurityLevelException is thrown when the specified security level is not valid. + * @throws ArgumentException is thrown when the specified security level is not valid. **/ - public String getDigest(String seed, int security, int index) throws InvalidSecurityLevelException { + public String getDigest(String seed, int security, int index) throws ArgumentException { int[] key = signingInstance.key(Converter.trits(seed, 243), index, security); return Converter.trytes(signingInstance.digests(key)); } @@ -75,10 +75,10 @@ public class Multisig { * @param seed Tryte-encoded seed. It should be noted that this seed is not transferred * @param index Key index to start search from. If the index is provided, the generation of the address is not deterministic. * @return trytes. - * @throws InvalidSecurityLevelException is thrown when the specified security level is not valid. + * @throws ArgumentException is thrown when the specified security level is not valid. **/ - public String getKey(String seed, int index, int security) throws InvalidSecurityLevelException { + public String getKey(String seed, int index, int security) throws ArgumentException { return Converter.trytes(signingInstance.key(Converter.trits(seed, 81 * security), index, security)); } @@ -140,7 +140,7 @@ public class Multisig { // Get the security used for the private key // 1 security level = 2187 trytes - int security = (keyTrytes.length() / 2187); + int security = (keyTrytes.length() / Constants.MESSAGE_LENGTH); // convert private key trytes into trits int[] key = Converter.trits(keyTrytes); diff --git a/jota/src/main/java/jota/utils/Signing.java b/jota/src/main/java/jota/utils/Signing.java index fc260eb..e08f0c5 100644 --- a/jota/src/main/java/jota/utils/Signing.java +++ b/jota/src/main/java/jota/utils/Signing.java @@ -1,6 +1,6 @@ package jota.utils; -import jota.error.InvalidSecurityLevelException; +import jota.error.ArgumentException; import jota.model.Bundle; import jota.model.Transaction; import jota.pow.ICurl; @@ -11,6 +11,7 @@ import java.util.Arrays; import java.util.List; import static jota.pow.JCurl.HASH_LENGTH; +import static jota.utils.Constants.INVALID_SECURITY_LEVEL_INPUT_ERROR; public class Signing { @@ -22,7 +23,7 @@ public class Signing { * public Signing() { * this(null); * } - *

+ * * /** * * @param curl @@ -36,18 +37,18 @@ public class Signing { * @param index * @param security * @return - * @throws InvalidSecurityLevelException is thrown when the specified security level is not valid. + * @throws ArgumentException is thrown when the specified security level is not valid. */ - public int[] key(final int[] inSeed, final int index, int security) throws InvalidSecurityLevelException { + public int[] key(final int[] inSeed, final int index, int security) throws ArgumentException { if (security < 1) { - throw new InvalidSecurityLevelException(); + throw new ArgumentException(INVALID_SECURITY_LEVEL_INPUT_ERROR); } int[] seed = inSeed.clone(); // Derive subseed. for (int i = 0; i < index; i++) { - for (int j = 0; j < HASH_LENGTH; j++) { + for (int j = 0; j < seed.length; j++) { if (++seed[j] > 1) { seed[j] = -1; } else { @@ -59,17 +60,20 @@ public class Signing { curl.reset(); curl.absorb(seed, 0, seed.length); // seed[0..HASH_LENGTH] contains subseed - curl.squeeze(seed, 0, HASH_LENGTH); + curl.squeeze(seed, 0, seed.length); curl.reset(); // absorb subseed - curl.absorb(seed, 0, HASH_LENGTH); + curl.absorb(seed, 0, seed.length); final int[] key = new int[security * HASH_LENGTH * 27]; + final int[] buffer = new int[seed.length]; int offset = 0; while (security-- > 0) { for (int i = 0; i < 27; i++) { - curl.squeeze(key, offset, HASH_LENGTH); + curl.squeeze(buffer, 0, seed.length); + System.arraycopy(buffer, 0, key, offset, HASH_LENGTH); + offset += HASH_LENGTH; } } diff --git a/jota/src/main/java/jota/utils/StopWatch.java b/jota/src/main/java/jota/utils/StopWatch.java index c68b383..3ad93a8 100644 --- a/jota/src/main/java/jota/utils/StopWatch.java +++ b/jota/src/main/java/jota/utils/StopWatch.java @@ -10,7 +10,7 @@ public class StopWatch { private long currentTime = 0; /** - * + * Initializes a new instance of the StopWatch class. */ public StopWatch() { this.startTime = System.currentTimeMillis(); @@ -26,7 +26,7 @@ public class StopWatch { } /** - * @return + * */ public StopWatch stop() { this.running = false; @@ -52,7 +52,7 @@ public class StopWatch { /** * Elapsed time in milliseconds. * - * @return + * @return The elapsed time in milliseconds. */ public long getElapsedTimeMili() { long elapsed = 0; @@ -65,7 +65,7 @@ public class StopWatch { /** * Elapsed time in seconds. * - * @return + * @return The elapsed time in seconds. */ public long getElapsedTimeSecs() { long elapsed = 0; @@ -78,7 +78,7 @@ public class StopWatch { /** * Elapsed time in minutes. * - * @return + * @return The elapsed time in minutes. */ public long getElapsedTimeMin() { long elapsed = 0; @@ -91,7 +91,7 @@ public class StopWatch { /** * Elapsed time in hours. * - * @return + * @return The elapsed time in hours. */ public long getElapsedTimeHour() { long elapsed = 0; diff --git a/jota/src/main/java/jota/utils/TrytesConverter.java b/jota/src/main/java/jota/utils/TrytesConverter.java index e144545..8b90b75 100644 --- a/jota/src/main/java/jota/utils/TrytesConverter.java +++ b/jota/src/main/java/jota/utils/TrytesConverter.java @@ -10,20 +10,20 @@ public class TrytesConverter { /** * Conversion of ascii encoded bytes to trytes. * Input is a string (can be stringified JSON object), return value is Trytes - *

+ * * How the conversion works: * 2 Trytes === 1 Byte * There are a total of 27 different tryte values: 9ABCDEFGHIJKLMNOPQRSTUVWXYZ - *

+ * * 1. We get the decimal value of an individual ASCII character * 2. From the decimal value, we then derive the two tryte values by basically calculating the tryte equivalent (e.g. 100 === 19 + 3 * 27) * a. The first tryte value is the decimal value modulo 27 (27 trytes) * b. The second value is the remainder (decimal value - first value), divided by 27 * 3. The two values returned from Step 2. are then input as indices into the available values list ('9ABCDEFGHIJKLMNOPQRSTUVWXYZ') to get the correct tryte value - *

- *

+ * + * * EXAMPLE - *

+ * * Lets say we want to convert the ASCII character "Z". * 1. 'Z' has a decimal value of 90. * 2. 90 can be represented as 9 + 3 * 27. To make it simpler: diff --git a/jota/src/test/java/jota/ChecksumTest.java b/jota/src/test/java/jota/ChecksumTest.java index d247ff3..4c5d00b 100644 --- a/jota/src/test/java/jota/ChecksumTest.java +++ b/jota/src/test/java/jota/ChecksumTest.java @@ -1,6 +1,6 @@ package jota; -import jota.error.InvalidAddressException; +import jota.error.ArgumentException; import jota.utils.Checksum; import org.junit.Test; @@ -11,23 +11,21 @@ import static org.junit.Assert.assertEquals; */ public class ChecksumTest { - private static final String TEST_ADDRESS_WITHOUT_CHECKSUM = "EUHMAFIYBYZOXAVQQYRQ9RCNMTYX9KNEZFWXYMQIYPSRZRVDOLXDPUEARYPTWSZCAXJLXRYUUQKSHIJYZ"; - private static final String TEST_ADDRESS_WITHOUT_CHECKSUM2 = "P9UDUZMN9DEXCRQEKLJYSBSBZFCHOBPJSDKMLCCVJDOVOFDWMNBZRIRRZJGINOUMPJBMYYZEGRTIDUABD"; - private static final String TEST_ADDRESS_WITH_CHECKSUM = "EUHMAFIYBYZOXAVQQYRQ9RCNMTYX9KNEZFWXYMQIYPSRZRVDOLXDPUEARYPTWSZCAXJLXRYUUQKSHIJYZICCXCXUHX"; - private static final String TEST_ADDRESS_WITH_CHECKSUM2 = "P9UDUZMN9DEXCRQEKLJYSBSBZFCHOBPJSDKMLCCVJDOVOFDWMNBZRIRRZJGINOUMPJBMYYZEGRTIDUABDODCNSCYJD"; + private static final String TEST_ADDRESS_WITHOUT_CHECKSUM = "LXQHWNY9CQOHPNMKFJFIJHGEPAENAOVFRDIBF99PPHDTWJDCGHLYETXT9NPUVSNKT9XDTDYNJKJCPQMZC"; + private static final String TEST_ADDRESS_WITH_CHECKSUM = "LXQHWNY9CQOHPNMKFJFIJHGEPAENAOVFRDIBF99PPHDTWJDCGHLYETXT9NPUVSNKT9XDTDYNJKJCPQMZCCOZVXMTXC"; @Test - public void shouldAddChecksum() throws InvalidAddressException { - assertEquals(Checksum.addChecksum(TEST_ADDRESS_WITHOUT_CHECKSUM2), TEST_ADDRESS_WITH_CHECKSUM2); + public void shouldAddChecksum() throws ArgumentException { + assertEquals(Checksum.addChecksum(TEST_ADDRESS_WITHOUT_CHECKSUM), TEST_ADDRESS_WITH_CHECKSUM); } @Test - public void shouldRemoveChecksum() throws InvalidAddressException { - assertEquals(Checksum.removeChecksum(TEST_ADDRESS_WITH_CHECKSUM2), TEST_ADDRESS_WITHOUT_CHECKSUM2); + public void shouldRemoveChecksum() throws ArgumentException { + assertEquals(Checksum.removeChecksum(TEST_ADDRESS_WITH_CHECKSUM), TEST_ADDRESS_WITHOUT_CHECKSUM); } @Test - public void shouldIsValidChecksum() throws InvalidAddressException { - assertEquals(Checksum.isValidChecksum(TEST_ADDRESS_WITH_CHECKSUM2), true); + public void shouldIsValidChecksum() throws ArgumentException { + assertEquals(Checksum.isValidChecksum(TEST_ADDRESS_WITH_CHECKSUM), true); } } diff --git a/jota/src/test/java/jota/InputValidatorTest.java b/jota/src/test/java/jota/InputValidatorTest.java index 997f079..087a29e 100644 --- a/jota/src/test/java/jota/InputValidatorTest.java +++ b/jota/src/test/java/jota/InputValidatorTest.java @@ -1,6 +1,6 @@ package jota; -import jota.error.InvalidAddressException; +import jota.error.ArgumentException; import jota.model.Transfer; import jota.utils.InputValidator; import org.junit.Test; @@ -28,7 +28,7 @@ public class InputValidatorTest { } @Test - public void shouldCheckAddress() throws InvalidAddressException { + public void shouldCheckAddress() throws ArgumentException { assertEquals(InputValidator.checkAddress(TEST_ADDRESS_WITHOUT_CHECKSUM), true); } @@ -48,12 +48,11 @@ public class InputValidatorTest { } @Test - public void shouldIsTransfersCollectionCorrect() { + public void shouldIsTransfersCollectionCorrect() throws ArgumentException { List transfers = new ArrayList<>(); - transfers.add(new jota.model.Transfer(TEST_ADDRESS_WITH_CHECKSUM, 0, TEST_MESSAGE, TEST_TAG)); - transfers.add(new jota.model.Transfer(TEST_ADDRESS_WITH_CHECKSUM, 0, TEST_MESSAGE, TEST_TAG)); - transfers.add(new jota.model.Transfer(TEST_ADDRESS_WITH_CHECKSUM, 0, TEST_MESSAGE, null)); - transfers.add(new jota.model.Transfer(TEST_ADDRESS_WITH_CHECKSUM, 0, TEST_MESSAGE, "")); + transfers.add(new Transfer(TEST_ADDRESS_WITH_CHECKSUM, 0, TEST_MESSAGE, TEST_TAG)); + transfers.add(new Transfer(TEST_ADDRESS_WITH_CHECKSUM, 0, "", "")); + transfers.add(new Transfer(TEST_ADDRESS_WITH_CHECKSUM, 0)); assertEquals(InputValidator.isTransfersCollectionValid(transfers), true); } } \ No newline at end of file diff --git a/jota/src/test/java/jota/IotaAPITest.java b/jota/src/test/java/jota/IotaAPITest.java index b5a3b92..32cee0c 100644 --- a/jota/src/test/java/jota/IotaAPITest.java +++ b/jota/src/test/java/jota/IotaAPITest.java @@ -2,8 +2,9 @@ package jota; import com.google.gson.Gson; import jota.dto.response.*; -import jota.error.*; +import jota.error.ArgumentException; import jota.model.Bundle; +import jota.model.Input; import jota.model.Transaction; import jota.model.Transfer; import org.hamcrest.core.Is; @@ -27,16 +28,16 @@ import static org.junit.Assert.assertThat; */ public class IotaAPITest { - private static final String TEST_SEED1 = "IHDEENZYITYVYSPKAURUZAQKGVJEREFDJMYTANNXXGPZ9GJWTEOJJ9IPMXOGZNQLSNMFDSQOTZAEETUEA"; - private static final String TEST_SEED2 = "IHDEENZYITYVYSPKAURUZAQKGVJEREFDJMYTANNXXGPZ9GJWTEOJJ9IPMXOGZNQLSNMFDSQOTZAEETUEA"; + private static final String TEST_ADDRESS_WITH_CHECKSUM_SECURITY_LEVEL_1 = "MALAZGDVZIAQQRTNYJDSZMY9VE9LAHQKTVCUOAGZUCX9IBUMODFFTMGUIUAXGLWZQ9CYRSLYBM9QBIBYAEIAOPKXEA"; + private static final String TEST_ADDRESS_WITH_CHECKSUM_SECURITY_LEVEL_2 = "LXQHWNY9CQOHPNMKFJFIJHGEPAENAOVFRDIBF99PPHDTWJDCGHLYETXT9NPUVSNKT9XDTDYNJKJCPQMZCCOZVXMTXC"; + private static final String TEST_ADDRESS_WITH_CHECKSUM_SECURITY_LEVEL_3 = "ASCZZOBQDMNHLELQKWJBMRETMHBTF9V9TNKYDIFW9PDXPUHPVVGHMSWPVMNJHSJF99QFCMNTPCPGS9DT9XAFKJVO9X"; private static final String TEST_ADDRESS_WITHOUT_CHECKSUM_SECURITY_LEVEL_1 = "MALAZGDVZIAQQRTNYJDSZMY9VE9LAHQKTVCUOAGZUCX9IBUMODFFTMGUIUAXGLWZQ9CYRSLYBM9QBIBYA"; private static final String TEST_ADDRESS_WITHOUT_CHECKSUM_SECURITY_LEVEL_2 = "LXQHWNY9CQOHPNMKFJFIJHGEPAENAOVFRDIBF99PPHDTWJDCGHLYETXT9NPUVSNKT9XDTDYNJKJCPQMZC"; - private static final String TEST_ADDRESS_WITHOUT_CHECKSUM_SECURITY_LEVEL_2_2 = "RXTLHYQWBSJUZQXUS9LMLBE9RLAQFNDWBMZUGYJRJRHYRQQKVXBXJKEZOJDCVKFXM9GXYNMKTESEEILAYFCTLW9DQD"; private static final String TEST_ADDRESS_WITHOUT_CHECKSUM_SECURITY_LEVEL_3 = "ASCZZOBQDMNHLELQKWJBMRETMHBTF9V9TNKYDIFW9PDXPUHPVVGHMSWPVMNJHSJF99QFCMNTPCPGS9DT9"; - private static final String TEST_HASH = "EVCNKLXUTEKHSQKYKBSBACP9SCPTCBLLYLB9IDBMNQ9HAYANSUBZOCAAIPSGIMDAYLICTGWJAFFAA9999"; + private static final String TEST_HASH = "BKBALUPMEECOGEYQU9OHXTFTHV9OKEVUGHAUNNQCNETAQWIRJIKDGWSWXY9RSIMZJBPIPEIQEFEIA9999"; private static final String TEST_INVALID_TRYTES = "BYSWEAUTWXHXZ9YBZISEK9LUHWGMHXCGEVNZHRLUWQFCUSDXZHOFHWHL9MQPVJXXZLIXPXPXF9KYEREFSKCPKYIIKPZVLHUTDFQKKVVBBN9ATTLPCNPJDWDEVIYYLGPZGCWXOBDXMLJC9VO9QXTTBLAXTTBFUAROYEGQIVB9MJWJKXJMCUPTWAUGFZBTZCSJVRBGMYXTVBDDS9MYUJCPZ9YDWWQNIPUAIJXXSNLKUBSCOIJPCLEFPOXFJREXQCUVUMKSDOVQGGHRNILCO9GNCLWFM9APMNMWYASHXQAYBEXF9QRIHIBHYEJOYHRQJAOKAQ9AJJFQ9WEIWIJOTZATIBOXQLBMIJU9PCGBLVDDVFP9CFFSXTDUXMEGOOFXWRTLFGV9XXMYWEMGQEEEDBTIJ9OJOXFAPFQXCDAXOUDMLVYRMRLUDBETOLRJQAEDDLNVIRQJUBZBO9CCFDHIX9MSQCWYAXJVWHCUPTRSXJDESISQPRKZAFKFRULCGVRSBLVFOPEYLEE99JD9SEBALQINPDAZHFAB9RNBH9AZWIJOTLBZVIEJIAYGMC9AZGNFWGRSWAXTYSXVROVNKCOQQIWGPNQZKHUNODGYADPYLZZZUQRTJRTODOUKAOITNOMWNGHJBBA99QUMBHRENGBHTH9KHUAOXBVIVDVYYZMSEYSJWIOGGXZVRGN999EEGQMCOYVJQRIRROMPCQBLDYIGQO9AMORPYFSSUGACOJXGAQSPDY9YWRRPESNXXBDQ9OZOXVIOMLGTSWAMKMTDRSPGJKGBXQIVNRJRFRYEZ9VJDLHIKPSKMYC9YEGHFDS9SGVDHRIXBEMLFIINOHVPXIFAZCJKBHVMQZEVWCOSNWQRDYWVAIBLSCBGESJUIBWZECPUCAYAWMTQKRMCHONIPKJYYTEGZCJYCT9ABRWTJLRQXKMWY9GWZMHYZNWPXULNZAPVQLPMYQZCYNEPOCGOHBJUZLZDPIXVHLDMQYJUUBEDXXPXFLNRGIPWBRNQQZJSGSJTTYHIGGFAWJVXWL9THTPWOOHTNQWCNYOYZXALHAZXVMIZE9WMQUDCHDJMIBWKTYH9AC9AFOT9DPCADCV9ZWUTE9QNOMSZPTZDJLJZCJGHXUNBJFUBJWQUEZDMHXGBPTNSPZBR9TGSKVOHMOQSWPGFLSWNESFKSAZY9HHERAXALZCABFYPOVLAHMIHVDBGKUMDXC9WHHTIRYHZVWNXSVQUWCR9M9RAGMFEZZKZ9XEOQGOSLFQCHHOKLDSA9QCMDGCGMRYJZLBVIFOLBIJPROKMHOYTBTJIWUZWJMCTKCJKKTR9LCVYPVJI9AHGI9JOWMIWZAGMLDFJA9WU9QAMEFGABIBEZNNAL9OXSBFLOEHKDGHWFQSHMPLYFCNXAAZYJLMQDEYRGL9QKCEUEJ9LLVUOINVSZZQHCIKPAGMT9CAYIIMTTBCPKWTYHOJIIY9GYNPAJNUJ9BKYYXSV9JSPEXYMCFAIKTGNRSQGUNIYZCRT9FOWENSZQPD9ALUPYYAVICHVYELYFPUYDTWUSWNIYFXPX9MICCCOOZIWRNJIDALWGWRATGLJXNAYTNIZWQ9YTVDBOFZRKO9CFWRPAQQRXTPACOWCPRLYRYSJARRKSQPR9TCFXDVIXLP9XVL99ERRDSOHBFJDJQQGGGCZNDQ9NYCTQJWVZIAELCRBJJFDMCNZU9FIZRPGNURTXOCDSQGXTQHKHUECGWFUUYS9J9NYQ9U9P9UUP9YMZHWWWCIASCFLCMSKTELZWUGCDE9YOKVOVKTAYPHDF9ZCCQAYPJIJNGSHUIHHCOSSOOBUDOKE9CJZGYSSGNCQJVBEFTZFJ9SQUHOASKRRGBSHWKBCBWBTJHOGQ9WOMQFHWJVEG9NYX9KWBTCAIXNXHEBDIOFO9ALYMFGRICLCKKLG9FOBOX9PDWNQRGHBKHGKKRLWTBEQMCWQRLHAVYYZDIIPKVQTHYTWQMTOACXZOQCDTJTBAAUWXSGJF9PNQIJ9AJRUMUVCPWYVYVARKR9RKGOUHHNKNVGGPDDLGKPQNOYHNKAVVKCXWXOQPZNSLATUJT9AUWRMPPSWHSTTYDFAQDXOCYTZHOYYGAIM9CELMZ9AZPWB9MJXGHOKDNNSZVUDAGXTJJSSZCPZVPZBYNNTUQABSXQWZCHDQSLGK9UOHCFKBIBNETK999999999999999999999999999999999999999999999999999999999999999999999999999999999NOXDXXKUDWLOFJLIPQIBRBMGDYCPGDNLQOLQS99EQYKBIU9VHCJVIPFUYCQDNY9APGEVYLCENJIOBLWNB999999999XKBRHUD99C99999999NKZKEKWLDKMJCI9N9XQOLWEPAYWSH9999999999999999999999999KDDTGZLIPBNZKMLTOLOXQVNGLASESDQVPTXALEKRMIOHQLUHD9ELQDBQETS9QFGTYOYWLNTSKKMVJAUXSIROUICDOXKSYZTDPEDKOQENTJOWJONDEWROCEJIEWFWLUAACVSJFTMCHHXJBJRKAAPUDXXVXFWP9X9999IROUICDOXKSYZTDPEDKOQENTJOWJONDEWROCEJIEWFWLUAACVSJFTMCHHXJBJRKAAPUDXXVXFWP9X9999"; - private static final String TEST_TRYTES = "9RYSLXACOTYQZAQIAMCULCVKMBIPMKINPFJCZFIZOOZMTCTKIXQHQTUTVGZMVHGKLRZGWOT9UGYQFNCGNRJWDETRKWUFIAFA9M9ZPZKVJWKOJENHFWMFBDVOLEVCGQTKCTOPNGRYQURVQPFJAZFUKCXAOORIYCVDKDINDXRFAFRSFVRXCTPETGIJULBYGXUHQMBGHAKGJLMNZUQE9EVOGTFVJ9EVSDNUYPGQLZBAJNWG9XXXDHETVT9XBBCQZEWJXFLVHEXHEQARCOSRKQQVEQKK9APNBRBJHHUWRGAWUIMLY9AFCULX9ITRJBYU9BNQPZBJKJDNHDAKIGDMNUOFCWAEDSBDRUTORPZQCHCSQRVIERZNGPYBPEOQXGFAKANGXPE9MA9ZZCLKDQANOKIAV9QDDUZILVMEIHXDSHDISEJMLQGVEUJWMCKCMIQTRRGJKJFSVMZWYNQJCFCPOEGOTJULGPFTM9GQGEONOXSYXYPQZHVFYHKYREHQMYWHYUTZE999HRWIQTOENSRFPB9NXDVFSUA9NLAKOELYAAHTFDDAYBHPKNAXXTJIPYOKXTEMYUIOKXORYUFEIIAZCFGCCINBPTXFNTGPKFOQNGEODMSCVOZKRJYLECZB9VDZJCLPMTY9UPLTLH9GVDBALFNBLQXI9ADJJXCSPQJXHNNZUOJCMFJKZZ9ZTJRQMNLDSTZYTFNXQPZKMQJLZBHF9URFHNX9MQVMTIHEMROFCCPDLUOTRCAURYL9IJ9IGTRFVIJXSFLYBJOQOASBNVRFQGVIGKA9UJUDHWUSBFFKDHDVRGLOZQYADXGS9IOGCPCVCFPNUDFTUKXCOEEUMNDZCZGUXIECIYCKL9XCPEIQMYV9VCP9JJMSREJFQB9IVXUAXWCURUADEPBIVIGERXIMFZAGQPRC9KSYYLHBZVZGQJVTZVBGMRBWYJCYRHMJWPIKJYAYTALAAZROZYCMQKWBSFUGHFSOGGTCQDHWJU9VJGCAHJLHSORFKVJKV9RSZHLJZTDJJGOXTRLKNJORWYPW9UKRZROJONZQWJNUEPBZZJYBJJNCAQOEYTHFWVUBACCFTREABOZKQEKSMDAFECVGMGELNZUFZJHWHNXLBOSHLNBPGSQDVLZLBUXWINABWYBDMZNIYNVPYLRKUULTMNNKZUFNQOQKROJSXWYTBRDSJQKTOUXLMXVCVIXEYPZWBSMEXMBGUIVACRTGKDEIYZKP9KQCQXPWRXNLGQOATRHCXJFQINXFYQIDTPUJVXKUYVRYHWDHWSNLWUFPNNJZVNMRFWPZBJCRRSHMHUG9NKKH9SOXTUJUAXBF9MHYWHJ9ZTJRUQFKRLHMNVPWX9XFXLMVJAGASMWMIFYUZFAUCEIOOYMEYWOIZTNEWFVZKOQFECWEPSMOYFSJJKEJQMPSXGE9WTYRQJVMHUQZFD9MJUFFCNSGAZCTXYPIJFNSXAUCYPGZMNWMQWSWCKAQYKXJTWINSGPPZG9HLDLEAWUWEVCTVRCBDFOXKUROXH9HXXAXVPEJFRSLOGRVGYZASTEBAQNXJJROCYRTDPYFUIQJVDHAKEG9YACV9HCPJUEUKOYFNWDXCCJBIFQKYOXGRDHVTHEQUMHO999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999DNVEZXD99A99999999A99999999BULMKQXROXEBHPBYGKQINYJTHPTL9OGKUFBFAVRHPZSNXBUDMNRJFYIIGWOFVCXSVFQRZMPGCZMZUNKCDDRWDLKTKCZXZFMIZ9CZBWNOJGSXHBKEXCFQPBNFAE9QAVRX9SWGEZQRSYAYNW9TPWVWCJXAUPQHYZ9999NBDPASDXMXDCHLMZJIBHAZREUBOTZZAYGKCWTBSBKKETULAPABDTY9AMPBSXO9KJOLCWJMJSZFKU999999999999999999999999999999999999999999999999999999999999CWJQRPBIJGTWQTCMDUVOCBUAMH"; + private static final String TEST_TRYTES = "CCWCXCGDEAXCGDEAPCEAHDTCGDHDRAADTCGDGDPCVCTC9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999WITPXKWONPNUPBESJTXQTZTFXFSTDUWVGYHW9VRDULWGBKDVAAJLOSAEPUSCMSOIYLKMIZLPEKAOYAXMWFLDKQJI99999999999999999999UUC9999999999999999FUCK9YOUIVBUGXD99999999999B99999999IDPWGXASJFLLGCDGPQVXYGSNUESCZQCEKVREGLZX9FCYQVUWESEKWSMHZTGMJLGBOLKU9GILFITSJLZBWEHH9RSRNBPSKKUZBBJDSYHYWYHLJUOAFCKMXGTRFTZHKKWSVKGRHHJECSILLLZXKYJAYAQYEOINSZ9999OCYREQNINOB9XMLJOXMDFJDTXYO9PANNXQSW9HPFAAHEPTSPHTNEBOFFNRPKSUQNTKSACROOJPXF99999UUC9999999999999999FUCK9YOUPNMHCEJIE999999999L99999999IGMVBPROUATGVGQTHYIYFVQETRW"; private static final String TEST_MESSAGE = "JUSTANOTHERJOTATEST"; private static final String TEST_TAG = "JOTASPAM9999999999999999999"; private static final int MIN_WEIGHT_MAGNITUDE = 14; @@ -64,125 +65,148 @@ public class IotaAPITest { , "XCCPS9GMTSUB9DXPVKLTBDHOFX9PJMBYZQYQEXMRQDPGQPLWRGZGXODYJKGVFOHHYUJRCSXAIDGYSAWRB" , "KVEBCGMEOPDPRCQBPIEMZTTXYBURGZVNH9PLHKPMM9D9FUKWIGLKZROGNSYIFHULLWQWXCNAW9HKKVIDC"}; - private IotaAPI iotaClient; + private IotaAPI iotaAPI; @Before public void createApiClientInstance() { - iotaClient = new IotaAPI.Builder().build(); + iotaAPI = new IotaAPI.Builder().build(); } @Test public void shouldCreateIotaApiProxyInstanceWithDefaultValues() { - IotaAPI proxy = new IotaAPI.Builder().build(); - assertThat(proxy, IsNull.notNullValue()); - assertThat(proxy.getHost(), Is.is("localhost")); - assertThat(proxy.getPort(), Is.is("14265")); - assertThat(proxy.getProtocol(), Is.is("http")); + iotaAPI = new IotaAPI.Builder().build(); + assertThat(iotaAPI, IsNull.notNullValue()); + assertThat(iotaAPI.getHost(), Is.is("node.iotawallet.info")); + assertThat(iotaAPI.getPort(), Is.is("14265")); + assertThat(iotaAPI.getProtocol(), Is.is("http")); } @Test public void shouldRetainValuesFromBuilder() { - IotaAPI proxy = new IotaAPI.Builder().host("somewhere_over_the_rainbow").build(); - assertThat(proxy.getHost(), Is.is("somewhere_over_the_rainbow")); + iotaAPI = new IotaAPI.Builder().host("somewhere_over_the_rainbow").build(); + assertThat(iotaAPI.getHost(), Is.is("somewhere_over_the_rainbow")); - proxy = new IotaAPI.Builder().port("15515").build(); - assertThat(proxy.getPort(), Is.is("15515")); + iotaAPI = new IotaAPI.Builder().port("15515").build(); + assertThat(iotaAPI.getPort(), Is.is("15515")); - proxy = new IotaAPI.Builder().protocol("https").build(); - assertThat(proxy.getProtocol(), Is.is("https")); + iotaAPI = new IotaAPI.Builder().protocol("https").build(); + assertThat(iotaAPI.getProtocol(), Is.is("https")); } @Test public void shouldGetValuesFromProperties() { Properties properties = new Properties(); + properties.put("iota.node.host", "somewhere_over_the_rainbow"); - IotaAPI proxy = new IotaAPI.Builder().config(properties).build(); - assertThat(proxy.getHost(), Is.is("somewhere_over_the_rainbow")); + iotaAPI = new IotaAPI.Builder().config(properties).build(); + assertThat(iotaAPI.getHost(), Is.is("somewhere_over_the_rainbow")); properties = new Properties(); properties.put("iota.node.port", "15515"); - proxy = new IotaAPI.Builder().config(properties).build(); - assertThat(proxy.getPort(), Is.is("15515")); + iotaAPI = new IotaAPI.Builder().config(properties).build(); + assertThat(iotaAPI.getPort(), Is.is("15515")); properties = new Properties(); properties.put("iota.node.protocol", "https"); - proxy = new IotaAPI.Builder().config(properties).build(); - assertThat(proxy.getProtocol(), Is.is("https")); + iotaAPI = new IotaAPI.Builder().config(properties).build(); + assertThat(iotaAPI.getProtocol(), Is.is("https")); } @Test - public void shouldGetInputs() throws InvalidSecurityLevelException, InvalidAddressException { - GetBalancesAndFormatResponse res = iotaClient.getInputs(TEST_SEED1, 2, 0, 0, 0); + public void shouldGetInputs() throws ArgumentException { + GetBalancesAndFormatResponse res = iotaAPI.getInputs(TEST_SEED1, 2, 0, 0, 0); System.out.println(res); assertThat(res, IsNull.notNullValue()); assertThat(res.getTotalBalance(), IsNull.notNullValue()); - assertThat(res.getInput(), IsNull.notNullValue()); - + assertThat(res.getInputs(), IsNull.notNullValue()); } @Test - public void shouldCreateANewAddressWithoutChecksum() throws InvalidSecurityLevelException, InvalidAddressException { - final GetNewAddressResponse res1 = iotaClient.getNewAddress(TEST_SEED1, 1, 0, false, 5, false); + public void shouldCreateANewAddressWithChecksum() throws ArgumentException { + final GetNewAddressResponse res1 = iotaAPI.getNewAddress(TEST_SEED1, 1, 0, true, 5, false); + assertThat(res1.getAddresses().get(0), Is.is(TEST_ADDRESS_WITH_CHECKSUM_SECURITY_LEVEL_1)); + + final GetNewAddressResponse res2 = iotaAPI.getNewAddress(TEST_SEED1, 2, 0, true, 5, false); + assertThat(res2.getAddresses().get(0), Is.is(TEST_ADDRESS_WITH_CHECKSUM_SECURITY_LEVEL_2)); + + final GetNewAddressResponse res3 = iotaAPI.getNewAddress(TEST_SEED1, 3, 0, true, 5, false); + assertThat(res3.getAddresses().get(0), Is.is(TEST_ADDRESS_WITH_CHECKSUM_SECURITY_LEVEL_3)); + } + + @Test + public void shouldCreateANewAddressWithoutChecksum() throws ArgumentException { + final GetNewAddressResponse res1 = iotaAPI.getNewAddress(TEST_SEED1, 1, 0, false, 5, false); assertThat(res1.getAddresses().get(0), Is.is(TEST_ADDRESS_WITHOUT_CHECKSUM_SECURITY_LEVEL_1)); - final GetNewAddressResponse res2 = iotaClient.getNewAddress(TEST_SEED1, 2, 0, false, 5, false); + final GetNewAddressResponse res2 = iotaAPI.getNewAddress(TEST_SEED1, 2, 0, false, 5, false); assertThat(res2.getAddresses().get(0), Is.is(TEST_ADDRESS_WITHOUT_CHECKSUM_SECURITY_LEVEL_2)); - final GetNewAddressResponse res3 = iotaClient.getNewAddress(TEST_SEED1, 3, 0, false, 5, false); + final GetNewAddressResponse res3 = iotaAPI.getNewAddress(TEST_SEED1, 3, 0, false, 5, false); assertThat(res3.getAddresses().get(0), Is.is(TEST_ADDRESS_WITHOUT_CHECKSUM_SECURITY_LEVEL_3)); } @Test - public void shouldCreate100Addresses() throws InvalidSecurityLevelException, InvalidAddressException { - GetNewAddressResponse res = iotaClient.getNewAddress(TEST_SEED1, 2, 0, false, 100, false); + public void shouldCreate100Addresses() throws ArgumentException { + GetNewAddressResponse res = iotaAPI.getNewAddress(TEST_SEED1, 2, 0, false, 100, false); assertEquals(res.getAddresses().size(), 100); } @Test - public void shouldPrepareTransfer() throws InvalidSecurityLevelException, NotEnoughBalanceException, InvalidAddressException, InvalidTransferException { + public void shouldPrepareTransfer() throws ArgumentException { + List inputlist = new ArrayList<>(); List transfers = new ArrayList<>(); - transfers.add(new jota.model.Transfer(TEST_ADDRESS_WITHOUT_CHECKSUM_SECURITY_LEVEL_2, 0, TEST_MESSAGE, TEST_TAG)); - transfers.add(new jota.model.Transfer(TEST_ADDRESS_WITHOUT_CHECKSUM_SECURITY_LEVEL_2, 0, TEST_MESSAGE, TEST_TAG)); - List trytes = iotaClient.prepareTransfers(TEST_SEED1, 2, transfers, null, null); - Assert.assertNotNull(trytes); - assertThat(trytes.isEmpty(), Is.is(false)); + + GetBalancesAndFormatResponse rsp = iotaAPI.getInputs(TEST_SEED1, 2, 0, 0, 100); + + for (Input input : rsp.getInputs()) { + inputlist.add(input); + } + transfers.add(new Transfer(TEST_ADDRESS_WITH_CHECKSUM_SECURITY_LEVEL_2, 0, TEST_MESSAGE, TEST_TAG)); + transfers.add(new Transfer(TEST_ADDRESS_WITH_CHECKSUM_SECURITY_LEVEL_2, 0)); + List trytes1 = iotaAPI.prepareTransfers(TEST_SEED1, 2, transfers, null, null, false); + List trytes2 = iotaAPI.prepareTransfers(TEST_SEED1, 2, transfers, null, inputlist, true); + + Assert.assertNotNull(trytes1); + assertThat(trytes1.isEmpty(), Is.is(false)); + Assert.assertNotNull(trytes2); + assertThat(trytes2.isEmpty(), Is.is(false)); } @Test - public void shouldGetLastInclusionState() throws NoNodeInfoException { - GetInclusionStateResponse res = iotaClient.getLatestInclusion(new String[]{TEST_HASH}); + public void shouldGetLastInclusionState() throws ArgumentException { + GetInclusionStateResponse res = iotaAPI.getLatestInclusion(new String[]{TEST_HASH}); assertThat(res.getStates(), IsNull.notNullValue()); } @Test - public void shouldFindTransactionObjects() { - List ftr = iotaClient.findTransactionObjects(TEST_ADDRESSES); + public void shouldFindTransactionObjects() throws ArgumentException { + List ftr = iotaAPI.findTransactionObjectsByAddresses(TEST_ADDRESSES); System.out.println(ftr); assertThat(ftr, IsNull.notNullValue()); } @Test - public void shouldGetAccountData() throws NoInclusionStatesException, InvalidTrytesException, NoNodeInfoException, ArgumentException, InvalidBundleException, InvalidSecurityLevelException, InvalidAddressException, InvalidSignatureException { - GetAccountDataResponse gad = iotaClient.getAccountData(TEST_SEED1, 2, 0, true, 0, true, 0, 0, true, 0); + public void shouldGetAccountData() throws ArgumentException { + GetAccountDataResponse gad = iotaAPI.getAccountData(TEST_SEED1, 2, 0, true, 0, true, 0, 0, true, 0); assertThat(gad, IsNull.notNullValue()); } - @Test(expected = IllegalAccessError.class) - public void shouldNotGetBundle() throws InvalidBundleException, ArgumentException, InvalidSignatureException { - GetBundleResponse gbr = iotaClient.getBundle("SADASD"); + @Test(expected = ArgumentException.class) + public void shouldNotGetBundle() throws ArgumentException { + GetBundleResponse gbr = iotaAPI.getBundle("SADASD"); assertThat(gbr, IsNull.notNullValue()); } @Test - public void shouldGetBundle() throws InvalidBundleException, ArgumentException, InvalidSignatureException { - GetBundleResponse gbr = iotaClient.getBundle(TEST_HASH); + public void shouldGetBundle() throws ArgumentException { + GetBundleResponse gbr = iotaAPI.getBundle(TEST_HASH); System.out.println(gbr); assertThat(gbr, IsNull.notNullValue()); } @Test - public void shouldGetTransfers() throws InvalidBundleException, ArgumentException, InvalidSignatureException, NoInclusionStatesException, NoNodeInfoException, InvalidSecurityLevelException, InvalidAddressException { - GetTransferResponse gtr = iotaClient.getTransfers(TEST_SEED1, 2, 0, 0, false); + public void shouldGetTransfers() throws ArgumentException { + GetTransferResponse gtr = iotaAPI.getTransfers(TEST_SEED1, 2, 0, 0, false); assertThat(gtr.getTransfers(), IsNull.notNullValue()); System.out.println(gtr); @@ -195,44 +219,69 @@ public class IotaAPITest { @Ignore @Test - public void shouldReplayBundle() throws InvalidTrytesException, InvalidBundleException, InvalidSignatureException, ArgumentException { - ReplayBundleResponse rbr = iotaClient.replayBundle(TEST_HASH, DEPTH, MIN_WEIGHT_MAGNITUDE); + public void shouldReplayBundle() throws ArgumentException { + ReplayBundleResponse rbr = iotaAPI.replayBundle(TEST_HASH, DEPTH, MIN_WEIGHT_MAGNITUDE); assertThat(rbr, IsNull.notNullValue()); } @Ignore - @Test(expected = InvalidTrytesException.class) - public void shouldNotSendTrytes() throws InvalidTrytesException { - iotaClient.sendTrytes(new String[]{TEST_INVALID_TRYTES}, DEPTH, MIN_WEIGHT_MAGNITUDE); + @Test(expected = ArgumentException.class) + public void shouldNotSendTrytes() throws ArgumentException { + iotaAPI.sendTrytes(new String[]{TEST_INVALID_TRYTES}, DEPTH, MIN_WEIGHT_MAGNITUDE); } @Test() - public void shouldGetTrytes() throws InvalidTrytesException { - System.out.println(iotaClient.getTrytes(TEST_HASH)); + public void shouldGetTrytes() throws ArgumentException { + System.out.println(iotaAPI.getTrytes(TEST_HASH)); } + @Test() + public void shouldBroadcastAndStore() throws ArgumentException { + System.out.println(iotaAPI.broadcastAndStore(TEST_TRYTES)); + } @Ignore @Test - public void shouldSendTrytes() throws InvalidTrytesException { - iotaClient.sendTrytes(new String[]{TEST_TRYTES}, DEPTH, MIN_WEIGHT_MAGNITUDE); + public void shouldSendTrytes() throws ArgumentException { + iotaAPI.sendTrytes(new String[]{TEST_TRYTES}, DEPTH, MIN_WEIGHT_MAGNITUDE); } @Ignore @Test(expected = IllegalStateException.class) - public void shouldNotSendTransfer() throws ArgumentException, InvalidSignatureException, InvalidBundleException, NotEnoughBalanceException, InvalidSecurityLevelException, InvalidTrytesException, InvalidAddressException, InvalidTransferException { + public void shouldNotSendTransfer() throws ArgumentException { List transfers = new ArrayList<>(); - transfers.add(new jota.model.Transfer(TEST_ADDRESS_WITHOUT_CHECKSUM_SECURITY_LEVEL_2, 0, TEST_MESSAGE, TEST_TAG)); - SendTransferResponse str = iotaClient.sendTransfer(TEST_SEED2, 2, DEPTH, MIN_WEIGHT_MAGNITUDE, transfers, null, null); + transfers.add(new Transfer(TEST_ADDRESS_WITHOUT_CHECKSUM_SECURITY_LEVEL_2, 2, TEST_MESSAGE, TEST_TAG)); + SendTransferResponse str = iotaAPI.sendTransfer(TEST_SEED1, 2, DEPTH, MIN_WEIGHT_MAGNITUDE, transfers, null, null, false); + assertThat(str.getTransactions(), IsNull.notNullValue()); assertThat(str.getSuccessfully(), IsNull.notNullValue()); } @Ignore @Test - public void shouldSendTransfer() throws ArgumentException, InvalidSignatureException, InvalidBundleException, NotEnoughBalanceException, InvalidSecurityLevelException, InvalidTrytesException, InvalidAddressException, InvalidTransferException { + public void shouldSendTransferWithoutInputs() throws ArgumentException { List transfers = new ArrayList<>(); - transfers.add(new jota.model.Transfer(TEST_ADDRESS_WITHOUT_CHECKSUM_SECURITY_LEVEL_2_2, 0, TEST_MESSAGE, TEST_TAG)); - SendTransferResponse str = iotaClient.sendTransfer(TEST_SEED1, 2, DEPTH, MIN_WEIGHT_MAGNITUDE, transfers, null, null); + transfers.add(new Transfer(TEST_ADDRESS_WITHOUT_CHECKSUM_SECURITY_LEVEL_2, 1, TEST_MESSAGE, TEST_TAG)); + SendTransferResponse str = iotaAPI.sendTransfer(TEST_SEED1, 2, DEPTH, MIN_WEIGHT_MAGNITUDE, transfers, null, null, false); + assertThat(str.getTransactions(), IsNull.notNullValue()); + assertThat(str.getSuccessfully(), IsNull.notNullValue()); + } + + @Ignore + @Test + public void shouldSendTransferWithInputs() throws ArgumentException { + List inputlist = new ArrayList<>(); + List transfers = new ArrayList<>(); + + GetBalancesAndFormatResponse rsp = iotaAPI.getInputs(TEST_SEED1, 2, 0, 0, 1); + + for (Input input : rsp.getInputs()) { + inputlist.add(input); + } + + transfers.add(new Transfer(TEST_ADDRESS_WITHOUT_CHECKSUM_SECURITY_LEVEL_2, 1, TEST_MESSAGE, TEST_TAG)); + + SendTransferResponse str = iotaAPI.sendTransfer(TEST_SEED1, 2, DEPTH, MIN_WEIGHT_MAGNITUDE, transfers, inputlist, null, true); + assertThat(str.getTransactions(), IsNull.notNullValue()); assertThat(str.getSuccessfully(), IsNull.notNullValue()); } } \ No newline at end of file diff --git a/jota/src/test/java/jota/IotaCoreApiTest.java b/jota/src/test/java/jota/IotaCoreApiTest.java index a75f7fe..3962e26 100644 --- a/jota/src/test/java/jota/IotaCoreApiTest.java +++ b/jota/src/test/java/jota/IotaCoreApiTest.java @@ -2,10 +2,13 @@ package jota; import com.google.gson.Gson; import jota.dto.response.*; +import jota.error.ArgumentException; import org.hamcrest.core.IsNull; import org.junit.Before; import org.junit.Test; +import java.util.Collections; + import static org.junit.Assert.assertThat; /** @@ -70,7 +73,7 @@ public class IotaCoreApiTest { } @Test - public void shouldFindTransactionsByAddresses() { + public void shouldFindTransactionsByAddresses() throws ArgumentException { FindTransactionResponse trans = proxy.findTransactionsByAddresses(TEST_ADDRESS_WITH_CHECKSUM); assertThat(trans.getHashes(), IsNull.notNullValue()); } @@ -94,21 +97,20 @@ public class IotaCoreApiTest { } @Test - public void shouldGetTrytes() { + public void shouldGetTrytes() throws ArgumentException { GetTrytesResponse res = proxy.getTrytes(TEST_HASH); assertThat(res.getTrytes(), IsNull.notNullValue()); } - @Test(expected = IllegalAccessError.class) - public void shouldNotGetInclusionStates() { - GetInclusionStateResponse res = proxy.getInclusionStates(new String[]{"DBPECSH9YLSSTQDGERUHJBBJTKVUDBMTJLG9WPHBINGHIFOSJMDJLARTVOXXWEFQJLLBINOHCZGYFSMUEXWPPMTOFW"}, new String[]{"EJDQOQHMLJGBMFWB9WJSPRCYIGNPO9WRHDCEQXIMPVPIJ9JV9RJGVHNX9EPGXFOOKBABCVMMAAX999999"}); - assertThat(res.getStates(), IsNull.notNullValue()); + @Test(expected = ArgumentException.class) + public void shouldNotGetInclusionStates() throws ArgumentException { + proxy.getInclusionStates(new String[]{TEST_HASH}, new String[]{"ZIJGAJ9AADLRPWNCYNNHUHRRAC9QOUDATEDQUMTNOTABUVRPTSTFQDGZKFYUUIE9ZEBIVCCXXXLKX9999"}); } @Test - public void shouldGetInclusionStates() { - GetInclusionStateResponse res = proxy.getInclusionStates(new String[]{TEST_ADDRESS_WITH_CHECKSUM}, new String[]{proxy.getNodeInfo().getLatestSolidSubtangleMilestone()}); + public void shouldGetInclusionStates() throws ArgumentException { + GetInclusionStateResponse res = proxy.getInclusionStates(new String[]{TEST_HASH}, new String[]{proxy.getNodeInfo().getLatestSolidSubtangleMilestone()}); assertThat(res.getStates(), IsNull.notNullValue()); } @@ -127,8 +129,8 @@ public class IotaCoreApiTest { } @Test - public void shouldGetBalances() { - GetBalancesResponse res = proxy.getBalances(100, new String[]{TEST_ADDRESS_WITH_CHECKSUM}); + public void shouldGetBalances() throws ArgumentException { + GetBalancesResponse res = proxy.getBalances(100, Collections.singletonList(TEST_ADDRESS_WITH_CHECKSUM)); assertThat(res.getBalances(), IsNull.notNullValue()); assertThat(res.getMilestone(), IsNull.notNullValue()); assertThat(res.getMilestoneIndex(), IsNull.notNullValue()); diff --git a/jota/src/test/java/jota/IotaLocalPoWTest.java b/jota/src/test/java/jota/IotaLocalPoWTest.java index 66792b0..93ffdf4 100644 --- a/jota/src/test/java/jota/IotaLocalPoWTest.java +++ b/jota/src/test/java/jota/IotaLocalPoWTest.java @@ -2,7 +2,7 @@ package jota; import cfb.pearldiver.PearlDiverLocalPoW; import jota.dto.response.SendTransferResponse; -import jota.error.*; +import jota.error.ArgumentException; import jota.model.Transfer; import org.hamcrest.core.IsNull; import org.junit.Before; @@ -20,7 +20,7 @@ import static org.junit.Assert.assertThat; public class IotaLocalPoWTest { private static final String TEST_SEED1 = "IHDEENZYITYVYSPKAURUZAQKGVJEREFDJMYTANNXXGPZ9GJWTEOJJ9IPMXOGZNQLSNMFDSQOTZAEETUEA"; - private static final String TEST_ADDRESS_WITHOUT_CHECKSUM_SECURITY_LEVEL_2_2 = "RXTLHYQWBSJUZQXUS9LMLBE9RLAQFNDWBMZUGYJRJRHYRQQKVXBXJKEZOJDCVKFXM9GXYNMKTESEEILAYFCTLW9DQD"; + private static final String TEST_ADDRESS_WITHOUT_CHECKSUM_SECURITY_LEVEL_2 = "LXQHWNY9CQOHPNMKFJFIJHGEPAENAOVFRDIBF99PPHDTWJDCGHLYETXT9NPUVSNKT9XDTDYNJKJCPQMZC"; private static final String TEST_MESSAGE = "JUSTANOTHERJOTATEST"; private static final String TEST_TAG = "JOTASPAM9999999999999999999"; private static final int MIN_WEIGHT_MAGNITUDE = 14; @@ -35,10 +35,10 @@ public class IotaLocalPoWTest { @Ignore @Test - public void shouldSendTransfer() throws ArgumentException, InvalidSignatureException, InvalidBundleException, NotEnoughBalanceException, InvalidSecurityLevelException, InvalidTrytesException, InvalidAddressException, InvalidTransferException { + public void shouldSendTransfer() throws ArgumentException { List transfers = new ArrayList<>(); - transfers.add(new jota.model.Transfer(TEST_ADDRESS_WITHOUT_CHECKSUM_SECURITY_LEVEL_2_2, 0, TEST_MESSAGE, TEST_TAG)); - SendTransferResponse str = iotaClient.sendTransfer(TEST_SEED1, 2, DEPTH, MIN_WEIGHT_MAGNITUDE, transfers, null, null); + transfers.add(new Transfer(TEST_ADDRESS_WITHOUT_CHECKSUM_SECURITY_LEVEL_2, 0, TEST_MESSAGE, TEST_TAG)); + SendTransferResponse str = iotaClient.sendTransfer(TEST_SEED1, 2, DEPTH, MIN_WEIGHT_MAGNITUDE, transfers, null, null, false); assertThat(str.getSuccessfully(), IsNull.notNullValue()); } } diff --git a/jota/src/test/java/jota/IotaMultisigTest.java b/jota/src/test/java/jota/IotaMultisigTest.java index 060a679..82435ff 100644 --- a/jota/src/test/java/jota/IotaMultisigTest.java +++ b/jota/src/test/java/jota/IotaMultisigTest.java @@ -1,11 +1,6 @@ package jota; -import com.google.gson.Gson; -import com.google.gson.GsonBuilder; -import jota.error.InvalidAddressException; -import jota.error.InvalidBundleException; -import jota.error.InvalidSecurityLevelException; -import jota.error.InvalidTransferException; +import jota.error.ArgumentException; import jota.model.Bundle; import jota.model.Transaction; import jota.model.Transfer; @@ -30,8 +25,8 @@ public class IotaMultisigTest { private static final String TEST_SEED2 = "FDSAG"; private static final String REMAINDER_ADDRESS = "NZRALDYNVGJWUVLKDWFKJVNYLWQGCWYCURJIIZRLJIKSAIVZSGEYKTZRDBGJLOA9AWYJQB9IPWRAKUC9FBDRZJZXZG"; private static final String RECEIVE_ADDRESS = "ZGHXPZYDKXPEOSQTAQOIXEEI9K9YKFKCWKYYTYAUWXK9QZAVMJXWAIZABOXHHNNBJIEBEUQRTBWGLYMTX"; + private static final String TEST_TAG = "JOTASPAM9999999999999999999"; - private static Gson gson = new GsonBuilder().create(); private IotaAPI iotaClient; @Before @@ -40,8 +35,7 @@ public class IotaMultisigTest { } @Test - public void basicMultiSigTest() throws InvalidBundleException, InvalidTransferException, InvalidAddressException, InvalidSecurityLevelException { - + public void basicMultiSigTest() throws ArgumentException { Multisig ms = new Multisig(); // First co-signer uses security level 3 and index 0 for the private key @@ -66,9 +60,8 @@ public class IotaMultisigTest { System.out.println("Is a valid multisig address " + isValidMultisigAddress); assertTrue("Address is not a valid multisigAddress", isValidMultisigAddress); - Transfer transfer = new Transfer(RECEIVE_ADDRESS, 999, "", ""); List transfers = new ArrayList<>(); - transfers.add(transfer); + transfers.add(new Transfer(RECEIVE_ADDRESS, 999, "", TEST_TAG)); List trxs = iotaClient.initiateTransfer(6, multiSigAddress, REMAINDER_ADDRESS, transfers, true); diff --git a/jota/src/test/java/jota/SendMessageTest.java b/jota/src/test/java/jota/SendMessageTest.java index 1d03702..642d148 100644 --- a/jota/src/test/java/jota/SendMessageTest.java +++ b/jota/src/test/java/jota/SendMessageTest.java @@ -1,7 +1,10 @@ package jota; -import jota.error.*; +import jota.dto.response.SendTransferResponse; +import jota.error.ArgumentException; import jota.model.Transfer; +import org.apache.commons.lang3.StringUtils; +import org.hamcrest.core.IsNull; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; @@ -9,14 +12,15 @@ import org.junit.Test; import java.util.ArrayList; import java.util.List; -import static org.junit.Assert.assertEquals; +import static junit.framework.TestCase.assertEquals; +import static org.junit.Assert.assertThat; public class SendMessageTest { private static final String TEST_SEED1 = "IHDEENZYITYVYSPKAURUZAQKGVJEREFDJMYTANNXXGPZ9GJWTEOJJ9IPMXOGZNQLSNMFDSQOTZAEETUEA"; - private static final String TEST_ADDRESS_WITHOUT_CHECKSUM_SECURITY_LEVEL_2_2 = "RXTLHYQWBSJUZQXUS9LMLBE9RLAQFNDWBMZUGYJRJRHYRQQKVXBXJKEZOJDCVKFXM9GXYNMKTESEEILAYFCTLW9DQD"; - private static final String TEST_MESSAGE = "JUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATESTJUSTANOTHERJOTATEST"; - private static final String TEST_TAG = "TESTER999999999999999999999"; + private static final String TEST_ADDRESS_WITH_CHECKSUM_SECURITY_LEVEL_2 = "LXQHWNY9CQOHPNMKFJFIJHGEPAENAOVFRDIBF99PPHDTWJDCGHLYETXT9NPUVSNKT9XDTDYNJKJCPQMZCCOZVXMTXC"; + private static final String TEST_MESSAGE = "JUSTANOTHERJOTATEST"; + private static final String TEST_TAG = "JOTASPAM9999999999999999999"; private static final int MIN_WEIGHT_MAGNITUDE = 14; private static final int DEPTH = 9; @@ -29,14 +33,15 @@ public class SendMessageTest { @Ignore @Test - public void shouldSendMessage() throws ArgumentException, InvalidSignatureException, InvalidBundleException, NotEnoughBalanceException, InvalidSecurityLevelException, InvalidTrytesException, InvalidAddressException, InvalidTransferException { + public void shouldSendMessage() throws ArgumentException { List transfers = new ArrayList<>(); - transfers.add(new jota.model.Transfer(TEST_ADDRESS_WITHOUT_CHECKSUM_SECURITY_LEVEL_2_2, 0, TEST_MESSAGE, TEST_TAG)); - // for each 2187 trytes in a message a new transfer is necessary - List trytes = iotaClient.prepareTransfers(TEST_SEED1, 2, transfers, null, null); - assertEquals(trytes.size(), 2); + // for each 2187 trytes in a message one transfer is necessary + transfers.add(new Transfer(TEST_ADDRESS_WITH_CHECKSUM_SECURITY_LEVEL_2, 0, StringUtils.rightPad(TEST_MESSAGE, 2188, '9'), TEST_TAG)); - iotaClient.sendTrytes(trytes.toArray(new String[trytes.size()]), DEPTH, MIN_WEIGHT_MAGNITUDE); + SendTransferResponse str = iotaClient.sendTransfer(TEST_SEED1, 2, DEPTH, MIN_WEIGHT_MAGNITUDE, transfers, null, null, false); + assertEquals(str.getTransactions().size(), 2); + assertThat(str.getTransactions(), IsNull.notNullValue()); + assertThat(str.getSuccessfully(), IsNull.notNullValue()); } } diff --git a/jota/src/test/java/jota/SigningTest.java b/jota/src/test/java/jota/SigningTest.java index b9d6792..21eca60 100644 --- a/jota/src/test/java/jota/SigningTest.java +++ b/jota/src/test/java/jota/SigningTest.java @@ -1,7 +1,6 @@ package jota; -import jota.error.InvalidAddressException; -import jota.error.InvalidSecurityLevelException; +import jota.error.ArgumentException; import jota.model.Bundle; import jota.pow.ICurl; import jota.pow.SpongeFactory; @@ -24,14 +23,31 @@ public class SigningTest { private static final String SIGNATURE1 = "PYWFM9MYTPNZ9HTLZBBB9CGQWKPALDUNAQYCAA9VMQ9UMBLLAXSPPHQSNAAKJA9MZBXBHBQBFFKMBSDHDTCVCDWLUYCEQ9YZJAJAXXXZHDWTSLWGIWRE9LJFVWAFUMOAGHDBHJQ9APNBLSX9GPTJNTO9SBJT9UKYCZXYAWVGXEBJANNWEWZSPRYHASHGIFUWOEHUFMP9MWQBYZOZESCPLVJUCWGLEJIDPMEVNPBITBNFSQ9GBWCDTQZOPLPXOWWNQAEIXQRWMHAQDH9C9KKHGNKAX9INMUVVGIK9TPGRHOMDFAB9VICYDMSHHDDBRSTEFSZXMXFJUQRRAFBSCNHSMKRNNTTCMBURKBGC9EDWKLPBSQAKYCUKKSZWRVURZGUA9QVSXXPICIYFHLPJSWEFBZPUTWWNIKSAJM9OMRFFQVFJZZHLQBSEYXM9CN9HCGHSJBTYDGWOQPXOPZZE9EPQAQFT9GDWZCSOPMZHYYZXDDZ9DJDLOOOTIFQANFANNAYVIRUNDXSB9XRNXJYRDBLTEDWSUOVISMCHGKD9KDRSFDWRSVZQQKGAMDXFAWBSLMTTUMH9RAUIVI9HJMTODACSOP9MLHOJMSIWQ9TTNGPXRNWRHLMEMAH9GZHJRNJHQNBBLWKFXIZBMGMATZIZBFDPAFDCLDIFFAIK9JUSFYYC9ANDGXCZFLZYGURTUI9SWYYRGDJAHXDDNHSJZBCENZUSQXSFZMTXSFLRK9RIYAUMHPBOBNOXCHDIMBGIBVOOHIDQ9ORHHDECDTREIEILWDUFMUWYMGIXBIKRZMKGXTYZTX9GKFP9AUXMTUUQXRHHKPYULGJFJLEEYCNKLOWULRIAFM9OYKEDFRXFVTSJMSEMOURCLNOIETIHEUCMPLWKDXDO9TAHVH99MKTBAAKCMYKLJUQIVLLSVTFUM9KDSIHYXYHPRLDADSLSSOIGLLXMPKTHS9YXUNMUTBTBPDWXA9GVTBGLTCLEZEUNNIRBBURDWOFFYXELPFSZRQARVRPHGETKJTRUZIFDDWBOHHGUZTODZFMOVMAGCYCTGBWSGAVZADIPIASCKTRKIUUMHNGUYZKDVOPKKHXD9EXVUVJ9YFNYMLIJLEEGPIZLFS9FIEMG9MIEO9FPW9JZEVDQOECMTESICSMVWXZNXXJILJLVQHEBHQWPOBHKEGRLFCPLB9ZECJOZDAB9DMU9UALBIQDABVDYRRTPMZOCQX9WNGXVNKQZWPA9ACVONQMRHQDPPIQTP9VKP9PAORNOFTZZWGC9RYBWSNLULZGYLMYIWWPDMOHPZTQWRPRCN9RAUOKDSCWBRI9NPUPLBILOZDOOPHSWQGJEGUYWAWJDEBLEOBSYYU9XSRPBHRUQXIDOWJZQQVJTMP9VLWLOGBK9FZFHYLJCNENDATNPSF99DFPVPTNNKIUMHRGEBJXNUVENAHYLFPPHYFTIKCB9DBVCCSJTDMOMISBAAEJVBVLHOADKNFG9NQGIGRDICQCWZVHGGXLTUNQKBUTLDWXIM9REWBLIXFBPTOXBLWBQQUSRLRDHTXQWARPMBQILAJSYLLTDAGTFPCXBCDITDOIZNGKPZQWWHJDZIPYCPFEYFD9CVXYOJHJNUNMCMSIAUVSKCACNNPGDYJJVTZOREJOPIBYCMBULMTSDTJPZNVNYQBQPPABOSSNZJKQQZ9LULSHJUBLHIFMYWSNPGUERCLVFV9LOEBJEERYHI9OMSMSCDFDLNHEMLQXNRJDYSNKTOYCPTAUWAWIGCPJKMAMGLXNBJMO9BZGFIHWDVJWYCNZZV9KBWIFQSMAXBPGVXDW9SLTHOLMJORRXZJSTNOQDRGNBLGTFCCNBJECYZGWTDRJKJRBAJRCULMOUBQJFWCLWMEWGAAVNZWMDWBYDKZMUCZAKXQLRQPIQJPMORKJXKSDTGXWDHAKUOSMXCFXWSZYWXODWFACBMFSWQFVMBELPZMISVWRQQQPNHOTWOEQQAQJDLXFEEBXLJQEECWG9ARRRDLTVBHTPARJMLOZHYWDCSXPTZCNZWTCRUJNZWKFZXAARPHFCBTLWSLERGJJMKIG9NEBADRMZWYNWIRGTMOBRKURUE9GDLRIEODY9BXJOZUVNCXKXFPFDXKUTMXZRJDOQ9YTV9BJDKGZBYTWGVPQQMNVCNARLPSRQWN9TRMHWLNEJZFTCSRD"; private static final String SIGNATURE2 = "URKFKLNXFEKDOGSQVMAOPEDIWSMTCKJZ9KEVWYALY9JAO9KHUGNDTMGQLKQJUIPWDIVMPEDSVPLFMDCIXDDT9WBBRTFQENL9AXLSBYHINXCDYBFGRNKJDYHAQVJKWCVOYXHTNBEZUNLVMJLUMZYJFAOW9PVVMJZNZZFJQEQFELVFZVFVWPJ9WQZJLPSGBYECHXSFVFQJGUCPFXC9GATTILVCAANNHOYMLOYX9QSUPCERYCOXPACZEEGLREBRZWXGUTTVTHB9GBRCIFEOBPIRXXPQKRSODEHDSZXLGIKXUQWNTQKIOPVDVSIK9WJUAEFOJBU9MBPBSVYSCLBMINTT9ZCTREZSMSVOPXSZOMCGFEZKMOCNLJ9QUTAPKBHRIAIYLCHUQHOINKSCMXWZVDGDXHNJQXJHPCCGBEWROVKEPAPBFFRCAVXZWIRKCRAWYHIHMDXFAGDJQNJJPYSQUHKFOOCEVQOGRQEIOQFKZWUQ9XVRNXKGMJOQEZHQZXQABWUQRBKXWHYUXEAEMDGXVY9WS9VJOCMGBQASSRNKAYJPTSPQEMYSJMTCLMDQJKDPBGQZZSFBDOKHBYY9UDRXNKTPWBCQTVKUGMEDUXL9TTKPATNIKVAGHACHPFSCRYNIRJBQC9OADPGWBFYYARSVNQCGMYQGCYLZH9KLMUIJPCLPQVS9BORXCJBXPDECJGKDNOUYWTKKFLXZARWKGUSMVMXKJTMRYZRERFCFGTZFZFCAOQSZGPQJUEZUJLJPU9QPMJUTZNLMSMPRGIFHUUZHMPMRBEBATEIIWPCOIMWOYOG9NYFBYOWFDKRXOTREBU99GNCPXKOWGI99LNVPRFFF9FCLFXI9HMUFU9NRLNJVTFNUSUJTAVOG9GKUYYEXIM9HTPIDTWIGLKRAQPKMQVZAPYMPSQIOJ9JZBWDMQHDSSRSHNCWSAJCSRORSEXLLQNZUKPXPGRLYMXOXWCCWWSBALFLXPHSGFLTOAFWPETBKJUMBLHMSKYLPJT9EJAZCPPNZWKPVCGKDJCRCLBBIAKVDSNWGONPLKFAYXZDI9FKPHDPKCB9UUPXLJVQTXOAZOQDRNSONXDVSLQGZYRIPGREYHRAUOSBFZDZPZHFNMWCZQGPXCZVLNCSASB9RQDFHOYMUVYLFKOEEWNREYCDMCTZIAFBFKLKRQWZCJHQZCZGWXIFTKRVMPHMVHAABHBDEV9WDEZBR9FLXLNBVNYKUOUFJQKNZVZVGZDDTFYNYFUVRLZKOLXXQYNV9MDVBLZSERXPGYKRIEZQZD9IBKFDT9AIYGWJJCXFWDUDURGJQLXVEJAVEOMZUVVTNCVBXEVQRDQIEHDUCSLCIJUTSCLFXEGMFYP9YLXELCZPMTBZWBIODZCFNJLVWTPQGLMQIHIABAYGJFFMOEDTCXGEDTNXMVXZYFGXRKVVRTIZ9ISXTDHAFPEKQZSM9XXQLOYBLTMD9MBERBIBEJDEXGMOLDZPZVVEPIRKJBDPAKFAWJPTCJSHZPDUKZEEHRFLMZCUGCOWFJBSTDGPHUIXSPPPHRQARMCFMTWKYPJNJQV9VSFZ9EWB9GVEAFUXHWRNUXQLCSBWROOITBATWUXUYGSMGAXKGEBP9ZJWXQWHBVPOSLDHTWXUOFQNO9EXSYPQF9LQLQAFNRU9MTIIRQLBBBYKUPANWRQKGESFARQIRUTGFMZVUKHZJYKTYOARTDOBIYBFRHJWEFHCYVHRHTLTWBRMUDVIVQVNELQMQRXYDNGVSICZINWIZCIWVFXLYOLYKWDNWCWFZUXHUWOPRDHMTSXOZX9CVHANU9ZXTJOGKEPYR9CHGOTIUQSWIALAOIKHQFXWY9ZWTSZADVXJNNZOLSCXVVFBRHLRBTGMSZOYNIXTAMABKGJTLGTZKRHOPPJMNYIQNVKRGXUQDWYEIEZYM9CSXO9YLSBJLDJUWOLUXDEKBGGEIDEXFLZMESDOITNYTNRLGOMHJH9HOLXJABUNLXCZYTXFPZMHRJPLXSVPDBJBBZX9TBIMZZFZOXUSFEJYHEXPFXGJCQTBBLPEEWAPHUETGXSXYYAF9PCCCOONRMQGAPJ9JO9BZQ9QSKTPFFYIFVHSLAZY9CWYSIMKDOSLRKWBHPGJGVEJEEMLCCWXKSOCMBMZZZJWYBBXE9FTAYJALGWITJRXAXWZEXMECTZEEIWZPHYX"; + private static final String ADDR_SEED = "LIESNFZLPFNWAPWXBLKEABZEEWUDCXKTRKZIRTPCKLKWOMJSEREWKMMMODUOFWM9ELEVXADTSQWMSNFVD"; + private static final String ADDR_I0_S1 = "HIPPOUPZFMHJUQBLBVWORCNJWAOSFLHDWF9IOFEYVHPTTAAF9NIBMRKBICAPHYCDKMEEOXOYHJBMONJ9D"; + private static final String ADDR_I0_S2 = "BPYZABTUMEIOARZTMCDNUDAPUOFCGKNGJWUGUXUKNNBVKQARCZIXFVBZAAMDAFRS9YOIXWOTEUNSXVOG9"; + private static final String ADDR_I0_S3 = "BYWHJJYSHSEGVZKKYTJTYILLEYBSIDLSPXDLDZSWQ9XTTRLOSCBCQ9TKXJYQAVASYCMUCWXZHJYRGDOBW"; + private static final String ADDR_LS_I0_S1 = "VKPCVHWKSCYQNHULMPYDZTNKOQHZNPEGJVPEHPTDIUYUBFKFICDRLLSIULHCVHOHZRHJOHNASOFRWFWZC"; + private static final String ADDR_LS_I0_S2 = "PTHVACKMXOKIERJOFSRPBWCNKVEXQ9CWUTIJGEUORSKWEDDJCBFQCCBQZLTYXQCXEDWLTMRQM9OQPUGNC"; + private static final String ADDR_LS_I0_S3 = "AGSAAETPMSBCDOSNXFXIOBAE9MVEJCSWVP9PAULQ9VABOTWLDMXID9MXCCWQIWRTJBASWPIJDFUC9ISWD"; + + @Test - public void testAddressGeneration() throws InvalidAddressException, InvalidSecurityLevelException { + public void testAddressGeneration() throws ArgumentException { assertEquals(FIRST_ADDR, IotaAPIUtils.newAddress(TEST_SEED, 2, 0, true, null)); assertEquals(SIXTH_ADDR, IotaAPIUtils.newAddress(TEST_SEED, 2, 5, true, null)); + + assertEquals(ADDR_I0_S1, IotaAPIUtils.newAddress(ADDR_SEED, 1, 0, false, null)); + assertEquals(ADDR_I0_S2, IotaAPIUtils.newAddress(ADDR_SEED, 2, 0, false, null)); + assertEquals(ADDR_I0_S3, IotaAPIUtils.newAddress(ADDR_SEED, 3, 0, false, null)); + + assertEquals(ADDR_LS_I0_S1, IotaAPIUtils.newAddress(ADDR_SEED + ADDR_SEED, 1, 0, false, null)); + assertEquals(ADDR_LS_I0_S2, IotaAPIUtils.newAddress(ADDR_SEED + ADDR_SEED, 2, 0, false, null)); + assertEquals(ADDR_LS_I0_S3, IotaAPIUtils.newAddress(ADDR_SEED + ADDR_SEED, 3, 0, false, null)); } @Test - public void testLongSeedKeyGeneration() throws InvalidSecurityLevelException { + public void testLongSeedKeyGeneration() throws ArgumentException { ICurl curl = SpongeFactory.create(SpongeFactory.Mode.KERL); Signing signing = new Signing(curl); String seed = "EV9QRJFJZVFNLYUFXWKXMCRRPNAZYQVEYB9VEPUHQNXJCWKZFVUCTQJFCUAMXAHMMIUQUJDG9UGGQBPIY"; @@ -47,7 +63,7 @@ public class SigningTest { } @Test - public void testSigning() throws InvalidAddressException, InvalidSecurityLevelException { + public void testSigning() throws ArgumentException { // we can sign any hash, so for convenience we will sign the first // address of our test seed // (but remove the checksum) with the key of our fifth address @@ -62,7 +78,7 @@ public class SigningTest { } @Test - public void testKeyLength() throws InvalidSecurityLevelException { + public void testKeyLength() throws ArgumentException { Signing signing = new Signing(null); int[] key = signing.key(Converter.trits(TEST_SEED), 5, 1); assertEquals(Signing.KEY_LENGTH, key.length); @@ -73,11 +89,11 @@ public class SigningTest { } @Test - public void testVerifying() throws InvalidAddressException { + public void testVerifying() throws ArgumentException { assertTrue(new Signing(null).validateSignatures(removeChecksum(SIXTH_ADDR), new String[]{SIGNATURE1, SIGNATURE2}, removeChecksum(FIRST_ADDR))); } - private String removeChecksum(String address) throws InvalidAddressException { + private String removeChecksum(String address) throws ArgumentException { assertTrue(Checksum.isValidChecksum(address)); return address.substring(0, Constants.ADDRESS_LENGTH_WITHOUT_CHECKSUM); } diff --git a/jota/src/test/java/jota/TrytesConverterTest.java b/jota/src/test/java/jota/TrytesConverterTest.java index 9c65c4f..1b12973 100644 --- a/jota/src/test/java/jota/TrytesConverterTest.java +++ b/jota/src/test/java/jota/TrytesConverterTest.java @@ -27,9 +27,7 @@ public class TrytesConverterTest { @Test public void shouldConvertBackAndForth() { String str = RandomStringUtils.randomAlphabetic(1000).toUpperCase(); - System.err.println(str); String back = TrytesConverter.toString(TrytesConverter.toTrytes(str)); - assertTrue(str.equals(back)); } } \ No newline at end of file