diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000..964491c
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,13 @@
+language: java
+jdk:
+- oraclejdk8
+script: mvn package
+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
diff --git a/README.md b/README.md
index c0f5a0e..915be80 100644
--- a/README.md
+++ b/README.md
@@ -4,11 +4,11 @@ The JOTA library is a simple Java wrapper around [[IOTA]](http://www.iotatoken.c
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:** 1.0.0 Release
-* **Compatibility:** in development to be fully compatible with IOTA IRI v1.1.0
+* **Latest release:** 0.9.0 RC1
+* **Compatibility:** fully compatible with IOTA IRI v1.2.4
* **API coverage:** 14 of 14 commands fully implemented
* **License:** Apache License 2.0
-* **Readme updated:** 2016-11-12 21:05:02 (UTC)
+* **Readme updated:** 2016-01-19 21:05:02 (UTC)
A list of all *IOTA* JSON-REST API commands currently supported by jota wrapper can be found in the `Commands` enum (see [here](https://github.com/davassi/JOTA/blob/master/src/main/java/jota/IotaAPICommands.java) for more details).
@@ -32,27 +32,33 @@ Other dependencies:
Connect to your local node with the default settings is quite straightforward: it requires only 2 lines of code. For example, in order to fetch the Node Info:
- IotaApiProxy api = new IotaApiProxy.Builder.build();
+ IotaApi api = new IotaApi.Builder.build();
GetNodeInfoResponse response = api.getNodeInfo();
-of if you need to connect to a remote node on https:
+of if you need to connect to a remote node:
- IotaApiProxy api = new IotaApiProxy.Builder
- .protocol("https")
+ IotaApi api = new IotaApi.Builder
+ .protocol("http")
.nodeAddress("somewhere_over_the_rainbow")
- .port(54321)
+ .port(14265)
.build();
GetNodeInfoResponse response = api.getNodeInfo();
-Jota is still *not* in the central maven repository. It will be available when it will cover 100% iota's rest interface.
+In order to communicate with *IOTA node*, JOTA needs to be aware of your node's exact configuration. If you dont want to use the builder the easiest way of providing this information is via a `node_config.properties` file, for example:
-In order to communicate with *IOTA node*, JOTA needs to be aware of your node's exact configuration. The easiest way of providing this information is via a `node_config.properties` file, for example:
-
- iota.node.protocol=http
+ iota.node.protocol=http``****************``
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.
+
+##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"
+
That's it!
##Examples
@@ -63,7 +69,5 @@ There's an extensive list of test coverages on the src/test/java package of the
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: `3FGCHqhG1SUpgn2eS1Agq2KnxJemWnQFbB`
-
-
-
+* Bitcoin (Gianni Davassi): `3FGCHqhG1SUpgn2eS1Agq2KnxJemWnQFbB`
+* Bitcoin (Adrian Ziser): `3FGCHqhG1SUpgn2eS1Agq2KnxJemWnQFbB`
\ No newline at end of file
diff --git a/node_config.properties b/node_config.properties
index e5e5a5a..fbd32d9 100644
--- a/node_config.properties
+++ b/node_config.properties
@@ -1,5 +1,7 @@
iota.node.protocol=http
-#iota.node.host=138.68.126.141
iota.node.host=node.iotawallet.info
+#iota.node.host=138.68.90.186
+#iota.node.host=192.168.11.2
+#iota.node.host=138.68.90.186
iota.node.port=14265
diff --git a/pom.xml b/pom.xml
index 70b381e..31625ee 100644
--- a/pom.xml
+++ b/pom.xml
@@ -2,12 +2,20 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
4.0.0
- com.iota
+ org.iotajota
- 1.0.0-RELEASE
+ 0.9.0-RC1JOTAJOTA 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
+
+
+
1.7UTF-8
@@ -63,6 +71,7 @@
4.12test
+
@@ -91,6 +100,13 @@
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+
+ true
+
+
diff --git a/src/main/java/jota/IotaAPI.java b/src/main/java/jota/IotaAPI.java
new file mode 100644
index 0000000..ad1353d
--- /dev/null
+++ b/src/main/java/jota/IotaAPI.java
@@ -0,0 +1,836 @@
+package jota;
+
+import jota.dto.response.*;
+import jota.error.*;
+import jota.model.*;
+import jota.pow.ICurl;
+import jota.pow.JCurl;
+import jota.utils.*;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.*;
+
+/**
+ * IotaAPI Builder. Usage:
+ *
+ * GetNodeInfoResponse response = api.getNodeInfo();
+ *
+ * @author davassi
+ */
+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);
+ customCurl = builder.customCurl;
+ }
+
+ /**
+ * 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
+ *
+ * @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
+ */
+ public GetNewAddressResponse getNewAddress(final String seed, final int index, final boolean checksum, final int total, final boolean returnAll) {
+ StopWatch stopWatch = new StopWatch();
+
+ List allAddresses = new ArrayList<>();
+
+ // If total number of addresses to generate is supplied, simply generate
+ // and return the list of all addresses
+ if (total != 0) {
+ for (int i = index; i < index + total; i++) {
+ allAddresses.add(IotaAPIUtils.newAddress(seed, i, checksum, customCurl));
+ }
+ return GetNewAddressResponse.create(allAddresses, stopWatch.getElapsedTimeMili());
+ }
+ // 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 FindTransactionResponse response = findTransactionsByAddresses(newAddress);
+
+ allAddresses.add(newAddress);
+ if (response.getHashes().length == 0) {
+ break;
+ }
+ }
+
+ // If !returnAll return only the last address that was generated
+ if (!returnAll) {
+
+ //allAddresses = allAddresses.subList(allAddresses.size() - 2, allAddresses.size() - 1);
+ allAddresses = allAddresses.subList(allAddresses.size() - 1, allAddresses.size());
+ }
+ return GetNewAddressResponse.create(allAddresses, stopWatch.getElapsedTimeMili());
+ }
+
+ /**
+ * @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 {
+ StopWatch stopWatch = new StopWatch();
+ // validate & if needed pad seed
+ if ((seed = InputValidator.validateSeed(seed)) == null) {
+ throw new IllegalStateException("Invalid Seed");
+ }
+
+ start = start != null ? 0 : start;
+
+ if (start > end || end > (start + 500)) {
+ throw new ArgumentException();
+ }
+ StopWatch sw = new StopWatch();
+
+ System.out.println("GetTransfer started");
+ GetNewAddressResponse gnr = getNewAddress(seed, start, false, end == null ? end - start : 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 {
+
+ List trxs = findTransactionObjects(addresses);
+ // set of tail transactions
+ List tailTransactions = new ArrayList<>();
+ List nonTailBundleHashes = new ArrayList<>();
+
+ for (Transaction trx : trxs) {
+ // Sort tail and nonTails
+ if (Long.parseLong(trx.getCurrentIndex()) == 0) {
+ tailTransactions.add(trx.getHash());
+ } else {
+ if (nonTailBundleHashes.indexOf(trx.getBundle()) == -1) {
+ nonTailBundleHashes.add(trx.getBundle());
+ }
+ }
+ }
+
+ List bundleObjects = findTransactionObjectsByBundle(nonTailBundleHashes.toArray(new String[nonTailBundleHashes.size()]));
+ for (Transaction trx : bundleObjects) {
+ // Sort tail and nonTails
+ if (Long.parseLong(trx.getCurrentIndex()) == 0) {
+ if (tailTransactions.indexOf(trx.getHash()) == -1) {
+ tailTransactions.add(trx.getHash());
+ }
+ }
+ }
+
+ final List finalBundles = new ArrayList<>();
+ final String[] tailTxArray = tailTransactions.toArray(new String[tailTransactions.size()]);
+
+ // If inclusionStates, get the confirmation status
+ // of the tail transactions, and thus the bundles
+ GetInclusionStateResponse gisr = null;
+ if (tailTxArray != null && tailTxArray.length != 0 && inclusionStates) {
+ try {
+ gisr = getLatestInclusion(tailTxArray);
+ } catch (IllegalAccessError ignored) {
+ throw new NoInclusionStatesExcpection();
+ }
+ if (gisr == null || gisr.getStates() == null || gisr.getStates().length == 0) {
+ throw new NoInclusionStatesExcpection();
+ }
+ }
+ final GetInclusionStateResponse finalInclusionStates = gisr;
+ Parallel.For(Arrays.asList(tailTxArray),
+ new Parallel.Operation() {
+ public void perform(String param) {
+
+ try {
+ GetBundleResponse bundleResponse = getBundle(param);
+ Bundle gbr = new Bundle(bundleResponse.getTransactions(), bundleResponse.getTransactions().size());
+ if (gbr != null && gbr.getTransactions() != null) {
+ if (inclusionStates) {
+ boolean thisInclusion = finalInclusionStates.getStates()[Arrays.asList(tailTxArray).indexOf(param)];
+ for (Transaction t : gbr.getTransactions()) {
+ t.setPersistence(thisInclusion);
+ }
+ }
+ finalBundles.add(gbr);
+ }
+ // If error returned from getBundle, simply ignore it because the bundle was most likely incorrect
+ } catch (InvalidBundleException | ArgumentException | InvalidSignatureException e) {
+ log.warn("GetBundleError: ", e);
+ }
+ }
+ });
+
+ Collections.sort(finalBundles);
+ Bundle[] returnValue = new Bundle[finalBundles.size()];
+ for (int i = 0; i < finalBundles.size(); i++) {
+ returnValue[i] = new Bundle(finalBundles.get(i).getTransactions(), finalBundles.get(i).getTransactions().size());
+ }
+ return returnValue;
+ }
+
+ /**
+ * @param trytes
+ * @return a StoreTransactionsResponse
+ */
+ public StoreTransactionsResponse broadcastAndStore(final String... trytes) throws BroadcastAndStoreException {
+
+ try {
+ broadcastTransactions(trytes);
+ } catch (Exception e) {
+ log.error("Impossible to broadcastAndStore, aborting.", e);
+ throw new BroadcastAndStoreException();
+ }
+ return storeTransactions(trytes);
+ }
+
+ /**
+ * Facade method: Gets transactions to approve, attaches to Tangle, broadcasts and stores
+ *
+ * @param {array} trytes
+ * @param {int} depth
+ * @param {int} minWeightMagnitude
+ * @return
+ */
+ public List sendTrytes(final String[] trytes, final int depth, final int minWeightMagnitude) {
+ final GetTransactionsToApproveResponse txs = getTransactionsToApprove(depth);
+
+ // attach to tangle - do pow
+ final GetAttachToTangleResponse res = attachToTangle(txs.getTrunkTransaction(), txs.getBranchTransaction(), minWeightMagnitude, trytes);
+
+ try {
+ broadcastAndStore(res.getTrytes());
+ } catch (BroadcastAndStoreException e) {
+ return new ArrayList<>();
+ }
+
+ final List trx = new ArrayList<>();
+
+ for (final String tryte : Arrays.asList(res.getTrytes())) {
+ trx.add(new Transaction(tryte, customCurl));
+ }
+ return trx;
+ }
+
+ /**
+ * Wrapper function for getTrytes and transactionObjects
+ * gets the trytes and transaction object from a list of transaction hashes
+ *
+ * @param {array} hashes
+ * @return
+ * @method getTransactionsObjects
+ * @returns {function} callback
+ * @returns {object} success
+ **/
+ public List getTransactionsObjects(String[] hashes) {
+
+ if (!InputValidator.isArrayOfHashes(hashes)) {
+ throw new IllegalStateException("Not an Array of Hashes: " + Arrays.toString(hashes));
+ }
+
+ final GetTrytesResponse trytesResponse = getTrytes(hashes);
+
+ final List trxs = new ArrayList<>();
+
+ for (final String tryte : trytesResponse.getTrytes()) {
+ trxs.add(new Transaction(tryte, customCurl));
+ }
+ return trxs;
+ }
+
+ /**
+ * 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
+ **/
+ public List findTransactionObjects(String[] input) {
+ FindTransactionResponse ftr = findTransactions(input, null, null, null);
+ if (ftr == null || ftr.getHashes() == null)
+ return new ArrayList<>();
+ // get the transaction objects of the transactions
+ return getTransactionsObjects(ftr.getHashes());
+ }
+
+ /**
+ * 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
+ **/
+ public List findTransactionObjectsByBundle(String[] input) {
+ FindTransactionResponse ftr = findTransactions(null, null, null, input);
+ if (ftr == null || ftr.getHashes() == null)
+ return new ArrayList<>();
+
+ // get the transaction objects of the transactions
+ return getTransactionsObjects(ftr.getHashes());
+ }
+
+ /**
+ * 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 {
+
+ // Input validation of transfers object
+ if (!InputValidator.isTransfersCollectionCorrect(transfers)) {
+ throw new IllegalStateException("Invalid Transfer");
+ }
+
+ // validate & if needed pad seed
+ if ((seed = InputValidator.validateSeed(seed)) == null) {
+ throw new IllegalStateException("Invalid Seed");
+ }
+
+
+ // Create a new bundle
+ final Bundle bundle = new Bundle();
+ final List signatureFragments = new ArrayList<>();
+
+ long totalValue = 0;
+ 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() ? "999999999999999999999999999" : transfer.getTag();
+
+ // Pad for required 27 tryte length
+ tag = StringUtils.rightPad(tag, 27, '9');
+
+ // Add first entry to the bundle
+ bundle.addEntry(signatureMessageLength, transfer.getAddress(), transfer.getValue(), tag, timestamp);
+ // Sum up total value
+ totalValue += transfer.getValue();
+ }
+
+ // Get inputs if we are sending tokens
+ if (totalValue != 0) {
+
+ // Case 1: user provided inputs
+ // Validate the inputs by calling getBalances
+ if (inputs != null && !inputs.isEmpty()) {
+
+ // Get list if addresses of the provided inputs
+ List inputsAddresses = new ArrayList<>();
+ for (final Input i : inputs) {
+ inputsAddresses.add(i.getAddress());
+ }
+
+ GetBalancesResponse balancesResponse = getBalances(100, inputsAddresses);
+ String[] balances = balancesResponse.getBalances();
+
+ List confirmedInputs = new ArrayList<>();
+ int totalBalance = 0;
+ 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) {
+ Input inputEl = inputs.get(i++);
+ inputEl.setBalance(thisBalance);
+ confirmedInputs.add(inputEl);
+ }
+ }
+
+ // Return not enough balance error
+ if (totalValue > totalBalance) {
+ throw new IllegalStateException("Not enough balance");
+ }
+
+ return addRemainder(seed, confirmedInputs, bundle, tag, totalValue, null, signatureFragments);
+ }
+
+ // Case 2: Get inputs deterministically
+ //
+ // If no inputs provided, derive the addresses from the seed and
+ // confirm that the inputs exceed the threshold
+ else {
+
+ @SuppressWarnings("unchecked") GetBalancesAndFormatResponse newinputs = getInputs(seed, 0, 0, totalValue);
+ // If inputs with enough balance
+ return addRemainder(seed, newinputs.getInput(), bundle, tag, totalValue, null, signatureFragments);
+ }
+ } else {
+
+ // If no input required, don't sign and simply finalize the bundle
+ bundle.finalize(customCurl);
+ bundle.addTrytes(signatureFragments);
+
+ List trxb = bundle.getTransactions();
+ List bundleTrytes = new ArrayList<>();
+
+ for (Transaction trx : trxb) {
+ bundleTrytes.add(trx.toTrytes());
+ }
+ Collections.reverse(bundleTrytes);
+ return bundleTrytes;
+ }
+ }
+
+ /**
+ * Gets the inputs of a seed
+ *
+ * @param {string} seed
+ * @param {object} options
+ * @param {function} callback
+ * @method getInputs
+ * @property {int} start Starting key index
+ * @property {int} end Ending key index
+ * @property {int} threshold Min balance required
+ **/
+ public GetBalancesAndFormatResponse getInputs(String seed, int start, int end, long threshold) {
+ StopWatch stopWatch = new StopWatch();
+ // validate the seed
+ if (!InputValidator.isTrytes(seed, 0)) {
+ throw new IllegalStateException("Invalid Seed");
+ }
+
+ // validate & if needed pad seed
+ if ((seed = InputValidator.validateSeed(seed)) == null) {
+ throw new IllegalStateException("Invalid Seed");
+ }
+
+ // If start value bigger than end, return error
+ // or if difference between end and start is bigger than 500 keys
+ if (start > end || end > (start + 500)) {
+ throw new IllegalStateException("Invalid inputs provided");
+ }
+
+ // Case 1: start and end
+ //
+ // If start and end is defined by the user, simply iterate through the keys
+ // and call getBalances
+ if (end != 0) {
+
+ List allAddresses = new ArrayList<>();
+
+ for (int i = start; i < end; i++) {
+
+ String address = IotaAPIUtils.newAddress(seed, i, false, customCurl);
+ allAddresses.add(address);
+ }
+
+ return getBalanceAndFormat(allAddresses, threshold, start, end, stopWatch);
+ }
+ // Case 2: iterate till threshold || end
+ //
+ // Either start from index: 0 or start (if defined) until threshold is reached.
+ // 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);
+ }
+ }
+
+ // 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) {
+
+ GetBalancesResponse getBalancesResponse = getBalances(100, addresses);
+ List balances = Arrays.asList(getBalancesResponse.getBalances());
+
+ // If threshold defined, keep track of whether reached or not
+ // else set default to true
+ boolean thresholdReached = threshold == 0;
+ int i = -1;
+
+ List inputs = new ArrayList<>();
+ long totalBalance = 0;
+
+ for (String address : addresses) {
+
+ long balance = Long.parseLong(balances.get(++i));
+
+ if (balance > 0) {
+ final Input newEntry = new Input(address, balance, start + i);
+
+ inputs.add(newEntry);
+ // Increase totalBalance of all aggregated inputs
+ totalBalance += balance;
+
+ if (!thresholdReached && totalBalance >= threshold) {
+ thresholdReached = true;
+ break;
+ }
+ }
+ }
+
+ if (thresholdReached) {
+ return GetBalancesAndFormatResponse.create(inputs, totalBalance, stopWatch.getElapsedTimeMili());
+ }
+ throw new IllegalStateException("Not enough balance");
+ }
+
+ /**
+ * Gets the associated bundle transactions of a single transaction
+ * Does validation of signatures, total sum as well as bundle order
+ *
+ * @param {string} transaction Hash of a tail transaction
+ * @method getBundle
+ * @returns {list} bundle Transaction objects
+ **/
+ public GetBundleResponse getBundle(String transaction) throws ArgumentException, InvalidBundleException, InvalidSignatureException {
+ StopWatch stopWatch = new StopWatch();
+
+ Bundle bundle = traverseBundle(transaction, null, new Bundle());
+ if (bundle == null) {
+ throw new ArgumentException("Unknown Bundle");
+ }
+
+ long totalSum = 0;
+ String bundleHash = bundle.getTransactions().get(0).getBundle();
+
+ ICurl curl = new JCurl();
+ curl.reset();
+
+ List signaturesToValidate = new ArrayList<>();
+
+ for (int i = 0; i < bundle.getTransactions().size(); i++) {
+ Transaction trx = bundle.getTransactions().get(i);
+ Long bundleValue = Long.parseLong(trx.getValue());
+ totalSum += bundleValue;
+
+ if (i != Integer.parseInt(bundle.getTransactions().get(i).getCurrentIndex())) {
+ throw new ArgumentException("Invalid Bundle");
+ }
+
+ String trxTrytes = trx.toTrytes().substring(2187, 2187 + 162);
+ //System.out.println("Bundlesize "+bundle.getTransactions().size()+" "+trxTrytes);
+ // Absorb bundle hash + value + timestamp + lastIndex + currentIndex trytes.
+ curl.absorb(Converter.trits(trxTrytes));
+ // Check if input transaction
+ if (bundleValue < 0) {
+ String address = trx.getAddress();
+ Signature sig = new Signature();
+ sig.setAddress(address);
+ sig.getSignatureFragments().add(trx.getSignatureFragments());
+
+ // Find the subsequent txs with the remaining signature fragment
+ for (int y = i; y < bundle.getTransactions().size() - 1; y++) {
+ 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 (sig.getSignatureFragments().indexOf(newBundleTx.getSignatureFragments()) == -1)
+ sig.getSignatureFragments().add(newBundleTx.getSignatureFragments());
+ }
+ }
+ signaturesToValidate.add(sig);
+ }
+ }
+
+ // Check for total sum, if not equal 0 return error
+ if (totalSum != 0) throw new InvalidBundleException("Invalid Bundle Sum");
+ int[] bundleFromTrxs = new int[243];
+ curl.squeeze(bundleFromTrxs);
+ String bundleFromTxString = Converter.trytes(bundleFromTrxs);
+
+ // Check if bundle hash is the same as returned by tx object
+ if (!bundleFromTxString.equals(bundleHash)) throw new InvalidBundleException("Invalid Bundle Hash");
+ // 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()))
+ 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);
+
+ if (!isValidSignature) throw new InvalidSignatureException();
+ }
+
+ return GetBundleResponse.create(bundle.getTransactions(), stopWatch.getElapsedTimeMili());
+ }
+
+ /**
+ * 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 {
+ StopWatch stopWatch = new StopWatch();
+
+ List bundleTrytes = new ArrayList<>();
+
+ GetBundleResponse bundleResponse = getBundle(transaction);
+ Bundle bundle = new Bundle(bundleResponse.getTransactions(), bundleResponse.getTransactions().size());
+ for (Transaction trx : bundle.getTransactions()) {
+
+ bundleTrytes.add(trx.toTrytes());
+ }
+
+ List trxs = sendTrytes(bundleTrytes.toArray(new String[bundleTrytes.size()]), depth, minWeightMagnitude);
+
+ Boolean[] successful = new Boolean[trxs.size()];
+
+ for (int i = 0; i < trxs.size(); i++) {
+
+ final FindTransactionResponse response = findTransactionsByBundles(trxs.get(i).getBundle());
+
+
+ successful[i] = response.getHashes().length != 0;
+ }
+
+ return ReplayBundleResponse.create(successful, stopWatch.getElapsedTimeMili());
+ }
+
+ /**
+ * Wrapper function for getNodeInfo and getInclusionStates
+ *
+ * @param {array} hashes
+ * @method getLatestInclusion
+ * @returns {function} callback
+ * @returns {array} state
+ **/
+ public GetInclusionStateResponse getLatestInclusion(String[] hashes) throws NoNodeInfoException {
+ GetNodeInfoResponse getNodeInfoResponse = getNodeInfo();
+ if (getNodeInfoResponse == null) throw new NoNodeInfoException();
+
+ String[] latestMilestone = {getNodeInfoResponse.getLatestSolidSubtangleMilestone()};
+
+ return getInclusionStates(hashes, latestMilestone);
+ }
+
+ public SendTransferResponse sendTransfer(String seed, int depth, int minWeightMagnitude, final List transfers, Input[] inputs, String address) throws NotEnoughBalanceException {
+ StopWatch stopWatch = new StopWatch();
+
+ List trytes = prepareTransfers(seed, 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()];
+
+ for (int i = 0; i < trxs.size(); i++) {
+
+ final FindTransactionResponse response = findTransactionsByBundles(trxs.get(i).getBundle());
+
+ successful[i] = response.getHashes().length != 0;
+ }
+
+ return SendTransferResponse.create(successful, stopWatch.getElapsedTimeMili());
+ }
+
+ /**
+ * Basically traverse the Bundle by going down the trunkTransactions until
+ * 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
+ **/
+ public Bundle traverseBundle(String trunkTx, String bundleHash, Bundle bundle) throws ArgumentException {
+ GetTrytesResponse gtr = getTrytes(trunkTx);
+
+ if (gtr != null) {
+
+ if (gtr.getTrytes().length == 0) {
+ throw new ArgumentException("Bundle transactions not visible");
+ }
+
+ Transaction trx = new Transaction(gtr.getTrytes()[0], customCurl);
+ if (trx == null || 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) {
+ throw new ArgumentException("Invalid tail transaction supplied.");
+ }
+ // If no bundle hash, define it
+ if (bundleHash == null) {
+ bundleHash = trx.getBundle();
+ }
+ // If different bundle hash, return with bundle
+ if (!bundleHash.equals(trx.getBundle())) {
+ return bundle;
+ }
+ // If only one bundle element, return
+ if (Integer.parseInt(trx.getLastIndex()) == 0 && Integer.parseInt(trx.getCurrentIndex()) == 0) {
+ return new Bundle(Collections.singletonList(trx), 1);
+ }
+ // Define new trunkTransaction for search
+ trunkTx = trx.getTrunkTransaction();
+ // Add transaction object to bundle
+ bundle.getTransactions().add(trx);
+
+ // Continue traversing with new trunkTx
+ return traverseBundle(trunkTx, bundleHash, bundle);
+ } else {
+ throw new ArgumentException("Get Trytes Response was null");
+ }
+ }
+
+ public String findTailTransactionHash(String hash) throws ArgumentException {
+ GetTrytesResponse gtr = getTrytes(hash);
+
+ if (gtr == null) throw new ArgumentException("Invalid hash");
+
+ if (gtr.getTrytes().length == 0) {
+ throw new ArgumentException("Bundle transactions not visible");
+ }
+
+ Transaction trx = new Transaction(gtr.getTrytes()[0], customCurl);
+ if (trx == null || trx.getBundle() == null) {
+ throw new ArgumentException("Invalid trytes, could not create object");
+ }
+ if (Integer.parseInt(trx.getCurrentIndex()) == 0) return trx.getHash();
+ else return findTailTransactionHash(trx.getBundle());
+ }
+
+ public List addRemainder(final String seed,
+ final List inputs,
+ final Bundle bundle,
+ final String tag,
+ final long totalValue,
+ final String remainderAddress,
+ final List signatureFragments) throws NotEnoughBalanceException {
+
+ long totalTransferValue = totalValue;
+ for (int i = 0; i < inputs.size(); i++) {
+ long thisBalance = inputs.get(i).getBalance();
+ long toSubtract = 0 - thisBalance;
+ long timestamp = (long) Math.floor(Calendar.getInstance().getTimeInMillis() / 1000);
+
+ // Add input as bundle entry
+ bundle.addEntry(2, inputs.get(i).getAddress(), toSubtract, tag, timestamp);
+ // If there is a remainder value
+ // Add extra output to send remaining funds to
+
+ if (thisBalance >= totalTransferValue) {
+ long remainder = thisBalance - totalTransferValue;
+
+ // If user has provided remainder address
+ // Use it to send remaining funds to
+ if (remainder > 0 && remainderAddress != null) {
+ // Remainder bundle entry
+ bundle.addEntry(1, remainderAddress, remainder, tag, timestamp);
+ // Final function for signing inputs
+ return IotaAPIUtils.signInputsAndReturn(seed, inputs, bundle, signatureFragments, customCurl);
+ } else if (remainder > 0) {
+ // Generate a new Address by calling getNewAddress
+
+ GetNewAddressResponse res = getNewAddress(seed, 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);
+ } else {
+ // If there is no remainder, do not add transaction to bundle
+ // simply sign and return
+ return IotaAPIUtils.signInputsAndReturn(seed, inputs, bundle, signatureFragments, customCurl);
+ }
+
+ // If multiple inputs provided, subtract the totalTransferValue by
+ // the inputs balance
+ } else {
+ totalTransferValue -= thisBalance;
+ }
+ }
+ throw new NotEnoughBalanceException();
+ }
+
+ public static class Builder extends IotaAPICore.Builder {
+ private ICurl customCurl;
+
+ public Builder withCustomCurl(ICurl curl) {
+ customCurl = curl;
+ return this;
+ }
+
+ public IotaAPI build() {
+ super.build();
+ return new IotaAPI(this);
+ }
+ }
+}
diff --git a/src/main/java/jota/IotaAPICommands.java b/src/main/java/jota/IotaAPICommands.java
index bcb9b58..ed4d6bc 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 {
diff --git a/src/main/java/jota/IotaAPICore.java b/src/main/java/jota/IotaAPICore.java
new file mode 100644
index 0000000..7e032ac
--- /dev/null
+++ b/src/main/java/jota/IotaAPICore.java
@@ -0,0 +1,254 @@
+package jota;
+
+import jota.dto.request.*;
+import jota.dto.response.*;
+import okhttp3.OkHttpClient;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import retrofit2.Call;
+import retrofit2.Response;
+import retrofit2.Retrofit;
+import retrofit2.converter.gson.GsonConverterFactory;
+
+import java.io.BufferedReader;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.List;
+import java.util.Properties;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * Created by Adrian on 15.01.2017.
+ */
+public class IotaAPICore {
+
+ private static final Logger log = LoggerFactory.getLogger(IotaAPICore.class);
+
+ private IotaAPIService service;
+ private String protocol, host, port;
+
+ protected IotaAPICore(final Builder builder) {
+ protocol = builder.protocol;
+ host = builder.host;
+ port = builder.port;
+ postConstruct();
+ }
+
+ protected static Response wrapCheckedException(final Call call) {
+ try {
+ final Response res = call.execute();
+ if (res.code() == 400) {
+ throw new IllegalAccessError("400 " + res.errorBody().string());
+ } else if (res.code() == 401) {
+ throw new IllegalAccessError("401 " + res.errorBody().string());
+ } else if (res.code() == 500) {
+ throw new IllegalAccessError("500 " + res.errorBody().string());
+ }
+ return res;
+ } catch (IOException e) {
+ log.error("Execution of the API call raised exception. IOTA Node not reachable?", e);
+ throw new IllegalStateException(e.getMessage());
+ }
+ }
+
+ private static String env(String env, String def) {
+ final String value = System.getenv(env);
+ if (value == null) {
+ log.warn("Environment variable '{}' is not defined, and actual value has not been specified. "
+ + "Rolling back to default value: '{}'", env, def);
+ return def;
+ }
+ return value;
+ }
+
+ private void postConstruct() {
+
+ final String nodeUrl = protocol + "://" + host + ":" + port;
+
+ final OkHttpClient client = new OkHttpClient.Builder()
+ .readTimeout(5000, TimeUnit.SECONDS)
+ .connectTimeout(5000, TimeUnit.SECONDS)
+ .build();
+
+ final Retrofit retrofit = new Retrofit.Builder()
+ .baseUrl(nodeUrl)
+ .addConverterFactory(GsonConverterFactory.create())
+ .client(client)
+ .build();
+
+ service = retrofit.create(IotaAPIService.class);
+
+ log.debug("Jota-API Java proxy pointing to node url: '{}'", nodeUrl);
+ }
+
+ public GetNodeInfoResponse getNodeInfo() {
+ final Call res = service.getNodeInfo(IotaCommandRequest.createNodeInfoRequest());
+ return wrapCheckedException(res).body();
+ }
+
+ public GetNeighborsResponse getNeighbors() {
+ final Call res = service.getNeighbors(IotaCommandRequest.createGetNeighborsRequest());
+ return wrapCheckedException(res).body();
+ }
+
+ public AddNeighborsResponse addNeighbors(String... uris) {
+ final Call res = service.addNeighbors(IotaNeighborsRequest.createAddNeighborsRequest(uris));
+ return wrapCheckedException(res).body();
+ }
+
+ public RemoveNeighborsResponse removeNeighbors(String... uris) {
+ final Call res = service.removeNeighbors(IotaNeighborsRequest.createRemoveNeighborsRequest(uris));
+ return wrapCheckedException(res).body();
+ }
+
+ public GetTipsResponse getTips() {
+ final Call res = service.getTips(IotaCommandRequest.createGetTipsRequest());
+ return wrapCheckedException(res).body();
+ }
+
+ public FindTransactionResponse findTransactions(String[] addresses, String[] tags, String[] approvees, String[] bundles) {
+
+ final IotaFindTransactionsRequest findTransRequest = IotaFindTransactionsRequest
+ .createFindTransactionRequest()
+ .byAddresses(addresses)
+ .byTags(tags)
+ .byApprovees(approvees)
+ .byBundles(bundles);
+
+ final Call res = service.findTransactions(findTransRequest);
+ return wrapCheckedException(res).body();
+ }
+
+ public FindTransactionResponse findTransactionsByAddresses(final String... addresses) {
+ return findTransactions(addresses, null, null, null);
+ }
+
+ public FindTransactionResponse findTransactionsByBundles(final String... bundles) {
+ return findTransactions(null, null, null, bundles);
+ }
+
+ public FindTransactionResponse findTransactionsByApprovees(final String... approvees) {
+ return findTransactions(null, null, approvees, null);
+ }
+
+ public FindTransactionResponse findTransactionsByDigests(final String... digests) {
+ return findTransactions(null, digests, null, null);
+ }
+
+ public GetInclusionStateResponse getInclusionStates(String[] transactions, String[] tips) {
+ final Call res = service.getInclusionStates(IotaGetInclusionStateRequest
+ .createGetInclusionStateRequest(transactions, tips));
+ return wrapCheckedException(res).body();
+ }
+
+ public GetTrytesResponse getTrytes(String... hashes) {
+ final Call res = service.getTrytes(IotaGetTrytesRequest.createGetTrytesRequest(hashes));
+ return wrapCheckedException(res).body();
+ }
+
+ public GetTransactionsToApproveResponse getTransactionsToApprove(Integer depth) {
+ final Call res = service.getTransactionsToApprove(IotaGetTransactionsToApproveRequest.createIotaGetTransactionsToApproveRequest(depth));
+ return wrapCheckedException(res).body();
+ }
+
+ public GetBalancesResponse getBalances(Integer threshold, String[] addresses) {
+ final Call res = service.getBalances(IotaGetBalancesRequest.createIotaGetBalancesRequest(threshold, addresses));
+ return wrapCheckedException(res).body();
+ }
+
+ public GetBalancesResponse getBalances(Integer threshold, List addresses) {
+ return getBalances(threshold, addresses.toArray(new String[]{}));
+ }
+
+ public InterruptAttachingToTangleResponse interruptAttachingToTangle() {
+ final Call res = service.interruptAttachingToTangle(IotaCommandRequest.createInterruptAttachToTangleRequest());
+ return wrapCheckedException(res).body();
+ }
+
+ public GetAttachToTangleResponse attachToTangle(String trunkTransaction, String branchTransaction, Integer minWeightMagnitude, String... trytes) {
+ final Call res = service.attachToTangle(IotaAttachToTangleRequest.createAttachToTangleRequest(trunkTransaction, branchTransaction, minWeightMagnitude, trytes));
+ return wrapCheckedException(res).body();
+ }
+
+ public StoreTransactionsResponse storeTransactions(String... trytes) {
+ final Call res = service.storeTransactions(IotaStoreTransactionsRequest.createStoreTransactionsRequest(trytes));
+ return wrapCheckedException(res).body();
+ }
+
+ public BroadcastTransactionsResponse broadcastTransactions(String... trytes) {
+ final Call res = service.broadcastTransactions(IotaBroadcastTransactionRequest.createBroadcastTransactionsRequest(trytes));
+ return wrapCheckedException(res).body();
+ }
+
+ @SuppressWarnings("unchecked")
+ public static class Builder> {
+
+ String protocol, host, port;
+
+ public IotaAPICore build() {
+
+ if (protocol == null || host == null || port == null) {
+
+ // check properties files.
+ if (!checkPropertiesFiles()) {
+
+ // last resort: best effort on enviroment variable,
+ // before assigning default values.
+ checkEnviromentVariables();
+ }
+ }
+
+ return new IotaAPICore(this);
+ }
+
+ private boolean checkPropertiesFiles() {
+
+ try {
+
+ FileReader fileReader = new FileReader("node_config.properties");
+ BufferedReader bufferedReader = new BufferedReader(fileReader);
+
+ final Properties nodeConfig = new Properties();
+ nodeConfig.load(bufferedReader);
+
+ if (nodeConfig.getProperty("iota.node.protocol") != null) {
+ protocol = nodeConfig.getProperty("iota.node.protocol");
+ }
+
+ if (nodeConfig.getProperty("iota.node.host") != null) {
+ host = nodeConfig.getProperty("iota.node.host");
+ }
+
+ if (nodeConfig.getProperty("iota.node.port") != null) {
+ port = nodeConfig.getProperty("iota.node.port");
+ }
+
+ } catch (IOException e1) {
+ log.debug("node_config.properties not found. Rolling back for another solution...");
+ }
+ 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");
+ }
+
+ public T host(String host) {
+ this.host = host;
+ return (T) this;
+ }
+
+ public T port(String port) {
+ this.port = port;
+ return (T) this;
+ }
+
+ public T protocol(String protocol) {
+ this.protocol = protocol;
+ return (T) this;
+ }
+
+ }
+}
diff --git a/src/main/java/jota/IotaAPIProxy.java b/src/main/java/jota/IotaAPIProxy.java
deleted file mode 100644
index 173bda8..0000000
--- a/src/main/java/jota/IotaAPIProxy.java
+++ /dev/null
@@ -1,721 +0,0 @@
-package jota;
-
-import jota.dto.request.*;
-import jota.dto.response.*;
-import jota.model.Bundle;
-import jota.model.Input;
-import jota.model.Transaction;
-import jota.model.Transfer;
-import jota.utils.Converter;
-import jota.utils.InputValidator;
-import jota.utils.IotaAPIUtils;
-import okhttp3.OkHttpClient;
-import org.apache.commons.lang3.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import retrofit2.Call;
-import retrofit2.Response;
-import retrofit2.Retrofit;
-import retrofit2.converter.gson.GsonConverterFactory;
-
-import java.io.BufferedReader;
-import java.io.FileReader;
-import java.io.IOException;
-import java.util.*;
-import java.util.concurrent.TimeUnit;
-
-/**
- * IotaAPIProxy Builder. Usage:
- *
- * IotaApiProxy api = IotaApiProxy.Builder
- * .protocol("http")
- * .nodeAddress("localhost")
- * .port(12345)
- * .build();
- *
- * GetNodeInfoResponse response = api.getNodeInfo();
- *
- * @author davassi
- */
-public class IotaAPIProxy {
-
- private static final Logger log = LoggerFactory.getLogger(IotaAPIProxy.class);
-
- private IotaAPIService service;
- private String protocol, host, port;
-
- private IotaAPIProxy(final Builder builder) {
- protocol = builder.protocol;
- host = builder.host;
- port = builder.port;
- postConstruct();
- }
-
- protected static Response wrapCheckedException(final Call call) {
- try {
- final Response res = call.execute();
- if (res.code() == 400) {
- throw new IllegalAccessError(res.errorBody().toString());
- }
- return res;
- } catch (IOException e) {
- log.error("Execution of the API call raised exception. IOTA Node not reachable?", e);
- throw new IllegalStateException(e.getMessage());
- }
- }
-
- private static final String env(String env, String def) {
- final String value = System.getenv(env);
- if (value == null) {
- log.warn("Environment variable '{}' is not defined, and actual value has not been specified. "
- + "Rolling back to default value: '{}'", env, def);
- return def;
- }
- return value;
- }
-
- private void postConstruct() {
-
- final String nodeUrl = protocol + "://" + host + ":" + port;
-
- final OkHttpClient client = new OkHttpClient.Builder()
- .readTimeout(120, TimeUnit.SECONDS)
- .connectTimeout(120, TimeUnit.SECONDS)
- .build();
-
- final Retrofit retrofit = new Retrofit.Builder()
- .baseUrl(nodeUrl)
- .addConverterFactory(GsonConverterFactory.create())
- .client(client)
- .build();
-
- service = retrofit.create(IotaAPIService.class);
-
- log.debug("Jota-API Java proxy pointing to node url: '{}'", nodeUrl);
- }
-
- public GetNodeInfoResponse getNodeInfo() {
- final Call res = service.getNodeInfo(IotaCommandRequest.createNodeInfoRequest());
- return wrapCheckedException(res).body();
- }
-
- public GetNeighborsResponse getNeighbors() {
- final Call res = service.getNeighbors(IotaCommandRequest.createGetNeighborsRequest());
- return wrapCheckedException(res).body();
- }
-
- public AddNeighborsResponse addNeighbors(String... uris) {
- final Call res = service.addNeighbors(IotaNeighborsRequest.createAddNeighborsRequest(uris));
- return wrapCheckedException(res).body();
- }
-
- public RemoveNeighborsResponse removeNeighbors(String... uris) {
- final Call res = service.removeNeighbors(IotaNeighborsRequest.createRemoveNeighborsRequest(uris));
- return wrapCheckedException(res).body();
- }
-
- public GetTipsResponse getTips() {
- final Call res = service.getTips(IotaCommandRequest.createGetTipsRequest());
- return wrapCheckedException(res).body();
- }
-
- public FindTransactionResponse findTransactions(String[] addresses, String[] tags, String[] approvees, String[] bundles) {
-
- final IotaFindTransactionsRequest findTransRequest = IotaFindTransactionsRequest
- .createFindTransactionRequest()
- .byAddresses(addresses)
- .byTags(tags)
- .byApprovees(approvees)
- .byBundles(bundles);
-
- final Call res = service.findTransactions(findTransRequest);
- return wrapCheckedException(res).body();
- }
-
- public FindTransactionResponse findTransactionsByAddresses(final String... addresses) {
- return findTransactions(addresses, null, null, null);
- }
-
- public FindTransactionResponse findTransactionsByBundles(final String... bundles) {
- return findTransactions(null, null, null, bundles);
- }
-
- public FindTransactionResponse findTransactionsByApprovees(final String... approvees) {
- return findTransactions(null, null, approvees, null);
- }
-
- public FindTransactionResponse findTransactionsByDigests(final String... digests) {
- return findTransactions(null, digests, null, null);
- }
-
- public GetInclusionStateResponse getInclusionStates(String[] transactions, String[] tips) {
- final Call res = service.getInclusionStates(IotaGetInclusionStateRequest
- .createGetInclusionStateRequest(transactions, tips));
- return wrapCheckedException(res).body();
- }
-
- public GetInclusionStateResponse getInclusionStates(Collection transactions, Collection tips) {
- final Call res = service.getInclusionStates(IotaGetInclusionStateRequest
- .createGetInclusionStateRequest(transactions, tips));
- return wrapCheckedException(res).body();
- }
-
- public GetTrytesResponse getTrytes(String... hashes) {
- final Call res = service.getTrytes(IotaGetTrytesRequest.createGetTrytesRequest(hashes));
- return wrapCheckedException(res).body();
- }
-
- public GetTransactionsToApproveResponse getTransactionsToApprove(Integer depth) {
- final Call res = service.getTransactionsToApprove(IotaGetTransactionsToApproveRequest.createIotaGetTransactionsToApproveRequest(depth));
- return wrapCheckedException(res).body();
- }
-
- public GetBalancesResponse getBalances(Integer threshold, String[] addresses) {
- final Call res = service.getBalances(IotaGetBalancesRequest.createIotaGetBalancesRequest(threshold, addresses));
- return wrapCheckedException(res).body();
- }
-
- public GetBalancesResponse getBalances(Integer threshold, List addresses) {
- return getBalances(threshold, addresses.toArray(new String[] {}));
- }
-
- public InterruptAttachingToTangleResponse interruptAttachingToTangle() {
- final Call res = service.interruptAttachingToTangle(IotaCommandRequest.createInterruptAttachToTangleRequest());
- return wrapCheckedException(res).body();
- }
-
- public GetAttachToTangleResponse attachToTangle(String trunkTransaction, String branchTransaction, Integer minWeightMagnitude, String... trytes) {
- final Call res = service.attachToTangle(IotaAttachToTangleRequest.createAttachToTangleRequest(trunkTransaction, branchTransaction, minWeightMagnitude, trytes));
- return wrapCheckedException(res).body();
- }
-
- public StoreTransactionsResponse storeTransactions(String... trytes) {
- final Call res = service.storeTransactions(IotaStoreTransactionsRequest.createStoreTransactionsRequest(trytes));
- return wrapCheckedException(res).body();
- }
-
- public BroadcastTransactionsResponse broadcastTransactions(String... trytes) {
- final Call res = service.broadcastTransactions(IotaBroadcastTransactionRequest.createBroadcastTransactionsRequest(trytes));
- return wrapCheckedException(res).body();
- }
-
- // end of proxied calls.
-
- /**
- * 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
- *
- * @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
- */
- public GetNewAddressResponse getNewAddress(final String seed, final int index, final boolean checksum, final int total, final boolean returnAll) {
-
- final List allAddresses = new ArrayList<>();
-
- // If total number of addresses to generate is supplied, simply generate
- // and return the list of all addresses
- if (total != 0) {
- for (int i = index; i < index + total; i++) {
- allAddresses.add(IotaAPIUtils.newAddress(seed, i, checksum));
- }
- return GetNewAddressResponse.create(allAddresses);
- }
- // No total provided: Continue calling findTransactions to see if address was
- // already created if null, return list of addresses
- for (int i = index; ; i++) {
-
- final String newAddress = IotaAPIUtils.newAddress(seed, i, checksum);
- final FindTransactionResponse response = findTransactionsByAddresses(new String[]{newAddress});
-
- allAddresses.add(newAddress);
- if (response.getHashes().length == 0) {
- break;
- }
- }
-
- // If !returnAll return only the last address that was generated
- if (!returnAll) {
- allAddresses.subList(0, allAddresses.size()-1).clear();
- }
- return GetNewAddressResponse.create(allAddresses);
- }
-
- /*
- * newAddress
- * broadcastAndStore
- * sendTrytes
- * prepareTransfers
- * getInputs
- * getLatestInclusion
-
- getTransfers
- sendTransfer
- getBundle
-
- getTransactionsObjects
- findTransactionObjects
-
- replayBundle
- broadcastBundle
- getAccountData
- */
-
- /**
- *
- * @param trytes
- * @return a StoreTransactionsResponse
- */
- public StoreTransactionsResponse broadcastAndStore(final String ... trytes) {
-
- try {
- broadcastTransactions(trytes);
- } catch (Exception e) {
- log.error("Impossible to broadcastAndStore, aborting.", e);
- throw new IllegalStateException("BroadcastAndStore Illegal state Exception");
- }
- return storeTransactions(trytes);
- }
-
- /**
- * Facade method: Gets transactions to approve, attaches to Tangle, broadcasts and stores
- * @param {array} trytes
- * @param {int} depth
- * @param {int} minWeightMagnitude
- * @return
- */
- public List sendTrytes(final String trytes, final int minWeightMagnitude) {
-
- final GetTransactionsToApproveResponse txs = getTransactionsToApprove(minWeightMagnitude);
-
- // attach to tangle - do pow
- final GetAttachToTangleResponse res = attachToTangle(txs.getTrunkTransaction(), txs.getBranchTransaction(), minWeightMagnitude, trytes);
-
- try {
- broadcastAndStore(res.getTrytes());
- } catch (Exception e) {
- log.error("Impossible to sendTrytes, aborting.", e);
- throw new IllegalStateException("sendTrytes Illegal state Exception");
- }
-
- //return Arrays.stream(res.getTrytes()).map(Converter::transactionObject).collect(Collectors.toList());
- final List trx = new ArrayList<>();
-
- for (final String tx : Arrays.asList(res.getTrytes())) {
- trx.add(Converter.transactionObject(tx));
- }
- return trx;
- }
-
- /**
- * Wrapper function for getTrytes and transactionObjects
- * gets the trytes and transaction object from a list of transaction hashes
- *
- * @method getTransactionsObjects
- * @param {array} hashes
- * @return
- * @returns {function} callback
- * @returns {object} success
- **/
- public List getTransactionsObjects(String[] hashes) {
-
- if (!InputValidator.isArrayOfHashes(hashes)) {
- throw new IllegalStateException("Not an Array of Hashes: " + Arrays.toString(hashes));
- }
-
- final GetTrytesResponse trytesResponse = getTrytes(hashes);
-
- final List trxs = new ArrayList<>();
-
- for (final String tryte : trytesResponse.getTrytes()) {
- trxs.add(Converter.transactionObject(tryte));
- }
- return trxs;
- }
-
- /**
- * 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
- **/
- public List findTransactionObjects(String[] input) {
- FindTransactionResponse ftr = findTransactions(input, null, null, null);
- if (ftr == null || ftr.getHashes() == null)
-
- return null;
-
- // get the transaction objects of the transactions
- return getTransactionsObjects(ftr.getHashes());
- }
-
- /**
- * Prepares transfer by generating bundle, finding and signing inputs
- *
- * @method prepareTransfers
- * @param {string} seed
- * @param {object} transfers
- * @param {object} options
- * @property {array} inputs Inputs used for signing. Needs to have correct keyIndex and address value
- * @property {string} address Remainder address
- * @param {function} callback
- * @return
- * @returns {array} trytes Returns bundle trytes
- **/
- public List prepareTransfers(final String seed, final List transfers, String remainder, List inputs) {
-
- // Input validation of transfers object
- if (!InputValidator.isTransfersCollectionCorrect(transfers)) {
- throw new IllegalStateException("Invalid Transfer");
- }
-
- // Create a new bundle
- final Bundle bundle = new Bundle();
- final List signatureFragments = new ArrayList<>();
-
- int totalValue = 0;
- 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
- for (int j = 0; fragment.length() < 2187; j++) {
- fragment += "9";
- }
-
- signatureFragments.add(fragment);
- }
- } else {
- // Else, get single fragment with 2187 of 9's trytes
- String fragment = StringUtils.substring(transfer.getMessage(), 0, 2187);
-
- for (int j = 0; fragment.length() < 2187; j++) {
- fragment += '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() ? "999999999999999999999999999" : transfer.getTag();
-
- // Pad for required 27 tryte length
- for (int j = 0; tag.length() < 27; j++) {
- tag += '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) {
-
- // Case 1: user provided inputs
- // Validate the inputs by calling getBalances
- if (!inputs.isEmpty()) {
-
- // Get list if addresses of the provided inputs
- List inputsAddresses = new ArrayList<>();
- for (final Input i : inputs) {
- inputsAddresses.add(i.getAddress());
- }
-
- GetBalancesResponse resbalances = getBalances(100, inputsAddresses);
- String[] balances = resbalances.getBalances();
-
-
- List confirmedInputs = new ArrayList<>();
- int totalBalance = 0; 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) {
- Input inputEl = inputs.get(i++);
- inputEl.setBalance(thisBalance);
- confirmedInputs.add(inputEl);
- }
- }
-
- // Return not enough balance error
- if (totalValue > totalBalance) {
- throw new IllegalStateException("Not enough balance");
- }
-
- return IotaAPIUtils.signInputsAndReturn(seed, confirmedInputs, bundle, signatureFragments);
- }
-
- // Case 2: Get inputs deterministically
- //
- // If no inputs provided, derive the addresses from the seed and
- // confirm that the inputs exceed the threshold
- else {
-
- GetBalancesAndFormatResponse newinputs = getInputs(seed, Collections.EMPTY_LIST, 0, 0, totalValue);
- // If inputs with enough balance
- return IotaAPIUtils.signInputsAndReturn(seed, newinputs.getInput(), bundle, signatureFragments);
- }
- } else {
-
- // If no input required, don't sign and simply finalize the bundle
- bundle.finalize();
- bundle.addTrytes(signatureFragments);
-
- List trxb = bundle.getTransactions();
- List bundleTrytes = new ArrayList<>();
- for (Transaction tx : trxb) {
- jota.utils.IotaAPIUtils.transactionTrytes(tx);
- }
- Collections.reverse(bundleTrytes);
- return bundleTrytes;
- }
- }
-
- /**
- * Gets the inputs of a seed
- *
- * @method getInputs
- * @param {string} seed
- * @param {object} options
- * @property {int} start Starting key index
- * @property {int} end Ending key index
- * @property {int} threshold Min balance required
- * @param {function} callback
- **/
- public GetBalancesAndFormatResponse getInputs(final String seed, final List balances, int start, int end, int threshold) {
-
- // validate the seed
- if (!InputValidator.isTrytes(seed, 0)) {
- throw new IllegalStateException("Invalid Seed");
- }
-
- // If start value bigger than end, return error
- // or if difference between end and start is bigger than 500 keys
- if (start > end || end > (start + 500)) {
- throw new IllegalStateException("Invalid inputs provided");
- }
-
- // Case 1: start and end
- //
- // If start and end is defined by the user, simply iterate through the keys
- // and call getBalances
- if (end != 0) {
-
- List allAddresses = new ArrayList<>();
-
- for (int i = start; i < end; i++) {
-
- String address = IotaAPIUtils.newAddress(seed, i, false);
- allAddresses.add(address);
- }
-
- return getBalanceAndFormat(allAddresses, balances, threshold, start, end);
- }
- // Case 2: iterate till threshold || end
- //
- // Either start from index: 0 or start (if defined) until threshold is reached.
- // 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(), balances, threshold, start, end);
- }
- }
-
- // Calls getBalances and formats the output
- // returns the final inputsObject then
- public GetBalancesAndFormatResponse getBalanceAndFormat(final List addresses, List balances, long threshold, int start, int end) {
-
- if (balances == null || balances.isEmpty()) {
- GetBalancesResponse getBalancesResponse = getBalances(100, addresses);
- balances = Arrays.asList(getBalancesResponse.getBalances());
- }
-
- // If threshold defined, keep track of whether reached or not
- // else set default to true
- boolean thresholdReached = threshold != 0 ? false : true; int i = -1;
-
- List inputs = new ArrayList<>();
- long totalBalance = 0;
-
- for (String address : addresses) {
-
- long balance = Long.parseLong(balances.get(++i));
-
- if (balance > 0) {
- final Input newEntry = new Input(address, balance, start+i);
-
- inputs.add(newEntry);
- // Increase totalBalance of all aggregated inputs
- totalBalance += balance;
-
- if (!thresholdReached && totalBalance >= threshold) {
- thresholdReached = true;
- break;
- }
- }
- }
-
- if (thresholdReached) {
- return GetBalancesAndFormatResponse.create(inputs, totalBalance);
- }
- throw new IllegalStateException("Not enough balance");
- }
-
- /**
- * Gets the associated bundle transactions of a single transaction
- * Does validation of signatures, total sum as well as bundle order
- *
- * @method getBundle
- * @param {string} transaction Hash of a tail transaction
- * @returns {list} bundle Transaction objects
- **/
- public GetBundleResponse getBundle(String transaction) {
- return null; //IotaAPIUtils.getBundle(transaction);
- }
-
- /**
- * Replays a transfer by doing Proof of Work again
- *
- * @method replayBundle
- * @param {string} tail
- * @param {int} depth
- * @param {int} minWeightMagnitude
- * @param {function} callback
- * @returns {object} analyzed Transaction objects
- **/
- public List replayTransfer(String transaction, int depth, int minWeightMagnitude) {
-
- List bundleTrytes = new ArrayList<>();
-
- GetBundleResponse bundle = getBundle(transaction);
-
- for (Transaction element : bundle.getTransactions()) {
-
- bundleTrytes.add(IotaAPIUtils.transactionTrytes(element));
- }
-
- return sendTrytes(bundleTrytes, minWeightMagnitude);
- }
-
- /**
- * Wrapper function for getNodeInfo and getInclusionStates
- *
- * @method getLatestInclusion
- * @param {array} hashes
- * @returns {function} callback
- * @returns {array} state
- **/
- public GetInclusionStateResponse getLatestInclusion(String[] hashes) {
- GetNodeInfoResponse getNodeInfoResponse = getNodeInfo();
- if (getNodeInfoResponse == null) return null;
-
- String[] latestMilestone = {getNodeInfoResponse.getLatestSolidSubtangleMilestone()};
-
- return getInclusionStates(hashes, latestMilestone);
- }
-
- public static class Builder {
-
- String protocol, host, port;
-
- public IotaAPIProxy build() {
-
- if (protocol == null || host == null || port == null) {
-
- // check properties files.
- if (!checkPropertiesFiles()) {
-
- // last resort: best effort on enviroment variable,
- // before assigning default values.
- checkEnviromentVariables();
- }
- }
-
- return new IotaAPIProxy(this);
- }
-
- private boolean checkPropertiesFiles() {
-
- try {
-
- FileReader fileReader = new FileReader("node_config.properties");
- BufferedReader bufferedReader = new BufferedReader(fileReader);
-
- final Properties nodeConfig = new Properties();
- nodeConfig.load(bufferedReader);
-
- if (nodeConfig.getProperty("iota.node.protocol") != null) {
- protocol = nodeConfig.getProperty("iota.node.protocol");
- }
-
- if (nodeConfig.getProperty("iota.node.host") != null) {
- host = nodeConfig.getProperty("iota.node.host");
- }
-
- if (nodeConfig.getProperty("iota.node.port") != null) {
- port = nodeConfig.getProperty("iota.node.port");
- }
-
- } catch (IOException e1) {
- log.debug("node_config.properties not found. Rolling back for another solution...");
- }
- 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");
- }
-
- public Builder host(String host) {
- this.host = host;
- return this;
- }
-
- public Builder port(String port) {
- this.port = port;
- return this;
- }
-
- public Builder protocol(String protocol) {
- this.protocol = protocol;
- return 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": "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 bfef85b..8d50a54 100644
--- a/src/main/java/jota/dto/request/IotaAttachToTangleRequest.java
+++ b/src/main/java/jota/dto/request/IotaAttachToTangleRequest.java
@@ -20,4 +20,36 @@ public class IotaAttachToTangleRequest extends IotaCommandRequest {
public static IotaAttachToTangleRequest createAttachToTangleRequest(final String trunkTransaction, final String branchTransaction, final Integer minWeightMagnitude, final String... trytes) {
return new IotaAttachToTangleRequest(trunkTransaction, branchTransaction, minWeightMagnitude, trytes);
}
+
+ public String getTrunkTransaction() {
+ return trunkTransaction;
+ }
+
+ public void setTrunkTransaction(String trunkTransaction) {
+ this.trunkTransaction = trunkTransaction;
+ }
+
+ public String getBranchTransaction() {
+ return branchTransaction;
+ }
+
+ public void setBranchTransaction(String branchTransaction) {
+ this.branchTransaction = branchTransaction;
+ }
+
+ public Integer getMinWeightMagnitude() {
+ return minWeightMagnitude;
+ }
+
+ public void setMinWeightMagnitude(Integer minWeightMagnitude) {
+ this.minWeightMagnitude = minWeightMagnitude;
+ }
+
+ public String[] getTrytes() {
+ return 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 42847d9..5a0a5d5 100644
--- a/src/main/java/jota/dto/request/IotaBroadcastTransactionRequest.java
+++ b/src/main/java/jota/dto/request/IotaBroadcastTransactionRequest.java
@@ -14,4 +14,12 @@ public class IotaBroadcastTransactionRequest extends IotaCommandRequest {
public static IotaBroadcastTransactionRequest createBroadcastTransactionsRequest(final String... trytes) {
return new IotaBroadcastTransactionRequest(trytes);
}
+
+ public String[] getTrytes() {
+ return trytes;
+ }
+
+ public void setTrytes(String[] trytes) {
+ this.trytes = trytes;
+ }
}
\ No newline at end of file
diff --git a/src/main/java/jota/dto/request/IotaFindTransactionsRequest.java b/src/main/java/jota/dto/request/IotaFindTransactionsRequest.java
index b3a72df..04da886 100644
--- a/src/main/java/jota/dto/request/IotaFindTransactionsRequest.java
+++ b/src/main/java/jota/dto/request/IotaFindTransactionsRequest.java
@@ -17,6 +17,38 @@ public class IotaFindTransactionsRequest extends IotaCommandRequest {
return new IotaFindTransactionsRequest();
}
+ 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;
+ }
+
public IotaFindTransactionsRequest byBundles(String... bundles) {
this.bundles = bundles;
return this;
diff --git a/src/main/java/jota/dto/request/IotaGetBalancesRequest.java b/src/main/java/jota/dto/request/IotaGetBalancesRequest.java
index 807865d..33d760d 100644
--- a/src/main/java/jota/dto/request/IotaGetBalancesRequest.java
+++ b/src/main/java/jota/dto/request/IotaGetBalancesRequest.java
@@ -17,5 +17,20 @@ public class IotaGetBalancesRequest extends IotaCommandRequest {
return new IotaGetBalancesRequest(threshold, addresses);
}
+ public String[] getAddresses() {
+ return addresses;
+ }
+
+ public void setAddresses(String[] addresses) {
+ this.addresses = addresses;
+ }
+
+ public Integer getThreshold() {
+ return 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 d0d323c..704806e 100644
--- a/src/main/java/jota/dto/request/IotaGetInclusionStateRequest.java
+++ b/src/main/java/jota/dto/request/IotaGetInclusionStateRequest.java
@@ -25,4 +25,19 @@ public class IotaGetInclusionStateRequest extends IotaCommandRequest {
tips.toArray(new String[]{}));
}
+ public String[] getTransactions() {
+ return transactions;
+ }
+
+ public void setTransactions(String[] transactions) {
+ this.transactions = transactions;
+ }
+
+ public String[] getTips() {
+ return 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 f597448..fb1b367 100644
--- a/src/main/java/jota/dto/request/IotaGetTransactionsToApproveRequest.java
+++ b/src/main/java/jota/dto/request/IotaGetTransactionsToApproveRequest.java
@@ -14,4 +14,12 @@ public class IotaGetTransactionsToApproveRequest extends IotaCommandRequest {
public static IotaGetTransactionsToApproveRequest createIotaGetTransactionsToApproveRequest(Integer depth) {
return new IotaGetTransactionsToApproveRequest(depth);
}
+
+ public Integer getDepth() {
+ return 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 b493451..eaa5888 100644
--- a/src/main/java/jota/dto/request/IotaGetTrytesRequest.java
+++ b/src/main/java/jota/dto/request/IotaGetTrytesRequest.java
@@ -14,4 +14,12 @@ public class IotaGetTrytesRequest extends IotaCommandRequest {
public static IotaGetTrytesRequest createGetTrytesRequest(String... hashes) {
return new IotaGetTrytesRequest(hashes);
}
+
+ public String[] getHashes() {
+ return 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 82c96b1..c81c491 100644
--- a/src/main/java/jota/dto/request/IotaNeighborsRequest.java
+++ b/src/main/java/jota/dto/request/IotaNeighborsRequest.java
@@ -18,5 +18,13 @@ public class IotaNeighborsRequest extends IotaCommandRequest {
public static IotaNeighborsRequest createRemoveNeighborsRequest(String... uris) {
return new IotaNeighborsRequest(IotaAPICommands.REMOVE_NEIGHBORS, uris);
}
+
+ public String[] getUris() {
+ return 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 5247894..1b9c55b 100644
--- a/src/main/java/jota/dto/request/IotaStoreTransactionsRequest.java
+++ b/src/main/java/jota/dto/request/IotaStoreTransactionsRequest.java
@@ -14,4 +14,12 @@ public class IotaStoreTransactionsRequest extends IotaCommandRequest {
public static IotaStoreTransactionsRequest createStoreTransactionsRequest(final String... trytes) {
return new IotaStoreTransactionsRequest(trytes);
}
+
+ public String[] getTrytes() {
+ return 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 cab9488..e93ee07 100644
--- a/src/main/java/jota/dto/response/AbstractResponse.java
+++ b/src/main/java/jota/dto/response/AbstractResponse.java
@@ -7,12 +7,16 @@ import org.apache.commons.lang3.builder.ToStringStyle;
public abstract class AbstractResponse {
- private Integer duration;
+ private Long duration;
- public Integer getDuration() {
+ public Long getDuration() {
return duration;
}
+ public void setDuration(Long duration) {
+ this.duration = duration;
+ }
+
@Override
public String toString() {
return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
diff --git a/src/main/java/jota/dto/response/AnalyzeTransactionResponse.java b/src/main/java/jota/dto/response/AnalyzeTransactionResponse.java
index 53081ff..08c56cf 100644
--- a/src/main/java/jota/dto/response/AnalyzeTransactionResponse.java
+++ b/src/main/java/jota/dto/response/AnalyzeTransactionResponse.java
@@ -7,7 +7,7 @@ import java.util.List;
public class AnalyzeTransactionResponse extends AbstractResponse {
- private List transactions = new ArrayList();
+ private List transactions = new ArrayList<>();
public List getTransactions() {
return transactions;
diff --git a/src/main/java/jota/dto/response/GetAttachToTangleResponse.java b/src/main/java/jota/dto/response/GetAttachToTangleResponse.java
index 53eb98b..acbbc42 100644
--- a/src/main/java/jota/dto/response/GetAttachToTangleResponse.java
+++ b/src/main/java/jota/dto/response/GetAttachToTangleResponse.java
@@ -4,6 +4,10 @@ public class GetAttachToTangleResponse extends AbstractResponse {
private String[] trytes;
+ public GetAttachToTangleResponse(long duration) {
+ setDuration(duration);
+ }
+
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 493d063..f06d27a 100644
--- a/src/main/java/jota/dto/response/GetBalancesAndFormatResponse.java
+++ b/src/main/java/jota/dto/response/GetBalancesAndFormatResponse.java
@@ -1,14 +1,22 @@
package jota.dto.response;
-import java.util.List;
-
import jota.model.Input;
+import java.util.List;
+
public class GetBalancesAndFormatResponse extends AbstractResponse {
private List input;
private long totalBalance;
-
+
+ public static GetBalancesAndFormatResponse create(List inputs, long totalBalance2, long duration) {
+ GetBalancesAndFormatResponse res = new GetBalancesAndFormatResponse();
+ res.setInput(inputs);
+ res.setTotalBalance(totalBalance2);
+ res.setDuration(duration);
+ return res;
+ }
+
public List getInput() {
return input;
}
@@ -16,19 +24,12 @@ public class GetBalancesAndFormatResponse extends AbstractResponse {
public void setInput(List input) {
this.input = input;
}
-
+
public long getTotalBalance() {
return totalBalance;
}
-
+
public void setTotalBalance(long totalBalance) {
this.totalBalance = totalBalance;
}
-
- public static GetBalancesAndFormatResponse create(List inputs, long totalBalance2) {
- GetBalancesAndFormatResponse res = new GetBalancesAndFormatResponse();
- res.setInput(inputs);
- res.setTotalBalance(totalBalance2);
- return res;
- }
}
diff --git a/src/main/java/jota/dto/response/GetBundleResponse.java b/src/main/java/jota/dto/response/GetBundleResponse.java
index 278631f..c3dfa1b 100644
--- a/src/main/java/jota/dto/response/GetBundleResponse.java
+++ b/src/main/java/jota/dto/response/GetBundleResponse.java
@@ -9,7 +9,15 @@ public class GetBundleResponse extends AbstractResponse {
private List transactions = new ArrayList<>();
+ public static GetBundleResponse create(List transactions, long duration) {
+ GetBundleResponse res = new GetBundleResponse();
+ res.transactions = transactions;
+ res.setDuration(duration);
+ return res;
+ }
+
+
public List getTransactions() {
return transactions;
}
-}
+}
\ No newline at end of file
diff --git a/src/main/java/jota/dto/response/GetNewAddressResponse.java b/src/main/java/jota/dto/response/GetNewAddressResponse.java
index 484e17e..42d2288 100644
--- a/src/main/java/jota/dto/response/GetNewAddressResponse.java
+++ b/src/main/java/jota/dto/response/GetNewAddressResponse.java
@@ -6,9 +6,10 @@ public class GetNewAddressResponse extends AbstractResponse {
private List addresses;
- public static GetNewAddressResponse create(List addresses) {
+ public static GetNewAddressResponse create(List addresses, long duration) {
GetNewAddressResponse res = new GetNewAddressResponse();
res.addresses = addresses;
+ res.setDuration(duration);
return res;
}
diff --git a/src/main/java/jota/dto/response/GetTransferResponse.java b/src/main/java/jota/dto/response/GetTransferResponse.java
new file mode 100644
index 0000000..a4fc8da
--- /dev/null
+++ b/src/main/java/jota/dto/response/GetTransferResponse.java
@@ -0,0 +1,21 @@
+package jota.dto.response;
+
+import jota.model.Bundle;
+
+/**
+ * Created by pinpong on 28.12.16.
+ */
+public class GetTransferResponse extends AbstractResponse {
+
+ private Bundle[] transferBundle;
+
+ public static GetTransferResponse create(Bundle[] transferBundle, long duration) {
+ GetTransferResponse res = new GetTransferResponse();
+ res.transferBundle = transferBundle;
+ return res;
+ }
+
+ public Bundle[] getTransfers() {
+ return transferBundle;
+ }
+}
diff --git a/src/main/java/jota/dto/response/GetTransfersResponse.java b/src/main/java/jota/dto/response/GetTransfersResponse.java
deleted file mode 100644
index 441ccea..0000000
--- a/src/main/java/jota/dto/response/GetTransfersResponse.java
+++ /dev/null
@@ -1,15 +0,0 @@
-package jota.dto.response;
-
-import jota.model.Transfer;
-
-import java.util.ArrayList;
-import java.util.List;
-
-public class GetTransfersResponse extends AbstractResponse {
-
- private List transfers = new ArrayList<>();
-
- public List getTransfers() {
- return transfers;
- }
-}
diff --git a/src/main/java/jota/dto/response/ReplayBundleResponse.java b/src/main/java/jota/dto/response/ReplayBundleResponse.java
new file mode 100644
index 0000000..2c60c6c
--- /dev/null
+++ b/src/main/java/jota/dto/response/ReplayBundleResponse.java
@@ -0,0 +1,25 @@
+package jota.dto.response;
+
+/**
+ * Created by pinpong on 01.01.17.
+ */
+public class ReplayBundleResponse extends AbstractResponse {
+
+ private Boolean[] successfully;
+
+ public static ReplayBundleResponse create(Boolean[] successfully, long duration) {
+ ReplayBundleResponse res = new ReplayBundleResponse();
+ res.successfully = successfully;
+ res.setDuration(duration);
+ return res;
+ }
+
+ public Boolean[] getSuccessfully() {
+ return 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
new file mode 100644
index 0000000..d31b295
--- /dev/null
+++ b/src/main/java/jota/dto/response/SendTransferResponse.java
@@ -0,0 +1,25 @@
+package jota.dto.response;
+
+/**
+ * Created by pinpong on 28.12.16.
+ */
+public class SendTransferResponse extends AbstractResponse {
+
+ private Boolean[] successfully;
+
+ public static SendTransferResponse create(Boolean[] successfully, long duration) {
+ SendTransferResponse res = new SendTransferResponse();
+ res.successfully = successfully;
+ res.setDuration(duration);
+ return res;
+ }
+
+ public Boolean[] getSuccessfully() {
+ return 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 04128d2..af6c773 100644
--- a/src/main/java/jota/dto/response/StoreTransactionsResponse.java
+++ b/src/main/java/jota/dto/response/StoreTransactionsResponse.java
@@ -1,6 +1,8 @@
package jota.dto.response;
public class StoreTransactionsResponse extends AbstractResponse {
- // empty response
+ 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 c3da421..075d90e 100644
--- a/src/main/java/jota/error/ArgumentException.java
+++ b/src/main/java/jota/error/ArgumentException.java
@@ -10,4 +10,8 @@ public class ArgumentException extends BaseException {
public ArgumentException() {
super("Wrong arguments passed to function");
}
+
+ 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 2931408..972a0ac 100644
--- a/src/main/java/jota/error/BaseException.java
+++ b/src/main/java/jota/error/BaseException.java
@@ -1,5 +1,6 @@
package jota.error;
+import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -14,6 +15,10 @@ public class BaseException extends Exception {
public BaseException(String msg) {
super(msg);
+ if (messages == null) {
+ messages = new ArrayList<>();
+ }
+ messages.add(msg);
}
public BaseException(String msg, Exception cause) {
diff --git a/src/main/java/jota/error/BroadcastAndStoreException.java b/src/main/java/jota/error/BroadcastAndStoreException.java
new file mode 100644
index 0000000..a5b58e6
--- /dev/null
+++ b/src/main/java/jota/error/BroadcastAndStoreException.java
@@ -0,0 +1,11 @@
+package jota.error;
+
+/**
+ * Created by Adrian on 22.01.2017.
+ */
+public class BroadcastAndStoreException extends BaseException {
+
+ public BroadcastAndStoreException() {
+ super("Impossible to broadcastAndStore, aborting.");
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/jota/error/InvalidBundleException.java b/src/main/java/jota/error/InvalidBundleException.java
new file mode 100644
index 0000000..658011b
--- /dev/null
+++ b/src/main/java/jota/error/InvalidBundleException.java
@@ -0,0 +1,15 @@
+package jota.error;
+
+/**
+ * Created by Adrian on 27.12.2016.
+ */
+public class InvalidBundleException extends BaseException {
+
+ public InvalidBundleException() {
+ super("Invalid Bundle");
+ }
+
+ public InvalidBundleException(String msg) {
+ super(msg);
+ }
+}
diff --git a/src/main/java/jota/error/InvalidSignatureException.java b/src/main/java/jota/error/InvalidSignatureException.java
new file mode 100644
index 0000000..d8d5565
--- /dev/null
+++ b/src/main/java/jota/error/InvalidSignatureException.java
@@ -0,0 +1,10 @@
+package jota.error;
+
+/**
+ * Created by Adrian on 27.12.2016.
+ */
+public class InvalidSignatureException extends BaseException {
+ public InvalidSignatureException() {
+ super("Invalid Signatures!");
+ }
+}
diff --git a/src/main/java/jota/error/NoInclusionStatesExcpection.java b/src/main/java/jota/error/NoInclusionStatesExcpection.java
new file mode 100644
index 0000000..c79ee4b
--- /dev/null
+++ b/src/main/java/jota/error/NoInclusionStatesExcpection.java
@@ -0,0 +1,11 @@
+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
new file mode 100644
index 0000000..920c6f3
--- /dev/null
+++ b/src/main/java/jota/error/NoNodeInfoException.java
@@ -0,0 +1,11 @@
+package jota.error;
+
+/**
+ * Created by Adrian on 22.01.2017.
+ */
+public class NoNodeInfoException extends BaseException {
+
+ public NoNodeInfoException() {
+ super("Node info could not be retrieved");
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/jota/error/NotEnoughBalanceException.java b/src/main/java/jota/error/NotEnoughBalanceException.java
index 64c516c..dfe44a1 100644
--- a/src/main/java/jota/error/NotEnoughBalanceException.java
+++ b/src/main/java/jota/error/NotEnoughBalanceException.java
@@ -4,7 +4,7 @@ package jota.error;
* Created by Adrian on 09.12.2016.
*/
public class NotEnoughBalanceException extends BaseException {
-
+
private static final long serialVersionUID = -3807270816402226476L;
public NotEnoughBalanceException() {
diff --git a/src/main/java/jota/model/Bundle.java b/src/main/java/jota/model/Bundle.java
index 90d966d..7c02db5 100644
--- a/src/main/java/jota/model/Bundle.java
+++ b/src/main/java/jota/model/Bundle.java
@@ -1,20 +1,22 @@
package jota.model;
-import jota.pow.Curl;
+import jota.pow.ICurl;
+import jota.pow.JCurl;
import jota.utils.Converter;
+import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
import java.util.List;
+
/**
* Created by pinpong on 09.12.16.
*/
-public class Bundle {
-
- private List transactions;
- private int length;
+public class Bundle implements Comparable {
public static String EMPTY_HASH = "999999999999999999999999999999999999999999999999999999999999999999999999999999999";
+ private List transactions;
+ private int length;
public Bundle() {
@@ -30,10 +32,6 @@ public class Bundle {
return transactions;
}
- public void setTransactions(List transactions) {
- this.transactions = transactions;
- }
-
public int getLength() {
return length;
}
@@ -43,48 +41,37 @@ public class Bundle {
}
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++) {
-
- List transactions = new ArrayList<>(getTransactions());
- transactions.add(new Transaction(address, String.valueOf(i == 0 ? value : 0), tag, String.valueOf(timestamp)));
-
- setTransactions(transactions);
-
+ Transaction trx = new Transaction(address, String.valueOf(i == 0 ? value : 0), tag, String.valueOf(timestamp));
+ getTransactions().add(trx);
}
}
- public void finalize() {
+ public void finalize(ICurl customCurl) {
- Curl curl = new Curl();
+ ICurl curl = customCurl == null ? new JCurl() : customCurl;
curl.reset();
for (int i = 0; i < this.getTransactions().size(); i++) {
- int[] valueTrits = Converter.trits(this.getTransactions().get(i).getValue());
- while (valueTrits.length < 81) {
- valueTrits[valueTrits.length] = 0;
- }
+ int[] valueTrits = Converter.trits(this.getTransactions().get(i).getValue(), 81);
- int[] timestampTrits = Converter.trits(this.getTransactions().get(i).getTimestamp());
- while (timestampTrits.length < 27) {
- timestampTrits[timestampTrits.length] = 0;
- }
+ int[] timestampTrits = Converter.trits(this.getTransactions().get(i).getTimestamp(), 27);
- int[] currentIndexTrits = Converter.trits(this.getTransactions().get(i).setCurrentIndex("" + i));
- while (currentIndexTrits.length < 27) {
- currentIndexTrits[currentIndexTrits.length] = 0;
- }
+ int[] currentIndexTrits = Converter.trits(this.getTransactions().get(i).setCurrentIndex("" + i), 27);
+
+ int[] lastIndexTrits = Converter.trits(this.getTransactions().get(i).setLastIndex("" + (this.getTransactions().size() - 1)), 27);
- int[] lastIndexTrits = Converter.trits(this.getTransactions().get(i).setLastIndex("" + (this.getTransactions().size() - 1)));
- while (lastIndexTrits.length < 27) {
- lastIndexTrits[lastIndexTrits.length] = 0;
- }
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);
}
- int[] hash = new int[90];
+ int[] hash = new int[243];
curl.squeeze(hash, 0, hash.length);
String hashInTrytes = Converter.trytes(hash);
@@ -98,14 +85,12 @@ public class Bundle {
String emptySignatureFragment = "";
String emptyHash = EMPTY_HASH;
- for (int j = 0; emptySignatureFragment.length() < 2187; j++) {
- emptySignatureFragment += '9';
- }
+ emptySignatureFragment = StringUtils.rightPad(emptySignatureFragment, 2187, '9');
for (int i = 0; i < this.getTransactions().size(); i++) {
// Fill empty signatureMessageFragment
- this.getTransactions().get(i).setSignatureFragments(signatureFragments.get(i) == null ? signatureFragments.get(i) : emptySignatureFragment);
+ this.getTransactions().get(i).setSignatureFragments((signatureFragments.size() <= i || signatureFragments.get(i).isEmpty()) ? emptySignatureFragment : signatureFragments.get(i));
// Fill empty trunkTransaction
this.getTransactions().get(i).setTrunkTransaction(emptyHash);
@@ -118,14 +103,14 @@ public class Bundle {
}
public int[] normalizedBundle(String bundleHash) {
- int[] normalizedBundle = new int[33 * 27 + 27];
+ int[] normalizedBundle = new int[81];
for (int i = 0; i < 3; i++) {
long sum = 0;
for (int j = 0; j < 27; j++) {
- sum += (normalizedBundle[i * 27 + j] = Converter.value(Converter.trits("" + bundleHash.charAt(i * 27 + j))));
+ sum += (normalizedBundle[i * 27 + j] = Converter.value(Converter.tritsString("" + bundleHash.charAt(i * 27 + j))));
}
if (sum >= 0) {
@@ -155,4 +140,8 @@ public class Bundle {
return normalizedBundle;
}
-}
+ @Override
+ public int compareTo(Bundle o) {
+ return Long.compare(Long.parseLong(this.getTransactions().get(0).getTimestamp()), Long.parseLong(o.getTransactions().get(0).getTimestamp()));
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/jota/model/Inputs.java b/src/main/java/jota/model/Inputs.java
new file mode 100644
index 0000000..5d4b993
--- /dev/null
+++ b/src/main/java/jota/model/Inputs.java
@@ -0,0 +1,39 @@
+package jota.model;
+
+import com.google.gson.Gson;
+
+import java.util.List;
+
+/**
+ * Created by Adrian on 09.12.2016.
+ */
+public class Inputs {
+ private List inputsList;
+ private long totalBalance;
+
+ public Inputs(List inputsList, long totalBalance) {
+ this.inputsList = inputsList;
+ this.totalBalance = totalBalance;
+ }
+
+ @Override
+ public String toString() {
+ return new Gson().toJson(this);
+ }
+
+ public List getInputsList() {
+ return inputsList;
+ }
+
+ public void setInputsList(List inputsList) {
+ inputsList = inputsList;
+ }
+
+ public long getTotalBalance() {
+ return totalBalance;
+ }
+
+ public void setTotalBalance(long totalBalance) {
+ this.totalBalance = totalBalance;
+ }
+}
diff --git a/src/main/java/jota/model/Signature.java b/src/main/java/jota/model/Signature.java
new file mode 100644
index 0000000..3e0a9ba
--- /dev/null
+++ b/src/main/java/jota/model/Signature.java
@@ -0,0 +1,33 @@
+package jota.model;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Created by Adrian on 27.12.2016.
+ */
+public class Signature {
+
+ String address;
+ List signatureFragments;
+
+ public Signature() {
+ this.signatureFragments = new ArrayList<>();
+ }
+
+ public String getAddress() {
+ return address;
+ }
+
+ public void setAddress(String address) {
+ this.address = address;
+ }
+
+ public List getSignatureFragments() {
+ return 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 0f7f962..9b49bc8 100644
--- a/src/main/java/jota/model/Transaction.java
+++ b/src/main/java/jota/model/Transaction.java
@@ -1,12 +1,23 @@
package jota.model;
+import jota.pow.ICurl;
+import jota.pow.JCurl;
+import jota.utils.Converter;
+import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.Arrays;
/**
* Created by pinpong on 02.12.16.
*/
public class Transaction {
+ private static final Logger log = LoggerFactory.getLogger(Transaction.class);
+ private ICurl customCurl;
+
private String hash;
private String signatureFragments;
private String address;
@@ -21,8 +32,21 @@ public class Transaction {
private String nonce;
private Boolean persistence;
- public Transaction() {
+ public Transaction(ICurl curl) {
+ customCurl = curl;
+ }
+ public Transaction() {
+ customCurl = null;
+ }
+
+ public Transaction(String trytes) {
+ transactionObject(trytes);
+ }
+
+ 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) {
@@ -157,4 +181,72 @@ public class Transaction {
public void setPersistence(Boolean persistence) {
this.persistence = persistence;
}
+
+ public boolean equals(Object obj) {
+ return obj != null && ((Transaction) obj).getHash().equals(this.getHash());
+ }
+
+ public String toTrytes() {
+ int[] valueTrits = Converter.trits(this.getValue(), 81);
+
+ int[] timestampTrits = Converter.trits(this.getTimestamp(), 27);
+
+
+ int[] currentIndexTrits = Converter.trits(this.getCurrentIndex(), 27);
+
+
+ int[] lastIndexTrits = Converter.trits(this.getLastIndex(), 27);
+
+
+ return this.getSignatureFragments()
+ + this.getAddress()
+ + Converter.trytes(valueTrits)
+ + this.getTag()
+ + Converter.trytes(timestampTrits)
+ + Converter.trytes(currentIndexTrits)
+ + Converter.trytes(lastIndexTrits)
+ + this.getBundle()
+ + this.getTrunkTransaction()
+ + this.getBranchTransaction()
+ + this.getNonce();
+ }
+
+ public void transactionObject(final String trytes) {
+
+ if (StringUtils.isEmpty(trytes)) {
+ log.warn("Warning: empty trytes in input for transactionObject");
+ return;
+ }
+
+ // validity check
+ for (int i = 2279; i < 2295; i++) {
+ if (trytes.charAt(i) != '9') {
+ log.warn("Trytes {} does not seem a valid tryte", trytes);
+ return;
+ }
+ }
+
+ int[] transactionTrits = Converter.trits(trytes);
+ int[] hash = new int[243];
+
+ final ICurl curl = customCurl == null ? new JCurl() : customCurl; // we need a fluent JCurl.
+
+ // generate the correct transaction hash
+ 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.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.setBundle(trytes.substring(2349, 2430));
+ this.setTrunkTransaction(trytes.substring(2430, 2511));
+ this.setBranchTransaction(trytes.substring(2511, 2592));
+ this.setNonce(trytes.substring(2592, 2673));
+ }
}
\ No newline at end of file
diff --git a/src/main/java/jota/model/Transfer.java b/src/main/java/jota/model/Transfer.java
index a1b675e..65cb8de 100644
--- a/src/main/java/jota/model/Transfer.java
+++ b/src/main/java/jota/model/Transfer.java
@@ -16,7 +16,7 @@ public class Transfer {
private String tag;
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;
@@ -43,54 +43,54 @@ public class Transfer {
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;
- }
-
public void setAddress(String address) {
this.address = address;
}
+ public String getHash() {
+ return hash;
+ }
+
public void setHash(String hash) {
this.hash = hash;
}
+ public Boolean getPersistence() {
+ return persistence;
+ }
+
public void setPersistence(Boolean persistence) {
this.persistence = persistence;
}
+ public String getTimestamp() {
+ return timestamp;
+ }
+
+ public void setTimestamp(String timestamp) {
+ this.timestamp = timestamp;
+ }
+
+ public long getValue() {
+ return value;
+ }
+
public void setValue(long value) {
this.value = value;
}
+ public String getMessage() {
+ return message;
+ }
+
public void setMessage(String message) {
this.message = message;
}
+ public String getTag() {
+ return 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
new file mode 100644
index 0000000..9534837
--- /dev/null
+++ b/src/main/java/jota/pow/ICurl.java
@@ -0,0 +1,22 @@
+package jota.pow;
+
+/**
+ * Created by Adrian on 07.01.2017.
+ */
+public interface ICurl {
+ JCurl absorb(final int[] trits, int offset, int length);
+
+ JCurl absorb(final int[] trits);
+
+ int[] squeeze(final int[] trits, int offset, int length);
+
+ int[] squeeze(final int[] trits);
+
+ JCurl transform();
+
+ JCurl reset();
+
+ int[] getState();
+
+ void setState(int[] state);
+}
diff --git a/src/main/java/jota/pow/Curl.java b/src/main/java/jota/pow/JCurl.java
similarity index 84%
rename from src/main/java/jota/pow/Curl.java
rename to src/main/java/jota/pow/JCurl.java
index b804250..8eeebf1 100644
--- a/src/main/java/jota/pow/Curl.java
+++ b/src/main/java/jota/pow/JCurl.java
@@ -3,9 +3,9 @@ package jota.pow;
/**
* (c) 2016 Come-from-Beyond
*
- * Curl belongs to the sponge function family.
+ * JCurl belongs to the sponge function family.
*/
-public class Curl {
+public class JCurl implements ICurl {
public static final int HASH_LENGTH = 243;
private static final int STATE_LENGTH = 3 * HASH_LENGTH;
@@ -15,22 +15,23 @@ public class Curl {
private int[] state = new int[STATE_LENGTH];
- public Curl absorb(final int[] trits, int offset, int length) {
+ public JCurl absorb(final int[] trits, int offset, int length) {
do {
System.arraycopy(trits, offset, state, 0, length < HASH_LENGTH ? length : HASH_LENGTH);
transform();
offset += HASH_LENGTH;
} while ((length -= HASH_LENGTH) > 0);
-
+
return this;
}
-
- public Curl absorb(final int[] trits) {
+
+
+ public JCurl absorb(final int[] trits) {
return absorb(trits, 0, trits.length);
}
- public Curl transform() {
+ public JCurl transform() {
final int[] scratchpad = new int[STATE_LENGTH];
int scratchpadIndex = 0;
@@ -43,13 +44,13 @@ public class Curl {
return this;
}
- public Curl reset() {
+ public JCurl reset() {
for (int stateIndex = 0; stateIndex < STATE_LENGTH; stateIndex++) {
state[stateIndex] = 0;
}
return this;
}
-
+
public int[] squeeze(final int[] trits, int offset, int length) {
do {
@@ -60,7 +61,7 @@ public class Curl {
return state;
}
-
+
public int[] squeeze(final int[] trits) {
return squeeze(trits, 0, trits.length);
}
@@ -68,7 +69,8 @@ public class Curl {
public int[] getState() {
return state;
}
- public void setState(int[] state) {
- this.state = state;
+
+ public void setState(int[] state) {
+ this.state = state;
}
}
diff --git a/src/main/java/jota/utils/Checksum.java b/src/main/java/jota/utils/Checksum.java
index 6bf83f5..79605e5 100644
--- a/src/main/java/jota/utils/Checksum.java
+++ b/src/main/java/jota/utils/Checksum.java
@@ -1,9 +1,8 @@
package jota.utils;
+import jota.pow.JCurl;
import org.apache.commons.lang3.StringUtils;
-import jota.pow.Curl;
-
/**
* Created by pinpong on 02.12.16.
*/
@@ -33,12 +32,16 @@ public class Checksum {
return addressWithRecalculateChecksum.equals(addressWithChecksum);
}
- private static boolean isAddressWithChecksum(String addressWithChecksum) {
- return InputValidator.checkAddress(addressWithChecksum) && addressWithChecksum.length() == Constants.ADDRESS_LENGTH_WITH_CHECKSUM;
+ public static boolean isAddressWithChecksum(String address) {
+ return InputValidator.checkAddress(address) && address.length() == Constants.ADDRESS_LENGTH_WITH_CHECKSUM;
+ }
+
+ public static boolean isAddressWithoutChecksum(String address) {
+ return InputValidator.checkAddress(address) && address.length() == Constants.ADDRESS_LENGTH_WITHOUT_CHECKSUM;
}
public static String calculateChecksum(String address) {
- Curl curl = new Curl();
+ JCurl curl = new JCurl();
curl.reset();
curl.setState(Converter.copyTrits(address, curl.getState()));
curl.transform();
diff --git a/src/main/java/jota/utils/Converter.java b/src/main/java/jota/utils/Converter.java
index 4276b08..283c20b 100644
--- a/src/main/java/jota/utils/Converter.java
+++ b/src/main/java/jota/utils/Converter.java
@@ -1,16 +1,10 @@
package jota.utils;
-import jota.model.Transaction;
-import jota.pow.Curl;
-import org.apache.commons.lang3.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
public class Converter {
-
- private static final Logger log = LoggerFactory.getLogger(Converter.class);
private static final int RADIX = 3;
private static final int MAX_TRIT_VALUE = (RADIX - 1) / 2, MIN_TRIT_VALUE = -MAX_TRIT_VALUE;
@@ -66,15 +60,46 @@ public class Converter {
}
}
- public static int[] trits(final String trytes) {
- final int[] trits = new int[trytes.length() * NUMBER_OF_TRITS_IN_A_TRYTE];
+ public static int[] convertToIntArray(List integers) {
+ int[] ret = new int[integers.size()];
+ for (int i = 0; i < ret.length; i++) {
+ ret[i] = integers.get(i);
+ }
+ return ret;
+ }
+ public static int[] trits(final String trytes, int length) {
+ int[] trits = trits(trytes);
+
+ List tritsList = new LinkedList<>();
+
+ for (int i : trits)
+ tritsList.add(i);
+
+ while (tritsList.size() < length)
+ tritsList.add(0);
+
+ return convertToIntArray(tritsList);
+ }
+
+ 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);
+ }
+ return d;
+ }
+
+ public static int[] trits(final String trytes) {
+ final List trits = new LinkedList<>();
if (InputValidator.isValue(trytes)) {
- int value = Integer.parseInt(trytes);
+ long value = Long.parseLong(trytes);
long absoluteValue = value < 0 ? -value : value;
+ int position = 0;
+
while (absoluteValue > 0) {
int remainder = (int) (absoluteValue % RADIX);
@@ -85,22 +110,21 @@ public class Converter {
absoluteValue++;
}
- trits[trits.length] = remainder;
+ trits.add(position++, remainder);
}
if (value < 0) {
-
- for (int i = 0; i < trits.length; i++) {
-
- trits[i] = -trits[i];
+ for (int i = 0; i < trits.size(); i++) {
+ trits.set(i, -trits.get(i));
}
}
} else {
-
+ 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, trits, i * NUMBER_OF_TRITS_IN_A_TRYTE, NUMBER_OF_TRITS_IN_A_TRYTE);
+ 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);
}
+ return d;
}
- return trits;
+ return convertToIntArray(trits);
}
public static void copyTrits(final long value, final int[] destination, final int offset, final int size) {
@@ -168,6 +192,15 @@ public class Converter {
return value;
}
+ public static long longValue(final int[] trits) {
+ long value = 0;
+
+ for (int i = trits.length; i-- > 0; ) {
+ value = value * 3 + trits[i];
+ }
+ return value;
+ }
+
public static void increment(final int[] trits, final int size) {
for (int i = 0; i < size; i++) {
@@ -178,47 +211,5 @@ public class Converter {
}
}
}
-
- public static Transaction transactionObject(final String trytes) {
-
- if (StringUtils.isEmpty(trytes)) {
- log.warn("Warning: empty trytes in input for transactionObject");
- return null;
- }
-
- // validity check
- for (int i = 2279; i < 2295; i++) {
- if (trytes.charAt(i) != '9') {
- log.warn("Trytes {} does not seem a valid tryte", trytes);
- return null;
- }
- }
-
- int[] transactionTrits = Converter.trits(trytes);
- int[] hash = new int[90];
- final Curl curl = new Curl(); // we need a fluent Curl.
-
- // generate the correct transaction hash
- curl.reset();
- curl.absorb(transactionTrits, 0, transactionTrits.length);
- curl.squeeze(hash, 0, hash.length);
-
- Transaction trx = new Transaction();
-
- trx.setHash(Converter.trytes(hash));
- trx.setSignatureFragments(trytes.substring(0, 2187));
- trx.setAddress(trytes.substring(2187, 2268));
- trx.setValue("" + Converter.value(Arrays.copyOfRange(transactionTrits, 6804, 6837)));
- trx.setTag(trytes.substring(2295, 2322));
- trx.setTimestamp("" + Converter.value(Arrays.copyOfRange(transactionTrits, 6966, 6993)));
- trx.setCurrentIndex("" + Converter.value(Arrays.copyOfRange(transactionTrits, 6993, 7020)));
- trx.setLastIndex("" + Converter.value(Arrays.copyOfRange(transactionTrits, 7020, 7047)));
- trx.setBundle(trytes.substring(2349, 2430));
- trx.setTrunkTransaction(trytes.substring(2430, 2511));
- trx.setBranchTransaction(trytes.substring(2511, 2592));
- trx.setNonce(trytes.substring(2592, 2673));
-
- return trx;
- }
-}
+}
\ 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 6e85443..4e01cd4 100644
--- a/src/main/java/jota/utils/InputValidator.java
+++ b/src/main/java/jota/utils/InputValidator.java
@@ -1,11 +1,10 @@
package jota.utils;
-import java.util.List;
-
-import org.apache.commons.lang3.StringUtils;
-
-import jota.model.Transaction;
import jota.model.Transfer;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.math.NumberUtils;
+
+import java.util.List;
/**
* Created by pinpong on 02.12.16.
@@ -27,13 +26,14 @@ public class InputValidator {
public static boolean isTrytes(final String trytes, final int length) {
return trytes.matches("^[A-Z9]{" + (length == 0 ? "0," : length) + "}$");
}
-
+
public static boolean isValue(final String value) {
- return StringUtils.isNumeric(value);
+ return NumberUtils.isNumber(value);
}
public static boolean isArrayOfHashes(String[] hashes) {
- if (hashes == null) return false;
+ if (hashes == null)
+ return false;
for (String hash : hashes) {
// Check if address with checksum
@@ -49,16 +49,16 @@ public class InputValidator {
}
return true;
}
-
+
/**
- * checks if input is correct hash collections
- *
- * @method isTransfersArray
- * @param {array} hash
- * @returns {boolean}
- **/
+ * checks if input is correct hash collections
+ *
+ * @param {array} hash
+ * @method isTransfersArray
+ * @returns {boolean}
+ **/
public static boolean isTransfersCollectionCorrect(final List transfers) {
-
+
for (final Transfer transfer : transfers) {
if (!isTransfersArray(transfer)) {
return false;
@@ -66,9 +66,9 @@ public class InputValidator {
}
return true;
}
-
+
public static boolean isTransfersArray(final Transfer transfer) {
-
+
if (!isAddress(transfer.getAddress())) {
return false;
}
@@ -79,10 +79,15 @@ public class InputValidator {
}
// Check if tag is correct trytes of {0,27} trytes
- if (!isTrytes(transfer.getTag(), 27)) {
- return false;
- }
+ return isTrytes(transfer.getTag(), 27);
+ }
- return true;
+ public static String validateSeed(String seed) {
+ if (seed.length() > 81)
+ return null;
+
+ seed = StringUtils.rightPad(seed, 81, '9');
+
+ return seed;
}
}
diff --git a/src/main/java/jota/utils/IotaAPIUtils.java b/src/main/java/jota/utils/IotaAPIUtils.java
index 617f014..3d59c4c 100644
--- a/src/main/java/jota/utils/IotaAPIUtils.java
+++ b/src/main/java/jota/utils/IotaAPIUtils.java
@@ -1,17 +1,17 @@
package jota.utils;
+import jota.model.Bundle;
+import jota.model.Input;
+import jota.model.Transaction;
+import jota.pow.ICurl;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import jota.model.Bundle;
-import jota.model.Input;
-import jota.model.Transaction;
-
/**
* Client Side computation service
*
@@ -29,11 +29,11 @@ public class IotaAPIUtils {
* @param checksum
* @return an String with address
*/
- public static String newAddress(String seed, int index, boolean checksum) {
-
- final int[] key = Signing.key(Converter.trits(seed), index, 2);
- final int[] digests = Signing.digests(key);
- final int[] addressTrits = Signing.address(digests);
+ public static String newAddress(String seed, int index, boolean checksum, ICurl curl) {
+ Signing signing = new Signing(curl);
+ final int[] key = signing.key(Converter.trits(seed), index, 2);
+ final int[] digests = signing.digests(key);
+ final int[] addressTrits = signing.address(digests);
String address = Converter.trytes(addressTrits);
@@ -43,45 +43,11 @@ public class IotaAPIUtils {
return address;
}
- public static String transactionTrytes(Transaction trx) {
- int[] valueTrits = Converter.trits(trx.getValue());
- while (valueTrits.length < 81) {
- valueTrits[valueTrits.length] = 0;
- }
-
- int[] timestampTrits = Converter.trits(trx.getTimestamp());
- while (timestampTrits.length < 27) {
- timestampTrits[timestampTrits.length] = 0;
- }
-
- int[] currentIndexTrits = Converter.trits(trx.getTimestamp());
- while (currentIndexTrits.length < 27) {
- currentIndexTrits[currentIndexTrits.length] = 0;
- }
-
- int[] lastIndexTrits = Converter.trits(trx.getCurrentIndex());
- while (lastIndexTrits.length < 27) {
- lastIndexTrits[lastIndexTrits.length] = 0;
- }
-
- return trx.getSignatureFragments()
- + trx.getAddress()
- + Converter.trytes(valueTrits)
- + trx.getTag()
- + Converter.trytes(timestampTrits)
- + Converter.trytes(currentIndexTrits)
- + Converter.trytes(lastIndexTrits)
- + trx.getBundle()
- + trx.getTrunkTransaction()
- + trx.getBranchTransaction()
- + trx.getNonce();
- }
-
- public static List signInputsAndReturn(final String seed,
- final List inputs,
+ public static List signInputsAndReturn(final String seed,
+ final List inputs,
final Bundle bundle,
- final List signatureFragments) {
- bundle.finalize();
+ final List signatureFragments, ICurl curl) {
+ bundle.finalize(curl);
bundle.addTrytes(signatureFragments);
// SIGNING OF INPUTS
@@ -95,9 +61,9 @@ public class IotaAPIUtils {
// Get the corresponding keyIndex of the address
int keyIndex = 0;
- for (int k = 0; k < inputs.size(); k++) {
- if (inputs.get(k).getAddress().equals(thisAddress)) {
- keyIndex = inputs.get(k).getKeyIndex();
+ for (Input input : inputs) {
+ if (input.getAddress().equals(thisAddress)) {
+ keyIndex = input.getKeyIndex();
break;
}
}
@@ -105,7 +71,7 @@ public class IotaAPIUtils {
String bundleHash = bundle.getTransactions().get(i).getBundle();
// Get corresponding private key of address
- int[] key = Signing.key(Converter.trits(seed), keyIndex, 2);
+ int[] key = new Signing(curl).key(Converter.trits(seed), keyIndex, 2);
// First 6561 trits for the firstFragment
int[] firstFragment = Arrays.copyOfRange(key, 0, 6561);
@@ -117,7 +83,7 @@ public class IotaAPIUtils {
int[] firstBundleFragment = Arrays.copyOfRange(normalizedBundleHash, 0, 27);
// Calculate the new signatureFragment with the first bundle fragment
- int[] firstSignedFragment = Signing.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));
@@ -126,7 +92,7 @@ public class IotaAPIUtils {
// 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() == thisAddress && Long.parseLong(bundle.getTransactions().get(j).getValue()) == 0) {
+ 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);
@@ -134,7 +100,7 @@ public class IotaAPIUtils {
int[] secondBundleFragment = Arrays.copyOfRange(normalizedBundleHash, 27, 27 * 2);
// Calculate the new signature
- int[] secondSignedFragment = Signing.signatureFragment(secondBundleFragment, secondFragment);
+ int[] secondSignedFragment = new Signing(curl).signatureFragment(secondBundleFragment, secondFragment);
// Convert signature to trytes and assign it again to this bundle entry
bundle.getTransactions().get(j).setSignatureFragments(Converter.trytes(secondSignedFragment));
@@ -147,7 +113,7 @@ public class IotaAPIUtils {
// Convert all bundle entries into trytes
for (Transaction tx : bundle.getTransactions()) {
- bundleTrytes.add(IotaAPIUtils.transactionTrytes(tx));
+ bundleTrytes.add(tx.toTrytes());
}
Collections.reverse(bundleTrytes);
return bundleTrytes;
diff --git a/src/main/java/jota/utils/IotaUnitConverter.java b/src/main/java/jota/utils/IotaUnitConverter.java
index d25a39e..def86e0 100644
--- a/src/main/java/jota/utils/IotaUnitConverter.java
+++ b/src/main/java/jota/utils/IotaUnitConverter.java
@@ -16,24 +16,28 @@ public class IotaUnitConverter {
return (long) (amount / Math.pow(10, toUnit.getValue()));
}
- public static String convertRawIotaAmountToDisplayText(long amount) {
+ public static String convertRawIotaAmountToDisplayText(long amount, boolean extended) {
IotaUnits unit = findOptimalIotaUnitToDisplay(amount);
double amountInDisplayUnit = convertAmountTo(amount, unit);
- return createAmountWithUnitDisplayText(amountInDisplayUnit, unit);
+ return createAmountWithUnitDisplayText(amountInDisplayUnit, unit, extended);
}
public static double convertAmountTo(long amount, IotaUnits target) {
return amount / Math.pow(10, target.getValue());
}
- private static String createAmountWithUnitDisplayText(double amountInUnit, IotaUnits unit) {
- String result = createAmountDisplayText(amountInUnit, unit);
+ private static String createAmountWithUnitDisplayText(double amountInUnit, IotaUnits unit, boolean extended) {
+ String result = createAmountDisplayText(amountInUnit, unit, extended);
result += " " + unit.getUnit();
return result;
}
- public static String createAmountDisplayText(double amountInUnit, IotaUnits unit) {
- DecimalFormat df = new DecimalFormat("##0.##################");
+ public static String createAmountDisplayText(double amountInUnit, IotaUnits unit, boolean extended) {
+ DecimalFormat df;
+ if (extended) df = new DecimalFormat("##0.##################");
+ else
+ df = new DecimalFormat("##0.##");
+
String result = "";
// display unit as integer if value is between 1-999 or in decimal format
result += unit == IotaUnits.IOTA ? (long) amountInUnit : df.format(amountInUnit);
@@ -43,7 +47,7 @@ public class IotaUnitConverter {
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 779dde0..e799913 100644
--- a/src/main/java/jota/utils/IotaUnits.java
+++ b/src/main/java/jota/utils/IotaUnits.java
@@ -1,14 +1,10 @@
package jota.utils;
-/**
- * Created by pinpong on 30.11.16.
- */
-
/**
* Table of IOTA units based off of the standard system of Units
**/
public enum IotaUnits {
-
+
IOTA("i", 0),
KILO_IOTA("Ki", 3),
MEGA_IOTA("Mi", 6),
diff --git a/src/main/java/jota/utils/NamedThreadFactory.java b/src/main/java/jota/utils/NamedThreadFactory.java
new file mode 100644
index 0000000..a6e3dab
--- /dev/null
+++ b/src/main/java/jota/utils/NamedThreadFactory.java
@@ -0,0 +1,26 @@
+package jota.utils;
+
+import java.util.concurrent.Executors;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Created by Adrian on 15.01.2017.
+ */
+public class NamedThreadFactory implements ThreadFactory {
+ private final String baseName;
+ private final AtomicInteger threadNum = new AtomicInteger(0);
+
+ public NamedThreadFactory(String baseName) {
+ this.baseName = baseName;
+ }
+
+ @Override
+ public synchronized Thread newThread(Runnable r) {
+ Thread t = Executors.defaultThreadFactory().newThread(r);
+
+ t.setName(baseName + "-" + threadNum.getAndIncrement());
+
+ return t;
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/jota/utils/Parallel.java b/src/main/java/jota/utils/Parallel.java
new file mode 100644
index 0000000..f5cdeb7
--- /dev/null
+++ b/src/main/java/jota/utils/Parallel.java
@@ -0,0 +1,45 @@
+package jota.utils;
+
+import java.util.Collection;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+/**
+ * Created by Adrian on 15.01.2017.
+ */
+public class Parallel {
+ private static final int NUM_CORES = Runtime.getRuntime().availableProcessors();
+
+ private static final ExecutorService forPool = Executors.newFixedThreadPool(NUM_CORES * 2, new NamedThreadFactory("Parallel.For"));
+
+ public static void For(final Iterable elements, final Operation operation) {
+ try {
+ // invokeAll blocks for us until all submitted tasks in the call complete
+ forPool.invokeAll(createCallables(elements, operation));
+ } catch (InterruptedException e) {
+ e.printStackTrace();
+ }
+ }
+
+ public static Collection> createCallables(final Iterable elements, final Operation operation) {
+ List> callables = new LinkedList<>();
+ for (final T elem : elements) {
+ callables.add(new Callable() {
+ @Override
+ public Void call() {
+ operation.perform(elem);
+ return null;
+ }
+ });
+ }
+
+ return callables;
+ }
+
+ public interface Operation {
+ void perform(T pParameter);
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/jota/utils/Signing.java b/src/main/java/jota/utils/Signing.java
index e0f2e84..30b55e8 100644
--- a/src/main/java/jota/utils/Signing.java
+++ b/src/main/java/jota/utils/Signing.java
@@ -1,15 +1,25 @@
package jota.utils;
+import jota.model.Bundle;
+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.Curl;
-
public class Signing {
+ private ICurl curl;
- static int[] key(int[] seed, int index, int length) {
+ public Signing() {
+ this(null);
+ }
+
+ public Signing(ICurl curl) {
+ this.curl = curl == null ? new JCurl() : curl;
+ }
+
+ public int[] key(int[] seed, int index, int length) {
for (int i = 0; i < index; i++) {
for (int j = 0; j < 243; j++) {
@@ -21,7 +31,6 @@ public class Signing {
}
}
- final Curl curl = new Curl();
curl.reset();
curl.absorb(seed, 0, seed.length);
curl.squeeze(seed, 0, seed.length);
@@ -44,7 +53,7 @@ public class Signing {
return to(key);
}
- private static int[] to(List key) {
+ private int[] to(List key) {
int a[] = new int[key.size()];
int i = 0;
for (Integer v : key) {
@@ -53,42 +62,37 @@ public class Signing {
return a;
}
- public static int[] signatureFragment(int[] normalizedBundleFragment, int[] keyFragment) {
+ public int[] signatureFragment(int[] normalizedBundleFragment, int[] keyFragment) {
- int[] signatureFragment = keyFragment;
int[] hash;
- Curl curl = new Curl();
-
for (int i = 0; i < 27; i++) {
- hash = Arrays.copyOfRange(signatureFragment, i * 243, (i + 1) * 243);
+ hash = Arrays.copyOfRange(keyFragment, i * 243, (i + 1) * 243);
for (int j = 0; j < 13 - normalizedBundleFragment[i]; j++) {
curl.reset()
- .absorb(hash, 0, hash.length)
- .squeeze(hash, 0, hash.length);
+ .absorb(hash, 0, hash.length)
+ .squeeze(hash, 0, hash.length);
}
for (int j = 0; j < 243; j++) {
- signatureFragment[i * 243 + j] = hash[j];
+ System.arraycopy(hash, j, keyFragment, i * 243 + j, 1);
}
}
- return signatureFragment;
+ return keyFragment;
}
- public static int[] address(int[] digests) {
- final Curl curl = new Curl();
+ public int[] address(int[] digests) {
int[] address = new int[243];
curl.reset()
- .absorb(digests)
- .squeeze(address);
+ .absorb(digests)
+ .squeeze(address);
return address;
}
-
- public static int[] digests(int[] key) {
- final Curl curl = new Curl();
+
+ public int[] digests(int[] key) {
int[] digests = new int[(int) Math.floor(key.length / 6561) * 243];
int[] buffer = new int[243];
@@ -101,8 +105,8 @@ public class Signing {
buffer = Arrays.copyOfRange(keyFragment, j * 243, (j + 1) * 243);
for (int k = 0; k < 26; k++) {
curl.reset()
- .absorb(buffer)
- .squeeze(buffer);
+ .absorb(buffer)
+ .squeeze(buffer);
}
System.arraycopy(buffer, 0, keyFragment, j * 243, 243);
}
@@ -116,20 +120,19 @@ public class Signing {
return digests;
}
- public static int[] digest(int[] normalizedBundleFragment, int[] signatureFragment) {
-
+ public int[] digest(int[] normalizedBundleFragment, int[] signatureFragment) {
+ curl.reset();
int[] buffer = new int[243];
- Curl curl = new Curl().reset();
-
for (int i = 0; i < 27; i++) {
buffer = Arrays.copyOfRange(signatureFragment, i * 243, (i + 1) * 243);
for (int j = normalizedBundleFragment[i] + 13; j-- > 0; ) {
- new Curl().reset()
- .absorb(buffer)
- .squeeze(buffer);
+ ICurl jCurl = new JCurl();
+ jCurl.reset();
+ jCurl.absorb(buffer);
+ jCurl.squeeze(buffer);
}
curl.absorb(buffer);
}
@@ -138,7 +141,7 @@ public class Signing {
return buffer;
}
- public static Boolean validateSignatures(String expectedAddress, String[] signatureFragments, String bundleHash) {
+ public Boolean validateSignatures(String expectedAddress, String[] signatureFragments, String bundleHash) {
Bundle bundle = new Bundle();
@@ -151,18 +154,16 @@ public class Signing {
}
// Get digests
- int[] digests = new int[signatureFragments.length * 243 + 243];
+ int[] digests = new int[signatureFragments.length * 243];
for (int i = 0; i < signatureFragments.length; i++) {
int[] digestBuffer = digest(normalizedBundleFragments[i % 3], Converter.trits(signatureFragments[i]));
for (int j = 0; j < 243; j++) {
-
- digests[i * 243 + j] = digestBuffer[j];
+ System.arraycopy(digestBuffer, j, digests, i * 243 + j, 1);
}
}
-
String address = Converter.trytes(address(digests));
return (expectedAddress.equals(address));
diff --git a/src/main/java/jota/utils/StopWatch.java b/src/main/java/jota/utils/StopWatch.java
new file mode 100644
index 0000000..699de6f
--- /dev/null
+++ b/src/main/java/jota/utils/StopWatch.java
@@ -0,0 +1,71 @@
+package jota.utils;
+
+/**
+ * Created by Adrian on 15.01.2017.
+ */
+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;
+ }
+
+ 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
+ public long getElapsedTimeMili() {
+ long elapsed = 0;
+ if (running) {
+ elapsed = (System.currentTimeMillis() - startTime);
+ }
+ return elapsed;
+ }
+
+ //elaspsed time in seconds
+ public long getElapsedTimeSecs() {
+ long elapsed = 0;
+ if (running) {
+ elapsed = (System.currentTimeMillis() - startTime) / 1000;
+ }
+ return elapsed;
+ }
+
+ //elaspsed time in minutes
+ public long getElapsedTimeMin() {
+ long elapsed = 0;
+ if (running) {
+ elapsed = (System.currentTimeMillis() - startTime) / 1000 / 60;
+ }
+ return elapsed;
+ }
+
+ //elaspsed time in hours
+ public long getElapsedTimeHour() {
+ long elapsed = 0;
+ if (running) {
+ elapsed = ((System.currentTimeMillis() - startTime) / 1000 / 3600);
+ }
+ return elapsed;
+ }
+}
diff --git a/src/main/java/jota/utils/TrytesConverter.java b/src/main/java/jota/utils/TrytesConverter.java
index ab9d02a..81f585a 100644
--- a/src/main/java/jota/utils/TrytesConverter.java
+++ b/src/main/java/jota/utils/TrytesConverter.java
@@ -4,7 +4,7 @@ package jota.utils;
* Created by pinpong on 01.12.16.
*/
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 +19,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:
@@ -32,10 +32,9 @@ public class TrytesConverter {
* 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
+ * @return The ASCII char "Z" is represented as "IC" in trytes.
*/
public static String toTrytes(String inputString) {
diff --git a/src/test/java/jota/InputValidatorTest.java b/src/test/java/jota/InputValidatorTest.java
index b898baf..c41b4bd 100644
--- a/src/test/java/jota/InputValidatorTest.java
+++ b/src/test/java/jota/InputValidatorTest.java
@@ -20,6 +20,7 @@ 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);
diff --git a/src/test/java/jota/IotaAPIProxyTest.java b/src/test/java/jota/IotaAPIProxyTest.java
deleted file mode 100644
index ffb52ac..0000000
--- a/src/test/java/jota/IotaAPIProxyTest.java
+++ /dev/null
@@ -1,183 +0,0 @@
-package jota;
-
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import jota.dto.response.*;
-import jota.model.Transfer;
-import org.hamcrest.core.Is;
-import org.hamcrest.core.IsNull;
-import org.junit.Before;
-import org.junit.Test;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import static org.junit.Assert.assertThat;
-
-/**
- * Let's do some integration test coverage against a default local real node.
- *
- * @author davassi
- */
-public class IotaAPIProxyTest {
-
- private static Gson gson = new GsonBuilder().create();
-
- private static final String TEST_SEED = "AAA999999999999999999999999999999999999999999999999999999999999999999999999999999";
- private static final String TEST_ADDRESS_WITHOUT_CHECKSUM = "PNGMCSNRCTRHCHPXYTPKEJYPCOWKOMRXZFHH9N9VDIKMNVAZCMIYRHVJIAZARZTUETJVFDMBEBIQE9QTH";
- private static final String TEST_ADDRESS_WITH_CHECKSUM = "PNGMCSNRCTRHCHPXYTPKEJYPCOWKOMRXZFHH9N9VDIKMNVAZCMIYRHVJIAZARZTUETJVFDMBEBIQE9QTHBFWDAOEFA";
- private static final String TEST_HASH = "OAATQS9VQLSXCLDJVJJVYUGONXAXOFMJOZNSYWRZSWECMXAQQURHQBJNLD9IOFEPGZEPEMPXCIVRX9999";
- private static final String TEST_TRYTES = "BYSWEAUTWXHXZ9YBZISEK9LUHWGMHXCGEVNZHRLUWQFCUSDXZHOFHWHL9MQPVJXXZLIXPXPXF9KYEREFSKCPKYIIKPZVLHUTDFQKKVVBBN9ATTLPCNPJDWDEVIYYLGPZGCWXOBDXMLJC9VO9QXTTBLAXTTBFUAROYEGQIVB9MJWJKXJMCUPTWAUGFZBTZCSJVRBGMYXTVBDDS9MYUJCPZ9YDWWQNIPUAIJXXSNLKUBSCOIJPCLEFPOXFJREXQCUVUMKSDOVQGGHRNILCO9GNCLWFM9APMNMWYASHXQAYBEXF9QRIHIBHYEJOYHRQJAOKAQ9AJJFQ9WEIWIJOTZATIBOXQLBMIJU9PCGBLVDDVFP9CFFSXTDUXMEGOOFXWRTLFGV9XXMYWEMGQEEEDBTIJ9OJOXFAPFQXCDAXOUDMLVYRMRLUDBETOLRJQAEDDLNVIRQJUBZBO9CCFDHIX9MSQCWYAXJVWHCUPTRSXJDESISQPRKZAFKFRULCGVRSBLVFOPEYLEE99JD9SEBALQINPDAZHFAB9RNBH9AZWIJOTLBZVIEJIAYGMC9AZGNFWGRSWAXTYSXVROVNKCOQQIWGPNQZKHUNODGYADPYLZZZUQRTJRTODOUKAOITNOMWNGHJBBA99QUMBHRENGBHTH9KHUAOXBVIVDVYYZMSEYSJWIOGGXZVRGN999EEGQMCOYVJQRIRROMPCQBLDYIGQO9AMORPYFSSUGACOJXGAQSPDY9YWRRPESNXXBDQ9OZOXVIOMLGTSWAMKMTDRSPGJKGBXQIVNRJRFRYEZ9VJDLHIKPSKMYC9YEGHFDS9SGVDHRIXBEMLFIINOHVPXIFAZCJKBHVMQZEVWCOSNWQRDYWVAIBLSCBGESJUIBWZECPUCAYAWMTQKRMCHONIPKJYYTEGZCJYCT9ABRWTJLRQXKMWY9GWZMHYZNWPXULNZAPVQLPMYQZCYNEPOCGOHBJUZLZDPIXVHLDMQYJUUBEDXXPXFLNRGIPWBRNQQZJSGSJTTYHIGGFAWJVXWL9THTPWOOHTNQWCNYOYZXALHAZXVMIZE9WMQUDCHDJMIBWKTYH9AC9AFOT9DPCADCV9ZWUTE9QNOMSZPTZDJLJZCJGHXUNBJFUBJWQUEZDMHXGBPTNSPZBR9TGSKVOHMOQSWPGFLSWNESFKSAZY9HHERAXALZCABFYPOVLAHMIHVDBGKUMDXC9WHHTIRYHZVWNXSVQUWCR9M9RAGMFEZZKZ9XEOQGOSLFQCHHOKLDSA9QCMDGCGMRYJZLBVIFOLBIJPROKMHOYTBTJIWUZWJMCTKCJKKTR9LCVYPVJI9AHGI9JOWMIWZAGMLDFJA9WU9QAMEFGABIBEZNNAL9OXSBFLOEHKDGHWFQSHMPLYFCNXAAZYJLMQDEYRGL9QKCEUEJ9LLVUOINVSZZQHCIKPAGMT9CAYIIMTTBCPKWTYHOJIIY9GYNPAJNUJ9BKYYXSV9JSPEXYMCFAIKTGNRSQGUNIYZCRT9FOWENSZQPD9ALUPYYAVICHVYELYFPUYDTWUSWNIYFXPX9MICCCOOZIWRNJIDALWGWRATGLJXNAYTNIZWQ9YTVDBOFZRKO9CFWRPAQQRXTPACOWCPRLYRYSJARRKSQPR9TCFXDVIXLP9XVL99ERRDSOHBFJDJQQGGGCZNDQ9NYCTQJWVZIAELCRBJJFDMCNZU9FIZRPGNURTXOCDSQGXTQHKHUECGWFUUYS9J9NYQ9U9P9UUP9YMZHWWWCIASCFLCMSKTELZWUGCDE9YOKVOVKTAYPHDF9ZCCQAYPJIJNGSHUIHHCOSSOOBUDOKE9CJZGYSSGNCQJVBEFTZFJ9SQUHOASKRRGBSHWKBCBWBTJHOGQ9WOMQFHWJVEG9NYX9KWBTCAIXNXHEBDIOFO9ALYMFGRICLCKKLG9FOBOX9PDWNQRGHBKHGKKRLWTBEQMCWQRLHAVYYZDIIPKVQTHYTWQMTOACXZOQCDTJTBAAUWXSGJF9PNQIJ9AJRUMUVCPWYVYVARKR9RKGOUHHNKNVGGPDDLGKPQNOYHNKAVVKCXWXOQPZNSLATUJT9AUWRMPPSWHSTTYDFAQDXOCYTZHOYYGAIM9CELMZ9AZPWB9MJXGHOKDNNSZVUDAGXTJJSSZCPZVPZBYNNTUQABSXQWZCHDQSLGK9UOHCFKBIBNETK999999999999999999999999999999999999999999999999999999999999999999999999999999999NOXDXXKUDWLOFJLIPQIBRBMGDYCPGDNLQOLQS99EQYKBIU9VHCJVIPFUYCQDNY9APGEVYLCENJIOBLWNB999999999XKBRHUD99C99999999NKZKEKWLDKMJCI9N9XQOLWEPAYWSH9999999999999999999999999KDDTGZLIPBNZKMLTOLOXQVNGLASESDQVPTXALEKRMIOHQLUHD9ELQDBQETS9QFGTYOYWLNTSKKMVJAUXSIROUICDOXKSYZTDPEDKOQENTJOWJONDEWROCEJIEWFWLUAACVSJFTMCHHXJBJRKAAPUDXXVXFWP9X9999IROUICDOXKSYZTDPEDKOQENTJOWJONDEWROCEJIEWFWLUAACVSJFTMCHHXJBJRKAAPUDXXVXFWP9X9999";
- private static final String TEST_MILESTONE = "SMYMAKKPSUKCKDRUEYCGZJTYCZ9HHDMDUWBAPXARGURPQRHTAJDASRWMIDTPTBNDKDEFBUTBGGAFX9999";
- private static final Integer TEST_MILESTONE_INDEX = 8059;
- private static final String TEST_MESSAGE = "JOTA";
- private static final String TEST_TAG = "JOTASPAM9999999999999999999";
-
-
- private IotaAPIProxy proxy;
-
- @Before
- public void createProxyInstance() {
- proxy = new IotaAPIProxy.Builder().build();
- }
-
- @Test
- public void shouldGetNodeInfo() {
- GetNodeInfoResponse nodeInfo = proxy.getNodeInfo();
- assertThat(nodeInfo.getAppVersion(), IsNull.notNullValue());
- assertThat(nodeInfo.getAppName(), IsNull.notNullValue());
- //assertThat(nodeInfo.getJreVersion(), IsNull.notNullValue());
- assertThat(nodeInfo.getJreAvailableProcessors(), IsNull.notNullValue());
- assertThat(nodeInfo.getJreFreeMemory(), IsNull.notNullValue());
- assertThat(nodeInfo.getJreMaxMemory(), IsNull.notNullValue());
- assertThat(nodeInfo.getJreTotalMemory(), IsNull.notNullValue());
- assertThat(nodeInfo.getLatestMilestone(), IsNull.notNullValue());
- assertThat(nodeInfo.getLatestMilestoneIndex(), IsNull.notNullValue());
- assertThat(nodeInfo.getLatestSolidSubtangleMilestone(), IsNull.notNullValue());
- assertThat(nodeInfo.getLatestSolidSubtangleMilestoneIndex(), IsNull.notNullValue());
- assertThat(nodeInfo.getNeighbors(), IsNull.notNullValue());
- assertThat(nodeInfo.getPacketsQueueSize(), IsNull.notNullValue());
- assertThat(nodeInfo.getTime(), IsNull.notNullValue());
- assertThat(nodeInfo.getTips(), IsNull.notNullValue());
- assertThat(nodeInfo.getTransactionsToRequest(), IsNull.notNullValue());
- }
-
- @Test
- public void shouldGetNeighbors() {
- GetNeighborsResponse neighbors = proxy.getNeighbors();
- assertThat(neighbors.getNeighbors(), IsNull.notNullValue());
- }
-
- @Test
- public void shouldAddNeighbors() {
- AddNeighborsResponse res = proxy.addNeighbors("udp://8.8.8.8:14265");
- assertThat(res, IsNull.notNullValue());
- }
-
- @Test
- public void shouldRemoveNeighbors() {
- RemoveNeighborsResponse res = proxy.removeNeighbors("udp://8.8.8.8:14265");
- assertThat(res, IsNull.notNullValue());
- }
-
- @Test
- public void shouldGetTips() {
- GetTipsResponse tips = proxy.getTips();
- assertThat(tips, IsNull.notNullValue());
- }
-
- @Test
- public void shouldFindTransactionsByAddresses() {
- FindTransactionResponse trans = proxy.findTransactionsByAddresses(TEST_ADDRESS_WITH_CHECKSUM);
- System.err.println(gson.toJson(trans));
- assertThat(trans.getHashes(), IsNull.notNullValue());
- }
-
- @Test
- public void shouldFindTransactionsByApprovees() {
- FindTransactionResponse trans = proxy.findTransactionsByApprovees(new String[]{TEST_HASH});
- assertThat(trans.getHashes(), IsNull.notNullValue());
- }
-
- @Test
- public void shouldFindTransactionsByBundles() {
- FindTransactionResponse trans = proxy.findTransactionsByBundles(TEST_HASH);
- assertThat(trans.getHashes(), IsNull.notNullValue());
- }
-
- @Test
- public void shouldFindTransactionsByDigests() {
- FindTransactionResponse trans = proxy.findTransactionsByDigests(TEST_HASH);
- assertThat(trans.getHashes(), IsNull.notNullValue());
- }
-
-
- // ###
-
- @Test
- public void shouldGetTrytes() {
- GetTrytesResponse res = proxy.getTrytes(TEST_HASH);
- assertThat(res.getTrytes(), IsNull.notNullValue());
-
- }
-
- @Test
- public void shouldGetInclusionStates() {
- GetInclusionStateResponse res = proxy.getInclusionStates(new String[]{TEST_ADDRESS_WITH_CHECKSUM}, new String[]{"DNSBRJWNOVUCQPILOQIFDKBFJMVOTGHLIMLLRXOHFTJZGRHJUEDAOWXQRYGDI9KHYFGYDWQJZKX999999"});
- assertThat(res.getStates(), IsNull.notNullValue());
- }
-
- @Test // very long execution
- public void shouldGetTransactionsToApprove() {
- GetTransactionsToApproveResponse res = proxy.getTransactionsToApprove(27);
- assertThat(res.getTrunkTransaction(), IsNull.notNullValue());
- assertThat(res.getBranchTransaction(), IsNull.notNullValue());
-
- }
-
- @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());
-
- }
-
- @Test
- public void shouldCreateIotaApiProxyInstanceWithDefaultValues() {
- IotaAPIProxy proxy = new IotaAPIProxy.Builder().build();
- assertThat(proxy, IsNull.notNullValue());
- }
-
- @Test
- public void shouldCreateANewAddress() {
- final GetNewAddressResponse res = proxy.getNewAddress(TEST_SEED, 0, false, 1, false);
- assertThat(res.getAddresses(), Is.is(Collections.singletonList(TEST_ADDRESS_WITHOUT_CHECKSUM)));
- }
-
- @Test
- public void shouldPrepareTransfer() {
- List transfers = new ArrayList<>();
- transfers.add(new jota.model.Transfer(TEST_ADDRESS_WITH_CHECKSUM, 0, TEST_MESSAGE, TEST_TAG));
- proxy.prepareTransfers(TEST_SEED, transfers, null, null);
- }
-
- @Test
- public void shouldSendTrytes() {
- proxy.sendTrytes(TEST_TRYTES, 18);
- }
-
- @Test
- public void shouldGetLastInclusionState() {
- GetInclusionStateResponse res = proxy.getLatestInclusion(new String[]{TEST_HASH});
- assertThat(res.getStates(), IsNull.notNullValue());
- }
-
- @Test
- public void shouldFindTransactionObjects() {
- assertThat(proxy.findTransactionObjects(new String[]{TEST_ADDRESS_WITH_CHECKSUM}), IsNull.notNullValue());
- }
-}
\ No newline at end of file
diff --git a/src/test/java/jota/IotaAPITest.java b/src/test/java/jota/IotaAPITest.java
new file mode 100644
index 0000000..7fc438c
--- /dev/null
+++ b/src/test/java/jota/IotaAPITest.java
@@ -0,0 +1,160 @@
+package jota;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import jota.dto.response.*;
+import jota.error.*;
+import jota.model.Bundle;
+import jota.model.Transaction;
+import jota.model.Transfer;
+import org.hamcrest.core.Is;
+import org.hamcrest.core.IsNull;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static org.junit.Assert.assertThat;
+
+/**
+ * Let's do some integration test coverage against a default local real node.
+ *
+ * @author davassi
+ */
+public class IotaAPITest {
+
+ 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_HASH = "CKZ9TYPLUWH9FUSYJMPIZBVHWFZXTZMVOJLC9KOICSTBBQWXYTOTMCVPSPMYNDONTXHRULRFAWD999999";
+ private static final String TEST_TRYTES = "BYSWEAUTWXHXZ9YBZISEK9LUHWGMHXCGEVNZHRLUWQFCUSDXZHOFHWHL9MQPVJXXZLIXPXPXF9KYEREFSKCPKYIIKPZVLHUTDFQKKVVBBN9ATTLPCNPJDWDEVIYYLGPZGCWXOBDXMLJC9VO9QXTTBLAXTTBFUAROYEGQIVB9MJWJKXJMCUPTWAUGFZBTZCSJVRBGMYXTVBDDS9MYUJCPZ9YDWWQNIPUAIJXXSNLKUBSCOIJPCLEFPOXFJREXQCUVUMKSDOVQGGHRNILCO9GNCLWFM9APMNMWYASHXQAYBEXF9QRIHIBHYEJOYHRQJAOKAQ9AJJFQ9WEIWIJOTZATIBOXQLBMIJU9PCGBLVDDVFP9CFFSXTDUXMEGOOFXWRTLFGV9XXMYWEMGQEEEDBTIJ9OJOXFAPFQXCDAXOUDMLVYRMRLUDBETOLRJQAEDDLNVIRQJUBZBO9CCFDHIX9MSQCWYAXJVWHCUPTRSXJDESISQPRKZAFKFRULCGVRSBLVFOPEYLEE99JD9SEBALQINPDAZHFAB9RNBH9AZWIJOTLBZVIEJIAYGMC9AZGNFWGRSWAXTYSXVROVNKCOQQIWGPNQZKHUNODGYADPYLZZZUQRTJRTODOUKAOITNOMWNGHJBBA99QUMBHRENGBHTH9KHUAOXBVIVDVYYZMSEYSJWIOGGXZVRGN999EEGQMCOYVJQRIRROMPCQBLDYIGQO9AMORPYFSSUGACOJXGAQSPDY9YWRRPESNXXBDQ9OZOXVIOMLGTSWAMKMTDRSPGJKGBXQIVNRJRFRYEZ9VJDLHIKPSKMYC9YEGHFDS9SGVDHRIXBEMLFIINOHVPXIFAZCJKBHVMQZEVWCOSNWQRDYWVAIBLSCBGESJUIBWZECPUCAYAWMTQKRMCHONIPKJYYTEGZCJYCT9ABRWTJLRQXKMWY9GWZMHYZNWPXULNZAPVQLPMYQZCYNEPOCGOHBJUZLZDPIXVHLDMQYJUUBEDXXPXFLNRGIPWBRNQQZJSGSJTTYHIGGFAWJVXWL9THTPWOOHTNQWCNYOYZXALHAZXVMIZE9WMQUDCHDJMIBWKTYH9AC9AFOT9DPCADCV9ZWUTE9QNOMSZPTZDJLJZCJGHXUNBJFUBJWQUEZDMHXGBPTNSPZBR9TGSKVOHMOQSWPGFLSWNESFKSAZY9HHERAXALZCABFYPOVLAHMIHVDBGKUMDXC9WHHTIRYHZVWNXSVQUWCR9M9RAGMFEZZKZ9XEOQGOSLFQCHHOKLDSA9QCMDGCGMRYJZLBVIFOLBIJPROKMHOYTBTJIWUZWJMCTKCJKKTR9LCVYPVJI9AHGI9JOWMIWZAGMLDFJA9WU9QAMEFGABIBEZNNAL9OXSBFLOEHKDGHWFQSHMPLYFCNXAAZYJLMQDEYRGL9QKCEUEJ9LLVUOINVSZZQHCIKPAGMT9CAYIIMTTBCPKWTYHOJIIY9GYNPAJNUJ9BKYYXSV9JSPEXYMCFAIKTGNRSQGUNIYZCRT9FOWENSZQPD9ALUPYYAVICHVYELYFPUYDTWUSWNIYFXPX9MICCCOOZIWRNJIDALWGWRATGLJXNAYTNIZWQ9YTVDBOFZRKO9CFWRPAQQRXTPACOWCPRLYRYSJARRKSQPR9TCFXDVIXLP9XVL99ERRDSOHBFJDJQQGGGCZNDQ9NYCTQJWVZIAELCRBJJFDMCNZU9FIZRPGNURTXOCDSQGXTQHKHUECGWFUUYS9J9NYQ9U9P9UUP9YMZHWWWCIASCFLCMSKTELZWUGCDE9YOKVOVKTAYPHDF9ZCCQAYPJIJNGSHUIHHCOSSOOBUDOKE9CJZGYSSGNCQJVBEFTZFJ9SQUHOASKRRGBSHWKBCBWBTJHOGQ9WOMQFHWJVEG9NYX9KWBTCAIXNXHEBDIOFO9ALYMFGRICLCKKLG9FOBOX9PDWNQRGHBKHGKKRLWTBEQMCWQRLHAVYYZDIIPKVQTHYTWQMTOACXZOQCDTJTBAAUWXSGJF9PNQIJ9AJRUMUVCPWYVYVARKR9RKGOUHHNKNVGGPDDLGKPQNOYHNKAVVKCXWXOQPZNSLATUJT9AUWRMPPSWHSTTYDFAQDXOCYTZHOYYGAIM9CELMZ9AZPWB9MJXGHOKDNNSZVUDAGXTJJSSZCPZVPZBYNNTUQABSXQWZCHDQSLGK9UOHCFKBIBNETK999999999999999999999999999999999999999999999999999999999999999999999999999999999NOXDXXKUDWLOFJLIPQIBRBMGDYCPGDNLQOLQS99EQYKBIU9VHCJVIPFUYCQDNY9APGEVYLCENJIOBLWNB999999999XKBRHUD99C99999999NKZKEKWLDKMJCI9N9XQOLWEPAYWSH9999999999999999999999999KDDTGZLIPBNZKMLTOLOXQVNGLASESDQVPTXALEKRMIOHQLUHD9ELQDBQETS9QFGTYOYWLNTSKKMVJAUXSIROUICDOXKSYZTDPEDKOQENTJOWJONDEWROCEJIEWFWLUAACVSJFTMCHHXJBJRKAAPUDXXVXFWP9X9999IROUICDOXKSYZTDPEDKOQENTJOWJONDEWROCEJIEWFWLUAACVSJFTMCHHXJBJRKAAPUDXXVXFWP9X9999";
+ private static final String TEST_MILESTONE = "SMYMAKKPSUKCKDRUEYCGZJTYCZ9HHDMDUWBAPXARGURPQRHTAJDASRWMIDTPTBNDKDEFBUTBGGAFX9999";
+ private static final Integer TEST_MILESTONE_INDEX = 8059;
+ private static final String TEST_MESSAGE = "JOTA";
+ private static final String TEST_TAG = "JOTASPAM9999999999999999999";
+ private static final String[] TEST_ADDRESSES = new String[]{"KHJXD9XKXPIVQRGREUIPVJTMEY9L9MXZAAKBBRYNINTIOXWBRMNLLW9MLGAXMGQWDBZLCOGFCBNKTDLDC"
+ , "MQSAAEDPMKIAJPPGNLIHPQIVFGLHNEGG9JNMSHOQSVQHBQBMLNHY9WVRTCOYUOWOIJHBQXIQVFPDF9YRW"
+ , "RGYOHMECRNVPYYPIAKEWHSOLBYOQPRFRPOJGHUMEGLICCUIPTZEXLWDLLPBNRXONUTQGLSAJSLHRXFVQD"
+ , "FOJHXRVJRFMJTFDUWJYYZXCZIJXKQALLXMLKHZFDMHWTIBBXUKSNSUYJLKYRQBNXKRSUXZHDTPWXYD9YF"
+ , "B9YNPQO9EXID9RDEEGLCBJBYKBLWHTOQOZKTLJDFPJZOPKJJTNUYUVVTDJPBCBYIWGPSCMNRZFGFHFSXH"
+ , "NQEFOAFIYKZOUXDFQ9X9PHCNSDETRTJZINZ9EYGKU99QJLDSTSC9VTBAA9FHLNLNYQXWLTNPRJDWCGIPP"
+ , "CEGLBSXDJVXGKGOUHRGMAQDRVYXCQLXBKUDWKFFSIABCUYRATFPTEEDIFYGAASKFZYREHLBIXBTKP9KLC"
+ , "QLOXU9GIQXPPE9UUT9DSIDSIESRIXMTGZJMKLSJTNBCRELAVLWVJLUOLKGFCWAEPEQWZWPBV9YZJJEHUS"
+ , "XIRMYJSGQXMM9YPHJVVLAVGBBLEEMOOKHHBFWKEAXJFONZLNSLBCGPQEVDMMOGHFVRDSYTETIFOIVNCR9"
+ , "PDVVBYBXMHZKADPAYOKQNDPHRSWTHAWQ9GRVIBOIMZQTYCWEPCDWDVRSOUNASVBDLBOAMVLYEVVCMAM9N"
+ , "U9GAIAPUUQWJGISAZWPLHUELTZ9WSHWXS9JLPKOWHRRIVUKGWCTJMBULVMKTETTUNHZ9HWHBALUCJIROU"
+ , "VFPMKZLLMDUOEKNBEKQZPTNZJZF9UHRWSTHXLWQQ9OAXTZQHTZPAWNJNXKAZFSDFWKFQEKZIGJTLWQFLO"
+ , "IGHK9XIWOAYBZUEZHQLEXBPTXSWVANIOUZZCPNKUIJIJOJNAQCJWUJHYKCZOIKVAAHDGAWJZKLTPVQL9G"
+ , "LXQPWMNXSUZTEYNC9ZBBFHY9YWCCOVKBNIIOUSVXZJZMJKJFDUWGUVXYCHGKUHEEIDHSGEWFAHVJPRIJT"
+ , "AKFDX9PGGQLZUWRMZ9YBDF9CG9TWXCNALCSXSAWHFIMGXCSYCJLSWIQDGGVDRMNEKKECQEYAITGNLNJFQ"
+ , "YX9QSPYMSFVOW9UVZRDVOCPYYMUTDHCCPKHMXQSJQJYIXVCHILKW9GBYJTYGLIKBTRQMDCYBMLLNGSSIK"
+ , "DSYCJKNG9TAGJHSKZQ9XLKAKNSKJFZIPVEDGJFXRTFGENHZFQGXHWDBNXLLDABDMOYELPG9DIXSNJFWAR"
+ , "9ANNACZYLDDPZILLQBQG9YMG9XJUMTAENDFQ9HMSSEFWYOAXPJTUXBFTSAXDJPAO9FKTWBBSCSFMOUR9I"
+ , "WDTFFXHBHMFQQVXQLBFJFVVHVIIAVYM9PFAZCHMKET9ESMHIRHSMVDJBZTXPTAFVIASMSXRDCIYVWVQNO"
+ , "XCCPS9GMTSUB9DXPVKLTBDHOFX9PJMBYZQYQEXMRQDPGQPLWRGZGXODYJKGVFOHHYUJRCSXAIDGYSAWRB"
+ , "KVEBCGMEOPDPRCQBPIEMZTTXYBURGZVNH9PLHKPMM9D9FUKWIGLKZROGNSYIFHULLWQWXCNAW9HKKVIDC"};
+ private static Gson gson = new GsonBuilder().create();
+ private IotaAPI iotaClient;
+
+ @Before
+ public void createApiClientInstance() {
+ iotaClient = new IotaAPI.Builder().build();
+ }
+
+ @Test
+ public void shouldCreateIotaApiProxyInstanceWithDefaultValues() {
+ IotaAPI proxy = new IotaAPI.Builder().build();
+ assertThat(proxy, IsNull.notNullValue());
+ }
+
+
+ @Test
+ public void shouldGetInputs() {
+ GetBalancesAndFormatResponse res = iotaClient.getInputs(TEST_SEED1, 0, 0, 0);
+ System.out.println(res);
+ assertThat(res, IsNull.notNullValue());
+ assertThat(res.getTotalBalance(), IsNull.notNullValue());
+ assertThat(res.getInput(), IsNull.notNullValue());
+
+ }
+
+
+ @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));
+ }
+
+ @Test
+ public void shouldPrepareTransfer() {
+ 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();
+ }
+ Assert.assertNotNull(trytes);
+ assertThat(trytes.isEmpty(), Is.is(false));
+ }
+
+ @Test
+ public void shouldGetLastInclusionState() throws NoNodeInfoException {
+ GetInclusionStateResponse res = iotaClient.getLatestInclusion(new String[]{TEST_HASH});
+ assertThat(res.getStates(), IsNull.notNullValue());
+ }
+
+ @Test
+ public void shouldFindTransactionObjects() {
+ List ftr = iotaClient.findTransactionObjects(TEST_ADDRESSES);
+ assertThat(ftr, IsNull.notNullValue());
+ }
+
+ @Test
+ 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);
+ assertThat(gtr.getTransfers(), IsNull.notNullValue());
+
+ for (Bundle test : gtr.getTransfers()) {
+ for (Transaction trx : test.getTransactions()) {
+ System.out.println(new Gson().toJson(trx));
+ }
+ }
+ }
+
+ @Ignore
+ @Test
+ public void shouldSendTrytes() {
+ iotaClient.sendTrytes(new String[]{TEST_TRYTES}, 9, 18);
+ }
+
+ @Test(expected = IllegalStateException.class)
+ public void shouldNotSendTransfer() throws ArgumentException, InvalidSignatureException, InvalidBundleException, NotEnoughBalanceException {
+ 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);
+ assertThat(str.getSuccessfully(), IsNull.notNullValue());
+ }
+
+ @Ignore
+ @Test
+ public void shouldSendTransfer() throws ArgumentException, InvalidSignatureException, InvalidBundleException, NotEnoughBalanceException {
+ 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);
+ 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
new file mode 100644
index 0000000..8913816
--- /dev/null
+++ b/src/test/java/jota/IotaCoreApiTest.java
@@ -0,0 +1,138 @@
+package jota;
+
+import com.google.gson.Gson;
+import jota.dto.response.*;
+import org.hamcrest.core.IsNull;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.assertThat;
+
+/**
+ * Created by Adrian on 15.01.2017.
+ */
+public class IotaCoreApiTest {
+
+ private static final String TEST_BUNDLE = "XZKJUUMQOYUQFKMWQZNTFMSS9FKJLOEV9DXXXWPMQRTNCOUSUQNTBIJTVORLOQPLYZOTMLFRHYKMTGZZU";
+ private static final String TEST_ADDRESS_WITH_CHECKSUM = "PNGMCSNRCTRHCHPXYTPKEJYPCOWKOMRXZFHH9N9VDIKMNVAZCMIYRHVJIAZARZTUETJVFDMBEBIQE9QTHBFWDAOEFA";
+ private static final String TEST_HASH = "OAATQS9VQLSXCLDJVJJVYUGONXAXOFMJOZNSYWRZSWECMXAQQURHQBJNLD9IOFEPGZEPEMPXCIVRX9999";
+ private static IotaAPICore proxy;
+
+ @Before
+ public void createProxyInstance() {
+ proxy = new IotaAPICore.Builder().build();
+ }
+
+ @Test
+ public void shouldGetNodeInfo() {
+ GetNodeInfoResponse nodeInfo = proxy.getNodeInfo();
+ System.out.println(new Gson().toJson(nodeInfo));
+ assertThat(nodeInfo.getAppVersion(), IsNull.notNullValue());
+ assertThat(nodeInfo.getAppName(), IsNull.notNullValue());
+ assertThat(nodeInfo.getJreVersion(), IsNull.notNullValue());
+ assertThat(nodeInfo.getJreAvailableProcessors(), IsNull.notNullValue());
+ assertThat(nodeInfo.getJreFreeMemory(), IsNull.notNullValue());
+ assertThat(nodeInfo.getJreMaxMemory(), IsNull.notNullValue());
+ assertThat(nodeInfo.getJreTotalMemory(), IsNull.notNullValue());
+ assertThat(nodeInfo.getLatestMilestone(), IsNull.notNullValue());
+ assertThat(nodeInfo.getLatestMilestoneIndex(), IsNull.notNullValue());
+ assertThat(nodeInfo.getLatestSolidSubtangleMilestone(), IsNull.notNullValue());
+ assertThat(nodeInfo.getLatestSolidSubtangleMilestoneIndex(), IsNull.notNullValue());
+ assertThat(nodeInfo.getNeighbors(), IsNull.notNullValue());
+ assertThat(nodeInfo.getPacketsQueueSize(), IsNull.notNullValue());
+ assertThat(nodeInfo.getTime(), IsNull.notNullValue());
+ assertThat(nodeInfo.getTips(), IsNull.notNullValue());
+ assertThat(nodeInfo.getTransactionsToRequest(), IsNull.notNullValue());
+ }
+
+ @Test
+ public void shouldGetNeighbors() {
+ GetNeighborsResponse neighbors = proxy.getNeighbors();
+ assertThat(neighbors.getNeighbors(), IsNull.notNullValue());
+ }
+
+ @Test
+ public void shouldAddNeighbors() {
+ AddNeighborsResponse res = proxy.addNeighbors("udp://8.8.8.8:14265");
+ assertThat(res, IsNull.notNullValue());
+ }
+
+ @Test
+ public void shouldRemoveNeighbors() {
+ RemoveNeighborsResponse res = proxy.removeNeighbors("udp://8.8.8.8:14265");
+ assertThat(res, IsNull.notNullValue());
+ }
+
+ @Test
+ public void shouldGetTips() {
+ GetTipsResponse tips = proxy.getTips();
+ assertThat(tips, IsNull.notNullValue());
+ }
+
+ @Test
+ public void shouldFindTransactionsByAddresses() {
+ FindTransactionResponse trans = proxy.findTransactionsByAddresses(TEST_ADDRESS_WITH_CHECKSUM);
+ assertThat(trans.getHashes(), IsNull.notNullValue());
+ }
+
+ @Test
+ public void shouldFindTransactionsByApprovees() {
+ FindTransactionResponse trans = proxy.findTransactionsByApprovees(new String[]{TEST_HASH});
+ assertThat(trans.getHashes(), IsNull.notNullValue());
+ }
+
+ @Test
+ public void shouldFindTransactionsByBundles() {
+ FindTransactionResponse trans = proxy.findTransactionsByBundles(TEST_HASH);
+ assertThat(trans.getHashes(), IsNull.notNullValue());
+ }
+
+ @Test
+ public void shouldFindTransactionsByDigests() {
+ FindTransactionResponse trans = proxy.findTransactionsByDigests(TEST_HASH);
+ assertThat(trans.getHashes(), IsNull.notNullValue());
+ }
+
+ @Test
+ public void shouldGetTrytes() {
+ GetTrytesResponse res = proxy.getTrytes(TEST_HASH);
+ assertThat(res.getTrytes(), IsNull.notNullValue());
+
+ }
+
+ @Test
+ public void shouldGetInclusionStates() {
+ 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"});
+ assertThat(res.getStates(), IsNull.notNullValue());
+ }
+
+ @Test // very long execution
+ public void shouldGetTransactionsToApprove() {
+ GetTransactionsToApproveResponse res = proxy.getTransactionsToApprove(27);
+ assertThat(res.getTrunkTransaction(), IsNull.notNullValue());
+ assertThat(res.getBranchTransaction(), IsNull.notNullValue());
+ }
+
+ @Test
+ public void shouldFindTransactions() {
+ String test = TEST_BUNDLE;
+ FindTransactionResponse resp = proxy.findTransactions(new String[]{test}, new String[]{test}, new String[]{test}, new String[]{test});
+ System.out.println(new Gson().toJson(resp));
+ }
+
+ @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());
+
+ }
+}
diff --git a/src/test/java/jota/IotaUnitConverterTest.java b/src/test/java/jota/IotaUnitConverterTest.java
index 81da852..624555a 100644
--- a/src/test/java/jota/IotaUnitConverterTest.java
+++ b/src/test/java/jota/IotaUnitConverterTest.java
@@ -48,11 +48,11 @@ public class IotaUnitConverterTest {
@Test
public void shouldConvertRawIotaAmountToDisplayText() {
- assertEquals(IotaUnitConverter.convertRawIotaAmountToDisplayText(1), "1 i");
- assertEquals(IotaUnitConverter.convertRawIotaAmountToDisplayText(1000), "1 Ki");
- assertEquals(IotaUnitConverter.convertRawIotaAmountToDisplayText(1000000), "1 Mi" );
- assertEquals(IotaUnitConverter.convertRawIotaAmountToDisplayText(1000000000), "1 Gi" );
- assertEquals(IotaUnitConverter.convertRawIotaAmountToDisplayText(1000000000000L), "1 Ti");
- assertEquals(IotaUnitConverter.convertRawIotaAmountToDisplayText(1000000000000000L), "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/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 28b54a6..f6403e5 100644
--- a/src/test/java/jota/TrytesConverterTest.java
+++ b/src/test/java/jota/TrytesConverterTest.java
@@ -1,12 +1,12 @@
package jota;
import jota.utils.TrytesConverter;
+import org.apache.commons.lang3.RandomStringUtils;
import org.junit.Test;
+
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
-import org.apache.commons.lang3.RandomStringUtils;
-
/**
* Created by pinpong on 01.12.16.
*/
@@ -15,19 +15,21 @@ public class TrytesConverterTest {
@Test
public void shouldConvertStringToTrytes() {
assertEquals(TrytesConverter.toTrytes("Z"), "IC");
+ assertEquals(TrytesConverter.toTrytes("JOTA JOTA"), "TBYBCCKBEATBYBCCKB");
}
+
@Test
public void shouldConvertTrytesToString() {
assertEquals(TrytesConverter.toString("IC"), "Z");
+ assertEquals(TrytesConverter.toString("TBYBCCKBEATBYBCCKB"), "JOTA JOTA");
}
-
+
@Test
public void shouldConvertBackAndForth() {
String str = RandomStringUtils.randomAlphabetic(1000).toUpperCase();
System.err.println(str);
String back = TrytesConverter.toString(TrytesConverter.toTrytes(str));
-
+
assertTrue(str.equals(back));
}
-
-}
+}
\ No newline at end of file