diff --git a/.travis.yml b/.travis.yml index 964491c..f9e9cd3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,13 +1,32 @@ language: java jdk: - oraclejdk8 -script: mvn package +before_install: +- openssl aes-256-cbc -K $encrypted_404912dc11ca_key -iv $encrypted_404912dc11ca_iv + -in codesigning.asc.enc -out codesigning.asc -d +before_script: gpg --fast-import codesigning.asc +script: mvn package -P build-extras deploy: - provider: releases - file_glob: true - file: "/home/travis/build/iotaledger/iota.lib.java/target/jota*.jar" - skip_cleanup: true - on: - tags: true - repo: iotaledger/iota.lib.java - all_branches: true + - provider: releases + api_key: + secure: YR8aDGTciBNQgI8GU5DSSm6dzKyZhgmixewIMkbjwrGkdLs/UnD2cfMh2ziNuivpmnIDj2rCMmf6gr1PhQno5nsPPrrFcJs0tIv2LAvAAJst/k32zMK3wv1x54eaTS3SK9VxUdAcnB0N3RvMKLiaqkwTcxa4PY9pWlHnZdc8h9oCqr7JAq8NH/94Ri4AiUc7hDgu6xnZNDqll6gJwdM8kUPQuUsAkkAl2dBVfqB7OeQFkmTvl6Hi5WCn9zbpBpKxE4t/SbgZvH5ccVBKOZveFG38/Mm1ur6VHQ8WvZFnEHps+aq8Sjz8irzcdGHC/hSGvMfsB2LRZHKd8KaRcSCypzuBjNt+ayEaaCd4AcNIsR/cEtC9aOzttNhS6eX4YpdaDjmvlqChjKvR+reKVXK7rb6Z08vHkJC1HOofovfjBP0RXT/O1CsUTpPS0lpNfrNZ0n0GfaHqtqxYrGDsXMFIHX5v39fqwAF2pmpJQaB3CeSLpEM7YbNcPlPRQ/w4XZ5SEN1ENS6a8oenOL+IZNMyspTywG3vQgdc82W5MhjFpUawrReeWd6y5xrHiWBLVPJGsgJQPIY0MkuAGiIGqiT8hSW8x8frYhX9IZ7/x4My6PYL8pCv+zn2V8LBr5KCtjVf3sGrxftlt1eLvQHkw290yRUgcfTAd2Dj8lk8H+jYgXA= + file_glob: true + file: + - "/home/travis/build/iotaledger/iota.lib.java/target/jota*.jar" + - "/home/travis/build/iotaledger/iota.lib.java/target/jota*.jar.asc" + - "/home/travis/build/iotaledger/iota.lib.java/target/jota*-sources.jar" + - "/home/travis/build/iotaledger/iota.lib.java/target/jota*-sources.jar.asc" + - "/home/travis/build/iotaledger/iota.lib.java/target/jota*-javadoc.jar" + - "/home/travis/build/iotaledger/iota.lib.java/target/jota*-javadoc.jar.asc" + skip_cleanup: true + on: + tags: true + repo: iotaledger/iota.lib.java + all_branches: true + - provider: script + script: chmod u+x .travis/push-jdoc-gh-pages.sh && .travis/push-jdoc-gh-pages.sh + skip_cleanup: true + on: + tags: true + repo: iotaledger/iota.lib.java + all_branches: true \ No newline at end of file diff --git a/.travis/push-jdoc-gh-pages.sh b/.travis/push-jdoc-gh-pages.sh new file mode 100644 index 0000000..9e9f560 --- /dev/null +++ b/.travis/push-jdoc-gh-pages.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +if [ "$TRAVIS_REPO_SLUG" == "iotaledger/iota.lib.java" ] && [ "$TRAVIS_PULL_REQUEST" == "false" ]; then + + echo -e "Publishing javadoc...\n" + + cp -R "/home/travis/build/iotaledger/iota.lib.java/target/apidocs/" $HOME/javadoc-latest + + cd $HOME + git config --global user.email "travis@travis-ci.org" + git config --global user.name "travis-ci" + git clone --quiet --branch=gh-pages https://${GH_TOKEN}@github.com/iotaledger/iota.lib.java.git gh-pages > /dev/null + + cd gh-pages + git rm -rf ./javadoc + cp -Rf $HOME/javadoc-latest ./javadoc + git add -f . + git commit -m "Latest javadoc on successful travis build $TRAVIS_BUILD_NUMBER auto-pushed to gh-pages" + git push -fq origin gh-pages > /dev/null + + echo -e "Published Javadoc to gh-pages.\n" + +fi \ No newline at end of file diff --git a/README.md b/README.md index 915be80..f198ec6 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,14 @@ +[![Build Status](https://travis-ci.org/iotaledger/iota.lib.java.svg?branch=dev)](https://travis-ci.org/iotaledger/iota.lib.java) + + ##Introduction The JOTA library is a simple Java wrapper around [[IOTA]](http://www.iotatoken.com/) Node's JSON-REST HTTP interface. It allows to connect easily using java directly to a local or a remote [[IOTA node]](https://iota.readme.io/docs/syncing-to-the-network). -* **Latest release:** 0.9.0 RC1 -* **Compatibility:** fully compatible with IOTA IRI v1.2.4 +* **Latest release:** 0.9.1 +* **Compatibility:** fully compatible with IOTA IRI v1.2.6 * **API coverage:** 14 of 14 commands fully implemented * **License:** Apache License 2.0 * **Readme updated:** 2016-01-19 21:05:02 (UTC) @@ -51,13 +54,13 @@ In order to communicate with *IOTA node*, JOTA needs to be aware of your node's iota.node.host=127.0.0.1 iota.node.port=14265 -Jota is still *not* in the central maven repository. It will be available when it will cover 100% iota's rest interface. +Jota is still *not* in the central maven repository. ##Warning - This is pre-release software! - There may be performance and stability issues. - You may loose all your money :) - - Please report any issues using the Issue Tracker" + - Please report any issues using the Issue Tracker That's it! @@ -67,7 +70,4 @@ There's an extensive list of test coverages on the src/test/java package of the ##Supporting the project -If JOTA has been useful to you and you feel like contributing, consider posting a bug report or a pull request. Alternatively, donations are very welcome too! - -* Bitcoin (Gianni Davassi): `3FGCHqhG1SUpgn2eS1Agq2KnxJemWnQFbB` -* Bitcoin (Adrian Ziser): `3FGCHqhG1SUpgn2eS1Agq2KnxJemWnQFbB` \ No newline at end of file +If JOTA has been useful to you and you feel like contributing, consider posting a bug report or a pull request. diff --git a/codesigning.asc.enc b/codesigning.asc.enc new file mode 100644 index 0000000..266c186 Binary files /dev/null and b/codesigning.asc.enc differ diff --git a/dependency-reduced-pom.xml b/dependency-reduced-pom.xml new file mode 100644 index 0000000..1ca7d78 --- /dev/null +++ b/dependency-reduced-pom.xml @@ -0,0 +1,128 @@ + + + 4.0.0 + org.iota + jota + JOTA + 0.9.0-RC1 + JOTA library is a simple Java wrapper around IOTA Node's JSON-REST HTTP interface. + + + Apache License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + repo + + + + + + maven-compiler-plugin + 3.3 + + ${java-version} + ${java-version} + ${java-version} + ${java-version} + + + + maven-shade-plugin + 2.4.3 + + + package + + shade + + + + + + maven-surefire-plugin + 2.12.4 + + true + + + + + + + build-extras + + + + maven-source-plugin + 3.0.1 + + + attach-sources + + jar + + + + + + maven-javadoc-plugin + 2.10.4 + + + attach-javadocs + + jar + + + private + true + -Xdoclint:none + + + + + private + true + -Xdoclint:none + + + + maven-gpg-plugin + 1.6 + + + sign-artifacts + package + + sign + + + + + + + + ${env.GPG_KEYNAME} + ${env.GPG_PASSPHRASE} + + + + + + junit + junit + 4.12 + test + + + hamcrest-core + org.hamcrest + + + + + + 1.7 + UTF-8 + + + diff --git a/pom.xml b/pom.xml index 31625ee..1a59524 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ 4.0.0 org.iota jota - 0.9.0-RC1 + 0.9.1 JOTA JOTA library is a simple Java wrapper around IOTA Node's JSON-REST HTTP interface. @@ -103,6 +103,7 @@ org.apache.maven.plugins maven-surefire-plugin + 2.12.4 true @@ -110,4 +111,68 @@ + + + + build-extras + + + build + full + + + + ${env.GPG_KEYNAME} + ${env.GPG_PASSPHRASE} + + + + + org.apache.maven.plugins + maven-source-plugin + + + attach-sources + + jar + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.10.4 + + private + true + -Xdoclint:none + + + + attach-javadocs + + jar + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.6 + + + sign-artifacts + package + + sign + + + + + + + + diff --git a/src/main/java/jota/IotaAPI.java b/src/main/java/jota/IotaAPI.java index 8bd00fd..c6504bc 100644 --- a/src/main/java/jota/IotaAPI.java +++ b/src/main/java/jota/IotaAPI.java @@ -29,7 +29,6 @@ public class IotaAPI extends IotaAPICore { private static final Logger log = LoggerFactory.getLogger(IotaAPI.class); private ICurl customCurl; - private StopWatch stopWatch; protected IotaAPI(Builder builder) { super(builder); @@ -38,16 +37,24 @@ public class IotaAPI extends IotaAPICore { /** * Generates a new address from a seed and returns the remainderAddress. - * This is either done deterministically, or by providing the index of the new remainderAddress + * This is either done deterministically, or by providing the index of the new remainderAddress. * - * @param seed Tryte-encoded seed. It should be noted that this seed is not transferred - * @param index Optional (default null). Key index to start search from. If the index is provided, the generation of the address is not deterministic. - * @param checksum Optional (default false). Adds 9-tryte address checksum - * @param total Optional (default 1)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 + * @param seed Tryte-encoded seed. It should be noted that this seed is not transferred. + * @param security Security level to be used for the private key / address. Can be 1, 2 or 3. + * @param index Key index to start search from. If the index is provided, the generation of the address is not deterministic. + * @param checksum Adds 9-tryte address checksum. + * @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. */ - public GetNewAddressResponse getNewAddress(final String seed, final int index, final boolean checksum, final int total, final boolean returnAll) { + 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 || security > 3) { + throw new InvalidSecurityLevelException(); + } + StopWatch stopWatch = new StopWatch(); List allAddresses = new ArrayList<>(); @@ -56,15 +63,15 @@ public class IotaAPI extends IotaAPICore { // and return the list of all addresses if (total != 0) { for (int i = index; i < index + total; i++) { - allAddresses.add(IotaAPIUtils.newAddress(seed, i, checksum, customCurl)); + allAddresses.add(IotaAPIUtils.newAddress(seed, security, i, checksum, customCurl.clone())); } return GetNewAddressResponse.create(allAddresses, stopWatch.getElapsedTimeMili()); } - // No total provided: Continue calling findTransactions to see if address was + // No total provided: Continue calling findTransactions to see if address was // already created if null, return list of addresses for (int i = index; ; i++) { - final String newAddress = IotaAPIUtils.newAddress(seed, i, checksum, customCurl); + final String newAddress = IotaAPIUtils.newAddress(seed, security, i, checksum, customCurl.clone()); final FindTransactionResponse response = findTransactionsByAddresses(newAddress); allAddresses.add(newAddress); @@ -83,22 +90,31 @@ public class IotaAPI extends IotaAPICore { } /** - * @param {string} seed - * @param {object} options - * @param {function} callback - * @method getTransfers - * @property {int} start Starting key index - * @property {int} end Ending key index - * @property {bool} inclusionStates returns confirmation status of all transactions - * @returns {object} success - **/ - public GetTransferResponse getTransfers(String seed, Integer start, Integer end, Boolean inclusionStates) throws ArgumentException, InvalidBundleException, InvalidSignatureException, NoNodeInfoException, NoInclusionStatesExcpection { + * @param seed Tryte-encoded seed. It should be noted that this seed is not transferred. + * @param security The security level of private key / seed. + * @param start Starting key index. + * @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. + */ + 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(); // validate & if needed pad seed if ((seed = InputValidator.validateSeed(seed)) == null) { throw new IllegalStateException("Invalid Seed"); } + if (security < 1 || security > 3) { + throw new InvalidSecurityLevelException(); + } + start = start != null ? 0 : start; if (start > end || end > (start + 500)) { @@ -106,18 +122,27 @@ public class IotaAPI extends IotaAPICore { } StopWatch sw = new StopWatch(); - System.out.println("GetTransfer started"); - GetNewAddressResponse gnr = getNewAddress(seed, start, false, end == null ? end - start : end, true); + GetNewAddressResponse gnr = getNewAddress(seed, security, start, false, end, true); if (gnr != null && gnr.getAddresses() != null) { - System.out.println("GetTransfers after getNewAddresses " + sw.getElapsedTimeMili() + " ms"); Bundle[] bundles = bundlesFromAddresses(gnr.getAddresses().toArray(new String[gnr.getAddresses().size()]), inclusionStates); - System.out.println("GetTransfers after bundlesFromAddresses " + sw.getElapsedTimeMili() + " ms"); return GetTransferResponse.create(bundles, stopWatch.getElapsedTimeMili()); } return GetTransferResponse.create(new Bundle[]{}, stopWatch.getElapsedTimeMili()); } - public Bundle[] bundlesFromAddresses(String[] addresses, final Boolean inclusionStates) throws ArgumentException, InvalidBundleException, InvalidSignatureException, NoNodeInfoException, NoInclusionStatesExcpection { + /** + * Internal function to get the formatted bundles of a list of addresses. + * + * @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. + */ + public Bundle[] bundlesFromAddresses(String[] addresses, final Boolean inclusionStates) throws ArgumentException, InvalidBundleException, InvalidSignatureException, NoNodeInfoException, NoInclusionStatesException { List trxs = findTransactionObjects(addresses); // set of tail transactions @@ -126,7 +151,7 @@ public class IotaAPI extends IotaAPICore { for (Transaction trx : trxs) { // Sort tail and nonTails - if (Long.parseLong(trx.getCurrentIndex()) == 0) { + if (trx.getCurrentIndex() == 0) { tailTransactions.add(trx.getHash()); } else { if (nonTailBundleHashes.indexOf(trx.getBundle()) == -1) { @@ -138,7 +163,7 @@ public class IotaAPI extends IotaAPICore { List bundleObjects = findTransactionObjectsByBundle(nonTailBundleHashes.toArray(new String[nonTailBundleHashes.size()])); for (Transaction trx : bundleObjects) { // Sort tail and nonTails - if (Long.parseLong(trx.getCurrentIndex()) == 0) { + if (trx.getCurrentIndex() == 0) { if (tailTransactions.indexOf(trx.getHash()) == -1) { tailTransactions.add(trx.getHash()); } @@ -151,14 +176,14 @@ public class IotaAPI extends IotaAPICore { // If inclusionStates, get the confirmation status // of the tail transactions, and thus the bundles GetInclusionStateResponse gisr = null; - if (tailTxArray != null && tailTxArray.length != 0 && inclusionStates) { + if (tailTxArray.length != 0 && inclusionStates) { try { gisr = getLatestInclusion(tailTxArray); } catch (IllegalAccessError ignored) { - throw new NoInclusionStatesExcpection(); + throw new NoInclusionStatesException(); } if (gisr == null || gisr.getStates() == null || gisr.getStates().length == 0) { - throw new NoInclusionStatesExcpection(); + throw new NoInclusionStatesException(); } } final GetInclusionStateResponse finalInclusionStates = gisr; @@ -169,9 +194,12 @@ public class IotaAPI extends IotaAPICore { try { GetBundleResponse bundleResponse = getBundle(param); Bundle gbr = new Bundle(bundleResponse.getTransactions(), bundleResponse.getTransactions().size()); - if (gbr != null && gbr.getTransactions() != null) { + if (gbr.getTransactions() != null) { if (inclusionStates) { - boolean thisInclusion = finalInclusionStates.getStates()[Arrays.asList(tailTxArray).indexOf(param)]; + boolean thisInclusion = false; + if (finalInclusionStates != null) { + thisInclusion = finalInclusionStates.getStates()[Arrays.asList(tailTxArray).indexOf(param)]; + } for (Transaction t : gbr.getTransactions()) { t.setPersistence(thisInclusion); } @@ -194,8 +222,11 @@ public class IotaAPI extends IotaAPICore { } /** - * @param trytes - * @return a StoreTransactionsResponse + * Wrapper function that broadcasts and stores the specified trytes. + * + * @param trytes The trytes. + * @return A StoreTransactionsResponse. + * @throws BroadcastAndStoreException is thrown if its not possible to broadcast and store. */ public StoreTransactionsResponse broadcastAndStore(final String... trytes) throws BroadcastAndStoreException { @@ -209,14 +240,15 @@ public class IotaAPI extends IotaAPICore { } /** - * Facade method: Gets transactions to approve, attaches to Tangle, broadcasts and stores + * Facade method: Gets transactions to approve, attaches to Tangle, broadcasts and stores. * - * @param {array} trytes - * @param {int} depth - * @param {int} minWeightMagnitude - * @return + * @param trytes The trytes. + * @param depth The depth. + * @param minWeightMagnitude The minimum weight magnitude. + * @return Transactions objects. + * @throws InvalidTrytesException is thrown when invalid trytes is provided. */ - public List sendTrytes(final String[] trytes, final int depth, final int minWeightMagnitude) { + public List sendTrytes(final String[] trytes, final int depth, final int minWeightMagnitude) throws InvalidTrytesException { final GetTransactionsToApproveResponse txs = getTransactionsToApprove(depth); // attach to tangle - do pow @@ -231,20 +263,17 @@ public class IotaAPI extends IotaAPICore { final List trx = new ArrayList<>(); for (final String tryte : Arrays.asList(res.getTrytes())) { - trx.add(new Transaction(tryte, customCurl)); + trx.add(new Transaction(tryte, customCurl.clone())); } return trx; } /** - * Wrapper function for getTrytes and transactionObjects - * gets the trytes and transaction object from a list of transaction hashes + * Wrapper function for getTrytes and transactionObjects. + * Gets the trytes and transaction object from a list of transaction hashes. * - * @param {array} hashes - * @return - * @method getTransactionsObjects - * @returns {function} callback - * @returns {object} success + * @param hashes The hashes + * @return Transaction objects. **/ public List getTransactionsObjects(String[] hashes) { @@ -257,20 +286,17 @@ public class IotaAPI extends IotaAPICore { final List trxs = new ArrayList<>(); for (final String tryte : trytesResponse.getTrytes()) { - trxs.add(new Transaction(tryte, customCurl)); + trxs.add(new Transaction(tryte, customCurl.clone())); } return trxs; } /** - * Wrapper function for findTransactions, getTrytes and transactionObjects - * Returns the transactionObject of a transaction hash. The input can be a valid - * findTransactions input + * Wrapper function for findTransactions, getTrytes and transactionObjects. + * Returns the transactionObject of a transaction hash. The input can be a valid findTransactions input. * - * @param {object} input - * @method getTransactionsObjects - * @returns {function} callback - * @returns {object} success + * @param input The inputs. + * @return Transactions. **/ public List findTransactionObjects(String[] input) { FindTransactionResponse ftr = findTransactions(input, null, null, null); @@ -281,14 +307,12 @@ 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 + * Wrapper function for findTransactions, getTrytes and transactionObjects. + * Returns the transactionObject of a transaction hash. The input can be a valid. * findTransactions input * - * @param {object} input - * @method getTransactionsObjects - * @returns {function} callback - * @returns {object} success + * @param input The inputs. + * @return Transactions. **/ public List findTransactionObjectsByBundle(String[] input) { FindTransactionResponse ftr = findTransactions(null, null, null, input); @@ -300,23 +324,24 @@ public class IotaAPI extends IotaAPICore { } /** - * Prepares transfer by generating bundle, finding and signing inputs + * Prepares transfer by generating bundle, finding and signing inputs. * - * @param {string} seed - * @param {object} transfers - * @param {object} options - * @param {function} callback - * @return - * @method prepareTransfers - * @property {array} inputs Inputs used for signing. Needs to have correct keyIndex and address value - * @property {string} address Remainder address - * @returns {array} trytes Returns bundle trytes - **/ - public List prepareTransfers(String seed, final List transfers, String remainder, List inputs) throws NotEnoughBalanceException { + * @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 { // Input validation of transfers object - if (!InputValidator.isTransfersCollectionCorrect(transfers)) { - throw new IllegalStateException("Invalid Transfer"); + if (!InputValidator.isTransfersCollectionValid(transfers)) { + throw new InvalidTransferException(); } // validate & if needed pad seed @@ -324,6 +349,9 @@ public class IotaAPI extends IotaAPICore { throw new IllegalStateException("Invalid Seed"); } + if (security < 1 || security > 3) { + throw new InvalidSecurityLevelException(); + } // Create a new bundle final Bundle bundle = new Bundle(); @@ -336,6 +364,10 @@ public class IotaAPI extends IotaAPICore { // and prepare the signatureFragments, message and tag for (final Transfer transfer : transfers) { + // If address with checksum then remove checksum + if (Checksum.isAddressWithChecksum(transfer.getAddress())) + transfer.setAddress(Checksum.removeChecksum(transfer.getAddress())); + int signatureMessageLength = 1; // If message longer than 2187 trytes, increase signatureMessageLength (add 2nd transaction) @@ -403,13 +435,19 @@ public class IotaAPI extends IotaAPICore { int i = 0; for (String balance : balances) { long thisBalance = Integer.parseInt(balance); - totalBalance += thisBalance; // If input has balance, add it to confirmedInputs if (thisBalance > 0) { + totalBalance += thisBalance; Input inputEl = inputs.get(i++); inputEl.setBalance(thisBalance); confirmedInputs.add(inputEl); + + // if we've already reached the intended input value, break out of loop + if (totalBalance >= totalValue) { + log.info("Total balance already reached "); + break; + } } } @@ -418,7 +456,7 @@ public class IotaAPI extends IotaAPICore { throw new IllegalStateException("Not enough balance"); } - return addRemainder(seed, confirmedInputs, bundle, tag, totalValue, null, signatureFragments); + return addRemainder(seed, security, confirmedInputs, bundle, tag, totalValue, null, signatureFragments); } // Case 2: Get inputs deterministically @@ -427,14 +465,14 @@ public class IotaAPI extends IotaAPICore { // confirm that the inputs exceed the threshold else { - @SuppressWarnings("unchecked") GetBalancesAndFormatResponse newinputs = getInputs(seed, 0, 0, totalValue); + @SuppressWarnings("unchecked") GetBalancesAndFormatResponse newinputs = getInputs(seed, security, 0, 0, totalValue); // If inputs with enough balance - return addRemainder(seed, newinputs.getInput(), bundle, tag, totalValue, null, signatureFragments); + return addRemainder(seed, security, newinputs.getInput(), bundle, tag, totalValue, null, signatureFragments); } } else { // If no input required, don't sign and simply finalize the bundle - bundle.finalize(customCurl); + bundle.finalize(customCurl.clone()); bundle.addTrytes(signatureFragments); List trxb = bundle.getTransactions(); @@ -451,15 +489,15 @@ public class IotaAPI extends IotaAPICore { /** * Gets the inputs of a seed * - * @param {string} seed - * @param {object} options - * @param {function} callback - * @method getInputs - * @property {int} start Starting key index - * @property {int} end Ending key index - * @property {int} threshold Min balance required + * @param seed Tryte-encoded seed. It should be noted that this seed is not transferred. + * @param security The Security level of private key / seed. + * @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. **/ - public GetBalancesAndFormatResponse getInputs(String seed, int start, int end, long threshold) { + public GetBalancesAndFormatResponse getInputs(String seed, int security, int start, int end, long threshold) throws InvalidSecurityLevelException, InvalidAddressException { StopWatch stopWatch = new StopWatch(); // validate the seed if (!InputValidator.isTrytes(seed, 0)) { @@ -471,6 +509,10 @@ public class IotaAPI extends IotaAPICore { throw new IllegalStateException("Invalid Seed"); } + if (security < 1 || security > 3) { + throw new InvalidSecurityLevelException(); + } + // 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)) { @@ -487,11 +529,11 @@ public class IotaAPI extends IotaAPICore { for (int i = start; i < end; i++) { - String address = IotaAPIUtils.newAddress(seed, i, false, customCurl); + String address = IotaAPIUtils.newAddress(seed, security, i, false, customCurl.clone()); allAddresses.add(address); } - return getBalanceAndFormat(allAddresses, threshold, start, end, stopWatch); + return getBalanceAndFormat(allAddresses, threshold, start, end, stopWatch, security); } // Case 2: iterate till threshold || end // @@ -499,14 +541,28 @@ public class IotaAPI extends IotaAPICore { // Calls getNewAddress and deterministically generates and returns all addresses // We then do getBalance, format the output and return it else { - final GetNewAddressResponse res = getNewAddress(seed, start, false, 0, true); - return getBalanceAndFormat(res.getAddresses(), threshold, start, end, stopWatch); + final GetNewAddressResponse res = getNewAddress(seed, security, start, false, 0, true); + return getBalanceAndFormat(res.getAddresses(), threshold, start, end, stopWatch, security); } } - // Calls getBalances and formats the output - // returns the final inputsObject then - public GetBalancesAndFormatResponse getBalanceAndFormat(final List addresses, long threshold, int start, int end, StopWatch stopWatch) { + /** + * Gets the balances and formats the output. + * + * @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. + **/ + public GetBalancesAndFormatResponse getBalanceAndFormat(final List addresses, long threshold, int start, int end, StopWatch stopWatch, int security) throws InvalidSecurityLevelException { + + if (security < 1 || security > 3) { + throw new InvalidSecurityLevelException(); + } GetBalancesResponse getBalancesResponse = getBalances(100, addresses); List balances = Arrays.asList(getBalancesResponse.getBalances()); @@ -524,7 +580,7 @@ public class IotaAPI extends IotaAPICore { long balance = Long.parseLong(balances.get(++i)); if (balance > 0) { - final Input newEntry = new Input(address, balance, start + i); + final Input newEntry = new Input(address, balance, start + i, security); inputs.add(newEntry); // Increase totalBalance of all aggregated inputs @@ -544,13 +600,15 @@ public class IotaAPI extends IotaAPICore { } /** - * Gets the associated bundle transactions of a single transaction - * Does validation of signatures, total sum as well as bundle order + * Gets the associated bundle transactions of a single transaction. + * Does validation of signatures, total sum as well as bundle order. * - * @param {string} transaction Hash of a tail transaction - * @method getBundle - * @returns {list} bundle Transaction objects - **/ + * @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. + */ public GetBundleResponse getBundle(String transaction) throws ArgumentException, InvalidBundleException, InvalidSignatureException { StopWatch stopWatch = new StopWatch(); @@ -560,7 +618,6 @@ public class IotaAPI extends IotaAPICore { } long totalSum = 0; - int lastIndex = 0; String bundleHash = bundle.getTransactions().get(0).getBundle(); ICurl curl = new JCurl(); @@ -570,10 +627,10 @@ public class IotaAPI extends IotaAPICore { for (int i = 0; i < bundle.getTransactions().size(); i++) { Transaction trx = bundle.getTransactions().get(i); - Long bundleValue = Long.parseLong(trx.getValue()); + Long bundleValue = trx.getValue(); totalSum += bundleValue; - if (i != Integer.parseInt(bundle.getTransactions().get(i).getCurrentIndex())) { + if (i != bundle.getTransactions().get(i).getCurrentIndex()) { throw new ArgumentException("Invalid Bundle"); } @@ -593,7 +650,7 @@ public class IotaAPI extends IotaAPICore { Transaction newBundleTx = bundle.getTransactions().get(i + 1); // Check if new tx is part of the signature fragment - if (newBundleTx.getAddress().equals(address) && Long.parseLong(newBundleTx.getValue()) == 0) { + if (newBundleTx.getAddress().equals(address) && newBundleTx.getValue() == 0) { if (sig.getSignatureFragments().indexOf(newBundleTx.getSignatureFragments()) == -1) sig.getSignatureFragments().add(newBundleTx.getSignatureFragments()); } @@ -612,14 +669,14 @@ public class IotaAPI extends IotaAPICore { if (!bundleFromTxString.equals(bundleHash)) throw new InvalidBundleException("Invalid Bundle Hash"); // Last tx in the bundle should have currentIndex === lastIndex bundle.setLength(bundle.getTransactions().size()); - if (!bundle.getTransactions().get(bundle.getLength() - 1).getCurrentIndex().equals(bundle.getTransactions().get(bundle.getLength() - 1).getLastIndex())) + if (!(bundle.getTransactions().get(bundle.getLength() - 1).getCurrentIndex() == (bundle.getTransactions().get(bundle.getLength() - 1).getLastIndex()))) throw new InvalidBundleException("Invalid Bundle"); // Validate the signatures for (Signature aSignaturesToValidate : signaturesToValidate) { String[] signatureFragments = aSignaturesToValidate.getSignatureFragments().toArray(new String[aSignaturesToValidate.getSignatureFragments().size()]); String address = aSignaturesToValidate.getAddress(); - boolean isValidSignature = new Signing().validateSignatures(address, signatureFragments, bundleHash); + boolean isValidSignature = new Signing(customCurl.clone()).validateSignatures(address, signatureFragments, bundleHash); if (!isValidSignature) throw new InvalidSignatureException(); } @@ -628,16 +685,18 @@ public class IotaAPI extends IotaAPICore { } /** - * Replays a transfer by doing Proof of Work again + * Replays a transfer by doing Proof of Work again. * - * @param {string} tail - * @param {int} depth - * @param {int} minWeightMagnitude - * @param {function} callback - * @method replayBundle - * @returns {object} analyzed Transaction objects - **/ - public ReplayBundleResponse replayBundle(String transaction, int depth, int minWeightMagnitude) throws InvalidBundleException, ArgumentException, InvalidSignatureException { + * @param transaction The transaction. + * @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. + */ + public ReplayBundleResponse replayBundle(String transaction, int depth, int minWeightMagnitude) throws InvalidBundleException, ArgumentException, InvalidSignatureException, InvalidTrytesException { StopWatch stopWatch = new StopWatch(); List bundleTrytes = new ArrayList<>(); @@ -667,11 +726,10 @@ public class IotaAPI extends IotaAPICore { /** * Wrapper function for getNodeInfo and getInclusionStates * - * @param {array} hashes - * @method getLatestInclusion - * @returns {function} callback - * @returns {array} state - **/ + * @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 { GetNodeInfoResponse getNodeInfoResponse = getNodeInfo(); if (getNodeInfoResponse == null) throw new NoNodeInfoException(); @@ -681,10 +739,33 @@ public class IotaAPI extends IotaAPICore { return getInclusionStates(hashes, latestMilestone); } - public SendTransferResponse sendTransfer(String seed, int depth, int minWeightMagnitude, final List transfers, Input[] inputs, String address) throws NotEnoughBalanceException { + /** + * Wrapper function that basically does prepareTransfers, as well as attachToTangle and finally, it broadcasts and stores the transactions locally. + * + * @param seed Tryte-encoded seed + * @param security The security level of private key / seed. + * @param depth The depth. + * @param minWeightMagnitude The minimum weight magnitude. + * @param transfers Array of transfer objects. + * @param inputs List of inputs used for funding the transfer. + * @param address If defined, this address will be used for sending the remainder value (of the inputs) to. + * @return Array of Transaction objects. + * @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 InvalidTrytesException is thrown when invalid trytes is provided. + * @throws InvalidAddressException is thrown when the specified address is not an valid address. + * @throws InvalidTransferException is thrown when an invalid transfer is provided. + */ + public SendTransferResponse sendTransfer(String seed, int security, int depth, int minWeightMagnitude, final List transfers, Input[] inputs, String address) throws NotEnoughBalanceException, InvalidSecurityLevelException, InvalidTrytesException, InvalidAddressException, InvalidTransferException { + + if (security < 1 || security > 3) { + throw new InvalidSecurityLevelException(); + } + StopWatch stopWatch = new StopWatch(); - List trytes = prepareTransfers(seed, transfers, address, inputs == null ? null : Arrays.asList(inputs)); + List trytes = prepareTransfers(seed, security, transfers, address, inputs == null ? null : Arrays.asList(inputs)); List trxs = sendTrytes(trytes.toArray(new String[trytes.size()]), depth, minWeightMagnitude); Boolean[] successful = new Boolean[trxs.size()]; @@ -704,12 +785,12 @@ public class IotaAPI extends IotaAPICore { * the bundle hash of the transaction is no longer the same. In case the input * transaction hash is not a tail, we return an error. * - * @param {string} trunkTx Hash of a trunk or a tail transaction of a bundle - * @param {string} bundleHash - * @param {array} bundle List of bundles to be populated - * @method traverseBundle - * @returns {array} bundle Transaction objects - **/ + * @param trunkTx Hash of a trunk or a tail transaction of a bundle. + * @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. + */ public Bundle traverseBundle(String trunkTx, String bundleHash, Bundle bundle) throws ArgumentException { GetTrytesResponse gtr = getTrytes(trunkTx); @@ -719,12 +800,12 @@ public class IotaAPI extends IotaAPICore { throw new ArgumentException("Bundle transactions not visible"); } - Transaction trx = new Transaction(gtr.getTrytes()[0], customCurl); - if (trx == null || trx.getBundle() == null) { + Transaction trx = new Transaction(gtr.getTrytes()[0], customCurl.clone()); + if (trx.getBundle() == null) { throw new ArgumentException("Invalid trytes, could not create object"); } // If first transaction to search is not a tail, return error - if (bundleHash == null && Integer.parseInt(trx.getCurrentIndex()) != 0) { + if (bundleHash == null && trx.getCurrentIndex() != 0) { throw new ArgumentException("Invalid tail transaction supplied."); } // If no bundle hash, define it @@ -736,7 +817,7 @@ public class IotaAPI extends IotaAPICore { return bundle; } // If only one bundle element, return - if (Integer.parseInt(trx.getLastIndex()) == 0 && Integer.parseInt(trx.getCurrentIndex()) == 0) { + if (trx.getLastIndex() == 0 && trx.getCurrentIndex() == 0) { return new Bundle(Collections.singletonList(trx), 1); } // Define new trunkTransaction for search @@ -751,6 +832,176 @@ public class IotaAPI extends IotaAPICore { } } + + /** + * Prepares transfer by generating the bundle with the corresponding cosigner transactions. + * Does not contain signatures. + * + * @param securitySum The sum of security levels used by all co-signers. + * @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. + */ + public List initiateTransfer(int securitySum, final String inputAddress, String remainderAddress, + final List transfers, boolean testMode) throws InvalidAddressException, InvalidBundleException, InvalidTransferException { + StopWatch sw = new StopWatch(); + + + // If message or tag is not supplied, provide it + // Also remove the checksum of the address if it's there + + 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())); + } + } + + // 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(); + } + + // Create a new bundle + final Bundle bundle = new Bundle(); + + int totalValue = 0; + final List signatureFragments = new ArrayList<>(); + String tag = ""; + // + + // Iterate over all transfers, get totalValue + // and prepare the signatureFragments, message and tag + for (final Transfer transfer : transfers) { + + int signatureMessageLength = 1; + + // If message longer than 2187 trytes, increase signatureMessageLength (add 2nd transaction) + if (transfer.getMessage().length() > 2187) { + + // Get total length, message / maxLength (2187 trytes) + signatureMessageLength += Math.floor(transfer.getMessage().length() / 2187); + + 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()); + + // Pad remainder of fragment + + fragment = StringUtils.rightPad(fragment, 2187, '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'); + + signatureFragments.add(fragment); + + } + + // 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 + totalValue += transfer.getValue(); + } + + // Get inputs if we are sending tokens + if (totalValue != 0) { + + GetBalancesResponse balancesResponse = getBalances(100, new String[]{inputAddress}); + String[] balances = balancesResponse.getBalances(); + + long totalBalance = 0; + + for (String balance : balances) { + long thisBalance = Integer.parseInt(balance); + + totalBalance += thisBalance; + } + + // get current timestamp in seconds + long timestamp = (long) Math.floor(Calendar.getInstance().getTimeInMillis() / 1000); + + // bypass the balance checks during unit testing + if (testMode) + totalBalance += 1000; + + if (totalBalance > 0) { + + long toSubtract = 0 - totalBalance; + + // Add input as bundle entry + // Only a single entry, signatures will be added later + bundle.addEntry(securitySum, inputAddress, toSubtract, tag, timestamp); + } + // Return not enough balance error + if (totalValue > totalBalance) { + throw new IllegalStateException("Not enough balance"); + } + + // If there is a remainder value + // Add extra output to send remaining funds to + if (totalBalance > totalValue) { + + long remainder = totalBalance - totalValue; + + // Remainder bundle entry if necessary + if (remainderAddress == null) { + throw new IllegalStateException("No remainder address defined"); + } + + bundle.addEntry(1, remainderAddress, remainder, tag, timestamp); + } + + bundle.finalize(customCurl.clone()); + bundle.addTrytes(signatureFragments); + + return bundle.getTransactions(); + } else { + throw new RuntimeException("Invalid value transfer: the transfer does not require a signature."); + } + + } + + /** + * @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); @@ -760,21 +1011,35 @@ public class IotaAPI extends IotaAPICore { throw new ArgumentException("Bundle transactions not visible"); } - Transaction trx = new Transaction(gtr.getTrytes()[0], customCurl); - if (trx == null || trx.getBundle() == null) { + Transaction trx = new Transaction(gtr.getTrytes()[0], customCurl.clone()); + if (trx.getBundle() == null) { throw new ArgumentException("Invalid trytes, could not create object"); } - if (Integer.parseInt(trx.getCurrentIndex()) == 0) return trx.getHash(); + 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. + * @param inputs List of inputs used for funding the transfer. + * @param bundle To be populated. + * @param tag The tag. + * @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. + */ public List addRemainder(final String seed, + final int security, final List inputs, final Bundle bundle, final String tag, final long totalValue, final String remainderAddress, - final List signatureFragments) throws NotEnoughBalanceException { + final List signatureFragments) throws NotEnoughBalanceException, InvalidSecurityLevelException, InvalidAddressException { long totalTransferValue = totalValue; for (int i = 0; i < inputs.size(); i++) { @@ -783,7 +1048,7 @@ public class IotaAPI extends IotaAPICore { long timestamp = (long) Math.floor(Calendar.getInstance().getTimeInMillis() / 1000); // Add input as bundle entry - bundle.addEntry(2, inputs.get(i).getAddress(), toSubtract, tag, timestamp); + bundle.addEntry(security, inputs.get(i).getAddress(), toSubtract, tag, timestamp); // If there is a remainder value // Add extra output to send remaining funds to @@ -796,20 +1061,20 @@ public class IotaAPI extends IotaAPICore { // Remainder bundle entry bundle.addEntry(1, remainderAddress, remainder, tag, timestamp); // Final function for signing inputs - return IotaAPIUtils.signInputsAndReturn(seed, inputs, bundle, signatureFragments, customCurl); + return IotaAPIUtils.signInputsAndReturn(seed, inputs, bundle, signatureFragments, customCurl.clone()); } else if (remainder > 0) { // Generate a new Address by calling getNewAddress - GetNewAddressResponse res = getNewAddress(seed, 0, false, 0, false); + GetNewAddressResponse res = getNewAddress(seed, security, 0, false, 0, false); // Remainder bundle entry bundle.addEntry(1, res.getAddresses().get(0), remainder, tag, timestamp); // Final function for signing inputs - return IotaAPIUtils.signInputsAndReturn(seed, inputs, bundle, signatureFragments, customCurl); + return IotaAPIUtils.signInputsAndReturn(seed, inputs, bundle, signatureFragments, customCurl.clone()); } else { // If there is no remainder, do not add transaction to bundle // simply sign and return - return IotaAPIUtils.signInputsAndReturn(seed, inputs, bundle, signatureFragments, customCurl); + return IotaAPIUtils.signInputsAndReturn(seed, inputs, bundle, signatureFragments, customCurl.clone()); } // If multiple inputs provided, subtract the totalTransferValue by @@ -822,7 +1087,7 @@ public class IotaAPI extends IotaAPICore { } public static class Builder extends IotaAPICore.Builder { - private ICurl customCurl; + private ICurl customCurl = new JCurl(); public Builder withCustomCurl(ICurl curl) { customCurl = curl; diff --git a/src/main/java/jota/IotaAPICommands.java b/src/main/java/jota/IotaAPICommands.java index bcb9b58..fe66f1b 100644 --- a/src/main/java/jota/IotaAPICommands.java +++ b/src/main/java/jota/IotaAPICommands.java @@ -2,7 +2,7 @@ package jota; /** * IOTA's node command list - * + *

* 'params' is not currently used. */ public enum IotaAPICommands { @@ -25,15 +25,25 @@ public enum IotaAPICommands { private String command; private int params; + /** + * @param command + * @param params + */ IotaAPICommands(String command, int params) { this.command = command; this.params = params; } + /** + * @return + */ public String command() { return command; } + /** + * @return + */ public int params() { return params; } diff --git a/src/main/java/jota/IotaAPICore.java b/src/main/java/jota/IotaAPICore.java index 1004eb6..9eba60c 100644 --- a/src/main/java/jota/IotaAPICore.java +++ b/src/main/java/jota/IotaAPICore.java @@ -2,6 +2,8 @@ package jota; import jota.dto.request.*; import jota.dto.response.*; +import jota.error.InvalidTrytesException; +import jota.utils.InputValidator; import okhttp3.OkHttpClient; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -18,7 +20,9 @@ import java.util.Properties; import java.util.concurrent.TimeUnit; /** - * Created by Adrian on 15.01.2017. + * This class provides access to the Iota core API + * + * @author Adrian */ public class IotaAPICore { @@ -27,6 +31,11 @@ public class IotaAPICore { private IotaAPIService service; private String protocol, host, port; + /** + * Build the API core. + * + * @param builder The builder. + */ protected IotaAPICore(final Builder builder) { protocol = builder.protocol; host = builder.host; @@ -34,6 +43,11 @@ public class IotaAPICore { postConstruct(); } + /** + * @param call + * @param + * @return + */ protected static Response wrapCheckedException(final Call call) { try { final Response res = call.execute(); @@ -51,6 +65,11 @@ 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) { @@ -61,6 +80,9 @@ public class IotaAPICore { return value; } + /** + * + */ private void postConstruct() { final String nodeUrl = protocol + "://" + host + ":" + port; @@ -165,7 +187,11 @@ public class IotaAPICore { return wrapCheckedException(res).body(); } - public GetAttachToTangleResponse attachToTangle(String trunkTransaction, String branchTransaction, Integer minWeightMagnitude, String... trytes) { + public GetAttachToTangleResponse attachToTangle(String trunkTransaction, String branchTransaction, Integer minWeightMagnitude, String... trytes) throws InvalidTrytesException { + if (!InputValidator.isArrayOfTrytes(trytes)) { + throw new InvalidTrytesException(); + } + final Call res = service.attachToTangle(IotaAttachToTangleRequest.createAttachToTangleRequest(trunkTransaction, branchTransaction, minWeightMagnitude, trytes)); return wrapCheckedException(res).body(); } @@ -181,7 +207,7 @@ public class IotaAPICore { } @SuppressWarnings("unchecked") - public static class Builder > { + public static class Builder> { String protocol, host, port; @@ -201,6 +227,9 @@ public class IotaAPICore { return new IotaAPICore(this); } + /** + * @return + */ private boolean checkPropertiesFiles() { try { @@ -229,25 +258,40 @@ public class IotaAPICore { return (port != null && protocol != null && host != null); } + /** + * + */ private void checkEnviromentVariables() { protocol = env("IOTA_NODE_PROTOCOL", "http"); host = env("IOTA_NODE_HOST", "localhost"); port = env("IOTA_NODE_PORT", "14265"); } + /** + * @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; + return (T) this; } } diff --git a/src/main/java/jota/IotaAPIService.java b/src/main/java/jota/IotaAPIService.java index a626209..2946307 100644 --- a/src/main/java/jota/IotaAPIService.java +++ b/src/main/java/jota/IotaAPIService.java @@ -19,7 +19,7 @@ public interface IotaAPIService { /** * Returns information about your node. - * + *

* curl http://localhost:14265 -X POST -H 'Content-Type: application/json' * -d '{"command": "getNodeInfo"}' * @@ -31,7 +31,7 @@ public interface IotaAPIService { /** * Get the list of latest tips (unconfirmed transactions). - * + *

* curl http://localhost:14265 -X POST -H 'Content-Type: application/json' * -d '{"command": "getNeighbors"}' */ @@ -41,7 +41,7 @@ public interface IotaAPIService { /** * Add a list of neighbors to your 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"]}' */ @@ -51,7 +51,7 @@ public interface IotaAPIService { /** * Removes a list of neighbors to your 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"]}' */ @@ -61,7 +61,7 @@ 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"}' */ @@ -71,7 +71,7 @@ public interface IotaAPIService { /** * 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"]}' */ @@ -82,7 +82,7 @@ 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. - * + *

* curl http://localhost:14265 -X POST -H 'Content-Type: application/json' * -d '{"command": "getInclusionStates", "transactions"Q9HZWYKFWYWZRE9JQKG9REPKIASHUUECPSQO9JT9XNMVKWYGVAZETAIRPTM"], "tips" : []}' */ @@ -92,7 +92,7 @@ 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"]}' */ @@ -102,7 +102,7 @@ public interface IotaAPIService { /** * 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}' */ @@ -112,7 +112,7 @@ 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}' */ @@ -122,7 +122,7 @@ 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"]}' */ @@ -132,7 +132,7 @@ public interface IotaAPIService { /** * Interrupts and completely aborts the attachToTangle process. - * + *

* curl http://localhost:14265 -X POST -H 'Content-Type: application/json' * -d '{"command": "interruptAttachingToTangle" } */ @@ -142,7 +142,7 @@ 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"]} */ @@ -152,7 +152,7 @@ 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"]}' */ diff --git a/src/main/java/jota/dto/request/IotaAttachToTangleRequest.java b/src/main/java/jota/dto/request/IotaAttachToTangleRequest.java index 8d50a54..6ff6f96 100644 --- a/src/main/java/jota/dto/request/IotaAttachToTangleRequest.java +++ b/src/main/java/jota/dto/request/IotaAttachToTangleRequest.java @@ -2,6 +2,10 @@ package jota.dto.request; 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 { private String trunkTransaction; @@ -9,6 +13,9 @@ public class IotaAttachToTangleRequest extends IotaCommandRequest { private Integer minWeightMagnitude; private String[] trytes; + /** + * Initializes a new instance of the IotaAttachedToTangleRequest class. + */ private IotaAttachToTangleRequest(final String trunkTransaction, final String branchTransaction, final Integer minWeightMagnitude, final String... trytes) { super(IotaAPICommands.ATTACH_TO_TANGLE); this.trunkTransaction = trunkTransaction; @@ -17,38 +24,81 @@ public class IotaAttachToTangleRequest extends IotaCommandRequest { this.trytes = trytes; } + /** + * Create a new instance of the IotaAttachedToTangleRequest class. + */ public static IotaAttachToTangleRequest createAttachToTangleRequest(final String trunkTransaction, final String branchTransaction, final Integer minWeightMagnitude, final String... trytes) { return new IotaAttachToTangleRequest(trunkTransaction, branchTransaction, minWeightMagnitude, trytes); } + /** + * Gets the trunk transaction. + * + * @return The trunk transaction. + */ public String getTrunkTransaction() { return trunkTransaction; } + /** + * Sets the trunk transaction. + * + * @param trunkTransaction The trunk transaction. + */ public void setTrunkTransaction(String trunkTransaction) { this.trunkTransaction = trunkTransaction; } + /** + * Gets the branch transaction. + * + * @return The branch transaction. + */ public String getBranchTransaction() { return branchTransaction; } + /** + * Sets the branch transaction. + * + * @param branchTransaction the branch transaction. + */ public void setBranchTransaction(String branchTransaction) { this.branchTransaction = branchTransaction; } + /** + * Gets the min weight magnitude. + * + * @return The min weight magnitude. + */ public Integer getMinWeightMagnitude() { return minWeightMagnitude; } + /** + * Sets the min weight magnitude. + * + * @param minWeightMagnitude The min weight magnitude. + */ public void setMinWeightMagnitude(Integer minWeightMagnitude) { this.minWeightMagnitude = minWeightMagnitude; } + /** + * Gets the trytes. + * + * @return The trytes. + */ public String[] getTrytes() { return trytes; } + /** + * Sets the trytes. + * + * @param trytes The trytes. + */ public void setTrytes(String[] trytes) { this.trytes = trytes; } diff --git a/src/main/java/jota/dto/request/IotaBroadcastTransactionRequest.java b/src/main/java/jota/dto/request/IotaBroadcastTransactionRequest.java index 5a0a5d5..bd25ef4 100644 --- a/src/main/java/jota/dto/request/IotaBroadcastTransactionRequest.java +++ b/src/main/java/jota/dto/request/IotaBroadcastTransactionRequest.java @@ -2,23 +2,42 @@ package jota.dto.request; import jota.IotaAPICommands; +/** + * Broadcast a list of transactions to all neighbors. The input trytes for this call are provided by attachToTangle + **/ public class IotaBroadcastTransactionRequest extends IotaCommandRequest { private String[] trytes; + /** + * Initializes a new instance of the IotaBroadcastTransactionRequest class. + */ private IotaBroadcastTransactionRequest(final String... trytes) { super(IotaAPICommands.BROADCAST_TRANSACTIONS); this.trytes = trytes; } + /** + * Initializes a new instance of the IotaBroadcastTransactionRequest class. + */ public static IotaBroadcastTransactionRequest createBroadcastTransactionsRequest(final String... trytes) { return new IotaBroadcastTransactionRequest(trytes); } + /** + * Gets the trytes. + * + * @return The trytes. + */ public String[] getTrytes() { return trytes; } + /** + * Sets the trytes. + * + * @param trytes The trytes. + */ public void setTrytes(String[] trytes) { this.trytes = trytes; } diff --git a/src/main/java/jota/dto/request/IotaCommandRequest.java b/src/main/java/jota/dto/request/IotaCommandRequest.java index 3f914a0..b22d266 100644 --- a/src/main/java/jota/dto/request/IotaCommandRequest.java +++ b/src/main/java/jota/dto/request/IotaCommandRequest.java @@ -2,26 +2,52 @@ package jota.dto.request; import jota.IotaAPICommands; +/** + * This class represents the core api request 'getNodeInfo', 'getNeighbors' and 'interruptAttachToTangle' + **/ public class IotaCommandRequest { final String command; + /** + * @param command + */ protected IotaCommandRequest(IotaAPICommands command) { this.command = command.command(); } + /** + * Get information about the node. + * + * @return The Node info. + */ public static IotaCommandRequest createNodeInfoRequest() { return new IotaCommandRequest(IotaAPICommands.GET_NODE_INFO); } + /** + * Gets the tips of the node. + * + * @return The tips of the node. + */ public static IotaCommandRequest createGetTipsRequest() { return new IotaCommandRequest(IotaAPICommands.GET_TIPS); } + /** + * Gets the neighbours of the node. + * + * @return The list of neighbors. + */ public static IotaCommandRequest createGetNeighborsRequest() { return new IotaCommandRequest(IotaAPICommands.GET_NEIGHBORS); } + /** + * Interrupt attaching to the tangle + * + * @return + */ public static IotaCommandRequest createInterruptAttachToTangleRequest() { return new IotaCommandRequest(IotaAPICommands.INTERRUPT_ATTACHING_TO_TANGLE); } diff --git a/src/main/java/jota/dto/request/IotaFindTransactionsRequest.java b/src/main/java/jota/dto/request/IotaFindTransactionsRequest.java index 71e70fe..620c131 100644 --- a/src/main/java/jota/dto/request/IotaFindTransactionsRequest.java +++ b/src/main/java/jota/dto/request/IotaFindTransactionsRequest.java @@ -2,70 +2,131 @@ package jota.dto.request; import jota.IotaAPICommands; +/** + * This class represents the core api request 'findTransactions' + **/ public class IotaFindTransactionsRequest extends IotaCommandRequest { - public String[] getBundles() { - return bundles; - } - - public void setBundles(String[] bundles) { - this.bundles = bundles; - } - - public String[] getAddresses() { - return addresses; - } - - public void setAddresses(String[] addresses) { - this.addresses = addresses; - } - - public String[] getTags() { - return tags; - } - - public void setTags(String[] tags) { - this.tags = tags; - } - - public String[] getApprovees() { - return approvees; - } - - public void setApprovees(String[] approvees) { - this.approvees = approvees; - } - private String[] bundles; // List of bundle hashes. The hashes need to be extended to 81chars by padding the hash with 9's. private String[] addresses; private String[] tags; private String[] approvees; + /** + * Initializes a new instance of the IotaFindTransactionsRequest class. + */ private IotaFindTransactionsRequest() { super(IotaAPICommands.FIND_TRANSACTIONS); } + /** + * Create a new instance of the IotaFindTransactionsRequest class. + */ public static IotaFindTransactionsRequest createFindTransactionRequest() { return new IotaFindTransactionsRequest(); } + /** + * Initializes a new instance of the IotaFindTransactionsRequest class. + */ public IotaFindTransactionsRequest byBundles(String... bundles) { this.bundles = bundles; return this; } + /** + * Initializes a new instance of the IotaFindTransactionsRequest class. + */ public IotaFindTransactionsRequest byAddresses(String... addresses) { this.addresses = addresses; return this; } + /** + * Initializes a new instance of the IotaFindTransactionsRequest class. + */ public IotaFindTransactionsRequest byTags(String... tags) { this.tags = tags; return this; } + /** + * Initializes a new instance of the IotaFindTransactionsRequest class. + */ public IotaFindTransactionsRequest byApprovees(String... approvees) { this.approvees = approvees; return this; } + + /** + * Gets the bundles. + * + * @return The bundles. + */ + public String[] getBundles() { + return bundles; + } + + /** + * Sets the bundles. + * + * @param bundles The bundles. + */ + public void setBundles(String[] bundles) { + this.bundles = bundles; + } + + /** + * Gets the addresses. + * + * @return The addresses. + */ + public String[] getAddresses() { + return addresses; + } + + /** + * Sets the addresses. + * + * @param addresses The addresses. + */ + public void setAddresses(String[] addresses) { + this.addresses = addresses; + } + + /** + * Gets the tags. + * + * @return The tags. + */ + public String[] getTags() { + return tags; + } + + /** + * Sets the tags. + * + * @param tags The tags. + */ + public void setTags(String[] tags) { + this.tags = tags; + } + + /** + * Gets the approvees. + * + * @return The approvees. + */ + public String[] getApprovees() { + return approvees; + } + + /** + * Sets the approvees. + * + * @param approvees The approvees. + */ + public void setApprovees(String[] approvees) { + this.approvees = approvees; + } } diff --git a/src/main/java/jota/dto/request/IotaGetBalancesRequest.java b/src/main/java/jota/dto/request/IotaGetBalancesRequest.java index 33d760d..56457cb 100644 --- a/src/main/java/jota/dto/request/IotaGetBalancesRequest.java +++ b/src/main/java/jota/dto/request/IotaGetBalancesRequest.java @@ -2,33 +2,62 @@ package jota.dto.request; import jota.IotaAPICommands; +/** + * This class represents the core api request 'getBalances' + **/ public class IotaGetBalancesRequest extends IotaCommandRequest { private String[] addresses; private Integer threshold; + /** + * Initializes a new instance of the IotaGetBalancesRequest class. + */ private IotaGetBalancesRequest(final Integer threshold, final String... addresses) { super(IotaAPICommands.GET_BALANCES); this.addresses = addresses; this.threshold = threshold; } + /** + * Create a new instance of the IotaGetBalancesRequest class. + */ public static IotaGetBalancesRequest createIotaGetBalancesRequest(final Integer threshold, final String... addresses) { return new IotaGetBalancesRequest(threshold, addresses); } + /** + * Gets the addresses. + * + * @return The addresses. + */ public String[] getAddresses() { return addresses; } + /** + * Sets the addresses. + * + * @param addresses The addresses. + */ public void setAddresses(String[] addresses) { this.addresses = addresses; } + /** + * Gets the threshold. + * + * @return The threshold. + */ public Integer getThreshold() { return threshold; } + /** + * Sets the threshold. + * + * @param threshold The threshold. + */ public void setThreshold(Integer threshold) { this.threshold = threshold; } diff --git a/src/main/java/jota/dto/request/IotaGetInclusionStateRequest.java b/src/main/java/jota/dto/request/IotaGetInclusionStateRequest.java index 704806e..82cfe75 100644 --- a/src/main/java/jota/dto/request/IotaGetInclusionStateRequest.java +++ b/src/main/java/jota/dto/request/IotaGetInclusionStateRequest.java @@ -4,39 +4,71 @@ import jota.IotaAPICommands; import java.util.Collection; +/** + * This class represents the core API request 'getInclusionStates' + **/ public class IotaGetInclusionStateRequest extends IotaCommandRequest { private String[] transactions; private String[] tips; + /** + * Initializes a new instance of the IotaGetInclusionStateRequest class. + */ private IotaGetInclusionStateRequest(final String[] transactions, final String[] tips) { super(IotaAPICommands.GET_INCLUSIONS_STATES); this.transactions = transactions; this.tips = tips; } + /** + * Create a new instance of the IotaGetInclusionStateRequest class. + */ public static IotaGetInclusionStateRequest createGetInclusionStateRequest(String[] transactions, String[] tips) { return new IotaGetInclusionStateRequest(transactions, tips); } + /** + * Create a new instance of the IotaGetInclusionStateRequest class. + */ public static IotaGetInclusionStateRequest createGetInclusionStateRequest(Collection transactions, Collection tips) { return createGetInclusionStateRequest( transactions.toArray(new String[]{}), tips.toArray(new String[]{})); } + /** + * Gets the transactions. + * + * @return The transactions. + */ public String[] getTransactions() { return transactions; } + /** + * Sets the transactions. + * + * @param transactions The transactions. + */ public void setTransactions(String[] transactions) { this.transactions = transactions; } + /** + * Gets the tips. + * + * @return The tips. + */ public String[] getTips() { return tips; } + /** + * Sets the tips. + * + * @param tips The tips. + */ public void setTips(String[] tips) { this.tips = tips; } diff --git a/src/main/java/jota/dto/request/IotaGetTransactionsToApproveRequest.java b/src/main/java/jota/dto/request/IotaGetTransactionsToApproveRequest.java index fb1b367..e9cca7c 100644 --- a/src/main/java/jota/dto/request/IotaGetTransactionsToApproveRequest.java +++ b/src/main/java/jota/dto/request/IotaGetTransactionsToApproveRequest.java @@ -2,23 +2,42 @@ package jota.dto.request; import jota.IotaAPICommands; +/** + * This class represents the core API request 'getTransactionsToApprove' + **/ public class IotaGetTransactionsToApproveRequest extends IotaCommandRequest { private Integer depth; + /** + * Initializes a new instance of the IotaGetTransactionsToApproveRequest class. + */ private IotaGetTransactionsToApproveRequest(final Integer depth) { super(IotaAPICommands.GET_TRANSACTIONS_TO_APPROVE); this.depth = depth; } + /** + * Create a new instance of the IotaGetTransactionsToApproveRequest class. + */ public static IotaGetTransactionsToApproveRequest createIotaGetTransactionsToApproveRequest(Integer depth) { return new IotaGetTransactionsToApproveRequest(depth); } + /** + * Gets the depth. + * + * @return The depth. + */ public Integer getDepth() { return depth; } + /** + * Sets the depth. + * + * @param depth The depth. + */ public void setDepth(Integer depth) { this.depth = depth; } diff --git a/src/main/java/jota/dto/request/IotaGetTrytesRequest.java b/src/main/java/jota/dto/request/IotaGetTrytesRequest.java index eaa5888..35f5f8d 100644 --- a/src/main/java/jota/dto/request/IotaGetTrytesRequest.java +++ b/src/main/java/jota/dto/request/IotaGetTrytesRequest.java @@ -2,23 +2,42 @@ package jota.dto.request; import jota.IotaAPICommands; +/** + * This class represents the core API request 'getTrytes' + **/ public class IotaGetTrytesRequest extends IotaCommandRequest { private String[] hashes; + /** + * Initializes a new instance of the IotaGetTrytesRequest class. + */ private IotaGetTrytesRequest(final String... hashes) { super(IotaAPICommands.GET_TRYTES); this.hashes = hashes; } + /** + * Create a new instance of the IotaGetTrytesRequest class. + */ public static IotaGetTrytesRequest createGetTrytesRequest(String... hashes) { return new IotaGetTrytesRequest(hashes); } + /** + * Gets the hashes. + * + * @return The hashes. + */ public String[] getHashes() { return hashes; } + /** + * Sets the hashes. + * + * @param hashes The hashes. + */ public void setHashes(String[] hashes) { this.hashes = hashes; } diff --git a/src/main/java/jota/dto/request/IotaNeighborsRequest.java b/src/main/java/jota/dto/request/IotaNeighborsRequest.java index c81c491..c6059b8 100644 --- a/src/main/java/jota/dto/request/IotaNeighborsRequest.java +++ b/src/main/java/jota/dto/request/IotaNeighborsRequest.java @@ -2,27 +2,49 @@ package jota.dto.request; import jota.IotaAPICommands; +/** + * This class represents the core API request 'addNeighbors' and 'removeNeighbors' + **/ public class IotaNeighborsRequest extends IotaCommandRequest { private String[] uris; + /** + * Initializes a new instance of the IotaNeighborsRequest class. + */ private IotaNeighborsRequest(IotaAPICommands type, final String... uris) { super(type); this.uris = uris; } + /** + * Create a new instance of the IotaNeighborsRequest class. + */ public static IotaNeighborsRequest createAddNeighborsRequest(String... uris) { return new IotaNeighborsRequest(IotaAPICommands.ADD_NEIGHBORS, uris); } + /** + * Create a new instance of the IotaNeighborsRequest class. + */ public static IotaNeighborsRequest createRemoveNeighborsRequest(String... uris) { return new IotaNeighborsRequest(IotaAPICommands.REMOVE_NEIGHBORS, uris); } + /** + * Gets the uris. + * + * @return The uris. + */ public String[] getUris() { return uris; } + /** + * Sets the uris. + * + * @param uris The uris. + */ public void setUris(String[] uris) { this.uris = uris; } diff --git a/src/main/java/jota/dto/request/IotaStoreTransactionsRequest.java b/src/main/java/jota/dto/request/IotaStoreTransactionsRequest.java index 1b9c55b..7e9972c 100644 --- a/src/main/java/jota/dto/request/IotaStoreTransactionsRequest.java +++ b/src/main/java/jota/dto/request/IotaStoreTransactionsRequest.java @@ -2,23 +2,43 @@ package jota.dto.request; 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 { private String[] trytes; + /** + * Initializes a new instance of the IotaStoreTransactionsRequest class. + */ private IotaStoreTransactionsRequest(final String... trytes) { super(IotaAPICommands.STORE_TRANSACTIONS); this.trytes = trytes; } + /** + * Create a new instance of the IotaStoreTransactionsRequest class. + */ public static IotaStoreTransactionsRequest createStoreTransactionsRequest(final String... trytes) { return new IotaStoreTransactionsRequest(trytes); } + /** + * Gets the trytes. + * + * @return The trytes. + */ public String[] getTrytes() { return trytes; } + /** + * Sets the trytes. + * + * @param trytes The trytes. + */ public void setTrytes(String[] trytes) { this.trytes = trytes; } diff --git a/src/main/java/jota/dto/response/AbstractResponse.java b/src/main/java/jota/dto/response/AbstractResponse.java index 547bf65..4184265 100644 --- a/src/main/java/jota/dto/response/AbstractResponse.java +++ b/src/main/java/jota/dto/response/AbstractResponse.java @@ -5,14 +5,36 @@ import org.apache.commons.lang3.builder.HashCodeBuilder; import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; +/** + * Abstract response. + */ public abstract class AbstractResponse { private Long duration; + /** + * Gets the duration. + * + * @return The duration. + */ public Long getDuration() { return duration; } + /** + * Sets the duration. + * + * @param duration The duration + */ + public void setDuration(Long duration) { + this.duration = duration; + } + + /** + * Returns a String that represents this object. + * + * @return Returns a string representation of this object. + */ @Override public String toString() { return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE); @@ -27,8 +49,4 @@ public abstract class AbstractResponse { public boolean equals(Object obj) { return EqualsBuilder.reflectionEquals(this, obj, false); } - - public void setDuration(Long duration) { - this.duration = duration; - } } diff --git a/src/main/java/jota/dto/response/AddNeighborsResponse.java b/src/main/java/jota/dto/response/AddNeighborsResponse.java index 586f5a2..4e4e485 100644 --- a/src/main/java/jota/dto/response/AddNeighborsResponse.java +++ b/src/main/java/jota/dto/response/AddNeighborsResponse.java @@ -1,9 +1,17 @@ package jota.dto.response; +/** + * Response of {@link jota.dto.request.IotaNeighborsRequest} + **/ public class AddNeighborsResponse extends AbstractResponse { private int addedNeighbors; + /** + * Gets the number of added neighbors. + * + * @return The number of added neighbors. + */ public int getAddedNeighbors() { return addedNeighbors; } diff --git a/src/main/java/jota/dto/response/AnalyzeTransactionResponse.java b/src/main/java/jota/dto/response/AnalyzeTransactionResponse.java index 08c56cf..bbcb8ee 100644 --- a/src/main/java/jota/dto/response/AnalyzeTransactionResponse.java +++ b/src/main/java/jota/dto/response/AnalyzeTransactionResponse.java @@ -5,10 +5,18 @@ import jota.model.Transaction; import java.util.ArrayList; import java.util.List; +/** + * Response of {@link jota.dto.request.IotaGetBalancesRequest} + **/ public class AnalyzeTransactionResponse extends AbstractResponse { private List transactions = new ArrayList<>(); + /** + * Gets the transactions. + * + * @return transactions trytes The transactions. + */ public List getTransactions() { return transactions; } diff --git a/src/main/java/jota/dto/response/BroadcastTransactionsResponse.java b/src/main/java/jota/dto/response/BroadcastTransactionsResponse.java index fe4d7cd..f7c2e0d 100644 --- a/src/main/java/jota/dto/response/BroadcastTransactionsResponse.java +++ b/src/main/java/jota/dto/response/BroadcastTransactionsResponse.java @@ -1,5 +1,8 @@ package jota.dto.response; +/** + * Response of {@link jota.dto.request.IotaBroadcastTransactionRequest} + **/ public class BroadcastTransactionsResponse extends AbstractResponse { // empty response } diff --git a/src/main/java/jota/dto/response/FindTransactionResponse.java b/src/main/java/jota/dto/response/FindTransactionResponse.java index 1991e86..1082421 100644 --- a/src/main/java/jota/dto/response/FindTransactionResponse.java +++ b/src/main/java/jota/dto/response/FindTransactionResponse.java @@ -1,9 +1,18 @@ package jota.dto.response; +/** + * Response of {@link jota.dto.request.IotaFindTransactionsRequest} + **/ public class FindTransactionResponse extends AbstractResponse { String[] hashes; + + /** + * Gets the hashes. + * + * @return The hashes. + */ public String[] getHashes() { return hashes; } diff --git a/src/main/java/jota/dto/response/GetAttachToTangleResponse.java b/src/main/java/jota/dto/response/GetAttachToTangleResponse.java index 8b70851..7b44506 100644 --- a/src/main/java/jota/dto/response/GetAttachToTangleResponse.java +++ b/src/main/java/jota/dto/response/GetAttachToTangleResponse.java @@ -1,14 +1,25 @@ package jota.dto.response; +/** + * Response of {@link jota.dto.request.IotaAttachToTangleRequest} + **/ public class GetAttachToTangleResponse extends AbstractResponse { private String[] trytes; - public String[] getTrytes() { - return trytes; - } - + /** + * Initializes a new instance of the GetAttachToTangleResponse class. + */ public GetAttachToTangleResponse(long duration) { setDuration(duration); } + + /** + * Gets the rytes. + * + * @return The trytes. + */ + public String[] getTrytes() { + return trytes; + } } diff --git a/src/main/java/jota/dto/response/GetBalancesAndFormatResponse.java b/src/main/java/jota/dto/response/GetBalancesAndFormatResponse.java index 189e72e..d118c96 100644 --- a/src/main/java/jota/dto/response/GetBalancesAndFormatResponse.java +++ b/src/main/java/jota/dto/response/GetBalancesAndFormatResponse.java @@ -1,30 +1,20 @@ package jota.dto.response; -import java.util.List; - import jota.model.Input; +import java.util.List; + +/** + * Response of api request 'getBalancesAndFormatResponse' + **/ public class GetBalancesAndFormatResponse extends AbstractResponse { private List input; private long totalBalance; - public List getInput() { - return input; - } - - public void setInput(List input) { - this.input = input; - } - - public long getTotalBalance() { - return totalBalance; - } - - public void setTotalBalance(long totalBalance) { - this.totalBalance = totalBalance; - } - + /** + * Initializes a new instance of the GetBalancesAndFormatResponse class. + */ public static GetBalancesAndFormatResponse create(List inputs, long totalBalance2, long duration) { GetBalancesAndFormatResponse res = new GetBalancesAndFormatResponse(); res.setInput(inputs); @@ -32,4 +22,40 @@ public class GetBalancesAndFormatResponse extends AbstractResponse { res.setDuration(duration); return res; } + + /** + * Gets the input. + * + * @return The transactions. + */ + public List getInput() { + return input; + } + + /** + * Sets the input. + * + * @param input The input. + */ + public void setInput(List input) { + this.input = input; + } + + /** + * Gets the total balance. + * + * @return The total balance. + */ + public long getTotalBalance() { + return totalBalance; + } + + /** + * Sets the total balance. + * + * @param totalBalance The total balance. + */ + public void setTotalBalance(long totalBalance) { + this.totalBalance = totalBalance; + } } diff --git a/src/main/java/jota/dto/response/GetBalancesResponse.java b/src/main/java/jota/dto/response/GetBalancesResponse.java index 0637f61..b295bde 100644 --- a/src/main/java/jota/dto/response/GetBalancesResponse.java +++ b/src/main/java/jota/dto/response/GetBalancesResponse.java @@ -1,19 +1,37 @@ package jota.dto.response; +/** + * Response of {@link jota.dto.request.IotaGetBalancesRequest} + **/ public class GetBalancesResponse extends AbstractResponse { private String[] balances; private String milestone; private int milestoneIndex; + /** + * Gets the milestone index. + * + * @return The milestone index. + */ public int getMilestoneIndex() { return milestoneIndex; } + /** + * Gets the milestone. + * + * @return The milestone. + */ public String getMilestone() { return milestone; } + /** + * Gets the balances. + * + * @return The balances. + */ public String[] getBalances() { return balances; } diff --git a/src/main/java/jota/dto/response/GetBundleResponse.java b/src/main/java/jota/dto/response/GetBundleResponse.java index c3dfa1b..c32659d 100644 --- a/src/main/java/jota/dto/response/GetBundleResponse.java +++ b/src/main/java/jota/dto/response/GetBundleResponse.java @@ -5,10 +5,16 @@ import jota.model.Transaction; import java.util.ArrayList; import java.util.List; +/** + * Response of api request 'getBundle + **/ public class GetBundleResponse extends AbstractResponse { private List transactions = new ArrayList<>(); + /** + * Initializes a new instance of the GetBundleResponse class. + */ public static GetBundleResponse create(List transactions, long duration) { GetBundleResponse res = new GetBundleResponse(); res.transactions = transactions; @@ -16,7 +22,11 @@ public class GetBundleResponse extends AbstractResponse { return res; } - + /** + * Gets the transactions. + * + * @return The transactions. + */ public List getTransactions() { return transactions; } diff --git a/src/main/java/jota/dto/response/GetInclusionStateResponse.java b/src/main/java/jota/dto/response/GetInclusionStateResponse.java index 5b60af9..e73e725 100644 --- a/src/main/java/jota/dto/response/GetInclusionStateResponse.java +++ b/src/main/java/jota/dto/response/GetInclusionStateResponse.java @@ -1,9 +1,17 @@ package jota.dto.response; +/** + * Response of {@link jota.dto.request.IotaGetInclusionStateRequest} + **/ public class GetInclusionStateResponse extends AbstractResponse { - boolean[] states; + private boolean[] states; + /** + * Gets the states. + * + * @return The states. + */ public boolean[] getStates() { return states; } diff --git a/src/main/java/jota/dto/response/GetMilestoneResponse.java b/src/main/java/jota/dto/response/GetMilestoneResponse.java deleted file mode 100644 index 7e3ecbe..0000000 --- a/src/main/java/jota/dto/response/GetMilestoneResponse.java +++ /dev/null @@ -1,10 +0,0 @@ -package jota.dto.response; - -public class GetMilestoneResponse extends AbstractResponse { - - private String milestone; - - public String getMilestone() { - return milestone; - } -} diff --git a/src/main/java/jota/dto/response/GetNeighborsResponse.java b/src/main/java/jota/dto/response/GetNeighborsResponse.java index 3740307..14fcb64 100644 --- a/src/main/java/jota/dto/response/GetNeighborsResponse.java +++ b/src/main/java/jota/dto/response/GetNeighborsResponse.java @@ -5,10 +5,18 @@ import jota.model.Neighbor; import java.util.ArrayList; import java.util.List; +/** + * Response of {@link jota.dto.request.IotaCommandRequest} + **/ public class GetNeighborsResponse extends AbstractResponse { private List neighbors = new ArrayList<>(); + /** + * Gets the neighbors. + * + * @return The neighbors. + */ public List getNeighbors() { return neighbors; } diff --git a/src/main/java/jota/dto/response/GetNewAddressResponse.java b/src/main/java/jota/dto/response/GetNewAddressResponse.java index 42d2288..24ef29b 100644 --- a/src/main/java/jota/dto/response/GetNewAddressResponse.java +++ b/src/main/java/jota/dto/response/GetNewAddressResponse.java @@ -2,10 +2,16 @@ package jota.dto.response; import java.util.List; +/** + * Response of api request 'getNewAddress' + **/ public class GetNewAddressResponse extends AbstractResponse { private List addresses; + /** + * Initializes a new instance of the GetNewAddressResponse class. + */ public static GetNewAddressResponse create(List addresses, long duration) { GetNewAddressResponse res = new GetNewAddressResponse(); res.addresses = addresses; @@ -13,6 +19,11 @@ public class GetNewAddressResponse extends AbstractResponse { return res; } + /** + * Gets the addresses. + * + * @return The addresses. + */ public List getAddresses() { return addresses; } diff --git a/src/main/java/jota/dto/response/GetNodeInfoResponse.java b/src/main/java/jota/dto/response/GetNodeInfoResponse.java index 233c0fb..acf72c2 100644 --- a/src/main/java/jota/dto/response/GetNodeInfoResponse.java +++ b/src/main/java/jota/dto/response/GetNodeInfoResponse.java @@ -1,5 +1,8 @@ package jota.dto.response; +/** + * Response of {@link jota.dto.request.IotaNeighborsRequest} + **/ public class GetNodeInfoResponse extends AbstractResponse { private String appName; @@ -19,66 +22,148 @@ public class GetNodeInfoResponse extends AbstractResponse { private int tips; private int transactionsToRequest; + /** + * Name of the IOTA software you're currently using (IRI stands for Initial Reference Implementation). + * + * @return appName + */ public String getAppName() { return appName; } + /** + * The version of the IOTA software you're currently running. + * + * @return The version of the IOTA software you're currently running. + */ public String getAppVersion() { return appVersion; } + /** + * The version of running java version. + * + * @return The version of running java version. + */ public String getJreVersion() { return jreVersion; } + /** + * Available cores on your machine for JRE. + * + * @return Available cores on your machine for JRE. + */ public Integer getJreAvailableProcessors() { return jreAvailableProcessors; } + /** + * The amount of free memory in the Java Virtual Machine. + * + * @return The amount of free memory in the Java Virtual Machine. + */ public long getJreFreeMemory() { return jreFreeMemory; } + /** + * The maximum amount of memory that the Java virtual machine will attempt to use. + * + * @return The maximum amount of memory that the Java virtual machine will attempt to use. + */ public long getJreMaxMemory() { return jreMaxMemory; } + /** + * The total amount of memory in the Java virtual machine. + * + * @return The total amount of memory in the Java virtual machine. + */ public long getJreTotalMemory() { return jreTotalMemory; } + /** + * Latest milestone that was signed off by the coordinator. + * + * @return Latest milestone that was signed off by the coordinator. + */ public String getLatestMilestone() { return latestMilestone; } + /** + * Index of the latest milestone. + * + * @return Index of the latest milestone. + */ public int getLatestMilestoneIndex() { return latestMilestoneIndex; } + /** + * 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, + * and have a consistent view of all referenced transactions. + * + * @return The latest milestone which is solid and is used for sending transactions. + */ public String getLatestSolidSubtangleMilestone() { return latestSolidSubtangleMilestone; } + /** + * Index of the latest solid subtangle. + * + * @return Index of the latest solid subtangle. + */ public int getLatestSolidSubtangleMilestoneIndex() { return latestSolidSubtangleMilestoneIndex; } + /** + * Number of neighbors you are directly connected with. + * + * @return Number of neighbors you are directly connected with. + */ public int getNeighbors() { return neighbors; } + /** + * Packets which are currently queued up. + * + * @return Packets which are currently queued up. + */ public int getPacketsQueueSize() { return packetsQueueSize; } + /** + * Current UNIX timestamp. + * + * @return Current UNIX timestamp. + */ public Long getTime() { return time; } + /** + * Number of tips in the network. + * + * @return Number of tips in the network. + */ public int getTips() { return tips; } + /** + * Transactions to request during syncing process. + * + * @return Transactions to request during syncing process. + */ public int getTransactionsToRequest() { return transactionsToRequest; } diff --git a/src/main/java/jota/dto/response/GetTipsResponse.java b/src/main/java/jota/dto/response/GetTipsResponse.java index e45fb7e..0054563 100644 --- a/src/main/java/jota/dto/response/GetTipsResponse.java +++ b/src/main/java/jota/dto/response/GetTipsResponse.java @@ -1,9 +1,17 @@ package jota.dto.response; +/** + * Response of {@link jota.dto.request.IotaCommandRequest} + **/ public class GetTipsResponse extends AbstractResponse { private String[] hashes; + /** + * Gets the hashes. + * + * @return The hashes. + */ public String[] getHashes() { return hashes; } diff --git a/src/main/java/jota/dto/response/GetTransactionsToApproveResponse.java b/src/main/java/jota/dto/response/GetTransactionsToApproveResponse.java index ba7d478..2aa3adc 100644 --- a/src/main/java/jota/dto/response/GetTransactionsToApproveResponse.java +++ b/src/main/java/jota/dto/response/GetTransactionsToApproveResponse.java @@ -1,14 +1,27 @@ package jota.dto.response; +/** + * Response of {@link jota.dto.request.IotaGetTransactionsToApproveRequest} + **/ public class GetTransactionsToApproveResponse extends AbstractResponse { private String trunkTransaction; private String branchTransaction; + /** + * Gets the trunk transaction. + * + * @return The trunk transaction. + */ public String getTrunkTransaction() { return trunkTransaction; } + /** + * Gets the branch transaction. + * + * @return The branch transaction. + */ public String getBranchTransaction() { return branchTransaction; } diff --git a/src/main/java/jota/dto/response/GetTransferResponse.java b/src/main/java/jota/dto/response/GetTransferResponse.java index e98251e..8f143ed 100644 --- a/src/main/java/jota/dto/response/GetTransferResponse.java +++ b/src/main/java/jota/dto/response/GetTransferResponse.java @@ -3,19 +3,27 @@ package jota.dto.response; import jota.model.Bundle; /** - * Created by pinpong on 28.12.16. - */ -public class GetTransferResponse extends AbstractResponse { + * Response of api request 'getTransfer' + **/ +public class GetTransferResponse extends AbstractResponse { private Bundle[] transferBundle; + /** + * Initializes a new instance of the GetTransferResponse class. + */ public static GetTransferResponse create(Bundle[] transferBundle, long duration) { GetTransferResponse res = new GetTransferResponse(); res.transferBundle = transferBundle; return res; } - public Bundle[] getTransfers() { + /** + * Gets the transfer bundle. + * + * @return The transfer bundle. + */ + public Bundle[] getTransfers() { return transferBundle; } } diff --git a/src/main/java/jota/dto/response/GetTrytesResponse.java b/src/main/java/jota/dto/response/GetTrytesResponse.java index e745caa..7af55c8 100644 --- a/src/main/java/jota/dto/response/GetTrytesResponse.java +++ b/src/main/java/jota/dto/response/GetTrytesResponse.java @@ -1,9 +1,17 @@ package jota.dto.response; +/** + * Response of {@link jota.dto.request.IotaGetTrytesRequest} + **/ public class GetTrytesResponse extends AbstractResponse { private String[] trytes; + /** + * Gets the trytes. + * + * @return The trytes. + */ public String[] getTrytes() { return trytes; } diff --git a/src/main/java/jota/dto/response/InterruptAttachingToTangleResponse.java b/src/main/java/jota/dto/response/InterruptAttachingToTangleResponse.java index c3dda35..ab0400d 100644 --- a/src/main/java/jota/dto/response/InterruptAttachingToTangleResponse.java +++ b/src/main/java/jota/dto/response/InterruptAttachingToTangleResponse.java @@ -1,5 +1,8 @@ package jota.dto.response; +/** + * Response of {@link jota.dto.request.IotaCommandRequest} + **/ public class InterruptAttachingToTangleResponse extends AbstractResponse { // empty response } diff --git a/src/main/java/jota/dto/response/RemoveNeighborsResponse.java b/src/main/java/jota/dto/response/RemoveNeighborsResponse.java index 3f63730..24bd67b 100644 --- a/src/main/java/jota/dto/response/RemoveNeighborsResponse.java +++ b/src/main/java/jota/dto/response/RemoveNeighborsResponse.java @@ -1,9 +1,17 @@ package jota.dto.response; +/** + * Response of {@link jota.dto.request.IotaNeighborsRequest} + **/ public class RemoveNeighborsResponse extends AbstractResponse { private int removedNeighbors; + /** + * Gets the number of removed neighbors. + * + * @return The number of removed neighbors. + */ public int getRemovedNeighbors() { return removedNeighbors; } diff --git a/src/main/java/jota/dto/response/ReplayBundleResponse.java b/src/main/java/jota/dto/response/ReplayBundleResponse.java index 2c60c6c..5141de1 100644 --- a/src/main/java/jota/dto/response/ReplayBundleResponse.java +++ b/src/main/java/jota/dto/response/ReplayBundleResponse.java @@ -1,12 +1,15 @@ package jota.dto.response; /** - * Created by pinpong on 01.01.17. - */ + * Response of api request 'replayBundle' + **/ public class ReplayBundleResponse extends AbstractResponse { private Boolean[] successfully; + /** + * Initializes a new instance of the ReplayBundleResponse class. + */ public static ReplayBundleResponse create(Boolean[] successfully, long duration) { ReplayBundleResponse res = new ReplayBundleResponse(); res.successfully = successfully; @@ -14,10 +17,20 @@ public class ReplayBundleResponse extends AbstractResponse { return res; } + /** + * Gets the successfully. + * + * @return The successfully. + */ public Boolean[] getSuccessfully() { return successfully; } + /** + * Sets the successfully. + * + * @param successfully The successfully. + */ public void setSuccessfully(Boolean[] successfully) { this.successfully = successfully; } diff --git a/src/main/java/jota/dto/response/SendTransferResponse.java b/src/main/java/jota/dto/response/SendTransferResponse.java index d31b295..109aecd 100644 --- a/src/main/java/jota/dto/response/SendTransferResponse.java +++ b/src/main/java/jota/dto/response/SendTransferResponse.java @@ -1,12 +1,15 @@ package jota.dto.response; /** - * Created by pinpong on 28.12.16. - */ + * Response of api request 'sendTransfer' + **/ public class SendTransferResponse extends AbstractResponse { private Boolean[] successfully; + /** + * Initializes a new instance of the SendTransferResponse class. + */ public static SendTransferResponse create(Boolean[] successfully, long duration) { SendTransferResponse res = new SendTransferResponse(); res.successfully = successfully; @@ -14,10 +17,20 @@ public class SendTransferResponse extends AbstractResponse { return res; } + /** + * Gets the successfully. + * + * @return The successfully. + */ public Boolean[] getSuccessfully() { return successfully; } + /** + * Sets the successfully. + * + * @param successfully The successfully. + */ public void setSuccessfully(Boolean[] successfully) { this.successfully = successfully; } diff --git a/src/main/java/jota/dto/response/StoreTransactionsResponse.java b/src/main/java/jota/dto/response/StoreTransactionsResponse.java index af6c773..518d1f5 100644 --- a/src/main/java/jota/dto/response/StoreTransactionsResponse.java +++ b/src/main/java/jota/dto/response/StoreTransactionsResponse.java @@ -1,6 +1,13 @@ package jota.dto.response; +/** + * Response of {@link jota.dto.request.IotaStoreTransactionsRequest} + **/ public class StoreTransactionsResponse extends AbstractResponse { + + /** + * Initializes a new instance of the StoreTransactionsResponse class. + */ public StoreTransactionsResponse(long duration) { setDuration(duration); } diff --git a/src/main/java/jota/error/ArgumentException.java b/src/main/java/jota/error/ArgumentException.java index 075d90e..28fe374 100644 --- a/src/main/java/jota/error/ArgumentException.java +++ b/src/main/java/jota/error/ArgumentException.java @@ -1,16 +1,27 @@ package jota.error; /** - * Created by Adrian on 09.12.2016. + * This exception occurs when an invalid argument is provided. + * + * @author Adrian */ public class ArgumentException extends BaseException { + /** + * Serial version UID + */ private static final long serialVersionUID = -7850044681919575720L; + /** + * Initializes a new instance of the ArgumentException. + */ public ArgumentException() { super("Wrong arguments passed to function"); } + /** + * Initializes a new instance of the ArgumentException. + */ public ArgumentException(String msg) { super(msg); } diff --git a/src/main/java/jota/error/BaseException.java b/src/main/java/jota/error/BaseException.java index 972a0ac..b1f91cc 100644 --- a/src/main/java/jota/error/BaseException.java +++ b/src/main/java/jota/error/BaseException.java @@ -5,10 +5,13 @@ import java.util.Arrays; import java.util.Collection; /** - * Created by Adrian on 09.12.2016. + * @author Adrian */ public class BaseException extends Exception { + /** + * Serial version UID + */ private static final long serialVersionUID = 5617085097507773343L; protected Collection messages; diff --git a/src/main/java/jota/error/BroadcastAndStoreException.java b/src/main/java/jota/error/BroadcastAndStoreException.java index a5b58e6..8ad2c20 100644 --- a/src/main/java/jota/error/BroadcastAndStoreException.java +++ b/src/main/java/jota/error/BroadcastAndStoreException.java @@ -1,10 +1,15 @@ package jota.error; /** - * Created by Adrian on 22.01.2017. + * 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."); } diff --git a/src/main/java/jota/error/InvalidAddressException.java b/src/main/java/jota/error/InvalidAddressException.java new file mode 100644 index 0000000..9c6b591 --- /dev/null +++ b/src/main/java/jota/error/InvalidAddressException.java @@ -0,0 +1,16 @@ +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/src/main/java/jota/error/InvalidBundleException.java b/src/main/java/jota/error/InvalidBundleException.java index 9f7877d..55da93b 100644 --- a/src/main/java/jota/error/InvalidBundleException.java +++ b/src/main/java/jota/error/InvalidBundleException.java @@ -1,15 +1,23 @@ package jota.error; /** - * Created by Adrian on 27.12.2016. + * This exceptions occurs if an invalid bundle was found or provided. + * + * @author Adrian */ public class InvalidBundleException extends BaseException { - public InvalidBundleException(){ + /** + * Initializes a new instance of the InvalidBundleException. + */ + public InvalidBundleException() { super("Invalid Bundle"); } - public InvalidBundleException(String msg){ + /** + * Initializes a new instance of the InvalidBundleException. + */ + public InvalidBundleException(String msg) { super(msg); } } diff --git a/src/main/java/jota/error/InvalidSecurityLevelException.java b/src/main/java/jota/error/InvalidSecurityLevelException.java new file mode 100644 index 0000000..b48e6af --- /dev/null +++ b/src/main/java/jota/error/InvalidSecurityLevelException.java @@ -0,0 +1,16 @@ +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/src/main/java/jota/error/InvalidSignatureException.java b/src/main/java/jota/error/InvalidSignatureException.java index d8d5565..79944ea 100644 --- a/src/main/java/jota/error/InvalidSignatureException.java +++ b/src/main/java/jota/error/InvalidSignatureException.java @@ -1,9 +1,15 @@ package jota.error; /** - * Created by Adrian on 27.12.2016. + * 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/src/main/java/jota/error/InvalidTransferException.java b/src/main/java/jota/error/InvalidTransferException.java new file mode 100644 index 0000000..0da3d9b --- /dev/null +++ b/src/main/java/jota/error/InvalidTransferException.java @@ -0,0 +1,16 @@ +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/src/main/java/jota/error/InvalidTrytesException.java b/src/main/java/jota/error/InvalidTrytesException.java new file mode 100644 index 0000000..de97ff0 --- /dev/null +++ b/src/main/java/jota/error/InvalidTrytesException.java @@ -0,0 +1,16 @@ +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/src/main/java/jota/error/NoInclusionStatesException.java b/src/main/java/jota/error/NoInclusionStatesException.java new file mode 100644 index 0000000..65dd2d4 --- /dev/null +++ b/src/main/java/jota/error/NoInclusionStatesException.java @@ -0,0 +1,16 @@ +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/src/main/java/jota/error/NoInclusionStatesExcpection.java b/src/main/java/jota/error/NoInclusionStatesExcpection.java deleted file mode 100644 index c79ee4b..0000000 --- a/src/main/java/jota/error/NoInclusionStatesExcpection.java +++ /dev/null @@ -1,11 +0,0 @@ -package jota.error; - -/** - * Created by Adrian on 22.01.2017. - */ -public class NoInclusionStatesExcpection extends BaseException { - - public NoInclusionStatesExcpection() { - super("No inclusion states for the provided seed"); - } -} diff --git a/src/main/java/jota/error/NoNodeInfoException.java b/src/main/java/jota/error/NoNodeInfoException.java index 920c6f3..fba5f37 100644 --- a/src/main/java/jota/error/NoNodeInfoException.java +++ b/src/main/java/jota/error/NoNodeInfoException.java @@ -1,10 +1,15 @@ package jota.error; /** - * Created by Adrian on 22.01.2017. + * 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"); } diff --git a/src/main/java/jota/error/NotEnoughBalanceException.java b/src/main/java/jota/error/NotEnoughBalanceException.java index 64c516c..3abe9f8 100644 --- a/src/main/java/jota/error/NotEnoughBalanceException.java +++ b/src/main/java/jota/error/NotEnoughBalanceException.java @@ -1,12 +1,20 @@ package jota.error; /** - * Created by Adrian on 09.12.2016. + * 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/src/main/java/jota/model/Bundle.java b/src/main/java/jota/model/Bundle.java index 93acfae..1de54f6 100644 --- a/src/main/java/jota/model/Bundle.java +++ b/src/main/java/jota/model/Bundle.java @@ -8,49 +8,86 @@ import org.apache.commons.lang3.StringUtils; import java.util.ArrayList; import java.util.List; + /** - * Created by pinpong on 09.12.16. - */ + * This class represents a Bundle, a set of transactions. + * + * @author pinpong + **/ public class Bundle implements Comparable { + public static String EMPTY_HASH = "999999999999999999999999999999999999999999999999999999999999999999999999999999999"; private List transactions; private int length; - public static String EMPTY_HASH = "999999999999999999999999999999999999999999999999999999999999999999999999999999999"; - + /** + * Initializes a new instance of the Bundle class without transactions. + */ public Bundle() { this(new ArrayList(), 0); } + /** + * Initializes a new instance of the Bundle class. + */ public Bundle(List transactions, int length) { this.transactions = transactions; this.length = length; } + /** + * Gets the transactions + * + * @return transactions The transactions. + */ public List getTransactions() { return transactions; } + /** + * Gets the length of the bundle + * + * @return length The length. + */ public int getLength() { return length; } + /** + * Sets the length of the bundle + * + * @param length The length. + */ public void setLength(int length) { this.length = length; } + /** + * Adds a bundle entry. + * + * @param signatureMessageLength Length of the signature message. + * @param address The address. + * @param value The value. + * @param tag The tag. + * @param timestamp The timestamp. + */ public void addEntry(int signatureMessageLength, String address, long value, String tag, long timestamp) { if (getTransactions() == null) { this.transactions = new ArrayList<>(getTransactions()); } for (int i = 0; i < signatureMessageLength; i++) { - Transaction trx = new Transaction(address, String.valueOf(i == 0 ? value : 0), tag, String.valueOf(timestamp)); - getTransactions().add(trx); + Transaction trx = new Transaction(address, i == 0 ? value : 0, tag, timestamp); + transactions.add(trx); } } + /** + * Finalizes the bundle using the specified curl implementation, + * + * @param customCurl The custom curl. + */ public void finalize(ICurl customCurl) { ICurl curl = customCurl == null ? new JCurl() : customCurl; @@ -62,10 +99,13 @@ public class Bundle implements Comparable { int[] timestampTrits = Converter.trits(this.getTransactions().get(i).getTimestamp(), 27); - int[] currentIndexTrits = Converter.trits(this.getTransactions().get(i).setCurrentIndex("" + i), 27); + this.getTransactions().get(i).setCurrentIndex(i); - int[] lastIndexTrits = Converter.trits(this.getTransactions().get(i).setLastIndex("" + (this.getTransactions().size() - 1)), 27); + int[] currentIndexTrits = Converter.trits(this.getTransactions().get(i).getCurrentIndex(), 27); + this.getTransactions().get(i).setLastIndex(this.getTransactions().size() - 1); + + int[] lastIndexTrits = Converter.trits(this.getTransactions().get(i).getLastIndex(), 27); int[] t = Converter.trits(this.getTransactions().get(i).getAddress() + Converter.trytes(valueTrits) + this.getTransactions().get(i).getTag() + Converter.trytes(timestampTrits) + Converter.trytes(currentIndexTrits) + Converter.trytes(lastIndexTrits)); curl.absorb(t, 0, t.length); @@ -80,7 +120,11 @@ public class Bundle implements Comparable { } } - + /** + * Adds the trytes. + * + * @param signatureFragments The signature fragments. + */ public void addTrytes(List signatureFragments) { String emptySignatureFragment = ""; String emptyHash = EMPTY_HASH; @@ -102,6 +146,13 @@ public class Bundle implements Comparable { } } + + /** + * Normalized the bundle. + * + * @param bundleHash The bundle hash. + * @return normalizedBundle A normalized bundle hash. + */ public int[] normalizedBundle(String bundleHash) { int[] normalizedBundle = new int[81]; @@ -140,8 +191,15 @@ public class Bundle implements Comparable { return normalizedBundle; } + + /** + * Compares the current object with another object of the same type. + * + * @param o An object to compare with this object. + * @return A value that indicates the relative order of the objects being compared. The return value has the following meanings: Value Meaning Less than zero This object is less than the parameter.Zero This object is equal to . Greater than zero This object is greater than . + */ @Override public int compareTo(Bundle o) { - return Long.compare(Long.parseLong(this.getTransactions().get(0).getTimestamp()), Long.parseLong(o.getTransactions().get(0).getTimestamp())); + return Long.compare(this.getTransactions().get(0).getTimestamp(), o.getTransactions().get(0).getTimestamp()); } } \ No newline at end of file diff --git a/src/main/java/jota/model/Input.java b/src/main/java/jota/model/Input.java index 16ce445..0e33c38 100644 --- a/src/main/java/jota/model/Input.java +++ b/src/main/java/jota/model/Input.java @@ -4,45 +4,107 @@ import org.apache.commons.lang3.builder.ToStringBuilder; import org.apache.commons.lang3.builder.ToStringStyle; /** - * Created by Adrian on 09.12.2016. - */ + * This class represents an Input. + * + * @author Adrian + **/ public class Input { + private String address; private long balance; private int keyIndex; + private int security; - public Input(String address, long balance, int keyIndex) { + /** + * Initializes a new instance of the Input class. + */ + public Input(String address, long balance, int keyIndex, int security) { this.address = address; this.balance = balance; this.keyIndex = keyIndex; + this.security = security; + } + /** + * Returns a String that represents this object. + * + * @return Returns a string representation of this object. + */ @Override public String toString() { return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE); } + /** + * Get the address. + * + * @return The address. + */ public String getAddress() { return address; } + /** + * Get the address. + * + * @param address The address. + */ public void setAddress(String address) { this.address = address; } + /** + * Get the balance. + * + * @return The balance. + */ public long getBalance() { return balance; } + /** + * Get the balance. + * + * @param balance The balance. + */ public void setBalance(long balance) { this.balance = balance; } + /** + * Get the keyIndex. + * + * @return The keyIndex. + */ public int getKeyIndex() { return keyIndex; } + /** + * Get the keyIndex. + * + * @param keyIndex The keyIndex. + */ public void setKeyIndex(int keyIndex) { this.keyIndex = keyIndex; } + + /** + * Get the security. + * + * @return The security. + */ + public int getSecurity() { + return security; + } + + /** + * Get the security. + * + * @param security The security. + */ + public void setSecurity(int security) { + this.security = security; + } } \ No newline at end of file diff --git a/src/main/java/jota/model/Inputs.java b/src/main/java/jota/model/Inputs.java index 5d4b993..8d142e1 100644 --- a/src/main/java/jota/model/Inputs.java +++ b/src/main/java/jota/model/Inputs.java @@ -5,34 +5,65 @@ import com.google.gson.Gson; import java.util.List; /** - * Created by Adrian on 09.12.2016. - */ + * This class represents an Inputs. + * + * @author Adrian + **/ public class Inputs { + private List inputsList; private long totalBalance; + /** + * Initializes a new instance of the Input class. + */ public Inputs(List inputsList, long totalBalance) { this.inputsList = inputsList; this.totalBalance = totalBalance; } + /** + * Returns a Json Object that represents this object. + * + * @return Returns a string representation of this object. + */ @Override public String toString() { return new Gson().toJson(this); } + /** + * Get the input list. + * + * @return The input list. + */ public List getInputsList() { return inputsList; } + /** + * Set the input list. + * + * @param inputsList The input list. + */ public void setInputsList(List inputsList) { inputsList = inputsList; } + /** + * Get the total balance. + * + * @return The total balance. + */ public long getTotalBalance() { return totalBalance; } + /** + * Set the total balance. + * + * @param totalBalance The total balance. + */ public void setTotalBalance(long totalBalance) { this.totalBalance = totalBalance; } diff --git a/src/main/java/jota/model/Neighbor.java b/src/main/java/jota/model/Neighbor.java index 2eee719..9937bc0 100644 --- a/src/main/java/jota/model/Neighbor.java +++ b/src/main/java/jota/model/Neighbor.java @@ -1,8 +1,10 @@ package jota.model; /** - * Created by pinpong on 02.12.16. - */ + * This class represents an Neighbor. + * + * @author pinpong + **/ public class Neighbor { private String address; @@ -10,6 +12,9 @@ public class Neighbor { private Integer numberOfInvalidTransactions; private Integer numberOfNewTransactions; + /** + * Initializes a new instance of the Neighbor class. + */ public Neighbor(String address, Integer numberOfAllTransactions, Integer numberOfInvalidTransactions, Integer numberOfNewTransactions) { this.address = address; this.numberOfAllTransactions = numberOfAllTransactions; @@ -17,18 +22,38 @@ public class Neighbor { this.numberOfNewTransactions = numberOfNewTransactions; } + /** + * Get the address. + * + * @return The address. + */ public String getAddress() { return address; } + /** + * Get the number of all transactions. + * + * @return The number of all transactions. + */ public Integer getNumberOfAllTransactions() { return numberOfAllTransactions; } + /** + * Get the number of invalid transactions. + * + * @return The number of invalid transactions. + */ public Integer getNumberOfInvalidTransactions() { return numberOfInvalidTransactions; } + /** + * Get the number of nwe transactions. + * + * @return The number of new transactions. + */ public Integer getNumberOfNewTransactions() { return numberOfNewTransactions; } diff --git a/src/main/java/jota/model/Signature.java b/src/main/java/jota/model/Signature.java index 3e0a9ba..02f9b01 100644 --- a/src/main/java/jota/model/Signature.java +++ b/src/main/java/jota/model/Signature.java @@ -4,29 +4,54 @@ import java.util.ArrayList; import java.util.List; /** - * Created by Adrian on 27.12.2016. - */ + * This class represents an Signature. + * + * @author Adrian + **/ public class Signature { - String address; - List signatureFragments; + private String address; + private List signatureFragments; + /** + * Initializes a new instance of the Signature class. + */ public Signature() { this.signatureFragments = new ArrayList<>(); } + /** + * Get the address. + * + * @return The address. + */ public String getAddress() { return address; } + /** + * Set the address. + * + * @param address The address. + */ public void setAddress(String address) { this.address = address; } + /** + * Get the signatureFragments. + * + * @return The signatureFragments. + */ public List getSignatureFragments() { return signatureFragments; } + /** + * Set the signatureFragments. + * + * @param signatureFragments The signatureFragments. + */ public void setSignatureFragments(List signatureFragments) { this.signatureFragments = signatureFragments; } diff --git a/src/main/java/jota/model/Transaction.java b/src/main/java/jota/model/Transaction.java index dbe0506..4b70683 100644 --- a/src/main/java/jota/model/Transaction.java +++ b/src/main/java/jota/model/Transaction.java @@ -12,44 +12,62 @@ import org.slf4j.LoggerFactory; import java.util.Arrays; /** - * Created by pinpong on 02.12.16. + * This class represents an iota transaction. + * + * @author pinpong */ public class Transaction { + private static final Logger log = LoggerFactory.getLogger(Transaction.class); private ICurl customCurl; private String hash; private String signatureFragments; private String address; - private String value; + private long value; private String tag; - private String timestamp; - private String currentIndex; - private String lastIndex; + private long timestamp; + private long currentIndex; + private long lastIndex; private String bundle; private String trunkTransaction; private String branchTransaction; private String nonce; private Boolean persistence; + /** + * Initializes a new instance of the Signature class. + */ public Transaction(ICurl curl) { customCurl = curl; } + /** + * Initializes a new instance of the Signature class. + */ public Transaction() { customCurl = null; } + /** + * Initializes a new instance of the Signature class. + */ public Transaction(String trytes) { transactionObject(trytes); } + /** + * Initializes a new instance of the Signature class. + */ public Transaction(String trytes, ICurl customCurl) { transactionObject(trytes); this.customCurl = customCurl; } - public Transaction(String signatureFragments, String currentIndex, String lastIndex, String nonce, String hash, String tag, String timestamp, String trunkTransaction, String branchTransaction, String address, String value, String bundle) { + /** + * Initializes a new instance of the Signature class. + */ + public Transaction(String signatureFragments, long currentIndex, long lastIndex, String nonce, String hash, String tag, long timestamp, String trunkTransaction, String branchTransaction, String address, long value, String bundle) { this.hash = hash; this.tag = tag; @@ -65,119 +83,256 @@ public class Transaction { this.nonce = nonce; } - - public Transaction(String address, String value, String tag, String timestamp) { + /** + * Initializes a new instance of the Signature class. + */ + public Transaction(String address, long value, String tag, long timestamp) { this.address = address; this.value = value; this.tag = tag; this.timestamp = timestamp; } + /** + * Returns a String that represents this object. + * + * @return Returns a string representation of this object. + */ @Override public String toString() { return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE); } + /** + * Get the hash. + * + * @return The hash. + */ public String getHash() { return hash; } + /** + * Set the hash. + * + * @param hash The hash. + */ public void setHash(String hash) { this.hash = hash; } + /** + * Get the signature fragments. + * + * @return The signature fragments. + */ public String getSignatureFragments() { return signatureFragments; } - public String setSignatureFragments(String signatureFragments) { - return this.signatureFragments = signatureFragments; + /** + * Set the signature fragments. + * + * @param signatureFragments The signature fragments. + */ + public void setSignatureFragments(String signatureFragments) { + this.signatureFragments = signatureFragments; } + /** + * Get the address. + * + * @return The address. + */ public String getAddress() { return address; } + /** + * Set the address. + * + * @param address The address. + */ public void setAddress(String address) { this.address = address; } - public String getValue() { + /** + * Get the value. + * + * @return The value. + */ + public long getValue() { return value; } - public void setValue(String value) { + /** + * Set the value. + * + * @param value The value. + */ + public void setValue(long value) { this.value = value; } + /** + * Get the tag. + * + * @return The tag. + */ public String getTag() { return tag; } + /** + * Set the tag. + * + * @param tag The tag. + */ public void setTag(String tag) { this.tag = tag; } - public String getTimestamp() { + /** + * Get the timestamp. + * + * @return The timestamp. + */ + public long getTimestamp() { return timestamp; } - public void setTimestamp(String timestamp) { + /** + * Set the timestamp. + * + * @param timestamp The timestamp. + */ + public void setTimestamp(long timestamp) { this.timestamp = timestamp; } - public String getCurrentIndex() { + /** + * Get the current index. + * + * @return The current index. + */ + public long getCurrentIndex() { return currentIndex; } - public String setCurrentIndex(String currentIndex) { - return this.currentIndex = currentIndex; + /** + * Set the current index. + * + * @param currentIndex The current index. + */ + public void setCurrentIndex(long currentIndex) { + this.currentIndex = currentIndex; } - public String getLastIndex() { + /** + * Get the last index. + * + * @return The last index. + */ + public long getLastIndex() { return lastIndex; } - public String setLastIndex(String lastIndex) { - return this.lastIndex = lastIndex; + /** + * Set the last index. + * + * @param lastIndex The last index. + */ + public void setLastIndex(long lastIndex) { + this.lastIndex = lastIndex; } + /** + * Get the bundle. + * + * @return The bundle. + */ public String getBundle() { return bundle; } + /** + * Set the bundle. + * + * @param bundle The bundle. + */ public void setBundle(String bundle) { this.bundle = bundle; } + /** + * Get the trunk transaction. + * + * @return The trunk transaction. + */ public String getTrunkTransaction() { return trunkTransaction; } + /** + * Set the trunk transaction. + * + * @param trunkTransaction The trunk transaction. + */ public void setTrunkTransaction(String trunkTransaction) { this.trunkTransaction = trunkTransaction; } + /** + * Get the branch transaction. + * + * @return The branch transaction. + */ public String getBranchTransaction() { return branchTransaction; } + /** + * Set the branch transaction. + * + * @param branchTransaction The branch transaction. + */ public void setBranchTransaction(String branchTransaction) { this.branchTransaction = branchTransaction; } + /** + * Get the nonce. + * + * @return The nonce. + */ public String getNonce() { return nonce; } + /** + * Set the nonce. + * + * @param nonce The trunk nonce. + */ public void setNonce(String nonce) { this.nonce = nonce; } + /** + * Get the persistence. + * + * @return The persistence. + */ public Boolean getPersistence() { return persistence; } + /** + * Set the persistence. + * + * @param persistence The persistence. + */ public void setPersistence(Boolean persistence) { this.persistence = persistence; } @@ -186,6 +341,10 @@ public class Transaction { return obj != null && ((Transaction) obj).getHash().equals(this.getHash()); } + + /** + * Converts the transaction to the corresponding trytes representation + */ public String toTrytes() { int[] valueTrits = Converter.trits(this.getValue(), 81); @@ -211,6 +370,9 @@ public class Transaction { + this.getNonce(); } + /** + * Initializes a new instance of the Signature class. + */ public void transactionObject(final String trytes) { if (StringUtils.isEmpty(trytes)) { @@ -235,15 +397,15 @@ public class Transaction { curl.reset(); curl.absorb(transactionTrits, 0, transactionTrits.length); curl.squeeze(hash, 0, hash.length); - + this.setHash(Converter.trytes(hash)); this.setSignatureFragments(trytes.substring(0, 2187)); this.setAddress(trytes.substring(2187, 2268)); - this.setValue("" + Converter.longValue(Arrays.copyOfRange(transactionTrits, 6804, 6837))); + this.setValue(Converter.longValue(Arrays.copyOfRange(transactionTrits, 6804, 6837))); this.setTag(trytes.substring(2295, 2322)); - this.setTimestamp("" + Converter.longValue(Arrays.copyOfRange(transactionTrits, 6966, 6993))); - this.setCurrentIndex("" + Converter.longValue(Arrays.copyOfRange(transactionTrits, 6993, 7020))); - this.setLastIndex("" + Converter.longValue(Arrays.copyOfRange(transactionTrits, 7020, 7047))); + this.setTimestamp(Converter.longValue(Arrays.copyOfRange(transactionTrits, 6966, 6993))); + this.setCurrentIndex(Converter.longValue(Arrays.copyOfRange(transactionTrits, 6993, 7020))); + this.setLastIndex(Converter.longValue(Arrays.copyOfRange(transactionTrits, 7020, 7047))); this.setBundle(trytes.substring(2349, 2430)); this.setTrunkTransaction(trytes.substring(2430, 2511)); this.setBranchTransaction(trytes.substring(2511, 2592)); diff --git a/src/main/java/jota/model/Transfer.java b/src/main/java/jota/model/Transfer.java index a1b675e..545e6e0 100644 --- a/src/main/java/jota/model/Transfer.java +++ b/src/main/java/jota/model/Transfer.java @@ -3,7 +3,9 @@ package jota.model; import com.google.gson.Gson; /** - * Created by pinpong on 02.12.16. + * This class represents a Transfer. + * + * @author pinpong */ public class Transfer { @@ -15,8 +17,11 @@ public class Transfer { private String message; private String tag; + /** + * Initializes a new instance of the Transfer class. + */ public Transfer(String timestamp, String address, String hash, Boolean persistence, long value, String message, - String tag) { + String tag) { this.timestamp = timestamp; this.address = address; this.hash = hash; @@ -27,6 +32,9 @@ public class Transfer { } + /** + * Initializes a new instance of the Transfer class. + */ public Transfer(String address, long value, String message, String tag) { this.address = address; this.value = value; @@ -34,63 +42,138 @@ public class Transfer { this.tag = tag; } + /** + * Returns a Json Object that represents this object. + * + * @return Returns a string representation of this object. + */ @Override public String toString() { return new Gson().toJson(this); } + /** + * Get the address. + * + * @return The address. + */ public String getAddress() { return address; } - public String getHash() { - return hash; - } - - public Boolean getPersistence() { - return persistence; - } - - public String getTimestamp() { - return timestamp; - } - - public long getValue() { - return value; - } - - public String getMessage() { - return message; - } - - public String getTag() { - return tag; - } - - public void setTimestamp(String timestamp) { - this.timestamp = timestamp; - } - + /** + * Set the address. + * + * @param address The address. + */ public void setAddress(String address) { this.address = address; } + /** + * Get the hash. + * + * @return The hash. + */ + public String getHash() { + return hash; + } + + /** + * Set the hash. + * + * @param hash The hash. + */ public void setHash(String hash) { this.hash = hash; } + /** + * Get the persistence. + * + * @return The persistence. + */ + public Boolean getPersistence() { + return persistence; + } + + /** + * Set the persistence. + * + * @param persistence The persistence. + */ public void setPersistence(Boolean persistence) { this.persistence = persistence; } + /** + * Get the timestamp. + * + * @return The timestamp. + */ + public String getTimestamp() { + return timestamp; + } + + /** + * Set the timestamp. + * + * @param timestamp The timestamp. + */ + public void setTimestamp(String timestamp) { + this.timestamp = timestamp; + } + + /** + * Get the value. + * + * @return The value. + */ + public long getValue() { + return value; + } + + /** + * Set the value. + * + * @param value The value. + */ public void setValue(long value) { this.value = value; } + /** + * Get the message. + * + * @return The message. + */ + public String getMessage() { + return message; + } + + /** + * Set the message. + * + * @param message The message. + */ public void setMessage(String message) { this.message = message; } + /** + * Get the tag. + * + * @return The tag. + */ + public String getTag() { + return tag; + } + + /** + * Set the tag. + * + * @param tag The tag. + */ public void setTag(String tag) { this.tag = tag; } diff --git a/src/main/java/jota/pow/ICurl.java b/src/main/java/jota/pow/ICurl.java index 9534837..0608755 100644 --- a/src/main/java/jota/pow/ICurl.java +++ b/src/main/java/jota/pow/ICurl.java @@ -1,22 +1,80 @@ package jota.pow; /** - * Created by Adrian on 07.01.2017. + * This interface abstracts the curl hashing algorithm. + * + * @author Adrian */ public interface ICurl { - JCurl absorb(final int[] trits, int offset, int length); - JCurl absorb(final int[] trits); + /** + * Absorbs the specified trits. + * + * @param trits The trits. + * @param offset The offset to start from. + * @param length The length. + * @return The ICurl instance (used for method chaining). + */ + ICurl absorb(final int[] trits, int offset, int length); + /** + * Absorbs the specified trits. + * + * @param trits The trits. + * @return The ICurl instance (used for method chaining). + */ + ICurl absorb(final int[] trits); + + /** + * Squeezes the specified trits. + * + * @param trits The trits. + * @param offset The offset to start from. + * @param length The length. + * @return The squeezed trits. + */ int[] squeeze(final int[] trits, int offset, int length); + /** + * Squeezes the specified trits. + * + * @param trits The trits. + * @return The squeezed trits. + */ int[] squeeze(final int[] trits); - JCurl transform(); + /** + * Transforms this instance. + * + * @return The ICurl instance (used for method chaining). + */ + ICurl transform(); - JCurl reset(); + /** + * Resets this state. + * + * @return The ICurl instance (used for method chaining). + */ + ICurl reset(); + /** + * Gets or sets the state. + * + * @return The stae. + */ int[] getState(); + /** + * Sets or sets the state. + * + * @param state The state. + */ void setState(int[] state); + + /** + * Clones this instance. + * + * @return A new instance. + */ + ICurl clone(); } diff --git a/src/main/java/jota/pow/JCurl.java b/src/main/java/jota/pow/JCurl.java index c57f4b8..3a80848 100644 --- a/src/main/java/jota/pow/JCurl.java +++ b/src/main/java/jota/pow/JCurl.java @@ -7,6 +7,9 @@ package jota.pow; */ public class JCurl implements ICurl { + /** + * The hash length. + */ public static final int HASH_LENGTH = 243; private static final int STATE_LENGTH = 3 * HASH_LENGTH; @@ -15,6 +18,14 @@ public class JCurl implements ICurl { private int[] state = new int[STATE_LENGTH]; + /** + * Absorbs the specified trits. + * + * @param trits The trits. + * @param offset The offset to start from. + * @param length The length. + * @return The ICurl instance (used for method chaining). + */ public JCurl absorb(final int[] trits, int offset, int length) { do { @@ -22,16 +33,25 @@ public class JCurl implements ICurl { transform(); offset += HASH_LENGTH; } while ((length -= HASH_LENGTH) > 0); - + return this; } - - + /** + * Absorbs the specified trits. + * + * @param trits The trits. + * @return The ICurl instance (used for method chaining). + */ public JCurl absorb(final int[] trits) { return absorb(trits, 0, trits.length); } + /** + * Transforms this instance. + * + * @return The ICurl instance (used for method chaining). + */ public JCurl transform() { final int[] scratchpad = new int[STATE_LENGTH]; @@ -45,13 +65,26 @@ public class JCurl implements ICurl { return this; } + /** + * Resets this state. + * + * @return The ICurl instance (used for method chaining). + */ public JCurl reset() { for (int stateIndex = 0; stateIndex < STATE_LENGTH; stateIndex++) { state[stateIndex] = 0; } return this; } - + + /** + * Squeezes the specified trits. + * + * @param trits The trits. + * @param offset The offset to start from. + * @param length The length. + * @return The squeezes trits. + */ public int[] squeeze(final int[] trits, int offset, int length) { do { @@ -62,15 +95,42 @@ public class JCurl implements ICurl { return state; } - + + /** + * Squeezes the specified trits. + * + * @param trits The trits. + * @return The squeezes trits. + */ public int[] squeeze(final int[] trits) { return squeeze(trits, 0, trits.length); } + /** + * Gets the states. + * + * @return The state. + */ public int[] getState() { return state; } - public void setState(int[] state) { - this.state = state; + + /** + * Sets the state. + * + * @param state The states. + */ + public void setState(int[] state) { + this.state = state; + } + + /** + * Clones this instance. + * + * @return A new instance. + */ + @Override + public ICurl clone() { + return new JCurl(); } } diff --git a/src/main/java/jota/utils/Checksum.java b/src/main/java/jota/utils/Checksum.java index 79605e5..a69c3f9 100644 --- a/src/main/java/jota/utils/Checksum.java +++ b/src/main/java/jota/utils/Checksum.java @@ -1,46 +1,87 @@ package jota.utils; +import jota.error.InvalidAddressException; import jota.pow.JCurl; -import org.apache.commons.lang3.StringUtils; /** - * Created by pinpong on 02.12.16. + * This class defines utility methods to add/remove the checksum to/from an address. + * + * @author pinpong */ public class Checksum { - public static String addChecksum(String address) { + /** + * Adds the checksum to the specified address. + * + * @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. + **/ + public static String addChecksum(String address) throws InvalidAddressException { InputValidator.checkAddress(address); String addressWithChecksum = address; addressWithChecksum += calculateChecksum(address); return addressWithChecksum; } - public static String removeChecksum(String addressWithChecksum) { - if (isAddressWithChecksum(addressWithChecksum)) { - return getAddress(addressWithChecksum); + /** + * Remove the checksum to the specified address. + * + * @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. + **/ + public static String removeChecksum(String address) throws InvalidAddressException { + if (isAddressWithChecksum(address)) { + return removeChecksumFromAddress(address); + } else if (isAddressWithoutChecksum(address)) { + return address; } - return StringUtils.EMPTY; + throw new InvalidAddressException(); } - private static String getAddress(String addressWithChecksum) { + private static String removeChecksumFromAddress(String addressWithChecksum) { return addressWithChecksum.substring(0, Constants.ADDRESS_LENGTH_WITHOUT_CHECKSUM); } - public static boolean isValidChecksum(String addressWithChecksum) { + /** + * Determines whether the specified address with checksum has a valid 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. + **/ + public static boolean isValidChecksum(String addressWithChecksum) throws InvalidAddressException { String addressWithoutChecksum = removeChecksum(addressWithChecksum); String addressWithRecalculateChecksum = addressWithChecksum += calculateChecksum(addressWithoutChecksum); return addressWithRecalculateChecksum.equals(addressWithChecksum); } - public static boolean isAddressWithChecksum(String address) { + + /** + * Check if specified address is a 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 + **/ + public static boolean isAddressWithChecksum(String address) throws InvalidAddressException { return InputValidator.checkAddress(address) && address.length() == Constants.ADDRESS_LENGTH_WITH_CHECKSUM; } - public static boolean isAddressWithoutChecksum(String address) { + + /** + * check if specified address is a address + * + * @param address address + * @return boolean + * @throws InvalidAddressException is thrown when the specified address is not an valid address + **/ + public static boolean isAddressWithoutChecksum(String address) throws InvalidAddressException { return InputValidator.checkAddress(address) && address.length() == Constants.ADDRESS_LENGTH_WITHOUT_CHECKSUM; } - public static String calculateChecksum(String address) { + private static String calculateChecksum(String address) { JCurl curl = new JCurl(); curl.reset(); curl.setState(Converter.copyTrits(address, curl.getState())); diff --git a/src/main/java/jota/utils/Constants.java b/src/main/java/jota/utils/Constants.java index 5f8f9a2..5781486 100644 --- a/src/main/java/jota/utils/Constants.java +++ b/src/main/java/jota/utils/Constants.java @@ -1,14 +1,29 @@ package jota.utils; /** - * Created by pinpong on 02.12.16. + * This class defines the global constants. + * + * @author pinpong */ public class Constants { + /** + * This String contains all possible characters of the tryte alphabet + */ public static final String TRYTE_ALPHABET = "9ABCDEFGHIJKLMNOPQRSTUVWXYZ"; + /** + * The maximum seed length + */ public static final int SEED_LENGTH_MAX = 81; + /** + * The length of an address without checksum + */ public static int ADDRESS_LENGTH_WITHOUT_CHECKSUM = 81; + + /** + * The length of an address with checksum + */ public static int ADDRESS_LENGTH_WITH_CHECKSUM = 90; } diff --git a/src/main/java/jota/utils/Converter.java b/src/main/java/jota/utils/Converter.java index a5f5802..4410962 100644 --- a/src/main/java/jota/utils/Converter.java +++ b/src/main/java/jota/utils/Converter.java @@ -1,21 +1,32 @@ package jota.utils; -import jota.model.Transaction; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.util.Arrays; import java.util.LinkedList; import java.util.List; +/** + * This class provides a set of utility methods to are used to convert between different formats. + */ public class Converter { - private static final Logger log = LoggerFactory.getLogger(Converter.class); - + /** + * The radix + */ private static final int RADIX = 3; + + /** + * The maximum trit value + */ private static final int MAX_TRIT_VALUE = (RADIX - 1) / 2, MIN_TRIT_VALUE = -MAX_TRIT_VALUE; + /** + * The number of trits in a byte + */ private static final int NUMBER_OF_TRITS_IN_A_BYTE = 5; + + /** + * The number of trits in a tryte + */ private static final int NUMBER_OF_TRITS_IN_A_TRYTE = 3; private static final int[][] BYTE_TO_TRITS_MAPPINGS = new int[243][]; private static final int[][] TRYTE_TO_TRITS_MAPPINGS = new int[27][]; @@ -35,6 +46,14 @@ public class Converter { } } + /** + * Converts the specified trits array to bytes. + * + * @param trits The trits. + * @param offset The offset to start from. + * @param size The size. + * @return The bytes. + */ public static byte[] bytes(final int[] trits, final int offset, final int size) { final byte[] bytes = new byte[(size + NUMBER_OF_TRITS_IN_A_BYTE - 1) / NUMBER_OF_TRITS_IN_A_BYTE]; @@ -54,6 +73,12 @@ public class Converter { return bytes(trits, 0, trits.length); } + /** + * Gets the trits from the specified bytes and stores it into the provided trits array. + * + * @param bytes The bytes. + * @param trits The trits. + */ public static void getTrits(final byte[] bytes, final int[] trits) { int offset = 0; @@ -66,30 +91,63 @@ public class Converter { } } - public static int[] convertToIntArray(List integers) - { + public static int[] convertToIntArray(List integers) { int[] ret = new int[integers.size()]; - for (int i=0; i < ret.length; i++) - { + for (int i = 0; i < ret.length; i++) { ret[i] = integers.get(i); } return ret; } + /** + * Converts the specified trinary encoded string into a trits array of the specified length. + * + * @param trytes The trytes. + * @param length The length + * @return A trits array. + */ public static int[] trits(final String trytes, int length) { int[] trits = trits(trytes); List tritsList = new LinkedList<>(); - for(int i : trits) + for (int i : trits) tritsList.add(i); - while(tritsList.size() < length) + while (tritsList.size() < length) tritsList.add(0); return convertToIntArray(tritsList); } - public static int[] tritsString(final String trytes){ + + /** + * Converts the specified trinary encoded string into a trits array of the specified length. + * + * @param trytes The trytes. + * @param length The length. + * @return A trits array. + */ + public static int[] trits(final long trytes, int length) { + int[] trits = trits(String.valueOf(trytes)); + + List tritsList = new LinkedList<>(); + + for (int i : trits) + tritsList.add(i); + + while (tritsList.size() < length) + tritsList.add(0); + + return convertToIntArray(tritsList); + } + + /** + * Converts the specified trinary encoded trytes string to trits. + * + * @param trytes The trytes. + * @return A trits array. + */ + public static int[] tritsString(final String trytes) { int[] d = new int[3 * trytes.length()]; for (int i = 0; i < trytes.length(); i++) { System.arraycopy(TRYTE_TO_TRITS_MAPPINGS[Constants.TRYTE_ALPHABET.indexOf(trytes.charAt(i))], 0, d, i * NUMBER_OF_TRITS_IN_A_TRYTE, NUMBER_OF_TRITS_IN_A_TRYTE); @@ -97,6 +155,12 @@ public class Converter { return d; } + /** + * Converts trytes into trits. + * + * @param trytes The trytes to be converted. + * @return Array of trits. + **/ public static int[] trits(final String trytes) { final List trits = new LinkedList<>(); if (InputValidator.isValue(trytes)) { @@ -117,11 +181,11 @@ public class Converter { absoluteValue++; } - trits.add(position++,remainder); + trits.add(position++, remainder); } if (value < 0) { for (int i = 0; i < trits.size(); i++) { - trits.set(i,-trits.get(i)); + trits.set(i, -trits.get(i)); } } } else { @@ -134,29 +198,13 @@ public class Converter { return convertToIntArray(trits); } - public static void copyTrits(final long value, final int[] destination, final int offset, final int size) { - - long absoluteValue = value < 0 ? -value : value; - for (int i = 0; i < size; i++) { - - int remainder = (int) (absoluteValue % RADIX); - absoluteValue /= RADIX; - if (remainder > MAX_TRIT_VALUE) { - - remainder = MIN_TRIT_VALUE; - absoluteValue++; - } - destination[offset +i ] = remainder; - } - - if (value < 0) { - - for (int i = 0; i < size; i++) { - destination[offset + i] = -destination[offset + i]; - } - } - } - + /** + * Copies the trits from the input string into the destination array + * + * @param input The input String. + * @param destination The destination array. + * @return The destination. + */ public static int[] copyTrits(final String input, final int[] destination) { for (int i = 0; i < input.length(); i++) { int index = Constants.TRYTE_ALPHABET.indexOf(input.charAt(i)); @@ -167,6 +215,14 @@ public class Converter { return destination; } + /** + * Converts trites to trytes. + * + * @param trits Teh trits to be converted. + * @param offset The offset to start from. + * @param size The size. + * @return The trytes. + **/ public static String trytes(final int[] trits, final int offset, final int size) { StringBuilder trytes = new StringBuilder(); @@ -186,10 +242,23 @@ public class Converter { return trytes(trits, 0, trits.length); } + /** + * Converts the specified trits array to trytes in integer representation. + * + * @param trits The trits. + * @param offset The offset to start from. + * @return The value. + */ public static int tryteValue(final int[] trits, final int offset) { return trits[offset] + trits[offset + 1] * 3 + trits[offset + 2] * 9; } + /** + * Converts the specified trits to its corresponding integer value. + * + * @param trits The trits. + * @return The value. + */ public static int value(final int[] trits) { int value = 0; @@ -199,6 +268,12 @@ public class Converter { return value; } + /** + * Converts the specified trits to its corresponding integer value. + * + * @param trits The trits. + * @return The value. + */ public static long longValue(final int[] trits) { long value = 0; @@ -208,6 +283,12 @@ public class Converter { return value; } + /** + * Increments the specified trits. + * + * @param trits The trits. + * @param size The size. + */ public static void increment(final int[] trits, final int size) { for (int i = 0; i < size; i++) { @@ -219,4 +300,4 @@ public class Converter { } } -} +} \ No newline at end of file diff --git a/src/main/java/jota/utils/InputValidator.java b/src/main/java/jota/utils/InputValidator.java index 4e01cd4..7d1686e 100644 --- a/src/main/java/jota/utils/InputValidator.java +++ b/src/main/java/jota/utils/InputValidator.java @@ -1,5 +1,6 @@ package jota.utils; +import jota.error.InvalidAddressException; import jota.model.Transfer; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.math.NumberUtils; @@ -7,30 +8,91 @@ import org.apache.commons.lang3.math.NumberUtils; import java.util.List; /** - * Created by pinpong on 02.12.16. + * This class provides methods to validate the parameters of different iota API methods. + * + * @author pinpong */ public class InputValidator { + /** + * Determines whether the specified string is an address. + * + * @param address The address to validate. + * @return true if the specified string is an address; otherwise, false. + **/ public static boolean isAddress(String address) { return (address.length() == Constants.ADDRESS_LENGTH_WITHOUT_CHECKSUM || address.length() == Constants.ADDRESS_LENGTH_WITH_CHECKSUM) && isTrytes(address, address.length()); } - public static boolean checkAddress(String address) { + /** + * 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. + **/ + public static boolean checkAddress(String address) throws InvalidAddressException { if (!isAddress(address)) { - throw new RuntimeException("Invalid address: " + address); + throw new InvalidAddressException(); } return true; } + /** + * Determines whether the specified string contains only characters from the trytes alphabet (see ). + * + * @param trytes The trytes to validate. + * @param length The length. + * @return true if the specified trytes are trytes otherwise, false. + **/ public static boolean isTrytes(final String trytes, final int length) { return trytes.matches("^[A-Z9]{" + (length == 0 ? "0," : length) + "}$"); } + /** + * Determines whether the specified string consist only of '9'. + * + * @param trytes The trytes to validate. + * @param length The length. + * @return true if the specified string consist only of '9'; otherwise, false. + **/ + public static boolean isNinesTrytes(final String trytes, final int length) { + return trytes.matches("^[9]{" + (length == 0 ? "0," : length) + "}$"); + } + + /** + * Determines whether the specified string represents a signed integer. + * + * @param value The value to validate. + * @return true the specified string represents an integer value; otherwise, false. + **/ public static boolean isValue(final String value) { return NumberUtils.isNumber(value); } + /** + * Determines whether the specified string array contains only trytes. + * + * @param trytes The trytes array to validate. + * @return true if the specified array contains only valid trytes otherwise, false. + **/ + public static boolean isArrayOfTrytes(String[] trytes) { + for (String tryte : trytes) { + // Check if correct 2673 trytes + if (!isTrytes(tryte, 2673)) { + return false; + } + } + return true; + } + + /** + * Determines whether the specified array contains only valid hashes. + * + * @param hashes The hashes array to validate. + * @return true the specified array contains only valid hashes; otherwise, false. + **/ public static boolean isArrayOfHashes(String[] hashes) { if (hashes == null) return false; @@ -51,23 +113,28 @@ public class InputValidator { } /** - * checks if input is correct hash collections + * Determines whether the specified transfers are valid. * - * @param {array} hash - * @method isTransfersArray - * @returns {boolean} + * @param transfers The transfers list to validate. + * @return true if the specified transfers are valid; otherwise, false. **/ - public static boolean isTransfersCollectionCorrect(final List transfers) { + public static boolean isTransfersCollectionValid(final List transfers) { for (final Transfer transfer : transfers) { - if (!isTransfersArray(transfer)) { + if (!isValidTransfer(transfer)) { return false; } } return true; } - public static boolean isTransfersArray(final Transfer transfer) { + /** + * Determines whether the specified transfer is valid. + * + * @param transfer The transfer to validate. + * @return true if the specified transfer is valid; otherwise, false>. + **/ + public static boolean isValidTransfer(final Transfer transfer) { if (!isAddress(transfer.getAddress())) { return false; @@ -82,9 +149,19 @@ public class InputValidator { return isTrytes(transfer.getTag(), 27); } + /** + * Checks if the seed is valid. If not, an exception is thrown. + * + * @param seed The seed to validate. + * @return The validated seed. + * @throws IllegalStateException Format not in trytes or Invalid Seed: Seed too long. + **/ public static String validateSeed(String seed) { if (seed.length() > 81) - return null; + throw new IllegalStateException("Invalid Seed: Seed too long"); + + if (!isTrytes(seed, seed.length())) + throw new IllegalStateException("Invalid Seed: Format not in trytes"); seed = StringUtils.rightPad(seed, 81, '9'); diff --git a/src/main/java/jota/utils/IotaAPIUtils.java b/src/main/java/jota/utils/IotaAPIUtils.java index dfc869b..ae2ea2a 100644 --- a/src/main/java/jota/utils/IotaAPIUtils.java +++ b/src/main/java/jota/utils/IotaAPIUtils.java @@ -1,35 +1,37 @@ package jota.utils; -import java.util.*; - -import jota.pow.ICurl; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - +import jota.error.InvalidAddressException; import jota.model.Bundle; import jota.model.Input; import jota.model.Transaction; +import jota.pow.ICurl; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; /** - * Client Side computation service + * Client Side computation service. * * @author davassi */ public class IotaAPIUtils { - private static final Logger log = LoggerFactory.getLogger(IotaAPIUtils.class); - /** * Generates a new address * - * @param seed - * @param index - * @param checksum - * @return an String with address + * @param seed The tryte-encoded seed. It should be noted that this seed is not transferred. + * @param security The secuirty level of private key / seed. + * @param index The index to start search from. If the index is provided, the generation of the address is not deterministic. + * @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. */ - public static String newAddress(String seed, int index, boolean checksum, ICurl curl) { + public static String newAddress(String seed, int security, int index, boolean checksum, ICurl curl) throws InvalidAddressException { Signing signing = new Signing(curl); - final int[] key = signing.key(Converter.trits(seed), index, 2); + final int[] key = signing.key(Converter.trits(seed), index, security); final int[] digests = signing.digests(key); final int[] addressTrits = signing.address(digests); @@ -45,6 +47,7 @@ public class IotaAPIUtils { final List inputs, final Bundle bundle, final List signatureFragments, ICurl curl) { + bundle.finalize(curl); bundle.addTrytes(signatureFragments); @@ -54,22 +57,23 @@ public class IotaAPIUtils { // Iterate over all bundle transactions, find the inputs // Get the corresponding private key and calculate the signatureFragment for (int i = 0; i < bundle.getTransactions().size(); i++) { - if (Long.parseLong(bundle.getTransactions().get(i).getValue()) < 0) { + if (bundle.getTransactions().get(i).getValue() < 0) { String thisAddress = bundle.getTransactions().get(i).getAddress(); // Get the corresponding keyIndex of the address int keyIndex = 0; + int keySecurity = 0; for (Input input : inputs) { if (input.getAddress().equals(thisAddress)) { keyIndex = input.getKeyIndex(); - break; + keySecurity = input.getSecurity(); } } String bundleHash = bundle.getTransactions().get(i).getBundle(); // Get corresponding private key of address - int[] key = new Signing(curl).key(Converter.trits(seed), keyIndex, 2); + int[] key = new Signing(curl).key(Converter.trits(seed), keyIndex, keySecurity); // First 6561 trits for the firstFragment int[] firstFragment = Arrays.copyOfRange(key, 0, 6561); @@ -81,27 +85,32 @@ public class IotaAPIUtils { int[] firstBundleFragment = Arrays.copyOfRange(normalizedBundleHash, 0, 27); // Calculate the new signatureFragment with the first bundle fragment - int[] firstSignedFragment = new Signing(curl).signatureFragment(firstBundleFragment, firstFragment); + int[] firstSignedFragment = new Signing(curl).signatureFragment(firstBundleFragment, firstFragment); // Convert signature to trytes and assign the new signatureFragment bundle.getTransactions().get(i).setSignatureFragments(Converter.trytes(firstSignedFragment)); - // Because the signature is > 2187 trytes, we need to - // find the second transaction to add the remainder of the signature - for (int j = 0; j < bundle.getTransactions().size(); j++) { - // Same address as well as value = 0 (as we already spent the input) - if (bundle.getTransactions().get(j).getAddress().equals(thisAddress) && Long.parseLong(bundle.getTransactions().get(j).getValue()) == 0) { - // Use the second 6562 trits - int[] secondFragment = Arrays.copyOfRange(key, 6561, 6561 * 2); + // if user chooses higher than 27-tryte security + // for each security level, add an additional signature + for (int j = 1; j < keySecurity; j++) { - // The second 27 to 54 trytes of the bundle hash - int[] secondBundleFragment = Arrays.copyOfRange(normalizedBundleHash, 27, 27 * 2); + // Because the signature is > 2187 trytes, we need to + // find the second transaction to add the remainder of the signature + for (int k = 0; k < bundle.getTransactions().size(); k++) { + // Same address as well as value = 0 (as we already spent the input) + if (bundle.getTransactions().get(k).getAddress().equals(thisAddress) && bundle.getTransactions().get(k).getValue() == 0) { + // Use the second 6562 trits + int[] secondFragment = Arrays.copyOfRange(key, 6561, 6561 * 2); - // Calculate the new signature - int[] secondSignedFragment = new Signing(curl).signatureFragment(secondBundleFragment, secondFragment); + // The second 27 to 54 trytes of the bundle hash + int[] secondBundleFragment = Arrays.copyOfRange(normalizedBundleHash, 27, 27 * 2); - // Convert signature to trytes and assign it again to this bundle entry - bundle.getTransactions().get(j).setSignatureFragments(Converter.trytes(secondSignedFragment)); + // Calculate the new signature + int[] secondSignedFragment = new Signing(curl).signatureFragment(secondBundleFragment, secondFragment); + + // Convert signature to trytes and assign it again to this bundle entry + bundle.getTransactions().get(k).setSignatureFragments(Converter.trytes(secondSignedFragment)); + } } } } diff --git a/src/main/java/jota/utils/IotaUnitConverter.java b/src/main/java/jota/utils/IotaUnitConverter.java index eac11b4..758cbd3 100644 --- a/src/main/java/jota/utils/IotaUnitConverter.java +++ b/src/main/java/jota/utils/IotaUnitConverter.java @@ -3,35 +3,81 @@ package jota.utils; import java.text.DecimalFormat; /** - * Created by Sascha on 30.11.16. + * This class provides methods to convert Iota to different units. + * + * @author sascha */ public class IotaUnitConverter { + /** + * Convert the iota amount. + * + * @param amount The amount. + * @param fromUnit The source unit e.g. the unit of amount. + * @param toUnit The target unit. + * @return The specified amount in the target unit. + **/ public static long convertUnits(long amount, IotaUnits fromUnit, IotaUnits toUnit) { long amountInSource = (long) (amount * Math.pow(10, fromUnit.getValue())); return convertUnits(amountInSource, toUnit); } + /** + * Convert unit. + * + * @param amount The amount. + * @param toUnit The target unit. + * @return The specified amount in the target unit. + **/ private static long convertUnits(long amount, IotaUnits toUnit) { return (long) (amount / Math.pow(10, toUnit.getValue())); } + /** + * Convert the iota amount to text. + * + * @param amount The amount. + * @param extended Extended length. + * @return The specified amount in the target unit. + **/ public static String convertRawIotaAmountToDisplayText(long amount, boolean extended) { IotaUnits unit = findOptimalIotaUnitToDisplay(amount); double amountInDisplayUnit = convertAmountTo(amount, unit); return createAmountWithUnitDisplayText(amountInDisplayUnit, unit, extended); } + /** + * Convert amount to target unit. + * + * @param amount The amount. + * @return The target unit. + **/ public static double convertAmountTo(long amount, IotaUnits target) { return amount / Math.pow(10, target.getValue()); } + /** + * Create amount with unit text. + * + * @param amountInUnit The amount in units. + * @param unit The unit. + * @param extended Extended length. + * @return The target unit. + **/ private static String createAmountWithUnitDisplayText(double amountInUnit, IotaUnits unit, boolean extended) { String result = createAmountDisplayText(amountInUnit, unit, extended); result += " " + unit.getUnit(); return result; } + /** + * Create amount text. + * + * @param amountInUnit The amount in units. + * @param unit The unit. + * @param extended Extended length. + * @return The target unit. + **/ public static String createAmountDisplayText(double amountInUnit, IotaUnits unit, boolean extended) { DecimalFormat df; if (extended) df = new DecimalFormat("##0.##################"); @@ -44,10 +90,16 @@ public class IotaUnitConverter { return result; } + /** + * Finds the optimal unit to display the specified amount in. + * + * @param amount The amount. + * @return The optimal IotaUnit. + **/ public static IotaUnits findOptimalIotaUnitToDisplay(long amount) { int length = String.valueOf(amount).length(); - if (amount < 0) {// do not count "-" sign + if (amount < 0) {// do not count "-" sign length -= 1; } diff --git a/src/main/java/jota/utils/IotaUnits.java b/src/main/java/jota/utils/IotaUnits.java index d94b235..e64895f 100644 --- a/src/main/java/jota/utils/IotaUnits.java +++ b/src/main/java/jota/utils/IotaUnits.java @@ -1,29 +1,44 @@ package jota.utils; /** - * Table of IOTA units based off of the standard system of Units + * Table of IOTA units based off of the standard system of Units. + * + * @author pinpong **/ public enum IotaUnits { - + IOTA("i", 0), - KILO_IOTA("Ki", 3), - MEGA_IOTA("Mi", 6), - GIGA_IOTA("Gi", 9), - TERA_IOTA("Ti", 12), - PETA_IOTA("Pi", 15); + KILO_IOTA("Ki", 3), // 10^3 + MEGA_IOTA("Mi", 6), // 10^6 + GIGA_IOTA("Gi", 9), // 10^9 + TERA_IOTA("Ti", 12), // 10^12 + PETA_IOTA("Pi", 15); // 10^15 private String unit; private long value; + /** + * Initializes a new instance of the IotaUnit class. + */ IotaUnits(String unit, long value) { this.unit = unit; this.value = value; } + /** + * Gets the unit. + * + * @return The IOTA Unit. + */ public String getUnit() { return unit; } + /** + * Gets the value. + * + * @return The value. + */ public long getValue() { return value; } diff --git a/src/main/java/jota/utils/Multisig.java b/src/main/java/jota/utils/Multisig.java new file mode 100644 index 0000000..17ae539 --- /dev/null +++ b/src/main/java/jota/utils/Multisig.java @@ -0,0 +1,208 @@ +package jota.utils; + +import jota.model.Bundle; +import jota.pow.ICurl; +import jota.pow.JCurl; + +import java.util.Arrays; + +/** + * @author pinpong + */ +public class Multisig { + + private ICurl curl; + private Signing signingInstance; + + public Multisig(ICurl customCurl) { + this.curl = customCurl; + this.curl.reset(); + this.signingInstance = new Signing(curl.clone()); + } + + public Multisig() { + this(new JCurl()); + } + + /** + * @param seed tryte-encoded seed. It should be noted that this seed is not transferred + * @param security security secuirty level of private key / seed + * @param index + * @return digest trytes + **/ + public String getDigest(String seed, int security, int index) { + int[] key = signingInstance.key(Converter.trits(seed, 243), index, security); + return Converter.trytes(signingInstance.digests(key)); + } + + /** + * Initiates the generation of a new multisig address or adds the key digest to an existing one + * + * @param digestTrytes + * @param curlStateTrytes + * @return digest trytes + * @method addAddressDigest + **/ + public String addAddressDigest(String digestTrytes, String curlStateTrytes) { + + + int[] digest = Converter.trits(digestTrytes, digestTrytes.length() * 3); + + // If curlStateTrytes is provided, convert into trits + // else use empty state and initiate the creation of a new address + + int[] curlState = !curlStateTrytes.isEmpty() ? Converter.trits(curlStateTrytes, + digestTrytes.length() * 3) : new int[digestTrytes.length() * 3]; + + // initialize Curl with the provided state + curl.setState(curlState); + // absorb the key digest + curl.absorb(digest); + + return Converter.trytes(curl.getState()); + } + + /** + * Gets the key value of a seed + * + * @param seed tryte-encoded seed. It should be noted that this seed is not transferred + * @param index + * @return digest trytes + **/ + + public String getKey(String seed, int index, int security) { + + return Converter.trytes(signingInstance.key(Converter.trits(seed, 81 * security), index, security)); + } + + /** + * Generates a new address + * + * @param curlStateTrytes + * @return address + **/ + public String finalizeAddress(String curlStateTrytes) { + + int[] curlState = Converter.trits(curlStateTrytes); + + // initialize Curl with the provided state + curl.setState(curlState); + + int[] addressTrits = new int[243]; + curl.squeeze(addressTrits); + + // Convert trits into trytes and return the address + return Converter.trytes(addressTrits); + } + + /** + * Validates a generated multisig address + * + * @param multisigAddress + * @param digests + * @returns boolean + **/ + public boolean validateAddress(String multisigAddress, int[][] digests) { + + // initialize Curl with the provided state + curl.reset(); + + + for (int[] keyDigest : digests) { + curl.absorb(keyDigest); + } + + int[] addressTrits = new int[243]; + curl.squeeze(addressTrits); + + // Convert trits into trytes and return the address + return Converter.trytes(addressTrits).equals(multisigAddress); + } + + /** + * Adds the cosigner signatures to the corresponding bundle transaction + * + * @param bundleToSign + * @param inputAddress + * @param keyTrytes + * @return Returns bundle trytes. + **/ + public Bundle addSignature(Bundle bundleToSign, String inputAddress, String keyTrytes) { + + + // Get the security used for the private key + // 1 security level = 2187 trytes + int security = (keyTrytes.length() / 2187); + + // convert private key trytes into trits + int[] key = Converter.trits(keyTrytes); + + + // First get the total number of already signed transactions + // use that for the bundle hash calculation as well as knowing + // where to add the signature + int numSignedTxs = 0; + + + for (int i = 0; i < bundleToSign.getTransactions().size(); i++) { + + if (bundleToSign.getTransactions().get(i).getAddress().equals(inputAddress)) { + + // If transaction is already signed, increase counter + if (!InputValidator.isNinesTrytes(bundleToSign.getTransactions().get(i).getSignatureFragments(), + bundleToSign.getTransactions().get(i).getSignatureFragments().length())) { + + numSignedTxs++; + } + // Else sign the transactions + else { + + String bundleHash = bundleToSign.getTransactions().get(i).getBundle(); + + // First 6561 trits for the firstFragment + int[] firstFragment = Arrays.copyOfRange(key, 0, 6561); + + // Get the normalized bundle hash + int[][] normalizedBundleFragments = new int[3][27]; + int[] normalizedBundleHash = bundleToSign.normalizedBundle(bundleHash); + + + // Split hash into 3 fragments + for (int k = 0; k < 3; k++) { + normalizedBundleFragments[k] = Arrays.copyOfRange(normalizedBundleHash, (k * 27), (k + 1) * 27); + } + + + // First bundle fragment uses 27 trytes + int[] firstBundleFragment = normalizedBundleFragments[numSignedTxs % 3]; + + // Calculate the new signatureFragment with the first bundle fragment + int[] firstSignedFragment = signingInstance.signatureFragment(firstBundleFragment, firstFragment); + + // Convert signature to trytes and assign the new signatureFragment + bundleToSign.getTransactions().get(i).setSignatureFragments(Converter.trytes(firstSignedFragment)); + + for (int j = 1; j < security; j++) { + + // Next 6561 trits for the firstFragment + int[] nextFragment = Arrays.copyOfRange(key, 6561 * j, (j + 1) * 6561); + + // Use the next 27 trytes + int[] nextBundleFragment = normalizedBundleFragments[(numSignedTxs + j) % 3]; + + // Calculate the new signatureFragment with the first bundle fragment + int[] nextSignedFragment = signingInstance.signatureFragment(nextBundleFragment, nextFragment); + + // Convert signature to trytes and add new bundle entry at i + j position + // Assign the signature fragment + bundleToSign.getTransactions().get(i + j).setSignatureFragments(Converter.trytes(nextSignedFragment)); + } + + break; + } + } + } + + return bundleToSign; + } +} \ No newline at end of file diff --git a/src/main/java/jota/utils/NamedThreadFactory.java b/src/main/java/jota/utils/NamedThreadFactory.java index a6e3dab..9bc015a 100644 --- a/src/main/java/jota/utils/NamedThreadFactory.java +++ b/src/main/java/jota/utils/NamedThreadFactory.java @@ -5,16 +5,24 @@ import java.util.concurrent.ThreadFactory; import java.util.concurrent.atomic.AtomicInteger; /** - * Created by Adrian on 15.01.2017. + * @author Adrian */ public class NamedThreadFactory implements ThreadFactory { + private final String baseName; private final AtomicInteger threadNum = new AtomicInteger(0); + /** + * @param baseName + */ public NamedThreadFactory(String baseName) { this.baseName = baseName; } + /** + * @param r + * @return + */ @Override public synchronized Thread newThread(Runnable r) { Thread t = Executors.defaultThreadFactory().newThread(r); diff --git a/src/main/java/jota/utils/Parallel.java b/src/main/java/jota/utils/Parallel.java index f5cdeb7..7587393 100644 --- a/src/main/java/jota/utils/Parallel.java +++ b/src/main/java/jota/utils/Parallel.java @@ -8,13 +8,18 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** - * Created by Adrian on 15.01.2017. + * @author Adrian */ public class Parallel { - private static final int NUM_CORES = Runtime.getRuntime().availableProcessors(); + private static final int NUM_CORES = Runtime.getRuntime().availableProcessors(); private static final ExecutorService forPool = Executors.newFixedThreadPool(NUM_CORES * 2, new NamedThreadFactory("Parallel.For")); + /** + * @param elements + * @param operation + * @param + */ public static void For(final Iterable elements, final Operation operation) { try { // invokeAll blocks for us until all submitted tasks in the call complete @@ -24,6 +29,12 @@ public class Parallel { } } + /** + * @param elements + * @param operation + * @param + * @return + */ public static Collection> createCallables(final Iterable elements, final Operation operation) { List> callables = new LinkedList<>(); for (final T elem : elements) { @@ -39,6 +50,9 @@ public class Parallel { return callables; } + /** + * @param + */ public interface Operation { void perform(T pParameter); } diff --git a/src/main/java/jota/utils/SeedRandomGenerator.java b/src/main/java/jota/utils/SeedRandomGenerator.java index fa8b58c..9c58b9e 100644 --- a/src/main/java/jota/utils/SeedRandomGenerator.java +++ b/src/main/java/jota/utils/SeedRandomGenerator.java @@ -3,10 +3,18 @@ package jota.utils; import java.security.SecureRandom; /** - * Created by pinpong on 13.12.16. + * This class allows to create a secure random generated seed. + * + * @author pinpong */ public class SeedRandomGenerator { + + /** + * Generate a new seed. + * + * @return Random generated seed. + **/ public static String generateNewSeed() { char[] chars = Constants.TRYTE_ALPHABET.toCharArray(); StringBuilder builder = new StringBuilder(); diff --git a/src/main/java/jota/utils/Signing.java b/src/main/java/jota/utils/Signing.java index 1cf70a5..bd4b6a5 100644 --- a/src/main/java/jota/utils/Signing.java +++ b/src/main/java/jota/utils/Signing.java @@ -1,24 +1,41 @@ package jota.utils; +import jota.model.Bundle; +import jota.model.Transaction; +import jota.pow.ICurl; +import jota.pow.JCurl; + import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import jota.model.Bundle; -import jota.pow.ICurl; -import jota.pow.JCurl; public class Signing { + + /** + * Ask @come-from-beyond + */ private ICurl curl; - public Signing() { - this(null); - } - + /** + * public Signing() { + * this(null); + * } + *

+ * /** + * + * @param curl + */ public Signing(ICurl curl) { this.curl = curl == null ? new JCurl() : curl; } + /** + * @param seed + * @param index + * @param length + * @return + */ public int[] key(int[] seed, int index, int length) { for (int i = 0; i < index; i++) { @@ -141,6 +158,31 @@ public class Signing { return buffer; } + public Boolean validateSignatures(Bundle signedBundle, String inputAddress) { + String bundleHash = ""; + Transaction trx; + List signatureFragments = new ArrayList<>(); + for (int i = 0; i < signedBundle.getTransactions().size(); i++) { + + trx = signedBundle.getTransactions().get(i); + + if (trx.getAddress().equals(inputAddress)) { + bundleHash = trx.getBundle(); + + // if we reached remainder bundle + String signatureFragment = trx.getSignatureFragments(); + if (InputValidator.isNinesTrytes(signatureFragment, signatureFragment.length())) { + break; + } + signatureFragments.add(signatureFragment); + } + } + + + return validateSignatures(inputAddress, signatureFragments.toArray(new String[signatureFragments.size()]), bundleHash); + } + + public Boolean validateSignatures(String expectedAddress, String[] signatureFragments, String bundleHash) { Bundle bundle = new Bundle(); diff --git a/src/main/java/jota/utils/StopWatch.java b/src/main/java/jota/utils/StopWatch.java index 699de6f..c68b383 100644 --- a/src/main/java/jota/utils/StopWatch.java +++ b/src/main/java/jota/utils/StopWatch.java @@ -1,39 +1,59 @@ package jota.utils; /** - * Created by Adrian on 15.01.2017. + * @author adrian */ public class StopWatch { + private long startTime = 0; private boolean running = false; private long currentTime = 0; + /** + * + */ public StopWatch() { this.startTime = System.currentTimeMillis(); this.running = true; } + /** + * + */ public void reStart() { this.startTime = System.currentTimeMillis(); this.running = true; } + /** + * @return + */ public StopWatch stop() { this.running = false; return this; } + /** + * + */ public void pause() { this.running = false; currentTime = System.currentTimeMillis() - startTime; } + /** + * + */ public void resume() { this.running = true; this.startTime = System.currentTimeMillis() - currentTime; } - //elaspsed time in milliseconds + /** + * Elapsed time in milliseconds. + * + * @return + */ public long getElapsedTimeMili() { long elapsed = 0; if (running) { @@ -42,7 +62,11 @@ public class StopWatch { return elapsed; } - //elaspsed time in seconds + /** + * Elapsed time in seconds. + * + * @return + */ public long getElapsedTimeSecs() { long elapsed = 0; if (running) { @@ -51,7 +75,11 @@ public class StopWatch { return elapsed; } - //elaspsed time in minutes + /** + * Elapsed time in minutes. + * + * @return + */ public long getElapsedTimeMin() { long elapsed = 0; if (running) { @@ -60,7 +88,11 @@ public class StopWatch { return elapsed; } - //elaspsed time in hours + /** + * Elapsed time in hours. + * + * @return + */ public long getElapsedTimeHour() { long elapsed = 0; if (running) { diff --git a/src/main/java/jota/utils/TrytesConverter.java b/src/main/java/jota/utils/TrytesConverter.java index ab9d02a..c1c2ac0 100644 --- a/src/main/java/jota/utils/TrytesConverter.java +++ b/src/main/java/jota/utils/TrytesConverter.java @@ -1,10 +1,12 @@ package jota.utils; /** - * Created by pinpong on 01.12.16. + * This class allows to convert between ASCII and tryte encoded strings. + * + * @author pinpong */ public class TrytesConverter { - + /** * Conversion of ascii encoded bytes to trytes. * Input is a string (can be stringified JSON object), return value is Trytes @@ -19,9 +21,9 @@ public class TrytesConverter { * 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: @@ -31,11 +33,9 @@ public class TrytesConverter { * a. The first tryte value is '9ABCDEFGHIJKLMNOPQRSTUVWXYZ'[9] === "I" * b. The second tryte value is '9ABCDEFGHIJKLMNOPQRSTUVWXYZ'[3] === "C" * Our tryte pair is "IC" - *

- * - * @param inputString - * @return - * The ASCII char "Z" is represented as "IC" in trytes. + * + * @param inputString The input String. + * @return The ASCII char "Z" is represented as "IC" in trytes. */ public static String toTrytes(String inputString) { diff --git a/src/test/java/jota/ChecksumTest.java b/src/test/java/jota/ChecksumTest.java index 1413f69..12ec896 100644 --- a/src/test/java/jota/ChecksumTest.java +++ b/src/test/java/jota/ChecksumTest.java @@ -1,12 +1,13 @@ package jota; +import jota.error.InvalidAddressException; import jota.utils.Checksum; import org.junit.Test; import static org.junit.Assert.assertEquals; /** - * Created by pinpong on 02.12.16. + * @author pinpong */ public class ChecksumTest { @@ -14,17 +15,17 @@ public class ChecksumTest { private static final String TEST_ADDRESS_WITH_CHECKSUM = "RVORZ9SIIP9RCYMREUIXXVPQIPHVCNPQ9HZWYKFWYWZRE9JQKG9REPKIASHUUECPSQO9JT9XNMVKWYGVAFOXM9MUBX"; @Test - public void shouldAddChecksum() { + public void shouldAddChecksum() throws InvalidAddressException { assertEquals(Checksum.addChecksum(TEST_ADDRESS_WITHOUT_CHECKSUM), TEST_ADDRESS_WITH_CHECKSUM); } - + @Test - public void shouldRemoveChecksum() { + public void shouldRemoveChecksum() throws InvalidAddressException { assertEquals(Checksum.removeChecksum(TEST_ADDRESS_WITH_CHECKSUM), TEST_ADDRESS_WITHOUT_CHECKSUM); } @Test - public void shouldIsValidChecksum() { + public void shouldIsValidChecksum() throws InvalidAddressException { assertEquals(Checksum.isValidChecksum(TEST_ADDRESS_WITH_CHECKSUM), true); } } diff --git a/src/test/java/jota/InputValidatorTest.java b/src/test/java/jota/InputValidatorTest.java index b898baf..a636ca9 100644 --- a/src/test/java/jota/InputValidatorTest.java +++ b/src/test/java/jota/InputValidatorTest.java @@ -1,5 +1,6 @@ package jota; +import jota.error.InvalidAddressException; import jota.model.Transfer; import jota.utils.InputValidator; import org.junit.Test; @@ -10,7 +11,7 @@ import java.util.List; import static org.junit.Assert.assertEquals; /** - * Created by pinpong on 02.12.16. + * @author pinpong */ public class InputValidatorTest { @@ -20,13 +21,14 @@ public class InputValidatorTest { private static final String TEST_HASH = "OAATQS9VQLSXCLDJVJJVYUGONXAXOFMJOZNSYWRZSWECMXAQQURHQBJNLD9IOFEPGZEPEMPXCIVRX9999"; private static final String TEST_MESSAGE = "JOTA"; private static final String TEST_TAG = "JOTASPAM9999999999999999999"; + @Test public void shouldIsAddress() { assertEquals(InputValidator.isAddress(TEST_ADDRESS_WITHOUT_CHECKSUM), true); } @Test - public void shouldCheckAddress() { + public void shouldCheckAddress() throws InvalidAddressException { assertEquals(InputValidator.checkAddress(TEST_ADDRESS_WITHOUT_CHECKSUM), true); } @@ -50,6 +52,6 @@ public class InputValidatorTest { 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)); - assertEquals(InputValidator.isTransfersCollectionCorrect(transfers), true); + assertEquals(InputValidator.isTransfersCollectionValid(transfers), true); } } \ No newline at end of file diff --git a/src/test/java/jota/IotaAPITest.java b/src/test/java/jota/IotaAPITest.java index 4ef7c92..11dd2dd 100644 --- a/src/test/java/jota/IotaAPITest.java +++ b/src/test/java/jota/IotaAPITest.java @@ -26,14 +26,14 @@ import static org.junit.Assert.assertThat; */ public class IotaAPITest { - private static Gson gson = new GsonBuilder().create(); - private static final String TEST_SEED1 = "AAA999999999999999999999999999999999999999999999999999999999999999999999999999999"; private static final String TEST_SEED2 = "IHDEENZYITYVYSPKAURUZAQKGVJEREFDJMYTANNXXGPZ9GJWTEOJJ9IPMXOGZNQLSNMFDSQOTZAEETUEA"; - private static final String TEST_ADDRESS_WITHOUT_CHECKSUM = "PNGMCSNRCTRHCHPXYTPKEJYPCOWKOMRXZFHH9N9VDIKMNVAZCMIYRHVJIAZARZTUETJVFDMBEBIQE9QTH"; - private static final String TEST_ADDRESS_WITH_CHECKSUM = "PNGMCSNRCTRHCHPXYTPKEJYPCOWKOMRXZFHH9N9VDIKMNVAZCMIYRHVJIAZARZTUETJVFDMBEBIQE9QTHBFWDAOEFA"; + private static final String TEST_ADDRESS_WITHOUT_CHECKSUM_SECURITY_LEVEL_1 = "NINSZRAKWBERQBBN9KGIRNXQDNENLBUBAYRZPUXFJSWRWVADEOGGOWMLQWSHA9NEOLASWRGOQJXAVRMFY"; + private static final String TEST_ADDRESS_WITHOUT_CHECKSUM_SECURITY_LEVEL_2 = "PNGMCSNRCTRHCHPXYTPKEJYPCOWKOMRXZFHH9N9VDIKMNVAZCMIYRHVJIAZARZTUETJVFDMBEBIQE9QTH"; + private static final String TEST_ADDRESS_WITHOUT_CHECKSUM_SECURITY_LEVEL_3 = "NOHBJKARAS9DZBFTRVIFY99STSQPSGTHMGMDYXLYIYKFYZISJUOGYWMZXDB9XEXFSSP9GYAIEHUQHLQ9C"; private static final String TEST_HASH = "CKZ9TYPLUWH9FUSYJMPIZBVHWFZXTZMVOJLC9KOICSTBBQWXYTOTMCVPSPMYNDONTXHRULRFAWD999999"; - private static final String TEST_TRYTES = "BYSWEAUTWXHXZ9YBZISEK9LUHWGMHXCGEVNZHRLUWQFCUSDXZHOFHWHL9MQPVJXXZLIXPXPXF9KYEREFSKCPKYIIKPZVLHUTDFQKKVVBBN9ATTLPCNPJDWDEVIYYLGPZGCWXOBDXMLJC9VO9QXTTBLAXTTBFUAROYEGQIVB9MJWJKXJMCUPTWAUGFZBTZCSJVRBGMYXTVBDDS9MYUJCPZ9YDWWQNIPUAIJXXSNLKUBSCOIJPCLEFPOXFJREXQCUVUMKSDOVQGGHRNILCO9GNCLWFM9APMNMWYASHXQAYBEXF9QRIHIBHYEJOYHRQJAOKAQ9AJJFQ9WEIWIJOTZATIBOXQLBMIJU9PCGBLVDDVFP9CFFSXTDUXMEGOOFXWRTLFGV9XXMYWEMGQEEEDBTIJ9OJOXFAPFQXCDAXOUDMLVYRMRLUDBETOLRJQAEDDLNVIRQJUBZBO9CCFDHIX9MSQCWYAXJVWHCUPTRSXJDESISQPRKZAFKFRULCGVRSBLVFOPEYLEE99JD9SEBALQINPDAZHFAB9RNBH9AZWIJOTLBZVIEJIAYGMC9AZGNFWGRSWAXTYSXVROVNKCOQQIWGPNQZKHUNODGYADPYLZZZUQRTJRTODOUKAOITNOMWNGHJBBA99QUMBHRENGBHTH9KHUAOXBVIVDVYYZMSEYSJWIOGGXZVRGN999EEGQMCOYVJQRIRROMPCQBLDYIGQO9AMORPYFSSUGACOJXGAQSPDY9YWRRPESNXXBDQ9OZOXVIOMLGTSWAMKMTDRSPGJKGBXQIVNRJRFRYEZ9VJDLHIKPSKMYC9YEGHFDS9SGVDHRIXBEMLFIINOHVPXIFAZCJKBHVMQZEVWCOSNWQRDYWVAIBLSCBGESJUIBWZECPUCAYAWMTQKRMCHONIPKJYYTEGZCJYCT9ABRWTJLRQXKMWY9GWZMHYZNWPXULNZAPVQLPMYQZCYNEPOCGOHBJUZLZDPIXVHLDMQYJUUBEDXXPXFLNRGIPWBRNQQZJSGSJTTYHIGGFAWJVXWL9THTPWOOHTNQWCNYOYZXALHAZXVMIZE9WMQUDCHDJMIBWKTYH9AC9AFOT9DPCADCV9ZWUTE9QNOMSZPTZDJLJZCJGHXUNBJFUBJWQUEZDMHXGBPTNSPZBR9TGSKVOHMOQSWPGFLSWNESFKSAZY9HHERAXALZCABFYPOVLAHMIHVDBGKUMDXC9WHHTIRYHZVWNXSVQUWCR9M9RAGMFEZZKZ9XEOQGOSLFQCHHOKLDSA9QCMDGCGMRYJZLBVIFOLBIJPROKMHOYTBTJIWUZWJMCTKCJKKTR9LCVYPVJI9AHGI9JOWMIWZAGMLDFJA9WU9QAMEFGABIBEZNNAL9OXSBFLOEHKDGHWFQSHMPLYFCNXAAZYJLMQDEYRGL9QKCEUEJ9LLVUOINVSZZQHCIKPAGMT9CAYIIMTTBCPKWTYHOJIIY9GYNPAJNUJ9BKYYXSV9JSPEXYMCFAIKTGNRSQGUNIYZCRT9FOWENSZQPD9ALUPYYAVICHVYELYFPUYDTWUSWNIYFXPX9MICCCOOZIWRNJIDALWGWRATGLJXNAYTNIZWQ9YTVDBOFZRKO9CFWRPAQQRXTPACOWCPRLYRYSJARRKSQPR9TCFXDVIXLP9XVL99ERRDSOHBFJDJQQGGGCZNDQ9NYCTQJWVZIAELCRBJJFDMCNZU9FIZRPGNURTXOCDSQGXTQHKHUECGWFUUYS9J9NYQ9U9P9UUP9YMZHWWWCIASCFLCMSKTELZWUGCDE9YOKVOVKTAYPHDF9ZCCQAYPJIJNGSHUIHHCOSSOOBUDOKE9CJZGYSSGNCQJVBEFTZFJ9SQUHOASKRRGBSHWKBCBWBTJHOGQ9WOMQFHWJVEG9NYX9KWBTCAIXNXHEBDIOFO9ALYMFGRICLCKKLG9FOBOX9PDWNQRGHBKHGKKRLWTBEQMCWQRLHAVYYZDIIPKVQTHYTWQMTOACXZOQCDTJTBAAUWXSGJF9PNQIJ9AJRUMUVCPWYVYVARKR9RKGOUHHNKNVGGPDDLGKPQNOYHNKAVVKCXWXOQPZNSLATUJT9AUWRMPPSWHSTTYDFAQDXOCYTZHOYYGAIM9CELMZ9AZPWB9MJXGHOKDNNSZVUDAGXTJJSSZCPZVPZBYNNTUQABSXQWZCHDQSLGK9UOHCFKBIBNETK999999999999999999999999999999999999999999999999999999999999999999999999999999999NOXDXXKUDWLOFJLIPQIBRBMGDYCPGDNLQOLQS99EQYKBIU9VHCJVIPFUYCQDNY9APGEVYLCENJIOBLWNB999999999XKBRHUD99C99999999NKZKEKWLDKMJCI9N9XQOLWEPAYWSH9999999999999999999999999KDDTGZLIPBNZKMLTOLOXQVNGLASESDQVPTXALEKRMIOHQLUHD9ELQDBQETS9QFGTYOYWLNTSKKMVJAUXSIROUICDOXKSYZTDPEDKOQENTJOWJONDEWROCEJIEWFWLUAACVSJFTMCHHXJBJRKAAPUDXXVXFWP9X9999IROUICDOXKSYZTDPEDKOQENTJOWJONDEWROCEJIEWFWLUAACVSJFTMCHHXJBJRKAAPUDXXVXFWP9X9999"; + private static final String TEST_INVALID_TRYTES = "BYSWEAUTWXHXZ9YBZISEK9LUHWGMHXCGEVNZHRLUWQFCUSDXZHOFHWHL9MQPVJXXZLIXPXPXF9KYEREFSKCPKYIIKPZVLHUTDFQKKVVBBN9ATTLPCNPJDWDEVIYYLGPZGCWXOBDXMLJC9VO9QXTTBLAXTTBFUAROYEGQIVB9MJWJKXJMCUPTWAUGFZBTZCSJVRBGMYXTVBDDS9MYUJCPZ9YDWWQNIPUAIJXXSNLKUBSCOIJPCLEFPOXFJREXQCUVUMKSDOVQGGHRNILCO9GNCLWFM9APMNMWYASHXQAYBEXF9QRIHIBHYEJOYHRQJAOKAQ9AJJFQ9WEIWIJOTZATIBOXQLBMIJU9PCGBLVDDVFP9CFFSXTDUXMEGOOFXWRTLFGV9XXMYWEMGQEEEDBTIJ9OJOXFAPFQXCDAXOUDMLVYRMRLUDBETOLRJQAEDDLNVIRQJUBZBO9CCFDHIX9MSQCWYAXJVWHCUPTRSXJDESISQPRKZAFKFRULCGVRSBLVFOPEYLEE99JD9SEBALQINPDAZHFAB9RNBH9AZWIJOTLBZVIEJIAYGMC9AZGNFWGRSWAXTYSXVROVNKCOQQIWGPNQZKHUNODGYADPYLZZZUQRTJRTODOUKAOITNOMWNGHJBBA99QUMBHRENGBHTH9KHUAOXBVIVDVYYZMSEYSJWIOGGXZVRGN999EEGQMCOYVJQRIRROMPCQBLDYIGQO9AMORPYFSSUGACOJXGAQSPDY9YWRRPESNXXBDQ9OZOXVIOMLGTSWAMKMTDRSPGJKGBXQIVNRJRFRYEZ9VJDLHIKPSKMYC9YEGHFDS9SGVDHRIXBEMLFIINOHVPXIFAZCJKBHVMQZEVWCOSNWQRDYWVAIBLSCBGESJUIBWZECPUCAYAWMTQKRMCHONIPKJYYTEGZCJYCT9ABRWTJLRQXKMWY9GWZMHYZNWPXULNZAPVQLPMYQZCYNEPOCGOHBJUZLZDPIXVHLDMQYJUUBEDXXPXFLNRGIPWBRNQQZJSGSJTTYHIGGFAWJVXWL9THTPWOOHTNQWCNYOYZXALHAZXVMIZE9WMQUDCHDJMIBWKTYH9AC9AFOT9DPCADCV9ZWUTE9QNOMSZPTZDJLJZCJGHXUNBJFUBJWQUEZDMHXGBPTNSPZBR9TGSKVOHMOQSWPGFLSWNESFKSAZY9HHERAXALZCABFYPOVLAHMIHVDBGKUMDXC9WHHTIRYHZVWNXSVQUWCR9M9RAGMFEZZKZ9XEOQGOSLFQCHHOKLDSA9QCMDGCGMRYJZLBVIFOLBIJPROKMHOYTBTJIWUZWJMCTKCJKKTR9LCVYPVJI9AHGI9JOWMIWZAGMLDFJA9WU9QAMEFGABIBEZNNAL9OXSBFLOEHKDGHWFQSHMPLYFCNXAAZYJLMQDEYRGL9QKCEUEJ9LLVUOINVSZZQHCIKPAGMT9CAYIIMTTBCPKWTYHOJIIY9GYNPAJNUJ9BKYYXSV9JSPEXYMCFAIKTGNRSQGUNIYZCRT9FOWENSZQPD9ALUPYYAVICHVYELYFPUYDTWUSWNIYFXPX9MICCCOOZIWRNJIDALWGWRATGLJXNAYTNIZWQ9YTVDBOFZRKO9CFWRPAQQRXTPACOWCPRLYRYSJARRKSQPR9TCFXDVIXLP9XVL99ERRDSOHBFJDJQQGGGCZNDQ9NYCTQJWVZIAELCRBJJFDMCNZU9FIZRPGNURTXOCDSQGXTQHKHUECGWFUUYS9J9NYQ9U9P9UUP9YMZHWWWCIASCFLCMSKTELZWUGCDE9YOKVOVKTAYPHDF9ZCCQAYPJIJNGSHUIHHCOSSOOBUDOKE9CJZGYSSGNCQJVBEFTZFJ9SQUHOASKRRGBSHWKBCBWBTJHOGQ9WOMQFHWJVEG9NYX9KWBTCAIXNXHEBDIOFO9ALYMFGRICLCKKLG9FOBOX9PDWNQRGHBKHGKKRLWTBEQMCWQRLHAVYYZDIIPKVQTHYTWQMTOACXZOQCDTJTBAAUWXSGJF9PNQIJ9AJRUMUVCPWYVYVARKR9RKGOUHHNKNVGGPDDLGKPQNOYHNKAVVKCXWXOQPZNSLATUJT9AUWRMPPSWHSTTYDFAQDXOCYTZHOYYGAIM9CELMZ9AZPWB9MJXGHOKDNNSZVUDAGXTJJSSZCPZVPZBYNNTUQABSXQWZCHDQSLGK9UOHCFKBIBNETK999999999999999999999999999999999999999999999999999999999999999999999999999999999NOXDXXKUDWLOFJLIPQIBRBMGDYCPGDNLQOLQS99EQYKBIU9VHCJVIPFUYCQDNY9APGEVYLCENJIOBLWNB999999999XKBRHUD99C99999999NKZKEKWLDKMJCI9N9XQOLWEPAYWSH9999999999999999999999999KDDTGZLIPBNZKMLTOLOXQVNGLASESDQVPTXALEKRMIOHQLUHD9ELQDBQETS9QFGTYOYWLNTSKKMVJAUXSIROUICDOXKSYZTDPEDKOQENTJOWJONDEWROCEJIEWFWLUAACVSJFTMCHHXJBJRKAAPUDXXVXFWP9X9999IROUICDOXKSYZTDPEDKOQENTJOWJONDEWROCEJIEWFWLUAACVSJFTMCHHXJBJRKAAPUDXXVXFWP9X9999"; + private static final String TEST_TRYTES = "JUSTANOTHERTEST999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999PNGMCSNRCTRHCHPXYTPKEJYPCOWKOMRXZFHH9N9VDIKMNVAZCMIYRHVJIAZARZTUETJVFDMBEBIQE9QTH999999999999999999999999999JOTASPAM9999999999999999999VADPPWD99999999999999999999AQKWPYWBUEPGRZAVQUKYAVRPPNEIZZFHHLBESBBINMZCDU9GYMQAUKXSDLAHCB9XCFEPACLJGLHFUSTWJ999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999"; private static final String TEST_MILESTONE = "SMYMAKKPSUKCKDRUEYCGZJTYCZ9HHDMDUWBAPXARGURPQRHTAJDASRWMIDTPTBNDKDEFBUTBGGAFX9999"; private static final Integer TEST_MILESTONE_INDEX = 8059; private static final String TEST_MESSAGE = "JOTA"; @@ -59,7 +59,7 @@ public class IotaAPITest { , "WDTFFXHBHMFQQVXQLBFJFVVHVIIAVYM9PFAZCHMKET9ESMHIRHSMVDJBZTXPTAFVIASMSXRDCIYVWVQNO" , "XCCPS9GMTSUB9DXPVKLTBDHOFX9PJMBYZQYQEXMRQDPGQPLWRGZGXODYJKGVFOHHYUJRCSXAIDGYSAWRB" , "KVEBCGMEOPDPRCQBPIEMZTTXYBURGZVNH9PLHKPMM9D9FUKWIGLKZROGNSYIFHULLWQWXCNAW9HKKVIDC"}; - + private static Gson gson = new GsonBuilder().create(); private IotaAPI iotaClient; @Before @@ -75,8 +75,8 @@ public class IotaAPITest { @Test - public void shouldGetInputs() { - GetBalancesAndFormatResponse res = iotaClient.getInputs(TEST_SEED1, 0, 0, 0); + public void shouldGetInputs() throws InvalidSecurityLevelException, InvalidAddressException { + GetBalancesAndFormatResponse res = iotaClient.getInputs(TEST_SEED1, 2, 0, 0, 0); System.out.println(res); assertThat(res, IsNull.notNullValue()); assertThat(res.getTotalBalance(), IsNull.notNullValue()); @@ -84,25 +84,24 @@ public class IotaAPITest { } - @Test - public void shouldCreateANewAddress() { - final GetNewAddressResponse res = iotaClient.getNewAddress(TEST_SEED1, 0, false, 100, false); - assertThat(res.getAddresses().get(0), Is.is(TEST_ADDRESS_WITHOUT_CHECKSUM)); - System.out.println(new Gson().toJson(res)); + public void shouldCreateANewAddressWithoutChecksum() throws InvalidSecurityLevelException, InvalidAddressException { + final GetNewAddressResponse res1 = iotaClient.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); + 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); + assertThat(res3.getAddresses().get(0), Is.is(TEST_ADDRESS_WITHOUT_CHECKSUM_SECURITY_LEVEL_3)); } @Test - public void shouldPrepareTransfer() { + public void shouldPrepareTransfer() throws InvalidSecurityLevelException, NotEnoughBalanceException, InvalidAddressException, InvalidTransferException { 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, 1, TEST_MESSAGE, TEST_TAG)); - List trytes = null; - try { - trytes = iotaClient.prepareTransfers(TEST_SEED1, transfers, null, null); - } catch (NotEnoughBalanceException e) { - e.printStackTrace(); - } + 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, 1, TEST_MESSAGE, TEST_TAG)); + List trytes = iotaClient.prepareTransfers(TEST_SEED1, 2, transfers, null, null); Assert.assertNotNull(trytes); assertThat(trytes.isEmpty(), Is.is(false)); } @@ -119,15 +118,21 @@ public class IotaAPITest { assertThat(ftr, IsNull.notNullValue()); } - @Test + @Test(expected = ArgumentException.class) + public void shouldNotGetBundle() throws InvalidBundleException, ArgumentException, InvalidSignatureException { + GetBundleResponse gbr = iotaClient.getBundle(TEST_HASH); + assertThat(gbr, IsNull.notNullValue()); + } + + @Test(expected = ArgumentException.class) public void shouldGetBundle() throws InvalidBundleException, ArgumentException, InvalidSignatureException { GetBundleResponse gbr = iotaClient.getBundle(TEST_HASH); assertThat(gbr, IsNull.notNullValue()); } @Test - public void shouldGetTransfers() throws InvalidBundleException, ArgumentException, InvalidSignatureException, NoInclusionStatesExcpection, NoNodeInfoException { - GetTransferResponse gtr = iotaClient.getTransfers(TEST_SEED1, 0, 0, false); + public void shouldGetTransfers() throws InvalidBundleException, ArgumentException, InvalidSignatureException, NoInclusionStatesException, NoNodeInfoException, InvalidSecurityLevelException, InvalidAddressException { + GetTransferResponse gtr = iotaClient.getTransfers(TEST_SEED1, 2, 0, 0, false); assertThat(gtr.getTransfers(), IsNull.notNullValue()); for (Bundle test : gtr.getTransfers()) { @@ -139,24 +144,38 @@ public class IotaAPITest { @Ignore @Test - public void shouldSendTrytes() { + public void shouldReplayBundle() throws InvalidTrytesException, InvalidBundleException, InvalidSignatureException, ArgumentException { + ReplayBundleResponse rbr = iotaClient.replayBundle(TEST_TRYTES, 9, 18); + assertThat(rbr, IsNull.notNullValue()); + } + + @Ignore + @Test(expected = InvalidTrytesException.class) + public void shouldNotSendTrytes() throws InvalidTrytesException { + iotaClient.sendTrytes(new String[]{TEST_INVALID_TRYTES}, 9, 18); + } + + @Ignore + @Test + public void shouldSendTrytes() throws InvalidTrytesException { iotaClient.sendTrytes(new String[]{TEST_TRYTES}, 9, 18); } + @Ignore @Test(expected = IllegalStateException.class) - public void shouldNotSendTransfer() throws ArgumentException, InvalidSignatureException, InvalidBundleException, NotEnoughBalanceException { + public void shouldNotSendTransfer() throws ArgumentException, InvalidSignatureException, InvalidBundleException, NotEnoughBalanceException, InvalidSecurityLevelException, InvalidTrytesException, InvalidAddressException, InvalidTransferException { List transfers = new ArrayList<>(); - transfers.add(new jota.model.Transfer(TEST_ADDRESS_WITHOUT_CHECKSUM, 10000990, "JUSTANOTHERTEST", TEST_TAG)); - SendTransferResponse str = iotaClient.sendTransfer(TEST_SEED2, 9, 18, transfers, null, null); + transfers.add(new jota.model.Transfer(TEST_ADDRESS_WITHOUT_CHECKSUM_SECURITY_LEVEL_2, 10000990, "JUSTANOTHERTEST", TEST_TAG)); + SendTransferResponse str = iotaClient.sendTransfer(TEST_SEED2, 2, 9, 18, transfers, null, null); assertThat(str.getSuccessfully(), IsNull.notNullValue()); } @Ignore @Test - public void shouldSendTransfer() throws ArgumentException, InvalidSignatureException, InvalidBundleException, NotEnoughBalanceException { + public void shouldSendTransfer() throws ArgumentException, InvalidSignatureException, InvalidBundleException, NotEnoughBalanceException, InvalidSecurityLevelException, InvalidTrytesException, InvalidAddressException, InvalidTransferException { List transfers = new ArrayList<>(); - transfers.add(new jota.model.Transfer(TEST_ADDRESS_WITHOUT_CHECKSUM, 0, "JUSTANOTHERTEST", TEST_TAG)); - SendTransferResponse str = iotaClient.sendTransfer(TEST_SEED2, 9, 18, transfers, null, null); + transfers.add(new jota.model.Transfer(TEST_ADDRESS_WITHOUT_CHECKSUM_SECURITY_LEVEL_2, 0, "JUSTANOTHERTEST", TEST_TAG)); + SendTransferResponse str = iotaClient.sendTransfer(TEST_SEED2, 2, 9, 18, transfers, null, null); assertThat(str.getSuccessfully(), IsNull.notNullValue()); } } \ No newline at end of file diff --git a/src/test/java/jota/IotaCoreApiTest.java b/src/test/java/jota/IotaCoreApiTest.java index 8913816..7e3ed96 100644 --- a/src/test/java/jota/IotaCoreApiTest.java +++ b/src/test/java/jota/IotaCoreApiTest.java @@ -9,7 +9,7 @@ import org.junit.Test; import static org.junit.Assert.assertThat; /** - * Created by Adrian on 15.01.2017. + * @author Adrian */ public class IotaCoreApiTest { @@ -51,13 +51,13 @@ public class IotaCoreApiTest { assertThat(neighbors.getNeighbors(), IsNull.notNullValue()); } - @Test + @Test(expected = IllegalAccessError.class) public void shouldAddNeighbors() { AddNeighborsResponse res = proxy.addNeighbors("udp://8.8.8.8:14265"); assertThat(res, IsNull.notNullValue()); } - @Test + @Test(expected = IllegalAccessError.class) public void shouldRemoveNeighbors() { RemoveNeighborsResponse res = proxy.removeNeighbors("udp://8.8.8.8:14265"); assertThat(res, IsNull.notNullValue()); @@ -77,7 +77,7 @@ public class IotaCoreApiTest { @Test public void shouldFindTransactionsByApprovees() { - FindTransactionResponse trans = proxy.findTransactionsByApprovees(new String[]{TEST_HASH}); + FindTransactionResponse trans = proxy.findTransactionsByApprovees(TEST_HASH); assertThat(trans.getHashes(), IsNull.notNullValue()); } @@ -100,15 +100,15 @@ public class IotaCoreApiTest { } - @Test - public void shouldGetInclusionStates() { + @Test(expected = IllegalAccessError.class) + public void shouldNotGetInclusionStates() { GetInclusionStateResponse res = proxy.getInclusionStates(new String[]{"DBPECSH9YLSSTQDGERUHJBBJTKVUDBMTJLG9WPHBINGHIFOSJMDJLARTVOXXWEFQJLLBINOHCZGYFSMUEXWPPMTOFW"}, new String[]{"EJDQOQHMLJGBMFWB9WJSPRCYIGNPO9WRHDCEQXIMPVPIJ9JV9RJGVHNX9EPGXFOOKBABCVMMAAX999999"}); assertThat(res.getStates(), IsNull.notNullValue()); } - @Test(expected = IllegalAccessError.class) - public void shouldNotGetInclusionStates() { - GetInclusionStateResponse res = proxy.getInclusionStates(new String[]{TEST_ADDRESS_WITH_CHECKSUM}, new String[]{"DNSBRJWNOVUCQPILOQIFDKBFJMVOTGHLIMLLRXOHFTJZGRHJUEDAOWXQRYGDI9KHYFGYDWQJZKX999999"}); + @Test + public void shouldGetInclusionStates() { + GetInclusionStateResponse res = proxy.getInclusionStates(new String[]{TEST_ADDRESS_WITH_CHECKSUM}, new String[]{proxy.getNodeInfo().getLatestSolidSubtangleMilestone()}); assertThat(res.getStates(), IsNull.notNullValue()); } @@ -129,10 +129,9 @@ public class IotaCoreApiTest { @Test public void shouldGetBalances() { GetBalancesResponse res = proxy.getBalances(100, new String[]{TEST_ADDRESS_WITH_CHECKSUM}); - System.err.println(res); assertThat(res.getBalances(), IsNull.notNullValue()); assertThat(res.getMilestone(), IsNull.notNullValue()); assertThat(res.getMilestoneIndex(), IsNull.notNullValue()); - + assertThat(res.getDuration(), IsNull.notNullValue()); } } diff --git a/src/test/java/jota/IotaMultisigTest.java b/src/test/java/jota/IotaMultisigTest.java new file mode 100644 index 0000000..91bbe0b --- /dev/null +++ b/src/test/java/jota/IotaMultisigTest.java @@ -0,0 +1,87 @@ +package jota; + +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import jota.error.InvalidAddressException; +import jota.error.InvalidBundleException; +import jota.error.InvalidTransferException; +import jota.model.Bundle; +import jota.model.Transaction; +import jota.model.Transfer; +import jota.pow.JCurl; +import jota.utils.Converter; +import jota.utils.Multisig; +import jota.utils.Signing; +import org.junit.Before; +import org.junit.Test; + +import java.util.ArrayList; +import java.util.List; + +import static org.junit.Assert.assertTrue; + +/** + * Created by Adrian on 18.02.2017. + */ +public class IotaMultisigTest { + + private static final String TEST_SEED1 = "ABCDFG"; + private static final String TEST_SEED2 = "FDSAG"; + private static final String REMAINDER_ADDRESS = "NZRALDYNVGJWUVLKDWFKJVNYLWQGCWYCURJIIZRLJIKSAIVZSGEYKTZRDBGJLOA9AWYJQB9IPWRAKUC9FBDRZJZXZG"; + private static final String RECEIVE_ADDRESS = "ZGHXPZYDKXPEOSQTAQOIXEEI9K9YKFKCWKYYTYAUWXK9QZAVMJXWAIZABOXHHNNBJIEBEUQRTBWGLYMTX"; + + private static Gson gson = new GsonBuilder().create(); + private IotaAPI iotaClient; + + @Before + public void createApiClientInstance() { + iotaClient = new IotaAPI.Builder().build(); + } + + @Test + public void basicMultiSigTest() throws InvalidBundleException, InvalidTransferException, InvalidAddressException { + + Multisig ms = new Multisig(); + + // First co-signer uses security level 3 and index 0 for the private key + String digestOne = ms.getDigest(TEST_SEED1, 3, 0); + + // We initiate the multisig address generation by absorbing the key digest + String initiatedMultisigDigests = ms.addAddressDigest(digestOne, ""); + + // Second cosigner also uses security level 3 and index 0 for the private key + String digestTwo = ms.getDigest(TEST_SEED2, 3, 0); + + // Add the multisig by absorbing the second cosigners key digest + String finalMultisigDigests = ms.addAddressDigest(digestTwo, initiatedMultisigDigests); + + // finally we generate the multisig address itself + String multiSigAddress = ms.finalizeAddress(finalMultisigDigests); + + System.out.println("MultisigAddress = " + multiSigAddress); + + boolean isValidMultisigAddress = ms.validateAddress(multiSigAddress, new int[][]{Converter.trits(digestOne), Converter.trits(digestTwo)}); + + 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); + + List trxs = iotaClient.initiateTransfer(6, multiSigAddress, REMAINDER_ADDRESS, transfers, true); + + Bundle bundle = new Bundle(trxs, trxs.size()); + + bundle = ms.addSignature(bundle, multiSigAddress, ms.getKey(TEST_SEED1, 0, 3)); + + bundle = ms.addSignature(bundle, multiSigAddress, ms.getKey(TEST_SEED2, 0, 3)); + + + Signing sgn = new Signing(new JCurl()); + + boolean isValidSignature = sgn.validateSignatures(bundle, multiSigAddress); + assertTrue("MultiSignature not valid", isValidSignature); + System.out.println("Result of multi-signature validation is " + isValidSignature); + } +} diff --git a/src/test/java/jota/IotaUnitConverterTest.java b/src/test/java/jota/IotaUnitConverterTest.java index 32976a6..a63e6de 100644 --- a/src/test/java/jota/IotaUnitConverterTest.java +++ b/src/test/java/jota/IotaUnitConverterTest.java @@ -7,7 +7,7 @@ import org.junit.Test; import static org.junit.Assert.assertEquals; /** - * Created by pinpong on 30.11.16. + * @author pinpong */ public class IotaUnitConverterTest { @@ -48,11 +48,11 @@ public class IotaUnitConverterTest { @Test public void shouldConvertRawIotaAmountToDisplayText() { - assertEquals(IotaUnitConverter.convertRawIotaAmountToDisplayText(1,false), "1 i"); - assertEquals(IotaUnitConverter.convertRawIotaAmountToDisplayText(1000,false), "1 Ki"); - assertEquals(IotaUnitConverter.convertRawIotaAmountToDisplayText(1000000,false), "1 Mi" ); - assertEquals(IotaUnitConverter.convertRawIotaAmountToDisplayText(1000000000,false), "1 Gi" ); - assertEquals(IotaUnitConverter.convertRawIotaAmountToDisplayText(1000000000000L,false), "1 Ti"); - assertEquals(IotaUnitConverter.convertRawIotaAmountToDisplayText(1000000000000000L,false), "1 Pi"); + assertEquals(IotaUnitConverter.convertRawIotaAmountToDisplayText(1, false), "1 i"); + assertEquals(IotaUnitConverter.convertRawIotaAmountToDisplayText(1000, false), "1 Ki"); + assertEquals(IotaUnitConverter.convertRawIotaAmountToDisplayText(1000000, false), "1 Mi"); + assertEquals(IotaUnitConverter.convertRawIotaAmountToDisplayText(1000000000, false), "1 Gi"); + assertEquals(IotaUnitConverter.convertRawIotaAmountToDisplayText(1000000000000L, false), "1 Ti"); + assertEquals(IotaUnitConverter.convertRawIotaAmountToDisplayText(1000000000000000L, false), "1 Pi"); } } diff --git a/src/test/java/jota/SeedRandomGeneratorTest.java b/src/test/java/jota/SeedRandomGeneratorTest.java index b2ab6d2..0876dfe 100644 --- a/src/test/java/jota/SeedRandomGeneratorTest.java +++ b/src/test/java/jota/SeedRandomGeneratorTest.java @@ -8,13 +8,12 @@ import org.junit.Test; import static org.junit.Assert.assertEquals; /** - * Created by pinpong on 13.12.16. + * @author pinpong */ public class SeedRandomGeneratorTest { @Test public void shouldGenerateNewSeed() { - String generatedSeed = SeedRandomGenerator.generateNewSeed(); assertEquals(InputValidator.isAddress(generatedSeed), true); assertEquals(generatedSeed.length(), Constants.SEED_LENGTH_MAX); diff --git a/src/test/java/jota/SendMessageTest.java b/src/test/java/jota/SendMessageTest.java index 9a62c04..19d7d67 100644 --- a/src/test/java/jota/SendMessageTest.java +++ b/src/test/java/jota/SendMessageTest.java @@ -3,10 +3,10 @@ package jota; import org.junit.Test; public class SendMessageTest { - - @Test - public void sendMessage() { - - } + + @Test + public void sendMessage() { + + } } diff --git a/src/test/java/jota/TrytesConverterTest.java b/src/test/java/jota/TrytesConverterTest.java index f6403e5..9c65c4f 100644 --- a/src/test/java/jota/TrytesConverterTest.java +++ b/src/test/java/jota/TrytesConverterTest.java @@ -8,7 +8,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; /** - * Created by pinpong on 01.12.16. + * @author pinpong */ public class TrytesConverterTest {