updated and added new Utils (#9)

* added SeedRandomGenerator

* extended IotaUnitConverter

* minor

* added isArrayOfHashes

* renamed constants

* added error package

* added transactionObject

* fixed IotaUnitConverter
This commit is contained in:
Oliver Nitzschke 2016-12-14 11:06:06 +01:00 committed by Gianluigi Davassi
parent 9dc1947234
commit 21ddac09d0
13 changed files with 368 additions and 62 deletions

View File

@ -0,0 +1,10 @@
package jota.error;
/**
* Created by Adrian on 09.12.2016.
*/
public class ArgumentException extends BaseException {
public ArgumentException() {
super("wrong arguments passed to function");
}
}

View File

@ -0,0 +1,51 @@
package jota.error;
import org.apache.commons.lang3.StringUtils;
import java.util.Collection;
/**
* Created by Adrian on 09.12.2016.
*/
public class BaseException extends Exception {
protected Collection<String> messages;
public BaseException(String msg) {
super(msg);
}
public BaseException(String msg, Exception cause) {
super(msg, cause);
}
public BaseException(Collection<String> messages) {
super();
this.messages = messages;
}
public BaseException(Collection<String> messages, Exception cause) {
super(cause);
this.messages = messages;
}
@Override
public String getMessage() {
String msg;
if (this.messages != null && !this.messages.isEmpty()) {
msg = "[";
for (String message : this.messages) {
msg += message + ",";
}
msg = StringUtils.removeEnd(msg, ",") + "]";
} else msg = super.getMessage();
return msg;
}
}

View File

@ -0,0 +1,10 @@
package jota.error;
/**
* Created by Adrian on 09.12.2016.
*/
public class NotEnoughBalanceException extends BaseException {
public NotEnoughBalanceException() {
super("not enough balance dude");
}
}

View File

@ -7,36 +7,38 @@ import org.apache.commons.lang3.builder.ToStringStyle;
* Created by pinpong on 02.12.16.
*/
public class Transaction {
private String signatureMessageChunk;
private String index;
private String approvalNonce;
private String hash;
private String digest;
private String type;
private String timestamp;
private String trunkTransaction;
private String branchTransaction;
private String signatureNonce;
private String signatureFragments;
private String address;
private String value;
private String tag;
private String timestamp;
private String currentIndex;
private String lastIndex;
private String bundle;
private String trunkTransaction;
private String branchTransaction;
private String nonce;
private Boolean persistence;
public Transaction(String signatureMessageChunk, String index, String approvalNonce, String hash, String digest, String type, String timestamp, String trunkTransaction, String branchTransaction, String signatureNonce, String address, String value, String bundle) {
public Transaction() {
}
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) {
this.hash = hash;
this.type = type;
this.signatureMessageChunk = signatureMessageChunk;
this.digest = digest;
this.tag = tag;
this.signatureFragments = signatureFragments;
this.address = address;
this.value = value;
this.timestamp = timestamp;
this.index = index;
this.currentIndex = currentIndex;
this.lastIndex = lastIndex;
this.bundle = bundle;
this.signatureNonce = signatureNonce;
this.approvalNonce = approvalNonce;
this.trunkTransaction = trunkTransaction;
this.branchTransaction = branchTransaction;
this.nonce = nonce;
}
@Override
@ -44,56 +46,107 @@ public class Transaction {
return ToStringBuilder.reflectionToString(this, ToStringStyle.MULTI_LINE_STYLE);
}
public String getValue() {
return value;
public String getHash() {
return hash;
}
public String getDigest() {
return digest;
public void setHash(String hash) {
this.hash = hash;
}
public String getTrunkTransaction() {
return trunkTransaction;
public String getSignatureFragments() {
return signatureFragments;
}
public String getTimestamp() {
return timestamp;
}
public String getSignatureNonce() {
return signatureNonce;
}
public String getType() {
return type;
public String setSignatureFragments(String signatureFragments) {
return this.signatureFragments = signatureFragments;
}
public String getAddress() {
return address;
}
public String getApprovalNonce() {
return approvalNonce;
public void setAddress(String address) {
this.address = address;
}
public String getBranchTransaction() {
return branchTransaction;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getTag() {
return tag;
}
public void setTag(String tag) {
this.tag = tag;
}
public String getTimestamp() {
return timestamp;
}
public void setTimestamp(String timestamp) {
this.timestamp = timestamp;
}
public String getCurrentIndex() {
return currentIndex;
}
public String setCurrentIndex(String currentIndex) {
return this.currentIndex = currentIndex;
}
public String getLastIndex() {
return lastIndex;
}
public String setLastIndex(String lastIndex) {
return this.lastIndex = lastIndex;
}
public String getBundle() {
return bundle;
}
public String getHash() {
return hash;
public void setBundle(String bundle) {
this.bundle = bundle;
}
public String getIndex() {
return index;
public String getTrunkTransaction() {
return trunkTransaction;
}
public String getSignatureMessageChunk() {
return signatureMessageChunk;
public void setTrunkTransaction(String trunkTransaction) {
this.trunkTransaction = trunkTransaction;
}
}
public String getBranchTransaction() {
return branchTransaction;
}
public void setBranchTransaction(String branchTransaction) {
this.branchTransaction = branchTransaction;
}
public String getNonce() {
return nonce;
}
public void setNonce(String nonce) {
this.nonce = nonce;
}
public Boolean getPersistence() {
return persistence;
}
public void setPersistence(Boolean persistence) {
this.persistence = persistence;
}
}

View File

@ -24,7 +24,7 @@ public class Checksum {
}
private static String getAddress(String addressWithChecksum) {
return addressWithChecksum.substring(0, Constants.addressLengthWithoutChecksum);
return addressWithChecksum.substring(0, Constants.ADDRESS_LENGTH_WITHOUT_CHECKSUM);
}
public static boolean isValidChecksum(String addressWithChecksum) {
@ -34,7 +34,7 @@ public class Checksum {
}
private static boolean isAddressWithChecksum(String addressWithChecksum) {
return InputValidator.checkAddress(addressWithChecksum) && addressWithChecksum.length() == Constants.addressLengthWithChecksum;
return InputValidator.checkAddress(addressWithChecksum) && addressWithChecksum.length() == Constants.ADDRESS_LENGTH_WITH_CHECKSUM;
}
public static String calculateChecksum(String address) {

View File

@ -7,7 +7,9 @@ public class Constants {
public static final String TRYTE_ALPHABET = "9ABCDEFGHIJKLMNOPQRSTUVWXYZ";
public static int addressLengthWithoutChecksum = 81;
public static int addressLengthWithChecksum = 90;
public static final int SEED_LENGTH_MAX = 81;
public static int ADDRESS_LENGTH_WITHOUT_CHECKSUM = 81;
public static int ADDRESS_LENGTH_WITH_CHECKSUM = 90;
}

View File

@ -1,16 +1,19 @@
package jota.utils;
import jota.model.Transaction;
import jota.pow.Curl;
import java.util.Arrays;
public class Converter {
public static final int RADIX = 3;
public static final int MAX_TRIT_VALUE = (RADIX - 1) / 2, MIN_TRIT_VALUE = -MAX_TRIT_VALUE;
private static final int RADIX = 3;
private static final int MAX_TRIT_VALUE = (RADIX - 1) / 2, MIN_TRIT_VALUE = -MAX_TRIT_VALUE;
public static final int NUMBER_OF_TRITS_IN_A_BYTE = 5;
public static final int NUMBER_OF_TRITS_IN_A_TRYTE = 3;
static final int[][] BYTE_TO_TRITS_MAPPINGS = new int[243][];
static final int[][] TRYTE_TO_TRITS_MAPPINGS = new int[27][];
private static final int NUMBER_OF_TRITS_IN_A_BYTE = 5;
private static final int NUMBER_OF_TRITS_IN_A_TRYTE = 3;
private static final int[][] BYTE_TO_TRITS_MAPPINGS = new int[243][];
private static final int[][] TRYTE_TO_TRITS_MAPPINGS = new int[27][];
static {
@ -94,7 +97,7 @@ public class Converter {
public static int[] copyTrits(final String input, final int[] destination) {
for (int i = 0; i < input.length(); i++) {
int index = Constants.TRYTE_ALPHABET.indexOf(input.charAt(i));
destination[i * 3] = TRYTE_TO_TRITS_MAPPINGS [index][0];
destination[i * 3] = TRYTE_TO_TRITS_MAPPINGS[index][0];
destination[i * 3 + 1] = TRYTE_TO_TRITS_MAPPINGS[index][1];
destination[i * 3 + 2] = TRYTE_TO_TRITS_MAPPINGS[index][2];
}
@ -124,6 +127,15 @@ public class Converter {
return trits[offset] + trits[offset + 1] * 3 + trits[offset + 2] * 9;
}
public static int value(final int[] trits) {
int 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++) {
@ -134,4 +146,41 @@ public class Converter {
}
}
}
public static Transaction transactionObject(String trytes) {
if (trytes == null) return null;
// validity check
for (int i = 2279; i < 2295; i++) {
if (trytes.charAt(i) != '9') {
return null;
}
}
int[] transactionTrits = Converter.trits(trytes);
int[] hash = new int[90];
Curl curl = new 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;
}
}

View File

@ -6,8 +6,8 @@ package jota.utils;
public class InputValidator {
public static boolean isAddress(String address) {
return (address.length() == Constants.addressLengthWithoutChecksum ||
address.length() == Constants.addressLengthWithChecksum) && isTrytes(address, address.length());
return (address.length() == Constants.ADDRESS_LENGTH_WITHOUT_CHECKSUM ||
address.length() == Constants.ADDRESS_LENGTH_WITH_CHECKSUM) && isTrytes(address, address.length());
}
public static boolean checkAddress(String address) {
@ -20,4 +20,22 @@ 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 isArrayOfHashes(String[] hashes) {
if (hashes == null) return false;
for (String hash : hashes) {
// Check if address with checksum
if (hash.length() == 90) {
if (!isTrytes(hash, 90)) {
return false;
}
} else {
if (!isTrytes(hash, 81)) {
return false;
}
}
}
return true;
}
}

View File

@ -1,7 +1,9 @@
package jota.utils;
import java.text.DecimalFormat;
/**
* Created by pinpong on 30.11.16.
* Created by Sascha on 30.11.16.
*/
public class IotaUnitConverter {
@ -13,4 +15,53 @@ public class IotaUnitConverter {
private static long convertUnits(long amount, IotaUnits toUnit) {
return (long) (amount / Math.pow(10, toUnit.getValue()));
}
public static String convertRawIotaAmountToDisplayText(long amount) {
IotaUnits unit = findOptimalIotaUnitToDisplay(amount);
double amountInDisplayUnit = convertAmountTo(amount, unit);
return createAmountWithUnitDisplayText(amountInDisplayUnit, unit);
}
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);
result += " " + unit.getUnit();
return result;
}
public static String createAmountDisplayText(double amountInUnit, IotaUnits unit) {
DecimalFormat 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);
return result;
}
public static IotaUnits findOptimalIotaUnitToDisplay(long amount) {
int length = String.valueOf(amount).length();
if (amount < 0) // do not count "-" sign
length -= 1;
IotaUnits units = IotaUnits.IOTA;
if (length >= 1 && length <= 3) {
units = IotaUnits.IOTA;
} else if (length > 3 && length <= 6) {
units = IotaUnits.KILO_IOTA;
} else if (length > 6 && length <= 9) {
units = IotaUnits.MEGA_IOTA;
} else if (length > 9 && length <= 12) {
units = IotaUnits.GIGA_IOTA;
} else if (length > 12 && length <= 15) {
units = IotaUnits.TERA_IOTA;
} else if (length > 15 && length <= 18) {
units = IotaUnits.PETA_IOTA;
}
return units;
}
}

View File

@ -0,0 +1,20 @@
package jota.utils;
import java.util.Random;
/**
* Created by pinpong on 13.12.16.
*/
public class SeedRandomGenerator {
public static String generateNewSeed() {
char[] chars = Constants.TRYTE_ALPHABET.toCharArray();
StringBuilder builder = new StringBuilder();
Random random = new Random();
for (int i = 0; i < Constants.SEED_LENGTH_MAX; i++) {
char c = chars[random.nextInt(chars.length)];
builder.append(c);
}
return builder.toString();
}
}

View File

@ -70,7 +70,7 @@ public class TrytesConverter {
public static String toString(String inputTrytes) {
String string = "";
StringBuilder string = new StringBuilder();
for (int i = 0; i < inputTrytes.length(); i += 2) {
// get a trytes pair
@ -82,9 +82,9 @@ public class TrytesConverter {
String character = Character.toString((char) decimalValue);
string += character;
string.append(character);
}
return string;
return string.toString();
}
}
}

View File

@ -35,4 +35,24 @@ public class IotaUnitConverterTest {
public void shouldConvertUnitTiToPi() {
assertEquals(IotaUnitConverter.convertUnits(1000, IotaUnits.TERA_IOTA, IotaUnits.PETA_IOTA), 1);
}
@Test
public void shouldFindOptimizeUnitToDisplay() {
assertEquals(IotaUnitConverter.findOptimalIotaUnitToDisplay(1), IotaUnits.IOTA);
assertEquals(IotaUnitConverter.findOptimalIotaUnitToDisplay(1000), IotaUnits.KILO_IOTA);
assertEquals(IotaUnitConverter.findOptimalIotaUnitToDisplay(1000000), IotaUnits.MEGA_IOTA);
assertEquals(IotaUnitConverter.findOptimalIotaUnitToDisplay(1000000000), IotaUnits.GIGA_IOTA);
assertEquals(IotaUnitConverter.findOptimalIotaUnitToDisplay(1000000000000L), IotaUnits.TERA_IOTA);
assertEquals(IotaUnitConverter.findOptimalIotaUnitToDisplay(1000000000000000L), IotaUnits.PETA_IOTA);
}
@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");
}
}

View File

@ -0,0 +1,22 @@
package jota;
import jota.utils.Constants;
import jota.utils.InputValidator;
import jota.utils.SeedRandomGenerator;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
/**
* Created by pinpong on 13.12.16.
*/
public class SeedRandomGeneratorTest {
@Test
public void shouldGenerateNewSeed() {
String generatedSeed = SeedRandomGenerator.generateNewSeed();
assertEquals(InputValidator.isAddress(generatedSeed), true);
assertEquals(generatedSeed.length(), Constants.SEED_LENGTH_MAX);
}
}