From d262d33aaa3c33cb38d1accd2f13b53c5e4e4045 Mon Sep 17 00:00:00 2001 From: overcat <4catcode@gmail.com> Date: Mon, 31 Jul 2023 20:18:11 +0800 Subject: [PATCH] Add abstractions for converting between SCVal and native types. --- .../sdk/InvokeHostFunctionOperation.java | 11 +- .../java/org/stellar/sdk/SorobanServer.java | 3 +- src/main/java/org/stellar/sdk/StrKey.java | 2 +- src/main/java/org/stellar/sdk/scval/Scv.java | 94 +++++ .../{Address.java => scval/ScvAddress.java} | 64 ++-- .../org/stellar/sdk/scval/ScvBoolean.java | 36 ++ .../java/org/stellar/sdk/scval/ScvBytes.java | 37 ++ .../sdk/scval/ScvContractInstance.java | 30 ++ .../org/stellar/sdk/scval/ScvDuration.java | 50 +++ .../java/org/stellar/sdk/scval/ScvError.java | 42 +++ .../java/org/stellar/sdk/scval/ScvInt128.java | 83 +++++ .../java/org/stellar/sdk/scval/ScvInt256.java | 96 ++++++ .../java/org/stellar/sdk/scval/ScvInt32.java | 39 +++ .../java/org/stellar/sdk/scval/ScvInt64.java | 39 +++ .../scval/ScvLedgerKeyContractInstance.java | 36 ++ .../stellar/sdk/scval/ScvLedgerKeyNonce.java | 40 +++ .../java/org/stellar/sdk/scval/ScvMap.java | 53 +++ .../java/org/stellar/sdk/scval/ScvString.java | 44 +++ .../java/org/stellar/sdk/scval/ScvSymbol.java | 37 ++ .../org/stellar/sdk/scval/ScvTimePoint.java | 53 +++ .../org/stellar/sdk/scval/ScvUint128.java | 79 +++++ .../org/stellar/sdk/scval/ScvUint256.java | 90 +++++ .../java/org/stellar/sdk/scval/ScvUint32.java | 52 +++ .../java/org/stellar/sdk/scval/ScvUint64.java | 52 +++ .../java/org/stellar/sdk/scval/ScvVec.java | 46 +++ .../java/org/stellar/sdk/scval/ScvVoid.java | 29 ++ src/test/java/org/stellar/sdk/DemoTest.java | 45 +++ .../sdk/InvokeHostFunctionOperationTest.java | 15 +- .../org/stellar/sdk/SorobanServerTest.java | 11 +- .../stellar/sdk/TransactionBuilderTest.java | 3 +- .../java/org/stellar/sdk/TransactionTest.java | 3 +- .../ScvAddressTest.java} | 49 +-- .../org/stellar/sdk/scval/ScvBooleanTest.java | 24 ++ .../org/stellar/sdk/scval/ScvBytesTest.java | 27 ++ .../sdk/scval/ScvContractInstanceTest.java | 23 ++ .../stellar/sdk/scval/ScvDurationTest.java | 65 ++++ .../org/stellar/sdk/scval/ScvErrorTest.java | 35 ++ .../org/stellar/sdk/scval/ScvInt128Test.java | 141 ++++++++ .../org/stellar/sdk/scval/ScvInt256Test.java | 324 ++++++++++++++++++ .../org/stellar/sdk/scval/ScvInt32Test.java | 27 ++ .../ScvLedgerKeyContractInstanceTest.java | 41 +++ .../sdk/scval/ScvLedgerKeyNonceTest.java | 31 ++ .../org/stellar/sdk/scval/ScvMapTest.java | 53 +++ .../org/stellar/sdk/scval/ScvStringTest.java | 52 +++ .../org/stellar/sdk/scval/ScvSymbolTest.java | 31 ++ .../stellar/sdk/scval/ScvTimePointTest.java | 65 ++++ .../org/stellar/sdk/scval/ScvUint128Test.java | 100 ++++++ .../org/stellar/sdk/scval/ScvUint256Test.java | 131 +++++++ .../org/stellar/sdk/scval/ScvUint32Test.java | 63 ++++ .../org/stellar/sdk/scval/ScvUint64Test.java | 63 ++++ .../org/stellar/sdk/scval/ScvVecTest.java | 47 +++ .../org/stellar/sdk/scval/ScvVoidTest.java | 23 ++ 52 files changed, 2658 insertions(+), 71 deletions(-) create mode 100644 src/main/java/org/stellar/sdk/scval/Scv.java rename src/main/java/org/stellar/sdk/{Address.java => scval/ScvAddress.java} (64%) create mode 100644 src/main/java/org/stellar/sdk/scval/ScvBoolean.java create mode 100644 src/main/java/org/stellar/sdk/scval/ScvBytes.java create mode 100644 src/main/java/org/stellar/sdk/scval/ScvContractInstance.java create mode 100644 src/main/java/org/stellar/sdk/scval/ScvDuration.java create mode 100644 src/main/java/org/stellar/sdk/scval/ScvError.java create mode 100644 src/main/java/org/stellar/sdk/scval/ScvInt128.java create mode 100644 src/main/java/org/stellar/sdk/scval/ScvInt256.java create mode 100644 src/main/java/org/stellar/sdk/scval/ScvInt32.java create mode 100644 src/main/java/org/stellar/sdk/scval/ScvInt64.java create mode 100644 src/main/java/org/stellar/sdk/scval/ScvLedgerKeyContractInstance.java create mode 100644 src/main/java/org/stellar/sdk/scval/ScvLedgerKeyNonce.java create mode 100644 src/main/java/org/stellar/sdk/scval/ScvMap.java create mode 100644 src/main/java/org/stellar/sdk/scval/ScvString.java create mode 100644 src/main/java/org/stellar/sdk/scval/ScvSymbol.java create mode 100644 src/main/java/org/stellar/sdk/scval/ScvTimePoint.java create mode 100644 src/main/java/org/stellar/sdk/scval/ScvUint128.java create mode 100644 src/main/java/org/stellar/sdk/scval/ScvUint256.java create mode 100644 src/main/java/org/stellar/sdk/scval/ScvUint32.java create mode 100644 src/main/java/org/stellar/sdk/scval/ScvUint64.java create mode 100644 src/main/java/org/stellar/sdk/scval/ScvVec.java create mode 100644 src/main/java/org/stellar/sdk/scval/ScvVoid.java create mode 100644 src/test/java/org/stellar/sdk/DemoTest.java rename src/test/java/org/stellar/sdk/{AddressTest.java => scval/ScvAddressTest.java} (77%) create mode 100644 src/test/java/org/stellar/sdk/scval/ScvBooleanTest.java create mode 100644 src/test/java/org/stellar/sdk/scval/ScvBytesTest.java create mode 100644 src/test/java/org/stellar/sdk/scval/ScvContractInstanceTest.java create mode 100644 src/test/java/org/stellar/sdk/scval/ScvDurationTest.java create mode 100644 src/test/java/org/stellar/sdk/scval/ScvErrorTest.java create mode 100644 src/test/java/org/stellar/sdk/scval/ScvInt128Test.java create mode 100644 src/test/java/org/stellar/sdk/scval/ScvInt256Test.java create mode 100644 src/test/java/org/stellar/sdk/scval/ScvInt32Test.java create mode 100644 src/test/java/org/stellar/sdk/scval/ScvLedgerKeyContractInstanceTest.java create mode 100644 src/test/java/org/stellar/sdk/scval/ScvLedgerKeyNonceTest.java create mode 100644 src/test/java/org/stellar/sdk/scval/ScvMapTest.java create mode 100644 src/test/java/org/stellar/sdk/scval/ScvStringTest.java create mode 100644 src/test/java/org/stellar/sdk/scval/ScvSymbolTest.java create mode 100644 src/test/java/org/stellar/sdk/scval/ScvTimePointTest.java create mode 100644 src/test/java/org/stellar/sdk/scval/ScvUint128Test.java create mode 100644 src/test/java/org/stellar/sdk/scval/ScvUint256Test.java create mode 100644 src/test/java/org/stellar/sdk/scval/ScvUint32Test.java create mode 100644 src/test/java/org/stellar/sdk/scval/ScvUint64Test.java create mode 100644 src/test/java/org/stellar/sdk/scval/ScvVecTest.java create mode 100644 src/test/java/org/stellar/sdk/scval/ScvVoidTest.java diff --git a/src/main/java/org/stellar/sdk/InvokeHostFunctionOperation.java b/src/main/java/org/stellar/sdk/InvokeHostFunctionOperation.java index e0fa39eab..982478ca5 100644 --- a/src/main/java/org/stellar/sdk/InvokeHostFunctionOperation.java +++ b/src/main/java/org/stellar/sdk/InvokeHostFunctionOperation.java @@ -11,6 +11,7 @@ import lombok.Singular; import lombok.Value; import lombok.experimental.SuperBuilder; +import org.stellar.sdk.scval.ScvAddress; import org.stellar.sdk.xdr.ContractExecutable; import org.stellar.sdk.xdr.ContractExecutableType; import org.stellar.sdk.xdr.ContractIDPreimage; @@ -93,7 +94,7 @@ public static InvokeHostFunctionOperation fromXdr(InvokeHostFunctionOp op) { * @return {@link InvokeHostFunctionOperationBuilder} */ public static InvokeHostFunctionOperationBuilder createContractOperationBuilder( - String wasmId, Address address, @Nullable byte[] salt) { + String wasmId, ScvAddress address, @Nullable byte[] salt) { byte[] wasmIdBytes = Util.hexToBytes(wasmId); return createContractOperationBuilder(wasmIdBytes, address, salt); } @@ -110,7 +111,7 @@ public static InvokeHostFunctionOperation fromXdr(InvokeHostFunctionOp op) { * @return {@link InvokeHostFunctionOperationBuilder} */ public static InvokeHostFunctionOperationBuilder createContractOperationBuilder( - byte[] wasmId, Address address, @Nullable byte[] salt) { + byte[] wasmId, ScvAddress address, @Nullable byte[] salt) { if (salt == null) { salt = new byte[32]; new SecureRandom().nextBytes(salt); @@ -188,7 +189,7 @@ public static InvokeHostFunctionOperation fromXdr(InvokeHostFunctionOp op) { * @return {@link InvokeHostFunctionOperationBuilder} */ public static InvokeHostFunctionOperationBuilder createTokenContractOperationBuilder( - Address address, @Nullable byte[] salt) { + ScvAddress address, @Nullable byte[] salt) { if (salt == null) { salt = new byte[32]; new SecureRandom().nextBytes(salt); @@ -235,8 +236,8 @@ public static InvokeHostFunctionOperation fromXdr(InvokeHostFunctionOp op) { */ public static InvokeHostFunctionOperationBuilder invokeContractFunctionOperationBuilder( String contractId, String functionName, @Nullable Collection parameters) { - Address address = new Address(contractId); - if (address.getType() != Address.AddressType.CONTRACT) { + ScvAddress address = new ScvAddress(contractId); + if (address.getAddressType() != ScvAddress.AddressType.CONTRACT) { throw new IllegalArgumentException("\"contractId\" must be a contract address"); } SCVal contractIdScVal = address.toSCVal(); diff --git a/src/main/java/org/stellar/sdk/SorobanServer.java b/src/main/java/org/stellar/sdk/SorobanServer.java index f1b81fe99..28c641b48 100644 --- a/src/main/java/org/stellar/sdk/SorobanServer.java +++ b/src/main/java/org/stellar/sdk/SorobanServer.java @@ -40,6 +40,7 @@ import org.stellar.sdk.responses.sorobanrpc.SendTransactionResponse; import org.stellar.sdk.responses.sorobanrpc.SimulateTransactionResponse; import org.stellar.sdk.responses.sorobanrpc.SorobanRpcResponse; +import org.stellar.sdk.scval.ScvAddress; import org.stellar.sdk.xdr.ContractDataDurability; import org.stellar.sdk.xdr.ContractEntryBodyType; import org.stellar.sdk.xdr.LedgerEntry; @@ -175,7 +176,7 @@ public Optional getContractData( throw new IllegalArgumentException("Invalid durability: " + durability); } - Address address = new Address(contractId); + ScvAddress address = new ScvAddress(contractId); LedgerKey.LedgerKeyContractData ledgerKeyContractData = new LedgerKey.LedgerKeyContractData.Builder() .contract(address.toSCAddress()) diff --git a/src/main/java/org/stellar/sdk/StrKey.java b/src/main/java/org/stellar/sdk/StrKey.java index c6ab224f6..366250989 100644 --- a/src/main/java/org/stellar/sdk/StrKey.java +++ b/src/main/java/org/stellar/sdk/StrKey.java @@ -21,7 +21,7 @@ import org.stellar.sdk.xdr.XdrDataOutputStream; import org.stellar.sdk.xdr.XdrUnsignedHyperInteger; -class StrKey { +public class StrKey { public static final int ACCOUNT_ID_ADDRESS_LENGTH = 56; private static final byte[] b32Table = decodingTable(); diff --git a/src/main/java/org/stellar/sdk/scval/Scv.java b/src/main/java/org/stellar/sdk/scval/Scv.java new file mode 100644 index 000000000..62bf5c6e0 --- /dev/null +++ b/src/main/java/org/stellar/sdk/scval/Scv.java @@ -0,0 +1,94 @@ +package org.stellar.sdk.scval; + +import java.math.BigInteger; +import java.util.Arrays; +import org.stellar.sdk.xdr.SCVal; +import org.stellar.sdk.xdr.SCValType; + +/** Abstract class for all SCV types. */ +public abstract class Scv { + + /** + * Convert this object to {@link SCVal}. + * + * @return {@link SCVal} + */ + public abstract SCVal toSCVal(); + + /** + * Get the {@link SCValType} of this object. + * + * @return {@link SCValType} + */ + public abstract SCValType getSCValType(); + + /** + * Convert from {@link SCVal} to {@link Scv}. + * + * @param scVal {@link SCVal} to convert + * @return {@link Scv} + */ + public static Scv fromSCVal(SCVal scVal) { + switch (scVal.getDiscriminant()) { + case SCV_BOOL: + return ScvBoolean.fromSCVal(scVal); + case SCV_VOID: + return ScvVoid.fromSCVal(scVal); + case SCV_ERROR: + return ScvError.fromSCVal(scVal); + case SCV_U32: + return ScvUint32.fromSCVal(scVal); + case SCV_I32: + return ScvInt32.fromSCVal(scVal); + case SCV_U64: + return ScvUint64.fromSCVal(scVal); + case SCV_I64: + return ScvInt64.fromSCVal(scVal); + case SCV_TIMEPOINT: + return ScvTimePoint.fromSCVal(scVal); + case SCV_DURATION: + return ScvDuration.fromSCVal(scVal); + case SCV_U128: + return ScvUint128.fromSCVal(scVal); + case SCV_I128: + return ScvInt128.fromSCVal(scVal); + case SCV_U256: + return ScvUint256.fromSCVal(scVal); + case SCV_I256: + return ScvInt256.fromSCVal(scVal); + case SCV_BYTES: + return ScvBytes.fromSCVal(scVal); + case SCV_STRING: + return ScvString.fromSCVal(scVal); + case SCV_SYMBOL: + return ScvSymbol.fromSCVal(scVal); + case SCV_VEC: + return ScvVec.fromSCVal(scVal); + case SCV_MAP: + return ScvMap.fromSCVal(scVal); + case SCV_ADDRESS: + return ScvAddress.fromSCVal(scVal); + case SCV_CONTRACT_INSTANCE: + return ScvContractInstance.fromSCVal(scVal); + case SCV_LEDGER_KEY_CONTRACT_INSTANCE: + return ScvLedgerKeyContractInstance.fromSCVal(scVal); + case SCV_LEDGER_KEY_NONCE: + return ScvLedgerKeyNonce.fromSCVal(scVal); + default: + throw new IllegalArgumentException( + String.format("unsupported scVal type: %s", scVal.getDiscriminant())); + } + } + + static byte[] getBytes(BigInteger value) { + byte[] bytes = value.toByteArray(); + if (bytes.length < 8) { + byte[] temp = new byte[8]; + System.arraycopy(bytes, 0, temp, 8 - bytes.length, bytes.length); + bytes = temp; + } else if (bytes.length > 8) { + bytes = Arrays.copyOfRange(bytes, bytes.length - 8, bytes.length); + } + return bytes; + } +} diff --git a/src/main/java/org/stellar/sdk/Address.java b/src/main/java/org/stellar/sdk/scval/ScvAddress.java similarity index 64% rename from src/main/java/org/stellar/sdk/Address.java rename to src/main/java/org/stellar/sdk/scval/ScvAddress.java index 385ea9242..cce5367b5 100644 --- a/src/main/java/org/stellar/sdk/Address.java +++ b/src/main/java/org/stellar/sdk/scval/ScvAddress.java @@ -1,6 +1,8 @@ -package org.stellar.sdk; +package org.stellar.sdk.scval; import com.google.common.base.Objects; +import org.stellar.sdk.KeyPair; +import org.stellar.sdk.StrKey; import org.stellar.sdk.xdr.Hash; import org.stellar.sdk.xdr.SCAddress; import org.stellar.sdk.xdr.SCVal; @@ -10,18 +12,19 @@ * Represents a single address in the Stellar network. An address can represent an account or a * contract. */ -public class Address { +public class ScvAddress extends Scv { + private static final SCValType TYPE = SCValType.SCV_ADDRESS; private final byte[] key; private final AddressType type; /** - * Creates a new {@link Address} from a Stellar public key or contract ID. + * Creates a new {@link ScvAddress} from a Stellar public key or contract ID. * * @param address the StrKey encoded format of Stellar public key or contract ID. */ - public Address(String address) { + public ScvAddress(String address) { if (StrKey.isValidStellarAccountId(address)) { this.type = AddressType.ACCOUNT; this.key = StrKey.decodeStellarAccountId(address); @@ -34,53 +37,55 @@ public Address(String address) { } /** - * Creates a new {@link Address} from a Stellar public key. + * Creates a new {@link ScvAddress} from a Stellar public key. * * @param accountId the byte array of the Stellar public key. - * @return a new {@link Address} object from the given Stellar public key. + * @return a new {@link ScvAddress} object from the given Stellar public key. */ - public static Address fromAccount(byte[] accountId) { - return new Address(StrKey.encodeStellarAccountId(accountId)); + public static ScvAddress fromAccount(byte[] accountId) { + return new ScvAddress(StrKey.encodeStellarAccountId(accountId)); } /** - * Creates a new {@link Address} from a Stellar Contract ID. + * Creates a new {@link ScvAddress} from a Stellar Contract ID. * * @param contractId the byte array of the Stellar Contract ID. - * @return a new {@link Address} object from the given Stellar Contract ID. + * @return a new {@link ScvAddress} object from the given Stellar Contract ID. */ - public static Address fromContract(byte[] contractId) { - return new Address(StrKey.encodeContractId(contractId)); + public static ScvAddress fromContract(byte[] contractId) { + return new ScvAddress(StrKey.encodeContractId(contractId)); } /** - * Creates a new {@link Address} from a {@link SCAddress} XDR object. + * Creates a new {@link ScvAddress} from a {@link SCAddress} XDR object. * * @param scAddress the {@link SCAddress} object to convert - * @return a new {@link Address} object from the given XDR object + * @return a new {@link ScvAddress} object from the given XDR object */ - public static Address fromSCAddress(SCAddress scAddress) { + public static ScvAddress fromSCAddress(SCAddress scAddress) { switch (scAddress.getDiscriminant()) { case SC_ADDRESS_TYPE_ACCOUNT: - return new Address(StrKey.encodeStellarAccountId(scAddress.getAccountId())); + return new ScvAddress(StrKey.encodeStellarAccountId(scAddress.getAccountId())); case SC_ADDRESS_TYPE_CONTRACT: - return new Address(StrKey.encodeContractId(scAddress.getContractId().getHash())); + return new ScvAddress(StrKey.encodeContractId(scAddress.getContractId().getHash())); default: throw new IllegalArgumentException("Unsupported address type"); } } /** - * Creates a new {@link Address} from a {@link SCVal} XDR object. + * Creates a new {@link ScvAddress} from a {@link SCVal} XDR object. * * @param scVal the {@link SCVal} object to convert - * @return a new {@link Address} object from the given XDR object + * @return a new {@link ScvAddress} object from the given XDR object */ - public static Address fromSCVal(SCVal scVal) { - if (!SCValType.SCV_ADDRESS.equals(scVal.getDiscriminant())) { - throw new IllegalArgumentException("SCVal is not of type SCV_ADDRESS"); + public static ScvAddress fromSCVal(SCVal scVal) { + if (!TYPE.equals(scVal.getDiscriminant())) { + throw new IllegalArgumentException( + String.format( + "invalid scVal type, expected %s, but got %s", TYPE, scVal.getDiscriminant())); } - return Address.fromSCAddress(scVal.getAddress()); + return ScvAddress.fromSCAddress(scVal.getAddress()); } /** @@ -112,11 +117,16 @@ public SCAddress toSCAddress() { */ public SCVal toSCVal() { SCVal scVal = new SCVal(); - scVal.setDiscriminant(SCValType.SCV_ADDRESS); + scVal.setDiscriminant(TYPE); scVal.setAddress(this.toSCAddress()); return scVal; } + @Override + public SCValType getSCValType() { + return TYPE; + } + /** * Returns the byte array of the Stellar public key or contract ID. * @@ -131,7 +141,7 @@ public byte[] getBytes() { * * @return the type of this address. */ - public AddressType getType() { + public AddressType getAddressType() { return type; } @@ -142,11 +152,11 @@ public int hashCode() { @Override public boolean equals(Object object) { - if (!(object instanceof Address)) { + if (!(object instanceof ScvAddress)) { return false; } - Address other = (Address) object; + ScvAddress other = (ScvAddress) object; return Objects.equal(this.key, other.key) && Objects.equal(this.type, other.type); } diff --git a/src/main/java/org/stellar/sdk/scval/ScvBoolean.java b/src/main/java/org/stellar/sdk/scval/ScvBoolean.java new file mode 100644 index 000000000..81a485e5d --- /dev/null +++ b/src/main/java/org/stellar/sdk/scval/ScvBoolean.java @@ -0,0 +1,36 @@ +package org.stellar.sdk.scval; + +import lombok.EqualsAndHashCode; +import lombok.RequiredArgsConstructor; +import lombok.Value; +import org.stellar.sdk.xdr.SCVal; +import org.stellar.sdk.xdr.SCValType; + +@Value +@RequiredArgsConstructor +@EqualsAndHashCode(callSuper = false) +public class ScvBoolean extends Scv { + private static final SCValType TYPE = SCValType.SCV_BOOL; + + Boolean value; + + @Override + public SCVal toSCVal() { + return new SCVal.Builder().discriminant(TYPE).b(value).build(); + } + + @Override + public SCValType getSCValType() { + return TYPE; + } + + public static ScvBoolean fromSCVal(SCVal scVal) { + if (scVal.getDiscriminant() != TYPE) { + throw new IllegalArgumentException( + String.format( + "invalid scVal type, expected %s, but got %s", TYPE, scVal.getDiscriminant())); + } + + return new ScvBoolean(scVal.getB()); + } +} diff --git a/src/main/java/org/stellar/sdk/scval/ScvBytes.java b/src/main/java/org/stellar/sdk/scval/ScvBytes.java new file mode 100644 index 000000000..9f1792f6a --- /dev/null +++ b/src/main/java/org/stellar/sdk/scval/ScvBytes.java @@ -0,0 +1,37 @@ +package org.stellar.sdk.scval; + +import lombok.EqualsAndHashCode; +import lombok.RequiredArgsConstructor; +import lombok.Value; +import org.stellar.sdk.xdr.SCBytes; +import org.stellar.sdk.xdr.SCVal; +import org.stellar.sdk.xdr.SCValType; + +@Value +@RequiredArgsConstructor +@EqualsAndHashCode(callSuper = false) +public class ScvBytes extends Scv { + private static final SCValType TYPE = SCValType.SCV_BYTES; + + byte[] value; + + @Override + public SCVal toSCVal() { + return new SCVal.Builder().discriminant(TYPE).bytes(new SCBytes(value)).build(); + } + + @Override + public SCValType getSCValType() { + return TYPE; + } + + public static ScvBytes fromSCVal(SCVal scVal) { + if (scVal.getDiscriminant() != TYPE) { + throw new IllegalArgumentException( + String.format( + "invalid scVal type, expected %s, but got %s", TYPE, scVal.getDiscriminant())); + } + + return new ScvBytes(scVal.getBytes().getSCBytes()); + } +} diff --git a/src/main/java/org/stellar/sdk/scval/ScvContractInstance.java b/src/main/java/org/stellar/sdk/scval/ScvContractInstance.java new file mode 100644 index 000000000..11fce5507 --- /dev/null +++ b/src/main/java/org/stellar/sdk/scval/ScvContractInstance.java @@ -0,0 +1,30 @@ +package org.stellar.sdk.scval; + +import lombok.EqualsAndHashCode; +import org.stellar.sdk.xdr.SCVal; +import org.stellar.sdk.xdr.SCValType; + +@EqualsAndHashCode(callSuper = false) +public class ScvContractInstance extends Scv { + private static final SCValType TYPE = SCValType.SCV_CONTRACT_INSTANCE; + + @Override + public SCVal toSCVal() { + return new SCVal.Builder().discriminant(TYPE).build(); + } + + @Override + public SCValType getSCValType() { + return TYPE; + } + + public static ScvContractInstance fromSCVal(SCVal scVal) { + if (scVal.getDiscriminant() != TYPE) { + throw new IllegalArgumentException( + String.format( + "invalid scVal type, expected %s, but got %s", TYPE, scVal.getDiscriminant())); + } + + return new ScvContractInstance(); + } +} diff --git a/src/main/java/org/stellar/sdk/scval/ScvDuration.java b/src/main/java/org/stellar/sdk/scval/ScvDuration.java new file mode 100644 index 000000000..e2e5ce4fd --- /dev/null +++ b/src/main/java/org/stellar/sdk/scval/ScvDuration.java @@ -0,0 +1,50 @@ +package org.stellar.sdk.scval; + +import java.math.BigInteger; +import lombok.EqualsAndHashCode; +import lombok.Value; +import org.stellar.sdk.xdr.Duration; +import org.stellar.sdk.xdr.SCVal; +import org.stellar.sdk.xdr.SCValType; +import org.stellar.sdk.xdr.Uint64; +import org.stellar.sdk.xdr.XdrUnsignedHyperInteger; + +@Value +@EqualsAndHashCode(callSuper = false) +public class ScvDuration extends Scv { + private static final SCValType TYPE = SCValType.SCV_DURATION; + public static final BigInteger MAX_VALUE = XdrUnsignedHyperInteger.MAX_VALUE; + public static final BigInteger MIN_VALUE = XdrUnsignedHyperInteger.MIN_VALUE; + + BigInteger value; + + public ScvDuration(BigInteger value) { + if (value.compareTo(MIN_VALUE) < 0 || value.compareTo(MAX_VALUE) > 0) { + throw new IllegalArgumentException("Invalid Duration value, must be between 0 and 2^64-1"); + } + this.value = value; + } + + @Override + public SCVal toSCVal() { + return new SCVal.Builder() + .discriminant(TYPE) + .duration(new Duration(new Uint64(new XdrUnsignedHyperInteger(value)))) + .build(); + } + + @Override + public SCValType getSCValType() { + return TYPE; + } + + public static ScvDuration fromSCVal(SCVal scVal) { + if (scVal.getDiscriminant() != TYPE) { + throw new IllegalArgumentException( + String.format( + "invalid scVal type, expected %s, but got %s", TYPE, scVal.getDiscriminant())); + } + + return new ScvDuration(scVal.getDuration().getDuration().getUint64().getNumber()); + } +} diff --git a/src/main/java/org/stellar/sdk/scval/ScvError.java b/src/main/java/org/stellar/sdk/scval/ScvError.java new file mode 100644 index 000000000..4fa519c30 --- /dev/null +++ b/src/main/java/org/stellar/sdk/scval/ScvError.java @@ -0,0 +1,42 @@ +package org.stellar.sdk.scval; + +import lombok.EqualsAndHashCode; +import lombok.RequiredArgsConstructor; +import lombok.Value; +import org.stellar.sdk.xdr.SCErrorCode; +import org.stellar.sdk.xdr.SCErrorType; +import org.stellar.sdk.xdr.SCVal; +import org.stellar.sdk.xdr.SCValType; + +@Value +@RequiredArgsConstructor +@EqualsAndHashCode(callSuper = false) +public class ScvError extends Scv { + private static final SCValType TYPE = SCValType.SCV_ERROR; + + SCErrorType errorType; + SCErrorCode errorCode; + + @Override + public SCVal toSCVal() { + return new SCVal.Builder() + .discriminant(TYPE) + .error(new org.stellar.sdk.xdr.SCError.Builder().code(errorCode).type(errorType).build()) + .build(); + } + + @Override + public SCValType getSCValType() { + return TYPE; + } + + public static ScvError fromSCVal(SCVal scVal) { + if (scVal.getDiscriminant() != TYPE) { + throw new IllegalArgumentException( + String.format( + "invalid scVal type, expected %s, but got %s", TYPE, scVal.getDiscriminant())); + } + + return new ScvError(scVal.getError().getType(), scVal.getError().getCode()); + } +} diff --git a/src/main/java/org/stellar/sdk/scval/ScvInt128.java b/src/main/java/org/stellar/sdk/scval/ScvInt128.java new file mode 100644 index 000000000..810eb6df7 --- /dev/null +++ b/src/main/java/org/stellar/sdk/scval/ScvInt128.java @@ -0,0 +1,83 @@ +package org.stellar.sdk.scval; + +import com.google.common.primitives.Longs; +import java.math.BigInteger; +import java.util.Arrays; +import lombok.EqualsAndHashCode; +import lombok.Value; +import org.stellar.sdk.xdr.Int128Parts; +import org.stellar.sdk.xdr.Int64; +import org.stellar.sdk.xdr.SCVal; +import org.stellar.sdk.xdr.SCValType; +import org.stellar.sdk.xdr.Uint64; +import org.stellar.sdk.xdr.XdrUnsignedHyperInteger; + +@Value +@EqualsAndHashCode(callSuper = false) +public class ScvInt128 extends Scv { + private static final SCValType TYPE = SCValType.SCV_I128; + + public static final BigInteger MIN_VALUE = BigInteger.valueOf(-2).pow(127); + public static final BigInteger MAX_VALUE = + BigInteger.valueOf(2).pow(127).subtract(BigInteger.ONE); + + BigInteger value; + + public ScvInt128(BigInteger value) { + if (value.compareTo(MIN_VALUE) < 0 || value.compareTo(MAX_VALUE) > 0) { + throw new IllegalArgumentException( + String.format( + "invalid value, expected between %s and %s, but got %s", + MIN_VALUE, MAX_VALUE, value)); + } + this.value = value; + } + + @Override + public SCVal toSCVal() { + byte[] bytes = value.toByteArray(); + byte[] paddedBytes = new byte[16]; + if (value.signum() >= 0) { + int numBytesToCopy = Math.min(bytes.length, 16); + int copyStartIndex = bytes.length - numBytesToCopy; + System.arraycopy(bytes, copyStartIndex, paddedBytes, 16 - numBytesToCopy, numBytesToCopy); + } else { + Arrays.fill(paddedBytes, 0, 16 - bytes.length, (byte) 0xFF); + System.arraycopy(bytes, 0, paddedBytes, 16 - bytes.length, bytes.length); + } + + Int128Parts int128Parts = + new Int128Parts.Builder() + .hi(new Int64(Longs.fromByteArray(Arrays.copyOfRange(paddedBytes, 0, 8)))) + .lo( + new Uint64( + new XdrUnsignedHyperInteger( + new BigInteger(1, Arrays.copyOfRange(paddedBytes, 8, 16))))) + .build(); + return new SCVal.Builder().discriminant(TYPE).i128(int128Parts).build(); + } + + @Override + public SCValType getSCValType() { + return TYPE; + } + + public static ScvInt128 fromSCVal(SCVal scVal) { + if (scVal.getDiscriminant() != TYPE) { + throw new IllegalArgumentException( + String.format( + "invalid scVal type, expected %s, but got %s", TYPE, scVal.getDiscriminant())); + } + + Int128Parts int128Parts = scVal.getI128(); + byte[] hiBytes = Longs.toByteArray(int128Parts.getHi().getInt64()); + byte[] loBytes = getBytes(int128Parts.getLo().getUint64().getNumber()); + + byte[] fullBytes = new byte[16]; + System.arraycopy(hiBytes, 0, fullBytes, 0, 8); + System.arraycopy(loBytes, 0, fullBytes, 8, 8); + + BigInteger value = new BigInteger(fullBytes); + return new ScvInt128(value); + } +} diff --git a/src/main/java/org/stellar/sdk/scval/ScvInt256.java b/src/main/java/org/stellar/sdk/scval/ScvInt256.java new file mode 100644 index 000000000..ba3052ada --- /dev/null +++ b/src/main/java/org/stellar/sdk/scval/ScvInt256.java @@ -0,0 +1,96 @@ +package org.stellar.sdk.scval; + +import com.google.common.primitives.Longs; +import java.math.BigInteger; +import java.util.Arrays; +import lombok.EqualsAndHashCode; +import lombok.Value; +import org.stellar.sdk.xdr.Int256Parts; +import org.stellar.sdk.xdr.Int64; +import org.stellar.sdk.xdr.SCVal; +import org.stellar.sdk.xdr.SCValType; +import org.stellar.sdk.xdr.Uint64; +import org.stellar.sdk.xdr.XdrUnsignedHyperInteger; + +@Value +@EqualsAndHashCode(callSuper = false) +public class ScvInt256 extends Scv { + private static final SCValType TYPE = SCValType.SCV_I256; + + public static final BigInteger MIN_VALUE = BigInteger.valueOf(-2).pow(255); + public static final BigInteger MAX_VALUE = + BigInteger.valueOf(2).pow(255).subtract(BigInteger.ONE); + + BigInteger value; + + public ScvInt256(BigInteger value) { + if (value.compareTo(MIN_VALUE) < 0 || value.compareTo(MAX_VALUE) > 0) { + throw new IllegalArgumentException( + String.format( + "invalid value, expected between %s and %s, but got %s", + MIN_VALUE, MAX_VALUE, value)); + } + this.value = value; + } + + @Override + public SCVal toSCVal() { + byte[] bytes = value.toByteArray(); + byte[] paddedBytes = new byte[32]; + + if (value.signum() >= 0) { + int numBytesToCopy = Math.min(bytes.length, 32); + int copyStartIndex = bytes.length - numBytesToCopy; + System.arraycopy(bytes, copyStartIndex, paddedBytes, 32 - numBytesToCopy, numBytesToCopy); + } else { + Arrays.fill(paddedBytes, 0, 32 - bytes.length, (byte) 0xFF); + System.arraycopy(bytes, 0, paddedBytes, 32 - bytes.length, bytes.length); + } + + Int256Parts int256Parts = + new Int256Parts.Builder() + .hi_hi(new Int64(Longs.fromByteArray(Arrays.copyOfRange(paddedBytes, 0, 8)))) + .hi_lo( + new Uint64( + new XdrUnsignedHyperInteger( + new BigInteger(1, Arrays.copyOfRange(paddedBytes, 8, 16))))) + .lo_hi( + new Uint64( + new XdrUnsignedHyperInteger( + new BigInteger(1, Arrays.copyOfRange(paddedBytes, 16, 24))))) + .lo_lo( + new Uint64( + new XdrUnsignedHyperInteger( + new BigInteger(1, Arrays.copyOfRange(paddedBytes, 24, 32))))) + .build(); + return new SCVal.Builder().discriminant(TYPE).i256(int256Parts).build(); + } + + public static ScvInt256 fromSCVal(SCVal scVal) { + if (scVal.getDiscriminant() != TYPE) { + throw new IllegalArgumentException( + String.format( + "invalid scVal type, expected %s, but got %s", TYPE, scVal.getDiscriminant())); + } + + Int256Parts int256Parts = scVal.getI256(); + byte[] hiHiBytes = Longs.toByteArray(int256Parts.getHi_hi().getInt64()); + byte[] hiLoBytes = getBytes(int256Parts.getHi_lo().getUint64().getNumber()); + byte[] loHiBytes = getBytes(int256Parts.getLo_hi().getUint64().getNumber()); + byte[] loLoBytes = getBytes(int256Parts.getLo_lo().getUint64().getNumber()); + + byte[] fullBytes = new byte[32]; + System.arraycopy(hiHiBytes, 0, fullBytes, 0, 8); + System.arraycopy(hiLoBytes, 0, fullBytes, 8, 8); + System.arraycopy(loHiBytes, 0, fullBytes, 16, 8); + System.arraycopy(loLoBytes, 0, fullBytes, 24, 8); + + BigInteger value = new BigInteger(fullBytes); + return new ScvInt256(value); + } + + @Override + public SCValType getSCValType() { + return SCValType.SCV_I256; + } +} diff --git a/src/main/java/org/stellar/sdk/scval/ScvInt32.java b/src/main/java/org/stellar/sdk/scval/ScvInt32.java new file mode 100644 index 000000000..d39eca88b --- /dev/null +++ b/src/main/java/org/stellar/sdk/scval/ScvInt32.java @@ -0,0 +1,39 @@ +package org.stellar.sdk.scval; + +import lombok.EqualsAndHashCode; +import lombok.RequiredArgsConstructor; +import lombok.Value; +import org.stellar.sdk.xdr.Int32; +import org.stellar.sdk.xdr.SCVal; +import org.stellar.sdk.xdr.SCValType; + +@Value +@RequiredArgsConstructor +@EqualsAndHashCode(callSuper = false) +public class ScvInt32 extends Scv { + private static final SCValType TYPE = SCValType.SCV_I32; + public static final int MAX_VALUE = Integer.MAX_VALUE; + public static final int MIN_VALUE = Integer.MIN_VALUE; + + int value; + + @Override + public SCVal toSCVal() { + return new SCVal.Builder().discriminant(TYPE).i32(new Int32(value)).build(); + } + + @Override + public SCValType getSCValType() { + return TYPE; + } + + public static ScvInt32 fromSCVal(SCVal scVal) { + if (scVal.getDiscriminant() != TYPE) { + throw new IllegalArgumentException( + String.format( + "invalid scVal type, expected %s, but got %s", TYPE, scVal.getDiscriminant())); + } + + return new ScvInt32(scVal.getI32().getInt32()); + } +} diff --git a/src/main/java/org/stellar/sdk/scval/ScvInt64.java b/src/main/java/org/stellar/sdk/scval/ScvInt64.java new file mode 100644 index 000000000..cfd2c63ef --- /dev/null +++ b/src/main/java/org/stellar/sdk/scval/ScvInt64.java @@ -0,0 +1,39 @@ +package org.stellar.sdk.scval; + +import lombok.EqualsAndHashCode; +import lombok.RequiredArgsConstructor; +import lombok.Value; +import org.stellar.sdk.xdr.Int64; +import org.stellar.sdk.xdr.SCVal; +import org.stellar.sdk.xdr.SCValType; + +@Value +@RequiredArgsConstructor +@EqualsAndHashCode(callSuper = false) +public class ScvInt64 extends Scv { + private static final SCValType TYPE = SCValType.SCV_I64; + + public static final long MAX_VALUE = Long.MAX_VALUE; + public static final long MIN_VALUE = Long.MIN_VALUE; + + long value; + + @Override + public SCVal toSCVal() { + return new SCVal.Builder().discriminant(TYPE).i64(new Int64(value)).build(); + } + + @Override + public SCValType getSCValType() { + return TYPE; + } + + public static ScvInt64 fromSCVal(SCVal scVal) { + if (scVal.getDiscriminant() != TYPE) { + throw new IllegalArgumentException( + String.format( + "invalid scVal type, expected %s, but got %s", TYPE, scVal.getDiscriminant())); + } + return new ScvInt64(scVal.getI64().getInt64()); + } +} diff --git a/src/main/java/org/stellar/sdk/scval/ScvLedgerKeyContractInstance.java b/src/main/java/org/stellar/sdk/scval/ScvLedgerKeyContractInstance.java new file mode 100644 index 000000000..9f5752aac --- /dev/null +++ b/src/main/java/org/stellar/sdk/scval/ScvLedgerKeyContractInstance.java @@ -0,0 +1,36 @@ +package org.stellar.sdk.scval; + +import lombok.EqualsAndHashCode; +import lombok.RequiredArgsConstructor; +import lombok.Value; +import org.stellar.sdk.xdr.SCContractInstance; +import org.stellar.sdk.xdr.SCVal; +import org.stellar.sdk.xdr.SCValType; + +@Value +@RequiredArgsConstructor +@EqualsAndHashCode(callSuper = false) +public class ScvLedgerKeyContractInstance extends Scv { + private static final SCValType TYPE = SCValType.SCV_LEDGER_KEY_CONTRACT_INSTANCE; + + SCContractInstance value; + + @Override + public SCVal toSCVal() { + return new SCVal.Builder().discriminant(TYPE).instance(value).build(); + } + + @Override + public SCValType getSCValType() { + return TYPE; + } + + public static ScvLedgerKeyContractInstance fromSCVal(SCVal scVal) { + if (scVal.getDiscriminant() != TYPE) { + throw new IllegalArgumentException( + String.format( + "invalid scVal type, expected %s, but got %s", TYPE, scVal.getDiscriminant())); + } + return new ScvLedgerKeyContractInstance(scVal.getInstance()); + } +} diff --git a/src/main/java/org/stellar/sdk/scval/ScvLedgerKeyNonce.java b/src/main/java/org/stellar/sdk/scval/ScvLedgerKeyNonce.java new file mode 100644 index 000000000..227e8dbe8 --- /dev/null +++ b/src/main/java/org/stellar/sdk/scval/ScvLedgerKeyNonce.java @@ -0,0 +1,40 @@ +package org.stellar.sdk.scval; + +import lombok.EqualsAndHashCode; +import lombok.RequiredArgsConstructor; +import lombok.Value; +import org.stellar.sdk.xdr.Int64; +import org.stellar.sdk.xdr.SCNonceKey; +import org.stellar.sdk.xdr.SCVal; +import org.stellar.sdk.xdr.SCValType; + +@Value +@RequiredArgsConstructor +@EqualsAndHashCode(callSuper = false) +public class ScvLedgerKeyNonce extends Scv { + private static final SCValType TYPE = SCValType.SCV_LEDGER_KEY_NONCE; + + long value; + + @Override + public SCVal toSCVal() { + return new SCVal.Builder() + .discriminant(TYPE) + .nonce_key(new SCNonceKey.Builder().nonce(new Int64(value)).build()) + .build(); + } + + @Override + public SCValType getSCValType() { + return TYPE; + } + + public static ScvLedgerKeyNonce fromSCVal(SCVal scVal) { + if (scVal.getDiscriminant() != TYPE) { + throw new IllegalArgumentException( + String.format( + "invalid scVal type, expected %s, but got %s", TYPE, scVal.getDiscriminant())); + } + return new ScvLedgerKeyNonce(scVal.getNonce_key().getNonce().getInt64()); + } +} diff --git a/src/main/java/org/stellar/sdk/scval/ScvMap.java b/src/main/java/org/stellar/sdk/scval/ScvMap.java new file mode 100644 index 000000000..b669bd9be --- /dev/null +++ b/src/main/java/org/stellar/sdk/scval/ScvMap.java @@ -0,0 +1,53 @@ +package org.stellar.sdk.scval; + +import java.util.HashMap; +import java.util.Map; +import lombok.EqualsAndHashCode; +import lombok.RequiredArgsConstructor; +import lombok.Value; +import org.stellar.sdk.xdr.SCMap; +import org.stellar.sdk.xdr.SCMapEntry; +import org.stellar.sdk.xdr.SCVal; +import org.stellar.sdk.xdr.SCValType; + +@Value +@RequiredArgsConstructor +@EqualsAndHashCode(callSuper = false) +public class ScvMap extends Scv { + private static final SCValType TYPE = SCValType.SCV_MAP; + + Map value; + + @Override + public SCVal toSCVal() { + SCMapEntry[] scMapEntries = new SCMapEntry[value.size()]; + int i = 0; + for (Map.Entry entry : value.entrySet()) { + scMapEntries[i++] = + new SCMapEntry.Builder() + .key(entry.getKey().toSCVal()) + .val(entry.getValue().toSCVal()) + .build(); + } + return new SCVal.Builder().discriminant(TYPE).map(new SCMap(scMapEntries)).build(); + } + + @Override + public SCValType getSCValType() { + return TYPE; + } + + public static ScvMap fromSCVal(SCVal scVal) { + if (scVal.getDiscriminant() != TYPE) { + throw new IllegalArgumentException( + String.format( + "invalid scVal type, expected %s, but got %s", TYPE, scVal.getDiscriminant())); + } + + Map map = new HashMap<>(); + for (SCMapEntry entry : scVal.getMap().getSCMap()) { + map.put(Scv.fromSCVal(entry.getKey()), Scv.fromSCVal(entry.getVal())); + } + return new ScvMap(map); + } +} diff --git a/src/main/java/org/stellar/sdk/scval/ScvString.java b/src/main/java/org/stellar/sdk/scval/ScvString.java new file mode 100644 index 000000000..6e13f0b3d --- /dev/null +++ b/src/main/java/org/stellar/sdk/scval/ScvString.java @@ -0,0 +1,44 @@ +package org.stellar.sdk.scval; + +import lombok.EqualsAndHashCode; +import lombok.Value; +import org.stellar.sdk.xdr.SCString; +import org.stellar.sdk.xdr.SCVal; +import org.stellar.sdk.xdr.SCValType; +import org.stellar.sdk.xdr.XdrString; + +@Value +@EqualsAndHashCode(callSuper = false) +public class ScvString extends Scv { + private static final SCValType TYPE = SCValType.SCV_STRING; + + byte[] value; + + public ScvString(String value) { + this.value = value.getBytes(); + } + + public ScvString(byte[] value) { + this.value = value; + } + + @Override + public SCVal toSCVal() { + return new SCVal.Builder().discriminant(TYPE).str(new SCString(new XdrString(value))).build(); + } + + @Override + public SCValType getSCValType() { + return TYPE; + } + + public static ScvString fromSCVal(SCVal scVal) { + if (scVal.getDiscriminant() != TYPE) { + throw new IllegalArgumentException( + String.format( + "invalid scVal type, expected %s, but got %s", TYPE, scVal.getDiscriminant())); + } + + return new ScvString(scVal.getStr().getSCString().getBytes()); + } +} diff --git a/src/main/java/org/stellar/sdk/scval/ScvSymbol.java b/src/main/java/org/stellar/sdk/scval/ScvSymbol.java new file mode 100644 index 000000000..3ab27af5f --- /dev/null +++ b/src/main/java/org/stellar/sdk/scval/ScvSymbol.java @@ -0,0 +1,37 @@ +package org.stellar.sdk.scval; + +import lombok.EqualsAndHashCode; +import lombok.RequiredArgsConstructor; +import lombok.Value; +import org.stellar.sdk.xdr.SCSymbol; +import org.stellar.sdk.xdr.SCVal; +import org.stellar.sdk.xdr.SCValType; +import org.stellar.sdk.xdr.XdrString; + +@Value +@RequiredArgsConstructor +@EqualsAndHashCode(callSuper = false) +public class ScvSymbol extends Scv { + private static final SCValType TYPE = SCValType.SCV_SYMBOL; + + String value; + + @Override + public SCVal toSCVal() { + return new SCVal.Builder().discriminant(TYPE).sym(new SCSymbol(new XdrString(value))).build(); + } + + @Override + public SCValType getSCValType() { + return TYPE; + } + + public static ScvSymbol fromSCVal(SCVal scVal) { + if (scVal.getDiscriminant() != TYPE) { + throw new IllegalArgumentException( + String.format( + "invalid scVal type, expected %s, but got %s", TYPE, scVal.getDiscriminant())); + } + return new ScvSymbol(scVal.getSym().getSCSymbol().toString()); + } +} diff --git a/src/main/java/org/stellar/sdk/scval/ScvTimePoint.java b/src/main/java/org/stellar/sdk/scval/ScvTimePoint.java new file mode 100644 index 000000000..397424b8f --- /dev/null +++ b/src/main/java/org/stellar/sdk/scval/ScvTimePoint.java @@ -0,0 +1,53 @@ +package org.stellar.sdk.scval; + +import java.math.BigInteger; +import lombok.EqualsAndHashCode; +import lombok.Value; +import org.stellar.sdk.xdr.SCVal; +import org.stellar.sdk.xdr.SCValType; +import org.stellar.sdk.xdr.TimePoint; +import org.stellar.sdk.xdr.Uint64; +import org.stellar.sdk.xdr.XdrUnsignedHyperInteger; + +@Value +@EqualsAndHashCode(callSuper = false) +public class ScvTimePoint extends Scv { + private static final SCValType TYPE = SCValType.SCV_TIMEPOINT; + + public static final BigInteger MAX_VALUE = XdrUnsignedHyperInteger.MAX_VALUE; + public static final BigInteger MIN_VALUE = XdrUnsignedHyperInteger.MIN_VALUE; + + BigInteger value; + + public ScvTimePoint(BigInteger value) { + if (value.compareTo(MIN_VALUE) < 0 || value.compareTo(MAX_VALUE) > 0) { + throw new IllegalArgumentException( + String.format( + "invalid value, expected between %s and %s, but got %s", + MIN_VALUE, MAX_VALUE, value)); + } + this.value = value; + } + + @Override + public SCVal toSCVal() { + return new SCVal.Builder() + .discriminant(TYPE) + .timepoint(new TimePoint(new Uint64(new XdrUnsignedHyperInteger(value)))) + .build(); + } + + @Override + public SCValType getSCValType() { + return TYPE; + } + + public static ScvTimePoint fromSCVal(SCVal scVal) { + if (scVal.getDiscriminant() != TYPE) { + throw new IllegalArgumentException( + String.format( + "invalid scVal type, expected %s, but got %s", TYPE, scVal.getDiscriminant())); + } + return new ScvTimePoint(scVal.getTimepoint().getTimePoint().getUint64().getNumber()); + } +} diff --git a/src/main/java/org/stellar/sdk/scval/ScvUint128.java b/src/main/java/org/stellar/sdk/scval/ScvUint128.java new file mode 100644 index 000000000..f7b5243ed --- /dev/null +++ b/src/main/java/org/stellar/sdk/scval/ScvUint128.java @@ -0,0 +1,79 @@ +package org.stellar.sdk.scval; + +import java.math.BigInteger; +import java.util.Arrays; +import lombok.EqualsAndHashCode; +import lombok.Value; +import org.stellar.sdk.xdr.SCVal; +import org.stellar.sdk.xdr.SCValType; +import org.stellar.sdk.xdr.UInt128Parts; +import org.stellar.sdk.xdr.Uint64; +import org.stellar.sdk.xdr.XdrUnsignedHyperInteger; + +@Value +@EqualsAndHashCode(callSuper = false) +public class ScvUint128 extends Scv { + private static final SCValType TYPE = SCValType.SCV_U128; + + public static final BigInteger MIN_VALUE = BigInteger.ZERO; + public static final BigInteger MAX_VALUE = + BigInteger.valueOf(2).pow(128).subtract(BigInteger.ONE); + + BigInteger value; + + public ScvUint128(BigInteger value) { + if (value.compareTo(MIN_VALUE) < 0 || value.compareTo(MAX_VALUE) > 0) { + throw new IllegalArgumentException( + String.format( + "invalid value, expected between %s and %s, but got %s", + MIN_VALUE, MAX_VALUE, value)); + } + this.value = value; + } + + @Override + public SCVal toSCVal() { + byte[] bytes = value.toByteArray(); + byte[] paddedBytes = new byte[16]; + int numBytesToCopy = Math.min(bytes.length, 16); + int copyStartIndex = bytes.length - numBytesToCopy; + System.arraycopy(bytes, copyStartIndex, paddedBytes, 16 - numBytesToCopy, numBytesToCopy); + + UInt128Parts uInt128Parts = + new UInt128Parts.Builder() + .hi( + new Uint64( + new XdrUnsignedHyperInteger( + new BigInteger(1, Arrays.copyOfRange(paddedBytes, 0, 8))))) + .lo( + new Uint64( + new XdrUnsignedHyperInteger( + new BigInteger(1, Arrays.copyOfRange(paddedBytes, 8, 16))))) + .build(); + return new SCVal.Builder().discriminant(TYPE).u128(uInt128Parts).build(); + } + + @Override + public SCValType getSCValType() { + return TYPE; + } + + public static ScvUint128 fromSCVal(SCVal scVal) { + if (scVal.getDiscriminant() != TYPE) { + throw new IllegalArgumentException( + String.format( + "invalid scVal type, expected %s, but got %s", TYPE, scVal.getDiscriminant())); + } + + UInt128Parts uInt128Parts = scVal.getU128(); + byte[] hiBytes = getBytes(uInt128Parts.getHi().getUint64().getNumber()); + byte[] loBytes = getBytes(uInt128Parts.getLo().getUint64().getNumber()); + + byte[] fullBytes = new byte[16]; + System.arraycopy(hiBytes, 0, fullBytes, 0, 8); + System.arraycopy(loBytes, 0, fullBytes, 8, 8); + + BigInteger value = new BigInteger(1, fullBytes); + return new ScvUint128(value); + } +} diff --git a/src/main/java/org/stellar/sdk/scval/ScvUint256.java b/src/main/java/org/stellar/sdk/scval/ScvUint256.java new file mode 100644 index 000000000..7b077d534 --- /dev/null +++ b/src/main/java/org/stellar/sdk/scval/ScvUint256.java @@ -0,0 +1,90 @@ +package org.stellar.sdk.scval; + +import java.math.BigInteger; +import java.util.Arrays; +import lombok.EqualsAndHashCode; +import lombok.Value; +import org.stellar.sdk.xdr.SCVal; +import org.stellar.sdk.xdr.SCValType; +import org.stellar.sdk.xdr.UInt256Parts; +import org.stellar.sdk.xdr.Uint64; +import org.stellar.sdk.xdr.XdrUnsignedHyperInteger; + +@Value +@EqualsAndHashCode(callSuper = false) +public class ScvUint256 extends Scv { + private static final SCValType TYPE = SCValType.SCV_U256; + + public static final BigInteger MIN_VALUE = BigInteger.ZERO; + public static final BigInteger MAX_VALUE = + BigInteger.valueOf(2).pow(256).subtract(BigInteger.ONE); + + BigInteger value; + + public ScvUint256(BigInteger value) { + if (value.compareTo(MIN_VALUE) < 0 || value.compareTo(MAX_VALUE) > 0) { + throw new IllegalArgumentException( + String.format( + "invalid value, expected between %s and %s, but got %s", + MIN_VALUE, MAX_VALUE, value)); + } + this.value = value; + } + + @Override + public SCVal toSCVal() { + byte[] bytes = value.toByteArray(); + byte[] paddedBytes = new byte[32]; + int numBytesToCopy = Math.min(bytes.length, 32); + int copyStartIndex = bytes.length - numBytesToCopy; + System.arraycopy(bytes, copyStartIndex, paddedBytes, 32 - numBytesToCopy, numBytesToCopy); + + UInt256Parts uInt256Parts = + new UInt256Parts.Builder() + .hi_hi( + new Uint64( + new XdrUnsignedHyperInteger( + new BigInteger(1, Arrays.copyOfRange(paddedBytes, 0, 8))))) + .hi_lo( + new Uint64( + new XdrUnsignedHyperInteger( + new BigInteger(1, Arrays.copyOfRange(paddedBytes, 8, 16))))) + .lo_hi( + new Uint64( + new XdrUnsignedHyperInteger( + new BigInteger(1, Arrays.copyOfRange(paddedBytes, 16, 24))))) + .lo_lo( + new Uint64( + new XdrUnsignedHyperInteger( + new BigInteger(1, Arrays.copyOfRange(paddedBytes, 24, 32))))) + .build(); + return new SCVal.Builder().discriminant(TYPE).u256(uInt256Parts).build(); + } + + @Override + public SCValType getSCValType() { + return TYPE; + } + + public static ScvUint256 fromSCVal(SCVal scVal) { + if (scVal.getDiscriminant() != TYPE) { + throw new IllegalArgumentException( + String.format( + "invalid scVal type, expected %s, but got %s", TYPE, scVal.getDiscriminant())); + } + + UInt256Parts uInt256Parts = scVal.getU256(); + byte[] hiHiBytes = getBytes(uInt256Parts.getHi_hi().getUint64().getNumber()); + byte[] hiLoBytes = getBytes(uInt256Parts.getHi_lo().getUint64().getNumber()); + byte[] loHiBytes = getBytes(uInt256Parts.getLo_hi().getUint64().getNumber()); + byte[] loLoBytes = getBytes(uInt256Parts.getLo_lo().getUint64().getNumber()); + + byte[] fullBytes = new byte[32]; + System.arraycopy(hiHiBytes, 0, fullBytes, 0, 8); + System.arraycopy(hiLoBytes, 0, fullBytes, 8, 8); + System.arraycopy(loHiBytes, 0, fullBytes, 16, 8); + System.arraycopy(loLoBytes, 0, fullBytes, 24, 8); + + return new ScvUint256(new BigInteger(1, fullBytes)); + } +} diff --git a/src/main/java/org/stellar/sdk/scval/ScvUint32.java b/src/main/java/org/stellar/sdk/scval/ScvUint32.java new file mode 100644 index 000000000..0d3670677 --- /dev/null +++ b/src/main/java/org/stellar/sdk/scval/ScvUint32.java @@ -0,0 +1,52 @@ +package org.stellar.sdk.scval; + +import lombok.EqualsAndHashCode; +import lombok.Value; +import org.stellar.sdk.xdr.SCVal; +import org.stellar.sdk.xdr.SCValType; +import org.stellar.sdk.xdr.Uint32; +import org.stellar.sdk.xdr.XdrUnsignedInteger; + +@Value +@EqualsAndHashCode(callSuper = false) +public class ScvUint32 extends Scv { + private static final SCValType TYPE = SCValType.SCV_U32; + + public static final long MAX_VALUE = XdrUnsignedInteger.MAX_VALUE; + public static final long MIN_VALUE = XdrUnsignedInteger.MIN_VALUE; + + long value; + + public ScvUint32(long value) { + if (value < MIN_VALUE || value > MAX_VALUE) { + throw new IllegalArgumentException( + String.format( + "invalid value, expected between %s and %s, but got %s", + MIN_VALUE, MAX_VALUE, value)); + } + this.value = value; + } + + @Override + public SCVal toSCVal() { + return new SCVal.Builder() + .discriminant(TYPE) + .u32(new Uint32(new XdrUnsignedInteger(value))) + .build(); + } + + @Override + public SCValType getSCValType() { + return TYPE; + } + + public static ScvUint32 fromSCVal(SCVal scVal) { + if (scVal.getDiscriminant() != TYPE) { + throw new IllegalArgumentException( + String.format( + "invalid scVal type, expected %s, but got %s", TYPE, scVal.getDiscriminant())); + } + + return new ScvUint32(scVal.getU32().getUint32().getNumber()); + } +} diff --git a/src/main/java/org/stellar/sdk/scval/ScvUint64.java b/src/main/java/org/stellar/sdk/scval/ScvUint64.java new file mode 100644 index 000000000..2c96baf75 --- /dev/null +++ b/src/main/java/org/stellar/sdk/scval/ScvUint64.java @@ -0,0 +1,52 @@ +package org.stellar.sdk.scval; + +import java.math.BigInteger; +import lombok.EqualsAndHashCode; +import lombok.Value; +import org.stellar.sdk.xdr.SCVal; +import org.stellar.sdk.xdr.SCValType; +import org.stellar.sdk.xdr.Uint64; +import org.stellar.sdk.xdr.XdrUnsignedHyperInteger; + +@Value +@EqualsAndHashCode(callSuper = false) +public class ScvUint64 extends Scv { + private static final SCValType TYPE = SCValType.SCV_U64; + + public static final BigInteger MAX_VALUE = XdrUnsignedHyperInteger.MAX_VALUE; + public static final BigInteger MIN_VALUE = XdrUnsignedHyperInteger.MIN_VALUE; + + BigInteger value; + + public ScvUint64(BigInteger value) { + if (value.compareTo(MIN_VALUE) < 0 || value.compareTo(MAX_VALUE) > 0) { + throw new IllegalArgumentException( + String.format( + "invalid value, expected between %s and %s, but got %s", + MIN_VALUE, MAX_VALUE, value)); + } + this.value = value; + } + + @Override + public SCVal toSCVal() { + return new SCVal.Builder() + .discriminant(TYPE) + .u64(new Uint64(new XdrUnsignedHyperInteger(value))) + .build(); + } + + @Override + public SCValType getSCValType() { + return TYPE; + } + + public static ScvUint64 fromSCVal(SCVal scVal) { + if (scVal.getDiscriminant() != TYPE) { + throw new IllegalArgumentException( + String.format( + "invalid scVal type, expected %s, but got %s", TYPE, scVal.getDiscriminant())); + } + return new ScvUint64(scVal.getU64().getUint64().getNumber()); + } +} diff --git a/src/main/java/org/stellar/sdk/scval/ScvVec.java b/src/main/java/org/stellar/sdk/scval/ScvVec.java new file mode 100644 index 000000000..98aca81cf --- /dev/null +++ b/src/main/java/org/stellar/sdk/scval/ScvVec.java @@ -0,0 +1,46 @@ +package org.stellar.sdk.scval; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import lombok.EqualsAndHashCode; +import lombok.NonNull; +import lombok.RequiredArgsConstructor; +import lombok.Value; +import org.stellar.sdk.xdr.SCVal; +import org.stellar.sdk.xdr.SCValType; +import org.stellar.sdk.xdr.SCVec; + +@Value +@RequiredArgsConstructor +@EqualsAndHashCode(callSuper = false) +public class ScvVec extends Scv { + private static final SCValType TYPE = SCValType.SCV_VEC; + + @NonNull List value; + + @Override + public SCVal toSCVal() { + return new SCVal.Builder() + .discriminant(TYPE) + .vec(new SCVec(value.stream().map(Scv::toSCVal).toArray(SCVal[]::new))) + .build(); + } + + @Override + public SCValType getSCValType() { + return TYPE; + } + + public static ScvVec fromSCVal(SCVal scVal) { + if (scVal.getDiscriminant() != TYPE) { + throw new IllegalArgumentException( + String.format( + "invalid scVal type, expected %s, but got %s", TYPE, scVal.getDiscriminant())); + } + + List scValList = Arrays.asList(scVal.getVec().getSCVec()); + List value = scValList.stream().map(Scv::fromSCVal).collect(Collectors.toList()); + return new ScvVec(value); + } +} diff --git a/src/main/java/org/stellar/sdk/scval/ScvVoid.java b/src/main/java/org/stellar/sdk/scval/ScvVoid.java new file mode 100644 index 000000000..d2783e0ac --- /dev/null +++ b/src/main/java/org/stellar/sdk/scval/ScvVoid.java @@ -0,0 +1,29 @@ +package org.stellar.sdk.scval; + +import lombok.EqualsAndHashCode; +import org.stellar.sdk.xdr.SCVal; +import org.stellar.sdk.xdr.SCValType; + +@EqualsAndHashCode(callSuper = false) +public class ScvVoid extends Scv { + private static final SCValType TYPE = SCValType.SCV_VOID; + + @Override + public SCVal toSCVal() { + return new SCVal.Builder().discriminant(TYPE).build(); + } + + @Override + public SCValType getSCValType() { + return TYPE; + } + + public static ScvVoid fromSCVal(SCVal scVal) { + if (scVal.getDiscriminant() != TYPE) { + throw new IllegalArgumentException( + String.format( + "invalid scVal type, expected %s, but got %s", TYPE, scVal.getDiscriminant())); + } + return new ScvVoid(); + } +} diff --git a/src/test/java/org/stellar/sdk/DemoTest.java b/src/test/java/org/stellar/sdk/DemoTest.java new file mode 100644 index 000000000..12bf2f697 --- /dev/null +++ b/src/test/java/org/stellar/sdk/DemoTest.java @@ -0,0 +1,45 @@ +package org.stellar.sdk; + +import com.google.common.io.BaseEncoding; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import org.junit.Test; +import org.stellar.sdk.xdr.XdrDataInputStream; +import org.stellar.sdk.xdr.XdrDataOutputStream; +import org.stellar.sdk.xdr.XdrUnsignedInteger; + +public class DemoTest { + public static String xdrToSorobanTransactionData(XdrUnsignedInteger sorobanData) { + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + XdrDataOutputStream xdrDataOutputStream = new XdrDataOutputStream(byteArrayOutputStream); + try { + sorobanData.encode(xdrDataOutputStream); + } catch (IOException e) { + throw new IllegalArgumentException("invalid sorobanData.", e); + } + BaseEncoding base64Encoding = BaseEncoding.base64(); + return base64Encoding.encode(byteArrayOutputStream.toByteArray()); + } + + public static XdrUnsignedInteger sorobanTransactionDataToXDR(String sorobanData) { + BaseEncoding base64Encoding = BaseEncoding.base64(); + byte[] bytes = base64Encoding.decode(sorobanData); + ByteArrayInputStream inputStream = new ByteArrayInputStream(bytes); + XdrDataInputStream xdrInputStream = new XdrDataInputStream(inputStream); + try { + return XdrUnsignedInteger.decode(xdrInputStream); + } catch (IOException e) { + throw new IllegalArgumentException("invalid sorobanData: " + sorobanData, e); + } + } + + @Test + public void test() { + Long x = 4294967295L; + System.out.println(x); + XdrUnsignedInteger xdrUnsignedInteger = new XdrUnsignedInteger(x); + String xdr = (xdrToSorobanTransactionData(xdrUnsignedInteger)); + System.out.println(sorobanTransactionDataToXDR(xdr).equals(xdrUnsignedInteger)); + } +} diff --git a/src/test/java/org/stellar/sdk/InvokeHostFunctionOperationTest.java b/src/test/java/org/stellar/sdk/InvokeHostFunctionOperationTest.java index c241e7147..2efa74d50 100644 --- a/src/test/java/org/stellar/sdk/InvokeHostFunctionOperationTest.java +++ b/src/test/java/org/stellar/sdk/InvokeHostFunctionOperationTest.java @@ -9,6 +9,7 @@ import java.util.Collections; import java.util.List; import org.junit.Test; +import org.stellar.sdk.scval.ScvAddress; import org.stellar.sdk.xdr.ContractExecutable; import org.stellar.sdk.xdr.ContractExecutableType; import org.stellar.sdk.xdr.ContractIDPreimage; @@ -43,7 +44,7 @@ public class InvokeHostFunctionOperationTest { .fromAddress( new ContractIDPreimage.ContractIDPreimageFromAddress.Builder() .address( - new Address( + new ScvAddress( "GB7TAYRUZGE6TVT7NHP5SMIZRNQA6PLM423EYISAOAP3MKYIQMVYP2JO") .toSCAddress()) .salt(new Uint256(new byte[32])) @@ -172,7 +173,7 @@ public void testNotEqualsHostFunction() { .fromAddress( new ContractIDPreimage.ContractIDPreimageFromAddress.Builder() .address( - new Address( + new ScvAddress( "GAHJJJKMOKYE4RVPZEWZTKH5FVI4PA3VL7GK2LFNUBSGBV6OJP7TQSLX") .toSCAddress()) .salt(new Uint256(new byte[32])) @@ -212,7 +213,7 @@ public void testNotEqualsAuth() { .address( new SorobanAddressCredentials.Builder() .address( - new Address( + new ScvAddress( "GASOCNHNNLYFNMDJYQ3XFMI7BYHIOCFW3GJEOWRPEGK2TDPGTG2E5EDW") .toSCAddress()) .nonce(new Int64(123123432L)) @@ -316,7 +317,7 @@ public void createContractOperationBuilderWithWasmIdString() { 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }; - Address address = new Address("GAHJJJKMOKYE4RVPZEWZTKH5FVI4PA3VL7GK2LFNUBSGBV6OJP7TQSLX"); + ScvAddress address = new ScvAddress("GAHJJJKMOKYE4RVPZEWZTKH5FVI4PA3VL7GK2LFNUBSGBV6OJP7TQSLX"); InvokeHostFunctionOperation operation = InvokeHostFunctionOperation.createContractOperationBuilder(wasmIdString, address, salt) .build(); @@ -366,7 +367,7 @@ public void createContractOperationBuilderWithWasmIdBytes() { 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f }; - Address address = new Address("GAHJJJKMOKYE4RVPZEWZTKH5FVI4PA3VL7GK2LFNUBSGBV6OJP7TQSLX"); + ScvAddress address = new ScvAddress("GAHJJJKMOKYE4RVPZEWZTKH5FVI4PA3VL7GK2LFNUBSGBV6OJP7TQSLX"); InvokeHostFunctionOperation operation = InvokeHostFunctionOperation.createContractOperationBuilder(wasmId, address, salt).build(); @@ -403,7 +404,7 @@ public void createContractOperationBuilderWithWasmIdBytes() { @Test public void createTokenContractOperationBuilderWithAddress() { - Address address = new Address("GAHJJJKMOKYE4RVPZEWZTKH5FVI4PA3VL7GK2LFNUBSGBV6OJP7TQSLX"); + ScvAddress address = new ScvAddress("GAHJJJKMOKYE4RVPZEWZTKH5FVI4PA3VL7GK2LFNUBSGBV6OJP7TQSLX"); byte[] salt = new byte[] { 0x11, 0x33, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, @@ -490,7 +491,7 @@ public void invokeContractFunctionOperationBuilder() { contractId, funcName, parameters) .build(); - SCVal contractIdScVal = new Address(contractId).toSCVal(); + SCVal contractIdScVal = new ScvAddress(contractId).toSCVal(); SCVal functionNameScVal = new SCVal.Builder() .discriminant(SCValType.SCV_SYMBOL) diff --git a/src/test/java/org/stellar/sdk/SorobanServerTest.java b/src/test/java/org/stellar/sdk/SorobanServerTest.java index 7aae8ae34..7a9292847 100644 --- a/src/test/java/org/stellar/sdk/SorobanServerTest.java +++ b/src/test/java/org/stellar/sdk/SorobanServerTest.java @@ -39,6 +39,7 @@ import org.stellar.sdk.responses.sorobanrpc.GetNetworkResponse; import org.stellar.sdk.responses.sorobanrpc.SendTransactionResponse; import org.stellar.sdk.responses.sorobanrpc.SimulateTransactionResponse; +import org.stellar.sdk.scval.ScvAddress; import org.stellar.sdk.xdr.ContractDataDurability; import org.stellar.sdk.xdr.ContractEntryBodyType; import org.stellar.sdk.xdr.ContractExecutable; @@ -241,7 +242,7 @@ public void testGetContractData() throws IOException, SorobanRpcErrorResponse { public MockResponse dispatch(@NotNull RecordedRequest recordedRequest) throws InterruptedException { - Address address = new Address(contractId); + ScvAddress address = new ScvAddress(contractId); LedgerKey.LedgerKeyContractData ledgerKeyContractData = new LedgerKey.LedgerKeyContractData.Builder() .contract(address.toSCAddress()) @@ -311,7 +312,7 @@ public void testGetContractDataReturnNull() throws IOException, SorobanRpcErrorR public MockResponse dispatch(@NotNull RecordedRequest recordedRequest) throws InterruptedException { - Address address = new Address(contractId); + ScvAddress address = new ScvAddress(contractId); LedgerKey.LedgerKeyContractData ledgerKeyContractData = new LedgerKey.LedgerKeyContractData.Builder() .contract(address.toSCAddress()) @@ -1029,7 +1030,7 @@ public void testPrepareTransactionWithAuth() .fromAddress( new ContractIDPreimage.ContractIDPreimageFromAddress.Builder() .address( - new Address( + new ScvAddress( "GB7TAYRUZGE6TVT7NHP5SMIZRNQA6PLM423EYISAOAP3MKYIQMVYP2JO") .toSCAddress()) .salt(new Uint256(new byte[32])) @@ -1375,12 +1376,12 @@ private Transaction buildSorobanTransaction( .invokeContract( new SCVec( new SCVal[] { - new Address(contractId).toSCVal(), + new ScvAddress(contractId).toSCVal(), new SCVal.Builder() .discriminant(SCValType.SCV_SYMBOL) .sym(new SCSymbol(new XdrString("increment"))) .build(), - new Address(opInvokerKp.getAccountId()).toSCVal(), + new ScvAddress(opInvokerKp.getAccountId()).toSCVal(), new SCVal.Builder() .discriminant(SCValType.SCV_U32) .u32(new Uint32(new XdrUnsignedInteger(10))) diff --git a/src/test/java/org/stellar/sdk/TransactionBuilderTest.java b/src/test/java/org/stellar/sdk/TransactionBuilderTest.java index 2e6ca7f84..b13dbafc4 100644 --- a/src/test/java/org/stellar/sdk/TransactionBuilderTest.java +++ b/src/test/java/org/stellar/sdk/TransactionBuilderTest.java @@ -8,6 +8,7 @@ import java.io.IOException; import java.math.BigInteger; import org.junit.Test; +import org.stellar.sdk.scval.ScvAddress; import org.stellar.sdk.xdr.*; public class TransactionBuilderTest { @@ -1112,7 +1113,7 @@ public void voidBuilderSorobanDataXdrObject() { .fromAddress( new ContractIDPreimage.ContractIDPreimageFromAddress.Builder() .address( - new Address( + new ScvAddress( "GB7TAYRUZGE6TVT7NHP5SMIZRNQA6PLM423EYISAOAP3MKYIQMVYP2JO") .toSCAddress()) .salt(new Uint256(new byte[32])) diff --git a/src/test/java/org/stellar/sdk/TransactionTest.java b/src/test/java/org/stellar/sdk/TransactionTest.java index a121ea898..11122412c 100644 --- a/src/test/java/org/stellar/sdk/TransactionTest.java +++ b/src/test/java/org/stellar/sdk/TransactionTest.java @@ -13,6 +13,7 @@ import java.util.ArrayList; import java.util.Arrays; import org.junit.Test; +import org.stellar.sdk.scval.ScvAddress; import org.stellar.sdk.xdr.*; public class TransactionTest { @@ -220,7 +221,7 @@ public void testConstructorWithSorobanData() throws IOException { .fromAddress( new ContractIDPreimage.ContractIDPreimageFromAddress.Builder() .address( - new Address( + new ScvAddress( "GB7TAYRUZGE6TVT7NHP5SMIZRNQA6PLM423EYISAOAP3MKYIQMVYP2JO") .toSCAddress()) .salt(new Uint256(new byte[32])) diff --git a/src/test/java/org/stellar/sdk/AddressTest.java b/src/test/java/org/stellar/sdk/scval/ScvAddressTest.java similarity index 77% rename from src/test/java/org/stellar/sdk/AddressTest.java rename to src/test/java/org/stellar/sdk/scval/ScvAddressTest.java index 28e843fdb..9cc153e30 100644 --- a/src/test/java/org/stellar/sdk/AddressTest.java +++ b/src/test/java/org/stellar/sdk/scval/ScvAddressTest.java @@ -1,4 +1,4 @@ -package org.stellar.sdk; +package org.stellar.sdk.scval; import static junit.framework.TestCase.assertEquals; import static org.junit.Assert.fail; @@ -8,32 +8,34 @@ import java.io.IOException; import org.junit.Assert; import org.junit.Test; +import org.stellar.sdk.StrKey; import org.stellar.sdk.xdr.SCAddress; import org.stellar.sdk.xdr.SCVal; +import org.stellar.sdk.xdr.SCValType; import org.stellar.sdk.xdr.XdrDataInputStream; -public class AddressTest { +public class ScvAddressTest { @Test public void testConstructorAccountId() { String accountId = "GA7QYNF7SOWQ3GLR2BGMZEHXAVIRZA4KVWLTJJFC7MGXUA74P7UJVSGZ"; - Address address = new Address(accountId); + ScvAddress address = new ScvAddress(accountId); assertEquals(address.toString(), accountId); - assertEquals(address.getType(), Address.AddressType.ACCOUNT); + assertEquals(address.getAddressType(), ScvAddress.AddressType.ACCOUNT); } @Test public void testConstructorContractId() { String contractId = "CA7QYNF7SOWQ3GLR2BGMZEHXAVIRZA4KVWLTJJFC7MGXUA74P7UJUWDA"; - Address address = new Address(contractId); + ScvAddress address = new ScvAddress(contractId); assertEquals(address.toString(), contractId); - assertEquals(address.getType(), Address.AddressType.CONTRACT); + assertEquals(address.getAddressType(), ScvAddress.AddressType.CONTRACT); } @Test public void testConstructorInvalidAddressThrows() { String accountId = "GINVALID"; try { - new Address(accountId); + new ScvAddress(accountId); fail(); } catch (IllegalArgumentException e) { Assert.assertEquals("Unsupported address type", e.getMessage()); @@ -44,7 +46,7 @@ public void testConstructorInvalidAddressThrows() { public void testConstructorSecretThrows() { String secret = "SBUIAXRYKAEJWBSJZYE6P4N4X4ATXP5GAFK5TZ6SKKQ6TS4MLX6G6E4M"; try { - new Address(secret); + new ScvAddress(secret); fail(); } catch (IllegalArgumentException e) { Assert.assertEquals("Unsupported address type", e.getMessage()); @@ -55,24 +57,24 @@ public void testConstructorSecretThrows() { public void testFromAccountByte() { String accountId = "GA7QYNF7SOWQ3GLR2BGMZEHXAVIRZA4KVWLTJJFC7MGXUA74P7UJVSGZ"; byte[] accountIdBytes = StrKey.decodeStellarAccountId(accountId); - Address address = Address.fromAccount(accountIdBytes); + ScvAddress address = ScvAddress.fromAccount(accountIdBytes); assertEquals(address.toString(), accountId); - assertEquals(address.getType(), Address.AddressType.ACCOUNT); + assertEquals(address.getAddressType(), ScvAddress.AddressType.ACCOUNT); } @Test public void testFromContractByte() { String contractId = "CA7QYNF7SOWQ3GLR2BGMZEHXAVIRZA4KVWLTJJFC7MGXUA74P7UJUWDA"; byte[] contractIdBytes = StrKey.decodeContractId(contractId); - Address address = Address.fromContract(contractIdBytes); + ScvAddress address = ScvAddress.fromContract(contractIdBytes); assertEquals(address.toString(), contractId); - assertEquals(address.getType(), Address.AddressType.CONTRACT); + assertEquals(address.getAddressType(), ScvAddress.AddressType.CONTRACT); } @Test public void testToSCAddressAccount() throws IOException { String accountId = "GA7QYNF7SOWQ3GLR2BGMZEHXAVIRZA4KVWLTJJFC7MGXUA74P7UJVSGZ"; - Address address = new Address(accountId); + ScvAddress address = new ScvAddress(accountId); SCAddress scAddress = address.toSCAddress(); String xdr = "AAAAAAAAAAA/DDS/k60NmXHQTMyQ9wVRHIOKrZc0pKL7DXoD/H/omg=="; @@ -86,7 +88,7 @@ public void testToSCAddressAccount() throws IOException { @Test public void testToSCAddressContract() throws IOException { String contract = "CA7QYNF7SOWQ3GLR2BGMZEHXAVIRZA4KVWLTJJFC7MGXUA74P7UJUWDA"; - Address address = new Address(contract); + ScvAddress address = new ScvAddress(contract); SCAddress scAddress = address.toSCAddress(); String xdr = "AAAAAT8MNL+TrQ2ZcdBMzJD3BVEcg4qtlzSkovsNegP8f+ia"; @@ -104,10 +106,10 @@ public void testFromSCAddressAccount() throws IOException { byte[] bytes = base64Encoding.decode(xdr); SCAddress scAddress = SCAddress.decode(new XdrDataInputStream(new ByteArrayInputStream(bytes))); - Address address = Address.fromSCAddress(scAddress); + ScvAddress address = ScvAddress.fromSCAddress(scAddress); String accountId = "GA7QYNF7SOWQ3GLR2BGMZEHXAVIRZA4KVWLTJJFC7MGXUA74P7UJVSGZ"; assertEquals(address.toString(), accountId); - assertEquals(address.getType(), Address.AddressType.ACCOUNT); + assertEquals(address.getAddressType(), ScvAddress.AddressType.ACCOUNT); } @Test @@ -117,16 +119,16 @@ public void testFromSCAddressContract() throws IOException { byte[] bytes = base64Encoding.decode(xdr); SCAddress scAddress = SCAddress.decode(new XdrDataInputStream(new ByteArrayInputStream(bytes))); - Address address = Address.fromSCAddress(scAddress); + ScvAddress address = ScvAddress.fromSCAddress(scAddress); String contract = "CA7QYNF7SOWQ3GLR2BGMZEHXAVIRZA4KVWLTJJFC7MGXUA74P7UJUWDA"; assertEquals(address.toString(), contract); - assertEquals(address.getType(), Address.AddressType.CONTRACT); + assertEquals(address.getAddressType(), ScvAddress.AddressType.CONTRACT); } @Test public void testToSCVal() throws IOException { String contract = "CA7QYNF7SOWQ3GLR2BGMZEHXAVIRZA4KVWLTJJFC7MGXUA74P7UJUWDA"; - Address address = new Address(contract); + ScvAddress address = new ScvAddress(contract); SCVal scVal = address.toSCVal(); String xdr = "AAAAEgAAAAE/DDS/k60NmXHQTMyQ9wVRHIOKrZc0pKL7DXoD/H/omg=="; @@ -134,6 +136,7 @@ public void testToSCVal() throws IOException { byte[] bytes = base64Encoding.decode(xdr); SCVal expectSCVal = SCVal.decode(new XdrDataInputStream(new ByteArrayInputStream(bytes))); assertEquals(scVal, expectSCVal); + assertEquals(address.getSCValType(), SCValType.SCV_ADDRESS); } @Test @@ -143,23 +146,23 @@ public void testFromSCVal() throws IOException { byte[] bytes = base64Encoding.decode(xdr); SCVal scVal = SCVal.decode(new XdrDataInputStream(new ByteArrayInputStream(bytes))); - Address address = Address.fromSCVal(scVal); + ScvAddress address = ScvAddress.fromSCVal(scVal); String contract = "CA7QYNF7SOWQ3GLR2BGMZEHXAVIRZA4KVWLTJJFC7MGXUA74P7UJUWDA"; assertEquals(address.toString(), contract); - assertEquals(address.getType(), Address.AddressType.CONTRACT); + assertEquals(address.getAddressType(), ScvAddress.AddressType.CONTRACT); } @Test public void testToStringAccountId() { String accountId = "GA7QYNF7SOWQ3GLR2BGMZEHXAVIRZA4KVWLTJJFC7MGXUA74P7UJVSGZ"; - Address address = new Address(accountId); + ScvAddress address = new ScvAddress(accountId); assertEquals(address.toString(), accountId); } @Test public void testToStringContractId() { String contractId = "CA7QYNF7SOWQ3GLR2BGMZEHXAVIRZA4KVWLTJJFC7MGXUA74P7UJUWDA"; - Address address = new Address(contractId); + ScvAddress address = new ScvAddress(contractId); assertEquals(address.toString(), contractId); } } diff --git a/src/test/java/org/stellar/sdk/scval/ScvBooleanTest.java b/src/test/java/org/stellar/sdk/scval/ScvBooleanTest.java new file mode 100644 index 000000000..f8717f3d4 --- /dev/null +++ b/src/test/java/org/stellar/sdk/scval/ScvBooleanTest.java @@ -0,0 +1,24 @@ +package org.stellar.sdk.scval; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; +import org.stellar.sdk.xdr.SCVal; +import org.stellar.sdk.xdr.SCValType; + +public class ScvBooleanTest { + @Test + public void testScvBoolean() { + ScvBoolean scvBoolean = new ScvBoolean(true); + SCVal scVal = scvBoolean.toSCVal(); + + assertEquals(scvBoolean.getSCValType(), SCValType.SCV_BOOL); + assertEquals(scvBoolean.getValue(), true); + + assertEquals(ScvBoolean.fromSCVal(scVal), scvBoolean); + assertEquals(Scv.fromSCVal(scVal), scvBoolean); + + SCVal expectedScVal = new SCVal.Builder().discriminant(SCValType.SCV_BOOL).b(true).build(); + assertEquals(expectedScVal, scVal); + } +} diff --git a/src/test/java/org/stellar/sdk/scval/ScvBytesTest.java b/src/test/java/org/stellar/sdk/scval/ScvBytesTest.java new file mode 100644 index 000000000..aa19cea14 --- /dev/null +++ b/src/test/java/org/stellar/sdk/scval/ScvBytesTest.java @@ -0,0 +1,27 @@ +package org.stellar.sdk.scval; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; +import org.stellar.sdk.xdr.SCBytes; +import org.stellar.sdk.xdr.SCVal; +import org.stellar.sdk.xdr.SCValType; + +public class ScvBytesTest { + @Test + public void testScvBytes() { + byte[] data = new byte[] {0x01, 0x02, 0x03}; + ScvBytes scvBytes = new ScvBytes(data); + SCVal scVal = scvBytes.toSCVal(); + + assertEquals(scvBytes.getSCValType(), SCValType.SCV_BYTES); + assertEquals(scvBytes.getValue(), data); + + assertEquals(ScvBytes.fromSCVal(scVal), scvBytes); + assertEquals(Scv.fromSCVal(scVal), scvBytes); + + SCVal expectedScVal = + new SCVal.Builder().discriminant(SCValType.SCV_BYTES).bytes(new SCBytes(data)).build(); + assertEquals(expectedScVal, scVal); + } +} diff --git a/src/test/java/org/stellar/sdk/scval/ScvContractInstanceTest.java b/src/test/java/org/stellar/sdk/scval/ScvContractInstanceTest.java new file mode 100644 index 000000000..ec556b54b --- /dev/null +++ b/src/test/java/org/stellar/sdk/scval/ScvContractInstanceTest.java @@ -0,0 +1,23 @@ +package org.stellar.sdk.scval; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; +import org.stellar.sdk.xdr.SCVal; +import org.stellar.sdk.xdr.SCValType; + +public class ScvContractInstanceTest { + @Test + public void testScvContractInstance() { + ScvContractInstance scvContractInstance = new ScvContractInstance(); + SCVal scVal = scvContractInstance.toSCVal(); + + assertEquals(scvContractInstance.getSCValType(), SCValType.SCV_CONTRACT_INSTANCE); + + assertEquals(ScvContractInstance.fromSCVal(scVal), scvContractInstance); + assertEquals(Scv.fromSCVal(scVal), scvContractInstance); + + SCVal expectedScVal = new SCVal.Builder().discriminant(SCValType.SCV_CONTRACT_INSTANCE).build(); + assertEquals(expectedScVal, scVal); + } +} diff --git a/src/test/java/org/stellar/sdk/scval/ScvDurationTest.java b/src/test/java/org/stellar/sdk/scval/ScvDurationTest.java new file mode 100644 index 000000000..9c0734e5e --- /dev/null +++ b/src/test/java/org/stellar/sdk/scval/ScvDurationTest.java @@ -0,0 +1,65 @@ +package org.stellar.sdk.scval; + +import static org.junit.Assert.assertEquals; + +import java.math.BigInteger; +import org.junit.Test; +import org.stellar.sdk.xdr.Duration; +import org.stellar.sdk.xdr.SCVal; +import org.stellar.sdk.xdr.SCValType; +import org.stellar.sdk.xdr.Uint64; +import org.stellar.sdk.xdr.XdrUnsignedHyperInteger; + +public class ScvDurationTest { + @Test + public void testScvDurationMax() { + BigInteger value = ScvDuration.MAX_VALUE; + ScvDuration scvDuration = new ScvDuration(value); + SCVal scVal = scvDuration.toSCVal(); + + assertEquals(scvDuration.getSCValType(), SCValType.SCV_DURATION); + assertEquals(scvDuration.getValue(), XdrUnsignedHyperInteger.MAX_VALUE); + + assertEquals(ScvDuration.fromSCVal(scVal), scvDuration); + assertEquals(Scv.fromSCVal(scVal), scvDuration); + + SCVal expectedScVal = + new SCVal.Builder() + .discriminant(SCValType.SCV_DURATION) + .duration(new Duration(new Uint64(new XdrUnsignedHyperInteger(value)))) + .build(); + assertEquals(expectedScVal, scVal); + } + + @Test + public void testScvDurationMin() { + BigInteger value = ScvDuration.MIN_VALUE; + ScvDuration scvDuration = new ScvDuration(value); + SCVal scVal = scvDuration.toSCVal(); + + assertEquals(scvDuration.getSCValType(), SCValType.SCV_DURATION); + assertEquals(scvDuration.getValue(), XdrUnsignedHyperInteger.MIN_VALUE); + + assertEquals(ScvDuration.fromSCVal(scVal), scvDuration); + assertEquals(Scv.fromSCVal(scVal), scvDuration); + + SCVal expectedScVal = + new SCVal.Builder() + .discriminant(SCValType.SCV_DURATION) + .duration(new Duration(new Uint64(new XdrUnsignedHyperInteger(value)))) + .build(); + assertEquals(expectedScVal, scVal); + } + + @Test(expected = IllegalArgumentException.class) + public void testScvDurationMoreThanMaxThrows() { + BigInteger value = ScvDuration.MAX_VALUE.add(BigInteger.ONE); + new ScvDuration(value); + } + + @Test(expected = IllegalArgumentException.class) + public void testScvDurationLessThanMinThrows() { + BigInteger value = ScvDuration.MIN_VALUE.subtract(BigInteger.ONE); + new ScvDuration(value); + } +} diff --git a/src/test/java/org/stellar/sdk/scval/ScvErrorTest.java b/src/test/java/org/stellar/sdk/scval/ScvErrorTest.java new file mode 100644 index 000000000..2a8938023 --- /dev/null +++ b/src/test/java/org/stellar/sdk/scval/ScvErrorTest.java @@ -0,0 +1,35 @@ +package org.stellar.sdk.scval; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; +import org.stellar.sdk.xdr.SCError; +import org.stellar.sdk.xdr.SCErrorCode; +import org.stellar.sdk.xdr.SCErrorType; +import org.stellar.sdk.xdr.SCVal; +import org.stellar.sdk.xdr.SCValType; + +public class ScvErrorTest { + @Test + public void testScvError() { + SCErrorType errorType = SCErrorType.SCE_CONTEXT; + SCErrorCode errorCode = SCErrorCode.SCEC_UNEXPECTED_TYPE; + + ScvError scvError = new ScvError(errorType, errorCode); + SCVal scVal = scvError.toSCVal(); + + assertEquals(scvError.getSCValType(), SCValType.SCV_ERROR); + assertEquals(scvError.getErrorCode(), errorCode); + assertEquals(scvError.getErrorType(), errorType); + + assertEquals(ScvError.fromSCVal(scVal), scvError); + assertEquals(Scv.fromSCVal(scVal), scvError); + + SCVal expectedScVal = + new SCVal.Builder() + .discriminant(SCValType.SCV_ERROR) + .error(new SCError.Builder().code(errorCode).type(errorType).build()) + .build(); + assertEquals(expectedScVal, scVal); + } +} diff --git a/src/test/java/org/stellar/sdk/scval/ScvInt128Test.java b/src/test/java/org/stellar/sdk/scval/ScvInt128Test.java new file mode 100644 index 000000000..494d9e7bd --- /dev/null +++ b/src/test/java/org/stellar/sdk/scval/ScvInt128Test.java @@ -0,0 +1,141 @@ +package org.stellar.sdk.scval; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.math.BigInteger; +import java.util.Arrays; +import java.util.List; +import lombok.AllArgsConstructor; +import lombok.Value; +import org.junit.Test; +import org.stellar.sdk.xdr.Int128Parts; +import org.stellar.sdk.xdr.SCVal; +import org.stellar.sdk.xdr.SCValType; +import org.stellar.sdk.xdr.XdrDataOutputStream; + +public class ScvInt128Test { + + @Test + public void testScvInt128() { + List values = + Arrays.asList( + new TestCase( + BigInteger.ZERO, new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}), + new TestCase( + BigInteger.valueOf(1), new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}), + new TestCase( + BigInteger.valueOf(-1), + new byte[] { + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff + }), + new TestCase( + BigInteger.valueOf(2L).pow(64), + new byte[] {0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}), + new TestCase( + BigInteger.valueOf(2L).pow(64).negate(), + new byte[] { + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + }), + new TestCase( + ScvInt128.MAX_VALUE, + new byte[] { + (byte) 0x7f, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff + }), + new TestCase( + ScvInt128.MIN_VALUE, + new byte[] {(byte) 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0})); + + for (TestCase value : values) { + checkScvInt128(value); + } + } + + @Test(expected = IllegalArgumentException.class) + public void testScvInt128GreaterThanMaxValueThrows() { + new ScvInt128(ScvInt128.MAX_VALUE.add(BigInteger.ONE)); + } + + @Test(expected = IllegalArgumentException.class) + public void testScvInt128LessThanMinValueThrows() { + new ScvInt128(ScvInt128.MIN_VALUE.subtract(BigInteger.ONE)); + } + + private void checkScvInt128(TestCase value) { + ScvInt128 scvInt128 = new ScvInt128(value.v); + SCVal scVal = scvInt128.toSCVal(); + + assertEquals(scvInt128.getSCValType(), SCValType.SCV_I128); + assertEquals(scvInt128.getValue(), value.v); + + assertEquals(ScvInt128.fromSCVal(scVal), scvInt128); + assertEquals(Scv.fromSCVal(scVal), scvInt128); + + assertArrayEquals(getInt128PartsBytes(scVal.getI128()), value.getExpectedBytes()); + } + + private byte[] getInt128PartsBytes(Int128Parts int128Parts) { + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + XdrDataOutputStream xdrDataOutputStream = new XdrDataOutputStream(byteArrayOutputStream); + try { + int128Parts.encode(xdrDataOutputStream); + } catch (IOException e) { + throw new IllegalArgumentException("invalid int128Parts.", e); + } + return byteArrayOutputStream.toByteArray(); + } + + @Value + @AllArgsConstructor + private static class TestCase { + BigInteger v; + byte[] expectedBytes; + } +} diff --git a/src/test/java/org/stellar/sdk/scval/ScvInt256Test.java b/src/test/java/org/stellar/sdk/scval/ScvInt256Test.java new file mode 100644 index 000000000..3f9f1e0f0 --- /dev/null +++ b/src/test/java/org/stellar/sdk/scval/ScvInt256Test.java @@ -0,0 +1,324 @@ +package org.stellar.sdk.scval; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.math.BigInteger; +import java.util.Arrays; +import java.util.List; +import lombok.AllArgsConstructor; +import lombok.Value; +import org.junit.Test; +import org.stellar.sdk.xdr.Int256Parts; +import org.stellar.sdk.xdr.SCVal; +import org.stellar.sdk.xdr.SCValType; +import org.stellar.sdk.xdr.XdrDataOutputStream; + +public class ScvInt256Test { + + @Test + public void testScvInt256() { + List values = + Arrays.asList( + new TestCase(BigInteger.ZERO, new byte[32]), + new TestCase( + BigInteger.valueOf(1), + new byte[] { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1 + }), + new TestCase( + BigInteger.valueOf(-1), + new byte[] { + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff + }), + new TestCase( + BigInteger.valueOf(2L).pow(64), + new byte[] { + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x1, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0 + }), + new TestCase( + BigInteger.valueOf(2L).pow(64).negate(), + new byte[] { + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0x0, + (byte) 0x0, + (byte) 0x0, + (byte) 0x0, + (byte) 0x0, + (byte) 0x0, + (byte) 0x0, + (byte) 0x0 + }), + new TestCase( + BigInteger.valueOf(2L).pow(128), + new byte[] { + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x1, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0 + }), + new TestCase( + BigInteger.valueOf(2L).pow(128).negate(), + new byte[] { + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0x0, + (byte) 0x0, + (byte) 0x0, + (byte) 0x0, + (byte) 0x0, + (byte) 0x0, + (byte) 0x0, + (byte) 0x0, + (byte) 0x0, + (byte) 0x0, + (byte) 0x0, + (byte) 0x0, + (byte) 0x0, + (byte) 0x0, + (byte) 0x0, + (byte) 0x0 + }), + new TestCase( + BigInteger.valueOf(2L).pow(192), + new byte[] { + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x1, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, (byte) 0x0, + (byte) 0x0, (byte) 0x0 + }), + new TestCase( + BigInteger.valueOf(2L).pow(192).negate(), + new byte[] { + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0x0, + (byte) 0x0, + (byte) 0x0, + (byte) 0x0, + (byte) 0x0, + (byte) 0x0, + (byte) 0x0, + (byte) 0x0, + (byte) 0x0, + (byte) 0x0, + (byte) 0x0, + (byte) 0x0, + (byte) 0x0, + (byte) 0x0, + (byte) 0x0, + (byte) 0x0, + (byte) 0x0, + (byte) 0x0, + (byte) 0x0, + (byte) 0x0, + (byte) 0x0, + (byte) 0x0, + (byte) 0x0, + (byte) 0x0 + }), + new TestCase( + ScvInt256.MAX_VALUE, + new byte[] { + (byte) 0x7f, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + }), + new TestCase( + ScvInt256.MIN_VALUE, + new byte[] { + (byte) 0x80, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0, + 0 + })); + + for (TestCase value : values) { + checkScvInt256(value); + } + } + + @Test(expected = IllegalArgumentException.class) + public void testScvInt256GreaterThanMaxValueThrows() { + new ScvInt256(ScvInt256.MAX_VALUE.add(BigInteger.ONE)); + } + + @Test(expected = IllegalArgumentException.class) + public void testScvInt256LessThanMinValueThrows() { + new ScvInt256(ScvInt256.MIN_VALUE.subtract(BigInteger.ONE)); + } + + private void checkScvInt256(TestCase value) { + ScvInt256 scvInt256 = new ScvInt256(value.v); + SCVal scVal = scvInt256.toSCVal(); + + assertEquals(scvInt256.getSCValType(), SCValType.SCV_I256); + assertEquals(scvInt256.getValue(), value.v); + + assertEquals(ScvInt256.fromSCVal(scVal), scvInt256); + assertEquals(Scv.fromSCVal(scVal), scvInt256); + + assertArrayEquals(getInt256PartsBytes(scVal.getI256()), value.getExpectedBytes()); + } + + private byte[] getInt256PartsBytes(Int256Parts int256Parts) { + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + XdrDataOutputStream xdrDataOutputStream = new XdrDataOutputStream(byteArrayOutputStream); + try { + int256Parts.encode(xdrDataOutputStream); + } catch (IOException e) { + throw new IllegalArgumentException("invalid int256Parts.", e); + } + return byteArrayOutputStream.toByteArray(); + } + + @Value + @AllArgsConstructor + private static class TestCase { + BigInteger v; + byte[] expectedBytes; + } +} diff --git a/src/test/java/org/stellar/sdk/scval/ScvInt32Test.java b/src/test/java/org/stellar/sdk/scval/ScvInt32Test.java new file mode 100644 index 000000000..05ec61da8 --- /dev/null +++ b/src/test/java/org/stellar/sdk/scval/ScvInt32Test.java @@ -0,0 +1,27 @@ +package org.stellar.sdk.scval; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; +import org.stellar.sdk.xdr.Int32; +import org.stellar.sdk.xdr.SCVal; +import org.stellar.sdk.xdr.SCValType; + +public class ScvInt32Test { + @Test + public void testScvInt32() { + int value = -234; + ScvInt32 scvInt32 = new ScvInt32(value); + SCVal scVal = scvInt32.toSCVal(); + + assertEquals(scvInt32.getSCValType(), SCValType.SCV_I32); + assertEquals(scvInt32.getValue(), value); + + assertEquals(ScvInt32.fromSCVal(scVal), scvInt32); + assertEquals(Scv.fromSCVal(scVal), scvInt32); + + SCVal expectedScVal = + new SCVal.Builder().discriminant(SCValType.SCV_I32).i32(new Int32(value)).build(); + assertEquals(expectedScVal, scVal); + } +} diff --git a/src/test/java/org/stellar/sdk/scval/ScvLedgerKeyContractInstanceTest.java b/src/test/java/org/stellar/sdk/scval/ScvLedgerKeyContractInstanceTest.java new file mode 100644 index 000000000..bf1d48915 --- /dev/null +++ b/src/test/java/org/stellar/sdk/scval/ScvLedgerKeyContractInstanceTest.java @@ -0,0 +1,41 @@ +package org.stellar.sdk.scval; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; +import org.stellar.sdk.xdr.ContractExecutable; +import org.stellar.sdk.xdr.ContractExecutableType; +import org.stellar.sdk.xdr.SCContractInstance; +import org.stellar.sdk.xdr.SCVal; +import org.stellar.sdk.xdr.SCValType; + +public class ScvLedgerKeyContractInstanceTest { + @Test + public void testScvLedgerKeyContractInstance() { + SCContractInstance value = + new SCContractInstance.Builder() + .executable( + new ContractExecutable.Builder() + .discriminant(ContractExecutableType.CONTRACT_EXECUTABLE_TOKEN) + .build()) + .build(); + + ScvLedgerKeyContractInstance scvLedgerKeyContractInstance = + new ScvLedgerKeyContractInstance(value); + SCVal scVal = scvLedgerKeyContractInstance.toSCVal(); + + assertEquals( + scvLedgerKeyContractInstance.getSCValType(), SCValType.SCV_LEDGER_KEY_CONTRACT_INSTANCE); + assertEquals(scvLedgerKeyContractInstance.getValue(), value); + + assertEquals(ScvLedgerKeyContractInstance.fromSCVal(scVal), scvLedgerKeyContractInstance); + assertEquals(Scv.fromSCVal(scVal), scvLedgerKeyContractInstance); + + SCVal expectedScVal = + new SCVal.Builder() + .discriminant(SCValType.SCV_LEDGER_KEY_CONTRACT_INSTANCE) + .instance(value) + .build(); + assertEquals(expectedScVal, scVal); + } +} diff --git a/src/test/java/org/stellar/sdk/scval/ScvLedgerKeyNonceTest.java b/src/test/java/org/stellar/sdk/scval/ScvLedgerKeyNonceTest.java new file mode 100644 index 000000000..8fabf835e --- /dev/null +++ b/src/test/java/org/stellar/sdk/scval/ScvLedgerKeyNonceTest.java @@ -0,0 +1,31 @@ +package org.stellar.sdk.scval; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; +import org.stellar.sdk.xdr.Int64; +import org.stellar.sdk.xdr.SCNonceKey; +import org.stellar.sdk.xdr.SCVal; +import org.stellar.sdk.xdr.SCValType; + +public class ScvLedgerKeyNonceTest { + @Test + public void testScvLedgerKeyNonce() { + long value = 123456L; + ScvLedgerKeyNonce scvLedgerKeyNonce = new ScvLedgerKeyNonce(value); + SCVal scVal = scvLedgerKeyNonce.toSCVal(); + + assertEquals(scvLedgerKeyNonce.getSCValType(), SCValType.SCV_LEDGER_KEY_NONCE); + assertEquals(scvLedgerKeyNonce.getValue(), value); + + assertEquals(ScvLedgerKeyNonce.fromSCVal(scVal), scvLedgerKeyNonce); + assertEquals(Scv.fromSCVal(scVal), scvLedgerKeyNonce); + + SCVal expectedScVal = + new SCVal.Builder() + .discriminant(SCValType.SCV_LEDGER_KEY_NONCE) + .nonce_key(new SCNonceKey.Builder().nonce(new Int64(value)).build()) + .build(); + assertEquals(expectedScVal, scVal); + } +} diff --git a/src/test/java/org/stellar/sdk/scval/ScvMapTest.java b/src/test/java/org/stellar/sdk/scval/ScvMapTest.java new file mode 100644 index 000000000..e05089932 --- /dev/null +++ b/src/test/java/org/stellar/sdk/scval/ScvMapTest.java @@ -0,0 +1,53 @@ +package org.stellar.sdk.scval; + +import static org.junit.Assert.assertEquals; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import org.junit.Test; +import org.stellar.sdk.xdr.SCVal; +import org.stellar.sdk.xdr.SCValType; + +public class ScvMapTest { + @Test + public void testScvMap() { + Map value = new HashMap<>(); + value.put(new ScvSymbol("key1"), new ScvString("value1")); + value.put(new ScvString("key2"), new ScvInt32(123)); + + Map map = new HashMap<>(); + map.put(new ScvSymbol("mapKey1"), new ScvString("mapValue1")); + map.put(new ScvString("mapKey2"), new ScvInt32(23434)); + + value.put( + new ScvString("key3"), + new ScvVec( + Arrays.asList( + new ScvInt32(1), + new ScvInt32(2), + new ScvMap(map), + new ScvVec(Arrays.asList(new ScvBoolean(true), new ScvBoolean(false)))))); + + ScvMap scvMap = new ScvMap(value); + SCVal scVal = scvMap.toSCVal(); + + assertEquals(scvMap.getSCValType(), SCValType.SCV_MAP); + assertEquals(scvMap.getValue(), value); + + assertEquals(ScvMap.fromSCVal(scVal), scvMap); + assertEquals(Scv.fromSCVal(scVal), scvMap); + + assertEquals( + ScvMap.fromSCVal(scVal).getValue().get(new ScvSymbol("key1")), new ScvString("value1")); + assertEquals(ScvMap.fromSCVal(scVal).getValue().get(new ScvString("key2")), new ScvInt32(123)); + assertEquals( + ScvMap.fromSCVal(scVal).getValue().get(new ScvString("key3")), + new ScvVec( + Arrays.asList( + new ScvInt32(1), + new ScvInt32(2), + new ScvMap(map), + new ScvVec(Arrays.asList(new ScvBoolean(true), new ScvBoolean(false)))))); + } +} diff --git a/src/test/java/org/stellar/sdk/scval/ScvStringTest.java b/src/test/java/org/stellar/sdk/scval/ScvStringTest.java new file mode 100644 index 000000000..bcf7be037 --- /dev/null +++ b/src/test/java/org/stellar/sdk/scval/ScvStringTest.java @@ -0,0 +1,52 @@ +package org.stellar.sdk.scval; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; + +import org.junit.Test; +import org.stellar.sdk.xdr.SCString; +import org.stellar.sdk.xdr.SCVal; +import org.stellar.sdk.xdr.SCValType; +import org.stellar.sdk.xdr.XdrString; + +public class ScvStringTest { + @Test + public void testScvStringFromString() { + String value = "hello"; + ScvString scvString = new ScvString(value); + SCVal scVal = scvString.toSCVal(); + + assertEquals(scvString.getSCValType(), SCValType.SCV_STRING); + assertArrayEquals(scvString.getValue(), value.getBytes()); + + assertEquals(ScvString.fromSCVal(scVal), scvString); + assertEquals(Scv.fromSCVal(scVal), scvString); + + SCVal expectedScVal = + new SCVal.Builder() + .discriminant(SCValType.SCV_STRING) + .str(new SCString(new XdrString(value))) + .build(); + assertEquals(expectedScVal, scVal); + } + + @Test + public void testScvStringFromBytes() { + byte[] value = new byte[] {0, 1, 2, 3}; + ScvString scvString = new ScvString(value); + SCVal scVal = scvString.toSCVal(); + + assertEquals(scvString.getSCValType(), SCValType.SCV_STRING); + assertArrayEquals(scvString.getValue(), value); + + assertEquals(ScvString.fromSCVal(scVal), scvString); + assertEquals(Scv.fromSCVal(scVal), scvString); + + SCVal expectedScVal = + new SCVal.Builder() + .discriminant(SCValType.SCV_STRING) + .str(new SCString(new XdrString(value))) + .build(); + assertEquals(expectedScVal, scVal); + } +} diff --git a/src/test/java/org/stellar/sdk/scval/ScvSymbolTest.java b/src/test/java/org/stellar/sdk/scval/ScvSymbolTest.java new file mode 100644 index 000000000..5702cced6 --- /dev/null +++ b/src/test/java/org/stellar/sdk/scval/ScvSymbolTest.java @@ -0,0 +1,31 @@ +package org.stellar.sdk.scval; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; +import org.stellar.sdk.xdr.SCSymbol; +import org.stellar.sdk.xdr.SCVal; +import org.stellar.sdk.xdr.SCValType; +import org.stellar.sdk.xdr.XdrString; + +public class ScvSymbolTest { + @Test + public void testScvSymbol() { + String value = "hello"; + ScvSymbol scvSymbol = new ScvSymbol(value); + SCVal scVal = scvSymbol.toSCVal(); + + assertEquals(scvSymbol.getSCValType(), SCValType.SCV_SYMBOL); + assertEquals(scvSymbol.getValue(), value); + + assertEquals(ScvSymbol.fromSCVal(scVal), scvSymbol); + assertEquals(Scv.fromSCVal(scVal), scvSymbol); + + SCVal expectedScVal = + new SCVal.Builder() + .discriminant(SCValType.SCV_SYMBOL) + .sym(new SCSymbol(new XdrString(value))) + .build(); + assertEquals(expectedScVal, scVal); + } +} diff --git a/src/test/java/org/stellar/sdk/scval/ScvTimePointTest.java b/src/test/java/org/stellar/sdk/scval/ScvTimePointTest.java new file mode 100644 index 000000000..08b1e2e2a --- /dev/null +++ b/src/test/java/org/stellar/sdk/scval/ScvTimePointTest.java @@ -0,0 +1,65 @@ +package org.stellar.sdk.scval; + +import static org.junit.Assert.assertEquals; + +import java.math.BigInteger; +import org.junit.Test; +import org.stellar.sdk.xdr.SCVal; +import org.stellar.sdk.xdr.SCValType; +import org.stellar.sdk.xdr.TimePoint; +import org.stellar.sdk.xdr.Uint64; +import org.stellar.sdk.xdr.XdrUnsignedHyperInteger; + +public class ScvTimePointTest { + @Test + public void testScvTimePointMax() { + BigInteger value = ScvTimePoint.MAX_VALUE; + ScvTimePoint scvTimePoint = new ScvTimePoint(value); + SCVal scVal = scvTimePoint.toSCVal(); + + assertEquals(scvTimePoint.getSCValType(), SCValType.SCV_TIMEPOINT); + assertEquals(scvTimePoint.getValue(), value); + + assertEquals(ScvTimePoint.fromSCVal(scVal), scvTimePoint); + assertEquals(Scv.fromSCVal(scVal), scvTimePoint); + + SCVal expectedScVal = + new SCVal.Builder() + .discriminant(SCValType.SCV_TIMEPOINT) + .timepoint(new TimePoint(new Uint64(new XdrUnsignedHyperInteger(value)))) + .build(); + assertEquals(expectedScVal, scVal); + } + + @Test + public void testScvTimePointMin() { + BigInteger value = ScvTimePoint.MIN_VALUE; + ScvTimePoint scvTimePoint = new ScvTimePoint(value); + SCVal scVal = scvTimePoint.toSCVal(); + + assertEquals(scvTimePoint.getSCValType(), SCValType.SCV_TIMEPOINT); + assertEquals(scvTimePoint.getValue(), value); + + assertEquals(ScvTimePoint.fromSCVal(scVal), scvTimePoint); + assertEquals(Scv.fromSCVal(scVal), scvTimePoint); + + SCVal expectedScVal = + new SCVal.Builder() + .discriminant(SCValType.SCV_TIMEPOINT) + .timepoint(new TimePoint(new Uint64(new XdrUnsignedHyperInteger(value)))) + .build(); + assertEquals(expectedScVal, scVal); + } + + @Test(expected = IllegalArgumentException.class) + public void testScvTimePointMoreThanMaxThrows() { + BigInteger value = ScvDuration.MAX_VALUE.add(BigInteger.ONE); + new ScvTimePoint(value); + } + + @Test(expected = IllegalArgumentException.class) + public void testScvTimePointLessThanMinThrows() { + BigInteger value = ScvDuration.MIN_VALUE.subtract(BigInteger.ONE); + new ScvTimePoint(value); + } +} diff --git a/src/test/java/org/stellar/sdk/scval/ScvUint128Test.java b/src/test/java/org/stellar/sdk/scval/ScvUint128Test.java new file mode 100644 index 000000000..84133981e --- /dev/null +++ b/src/test/java/org/stellar/sdk/scval/ScvUint128Test.java @@ -0,0 +1,100 @@ +package org.stellar.sdk.scval; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; + +import com.google.common.io.BaseEncoding; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.math.BigInteger; +import java.util.Arrays; +import java.util.List; +import lombok.AllArgsConstructor; +import lombok.Value; +import org.junit.Test; +import org.stellar.sdk.xdr.SCVal; +import org.stellar.sdk.xdr.SCValType; +import org.stellar.sdk.xdr.UInt128Parts; +import org.stellar.sdk.xdr.XdrDataOutputStream; + +public class ScvUint128Test { + + @Test + public void testScvUint128() { + List values = + Arrays.asList( + new TestCase( + ScvUint128.MIN_VALUE, new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}), + new TestCase( + BigInteger.valueOf(1), new byte[] {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1}), + new TestCase( + BigInteger.valueOf(2L).pow(64), + new byte[] {0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0}), + new TestCase( + ScvUint128.MAX_VALUE, + new byte[] { + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff + })); + + for (TestCase value : values) { + checkScvUint128(value); + } + } + + @Test(expected = IllegalArgumentException.class) + public void testScvUint128GreaterThanMaxValueThrows() { + new ScvUint128(ScvUint128.MAX_VALUE.add(BigInteger.ONE)); + } + + @Test(expected = IllegalArgumentException.class) + public void testScvUint128LessThanMinValueThrows() { + new ScvUint128(ScvUint128.MIN_VALUE.subtract(BigInteger.ONE)); + } + + private void checkScvUint128(TestCase value) { + ScvUint128 scvUint128 = new ScvUint128(value.v); + SCVal scVal = scvUint128.toSCVal(); + + assertEquals(scvUint128.getSCValType(), SCValType.SCV_U128); + assertEquals(scvUint128.getValue(), value.v); + + assertEquals(ScvUint128.fromSCVal(scVal), scvUint128); + assertEquals(Scv.fromSCVal(scVal), scvUint128); + + assertArrayEquals(getUint128PartsBytes(scVal.getU128()), value.getExpectedBytes()); + } + + private byte[] getUint128PartsBytes(UInt128Parts uInt128Parts) { + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + XdrDataOutputStream xdrDataOutputStream = new XdrDataOutputStream(byteArrayOutputStream); + try { + uInt128Parts.encode(xdrDataOutputStream); + } catch (IOException e) { + throw new IllegalArgumentException("invalid int128Parts.", e); + } + BaseEncoding base64Encoding = BaseEncoding.base64(); + return byteArrayOutputStream.toByteArray(); + } + + @Value + @AllArgsConstructor + private static class TestCase { + BigInteger v; + byte[] expectedBytes; + } +} diff --git a/src/test/java/org/stellar/sdk/scval/ScvUint256Test.java b/src/test/java/org/stellar/sdk/scval/ScvUint256Test.java new file mode 100644 index 000000000..99082a9f1 --- /dev/null +++ b/src/test/java/org/stellar/sdk/scval/ScvUint256Test.java @@ -0,0 +1,131 @@ +package org.stellar.sdk.scval; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.math.BigInteger; +import java.util.Arrays; +import java.util.List; +import lombok.AllArgsConstructor; +import lombok.Value; +import org.junit.Test; +import org.stellar.sdk.xdr.SCVal; +import org.stellar.sdk.xdr.SCValType; +import org.stellar.sdk.xdr.UInt256Parts; +import org.stellar.sdk.xdr.XdrDataOutputStream; + +public class ScvUint256Test { + @Test + public void testScvUint256() { + List values = + Arrays.asList( + new TestCase(ScvUint256.MIN_VALUE, new byte[32]), + new TestCase( + BigInteger.valueOf(1), + new byte[] { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 1 + }), + new TestCase( + BigInteger.valueOf(2).pow(64), + new byte[] { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, + 0, 0, 0, 0, 0 + }), + new TestCase( + BigInteger.valueOf(2).pow(128), + new byte[] { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0 + }), + new TestCase( + BigInteger.valueOf(2).pow(192), + new byte[] { + 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0 + }), + new TestCase( + ScvUint256.MAX_VALUE, + new byte[] { + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff, + (byte) 0xff + })); + + for (TestCase value : values) { + checkScvUint256(value); + } + } + + @Test(expected = IllegalArgumentException.class) + public void testScvUint256GreaterThanMaxValueThrows() { + new ScvUint256(ScvUint256.MAX_VALUE.add(BigInteger.ONE)); + } + + @Test(expected = IllegalArgumentException.class) + public void testScvUint256LessThanMinValueThrows() { + new ScvUint256(ScvUint256.MIN_VALUE.subtract(BigInteger.ONE)); + } + + private void checkScvUint256(TestCase value) { + ScvUint256 scvUint256 = new ScvUint256(value.v); + SCVal scVal = scvUint256.toSCVal(); + + assertEquals(scvUint256.getSCValType(), SCValType.SCV_U256); + assertEquals(scvUint256.getValue(), value.v); + + assertEquals(ScvUint256.fromSCVal(scVal), scvUint256); + assertEquals(Scv.fromSCVal(scVal), scvUint256); + + assertArrayEquals(getInt256PartsBytes(scVal.getU256()), value.getExpectedBytes()); + } + + private byte[] getInt256PartsBytes(UInt256Parts uint256Parts) { + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + XdrDataOutputStream xdrDataOutputStream = new XdrDataOutputStream(byteArrayOutputStream); + try { + uint256Parts.encode(xdrDataOutputStream); + } catch (IOException e) { + throw new IllegalArgumentException("invalid uint256Parts.", e); + } + return byteArrayOutputStream.toByteArray(); + } + + @Value + @AllArgsConstructor + private static class TestCase { + BigInteger v; + byte[] expectedBytes; + } +} diff --git a/src/test/java/org/stellar/sdk/scval/ScvUint32Test.java b/src/test/java/org/stellar/sdk/scval/ScvUint32Test.java new file mode 100644 index 000000000..24d405368 --- /dev/null +++ b/src/test/java/org/stellar/sdk/scval/ScvUint32Test.java @@ -0,0 +1,63 @@ +package org.stellar.sdk.scval; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; +import org.stellar.sdk.xdr.SCVal; +import org.stellar.sdk.xdr.SCValType; +import org.stellar.sdk.xdr.Uint32; +import org.stellar.sdk.xdr.XdrUnsignedInteger; + +public class ScvUint32Test { + @Test + public void testScvUint32Max() { + long value = ScvUint32.MAX_VALUE; + ScvUint32 scvUint32 = new ScvUint32(value); + SCVal scVal = scvUint32.toSCVal(); + + assertEquals(scvUint32.getSCValType(), SCValType.SCV_U32); + assertEquals(scvUint32.getValue(), value); + + assertEquals(ScvUint32.fromSCVal(scVal), scvUint32); + assertEquals(Scv.fromSCVal(scVal), scvUint32); + + SCVal expectedScVal = + new SCVal.Builder() + .discriminant(SCValType.SCV_U32) + .u32(new Uint32(new XdrUnsignedInteger((1L << 32) - 1))) + .build(); + assertEquals(expectedScVal, scVal); + } + + @Test + public void testScvUint32Min() { + long value = ScvUint32.MIN_VALUE; + ScvUint32 scvUint32 = new ScvUint32(value); + SCVal scVal = scvUint32.toSCVal(); + + assertEquals(scvUint32.getSCValType(), SCValType.SCV_U32); + assertEquals(scvUint32.getValue(), value); + + assertEquals(ScvUint32.fromSCVal(scVal), scvUint32); + assertEquals(Scv.fromSCVal(scVal), scvUint32); + + SCVal expectedScVal = + new SCVal.Builder() + .discriminant(SCValType.SCV_U32) + .u32(new Uint32(new XdrUnsignedInteger(0))) + .build(); + assertEquals(expectedScVal, scVal); + } + + @Test(expected = IllegalArgumentException.class) + public void testScvUint32Overflow() { + long value = ScvUint32.MAX_VALUE + 1; + new ScvUint32(value); + } + + @Test(expected = IllegalArgumentException.class) + public void testScvUint32Underflow() { + long value = ScvUint32.MIN_VALUE - 1; + new ScvUint32(value); + } +} diff --git a/src/test/java/org/stellar/sdk/scval/ScvUint64Test.java b/src/test/java/org/stellar/sdk/scval/ScvUint64Test.java new file mode 100644 index 000000000..50ebcc6ec --- /dev/null +++ b/src/test/java/org/stellar/sdk/scval/ScvUint64Test.java @@ -0,0 +1,63 @@ +package org.stellar.sdk.scval; + +import static org.junit.Assert.assertEquals; + +import java.math.BigInteger; +import org.junit.Test; +import org.stellar.sdk.xdr.SCVal; +import org.stellar.sdk.xdr.SCValType; +import org.stellar.sdk.xdr.Uint64; +import org.stellar.sdk.xdr.XdrUnsignedHyperInteger; +import org.stellar.sdk.xdr.XdrUnsignedInteger; + +public class ScvUint64Test { + @Test + public void testScvUint64Max() { + BigInteger value = ScvUint64.MAX_VALUE; + ScvUint64 scvUint64 = new ScvUint64(value); + SCVal scVal = scvUint64.toSCVal(); + + assertEquals(scvUint64.getSCValType(), SCValType.SCV_U64); + assertEquals(scvUint64.getValue(), value); + + assertEquals(ScvUint64.fromSCVal(scVal), scvUint64); + assertEquals(Scv.fromSCVal(scVal), scvUint64); + + SCVal expectedScVal = + new SCVal.Builder() + .discriminant(SCValType.SCV_U64) + .u64(new Uint64(new XdrUnsignedHyperInteger(XdrUnsignedHyperInteger.MAX_VALUE))) + .build(); + assertEquals(expectedScVal, scVal); + } + + @Test + public void testScvUint64Min() { + BigInteger value = ScvUint64.MIN_VALUE; + ScvUint64 scvUint64 = new ScvUint64(value); + SCVal scVal = scvUint64.toSCVal(); + + assertEquals(scvUint64.getSCValType(), SCValType.SCV_U64); + assertEquals(scvUint64.getValue(), value); + + assertEquals(ScvUint64.fromSCVal(scVal), scvUint64); + assertEquals(Scv.fromSCVal(scVal), scvUint64); + + SCVal expectedScVal = + new SCVal.Builder() + .discriminant(SCValType.SCV_U64) + .u64(new Uint64(new XdrUnsignedHyperInteger(XdrUnsignedInteger.MIN_VALUE))) + .build(); + assertEquals(expectedScVal, scVal); + } + + @Test(expected = IllegalArgumentException.class) + public void testScvUint64GreaterThanMaxValueThrows() { + new ScvUint64(ScvUint64.MAX_VALUE.add(BigInteger.ONE)); + } + + @Test(expected = IllegalArgumentException.class) + public void testScvUint64LessThanMinValueThrows() { + new ScvUint64(ScvUint64.MIN_VALUE.subtract(BigInteger.ONE)); + } +} diff --git a/src/test/java/org/stellar/sdk/scval/ScvVecTest.java b/src/test/java/org/stellar/sdk/scval/ScvVecTest.java new file mode 100644 index 000000000..8961ec8a0 --- /dev/null +++ b/src/test/java/org/stellar/sdk/scval/ScvVecTest.java @@ -0,0 +1,47 @@ +package org.stellar.sdk.scval; + +import static org.junit.Assert.assertEquals; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.junit.Test; +import org.stellar.sdk.xdr.SCVal; +import org.stellar.sdk.xdr.SCValType; + +public class ScvVecTest { + @Test + public void testScvVec() { + List value = new ArrayList<>(); + + Map map = new HashMap<>(); + map.put(new ScvSymbol("key1"), new ScvString("mapValue1")); + map.put(new ScvString("key2"), new ScvInt32(23434)); + map.put( + new ScvString("key3"), + new ScvVec( + Arrays.asList( + new ScvInt32(1), + new ScvInt32(2), + new ScvVec(Arrays.asList(new ScvBoolean(true), new ScvBoolean(false)))))); + + value.add(new ScvMap(map)); + value.add(new ScvInt32(123)); + value.add(new ScvString("value1")); + + ScvVec scvVec = new ScvVec(value); + SCVal scVal = scvVec.toSCVal(); + + assertEquals(scvVec.getSCValType(), SCValType.SCV_VEC); + assertEquals(scvVec.getValue(), value); + + assertEquals(ScvVec.fromSCVal(scVal), scvVec); + assertEquals(Scv.fromSCVal(scVal), scvVec); + + assertEquals(ScvVec.fromSCVal(scVal).getValue().get(0), new ScvMap(map)); + assertEquals(ScvVec.fromSCVal(scVal).getValue().get(1), new ScvInt32(123)); + assertEquals(ScvVec.fromSCVal(scVal).getValue().get(2), new ScvString("value1")); + } +} diff --git a/src/test/java/org/stellar/sdk/scval/ScvVoidTest.java b/src/test/java/org/stellar/sdk/scval/ScvVoidTest.java new file mode 100644 index 000000000..862174179 --- /dev/null +++ b/src/test/java/org/stellar/sdk/scval/ScvVoidTest.java @@ -0,0 +1,23 @@ +package org.stellar.sdk.scval; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; +import org.stellar.sdk.xdr.SCVal; +import org.stellar.sdk.xdr.SCValType; + +public class ScvVoidTest { + @Test + public void testScvVoid() { + ScvVoid scvVoid = new ScvVoid(); + SCVal scVal = scvVoid.toSCVal(); + + assertEquals(scvVoid.getSCValType(), SCValType.SCV_VOID); + + assertEquals(ScvVoid.fromSCVal(scVal), scvVoid); + assertEquals(Scv.fromSCVal(scVal), scvVoid); + + SCVal expectedScVal = new SCVal.Builder().discriminant(SCValType.SCV_VOID).build(); + assertEquals(expectedScVal, scVal); + } +}