diff --git a/src/main/java/jota/IotaAPIProxy.java b/src/main/java/jota/IotaAPIProxy.java
index 5c0c47d..f02a19c 100644
--- a/src/main/java/jota/IotaAPIProxy.java
+++ b/src/main/java/jota/IotaAPIProxy.java
@@ -2,13 +2,15 @@ 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.error.ArgumentException;
+import jota.error.InvalidBundleException;
+import jota.error.InvalidSignatureException;
+import jota.model.*;
+import jota.pow.Curl;
import jota.utils.Converter;
import jota.utils.InputValidator;
import jota.utils.IotaAPIUtils;
+import jota.utils.Signing;
import okhttp3.OkHttpClient;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
@@ -26,13 +28,13 @@ import java.util.concurrent.TimeUnit;
/**
* IotaAPIProxy Builder. Usage:
- *
+ *
* IotaApiProxy api = IotaApiProxy.Builder
* .protocol("http")
* .nodeAddress("localhost")
* .port(12345)
* .build();
- *
+ *
* GetNodeInfoResponse response = api.getNodeInfo();
*
* @author davassi
@@ -79,8 +81,8 @@ public class IotaAPIProxy {
final String nodeUrl = protocol + "://" + host + ":" + port;
final OkHttpClient client = new OkHttpClient.Builder()
- .readTimeout(120, TimeUnit.SECONDS)
- .connectTimeout(120, TimeUnit.SECONDS)
+ .readTimeout(5000, TimeUnit.SECONDS)
+ .connectTimeout(5000, TimeUnit.SECONDS)
.build();
final Retrofit retrofit = new Retrofit.Builder()
@@ -174,9 +176,9 @@ public class IotaAPIProxy {
final Call res = service.getBalances(IotaGetBalancesRequest.createIotaGetBalancesRequest(threshold, addresses));
return wrapCheckedException(res).body();
}
-
+
public GetBalancesResponse getBalances(Integer threshold, List addresses) {
- return getBalances(threshold, addresses.toArray(new String[] {}));
+ return getBalances(threshold, addresses.toArray(new String[]{}));
}
public InterruptAttachingToTangleResponse interruptAttachingToTangle() {
@@ -215,7 +217,7 @@ public class IotaAPIProxy {
public GetNewAddressResponse getNewAddress(final String seed, final int index, final boolean checksum, final int total, final boolean returnAll) {
final List allAddresses = new ArrayList<>();
-
+
// If total number of addresses to generate is supplied, simply generate
// and return the list of all addresses
if (total != 0) {
@@ -227,10 +229,10 @@ public class IotaAPIProxy {
// No total provided: Continue calling findTransactions to see if address was
// already created if null, return list of addresses
for (int i = index; ; i++) {
-
- final String newAddress = IotaAPIUtils.newAddress(seed, i, checksum);
+
+ final String newAddress = IotaAPIUtils.newAddress(seed, i, checksum);
final FindTransactionResponse response = findTransactionsByAddresses(new String[]{newAddress});
-
+
allAddresses.add(newAddress);
if (response.getHashes().length == 0) {
break;
@@ -239,9 +241,9 @@ public class IotaAPIProxy {
// If !returnAll return only the last address that was generated
if (!returnAll) {
- allAddresses.subList(0, allAddresses.size()-1).clear();
+ allAddresses.subList(0, allAddresses.size() - 1).clear();
}
- return GetNewAddressResponse.create(allAddresses);
+ return GetNewAddressResponse.create(allAddresses);
}
/*
@@ -263,14 +265,101 @@ public class IotaAPIProxy {
broadcastBundle
getAccountData
*/
-
+
+ /**
+ * @method getTransfers
+ * @param {string} seed
+ * @param {object} options
+ * @property {int} start Starting key index
+ * @property {int} end Ending key index
+ * @property {bool} inclusionStates returns confirmation status of all transactions
+ * @param {function} callback
+ * @returns {object} success
+ **/
+ public Bundle[] getTransfers(String seed, Integer start, Integer end, Boolean inclusionStates) throws ArgumentException, InvalidBundleException, InvalidSignatureException {
+ start = start != null ? 0 : start;
+ end = end == null ? null : end;
+ inclusionStates = inclusionStates != null ? inclusionStates : null;
+
+ if (start > end || end > (start + 500)) {
+ throw new ArgumentException();
+ }
+
+ GetNewAddressResponse gnr = getNewAddress(seed, start, false, end == null ? end - start : end, true);
+ if (gnr != null && gnr.getAddresses() != null) {
+ return bundlesFromAddresses(gnr.getAddresses().toArray(new String[gnr.getAddresses().size()]), inclusionStates);
+ }
+ return null;
+ }
+
+ public Bundle[] bundlesFromAddresses(String[] addresses, Boolean inclusionStates) throws ArgumentException, InvalidBundleException, InvalidSignatureException{
+
+ 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 {
+ nonTailBundleHashes.add(trx.getBundle());
+ }
+ }
+ if (nonTailBundleHashes.isEmpty()) return null;
+
+ List bundleObjects = findTransactionObjects(addresses);
+ for (Transaction trx : bundleObjects) {
+ // Sort tail and nonTails
+ if (Long.parseLong(trx.getCurrentIndex()) == 0) {
+ tailTransactions.add(trx.getHash());
+ }
+ }
+
+ List finalBundles = new ArrayList<>();
+ String[] tailTxArray = tailTransactions.toArray(new String[tailTransactions.size()]);
+
+ // If inclusionStates, get the confirmation status
+ // of the tail transactions, and thus the bundles
+ if (inclusionStates) {
+ GetInclusionStateResponse gisr = getLatestInclusion(tailTxArray);
+ if (gisr == null || gisr.getStates() == null || gisr.getStates().length == 0) return null;
+ for (String trx : tailTxArray) {
+ Bundle gbr = getBundle(trx);
+ if (gbr != null && gbr.getTransactions() != null) {
+ if (inclusionStates) {
+ boolean thisInclusion = gisr.getStates()[Arrays.asList(tailTxArray).indexOf(trx)];
+ for (Transaction t : gbr.getTransactions()) {
+ t.setPersistence(thisInclusion);
+ }
+ }
+ finalBundles.add(gbr);
+ }
+ }
+ }
+ Collections.sort(finalBundles, new Comparator() {
+ public int compare(Bundle c1, Bundle c2) {
+ if (Long.parseLong(c1.getTransactions().get(0).getTimestamp()) > Long.parseLong(c2.getTransactions().get(0).getTimestamp()))
+ return -1;
+ if (Long.parseLong(c1.getTransactions().get(0).getTimestamp()) < Long.parseLong(c2.getTransactions().get(0).getTimestamp()))
+ return 1;
+ return 0;
+ }
+ });
+ 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) {
-
+ public StoreTransactionsResponse broadcastAndStore(final String... trytes) {
+
try {
broadcastTransactions(trytes);
} catch (Exception e) {
@@ -279,30 +368,31 @@ public class IotaAPIProxy {
}
return storeTransactions(trytes);
}
-
+
/**
* Facade method: Gets transactions to approve, attaches to Tangle, broadcasts and stores
+ *
* @param {array} trytes
- * @param {int} depth
- * @param {int} minWeightMagnitude
+ * @param {int} depth
+ * @param {int} minWeightMagnitude
* @return
*/
public List sendTrytes(final String[] trytes, final int minWeightMagnitude) {
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));
}
@@ -310,15 +400,15 @@ public class IotaAPIProxy {
}
/**
- * Wrapper function for getTrytes and transactionObjects
- * gets the trytes and transaction object from a list of transaction hashes
- *
- * @method getTransactionsObjects
- * @param {array} hashes
- * @return
- * @returns {function} callback
- * @returns {object} success
- **/
+ * Wrapper function for getTrytes and transactionObjects
+ * gets the trytes and transaction object from a list of transaction hashes
+ *
+ * @param {array} hashes
+ * @return
+ * @method getTransactionsObjects
+ * @returns {function} callback
+ * @returns {object} success
+ **/
public List getTransactionsObjects(String[] hashes) {
if (!InputValidator.isArrayOfHashes(hashes)) {
@@ -326,9 +416,9 @@ public class IotaAPIProxy {
}
final GetTrytesResponse trytesResponse = getTrytes(hashes);
-
+
final List trxs = new ArrayList<>();
-
+
for (final String tryte : trytesResponse.getTrytes()) {
trxs.add(Converter.transactionObject(tryte));
}
@@ -356,18 +446,18 @@ public class IotaAPIProxy {
}
/**
- * Prepares transfer by generating bundle, finding and signing inputs
- *
- * @method prepareTransfers
- * @param {string} seed
- * @param {object} transfers
- * @param {object} options
- * @property {array} inputs Inputs used for signing. Needs to have correct keyIndex and address value
- * @property {string} address Remainder address
- * @param {function} callback
- * @return
- * @returns {array} trytes Returns bundle trytes
- **/
+ * Prepares transfer by generating bundle, finding and signing inputs
+ *
+ * @param {string} seed
+ * @param {object} transfers
+ * @param {object} options
+ * @param {function} callback
+ * @return
+ * @method prepareTransfers
+ * @property {array} inputs Inputs used for signing. Needs to have correct keyIndex and address value
+ * @property {string} address Remainder address
+ * @returns {array} trytes Returns bundle trytes
+ **/
public List prepareTransfers(final String seed, final List transfers, String remainder, List inputs) {
// Input validation of transfers object
@@ -378,7 +468,7 @@ public class IotaAPIProxy {
// Create a new bundle
final Bundle bundle = new Bundle();
final List signatureFragments = new ArrayList<>();
-
+
int totalValue = 0;
String tag;
@@ -398,7 +488,7 @@ public class IotaAPIProxy {
// While there is still a message, copy it
while (!msgCopy.isEmpty()) {
-
+
String fragment = StringUtils.substring(msgCopy, 0, 2187);
msgCopy = StringUtils.substring(msgCopy, 2187, msgCopy.length());
@@ -454,7 +544,8 @@ public class IotaAPIProxy {
String[] balances = resbalances.getBalances();
List confirmedInputs = new ArrayList<>();
- int totalBalance = 0; int i = 0;
+ int totalBalance = 0;
+ int i = 0;
for (String balance : balances) {
long thisBalance = Integer.parseInt(balance);
totalBalance += thisBalance;
@@ -495,23 +586,23 @@ public class IotaAPIProxy {
List bundleTrytes = new ArrayList<>();
for (Transaction tx : trxb) {
- bundleTrytes.add(jota.utils.IotaAPIUtils.transactionTrytes(tx));
+ bundleTrytes.add(Converter.transactionTrytes(tx));
}
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
- **/
+ * Gets the inputs of a seed
+ *
+ * @param {string} seed
+ * @param {object} options
+ * @param {function} callback
+ * @method getInputs
+ * @property {int} start Starting key index
+ * @property {int} end Ending key index
+ * @property {int} threshold Min balance required
+ **/
public GetBalancesAndFormatResponse getInputs(final String seed, final List balances, int start, int end, int threshold) {
// validate the seed
@@ -564,18 +655,19 @@ public class IotaAPIProxy {
// If threshold defined, keep track of whether reached or not
// else set default to true
- boolean thresholdReached = threshold != 0 ? false : true; int i = -1;
-
+ boolean thresholdReached = threshold != 0 ? false : true;
+ int i = -1;
+
List inputs = new ArrayList<>();
long totalBalance = 0;
-
+
for (String address : addresses) {
-
+
long balance = Long.parseLong(balances.get(++i));
-
+
if (balance > 0) {
- final Input newEntry = new Input(address, balance, start+i);
-
+ final Input newEntry = new Input(address, balance, start + i);
+
inputs.add(newEntry);
// Increase totalBalance of all aggregated inputs
totalBalance += balance;
@@ -589,53 +681,121 @@ public class IotaAPIProxy {
if (thresholdReached) {
return GetBalancesAndFormatResponse.create(inputs, totalBalance);
- }
+ }
throw new IllegalStateException("Not enough balance");
}
/**
- * Gets the associated bundle transactions of a single transaction
- * Does validation of signatures, total sum as well as bundle order
+ * Gets the associated bundle transactions of a single transaction
+ * Does validation of signatures, total sum as well as bundle order
*
- * @method getBundle
- * @param {string} transaction Hash of a tail transaction
- * @returns {list} bundle Transaction objects
+ * @param {string} transaction Hash of a tail transaction
+ * @method getBundle
+ * @returns {list} bundle Transaction objects
**/
- public GetBundleResponse getBundle(String transaction) {
- return null; //IotaAPIUtils.getBundle(transaction);
+ public Bundle getBundle(String transaction) throws ArgumentException, InvalidBundleException, InvalidSignatureException {
+
+ Bundle bundle = traverseBundle(transaction, null, null);
+ if (bundle == null) {
+ return null;
+ }
+
+ long totalSum = 0;
+ int lastIndex = 0;
+ String bundleHash = bundle.getTransactions().get(0).getBundle();
+
+ Curl curl = new Curl();
+ 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 = Converter.transactionTrytes(trx).substring(2187, 2187 + 162);
+
+ // 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; i < bundle.getTransactions().size() - 1; i++) {
+ 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) {
+ 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 = curl.squeeze(new int[243]);
+ 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
+ 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 (int i = 0; i < signaturesToValidate.size(); i++) {
+
+ boolean isValidSignature = Signing.validateSignatures(signaturesToValidate.get(i).getAddress(), signaturesToValidate.get(i).getSignatureFragments().toArray(new String[signaturesToValidate.size()]), bundleHash);
+
+ if (!isValidSignature) throw new InvalidSignatureException();
+ }
+
+ return bundle;
}
/**
- * Replays a transfer by doing Proof of Work again
+ * Replays a transfer by doing Proof of Work again
*
- * @method replayBundle
- * @param {string} tail
- * @param {int} depth
- * @param {int} minWeightMagnitude
- * @param {function} callback
- * @returns {object} analyzed Transaction objects
+ * @param {string} tail
+ * @param {int} depth
+ * @param {int} minWeightMagnitude
+ * @param {function} callback
+ * @method replayBundle
+ * @returns {object} analyzed Transaction objects
**/
- public List replayTransfer(String transaction, int depth, int minWeightMagnitude) {
+ public List replayTransfer(String transaction, int depth, int minWeightMagnitude) throws InvalidBundleException, InvalidSignatureException, ArgumentException {
List bundleTrytes = new ArrayList<>();
- GetBundleResponse bundle = getBundle(transaction);
+ Bundle bundle = getBundle(transaction);
for (Transaction element : bundle.getTransactions()) {
- bundleTrytes.add(IotaAPIUtils.transactionTrytes(element));
+ bundleTrytes.add(Converter.transactionTrytes(element));
}
return sendTrytes(bundleTrytes.toArray(new String[bundleTrytes.size()]), minWeightMagnitude);
}
/**
- * Wrapper function for getNodeInfo and getInclusionStates
+ * Wrapper function for getNodeInfo and getInclusionStates
*
- * @method getLatestInclusion
- * @param {array} hashes
- * @returns {function} callback
- * @returns {array} state
+ * @param {array} hashes
+ * @method getLatestInclusion
+ * @returns {function} callback
+ * @returns {array} state
**/
public GetInclusionStateResponse getLatestInclusion(String[] hashes) {
GetNodeInfoResponse getNodeInfoResponse = getNodeInfo();
@@ -648,11 +808,57 @@ public class IotaAPIProxy {
public Transaction[] sendTransfer(String seed, int depth, int minWeightMagnitude, Transfer[] transactions, Input[] inputs, String address) {
- List trytes = prepareTransfers(seed, Arrays.asList(transactions), address, Arrays.asList(inputs));
+ List trytes = prepareTransfers(seed, Arrays.asList(transactions), address, inputs == null ? null : Arrays.asList(inputs));
List trxs = sendTrytes(trytes.toArray(new String[trytes.size()]), minWeightMagnitude);
return trxs.toArray(new Transaction[trxs.size()]);
}
+ /**
+ * 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 & gtr.getTrytes().length != 0) {
+ Transaction trx = Converter.transactionObject(gtr.getTrytes()[0]);
+ 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 != trx.getBundle()) {
+ return bundle;
+ }
+ // If only one bundle element, return
+ if (Integer.parseInt(trx.getLastIndex()) == 0 && Integer.parseInt(trx.getCurrentIndex()) == 0) {
+ return new Bundle(Arrays.asList(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 {
+ return null;
+ }
+ }
+
public static class Builder {
String protocol, host, port;
diff --git a/src/main/java/jota/dto/response/GetBundleResponse.java b/src/main/java/jota/dto/response/GetBundleResponse.java
index 278631f..34ffb89 100644
--- a/src/main/java/jota/dto/response/GetBundleResponse.java
+++ b/src/main/java/jota/dto/response/GetBundleResponse.java
@@ -7,6 +7,14 @@ import java.util.List;
public class GetBundleResponse extends AbstractResponse {
+ public GetBundleResponse(){
+
+ }
+
+ public GetBundleResponse(List trxs){
+ this.transactions = trxs;
+ }
+
private List transactions = new ArrayList<>();
public List getTransactions() {
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/InvalidBundleException.java b/src/main/java/jota/error/InvalidBundleException.java
new file mode 100644
index 0000000..9f7877d
--- /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/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/utils/Converter.java b/src/main/java/jota/utils/Converter.java
index 5e76567..f2a10b9 100644
--- a/src/main/java/jota/utils/Converter.java
+++ b/src/main/java/jota/utils/Converter.java
@@ -206,6 +206,31 @@ public class Converter {
}
}
}
+
+ public static String transactionTrytes(Transaction trx) {
+ int[] valueTrits = Converter.trits(trx.getValue(), 81);
+
+ int[] timestampTrits = Converter.trits(trx.getTimestamp(), 27);
+
+
+ int[] currentIndexTrits = Converter.trits(trx.getTimestamp(), 27);
+
+
+ int[] lastIndexTrits = Converter.trits(trx.getCurrentIndex(), 27);
+
+
+ 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 Transaction transactionObject(final String trytes) {
diff --git a/src/main/java/jota/utils/IotaAPIUtils.java b/src/main/java/jota/utils/IotaAPIUtils.java
index d790e82..3116681 100644
--- a/src/main/java/jota/utils/IotaAPIUtils.java
+++ b/src/main/java/jota/utils/IotaAPIUtils.java
@@ -43,31 +43,6 @@ public class IotaAPIUtils {
return address;
}
- public static String transactionTrytes(Transaction trx) {
- int[] valueTrits = Converter.trits(trx.getValue(), 81);
-
- int[] timestampTrits = Converter.trits(trx.getTimestamp(), 27);
-
-
- int[] currentIndexTrits = Converter.trits(trx.getTimestamp(), 27);
-
-
- int[] lastIndexTrits = Converter.trits(trx.getCurrentIndex(), 27);
-
-
- 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,
final Bundle bundle,
@@ -138,7 +113,7 @@ public class IotaAPIUtils {
// Convert all bundle entries into trytes
for (Transaction tx : bundle.getTransactions()) {
- bundleTrytes.add(IotaAPIUtils.transactionTrytes(tx));
+ bundleTrytes.add(Converter.transactionTrytes(tx));
}
Collections.reverse(bundleTrytes);
return bundleTrytes;