From 4035778fa9c764dad265fdcef109ad03303f68ec Mon Sep 17 00:00:00 2001 From: Anton Wiedermann Date: Tue, 3 Sep 2019 08:08:37 +0200 Subject: [PATCH] Fee calculation strategies and transaction builders (#116) * issue #99 - fee calculation strategies and transaction builders * issue #99 - adding ZERO strategy meaning no fees * issue #99 - refactoring + account link transaction * added account link transaction and builder * renamed transaction factory to transaction builder factory * made transaction builder factory available to all e2e tests * removed duplication of aggregate transaction size calculation * issue #99 - updates to account link, aggregate and alias transactions * issue #99 - LockFundsTransaction added * issue #99 - fee calculation is now fully owned by the builder * issue #99 - more transactions added, e2e tests updated, comments * issue #99 - junit test updates * issue #99 - fixed copy-paste error * issue #99 - adding blockchain config/upgrade + modify contract * issue #99 - refactoring tests to match constructors * issue #99 - size adding more transactions + fixes fixes for builder setter names and for size calculation * issue #99 - secret lock and proof + account properties * issue #99 - finished refactoring. e2e tests pass * issue #99 - api cleanup and fixed junit tests * issue #99 - first batch of builder junit tests * issue #99 - wrote tests for builders and couple transactions --- .../io/proximax/sdk/E2EAccountLinkTest.java | 11 +- .../java/io/proximax/sdk/E2EAccountTest.java | 251 ++++---- .../io/proximax/sdk/E2EAggregateTest.java | 164 +++-- .../java/io/proximax/sdk/E2EAliasTest.java | 62 +- src/e2e/java/io/proximax/sdk/E2EBaseTest.java | 20 +- .../io/proximax/sdk/E2EBlockchainTest.java | 8 +- .../java/io/proximax/sdk/E2EContractTest.java | 49 +- .../java/io/proximax/sdk/E2EMetadataTest.java | 51 +- .../java/io/proximax/sdk/E2EMosaicTest.java | 69 +-- .../java/io/proximax/sdk/E2EMultisigTest.java | 143 ++--- .../io/proximax/sdk/E2ENamespaceTest.java | 53 +- .../java/io/proximax/sdk/E2ESecretTest.java | 41 +- .../java/io/proximax/sdk/E2ETransferTest.java | 32 +- .../sdk/infrastructure/ListenerTest.java | 42 +- .../java/io/proximax/sdk/BlockchainApi.java | 13 + .../proximax/sdk/FeeCalculationStrategy.java | 46 ++ .../infrastructure/TransactionMapping.java | 173 +++--- .../transaction/AccountLinkTransaction.java | 101 +--- .../transaction/AggregateTransaction.java | 125 ++-- .../model/transaction/AliasTransaction.java | 119 ++-- .../BlockchainConfigTransaction.java | 72 ++- .../BlockchainUpgradeTransaction.java | 63 +- .../sdk/model/transaction/DeadlineRaw.java | 2 +- .../transaction/LockFundsTransaction.java | 225 +++---- .../ModifyAccountPropertyTransaction.java | 299 ++++----- .../ModifyContractTransaction.java | 193 +++--- .../ModifyMetadataTransaction.java | 132 ++-- .../ModifyMultisigAccountTransaction.java | 257 ++++---- .../MosaicDefinitionTransaction.java | 89 +-- .../MosaicSupplyChangeTransaction.java | 224 +++---- .../RegisterNamespaceTransaction.java | 305 +++++----- .../transaction/SecretLockTransaction.java | 281 +++++---- .../transaction/SecretProofTransaction.java | 240 ++++---- .../sdk/model/transaction/Transaction.java | 565 +++++++++--------- .../transaction/TransferTransaction.java | 329 +++++----- .../AccountLinkTransactionBuilder.java | 104 ++++ .../builder/AggregateTransactionBuilder.java | 121 ++++ .../builder/AliasTransactionBuilder.java | 183 ++++++ .../BlockchainConfigTransactionBuilder.java | 106 ++++ .../BlockchainUpgradeTransactionBuilder.java | 86 +++ .../builder/LockFundsTransactionBuilder.java | 115 ++++ ...ountPropertyAddressTransactionBuilder.java | 34 ++ ...countPropertyEntityTransactionBuilder.java | 34 ++ ...countPropertyMosaicTransactionBuilder.java | 34 ++ ...difyAccountPropertyTransactionBuilder.java | 73 +++ .../ModifyContractTransactionBuilder.java | 140 +++++ .../ModifyMetadataTransactionBuilder.java | 159 +++++ ...difyMultisigAccountTransactionBuilder.java | 120 ++++ .../MosaicDefinitionTransactionBuilder.java | 107 ++++ .../MosaicSupplyChangeTransactionBuilder.java | 128 ++++ .../RegisterNamespaceTransactionBuilder.java | 176 ++++++ .../builder/SecretLockTransactionBuilder.java | 154 +++++ .../SecretProofTransactionBuilder.java | 134 +++++ .../builder/TransactionBuilder.java | 230 +++++++ .../builder/TransactionBuilderFactory.java | 307 ++++++++++ .../builder/TransferTransactionBuilder.java | 151 +++++ .../io/proximax/sdk/BlockchainApiTest.java | 15 +- .../TransactionMappingTest.java | 4 +- .../sdk/model/account/AccountTest.java | 134 +++-- .../AccountLinkTransactionTest.java | 70 +-- .../AggregateTransactionCosignatureTest.java | 20 +- .../transaction/AggregateTransactionTest.java | 201 ++++--- .../transaction/AliasTransactionTest.java | 80 ++- .../BlockchainConfigTransactionTest.java | 38 +- .../BlockchainUpgradeTransactionTest.java | 25 +- .../CosignatureTransactionTest.java | 5 +- .../transaction/FakeTransferTransaction.java | 41 +- .../transaction/LockFundsTransactionTest.java | 62 +- .../ModifyAccountPropertyTransactionTest.java | 88 ++- .../ModifyContractTransactionTest.java | 47 +- .../ModifyMetadataTransactionTest.java | 84 ++- .../ModifyMultisigAccountTransactionTest.java | 76 +-- .../MosaicDefinitionTransactionTest.java | 42 +- .../MosaicSupplyChangeTransactionTest.java | 56 +- .../RegisterNamespaceTransactionTest.java | 69 +-- .../SecretLockTransactionTest.java | 36 +- .../SecretProofTransactionTest.java | 25 +- .../transaction/TransferTransactionTest.java | 151 +++-- .../AccountLinkTransactionBuilderTest.java | 58 ++ .../AggregateTransactionBuilderTest.java | 109 ++++ .../builder/AliasTransactionBuilderTest.java | 101 ++++ ...lockchainConfigTransactionBuilderTest.java | 44 ++ ...ockchainUpgradeTransactionBuilderTest.java | 45 ++ .../LockFundsTransactionBuilderTest.java | 49 ++ ...PropertyAddressTransactionBuilderTest.java | 53 ++ ...tPropertyEntityTransactionBuilderTest.java | 50 ++ ...tPropertyMosaicTransactionBuilderTest.java | 52 ++ .../ModifyContractTransactionBuilderTest.java | 72 +++ .../ModifyMetadataTransactionBuilderTest.java | 85 +++ ...MultisigAccountTransactionBuilderTest.java | 68 +++ ...osaicDefinitionTransactionBuilderTest.java | 65 ++ ...aicSupplyChangeTransactionBuilderTest.java | 59 ++ ...gisterNamespaceTransactionBuilderTest.java | 62 ++ .../SecretLockTransactionBuilderTest.java | 68 +++ .../SecretProofTransactionBuilderTest.java | 64 ++ .../TransactionBuilderFactoryTest.java | 63 ++ .../builder/TransactionBuilderTest.java | 80 +++ .../builder/TransactionFactoryTest.java | 35 ++ .../TransferTransactionBuilderTest.java | 95 +++ .../serialization/account_link.bytes | Bin 155 -> 155 bytes .../serialization/link_address.bytes | Bin 134 -> 156 bytes .../serialization/mosaic_definition.bytes | Bin 146 -> 146 bytes .../serialization/secret_proof.bytes | Bin 162 -> 162 bytes 103 files changed, 7267 insertions(+), 3024 deletions(-) create mode 100644 src/main/java/io/proximax/sdk/FeeCalculationStrategy.java create mode 100644 src/main/java/io/proximax/sdk/model/transaction/builder/AccountLinkTransactionBuilder.java create mode 100644 src/main/java/io/proximax/sdk/model/transaction/builder/AggregateTransactionBuilder.java create mode 100644 src/main/java/io/proximax/sdk/model/transaction/builder/AliasTransactionBuilder.java create mode 100644 src/main/java/io/proximax/sdk/model/transaction/builder/BlockchainConfigTransactionBuilder.java create mode 100644 src/main/java/io/proximax/sdk/model/transaction/builder/BlockchainUpgradeTransactionBuilder.java create mode 100644 src/main/java/io/proximax/sdk/model/transaction/builder/LockFundsTransactionBuilder.java create mode 100644 src/main/java/io/proximax/sdk/model/transaction/builder/ModifyAccountPropertyAddressTransactionBuilder.java create mode 100644 src/main/java/io/proximax/sdk/model/transaction/builder/ModifyAccountPropertyEntityTransactionBuilder.java create mode 100644 src/main/java/io/proximax/sdk/model/transaction/builder/ModifyAccountPropertyMosaicTransactionBuilder.java create mode 100644 src/main/java/io/proximax/sdk/model/transaction/builder/ModifyAccountPropertyTransactionBuilder.java create mode 100644 src/main/java/io/proximax/sdk/model/transaction/builder/ModifyContractTransactionBuilder.java create mode 100644 src/main/java/io/proximax/sdk/model/transaction/builder/ModifyMetadataTransactionBuilder.java create mode 100644 src/main/java/io/proximax/sdk/model/transaction/builder/ModifyMultisigAccountTransactionBuilder.java create mode 100644 src/main/java/io/proximax/sdk/model/transaction/builder/MosaicDefinitionTransactionBuilder.java create mode 100644 src/main/java/io/proximax/sdk/model/transaction/builder/MosaicSupplyChangeTransactionBuilder.java create mode 100644 src/main/java/io/proximax/sdk/model/transaction/builder/RegisterNamespaceTransactionBuilder.java create mode 100644 src/main/java/io/proximax/sdk/model/transaction/builder/SecretLockTransactionBuilder.java create mode 100644 src/main/java/io/proximax/sdk/model/transaction/builder/SecretProofTransactionBuilder.java create mode 100644 src/main/java/io/proximax/sdk/model/transaction/builder/TransactionBuilder.java create mode 100644 src/main/java/io/proximax/sdk/model/transaction/builder/TransactionBuilderFactory.java create mode 100644 src/main/java/io/proximax/sdk/model/transaction/builder/TransferTransactionBuilder.java create mode 100644 src/test/java/io/proximax/sdk/model/transaction/builder/AccountLinkTransactionBuilderTest.java create mode 100644 src/test/java/io/proximax/sdk/model/transaction/builder/AggregateTransactionBuilderTest.java create mode 100644 src/test/java/io/proximax/sdk/model/transaction/builder/AliasTransactionBuilderTest.java create mode 100644 src/test/java/io/proximax/sdk/model/transaction/builder/BlockchainConfigTransactionBuilderTest.java create mode 100644 src/test/java/io/proximax/sdk/model/transaction/builder/BlockchainUpgradeTransactionBuilderTest.java create mode 100644 src/test/java/io/proximax/sdk/model/transaction/builder/LockFundsTransactionBuilderTest.java create mode 100644 src/test/java/io/proximax/sdk/model/transaction/builder/ModifyAccountPropertyAddressTransactionBuilderTest.java create mode 100644 src/test/java/io/proximax/sdk/model/transaction/builder/ModifyAccountPropertyEntityTransactionBuilderTest.java create mode 100644 src/test/java/io/proximax/sdk/model/transaction/builder/ModifyAccountPropertyMosaicTransactionBuilderTest.java create mode 100644 src/test/java/io/proximax/sdk/model/transaction/builder/ModifyContractTransactionBuilderTest.java create mode 100644 src/test/java/io/proximax/sdk/model/transaction/builder/ModifyMetadataTransactionBuilderTest.java create mode 100644 src/test/java/io/proximax/sdk/model/transaction/builder/ModifyMultisigAccountTransactionBuilderTest.java create mode 100644 src/test/java/io/proximax/sdk/model/transaction/builder/MosaicDefinitionTransactionBuilderTest.java create mode 100644 src/test/java/io/proximax/sdk/model/transaction/builder/MosaicSupplyChangeTransactionBuilderTest.java create mode 100644 src/test/java/io/proximax/sdk/model/transaction/builder/RegisterNamespaceTransactionBuilderTest.java create mode 100644 src/test/java/io/proximax/sdk/model/transaction/builder/SecretLockTransactionBuilderTest.java create mode 100644 src/test/java/io/proximax/sdk/model/transaction/builder/SecretProofTransactionBuilderTest.java create mode 100644 src/test/java/io/proximax/sdk/model/transaction/builder/TransactionBuilderFactoryTest.java create mode 100644 src/test/java/io/proximax/sdk/model/transaction/builder/TransactionBuilderTest.java create mode 100644 src/test/java/io/proximax/sdk/model/transaction/builder/TransactionFactoryTest.java create mode 100644 src/test/java/io/proximax/sdk/model/transaction/builder/TransferTransactionBuilderTest.java diff --git a/src/e2e/java/io/proximax/sdk/E2EAccountLinkTest.java b/src/e2e/java/io/proximax/sdk/E2EAccountLinkTest.java index c98ae6db..b0df8f6d 100644 --- a/src/e2e/java/io/proximax/sdk/E2EAccountLinkTest.java +++ b/src/e2e/java/io/proximax/sdk/E2EAccountLinkTest.java @@ -18,7 +18,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals; -import java.math.BigInteger; import java.util.concurrent.TimeUnit; import org.junit.jupiter.api.BeforeAll; @@ -32,7 +31,6 @@ import io.proximax.core.crypto.KeyPair; import io.proximax.sdk.model.account.Account; import io.proximax.sdk.model.account.AccountInfo; -import io.proximax.sdk.model.transaction.AccountLinkAction; import io.proximax.sdk.model.transaction.AccountLinkTransaction; import io.proximax.sdk.model.transaction.TransactionStatusError; @@ -59,8 +57,7 @@ void test01linkAccounts() { @Test void test02unlinkAccounts() { - AccountLinkTransaction link = new AccountLinkTransaction(remoteAccount.getPublicAccount(), - AccountLinkAction.UNLINK, getNetworkType(), getDeadline(), BigInteger.ZERO); + AccountLinkTransaction link = transact.accountLink().unlink(remoteAccount.getPublicAccount()).build(); transactionHttp.announce(api.sign(link, localAccount)).blockingFirst(); listener.confirmed(localAccount.getAddress()).timeout(getTimeoutSeconds(), TimeUnit.SECONDS).blockingFirst(); @@ -82,16 +79,14 @@ void test03relinkAccounts() { @Test void test04overLinkAccounts() { Account remoteAccount2 = new Account(new KeyPair(), getNetworkType()); - AccountLinkTransaction link = new AccountLinkTransaction(remoteAccount2.getPublicAccount(), - AccountLinkAction.LINK, getNetworkType(), getDeadline(), BigInteger.ZERO); + AccountLinkTransaction link = transact.accountLink().link(remoteAccount2.getPublicAccount()).build(); transactionHttp.announce(api.sign(link, localAccount)).blockingFirst(); TransactionStatusError error = listener.status(localAccount.getAddress()).timeout(getTimeoutSeconds(), TimeUnit.SECONDS).blockingFirst(); assertEquals("Failure_AccountLink_Link_Already_Exists", error.getStatus()); } private void linkAndTestAccounts(Account localAccount, Account remoteAccount) { - AccountLinkTransaction link = new AccountLinkTransaction(remoteAccount.getPublicAccount(), AccountLinkAction.LINK, - getNetworkType(), getDeadline(), BigInteger.ZERO); + AccountLinkTransaction link = transact.accountLink().link(remoteAccount.getPublicAccount()).build(); transactionHttp.announce(api.sign(link, localAccount)).blockingFirst(); listener.confirmed(localAccount.getAddress()).timeout(getTimeoutSeconds(), TimeUnit.SECONDS).blockingFirst(); diff --git a/src/e2e/java/io/proximax/sdk/E2EAccountTest.java b/src/e2e/java/io/proximax/sdk/E2EAccountTest.java index edae8d56..b99727b6 100644 --- a/src/e2e/java/io/proximax/sdk/E2EAccountTest.java +++ b/src/e2e/java/io/proximax/sdk/E2EAccountTest.java @@ -20,7 +20,6 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; -import java.math.BigInteger; import java.util.Arrays; import java.util.List; import java.util.concurrent.ExecutionException; @@ -57,7 +56,7 @@ class E2EAccountTest extends E2EBaseTest { /** logger */ private static final Logger logger = LoggerFactory.getLogger(E2ETransferTest.class); - + private final Account simpleAccount = new Account(new KeyPair(), getNetworkType()); @BeforeAll @@ -69,7 +68,6 @@ void addListener() { sendSomeCash(simpleAccount, seedAccount.getAddress(), 1); } - @Test void addBlockAccountProperty() { Account acct = new Account(new KeyPair(), getNetworkType()); @@ -77,11 +75,12 @@ void addBlockAccountProperty() { signup(acct.getAddress()); signup(blocked.getAddress()); logger.info("going to block {} by {}", blocked.getPublicAccount(), acct.getPublicAccount()); - ModifyAccountPropertyTransaction
trans = ModifyAccountPropertyTransaction.createForAddress(getDeadline(), - BigInteger.ZERO, - AccountPropertyType.BLOCK_ADDRESS, - Arrays.asList(new AccountPropertyModification<>(AccountPropertyModificationType.ADD, blocked.getAddress())), - getNetworkType()); + + ModifyAccountPropertyTransaction
trans = transact.accountPropAddress() + .propertyType(AccountPropertyType.BLOCK_ADDRESS) + .modifications(Arrays + .asList(new AccountPropertyModification<>(AccountPropertyModificationType.ADD, blocked.getAddress()))) + .build(); // announce the transaction transactionHttp.announce(trans.signWith(acct, api.getNetworkGenerationHash())).blockingFirst(); logger.info("Waiting for confirmation"); @@ -97,18 +96,16 @@ void addBlockAccountProperty() { assertEquals(1, apsList.size()); testAccountProperties(apsList.get(0), blocked.getAddress()); } - + @Test void addAllowMosaicProperty() { Account acct = new Account(new KeyPair(), getNetworkType()); signup(acct.getAddress()); UInt64Id allowedMosaic = NetworkCurrencyMosaic.ID; logger.info("going to allow {} by {}", allowedMosaic, acct.getPublicAccount()); - ModifyAccountPropertyTransaction trans = ModifyAccountPropertyTransaction.createForMosaic(getDeadline(), - BigInteger.ZERO, - AccountPropertyType.ALLOW_MOSAIC, - Arrays.asList(AccountPropertyModification.add(allowedMosaic)), - getNetworkType()); + ModifyAccountPropertyTransaction trans = transact.accountPropMosaic() + .propertyType(AccountPropertyType.ALLOW_MOSAIC) + .modifications(Arrays.asList(AccountPropertyModification.add(allowedMosaic))).build(); // announce the transaction transactionHttp.announce(trans.signWith(acct, api.getNetworkGenerationHash())).blockingFirst(); logger.info("Waiting for confirmation"); @@ -124,18 +121,16 @@ void addAllowMosaicProperty() { assertEquals(1, apsList.size()); testAccountPropertiesOnSimpleAccount(apsList.get(0), allowedMosaic); } - + @Test void addAllowEntityTypeProperty() { Account acct = new Account(new KeyPair(), getNetworkType()); signup(acct.getAddress()); TransactionType allowedTransType = TransactionType.ACCOUNT_PROPERTIES_ENTITY_TYPE; logger.info("going to allow {} by {}", allowedTransType, acct.getPublicAccount()); - ModifyAccountPropertyTransaction trans = ModifyAccountPropertyTransaction.createForEntityType(getDeadline(), - BigInteger.ZERO, - AccountPropertyType.ALLOW_TRANSACTION, - Arrays.asList(AccountPropertyModification.add(allowedTransType)), - getNetworkType()); + ModifyAccountPropertyTransaction trans = transact.accountPropEntityType() + .propertyType(AccountPropertyType.ALLOW_TRANSACTION) + .modifications(Arrays.asList(AccountPropertyModification.add(allowedTransType))).build(); // announce the transaction transactionHttp.announce(trans.signWith(acct, api.getNetworkGenerationHash())).blockingFirst(); logger.info("Waiting for confirmation"); @@ -151,7 +146,7 @@ void addAllowEntityTypeProperty() { assertEquals(1, apsList.size()); testAccountPropertiesOnSimpleAccount(apsList.get(0), allowedTransType); } - + /** * check that address block is as expected * @@ -160,20 +155,20 @@ void addAllowEntityTypeProperty() { */ private void testAccountProperties(AccountProperties aps, Address blockedAddress) { boolean gotMatch = false; - for (AccountProperty ap: aps.getProperties()) { + for (AccountProperty ap : aps.getProperties()) { if (ap.getPropertyType().equals(AccountPropertyType.BLOCK_ADDRESS)) { - for (Object value: ap.getValues()) { + for (Object value : ap.getValues()) { // value should be string and should represent encoded address of the blocked account - if (value instanceof String && blockedAddress.equals(Address.createFromEncoded((String)value))) { - gotMatch = true; + if (value instanceof String && blockedAddress.equals(Address.createFromEncoded((String) value))) { + gotMatch = true; } } - + } } assertTrue(gotMatch); } - + /** * check that simple account has allowed mosaic as expected * @@ -183,30 +178,30 @@ private void testAccountProperties(AccountProperties aps, Address blockedAddress private void testAccountPropertiesOnSimpleAccount(AccountProperties aps, UInt64Id allowedAsset) { MosaicId allowedMosaic = null; if (allowedAsset instanceof MosaicId) { - allowedMosaic = (MosaicId)allowedAsset; + allowedMosaic = (MosaicId) allowedAsset; } else if (allowedAsset instanceof NamespaceId) { logger.info("Converting namespace to aliased mosaic"); - NamespaceInfo ns = namespaceHttp.getNamespace((NamespaceId)allowedAsset).blockingFirst(); + NamespaceInfo ns = namespaceHttp.getNamespace((NamespaceId) allowedAsset).blockingFirst(); allowedMosaic = ns.getMosaicAlias().orElseThrow(() -> new RuntimeException("Missing mosaic alias")); } else { fail("Unexpected asset " + allowedAsset); } boolean gotMatch = false; - for (AccountProperty ap: aps.getProperties()) { + for (AccountProperty ap : aps.getProperties()) { if (ap.getPropertyType().equals(AccountPropertyType.ALLOW_MOSAIC)) { - for (Object value: ap.getValues()) { + for (Object value : ap.getValues()) { logger.info("allowed mosaic: {}", value); // value should be string and should represent encoded address of the blocked account if (value instanceof List) { - UInt64DTO dto = new UInt64DTO(); - dto.addAll((List)value); - MosaicId retrievedMosaic = new MosaicId(UInt64Utils.toBigInt(dto)); - if (retrievedMosaic.equals(allowedMosaic)) { - gotMatch = true; - } + UInt64DTO dto = new UInt64DTO(); + dto.addAll((List) value); + MosaicId retrievedMosaic = new MosaicId(UInt64Utils.toBigInt(dto)); + if (retrievedMosaic.equals(allowedMosaic)) { + gotMatch = true; + } } } - + } } assertTrue(gotMatch); @@ -220,24 +215,25 @@ private void testAccountPropertiesOnSimpleAccount(AccountProperties aps, UInt64I */ private void testAccountPropertiesOnSimpleAccount(AccountProperties aps, TransactionType allowedTransactionType) { boolean gotMatch = false; - for (AccountProperty ap: aps.getProperties()) { + for (AccountProperty ap : aps.getProperties()) { if (ap.getPropertyType().equals(AccountPropertyType.ALLOW_TRANSACTION)) { for (Object value : ap.getValues()) { try { if (value instanceof Long && isValidTransactionTypeCode(((Long) value).intValue())) { - assertEquals(TransactionType.ACCOUNT_PROPERTIES_ENTITY_TYPE, TransactionType.rawValueOf(((Long) value).intValue())); + assertEquals(TransactionType.ACCOUNT_PROPERTIES_ENTITY_TYPE, + TransactionType.rawValueOf(((Long) value).intValue())); gotMatch = true; } } catch (RuntimeException e) { // do nothing just ignore } } - + } } assertTrue(gotMatch); } - + private static boolean isValidTransactionTypeCode(int code) { try { TransactionType.rawValueOf(code); @@ -246,105 +242,82 @@ private static boolean isValidTransactionTypeCode(int code) { return false; } } - - @Test - void getAccountInfo() throws ExecutionException, InterruptedException { - AccountInfo accountInfo = accountHttp - .getAccountInfo(simpleAccount.getAddress()) - .toFuture() - .get(); - - assertEquals(simpleAccount.getPublicKey(), accountInfo.getPublicKey()); - } - - @Test - void getAccountsInfo() { - List accountKeys = accountHttp - .getAccountsInfo(Arrays.asList(simpleAccount.getAddress(), seedAccount.getAddress())) - .flatMapIterable(list -> list) - .map(AccountInfo::getPublicKey) - .toList() - .blockingGet(); - - assertEquals(2, accountKeys.size()); - assertTrue(accountKeys.contains(simpleAccount.getPublicKey())); - assertTrue(accountKeys.contains(seedAccount.getPublicKey())); - } - - @Test - void transactions() throws ExecutionException, InterruptedException { - List transactions = accountHttp - .transactions(simpleAccount.getPublicAccount()) - .toFuture() - .get(); - - assertEquals(2, transactions.size()); - } - - @Test - void transactionsWithPagination() throws ExecutionException, InterruptedException { - // get list of transactions - List transactions = accountHttp - .transactions(simpleAccount.getPublicAccount()) - .toFuture() - .get(); - // there should be 2 as we did transfer to and from the account previously - assertEquals(2, transactions.size()); - // now make another request for page size 1 and start after first transaction ID in the list - List nextTransactions = accountHttp - .transactions(simpleAccount.getPublicAccount(), new QueryParams(10, transactions.get(0).getTransactionInfo().get().getId().get())) - .toFuture() - .get(); - // the result should be page with one item which is the second transaction - assertEquals(1, nextTransactions.size()); - assertEquals(transactions.get(1).getTransactionInfo().get().getHash(), nextTransactions.get(0).getTransactionInfo().get().getHash()); - // now try another request and start after second item which is last - List noTransactions = accountHttp - .transactions(simpleAccount.getPublicAccount(), new QueryParams(10, transactions.get(1).getTransactionInfo().get().getId().get())) - .toFuture() - .get(); + + @Test + void getAccountInfo() throws ExecutionException, InterruptedException { + AccountInfo accountInfo = accountHttp.getAccountInfo(simpleAccount.getAddress()).toFuture().get(); + + assertEquals(simpleAccount.getPublicKey(), accountInfo.getPublicKey()); + } + + @Test + void getAccountsInfo() { + List accountKeys = accountHttp + .getAccountsInfo(Arrays.asList(simpleAccount.getAddress(), seedAccount.getAddress())) + .flatMapIterable(list -> list).map(AccountInfo::getPublicKey).toList().blockingGet(); + + assertEquals(2, accountKeys.size()); + assertTrue(accountKeys.contains(simpleAccount.getPublicKey())); + assertTrue(accountKeys.contains(seedAccount.getPublicKey())); + } + + @Test + void transactions() throws ExecutionException, InterruptedException { + List transactions = accountHttp.transactions(simpleAccount.getPublicAccount()).toFuture().get(); + + assertEquals(2, transactions.size()); + } + + @Test + void transactionsWithPagination() throws ExecutionException, InterruptedException { + // get list of transactions + List transactions = accountHttp.transactions(simpleAccount.getPublicAccount()).toFuture().get(); + // there should be 2 as we did transfer to and from the account previously + assertEquals(2, transactions.size()); + // now make another request for page size 1 and start after first transaction ID in the list + List nextTransactions = accountHttp.transactions(simpleAccount.getPublicAccount(), + new QueryParams(10, transactions.get(0).getTransactionInfo().get().getId().get())).toFuture().get(); + // the result should be page with one item which is the second transaction + assertEquals(1, nextTransactions.size()); + assertEquals(transactions.get(1).getTransactionInfo().get().getHash(), + nextTransactions.get(0).getTransactionInfo().get().getHash()); + // now try another request and start after second item which is last + List noTransactions = accountHttp.transactions(simpleAccount.getPublicAccount(), + new QueryParams(10, transactions.get(1).getTransactionInfo().get().getId().get())).toFuture().get(); // the result should be page with no items because we skipped both transactions assertEquals(0, noTransactions.size()); - } - - @Test - void incomingTransactions() throws ExecutionException, InterruptedException { - List transactions = accountHttp - .incomingTransactions(simpleAccount.getPublicAccount()) - .toFuture() - .get(); - - assertEquals(1, transactions.size()); - } - - @Test - void outgoingTransactions() throws ExecutionException, InterruptedException { - List transactions = accountHttp - .outgoingTransactions(simpleAccount.getPublicAccount()) - .toFuture() - .get(); - - assertEquals(1, transactions.size()); - } - - @Test - void unconfirmedTransactions() throws ExecutionException, InterruptedException { - sleepForAWhile(); - List transactions = accountHttp - .unconfirmedTransactions(simpleAccount.getPublicAccount()) - .toFuture() - .get(); - - assertEquals(0, transactions.size()); - } - - @Test - void throwExceptionWhenBlockDoesNotExists() { - accountHttp.getAccountInfo(Address.createFromRawAddress("SARDGFTDLLCB67D4HPGIMIHPNSRYRJRT7DOBGWZY")) + } + + @Test + void incomingTransactions() throws ExecutionException, InterruptedException { + List transactions = accountHttp.incomingTransactions(simpleAccount.getPublicAccount()).toFuture() + .get(); + + assertEquals(1, transactions.size()); + } + + @Test + void outgoingTransactions() throws ExecutionException, InterruptedException { + List transactions = accountHttp.outgoingTransactions(simpleAccount.getPublicAccount()).toFuture() + .get(); + + assertEquals(1, transactions.size()); + } + + @Test + void unconfirmedTransactions() throws ExecutionException, InterruptedException { + sleepForAWhile(); + List transactions = accountHttp.unconfirmedTransactions(simpleAccount.getPublicAccount()).toFuture() + .get(); + + assertEquals(0, transactions.size()); + } + + @Test + void throwExceptionWhenBlockDoesNotExists() { + accountHttp.getAccountInfo(Address.createFromRawAddress("SARDGFTDLLCB67D4HPGIMIHPNSRYRJRT7DOBGWZY")) // .subscribeOn(Schedulers.single()) - .test() - .awaitDone(2, TimeUnit.SECONDS) - .assertFailure(RuntimeException.class); - } + .test().awaitDone(2, TimeUnit.SECONDS).assertFailure(RuntimeException.class); + } } \ No newline at end of file diff --git a/src/e2e/java/io/proximax/sdk/E2EAggregateTest.java b/src/e2e/java/io/proximax/sdk/E2EAggregateTest.java index b5c7ff27..4ce5ab55 100644 --- a/src/e2e/java/io/proximax/sdk/E2EAggregateTest.java +++ b/src/e2e/java/io/proximax/sdk/E2EAggregateTest.java @@ -57,18 +57,20 @@ public class E2EAggregateTest extends E2EBaseTest { private final Account bob = new Account(new KeyPair(), getNetworkType()); private final Account mike = new Account(new KeyPair(), getNetworkType()); - private final MosaicId mosaicX = new MosaicId(UInt64Utils.fromLongArray(new long[] {481110499,231112638})); - private final MosaicId mosaicY = new MosaicId(UInt64Utils.fromLongArray(new long[] {519256100,642862634})); - - + private final MosaicId mosaicX = new MosaicId(UInt64Utils.fromLongArray(new long[] { 481110499, 231112638 })); + private final MosaicId mosaicY = new MosaicId(UInt64Utils.fromLongArray(new long[] { 519256100, 642862634 })); + @BeforeAll void addListener() { - disposables.add(listener.status(alice.getAddress()) - .subscribe(err -> logger.error("Operation failed for alice: {}", err), t -> logger.error("exception thrown", t))); - disposables.add(listener.status(bob.getAddress()) - .subscribe(err -> logger.error("Operation failed for bob: {}", err), t -> logger.error("exception thrown", t))); - disposables.add(listener.status(mike.getAddress()) - .subscribe(err -> logger.error("Operation failed for mike: {}", err), t -> logger.error("exception thrown", t))); + disposables.add( + listener.status(alice.getAddress()).subscribe(err -> logger.error("Operation failed for alice: {}", err), + t -> logger.error("exception thrown", t))); + disposables + .add(listener.status(bob.getAddress()).subscribe(err -> logger.error("Operation failed for bob: {}", err), + t -> logger.error("exception thrown", t))); + disposables + .add(listener.status(mike.getAddress()).subscribe(err -> logger.error("Operation failed for mike: {}", err), + t -> logger.error("exception thrown", t))); // send funds to alice and bob logger.info("Mosaic X: {}", mosaicX.getIdAsHex()); logger.info("Mosaic Y: {}", mosaicY.getIdAsHex()); @@ -97,36 +99,28 @@ void escrowBetweenTwoParties() { sendMosaic(seedAccount, bob.getAddress(), new Mosaic(mosaicY, BigInteger.TEN)); logger.info("Escrow between {} and {}", alice, bob); // send mosaic X from alice to bob - TransferTransaction aliceToBob = TransferTransaction.create(getDeadline(), - bob.getAddress(), - Arrays.asList(NetworkCurrencyMosaic.ONE), - PlainMessage.Empty, - getNetworkType()); + TransferTransaction aliceToBob = transact.transfer().mosaics(NetworkCurrencyMosaic.ONE).to(bob.getAddress()) + .build(); // send mosaic Y from bob to alice - TransferTransaction bobToAlice = TransferTransaction.create(getDeadline(), - alice.getAddress(), - Arrays.asList(new Mosaic(mosaicY, BigInteger.TEN)), - PlainMessage.Empty, - getNetworkType()); + TransferTransaction bobToAlice = transact.transfer().mosaics(new Mosaic(mosaicY, BigInteger.TEN)) + .to(alice.getAddress()).build(); // aggregate bonded with the 2 transactions - escrow - AggregateTransaction escrow = AggregateTransaction.createBonded(getDeadline(), - Arrays.asList(aliceToBob.toAggregate(alice.getPublicAccount()), - bobToAlice.toAggregate(bob.getPublicAccount())), - getNetworkType()); + AggregateTransaction escrow = transact.aggregateBonded() + .innerTransactions(aliceToBob.toAggregate(alice.getPublicAccount()), + bobToAlice.toAggregate(bob.getPublicAccount())) + .build(); // alice sign the escrow trans SignedTransaction signedEscrow = api.sign(escrow, alice); // lock funds for escrow - LockFundsTransaction lock = LockFundsTransaction.create(getDeadline(), - NetworkCurrencyMosaic.TEN, - BigInteger.valueOf(480), - signedEscrow, - getNetworkType()); + LockFundsTransaction lock = transact.lockFunds().mosaic(NetworkCurrencyMosaic.TEN) + .duration(BigInteger.valueOf(480)).signedTransaction(signedEscrow).build(); // alice sign and announce the lock logger.info("announcing {}", lock); SignedTransaction signedLock = api.sign(lock, alice); transactionHttp.announce(signedLock).blockingFirst(); // wait for lock confirmation - logger.info("got confirmation: {}", listener.confirmed(alice.getAddress()).timeout(getTimeoutSeconds(), TimeUnit.SECONDS).blockingFirst()); + logger.info("got confirmation: {}", + listener.confirmed(alice.getAddress()).timeout(getTimeoutSeconds(), TimeUnit.SECONDS).blockingFirst()); sleepForAWhile(); // announce escrow logger.info("announcing {}", escrow); @@ -135,7 +129,8 @@ void escrowBetweenTwoParties() { listener.aggregateBondedAdded(alice.getAddress()).timeout(getTimeoutSeconds(), TimeUnit.SECONDS).blockingFirst(); // bob sign the escrow - AggregateTransaction pendingEscrow = accountHttp.aggregateBondedTransactions(bob.getPublicAccount()).timeout(getTimeoutSeconds(), TimeUnit.SECONDS).blockingFirst().get(0); + AggregateTransaction pendingEscrow = accountHttp.aggregateBondedTransactions(bob.getPublicAccount()) + .timeout(getTimeoutSeconds(), TimeUnit.SECONDS).blockingFirst().get(0); CosignatureSignedTransaction signedCosig = CosignatureTransaction.create(pendingEscrow).signWith(bob); // bob announce the cosignature logger.info("announcing escrow"); @@ -166,7 +161,7 @@ void escrowBetweenTwoParties() { } }); } - + @Test void escrowBetweenTwoPartiesComplete() { returnAllToSeed(alice); @@ -176,22 +171,16 @@ void escrowBetweenTwoPartiesComplete() { sendMosaic(seedAccount, bob.getAddress(), new Mosaic(mosaicY, BigInteger.TEN)); logger.info("Escrow between {} and {}", alice, bob); // send mosaic X from alice to bob - TransferTransaction aliceToBob = TransferTransaction.create(getDeadline(), - bob.getAddress(), - Arrays.asList(NetworkCurrencyMosaic.ONE), - PlainMessage.Empty, - getNetworkType()); + TransferTransaction aliceToBob = transact.transfer().mosaics(NetworkCurrencyMosaic.ONE).to(bob.getAddress()) + .build(); // send mosaic Y from bob to alice - TransferTransaction bobToAlice = TransferTransaction.create(getDeadline(), - alice.getAddress(), - Arrays.asList(new Mosaic(mosaicY, BigInteger.TEN)), - PlainMessage.Empty, - getNetworkType()); + TransferTransaction bobToAlice = transact.transfer().mosaics(new Mosaic(mosaicY, BigInteger.TEN)) + .to(alice.getAddress()).build(); // aggregate bonded with the 2 transactions - escrow - AggregateTransaction escrow = AggregateTransaction.createComplete(getDeadline(), - Arrays.asList(aliceToBob.toAggregate(alice.getPublicAccount()), - bobToAlice.toAggregate(bob.getPublicAccount())), - getNetworkType()); + AggregateTransaction escrow = transact.aggregateComplete() + .innerTransactions(aliceToBob.toAggregate(alice.getPublicAccount()), + bobToAlice.toAggregate(bob.getPublicAccount())) + .build(); // alice sign the escrow trans SignedTransaction signedEscrow = api.signWithCosigners(escrow, alice, Arrays.asList(bob)); // announce escrow @@ -223,7 +212,7 @@ void escrowBetweenTwoPartiesComplete() { } }); } - + @Test void escrowBetweenThreeParties() { returnAllToSeed(alice); @@ -236,38 +225,25 @@ void escrowBetweenThreeParties() { sleepForAWhile(); logger.info("Escrow between {}, {} and {}", alice, bob, mike); // send mosaic X from alice to bob - TransferTransaction aliceToBob = TransferTransaction.create(getDeadline(), - bob.getAddress(), - Arrays.asList(NetworkCurrencyMosaic.ONE), - PlainMessage.Empty, - getNetworkType()); + TransferTransaction aliceToBob = transact.transfer().mosaics(NetworkCurrencyMosaic.ONE).to(bob.getAddress()) + .build(); // send mosaic Y from bob to alice - TransferTransaction bobToAlice = TransferTransaction.create(getDeadline(), - alice.getAddress(), - Arrays.asList(new Mosaic(mosaicY, BigInteger.TEN)), - PlainMessage.Empty, - getNetworkType()); + TransferTransaction bobToAlice = transact.transfer().mosaics(new Mosaic(mosaicY, BigInteger.TEN)) + .to(alice.getAddress()).build(); // send mosaic Y from bob to alice - TransferTransaction mikeToAlice = TransferTransaction.create(getDeadline(), - alice.getAddress(), - Arrays.asList(NetworkCurrencyMosaic.ONE), - PlainMessage.Empty, - getNetworkType()); + TransferTransaction mikeToAlice = transact.transfer().mosaics(NetworkCurrencyMosaic.ONE).to(alice.getAddress()) + .build(); // aggregate bonded with the 3 transactions - escrow - AggregateTransaction escrow = AggregateTransaction.createBonded(getDeadline(), - Arrays.asList( - aliceToBob.toAggregate(alice.getPublicAccount()), + AggregateTransaction escrow = transact.aggregateBonded() + .innerTransactions(aliceToBob.toAggregate(alice.getPublicAccount()), bobToAlice.toAggregate(bob.getPublicAccount()), - mikeToAlice.toAggregate(mike.getPublicAccount())), - getNetworkType()); + mikeToAlice.toAggregate(mike.getPublicAccount())) + .build(); // alice sign the escrow trans SignedTransaction signedEscrow = api.sign(escrow, alice); // lock funds for escrow - LockFundsTransaction lock = LockFundsTransaction.create(getDeadline(), - NetworkCurrencyMosaic.TEN, - BigInteger.valueOf(480), - signedEscrow, - getNetworkType()); + LockFundsTransaction lock = transact.lockFunds().mosaic(NetworkCurrencyMosaic.TEN) + .duration(BigInteger.valueOf(480)).signedTransaction(signedEscrow).build(); // alice sign and announce the lock logger.info("announcing {}", lock); SignedTransaction signedLock = api.sign(lock, alice); @@ -280,18 +256,20 @@ void escrowBetweenThreeParties() { transactionHttp.announceAggregateBonded(signedEscrow).blockingFirst(); // wait for escrow confirmation listener.aggregateBondedAdded(alice.getAddress()).timeout(getTimeoutSeconds(), TimeUnit.SECONDS).blockingFirst(); - + // bob sign the escrow - AggregateTransaction pendingEscrowBob = accountHttp.aggregateBondedTransactions(bob.getPublicAccount()).timeout(getTimeoutSeconds(), TimeUnit.SECONDS).blockingFirst().get(0); + AggregateTransaction pendingEscrowBob = accountHttp.aggregateBondedTransactions(bob.getPublicAccount()) + .timeout(getTimeoutSeconds(), TimeUnit.SECONDS).blockingFirst().get(0); CosignatureSignedTransaction signedCosigBob = CosignatureTransaction.create(pendingEscrowBob).signWith(bob); // bob announce the cosignature logger.info("announcing cosig bob"); transactionHttp.announceAggregateBondedCosignature(signedCosigBob).blockingFirst(); // wait for cosig event listener.cosignatureAdded(bob.getAddress()).timeout(getTimeoutSeconds(), TimeUnit.SECONDS).blockingFirst(); - + // mike sign the escrow - AggregateTransaction pendingEscrowMike = accountHttp.aggregateBondedTransactions(mike.getPublicAccount()).timeout(getTimeoutSeconds(), TimeUnit.SECONDS).blockingFirst().get(0); + AggregateTransaction pendingEscrowMike = accountHttp.aggregateBondedTransactions(mike.getPublicAccount()) + .timeout(getTimeoutSeconds(), TimeUnit.SECONDS).blockingFirst().get(0); CosignatureSignedTransaction signedCosigMike = CosignatureTransaction.create(pendingEscrowMike).signWith(mike); // mike announce the cosignature logger.info("announcing cosig mike"); @@ -329,7 +307,7 @@ void escrowBetweenThreeParties() { List mikeMosaics = accountHttp.getAccountInfo(mike.getAddress()).blockingFirst().getMosaics(); assertTrue(mikeMosaics.isEmpty()); } - + @Test void askforMoney() { returnAllToSeed(alice); @@ -338,30 +316,21 @@ void askforMoney() { sendMosaic(seedAccount, bob.getAddress(), new Mosaic(mosaicY, BigInteger.TEN)); logger.info("Alice asks for money"); // send mosaic X from alice to bob - TransferTransaction aliceToBob = TransferTransaction.create(getDeadline(), - bob.getAddress(), - Arrays.asList(), - PlainMessage.create("send me 10 Y"), - getNetworkType()); + TransferTransaction aliceToBob = transact.transfer().to(bob.getAddress()) + .message(PlainMessage.create("send me 10 Y")).build(); // send mosaic Y from bob to alice - TransferTransaction bobToAlice = TransferTransaction.create(getDeadline(), - alice.getAddress(), - Arrays.asList(new Mosaic(mosaicY, BigInteger.TEN)), - PlainMessage.Empty, - getNetworkType()); + TransferTransaction bobToAlice = transact.transfer().mosaics(new Mosaic(mosaicY, BigInteger.TEN)) + .to(alice.getAddress()).build(); // aggregate bonded with the 2 transactions - escrow - AggregateTransaction escrow = AggregateTransaction.createBonded(getDeadline(), - Arrays.asList(aliceToBob.toAggregate(alice.getPublicAccount()), - bobToAlice.toAggregate(bob.getPublicAccount())), - getNetworkType()); + AggregateTransaction escrow = transact.aggregateBonded() + .innerTransactions(aliceToBob.toAggregate(alice.getPublicAccount()), + bobToAlice.toAggregate(bob.getPublicAccount())) + .build(); // alice sign the escrow trans SignedTransaction signedEscrow = api.sign(escrow, alice); // lock funds for escrow - LockFundsTransaction lock = LockFundsTransaction.create(getDeadline(), - NetworkCurrencyMosaic.TEN, - BigInteger.valueOf(480), - signedEscrow, - getNetworkType()); + LockFundsTransaction lock = transact.lockFunds().mosaic(NetworkCurrencyMosaic.TEN) + .duration(BigInteger.valueOf(480)).signedTransaction(signedEscrow).build(); // alice sign and announce the lock logger.info("announcing {}", lock); SignedTransaction signedLock = api.sign(lock, alice); @@ -375,7 +344,8 @@ void askforMoney() { // wait for escrow confirmation listener.aggregateBondedAdded(alice.getAddress()).timeout(getTimeoutSeconds(), TimeUnit.SECONDS).blockingFirst(); // bob sign the escrow - AggregateTransaction pendingEscrow = accountHttp.aggregateBondedTransactions(bob.getPublicAccount()).timeout(getTimeoutSeconds(), TimeUnit.SECONDS).blockingFirst().get(0); + AggregateTransaction pendingEscrow = accountHttp.aggregateBondedTransactions(bob.getPublicAccount()) + .timeout(getTimeoutSeconds(), TimeUnit.SECONDS).blockingFirst().get(0); CosignatureSignedTransaction signedCosig = CosignatureTransaction.create(pendingEscrow).signWith(bob); // bob announce the cosignature logger.info("announcing escrow"); diff --git a/src/e2e/java/io/proximax/sdk/E2EAliasTest.java b/src/e2e/java/io/proximax/sdk/E2EAliasTest.java index a763b983..d26ecf1c 100644 --- a/src/e2e/java/io/proximax/sdk/E2EAliasTest.java +++ b/src/e2e/java/io/proximax/sdk/E2EAliasTest.java @@ -34,7 +34,6 @@ import io.proximax.core.crypto.KeyPair; import io.proximax.sdk.model.account.Account; -import io.proximax.sdk.model.alias.AliasAction; import io.proximax.sdk.model.mosaic.Mosaic; import io.proximax.sdk.model.mosaic.MosaicId; import io.proximax.sdk.model.mosaic.MosaicNames; @@ -43,12 +42,9 @@ import io.proximax.sdk.model.mosaic.NetworkCurrencyMosaic; import io.proximax.sdk.model.namespace.NamespaceId; import io.proximax.sdk.model.transaction.AliasTransaction; -import io.proximax.sdk.model.transaction.MosaicDefinitionTransaction; -import io.proximax.sdk.model.transaction.PlainMessage; import io.proximax.sdk.model.transaction.RegisterNamespaceTransaction; import io.proximax.sdk.model.transaction.SignedTransaction; import io.proximax.sdk.model.transaction.Transaction; -import io.proximax.sdk.model.transaction.TransferTransaction; import io.reactivex.Observable; /** @@ -69,7 +65,7 @@ public class E2EAliasTest extends E2EBaseTest { private MosaicId mosaicId; private NamespaceId mosaNamespaceId = new NamespaceId(ROOT_NAME + "." + CHILD1_NAME); private NamespaceId accNamespaceId = new NamespaceId(ROOT_NAME + "." + CHILD2_NAME); - + /** logger */ private static final Logger logger = LoggerFactory.getLogger(E2EAliasTest.class); @@ -85,46 +81,48 @@ void initStuff() { void closeDown() { returnAllToSeed(account); } - + @Test void test01PrepareData() { NamespaceId rootId = new NamespaceId(ROOT_NAME); logger.info("Going to create namespace {}", rootId); // create root namespace - RegisterNamespaceTransaction registerNamespaceTransaction = RegisterNamespaceTransaction - .createRootNamespace(getDeadline(), ROOT_NAME, BigInteger.valueOf(200), getNetworkType()); + RegisterNamespaceTransaction registerNamespaceTransaction = transact.registerNamespace().rootNamespace(ROOT_NAME) + .duration(BigInteger.valueOf(200)).build(); SignedTransaction signedTransaction = api.sign(registerNamespaceTransaction, seedAccount); transactionHttp.announce(signedTransaction).blockingFirst(); logger.info("Registered namespace {}. {}", ROOT_NAME, - listener.confirmed(seedAccount.getAddress()).timeout(getTimeoutSeconds(), TimeUnit.SECONDS).blockingFirst()); + listener.confirmed(seedAccount.getAddress()).timeout(getTimeoutSeconds(), TimeUnit.SECONDS) + .blockingFirst()); sleepForAWhile(); // create child namespace for mosaic - RegisterNamespaceTransaction registerChildNamespaceTransaction = RegisterNamespaceTransaction - .createSubNamespace(getDeadline(), CHILD1_NAME, rootId, getNetworkType()); + RegisterNamespaceTransaction registerChildNamespaceTransaction = transact.registerNamespace() + .subNamespace(rootId, CHILD1_NAME).duration(BigInteger.valueOf(200)).build(); SignedTransaction signedChildTransaction = api.sign(registerChildNamespaceTransaction, seedAccount); transactionHttp.announce(signedChildTransaction).blockingFirst(); logger.info("Registered namespace {}. {}", CHILD1_NAME, - listener.confirmed(seedAccount.getAddress()).timeout(getTimeoutSeconds(), TimeUnit.SECONDS).blockingFirst()); + listener.confirmed(seedAccount.getAddress()).timeout(getTimeoutSeconds(), TimeUnit.SECONDS) + .blockingFirst()); sleepForAWhile(); // create child namespace for account - RegisterNamespaceTransaction accNamespace = RegisterNamespaceTransaction - .createSubNamespace(getDeadline(), CHILD2_NAME, rootId, getNetworkType()); + RegisterNamespaceTransaction accNamespace = transact.registerNamespace().subNamespace(rootId, CHILD2_NAME) + .duration(BigInteger.valueOf(200)).build(); SignedTransaction accNamespaceSigned = api.sign(accNamespace, seedAccount); transactionHttp.announce(accNamespaceSigned).blockingFirst(); logger.info("Registered namespace {}. {}", CHILD2_NAME, - listener.confirmed(seedAccount.getAddress()).timeout(getTimeoutSeconds(), TimeUnit.SECONDS).blockingFirst()); + listener.confirmed(seedAccount.getAddress()).timeout(getTimeoutSeconds(), TimeUnit.SECONDS) + .blockingFirst()); sleepForAWhile(); // create mosaic logger.info("Creating new mosaic"); - SignedTransaction mdt = MosaicDefinitionTransaction.create(mosaicNonce, - mosaicId, - getDeadline(), - new MosaicProperties(true, true, 6, Optional.of(BigInteger.valueOf(200))), - getNetworkType()).signWith(seedAccount, api.getNetworkGenerationHash()); - Observable confirmation = listener.confirmed(seedAccount.getAddress()).timeout(getTimeoutSeconds(), TimeUnit.SECONDS); + SignedTransaction mdt = transact.mosaicDefinition().nonce(mosaicNonce).mosaicId(mosaicId) + .mosaicProperties(new MosaicProperties(true, true, 6, Optional.of(BigInteger.valueOf(200)))).build() + .signWith(seedAccount, api.getNetworkGenerationHash()); + Observable confirmation = listener.confirmed(seedAccount.getAddress()).timeout(getTimeoutSeconds(), + TimeUnit.SECONDS); sleepForAWhile(); transactionHttp.announce(mdt).blockingFirst(); logger.info("Mosaic created. {}", confirmation.blockingFirst()); @@ -132,11 +130,12 @@ void test01PrepareData() { @Test void test02CreateMosaicAlias() { - AliasTransaction alias = AliasTransaction.create(mosaicId, mosaNamespaceId, AliasAction.LINK, getDeadline(), getNetworkType()); + AliasTransaction alias = transact.aliasMosaic().link(mosaicId).namespaceId(mosaNamespaceId).build(); SignedTransaction signed = api.sign(alias, seedAccount); transactionHttp.announce(signed).blockingFirst(); logger.info("created alias. {}", - listener.confirmed(seedAccount.getAddress()).timeout(getTimeoutSeconds(), TimeUnit.SECONDS).blockingFirst()); + listener.confirmed(seedAccount.getAddress()).timeout(getTimeoutSeconds(), TimeUnit.SECONDS) + .blockingFirst()); sleepForAWhile(); } @@ -145,11 +144,12 @@ void test03CreateAccountAlias() { sendSomeCash(seedAccount, account.getAddress(), 1); sendSomeCash(account, seedAccount.getAddress(), 1); logger.info("creating alias for address"); - AliasTransaction alias = AliasTransaction.create(account.getAddress(), accNamespaceId, AliasAction.LINK, getDeadline(), getNetworkType()); + AliasTransaction alias = transact.aliasAddress().link(account.getAddress()).namespaceId(accNamespaceId).build(); SignedTransaction signed = api.sign(alias, seedAccount); transactionHttp.announce(signed).blockingFirst(); logger.info("created alias. {}", - listener.confirmed(seedAccount.getAddress()).timeout(getTimeoutSeconds(), TimeUnit.SECONDS).blockingFirst()); + listener.confirmed(seedAccount.getAddress()).timeout(getTimeoutSeconds(), TimeUnit.SECONDS) + .blockingFirst()); sleepForAWhile(); } @@ -157,16 +157,14 @@ void test03CreateAccountAlias() { void test04RetrieveMosaicName() { List names = mosaicHttp.getMosaicNames(Arrays.asList(mosaicId)).blockingFirst(); MosaicNames name = names.get(0); - assertEquals(ROOT_NAME+"."+CHILD1_NAME, name.getNames().get(0)); + assertEquals(ROOT_NAME + "." + CHILD1_NAME, name.getNames().get(0)); } - + @Test void test05TransferUsingAliases() { - transactionHttp.announce(TransferTransaction.create(getDeadline(), - accNamespaceId, - Arrays.asList(new Mosaic(new NamespaceId(NetworkCurrencyMosaic.MOSAIC_NAMESPACE), BigInteger.valueOf(1_000_000))), - PlainMessage.Empty, - getNetworkType()).signWith(seedAccount, api.getNetworkGenerationHash())).blockingFirst(); + transactionHttp.announce(transact.transfer() + .mosaics(new Mosaic(new NamespaceId(NetworkCurrencyMosaic.MOSAIC_NAMESPACE), BigInteger.valueOf(1_000_000))) + .to(accNamespaceId).build().signWith(seedAccount, api.getNetworkGenerationHash())).blockingFirst(); logger.info("made transfer. {}", listener.confirmed(seedAccount.getAddress()).timeout(getTimeoutSeconds(), TimeUnit.SECONDS) .blockingFirst()); diff --git a/src/e2e/java/io/proximax/sdk/E2EBaseTest.java b/src/e2e/java/io/proximax/sdk/E2EBaseTest.java index c1704628..fbef3906 100644 --- a/src/e2e/java/io/proximax/sdk/E2EBaseTest.java +++ b/src/e2e/java/io/proximax/sdk/E2EBaseTest.java @@ -23,7 +23,6 @@ import java.math.BigInteger; import java.net.URL; import java.util.Collection; -import java.util.Collections; import java.util.LinkedList; import java.util.List; import java.util.concurrent.ExecutionException; @@ -40,10 +39,10 @@ import io.proximax.sdk.model.mosaic.Mosaic; import io.proximax.sdk.model.mosaic.NetworkCurrencyMosaic; import io.proximax.sdk.model.transaction.DeadlineRaw; -import io.proximax.sdk.model.transaction.PlainMessage; import io.proximax.sdk.model.transaction.SignedTransaction; import io.proximax.sdk.model.transaction.TransactionDeadline; import io.proximax.sdk.model.transaction.TransferTransaction; +import io.proximax.sdk.model.transaction.builder.TransactionBuilderFactory; import io.reactivex.disposables.Disposable; import io.reactivex.functions.Consumer; @@ -57,6 +56,8 @@ public class E2EBaseTest extends BaseTest { /** logger */ private static final Logger logger = LoggerFactory.getLogger(E2EBaseTest.class); + protected static final BigInteger DEFAULT_DEADLINE_DURATION = BigInteger.valueOf(5*60*1000l); + protected BlockchainApi api; protected BlockchainRepository blockchainHttp; protected AccountRepository accountHttp; @@ -66,6 +67,8 @@ public class E2EBaseTest extends BaseTest { protected MetadataRepository metadataHttp; protected ContractRepository contractHttp; + protected TransactionBuilderFactory transact; + protected ListenerRepository listener; protected Account seedAccount; @@ -89,6 +92,10 @@ void setup() throws ExecutionException, InterruptedException, IOException { metadataHttp = api.createMetadataRepository(); contractHttp = api.createContractRepository(); logger.info("Created HTTP interfaces"); + // create and initialize transaction factory + transact = api.transact(); + transact.setDeadlineMillis(DEFAULT_DEADLINE_DURATION); + transact.setFeeCalculationStrategy(FeeCalculationStrategy.ZERO); // prepare listener listener = api.createListener(); listener.open().get(); @@ -116,7 +123,7 @@ void cleanup() { * @return deadline */ protected TransactionDeadline getDeadline() { - return DeadlineRaw.startNow(BigInteger.valueOf(5*60*1000l)); + return DeadlineRaw.startNow(DEFAULT_DEADLINE_DURATION); } @@ -159,11 +166,12 @@ protected void sendSomeCash(Account sender, Address recipient, long amount) { * @param amount amount of XPX taking the divisibility into account */ protected void sendMosaic(Account sender, Address recipient, Mosaic mosaicToTransfer) { - TransferTransaction transfer = TransferTransaction - .create(getDeadline(), recipient, Collections.singletonList(mosaicToTransfer), PlainMessage.Empty, getNetworkType()); + TransferTransaction transfer = api.transact().transfer().mosaics(mosaicToTransfer).to(recipient) + .maxFee(BigInteger.ZERO).deadline(getDeadline()).build(); SignedTransaction signedTransfer = sender.sign(transfer, api.getNetworkGenerationHash()); logger.info("Sent XPX to {}: {}", recipient.pretty(), transactionHttp.announce(signedTransfer).blockingFirst()); - logger.info("request confirmed: {}", listener.confirmed(sender.getAddress()).timeout(getTimeoutSeconds(), TimeUnit.SECONDS).blockingFirst()); + logger.info("request confirmed: {}", + listener.confirmed(sender.getAddress()).timeout(getTimeoutSeconds(), TimeUnit.SECONDS).blockingFirst()); } /** diff --git a/src/e2e/java/io/proximax/sdk/E2EBlockchainTest.java b/src/e2e/java/io/proximax/sdk/E2EBlockchainTest.java index 13a27190..d0a509ca 100644 --- a/src/e2e/java/io/proximax/sdk/E2EBlockchainTest.java +++ b/src/e2e/java/io/proximax/sdk/E2EBlockchainTest.java @@ -197,8 +197,8 @@ void upgradeBlockchainVersion() { BlockchainVersion version = new BlockchainVersion(1, 2, 3, 4); Account nemesis = Account.createFromPrivateKey(NEMESIS_PRIVATE_KEY, getNetworkType()); BigInteger upgradePeriod = BigInteger.valueOf(1_000_000_000l); - BlockchainUpgradeTransaction trans = BlockchainUpgradeTransaction - .create(upgradePeriod, version, getDeadline(), getNetworkType()); + BlockchainUpgradeTransaction trans = transact.blockchainUpgrade().upgradePeriod(upgradePeriod).newVersion(version) + .build(); transactionHttp.announce(api.sign(trans, nemesis)).blockingFirst(); BlockchainUpgradeTransaction conFirmedTrans = (BlockchainUpgradeTransaction) listener .confirmed(nemesis.getAddress()).timeout(getTimeoutSeconds(), TimeUnit.SECONDS).blockingFirst(); @@ -214,8 +214,8 @@ void configTransaction() { String conf = configuration.getConfig(); String entities = configuration.getSupportedEntityVersions(); // prepare transaction - BlockchainConfigTransaction trans = BlockchainConfigTransaction - .create(BigInteger.valueOf(3), conf, entities, getNetworkType(), getDeadline()); + BlockchainConfigTransaction trans = transact.blockchainConfig().applyHeightDelta(BigInteger.valueOf(3)) + .blockchainConfig(conf).supportedEntityVersions(entities).build(); transactionHttp.announce(api.sign(trans, nemesis)).blockingFirst(); listener.confirmed(nemesis.getAddress()).timeout(getTimeoutSeconds(), TimeUnit.SECONDS).blockingFirst(); } diff --git a/src/e2e/java/io/proximax/sdk/E2EContractTest.java b/src/e2e/java/io/proximax/sdk/E2EContractTest.java index 28d27386..18840e38 100644 --- a/src/e2e/java/io/proximax/sdk/E2EContractTest.java +++ b/src/e2e/java/io/proximax/sdk/E2EContractTest.java @@ -81,23 +81,21 @@ void prepare() { void test02CreateContract() { logger.info("Creating contract"); // prepare transaction - ModifyContractTransaction trans = ModifyContractTransaction.create(getDeadline(), - BigInteger.ZERO, - BigInteger.valueOf(100l), - contentHash, - Arrays.asList(MultisigCosignatoryModification.add(customer.getPublicAccount())), - Arrays.asList( - MultisigCosignatoryModification.add(executor1.getPublicAccount()), - MultisigCosignatoryModification.add(executor2.getPublicAccount())), - Arrays.asList( - MultisigCosignatoryModification.add(validator1.getPublicAccount()), - MultisigCosignatoryModification.add(validator2.getPublicAccount())), - getNetworkType()); + ModifyContractTransaction trans = transact.modifyContract().durationDelta(BigInteger.valueOf(100l)) + .contentHash(contentHash) + .customersModifications(MultisigCosignatoryModification.add(customer.getPublicAccount())) + .executorsModifications(MultisigCosignatoryModification.add(executor1.getPublicAccount()), + MultisigCosignatoryModification.add(executor2.getPublicAccount())) + .verifiersModifications(MultisigCosignatoryModification.add(validator1.getPublicAccount()), + MultisigCosignatoryModification.add(validator2.getPublicAccount())) + .build(); + // sign the transaction SignedTransaction signedTrans = api.sign(trans, accContract); // announce the transaction transactionHttp.announce(signedTrans).blockingFirst(); - ModifyContractTransaction contractConfirmation = (ModifyContractTransaction)listener.confirmed(accContract.getAddress()).timeout(getTimeoutSeconds(), TimeUnit.SECONDS).blockingFirst(); + ModifyContractTransaction contractConfirmation = (ModifyContractTransaction) listener + .confirmed(accContract.getAddress()).timeout(getTimeoutSeconds(), TimeUnit.SECONDS).blockingFirst(); sleepForAWhile(); logger.info("Got contract confirmed: {}", contractConfirmation); // do couple sanity checks @@ -121,22 +119,15 @@ void test02CreateContract() { void test03ChangeExistingContract() { logger.info("Changing contract"); // prepare transaction - add one block to duration, move executor2 to verifiers - ModifyContractTransaction trans = ModifyContractTransaction.create(getDeadline(), - BigInteger.ZERO, - BigInteger.ONE, - contentHash, - Arrays.asList(), - Arrays.asList( - MultisigCosignatoryModification.remove(executor2.getPublicAccount())), - Arrays.asList( - MultisigCosignatoryModification.add(executor2.getPublicAccount())), - getNetworkType()); + ModifyContractTransaction trans = transact.modifyContract().durationDelta(BigInteger.ONE).contentHash(contentHash) + .executorsModifications(MultisigCosignatoryModification.remove(executor2.getPublicAccount())) + .verifiersModifications(MultisigCosignatoryModification.add(executor2.getPublicAccount())).build(); // create aggregate transaction for the multisig - AggregateTransaction aggregateTrans = AggregateTransaction.createComplete(getDeadline(), - Arrays.asList(trans.toAggregate(accContract.getPublicAccount())), - getNetworkType()); + AggregateTransaction aggregateTrans = transact.aggregateComplete() + .innerTransactions(trans.toAggregate(accContract.getPublicAccount())).build(); // sign the transaction - SignedTransaction signedTrans = validator1.signTransactionWithCosignatories(aggregateTrans, api.getNetworkGenerationHash(), + SignedTransaction signedTrans = validator1.signTransactionWithCosignatories(aggregateTrans, + api.getNetworkGenerationHash(), Arrays.asList(validator2)); // announce the transaction transactionHttp.announce(signedTrans).blockingFirst(); @@ -151,7 +142,7 @@ void test03ChangeExistingContract() { assertEquals(contentHash.toLowerCase(), contract.getContentHash().toLowerCase()); assertEquals(BigInteger.valueOf(101l), contract.getDuration()); } - + @Test void test04CompareContractEndpoints() { // prepare public key @@ -168,6 +159,6 @@ void test04CompareContractEndpoints() { assertEquals(contractByAddress, contractByPubKey); assertEquals(contractByAddress, contractsByAddresses.get(0)); assertEquals(contractByAddress, contractsByPubKeys.get(0)); - + } } diff --git a/src/e2e/java/io/proximax/sdk/E2EMetadataTest.java b/src/e2e/java/io/proximax/sdk/E2EMetadataTest.java index 4b8a97a0..ba112228 100644 --- a/src/e2e/java/io/proximax/sdk/E2EMetadataTest.java +++ b/src/e2e/java/io/proximax/sdk/E2EMetadataTest.java @@ -18,7 +18,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import java.math.BigInteger; -import java.util.Arrays; import java.util.LinkedList; import java.util.List; import java.util.Optional; @@ -45,7 +44,6 @@ import io.proximax.sdk.model.mosaic.MosaicProperties; import io.proximax.sdk.model.namespace.NamespaceId; import io.proximax.sdk.model.transaction.ModifyMetadataTransaction; -import io.proximax.sdk.model.transaction.MosaicDefinitionTransaction; import io.proximax.sdk.model.transaction.RegisterNamespaceTransaction; import io.proximax.sdk.model.transaction.SignedTransaction; import io.proximax.sdk.model.transaction.Transaction; @@ -61,14 +59,13 @@ public class E2EMetadataTest extends E2EBaseTest { private static final Logger logger = LoggerFactory.getLogger(E2EMetadataTest.class); private List metaIds = new LinkedList<>(); - + @Test void add01MetadataToAccount() { Account target = Account.generateNewAccount(getNetworkType()); logger.info("Adding metadata to account {}", target); - List mods = Arrays.asList(MetadataModification.add("tono", "a")); - ModifyMetadataTransaction addMeta = ModifyMetadataTransaction - .createForAddress(getDeadline(), target.getAddress(), mods, getNetworkType()); + ModifyMetadataTransaction addMeta = transact.modifyMetadata().forAddress(target.getAddress()) + .modifications(MetadataModification.add("tono", "a")).build(); SignedTransaction signedAddMeta = api.sign(addMeta, target); transactionHttp.announce(signedAddMeta).blockingFirst(); logger.info("Transfer done. {}", @@ -78,7 +75,7 @@ void add01MetadataToAccount() { Metadata meta = metadataHttp.getMetadata(target.getAddress()).blockingFirst(); checkMeta(meta, MetadataType.ADDRESS, new Field("tono", "a")); // add to the list of existing metadata items - metaIds.add(((AddressMetadata)meta).getId()); + metaIds.add(((AddressMetadata) meta).getId()); } @Test @@ -88,28 +85,28 @@ void add02MetadataToMosaic() { logger.info("Creating new mosaic {}", id); signup(seedAccount.getAddress()); // create mosaic - SignedTransaction mdt = MosaicDefinitionTransaction.create(nonce, - id, - getDeadline(), - new MosaicProperties(true, true, 6, Optional.of(BigInteger.valueOf(20))), - getNetworkType()).signWith(seedAccount, api.getNetworkGenerationHash()); - Observable confirmation = listener.confirmed(seedAccount.getAddress()).timeout(getTimeoutSeconds(), TimeUnit.SECONDS); + SignedTransaction mdt = transact.mosaicDefinition().nonce(nonce).mosaicId(id) + .mosaicProperties(new MosaicProperties(true, true, 6, Optional.of(BigInteger.valueOf(20)))).build() + .signWith(seedAccount, api.getNetworkGenerationHash()); + Observable confirmation = listener.confirmed(seedAccount.getAddress()).timeout(getTimeoutSeconds(), + TimeUnit.SECONDS); sleepForAWhile(); transactionHttp.announce(mdt).blockingFirst(); logger.info("Mosaic created. {}", confirmation.blockingFirst()); // now add metadata to the mosaic - List mods = Arrays.asList(MetadataModification.add("tono", "mosaic")); - SignedTransaction signedAddMeta = ModifyMetadataTransaction.createForMosaic(getDeadline(), id, mods, getNetworkType()) + SignedTransaction signedAddMeta = transact.modifyMetadata().forMosaic(id) + .modifications(MetadataModification.add("tono", "mosaic")).build() .signWith(seedAccount, api.getNetworkGenerationHash()); transactionHttp.announce(signedAddMeta).blockingFirst(); logger.info("Meta added to mosaic. {}", - listener.confirmed(seedAccount.getAddress()).timeout(getTimeoutSeconds(), TimeUnit.SECONDS).blockingFirst()); + listener.confirmed(seedAccount.getAddress()).timeout(getTimeoutSeconds(), TimeUnit.SECONDS) + .blockingFirst()); // check the meta sleepForAWhile(); Metadata meta = metadataHttp.getMetadata(id).blockingFirst(); checkMeta(meta, MetadataType.MOSAIC, new Field("tono", "mosaic")); // add to the list of existing metadata items - metaIds.add(((MosaicMetadata)meta).getId().getIdAsHex()); + metaIds.add(((MosaicMetadata) meta).getId().getIdAsHex()); } @Test @@ -118,28 +115,30 @@ void add03MetadataToNamespace() { NamespaceId rootId = new NamespaceId(name); logger.info("Going to create namespace {}", rootId); // create root namespace - RegisterNamespaceTransaction registerNamespaceTransaction = RegisterNamespaceTransaction - .createRootNamespace(getDeadline(), name, BigInteger.valueOf(100), getNetworkType()); + RegisterNamespaceTransaction registerNamespaceTransaction = transact.registerNamespace().rootNamespace(name) + .duration(BigInteger.valueOf(100)).build(); SignedTransaction signedTransaction = api.sign(registerNamespaceTransaction, seedAccount); transactionHttp.announce(signedTransaction).blockingFirst(); logger.info("Registered namespace {}. {}", name, - listener.confirmed(seedAccount.getAddress()).timeout(getTimeoutSeconds(), TimeUnit.SECONDS).blockingFirst()); + listener.confirmed(seedAccount.getAddress()).timeout(getTimeoutSeconds(), TimeUnit.SECONDS) + .blockingFirst()); sleepForAWhile(); // now add metadata to the namespace - List mods = Arrays.asList(MetadataModification.add("tono", "namespace")); - SignedTransaction signedAddMeta = ModifyMetadataTransaction - .createForNamespace(getDeadline(), rootId, mods, getNetworkType()).signWith(seedAccount, api.getNetworkGenerationHash()); + SignedTransaction signedAddMeta = transact.modifyMetadata().forNamespace(rootId) + .modifications(MetadataModification.add("tono", "namespace")).build() + .signWith(seedAccount, api.getNetworkGenerationHash()); transactionHttp.announce(signedAddMeta).blockingFirst(); logger.info("Meta added to namespace. {}", - listener.confirmed(seedAccount.getAddress()).timeout(getTimeoutSeconds(), TimeUnit.SECONDS).blockingFirst()); + listener.confirmed(seedAccount.getAddress()).timeout(getTimeoutSeconds(), TimeUnit.SECONDS) + .blockingFirst()); sleepForAWhile(); // check the meta sleepForAWhile(); Metadata meta = metadataHttp.getMetadata(rootId).blockingFirst(); checkMeta(meta, MetadataType.NAMESPACE, new Field("tono", "namespace")); // add to the list of existing metadata items - metaIds.add(((NamespaceMetadata)meta).getId().getIdAsHex()); + metaIds.add(((NamespaceMetadata) meta).getId().getIdAsHex()); } @Test @@ -147,7 +146,7 @@ void testBulkRequest() { sleepForAWhile(); assertEquals(3, metadataHttp.getMetadata(metaIds).count().blockingGet()); } - + /** * check the metadata values * diff --git a/src/e2e/java/io/proximax/sdk/E2EMosaicTest.java b/src/e2e/java/io/proximax/sdk/E2EMosaicTest.java index 5c49bc23..edfb18cb 100644 --- a/src/e2e/java/io/proximax/sdk/E2EMosaicTest.java +++ b/src/e2e/java/io/proximax/sdk/E2EMosaicTest.java @@ -18,7 +18,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import java.math.BigInteger; -import java.util.Arrays; import java.util.Optional; import java.util.concurrent.TimeUnit; @@ -35,7 +34,6 @@ import io.proximax.sdk.model.mosaic.MosaicInfo; import io.proximax.sdk.model.mosaic.MosaicNonce; import io.proximax.sdk.model.mosaic.MosaicProperties; -import io.proximax.sdk.model.mosaic.MosaicSupplyType; import io.proximax.sdk.model.transaction.AggregateTransaction; import io.proximax.sdk.model.transaction.MosaicDefinitionTransaction; import io.proximax.sdk.model.transaction.MosaicSupplyChangeTransaction; @@ -72,16 +70,15 @@ void test00PrepareMosaicId() { id = new MosaicId(nonce, seedAccount.getPublicKey()); signup(seedAccount.getAddress()); } - + @Test void test01CreateMosaic() { logger.info("Creating new mosaic"); - SignedTransaction mdt = MosaicDefinitionTransaction.create(nonce, - id, - getDeadline(), - new MosaicProperties(true, true, 6, Optional.of(BigInteger.valueOf(20))), - getNetworkType()).signWith(seedAccount, api.getNetworkGenerationHash()); - Observable confirmation = listener.confirmed(seedAccount.getAddress()).timeout(getTimeoutSeconds(), TimeUnit.SECONDS); + SignedTransaction mdt = transact.mosaicDefinition().nonce(nonce).mosaicId(id) + .mosaicProperties(new MosaicProperties(true, true, 6, Optional.of(BigInteger.valueOf(20)))).build() + .signWith(seedAccount, api.getNetworkGenerationHash()); + Observable confirmation = listener.confirmed(seedAccount.getAddress()).timeout(getTimeoutSeconds(), + TimeUnit.SECONDS); transactionHttp.announce(mdt).blockingFirst(); logger.info("Mosaic created. {}", confirmation.blockingFirst()); sleepForAWhile(); @@ -98,12 +95,12 @@ void test01CreateMosaic() { @Test void test02ChangeSupply() { logger.info("Changing supply"); - SignedTransaction supplychange = MosaicSupplyChangeTransaction - .create(getDeadline(), id, MosaicSupplyType.INCREASE, BigInteger.TEN, getNetworkType()) + SignedTransaction supplychange = transact.mosaicSupplyChange().increaseSupplyFor(id).delta(BigInteger.TEN).build() .signWith(seedAccount, api.getNetworkGenerationHash()); transactionHttp.announce(supplychange).blockingFirst(); logger.info("Supply changed. {}", - listener.confirmed(seedAccount.getAddress()).timeout(getTimeoutSeconds(), TimeUnit.SECONDS).blockingFirst()); + listener.confirmed(seedAccount.getAddress()).timeout(getTimeoutSeconds(), TimeUnit.SECONDS) + .blockingFirst()); // verify that mosaic looks fine sleepForAWhile(); MosaicInfo info = mosaicHttp.getMosaic(id).blockingFirst(); @@ -113,12 +110,12 @@ void test02ChangeSupply() { @Test void test03DecreaseSupply() { logger.info("Changing supply"); - SignedTransaction supplychange = MosaicSupplyChangeTransaction - .create(getDeadline(), id, MosaicSupplyType.DECREASE, BigInteger.ONE, getNetworkType()) + SignedTransaction supplychange = transact.mosaicSupplyChange().decreaseSupplyFor(id).delta(BigInteger.ONE).build() .signWith(seedAccount, api.getNetworkGenerationHash()); transactionHttp.announce(supplychange).blockingFirst(); logger.info("Supply changed. {}", - listener.confirmed(seedAccount.getAddress()).timeout(getTimeoutSeconds(), TimeUnit.SECONDS).blockingFirst()); + listener.confirmed(seedAccount.getAddress()).timeout(getTimeoutSeconds(), TimeUnit.SECONDS) + .blockingFirst()); // verify that mosaic looks fine sleepForAWhile(); MosaicInfo info = mosaicHttp.getMosaic(id).blockingFirst(); @@ -131,49 +128,44 @@ void test04AggregateMosaic() { MosaicNonce aNonce = MosaicNonce.createRandom(); MosaicId aId = new MosaicId(aNonce, seedAccount.getPublicKey()); // create mosaic - MosaicDefinitionTransaction create = MosaicDefinitionTransaction.create(aNonce, - aId, - getDeadline(), - new MosaicProperties(true, true, 6, Optional.of(BigInteger.valueOf(20))), - getNetworkType()); + MosaicDefinitionTransaction create = transact.mosaicDefinition().nonce(aNonce).mosaicId(aId) + .mosaicProperties(new MosaicProperties(true, true, 6, Optional.of(BigInteger.valueOf(20)))).build(); // add supply of 10 - MosaicSupplyChangeTransaction increaseSupply = MosaicSupplyChangeTransaction - .create(getDeadline(), aId, MosaicSupplyType.INCREASE, BigInteger.TEN, getNetworkType()); + MosaicSupplyChangeTransaction increaseSupply = transact.mosaicSupplyChange().increaseSupplyFor(aId) + .delta(BigInteger.TEN).build(); // remove supply of 1 - MosaicSupplyChangeTransaction decreaseSupply = MosaicSupplyChangeTransaction - .create(getDeadline(), aId, MosaicSupplyType.DECREASE, BigInteger.ONE, getNetworkType()); + MosaicSupplyChangeTransaction decreaseSupply = transact.mosaicSupplyChange().decreaseSupplyFor(aId) + .delta(BigInteger.ONE).build(); // create aggregate transaction - AggregateTransaction aggregateTransaction = AggregateTransaction.createComplete(getDeadline(), - Arrays.asList( - create.toAggregate(seedAccount.getPublicAccount()), + AggregateTransaction aggregateTransaction = transact.aggregateComplete() + .innerTransactions(create.toAggregate(seedAccount.getPublicAccount()), increaseSupply.toAggregate(seedAccount.getPublicAccount()), - decreaseSupply.toAggregate(seedAccount.getPublicAccount()) - ), - getNetworkType()); + decreaseSupply.toAggregate(seedAccount.getPublicAccount())) + .build(); // sign the transaction SignedTransaction signedTransaction = api.sign(aggregateTransaction, seedAccount); // announce the request transactionHttp.announce(signedTransaction).blockingFirst(); // wait for acceptance logger.info("Aggregate mosaic done. {}", - listener.confirmed(seedAccount.getAddress()).timeout(getTimeoutSeconds(), TimeUnit.SECONDS).blockingFirst()); + listener.confirmed(seedAccount.getAddress()).timeout(getTimeoutSeconds(), TimeUnit.SECONDS) + .blockingFirst()); sleepForAWhile(); // verify that mosaic looks fine MosaicInfo info = mosaicHttp.getMosaic(aId).blockingFirst(); assertEquals(BigInteger.valueOf(9), info.getSupply()); } - + @Test void test05CreateMosaicWithoutDuration() { MosaicNonce aNonce = MosaicNonce.createRandom(); MosaicId aId = new MosaicId(aNonce, seedAccount.getPublicKey()); logger.info("Creating new mosaic {}", aId.getIdAsHex()); - SignedTransaction mdt = MosaicDefinitionTransaction.create(aNonce, - aId, - getDeadline(), - new MosaicProperties(true, true, 6, Optional.empty()), - getNetworkType()).signWith(seedAccount, api.getNetworkGenerationHash()); - Observable confirmation = listener.confirmed(seedAccount.getAddress()).timeout(getTimeoutSeconds(), TimeUnit.SECONDS); + SignedTransaction mdt = transact.mosaicDefinition().nonce(aNonce).mosaicId(aId) + .mosaicProperties(new MosaicProperties(true, true, 6, Optional.empty())).build() + .signWith(seedAccount, api.getNetworkGenerationHash()); + Observable confirmation = listener.confirmed(seedAccount.getAddress()).timeout(getTimeoutSeconds(), + TimeUnit.SECONDS); transactionHttp.announce(mdt).blockingFirst(); logger.info("Mosaic created. {}", confirmation.blockingFirst()); sleepForAWhile(); @@ -187,5 +179,4 @@ void test05CreateMosaicWithoutDuration() { assertEquals(Optional.empty(), info.getDuration()); } - } diff --git a/src/e2e/java/io/proximax/sdk/E2EMultisigTest.java b/src/e2e/java/io/proximax/sdk/E2EMultisigTest.java index 961cc636..b7120384 100644 --- a/src/e2e/java/io/proximax/sdk/E2EMultisigTest.java +++ b/src/e2e/java/io/proximax/sdk/E2EMultisigTest.java @@ -19,7 +19,6 @@ import java.math.BigInteger; import java.util.Arrays; -import java.util.Collections; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; @@ -38,7 +37,15 @@ import io.proximax.sdk.model.account.MultisigAccountGraphInfo; import io.proximax.sdk.model.account.MultisigAccountInfo; import io.proximax.sdk.model.mosaic.NetworkCurrencyMosaic; -import io.proximax.sdk.model.transaction.*; +import io.proximax.sdk.model.transaction.AggregateTransaction; +import io.proximax.sdk.model.transaction.CosignatureSignedTransaction; +import io.proximax.sdk.model.transaction.CosignatureTransaction; +import io.proximax.sdk.model.transaction.LockFundsTransaction; +import io.proximax.sdk.model.transaction.ModifyMultisigAccountTransaction; +import io.proximax.sdk.model.transaction.MultisigCosignatoryModification; +import io.proximax.sdk.model.transaction.MultisigCosignatoryModificationType; +import io.proximax.sdk.model.transaction.SignedTransaction; +import io.proximax.sdk.model.transaction.TransferTransaction; /** * Multisig integration tests @@ -81,18 +88,12 @@ void test01CreateMultisig() throws InterruptedException, ExecutionException { sendSomeCash(seedAccount, multisigAccount.getAddress(), 1); // give cosig1 10XPX so he can lock funds for aggregate transactions sendSomeCash(seedAccount, cosig1.getAddress(), 10); // change the account to multisig with 1 of2 cosignatories - ModifyMultisigAccountTransaction changeToMultisig = ModifyMultisigAccountTransaction.create(getDeadline(), - 1, - 1, - Arrays.asList( - new MultisigCosignatoryModification(MultisigCosignatoryModificationType.ADD, - cosig1.getPublicAccount()), - new MultisigCosignatoryModification(MultisigCosignatoryModificationType.ADD, - cosig2.getPublicAccount())), - getNetworkType()); - AggregateTransaction changeToMultisigAggregate = AggregateTransaction.createComplete(getDeadline(), - Arrays.asList(changeToMultisig.toAggregate(multisigAccount.getPublicAccount())), - getNetworkType()); + ModifyMultisigAccountTransaction changeToMultisig = transact.multisigModification().minApprovalDelta(1).minRemovalDelta(1).modifications( + new MultisigCosignatoryModification(MultisigCosignatoryModificationType.ADD, + cosig1.getPublicAccount()), + new MultisigCosignatoryModification(MultisigCosignatoryModificationType.ADD, + cosig2.getPublicAccount())).build(); + AggregateTransaction changeToMultisigAggregate = transact.aggregateComplete().innerTransactions(changeToMultisig.toAggregate(multisigAccount.getPublicAccount())).build(); SignedTransaction signedChangeToMultisig = api .signWithCosigners(changeToMultisigAggregate, multisigAccount, Arrays.asList(cosig1, cosig2)); // announce the transaction @@ -108,15 +109,9 @@ void test01CreateMultisig() throws InterruptedException, ExecutionException { @Test void test01TransferFromMultisig1Of2Aggregate() { // prepare transfer to the seed account - TransferTransaction transfer = TransferTransaction.create(getDeadline(), - seedAccount.getAddress(), - Collections.singletonList(NetworkCurrencyMosaic.createAbsolute(BigInteger.valueOf(1))), - PlainMessage.Empty, - getNetworkType()); + TransferTransaction transfer = transact.transfer().mosaics(NetworkCurrencyMosaic.createAbsolute(BigInteger.valueOf(1))).to(seedAccount.getAddress()).build(); // add the modification to the aggregate transaction - AggregateTransaction aggregateTransaction = AggregateTransaction.createComplete(getDeadline(), - Arrays.asList(transfer.toAggregate(multisigAccount.getPublicAccount())), - getNetworkType()); + AggregateTransaction aggregateTransaction = transact.aggregateComplete().innerTransactions(transfer.toAggregate(multisigAccount.getPublicAccount())).build(); // sign the aggregate transaction SignedTransaction signedTransaction = api.sign(aggregateTransaction, cosig1); // announce the transfer @@ -129,23 +124,13 @@ void test01TransferFromMultisig1Of2Aggregate() { @Test void test01TransferFromMultisig1Of2AggregateBonded() { // prepare transfer to the seed account - TransferTransaction transfer = TransferTransaction.create(getDeadline(), - seedAccount.getAddress(), - Collections.singletonList(NetworkCurrencyMosaic.createAbsolute(BigInteger.valueOf(1))), - PlainMessage.Empty, - getNetworkType()); + TransferTransaction transfer = transact.transfer().mosaics(NetworkCurrencyMosaic.createAbsolute(BigInteger.valueOf(1))).to(seedAccount.getAddress()).build(); // add the modification to the aggregate transaction. has to be bonded because we are going to test the lock - AggregateTransaction aggregateTransaction = AggregateTransaction.createBonded(getDeadline(), - Arrays.asList(transfer.toAggregate(multisigAccount.getPublicAccount())), - getNetworkType()); + AggregateTransaction aggregateTransaction = transact.aggregateBonded().innerTransactions(transfer.toAggregate(multisigAccount.getPublicAccount())).build(); // sign the aggregate bonded transaction SignedTransaction signedTransaction = api.sign(aggregateTransaction, cosig1); // lock 10 of XPX (required to prevent spamming) - LockFundsTransaction lockFundsTransaction = LockFundsTransaction.create(getDeadline(), - NetworkCurrencyMosaic.TEN, - BigInteger.valueOf(480), - signedTransaction, - getNetworkType()); + LockFundsTransaction lockFundsTransaction = transact.lockFunds().aggregate(BigInteger.valueOf(480)).signedTransaction(signedTransaction).build(); logger.info("locking account {}", lockFundsTransaction); // sign the fund lock SignedTransaction lockFundsTransactionSigned = api.sign(lockFundsTransaction, cosig1); @@ -166,14 +151,8 @@ void test01TransferFromMultisig1Of2AggregateBonded() { void test02IncreaseMinApproval() throws InterruptedException, ExecutionException { logger.info("Going to make the account 2 of 2"); // modify account to be 2 of 2 - ModifyMultisigAccountTransaction changeTo2of2 = ModifyMultisigAccountTransaction.create(getDeadline(), - 1, // add one to the minApproval to change it to 2 - 0, - Arrays.asList(), - getNetworkType()); - AggregateTransaction aggregateTransaction = AggregateTransaction.createComplete(getDeadline(), - Arrays.asList(changeTo2of2.toAggregate(multisigAccount.getPublicAccount())), - getNetworkType()); + ModifyMultisigAccountTransaction changeTo2of2 = transact.multisigModification().minApprovalDelta(1).build(); + AggregateTransaction aggregateTransaction = transact.aggregateComplete().innerTransactions(changeTo2of2.toAggregate(multisigAccount.getPublicAccount())).build(); SignedTransaction signedChangeTo2of2 = api.sign(aggregateTransaction, cosig1); logger.info("Sent request: {}", transactionHttp.announce(signedChangeTo2of2).toFuture().get()); // verify that min approvals is set to 2 @@ -186,15 +165,9 @@ void test02IncreaseMinApproval() throws InterruptedException, ExecutionException @Test void test02TransferFromMultisig2Of2Aggregate() { // prepare transfer to the seed account - TransferTransaction transfer = TransferTransaction.create(getDeadline(), - seedAccount.getAddress(), - Collections.singletonList(NetworkCurrencyMosaic.createAbsolute(BigInteger.valueOf(1))), - PlainMessage.Empty, - getNetworkType()); + TransferTransaction transfer = transact.transfer().mosaics(NetworkCurrencyMosaic.createAbsolute(BigInteger.valueOf(1))).to(seedAccount.getAddress()).build(); // add the modification to the aggregate transaction - AggregateTransaction aggregateTransaction = AggregateTransaction.createComplete(getDeadline(), - Arrays.asList(transfer.toAggregate(multisigAccount.getPublicAccount())), - getNetworkType()); + AggregateTransaction aggregateTransaction = transact.aggregateComplete().innerTransactions(transfer.toAggregate(multisigAccount.getPublicAccount())).build(); // sign the aggregate transaction SignedTransaction signedTransaction = cosig1.signTransactionWithCosignatories(aggregateTransaction, api.getNetworkGenerationHash(), Arrays.asList(cosig2)); @@ -208,24 +181,14 @@ void test02TransferFromMultisig2Of2Aggregate() { @Test void test02TransferFromMultisig2Of2AggregateBonded() { // prepare transfer to the seed account - TransferTransaction transfer = TransferTransaction.create(getDeadline(), - seedAccount.getAddress(), - Collections.singletonList(NetworkCurrencyMosaic.createAbsolute(BigInteger.valueOf(1))), - PlainMessage.Empty, - getNetworkType()); + TransferTransaction transfer = transact.transfer().mosaics(NetworkCurrencyMosaic.createAbsolute(BigInteger.valueOf(1))).to(seedAccount.getAddress()).build(); // add the modification to the aggregate transaction. has to be bonded because we are going to test the lock - AggregateTransaction aggregateTransaction = AggregateTransaction.createBonded(getDeadline(), - Arrays.asList(transfer.toAggregate(multisigAccount.getPublicAccount())), - getNetworkType()); + AggregateTransaction aggregateTransaction = transact.aggregateBonded().innerTransactions(transfer.toAggregate(multisigAccount.getPublicAccount())).build(); // sign the aggregate bonded transaction SignedTransaction signedTransaction = cosig1.signTransactionWithCosignatories(aggregateTransaction, api.getNetworkGenerationHash(), Arrays.asList(cosig2)); // lock 10 of XPX (required to prevent spamming) - LockFundsTransaction lockFundsTransaction = LockFundsTransaction.create(getDeadline(), - NetworkCurrencyMosaic.TEN, - BigInteger.valueOf(480), - signedTransaction, - getNetworkType()); + LockFundsTransaction lockFundsTransaction = transact.lockFunds().aggregate(BigInteger.valueOf(480)).signedTransaction(signedTransaction).build(); logger.info("locking account {}", lockFundsTransaction); // sign the fund lock SignedTransaction lockFundsTransactionSigned = api.sign(lockFundsTransaction, cosig1); @@ -244,23 +207,13 @@ void test02TransferFromMultisig2Of2AggregateBonded() { @Test void test02TransferFromMultisig2Of2AggregateBondedSeparateConfirmation() { // prepare transfer to the seed account - TransferTransaction transfer = TransferTransaction.create(getDeadline(), - seedAccount.getAddress(), - Collections.singletonList(NetworkCurrencyMosaic.createAbsolute(BigInteger.valueOf(1))), - PlainMessage.Empty, - getNetworkType()); + TransferTransaction transfer = transact.transfer().mosaics(NetworkCurrencyMosaic.createAbsolute(BigInteger.valueOf(1))).to(seedAccount.getAddress()).build(); // add the modification to the aggregate transaction. has to be bonded because we are going to test the lock - AggregateTransaction aggregateTransaction = AggregateTransaction.createBonded(getDeadline(), - Arrays.asList(transfer.toAggregate(multisigAccount.getPublicAccount())), - getNetworkType()); + AggregateTransaction aggregateTransaction = transact.aggregateBonded().innerTransactions(transfer.toAggregate(multisigAccount.getPublicAccount())).build(); // sign the aggregate bonded transaction SignedTransaction signedTransaction = api.sign(aggregateTransaction, cosig1); // lock 10 of XPX (required to prevent spamming) - LockFundsTransaction lockFundsTransaction = LockFundsTransaction.create(getDeadline(), - NetworkCurrencyMosaic.TEN, - BigInteger.valueOf(480), - signedTransaction, - getNetworkType()); + LockFundsTransaction lockFundsTransaction = transact.lockFunds().aggregate(BigInteger.valueOf(480)).signedTransaction(signedTransaction).build(); logger.info("locking account {}", lockFundsTransaction); // sign the fund lock SignedTransaction lockFundsTransactionSigned = api.sign(lockFundsTransaction, cosig1); @@ -282,24 +235,14 @@ void test02TransferFromMultisig2Of2AggregateBondedSeparateConfirmation() { void test03AddCosignatory() throws InterruptedException, ExecutionException { logger.info("Going to add third cosignatory"); // create multisig modification - ModifyMultisigAccountTransaction addCosig3 = ModifyMultisigAccountTransaction.create(getDeadline(), - 0, - 0, - Arrays.asList(new MultisigCosignatoryModification(MultisigCosignatoryModificationType.ADD, - cosig3.getPublicAccount())), - getNetworkType()); + ModifyMultisigAccountTransaction addCosig3 = transact.multisigModification().modifications(new MultisigCosignatoryModification(MultisigCosignatoryModificationType.ADD, + cosig3.getPublicAccount())).build(); // add the modification to the aggregate bonded transaction - AggregateTransaction aggregateTransaction = AggregateTransaction.createBonded(getDeadline(), - Arrays.asList(addCosig3.toAggregate(multisigAccount.getPublicAccount())), - getNetworkType()); + AggregateTransaction aggregateTransaction = transact.aggregateBonded().innerTransactions(addCosig3.toAggregate(multisigAccount.getPublicAccount())).build(); // sign the aggregate bonded transaction SignedTransaction signedTransaction = api.signWithCosigners(aggregateTransaction, cosig1, Arrays.asList(cosig3)); // lock 10 of XPX (required to prevent spamming) - LockFundsTransaction lockFundsTransaction = LockFundsTransaction.create(getDeadline(), - NetworkCurrencyMosaic.TEN, - BigInteger.valueOf(480), - signedTransaction, - getNetworkType()); + LockFundsTransaction lockFundsTransaction = transact.lockFunds().aggregate(BigInteger.valueOf(480)).signedTransaction(signedTransaction).build(); // sign the fund lock SignedTransaction lockFundsTransactionSigned = api.sign(lockFundsTransaction, cosig1); // announce the transaction @@ -328,18 +271,12 @@ void test04CosignNewCosignatory() { @Disabled void test05CreateMultilevelMultisig() throws InterruptedException, ExecutionException { // change the account to multisig with 1 of2 cosignatories - ModifyMultisigAccountTransaction changeToMultisig = ModifyMultisigAccountTransaction.create(getDeadline(), - 1, - 1, - Arrays.asList( - new MultisigCosignatoryModification(MultisigCosignatoryModificationType.ADD, - cosig1.getPublicAccount()), - new MultisigCosignatoryModification(MultisigCosignatoryModificationType.ADD, - multisigAccount.getPublicAccount())), - getNetworkType()); - AggregateTransaction agg = AggregateTransaction.createComplete(getDeadline(), - Arrays.asList(changeToMultisig.toAggregate(multiMultisigAccount.getPublicAccount())), - getNetworkType()); + ModifyMultisigAccountTransaction changeToMultisig = transact.multisigModification().minApprovalDelta(1).minRemovalDelta(1).modifications( + new MultisigCosignatoryModification(MultisigCosignatoryModificationType.ADD, + cosig1.getPublicAccount()), + new MultisigCosignatoryModification(MultisigCosignatoryModificationType.ADD, + multisigAccount.getPublicAccount())).build(); + AggregateTransaction agg = transact.aggregateComplete().innerTransactions(changeToMultisig.toAggregate(multiMultisigAccount.getPublicAccount())).build(); SignedTransaction signedChangeToMultisig = api.signWithCosigners(agg, multiMultisigAccount, Arrays.asList(cosig1, cosig2)); // announce the transaction logger.info("Sent request: {}", transactionHttp.announce(signedChangeToMultisig).toFuture().get()); diff --git a/src/e2e/java/io/proximax/sdk/E2ENamespaceTest.java b/src/e2e/java/io/proximax/sdk/E2ENamespaceTest.java index d616cafc..47710243 100644 --- a/src/e2e/java/io/proximax/sdk/E2ENamespaceTest.java +++ b/src/e2e/java/io/proximax/sdk/E2ENamespaceTest.java @@ -69,13 +69,14 @@ void test01CreateRootNamespace() { NamespaceId rootId = new NamespaceId(ROOT_NAME); logger.info("Going to create namespace {}", rootId); // create root namespace - RegisterNamespaceTransaction registerNamespaceTransaction = RegisterNamespaceTransaction - .createRootNamespace(getDeadline(), ROOT_NAME, BigInteger.valueOf(100), getNetworkType()); + RegisterNamespaceTransaction registerNamespaceTransaction = transact.registerNamespace().rootNamespace(ROOT_NAME) + .duration(BigInteger.valueOf(100)).build(); SignedTransaction signedTransaction = api.sign(registerNamespaceTransaction, seedAccount); transactionHttp.announce(signedTransaction).blockingFirst(); logger.info("Registered namespace {}. {}", ROOT_NAME, - listener.confirmed(seedAccount.getAddress()).timeout(getTimeoutSeconds(), TimeUnit.SECONDS).blockingFirst()); + listener.confirmed(seedAccount.getAddress()).timeout(getTimeoutSeconds(), TimeUnit.SECONDS) + .blockingFirst()); sleepForAWhile(); // check the namespace checkNamespace(ROOT_NAME, Optional.empty(), 100); @@ -87,13 +88,14 @@ void test02CreateChildNamespace() { NamespaceId childId = new NamespaceId(ROOT_NAME + "." + CHILD1_NAME); logger.info("Going to create child namespace {}", childId); // create root namespace - RegisterNamespaceTransaction registerNamespaceTransaction = RegisterNamespaceTransaction - .createSubNamespace(getDeadline(), CHILD1_NAME, rootId, getNetworkType()); + RegisterNamespaceTransaction registerNamespaceTransaction = transact.registerNamespace() + .subNamespace(rootId, CHILD1_NAME).build(); SignedTransaction signedTransaction = api.sign(registerNamespaceTransaction, seedAccount); transactionHttp.announce(signedTransaction).blockingFirst(); logger.info("Registered namespace {}. {}", CHILD1_NAME, - listener.confirmed(seedAccount.getAddress()).timeout(getTimeoutSeconds(), TimeUnit.SECONDS).blockingFirst()); + listener.confirmed(seedAccount.getAddress()).timeout(getTimeoutSeconds(), TimeUnit.SECONDS) + .blockingFirst()); sleepForAWhile(); // check the namespace checkNamespace(CHILD1_NAME, Optional.of(ROOT_NAME), 100); @@ -106,21 +108,22 @@ void test03CreateAggregateRootAndChild() { NamespaceId childId = new NamespaceId(aggRootName + "." + CHILD1_NAME); logger.info("Going to create aggregate root and child namespace {}", childId); // create root namespace - RegisterNamespaceTransaction registerRootTransaction = RegisterNamespaceTransaction - .createRootNamespace(getDeadline(), aggRootName, BigInteger.valueOf(100), getNetworkType()); - RegisterNamespaceTransaction registerChildTransaction = RegisterNamespaceTransaction - .createSubNamespace(getDeadline(), CHILD1_NAME, rootId, getNetworkType()); + RegisterNamespaceTransaction registerRootTransaction = transact.registerNamespace().rootNamespace(aggRootName) + .duration(BigInteger.valueOf(100)).build(); + RegisterNamespaceTransaction registerChildTransaction = transact.registerNamespace() + .subNamespace(rootId, CHILD1_NAME).build(); // prepare aggregate transaction for both namespaces - AggregateTransaction aggregateTransaction = AggregateTransaction.createComplete(getDeadline(), - Arrays.asList(registerRootTransaction.toAggregate(seedAccount.getPublicAccount()), - registerChildTransaction.toAggregate(seedAccount.getPublicAccount())), - getNetworkType()); + AggregateTransaction aggregateTransaction = transact.aggregateComplete() + .innerTransactions(registerRootTransaction.toAggregate(seedAccount.getPublicAccount()), + registerChildTransaction.toAggregate(seedAccount.getPublicAccount())) + .build(); // sign the aggregate transaction SignedTransaction signedTransaction = api.sign(aggregateTransaction, seedAccount); transactionHttp.announce(signedTransaction).blockingFirst(); logger.info("Registered namespaces {}. {}", CHILD1_NAME, - listener.confirmed(seedAccount.getAddress()).timeout(getTimeoutSeconds(), TimeUnit.SECONDS).blockingFirst()); + listener.confirmed(seedAccount.getAddress()).timeout(getTimeoutSeconds(), TimeUnit.SECONDS) + .blockingFirst()); sleepForAWhile(); // check the namespaces checkNamespace(aggRootName, Optional.empty(), 100); @@ -132,27 +135,28 @@ void test04RetrieveFromAccount() { NamespaceId nsId = new NamespaceId(ROOT_NAME); // check that the seed account has the namespace as expected long nsCount = namespaceHttp.getNamespacesFromAccount(seedAccount.getAddress()).flatMapIterable(list -> list) - .filter(info -> nsId.getId().equals(info.getId().getId())) - .count().blockingGet(); + .filter(info -> nsId.getId().equals(info.getId().getId())).count().blockingGet(); assertEquals(1, nsCount); } - + @Test void test05RetrieveFromAccounts() { NamespaceId nsId = new NamespaceId(ROOT_NAME); // check that the seed account has the namespace as expected - long nsCount = namespaceHttp.getNamespacesFromAccounts(Arrays.asList(seedAccount.getAddress(), Account.generateNewAccount(getNetworkType()).getAddress())).flatMapIterable(list -> list) - .filter(info -> nsId.getId().equals(info.getId().getId())) - .count().blockingGet(); + long nsCount = namespaceHttp + .getNamespacesFromAccounts( + Arrays.asList(seedAccount.getAddress(), Account.generateNewAccount(getNetworkType()).getAddress())) + .flatMapIterable(list -> list).filter(info -> nsId.getId().equals(info.getId().getId())).count() + .blockingGet(); assertEquals(1, nsCount); } - + @Test void throwExceptionWhenNamespaceDoesNotExists() { namespaceHttp.getNamespace(new NamespaceId("nonregisterednamespace")).subscribeOn(Schedulers.single()).test() .awaitDone(2, TimeUnit.SECONDS).assertFailure(RuntimeException.class); } - + /** * service method that checks for existence of a namespace * @@ -171,7 +175,8 @@ private void checkNamespace(String name, Optional parentName, long durat logger.info("Checking namespace {}", nsId); // retrieve the namespace and check it is OK - NamespaceInfo namespace = namespaceHttp.getNamespace(nsId).timeout(getTimeoutSeconds(), TimeUnit.SECONDS).blockingFirst(); + NamespaceInfo namespace = namespaceHttp.getNamespace(nsId).timeout(getTimeoutSeconds(), TimeUnit.SECONDS) + .blockingFirst(); // check for namespace properties assertEquals(BigInteger.valueOf(duration), namespace.getEndHeight().subtract(namespace.getStartHeight())); assertEquals(nsId.getId(), namespace.getId().getId()); diff --git a/src/e2e/java/io/proximax/sdk/E2ESecretTest.java b/src/e2e/java/io/proximax/sdk/E2ESecretTest.java index 8d4da6fc..f5056401 100644 --- a/src/e2e/java/io/proximax/sdk/E2ESecretTest.java +++ b/src/e2e/java/io/proximax/sdk/E2ESecretTest.java @@ -17,7 +17,6 @@ package io.proximax.sdk; import java.math.BigInteger; -import java.util.Collections; import java.util.Random; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; @@ -88,21 +87,15 @@ void standaloneSecretLockAndProofTransaction(Account from, Address to, HashType String secret = Hex.toHexString(result); String proof = Hex.toHexString(secretBytes); // make a secret lock moving mosaic to the target account - SecretLockTransaction secretLocktx = SecretLockTransaction.create(getDeadline(), - NetworkCurrencyMosaic.ONE, - BigInteger.valueOf(10), - hashType, - secret, - to, - getNetworkType()); + SecretLockTransaction secretLocktx = transact.secretLock().mosaic(NetworkCurrencyMosaic.ONE) + .duration(BigInteger.valueOf(10)).hashType(hashType).secret(secret).recipient(to).build(); SignedTransaction secretLockTransactionSigned = api.sign(secretLocktx, from); transactionHttp.announce(secretLockTransactionSigned).blockingFirst(); logger.info("Lock confirmed: {}", listener.confirmed(from.getAddress()).timeout(getTimeoutSeconds(), TimeUnit.SECONDS).blockingFirst()); sleepForAWhile(); - - SecretProofTransaction secretProoftx = SecretProofTransaction - .create(getDeadline(), hashType, Recipient.from(to), secret, proof, getNetworkType()); + SecretProofTransaction secretProoftx = transact.secretProof().hashType(hashType).secret(secret).proof(proof) + .recipient(Recipient.from(to)).build(); SignedTransaction secretProoftxSigned = api.sign(secretProoftx, from); transactionHttp.announce(secretProoftxSigned).blockingFirst(); logger.info("Proof confirmed: {}", @@ -114,22 +107,22 @@ void standaloneSecretLockAndProofTransaction(Account from, Address to, HashType void aggregateSecretLockAndProofTransaction_SHA3_256() { aggregateSecretLockAndProofTransaction(seedAccount, simpleAccount.getAddress(), HashType.SHA3_256); } - + @Test void aggregateSecretLockandProofTransaction_KECCAK_256() { aggregateSecretLockAndProofTransaction(seedAccount, simpleAccount.getAddress(), HashType.KECCAK_256); } - + @Test void aggregateSecretLockAndProofTransaction_HASH_160() { aggregateSecretLockAndProofTransaction(seedAccount, simpleAccount.getAddress(), HashType.HASH_160); } - + @Test void aggregateSecretLockAndProofTransaction_HASH_256() { aggregateSecretLockAndProofTransaction(seedAccount, simpleAccount.getAddress(), HashType.HASH_256); } - + void aggregateSecretLockAndProofTransaction(Account from, Address to, HashType hashType) { logger.info("Creating aggregate lock and proof for {}", hashType); byte[] secretBytes = new byte[20]; @@ -138,13 +131,8 @@ void aggregateSecretLockAndProofTransaction(Account from, Address to, HashType h String secret = Hex.toHexString(result); String proof = Hex.toHexString(secretBytes); // make a secret lock moving mosaic to the target account - SecretLockTransaction secretLocktx = SecretLockTransaction.create(getDeadline(), - NetworkCurrencyMosaic.ONE, - BigInteger.valueOf(10), - hashType, - secret, - to, - getNetworkType()); + SecretLockTransaction secretLocktx = transact.secretLock().mosaic(NetworkCurrencyMosaic.ONE) + .duration(BigInteger.valueOf(10)).hashType(hashType).secret(secret).recipient(to).build(); SignedTransaction lockFundsTransactionSigned = api.sign(secretLocktx, from); transactionHttp.announce(lockFundsTransactionSigned).blockingFirst(); logger.info("Lock confirmed: {}", @@ -152,11 +140,10 @@ void aggregateSecretLockAndProofTransaction(Account from, Address to, HashType h sleepForAWhile(); // create aggregate proof - SecretProofTransaction secretProoftx = SecretProofTransaction - .create(getDeadline(), hashType, Recipient.from(to), secret, proof, getNetworkType()); - AggregateTransaction secretProofAggregatetx = AggregateTransaction.createComplete(getDeadline(), - Collections.singletonList(secretProoftx.toAggregate(from.getPublicAccount())), - getNetworkType()); + SecretProofTransaction secretProoftx = transact.secretProof().hashType(hashType).secret(secret).proof(proof) + .recipient(Recipient.from(to)).build(); + AggregateTransaction secretProofAggregatetx = transact.aggregateComplete() + .innerTransactions(secretProoftx.toAggregate(from.getPublicAccount())).build(); SignedTransaction secretProofTransactionSigned = api.sign(secretProofAggregatetx, from); transactionHttp.announce(secretProofTransactionSigned).blockingFirst(); diff --git a/src/e2e/java/io/proximax/sdk/E2ETransferTest.java b/src/e2e/java/io/proximax/sdk/E2ETransferTest.java index 7279741e..f8f6f6cd 100644 --- a/src/e2e/java/io/proximax/sdk/E2ETransferTest.java +++ b/src/e2e/java/io/proximax/sdk/E2ETransferTest.java @@ -18,8 +18,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import java.math.BigInteger; -import java.util.Arrays; -import java.util.Collections; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; @@ -86,22 +84,22 @@ void sendSecureMessage() { SecureMessage secureMessage = SecureMessage.create(seedAccount.getKeyPair().getPrivateKey(), simpleAccount.getKeyPair().getPublicKey(), "java SDK secure message"); - transfer(seedAccount, simpleAccount.getAddress(), NetworkCurrencyMosaic.createAbsolute(BigInteger.valueOf(1)), secureMessage); + transfer(seedAccount, + simpleAccount.getAddress(), + NetworkCurrencyMosaic.createAbsolute(BigInteger.valueOf(1)), + secureMessage); } @Test void insufficientFunds() { - TransferTransaction transaction = TransferTransaction.create(getDeadline(), - seedAccount.getAddress(), - Arrays.asList(NetworkCurrencyMosaic.TEN), - PlainMessage.Empty, - getNetworkType()); + TransferTransaction transaction = transact.transfer().to(seedAccount.getAddress()) + .mosaics(NetworkCurrencyMosaic.TEN).build(); SignedTransaction signedTransaction = api.sign(transaction, simpleAccount); transactionHttp.announce(signedTransaction).blockingFirst(); // await error listener.status(simpleAccount.getAddress()).timeout(getTimeoutSeconds(), TimeUnit.SECONDS).blockingFirst(); } - + /** * return transactions as specified by arguments signed by the signer account * @@ -112,9 +110,8 @@ void insufficientFunds() { * @return instance of signed transaction which can be then announced to the network */ private SignedTransaction signTransfer(Account signerAccount, Address target, Mosaic amount, Message message) { - TransferTransaction transaction = TransferTransaction - .create(getDeadline(), target, Collections.singletonList(amount), message, getNetworkType()); - return signerAccount.sign(transaction, api.getNetworkGenerationHash()); + TransferTransaction transaction = transact.transfer().mosaics(amount).to(target).message(message).build(); + return api.sign(transaction, signerAccount); } /** @@ -128,13 +125,12 @@ private SignedTransaction signTransfer(Account signerAccount, Address target, Mo */ private SignedTransaction signAggregateTransfer(Account signerAccount, Address target, Mosaic amount, Message message) { - TransferTransaction transfer = TransferTransaction - .create(getDeadline(), target, Collections.singletonList(amount), message, getNetworkType()); + TransferTransaction transfer = transact.transfer().mosaics(amount).to(target).message(message).build(); // add the modification to the aggregate transaction. has to be bonded because we are going to test the lock - AggregateTransaction aggregateTransaction = AggregateTransaction.createComplete(getDeadline(), - Arrays.asList(transfer.toAggregate(signerAccount.getPublicAccount())), - getNetworkType()); - return signerAccount.sign(aggregateTransaction, api.getNetworkGenerationHash()); + AggregateTransaction aggregateTransaction = transact.aggregateComplete() + .innerTransactions(transfer.toAggregate(signerAccount.getPublicAccount())).build(); + // return signed transaction + return api.sign(aggregateTransaction, signerAccount); } /** diff --git a/src/e2e/java/io/proximax/sdk/infrastructure/ListenerTest.java b/src/e2e/java/io/proximax/sdk/infrastructure/ListenerTest.java index 2ffd3aa8..da369af0 100644 --- a/src/e2e/java/io/proximax/sdk/infrastructure/ListenerTest.java +++ b/src/e2e/java/io/proximax/sdk/infrastructure/ListenerTest.java @@ -16,16 +16,14 @@ package io.proximax.sdk.infrastructure; -import static java.time.temporal.ChronoUnit.HOURS; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; import java.math.BigDecimal; +import java.math.BigInteger; import java.net.URL; -import java.util.Arrays; -import java.util.Collections; import java.util.List; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; @@ -38,6 +36,7 @@ import io.proximax.sdk.AccountRepository; import io.proximax.sdk.BaseTest; import io.proximax.sdk.BlockchainApi; +import io.proximax.sdk.FeeCalculationStrategy; import io.proximax.sdk.ListenerRepository; import io.proximax.sdk.TransactionRepository; import io.proximax.sdk.model.account.Account; @@ -48,17 +47,18 @@ import io.proximax.sdk.model.transaction.AggregateTransaction; import io.proximax.sdk.model.transaction.CosignatureSignedTransaction; import io.proximax.sdk.model.transaction.CosignatureTransaction; -import io.proximax.sdk.model.transaction.Deadline; import io.proximax.sdk.model.transaction.PlainMessage; import io.proximax.sdk.model.transaction.SignedTransaction; import io.proximax.sdk.model.transaction.Transaction; import io.proximax.sdk.model.transaction.TransactionStatusError; import io.proximax.sdk.model.transaction.TransferTransaction; +import io.proximax.sdk.model.transaction.builder.TransactionBuilderFactory; @TestInstance(TestInstance.Lifecycle.PER_CLASS) @Disabled("listeners are used by other tests") class ListenerTest extends BaseTest { private BlockchainApi api; + private TransactionBuilderFactory transact; private TransactionRepository transactionHttp; private AccountRepository accountHttp; private Account account; @@ -69,6 +69,8 @@ class ListenerTest extends BaseTest { @BeforeAll void setup() throws IOException { api = new BlockchainApi(new URL(getNodeUrl()), getNetworkType()); + transact = api.transact().setDeadlineMillis(BigInteger.valueOf(3_600_000)) + .setFeeCalculationStrategy(FeeCalculationStrategy.ZERO); transactionHttp = api.createTransactionRepository(); accountHttp = api.createAccountRepository(); account = new Account("787225aaff3d2c71f4ffa32d4f19ec4922f3cd869747f267378f81f8e3fcb12d", NetworkType.MIJIN_TEST); @@ -218,12 +220,8 @@ void shouldReturnTransactionStatusGivenAddedViaListener() } private SignedTransaction announceStandaloneTransferTransaction() throws ExecutionException, InterruptedException { - TransferTransaction transferTransaction = TransferTransaction.create(new Deadline(2, HOURS), - new Address("SBILTA367K2LX2FEXG5TFWAS7GEFYAGY7QLFBYKC", NetworkType.MIJIN_TEST), - Arrays.asList(), - PlainMessage.create("test-message"), - NetworkType.MIJIN_TEST); - + TransferTransaction transferTransaction = transact.transfer().message(PlainMessage.create("test-message")) + .to(new Address("SBILTA367K2LX2FEXG5TFWAS7GEFYAGY7QLFBYKC", NetworkType.MIJIN_TEST)).build(); SignedTransaction signedTransaction = this.account.sign(transferTransaction, api.getNetworkGenerationHash()); transactionHttp.announce(signedTransaction).toFuture().get(); return signedTransaction; @@ -231,11 +229,10 @@ private SignedTransaction announceStandaloneTransferTransaction() throws Executi private SignedTransaction announceStandaloneTransferTransactionWithInsufficientBalance() throws ExecutionException, InterruptedException { - TransferTransaction transferTransaction = TransferTransaction.create(new Deadline(2, HOURS), - new Address("SBILTA367K2LX2FEXG5TFWAS7GEFYAGY7QLFBYKC", NetworkType.MIJIN_TEST), - Arrays.asList(NetworkCurrencyMosaic.createRelative(new BigDecimal("100000000000"))), - PlainMessage.create("test-message"), - NetworkType.MIJIN_TEST); + TransferTransaction transferTransaction = transact.transfer() + .mosaics(NetworkCurrencyMosaic.createRelative(new BigDecimal("100000000000"))) + .message(PlainMessage.create("test-message")) + .to(new Address("SBILTA367K2LX2FEXG5TFWAS7GEFYAGY7QLFBYKC", NetworkType.MIJIN_TEST)).build(); SignedTransaction signedTransaction = this.account.sign(transferTransaction, api.getNetworkGenerationHash()); transactionHttp.announce(signedTransaction).toFuture().get(); @@ -243,17 +240,14 @@ private SignedTransaction announceStandaloneTransferTransactionWithInsufficientB } private SignedTransaction announceAggregateBondedTransaction() throws ExecutionException, InterruptedException { - TransferTransaction transferTransaction = TransferTransaction.create(new Deadline(2, HOURS), - new Address("SBILTA367K2LX2FEXG5TFWAS7GEFYAGY7QLFBYKC", NetworkType.MIJIN_TEST), - Arrays.asList(), - PlainMessage.create("test-message"), - NetworkType.MIJIN_TEST); + TransferTransaction transferTransaction = transact.transfer().message(PlainMessage.create("test-message")) + .to(new Address("SBILTA367K2LX2FEXG5TFWAS7GEFYAGY7QLFBYKC", NetworkType.MIJIN_TEST)).build(); - AggregateTransaction aggregateTransaction = AggregateTransaction.createComplete(new Deadline(2, HOURS), - Collections.singletonList(transferTransaction.toAggregate(this.multisigAccount.getPublicAccount())), - NetworkType.MIJIN_TEST); + AggregateTransaction aggregateTransaction = transact.aggregateBonded() + .innerTransactions(transferTransaction.toAggregate(this.multisigAccount.getPublicAccount())).build(); - SignedTransaction signedTransaction = this.cosignatoryAccount.sign(aggregateTransaction, api.getNetworkGenerationHash()); + SignedTransaction signedTransaction = this.cosignatoryAccount.sign(aggregateTransaction, + api.getNetworkGenerationHash()); transactionHttp.announceAggregateBonded(signedTransaction).toFuture().get(); diff --git a/src/main/java/io/proximax/sdk/BlockchainApi.java b/src/main/java/io/proximax/sdk/BlockchainApi.java index f4d1e6ba..06b2168d 100644 --- a/src/main/java/io/proximax/sdk/BlockchainApi.java +++ b/src/main/java/io/proximax/sdk/BlockchainApi.java @@ -33,11 +33,15 @@ import io.proximax.sdk.model.transaction.AggregateTransaction; import io.proximax.sdk.model.transaction.SignedTransaction; import io.proximax.sdk.model.transaction.Transaction; +import io.proximax.sdk.model.transaction.builder.TransactionBuilderFactory; /** * Central API for blockchain interaction */ public class BlockchainApi { + /** default fee calculation strategy */ + public static final FeeCalculationStrategy DEFAULT_FEE_CALCULATION_STRATEGY = FeeCalculationStrategy.MEDIUM; + /** URL of the node */ private final URL url; /** network type of the node */ @@ -216,4 +220,13 @@ public synchronized String getNetworkGenerationHash() { private NetworkType queryForNetworkType() { return createBlockchainRepository().getNetworkType().timeout(30, TimeUnit.SECONDS).blockingFirst(); } + + /** + * @return the factory to get transaction builders + */ + public TransactionBuilderFactory transact() { + TransactionBuilderFactory fac = new TransactionBuilderFactory(); + fac.setNetworkType(getNetworkType()); + return fac; + } } diff --git a/src/main/java/io/proximax/sdk/FeeCalculationStrategy.java b/src/main/java/io/proximax/sdk/FeeCalculationStrategy.java new file mode 100644 index 00000000..c3679eed --- /dev/null +++ b/src/main/java/io/proximax/sdk/FeeCalculationStrategy.java @@ -0,0 +1,46 @@ +/* + * Copyright 2019 ProximaX Limited. All rights reserved. + * Use of this source code is governed by the Apache 2.0 + * license that can be found in the LICENSE file. + */ +package io.proximax.sdk; + +import java.math.BigInteger; + +/** + * Fee calculation strategies for transactions + */ +public enum FeeCalculationStrategy { + ZERO(0), + LOW(25), + MEDIUM(250), + HIGH(2500); + + private static final int MAX_FEE = 5_000_000; + + private final int coefficient; + + /** + * @param coefficient + */ + private FeeCalculationStrategy(int coefficient) { + this.coefficient = coefficient; + } + + /** + * @return the coefficient + */ + public int getCoefficient() { + return coefficient; + } + + /** + * calculate fee based on the transaction size + * + * @param transactionSize size of transaction when serialized + * @return the default maxFee + */ + public BigInteger calculateFee(int transactionSize) { + return BigInteger.valueOf(Math.min(MAX_FEE, transactionSize * getCoefficient())); + } +} diff --git a/src/main/java/io/proximax/sdk/infrastructure/TransactionMapping.java b/src/main/java/io/proximax/sdk/infrastructure/TransactionMapping.java index a27ea92e..9d879c1e 100644 --- a/src/main/java/io/proximax/sdk/infrastructure/TransactionMapping.java +++ b/src/main/java/io/proximax/sdk/infrastructure/TransactionMapping.java @@ -186,11 +186,17 @@ public TransferTransaction apply(JsonObject input) { // version JsonElement version = transaction.get("version"); // create transfer transaction instance - return new TransferTransaction(extractNetworkType(version), extractTransactionVersion(version), deadline, + return new TransferTransaction( + extractNetworkType(version), + extractTransactionVersion(version), + deadline, extractFee(transaction), - Recipient.from(Address.createFromEncoded(transaction.get("recipient").getAsString())), mosaics, message, - transaction.get("signature").getAsString(), - new PublicAccount(transaction.get("signer").getAsString(), extractNetworkType(version)), transactionInfo); + Optional.of(transaction.get("signature").getAsString()), + Optional.of(new PublicAccount(transaction.get("signer").getAsString(), extractNetworkType(version))), + Optional.of(transactionInfo), + Recipient.from(Address.createFromEncoded(transaction.get("recipient").getAsString())), + mosaics, + message); } } @@ -225,19 +231,21 @@ public ModifyMetadataTransaction apply(JsonObject input) { switch (type) { case MODIFY_ADDRESS_METADATA: return new ModifyMetadataTransaction(type, extractNetworkType(version), extractTransactionVersion(version), - deadline, extractFee(transaction), Optional.empty(), - Optional.of(Address.createFromEncoded(transaction.get("metadataId").getAsString())), metadataType, - modifications, signature, signer, transactionInfo); + deadline, extractFee(transaction), Optional.of(signature), Optional.of(signer), + Optional.of(transactionInfo), metadataType, Optional.empty(), + Optional.of(Address.createFromEncoded(transaction.get("metadataId").getAsString())), modifications); case MODIFY_MOSAIC_METADATA: return new ModifyMetadataTransaction(type, extractNetworkType(version), extractTransactionVersion(version), - deadline, extractFee(transaction), - Optional.of(new MosaicId(GsonUtils.getBigInteger(transaction.getAsJsonArray("metadataId")))), Optional.empty(), - metadataType, modifications, signature, signer, transactionInfo); + deadline, extractFee(transaction), Optional.of(signature), Optional.of(signer), + Optional.of(transactionInfo), metadataType, + Optional.of(new MosaicId(GsonUtils.getBigInteger(transaction.getAsJsonArray("metadataId")))), + Optional.empty(), modifications); case MODIFY_NAMESPACE_METADATA: return new ModifyMetadataTransaction(type, extractNetworkType(version), extractTransactionVersion(version), - deadline, extractFee(transaction), + deadline, extractFee(transaction), Optional.of(signature), Optional.of(signer), + Optional.of(transactionInfo), metadataType, Optional.of(new NamespaceId(GsonUtils.getBigInteger(transaction.getAsJsonArray("metadataId")))), - Optional.empty(), metadataType, modifications, signature, signer, transactionInfo); + Optional.empty(), modifications); default: throw new IllegalArgumentException("unsupported transaction type " + type); } @@ -289,18 +297,17 @@ public ModifyAccountPropertyTransaction apply(JsonObject input) { // create instance of transaction switch (type) { case ACCOUNT_PROPERTIES_ADDRESS: - return new ModifyAccountPropertyTransaction.AddressModification(extractNetworkType(version), - extractTransactionVersion(version), deadline, extractFee(transaction), propertyType, - getAddressMods(transaction), Optional.of(signature), Optional.of(signer), Optional.of(transactionInfo)); + return new ModifyAccountPropertyTransaction.AddressModification(extractNetworkType(version), extractTransactionVersion(version), deadline, extractFee(transaction), + Optional.of(signature), Optional.of(signer), Optional.of(transactionInfo), + propertyType, getAddressMods(transaction)); case ACCOUNT_PROPERTIES_MOSAIC: - return new ModifyAccountPropertyTransaction.MosaicModification(extractNetworkType(version), - extractTransactionVersion(version), deadline, extractFee(transaction), propertyType, - getMosaicMods(transaction), Optional.of(signature), Optional.of(signer), Optional.of(transactionInfo)); + return new ModifyAccountPropertyTransaction.MosaicModification(extractNetworkType(version), extractTransactionVersion(version), deadline, extractFee(transaction), + Optional.of(signature), Optional.of(signer), Optional.of(transactionInfo), + propertyType, getMosaicMods(transaction)); case ACCOUNT_PROPERTIES_ENTITY_TYPE: - return new ModifyAccountPropertyTransaction.EntityTypeModification(extractNetworkType(version), - extractTransactionVersion(version), deadline, extractFee(transaction), propertyType, - getEntityTypeMods(transaction), Optional.of(signature), Optional.of(signer), - Optional.of(transactionInfo)); + return new ModifyAccountPropertyTransaction.EntityTypeModification(extractNetworkType(version), extractTransactionVersion(version), deadline, extractFee(transaction), + Optional.of(signature), Optional.of(signer), Optional.of(transactionInfo), + propertyType, getEntityTypeMods(transaction)); default: throw new IllegalArgumentException("unsupported transaction type " + type); } @@ -387,9 +394,10 @@ public RegisterNamespaceTransaction apply(JsonObject input) { JsonElement version = transaction.get("version"); // return the register namespace transaction return new RegisterNamespaceTransaction(extractNetworkType(version), extractTransactionVersion(version), deadline, - extractFee(transaction), transaction.get("name").getAsString(), namespaceId, namespaceType, - namespaceDuration, namespaceParentId, transaction.get("signature").getAsString(), - new PublicAccount(transaction.get("signer").getAsString(), extractNetworkType(version)), transactionInfo); + extractFee(transaction), Optional.of(transaction.get("signature").getAsString()), + Optional.of(new PublicAccount(transaction.get("signer").getAsString(), extractNetworkType(version))), + Optional.of(transactionInfo), transaction.get("name").getAsString(), namespaceId, namespaceDuration, + namespaceParentId, namespaceType); } } @@ -409,10 +417,11 @@ public MosaicDefinitionTransaction apply(JsonObject input) { JsonElement version = transaction.get("version"); // return instance of mosaic definition transaction return new MosaicDefinitionTransaction(extractNetworkType(version), extractTransactionVersion(version), deadline, - extractFee(transaction), extractNonce(transaction), + extractFee(transaction), Optional.of(transaction.get("signature").getAsString()), + Optional.of(new PublicAccount(transaction.get("signer").getAsString(), extractNetworkType(version))), + Optional.of(transactionInfo), extractNonce(transaction), new MosaicId(GsonUtils.getBigInteger(transaction.getAsJsonArray("mosaicId"))), - extractProperties(transaction.getAsJsonArray("properties")), transaction.get("signature").getAsString(), - new PublicAccount(transaction.get("signer").getAsString(), extractNetworkType(version)), transactionInfo); + extractProperties(transaction.getAsJsonArray("properties"))); } private static MosaicProperties extractProperties(JsonArray props) { @@ -473,22 +482,12 @@ public AliasTransaction apply(JsonObject input) { // return instance of mosaic alias definition transaction return new AliasTransaction(TransactionType.MOSAIC_ALIAS, extractNetworkType(version), extractTransactionVersion(version), deadline, extractFee(transaction), - Optional.of(new MosaicId(GsonUtils.getBigInteger(transaction.getAsJsonArray("mosaicId")))), Optional.empty(), - new NamespaceId(GsonUtils.getBigInteger(transaction.getAsJsonArray("namespaceId"))), - extractAliasAction(transaction), transaction.get("signature").getAsString(), - new PublicAccount(transaction.get("signer").getAsString(), extractNetworkType(version)), transactionInfo); - } - - private static AliasAction extractAliasAction(JsonObject json) { - Integer aliasCode; - // try aliasAction field - if (json.has("aliasAction")) { - aliasCode = json.get("aliasAction").getAsInt(); - } else { - // try alias - aliasCode = json.get("action").getAsInt(); - } - return AliasAction.getByCode(aliasCode); + Optional.of(transaction.get("signature").getAsString()), + Optional.of(new PublicAccount(transaction.get("signer").getAsString(), extractNetworkType(version))), + Optional.of(transactionInfo), + Optional.of(new MosaicId(GsonUtils.getBigInteger(transaction.getAsJsonArray("mosaicId")))), + Optional.empty(), new NamespaceId(GsonUtils.getBigInteger(transaction.getAsJsonArray("namespaceId"))), + AliasAction.getByCode(transaction.get("aliasAction").getAsInt())); } } @@ -507,12 +506,13 @@ public AliasTransaction apply(JsonObject input) { JsonElement version = transaction.get("version"); // return instance of mosaic alias definition transaction return new AliasTransaction(TransactionType.ADDRESS_ALIAS, extractNetworkType(version), - extractTransactionVersion(version), deadline, extractFee(transaction), Optional.empty(), + extractTransactionVersion(version), deadline, extractFee(transaction), + Optional.of(transaction.get("signature").getAsString()), + Optional.of(new PublicAccount(transaction.get("signer").getAsString(), extractNetworkType(version))), + Optional.of(transactionInfo), Optional.empty(), Optional.of(Address.createFromEncoded(transaction.get("address").getAsString())), new NamespaceId(GsonUtils.getBigInteger(transaction.getAsJsonArray("namespaceId"))), - AliasAction.getByCode(transaction.get("aliasAction").getAsInt()), - transaction.get("signature").getAsString(), - new PublicAccount(transaction.get("signer").getAsString(), extractNetworkType(version)), transactionInfo); + AliasAction.getByCode(transaction.get("aliasAction").getAsInt())); } } @@ -527,11 +527,12 @@ public MosaicSupplyChangeTransaction apply(JsonObject input) { return new MosaicSupplyChangeTransaction(extractNetworkType(transaction.get("version")), extractTransactionVersion(transaction.get("version")), deadline, extractFee(transaction), - new MosaicId(GsonUtils.getBigInteger(transaction.getAsJsonArray("mosaicId"))), + Optional.of(transaction.get("signature").getAsString()), + Optional.of(new PublicAccount(transaction.get("signer").getAsString(), + extractNetworkType(transaction.get("version")))), + Optional.of(transactionInfo), new MosaicId(GsonUtils.getBigInteger(transaction.getAsJsonArray("mosaicId"))), MosaicSupplyType.rawValueOf(transaction.get("direction").getAsInt()), - GsonUtils.getBigInteger(transaction.getAsJsonArray("delta")), transaction.get("signature").getAsString(), - new PublicAccount(transaction.get("signer").getAsString(), extractNetworkType(transaction.get("version"))), - transactionInfo); + GsonUtils.getBigInteger(transaction.getAsJsonArray("delta"))); } } @@ -556,9 +557,11 @@ public ModifyMultisigAccountTransaction apply(JsonObject input) { : Collections.emptyList(); return new ModifyMultisigAccountTransaction(networkType, extractTransactionVersion(transaction.get("version")), - deadline, extractFee(transaction), transaction.get("minApprovalDelta").getAsInt(), - transaction.get("minRemovalDelta").getAsInt(), modifications, transaction.get("signature").getAsString(), - new PublicAccount(transaction.get("signer").getAsString(), networkType), transactionInfo); + deadline, extractFee(transaction), Optional.of(transaction.get("signature").getAsString()), + Optional.of(new PublicAccount(transaction.get("signer").getAsString(), networkType)), + Optional.of(transactionInfo), transaction.get("minApprovalDelta").getAsInt(), + transaction.get("minRemovalDelta").getAsInt(), modifications); + } } @@ -640,11 +643,17 @@ public AggregateTransaction apply(JsonObject input) { new PublicAccount(aggregateCosignature.get("signer").getAsString(), networkType))) .collect(Collectors.toList()); } - - return new AggregateTransaction(networkType, TransactionType.rawValueOf(transaction.get("type").getAsInt()), - extractTransactionVersion(transaction.get("version")), deadline, extractFee(transaction), transactions, - cosignatures, transaction.get("signature").getAsString(), - new PublicAccount(transaction.get("signer").getAsString(), networkType), transactionInfo); + return new AggregateTransaction( + TransactionType.rawValueOf(transaction.get("type").getAsInt()), + networkType, + extractTransactionVersion(transaction.get("version")), + deadline, + extractFee(transaction), + Optional.of(transaction.get("signature").getAsString()), + Optional.of(new PublicAccount(transaction.get("signer").getAsString(), networkType)), + Optional.of(transactionInfo), + transactions, + cosignatures); } /** @@ -682,11 +691,16 @@ public LockFundsTransaction apply(JsonObject input) { new MosaicId(GsonUtils.getBigInteger(transaction.getAsJsonObject("mosaic").getAsJsonArray("id"))), GsonUtils.getBigInteger(transaction.getAsJsonObject("mosaic").getAsJsonArray("amount"))); } - return new LockFundsTransaction(networkType, extractTransactionVersion(transaction.get("version")), deadline, - extractFee(transaction), mosaic, GsonUtils.getBigInteger(transaction.getAsJsonArray("duration")), - new SignedTransaction("", transaction.get("hash").getAsString(), TransactionType.AGGREGATE_BONDED), - transaction.get("signature").getAsString(), - new PublicAccount(transaction.get("signer").getAsString(), networkType), transactionInfo); + return new LockFundsTransaction(networkType, + extractTransactionVersion(transaction.get("version")), + deadline, + extractFee(transaction), + Optional.of(transaction.get("signature").getAsString()), + Optional.of(new PublicAccount(transaction.get("signer").getAsString(), networkType)), + Optional.of(transactionInfo), + mosaic, + GsonUtils.getBigInteger(transaction.getAsJsonArray("duration")), + new SignedTransaction("", transaction.get("hash").getAsString(), TransactionType.AGGREGATE_BONDED)); } } @@ -709,11 +723,11 @@ public SecretLockTransaction apply(JsonObject input) { GsonUtils.getBigInteger(transaction.getAsJsonObject("mosaic").getAsJsonArray("amount"))); } return new SecretLockTransaction(networkType, extractTransactionVersion(transaction.get("version")), deadline, - extractFee(transaction), mosaic, GsonUtils.getBigInteger(transaction.getAsJsonArray("duration")), + extractFee(transaction), Optional.of(transaction.get("signature").getAsString()), + Optional.of(new PublicAccount(transaction.get("signer").getAsString(), networkType)), + Optional.of(transactionInfo), mosaic, GsonUtils.getBigInteger(transaction.getAsJsonArray("duration")), HashType.rawValueOf(transaction.get("hashAlgorithm").getAsInt()), transaction.get("secret").getAsString(), - Address.createFromEncoded(transaction.get("recipient").getAsString()), - transaction.get("signature").getAsString(), - new PublicAccount(transaction.get("signer").getAsString(), networkType), transactionInfo); + Address.createFromEncoded(transaction.get("recipient").getAsString())); } } @@ -728,11 +742,11 @@ public SecretProofTransaction apply(JsonObject input) { NetworkType networkType = extractNetworkType(transaction.get("version")); return new SecretProofTransaction(networkType, extractTransactionVersion(transaction.get("version")), deadline, - extractFee(transaction), HashType.rawValueOf(transaction.get("hashAlgorithm").getAsInt()), - Recipient.from(Address.createFromEncoded(transaction.get("recipient").getAsString())), + extractFee(transaction), Optional.of(transaction.get("signature").getAsString()), + Optional.of(new PublicAccount(transaction.get("signer").getAsString(), networkType)), + Optional.of(transactionInfo), HashType.rawValueOf(transaction.get("hashAlgorithm").getAsInt()), transaction.get("secret").getAsString(), transaction.get("proof").getAsString(), - transaction.get("signature").getAsString(), - new PublicAccount(transaction.get("signer").getAsString(), networkType), transactionInfo); + Recipient.from(Address.createFromEncoded(transaction.get("recipient").getAsString()))); } } @@ -749,13 +763,16 @@ public AccountLinkTransaction apply(JsonObject input) { JsonObject transaction = input.getAsJsonObject("transaction"); DeadlineBP deadline = new DeadlineBP(GsonUtils.getBigInteger(transaction.getAsJsonArray("deadline"))); NetworkType networkType = extractNetworkType(transaction.get("version")); - return new AccountLinkTransaction( + networkType, + extractTransactionVersion(transaction.get("version")), + deadline, + extractFee(transaction), + Optional.of(transaction.get("signature").getAsString()), + Optional.of(new PublicAccount(transaction.get("signer").getAsString(), networkType)), + Optional.of(transactionInfo), new PublicAccount(transaction.get("remoteAccountKey").getAsString(), networkType), - AccountLinkAction.getByCode(getAction(transaction).getAsByte()), networkType, - extractTransactionVersion(transaction.get("version")), deadline, extractFee(transaction), - transaction.get("signature").getAsString(), - new PublicAccount(transaction.get("signer").getAsString(), networkType), transactionInfo); + AccountLinkAction.getByCode(getAction(transaction).getAsByte())); } /** diff --git a/src/main/java/io/proximax/sdk/model/transaction/AccountLinkTransaction.java b/src/main/java/io/proximax/sdk/model/transaction/AccountLinkTransaction.java index 6102793d..fe69bc5f 100644 --- a/src/main/java/io/proximax/sdk/model/transaction/AccountLinkTransaction.java +++ b/src/main/java/io/proximax/sdk/model/transaction/AccountLinkTransaction.java @@ -23,82 +23,31 @@ */ public class AccountLinkTransaction extends Transaction { private final AccountLinkTransactionSchema schema = new AccountLinkTransactionSchema(); + private final PublicAccount remoteAccount; private final AccountLinkAction action; /** - * Create new instance of account link transaction - * - * @param remoteAccount account to manage link for - * @param action link action to perform * @param networkType network type - * @param version transaction version + * @param version transaction version. Use {@link TransactionVersion#ACCOUNT_LINK} for current version * @param deadline transaction deadline - * @param fee transaction fee - * @param signature signature - * @param signer signer - * @param transactionInfo transaction information + * @param maxFee transaction fee + * @param signature optional signature + * @param signer optional signer + * @param transactionInfo optional transaction info + * @param remoteAccount remote account + * @param action link/unlink action */ - private AccountLinkTransaction(PublicAccount remoteAccount, AccountLinkAction action, NetworkType networkType, - Integer version, TransactionDeadline deadline, BigInteger fee, Optional signature, - Optional signer, Optional transactionInfo) { - super(TransactionType.ACCOUNT_LINK, networkType, version, deadline, fee, signature, signer, transactionInfo); + public AccountLinkTransaction(NetworkType networkType, Integer version, TransactionDeadline deadline, + BigInteger maxFee, Optional signature, Optional signer, + Optional transactionInfo, PublicAccount remoteAccount, AccountLinkAction action) { + super(TransactionType.ACCOUNT_LINK, networkType, version, deadline, maxFee, signature, signer, transactionInfo); Validate.notNull(remoteAccount, "remoteAccount has to be specified"); Validate.notNull(action, "action has to be specified"); this.remoteAccount = remoteAccount; this.action = action; } - /** - * Create new instance of account link transaction - * - * @param remoteAccount account to manage link for - * @param action link action to perform - * @param networkType network type - * @param version transaction version - * @param deadline transaction deadline - * @param fee transaction fee - * @param signature signature - * @param signer signer - * @param transactionInfo transaction information - */ - public AccountLinkTransaction(PublicAccount remoteAccount, AccountLinkAction action, NetworkType networkType, - Integer version, TransactionDeadline deadline, BigInteger fee, String signature, PublicAccount signer, - TransactionInfo transactionInfo) { - this(remoteAccount, action, networkType, version, deadline, fee, Optional.of(signature), Optional.of(signer), - Optional.of(transactionInfo)); - } - - /** - * Create new instance of account link transaction - * - * @param remoteAccount account to manage link for - * @param action link action to perform - * @param networkType network type - * @param deadline transaction deadline - * @param fee transaction fee - */ - public AccountLinkTransaction(PublicAccount remoteAccount, AccountLinkAction action, NetworkType networkType, - TransactionDeadline deadline, BigInteger fee) { - this(remoteAccount, action, networkType, TransactionVersion.ACCOUNT_LINK.getValue(), deadline, fee, - Optional.empty(), Optional.empty(), Optional.empty()); - } - - /** - * Create new instance of account link transaction - * - * @param deadline transaction deadline - * @param fee transaction fee - * @param remoteAccount account to manage link for - * @param action link action to perform - * @param networkType network type - * @return account link transaction instance - */ - public static AccountLinkTransaction create(TransactionDeadline deadline, BigInteger fee, - PublicAccount remoteAccount, AccountLinkAction action, NetworkType networkType) { - return new AccountLinkTransaction(remoteAccount, action, networkType, deadline, fee); - } - /** * @return the remoteAccount */ @@ -114,7 +63,7 @@ public AccountLinkAction getAction() { } @Override - byte[] generateBytes() { + protected byte[] generateBytes() { FlatBufferBuilder builder = new FlatBufferBuilder(); // prepare data BigInteger deadlineBigInt = BigInteger.valueOf(getDeadline().getInstant()); @@ -125,16 +74,12 @@ byte[] generateBytes() { int signerVector = AccountLinkTransactionBuffer.createSignerVector(builder, new byte[32]); int deadlineVector = AccountLinkTransactionBuffer.createDeadlineVector(builder, UInt64Utils.fromBigInteger(deadlineBigInt)); - int feeVector = AccountLinkTransactionBuffer.createMaxFeeVector(builder, UInt64Utils.fromBigInteger(getFee())); + int feeVector = AccountLinkTransactionBuffer.createMaxFeeVector(builder, UInt64Utils.fromBigInteger(getMaxFee())); int remoteAccountVector = AccountLinkTransactionBuffer.createRemoteAccountKeyVector(builder, remoteAccountPublicKey); // total size of transaction - int size = HEADER_SIZE + - // remote account public key - 32 + - // link action - 1; + int size = getSerializedSize(); // flatbuffer serialization AccountLinkTransactionBuffer.startAccountLinkTransactionBuffer(builder); @@ -157,4 +102,20 @@ byte[] generateBytes() { return output; } + public static int calculatePayloadSize() { + // remote account public key + link action + return 32 + 1; + } + + @Override + protected int getPayloadSerializedSize() { + return calculatePayloadSize(); + } + + @Override + protected Transaction copyForSigner(PublicAccount signer) { + return new AccountLinkTransaction(getNetworkType(), getVersion(), getDeadline(), getMaxFee(), getSignature(), + Optional.of(signer), getTransactionInfo(), getRemoteAccount(), getAction()); + } + } diff --git a/src/main/java/io/proximax/sdk/model/transaction/AggregateTransaction.java b/src/main/java/io/proximax/sdk/model/transaction/AggregateTransaction.java index af885fdb..4e0576c5 100644 --- a/src/main/java/io/proximax/sdk/model/transaction/AggregateTransaction.java +++ b/src/main/java/io/proximax/sdk/model/transaction/AggregateTransaction.java @@ -17,7 +17,7 @@ package io.proximax.sdk.model.transaction; import java.math.BigInteger; -import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Optional; @@ -39,71 +39,56 @@ * @since 1.0 */ public class AggregateTransaction extends Transaction { - private final List innerTransactions; - private final List cosignatures; private final Schema schema = new AggregateTransactionSchema(); - public AggregateTransaction(NetworkType networkType, TransactionType transactionType, Integer version, - TransactionDeadline deadline, BigInteger fee, List innerTransactions, - List cosignatures, String signature, PublicAccount signer, - TransactionInfo transactionInfo) { - this(networkType, transactionType, version, deadline, fee, innerTransactions, cosignatures, - Optional.of(signature), Optional.of(signer), Optional.of(transactionInfo)); - } + private final List innerTransactions; + private final List cosignatures; - public AggregateTransaction(NetworkType networkType, TransactionType transactionType, Integer version, - TransactionDeadline deadline, BigInteger fee, List innerTransactions, + /** + * @param type transaction type which has to be one of {@link TransactionType#AGGREGATE_COMPLETE} or + * {@link TransactionType#AGGREGATE_BONDED} + * @param networkType network type + * @param version transaction version. For latest {@link TransactionVersion#AGGREGATE_COMPLETE} or + * {@link TransactionVersion#AGGREGATE_BONDED} + * @param deadline transaction deadline + * @param maxFee transaction fee + * @param signature optional signature + * @param signer optional signer + * @param transactionInfo optional transaction info + * @param innerTransactions inner transactions of this aggregate transaction + * @param cosignatures available cosignatures if any + */ + public AggregateTransaction(TransactionType type, NetworkType networkType, Integer version, + TransactionDeadline deadline, BigInteger maxFee, Optional signature, + Optional signer, Optional transactionInfo, + List innerTransactions, List cosignatures) { - this(networkType, transactionType, version, deadline, fee, innerTransactions, cosignatures, Optional.empty(), - Optional.empty(), Optional.empty()); - } - - private AggregateTransaction(NetworkType networkType, TransactionType transactionType, Integer version, - TransactionDeadline deadline, BigInteger fee, List innerTransactions, - List cosignatures, Optional signature, Optional signer, - Optional transactionInfo) { - super(transactionType, networkType, version, deadline, fee, signature, signer, transactionInfo); + super(type, networkType, version, deadline, maxFee, signature, signer, transactionInfo); Validate.notNull(innerTransactions, "InnerTransactions must not be null"); Validate.notNull(cosignatures, "Cosignatures must not be null"); - this.innerTransactions = innerTransactions; - this.cosignatures = cosignatures; + Validate.validState(type == TransactionType.AGGREGATE_BONDED || type == TransactionType.AGGREGATE_COMPLETE, + "Transaction type has to be aggregate bonded or complete but was %s", + type); + this.innerTransactions = Collections.unmodifiableList(innerTransactions); + this.cosignatures = Collections.unmodifiableList(cosignatures); } /** - * Create an aggregate complete transaction object - * - * @param deadline The deadline to include the transaction. - * @param innerTransactions The list of inner innerTransactions. - * @param networkType The network type. - * @return {@link AggregateTransaction} - */ - public static AggregateTransaction createComplete(TransactionDeadline deadline, List innerTransactions, - NetworkType networkType) { - return new AggregateTransaction(networkType, TransactionType.AGGREGATE_COMPLETE, 2, deadline, - BigInteger.valueOf(0), innerTransactions, new ArrayList<>()); - } - - /** - * Create an aggregate bonded transaction object + * Returns list of innerTransactions included in the aggregate transaction. * - * @param deadline The deadline to include the transaction. - * @param innerTransactions The list of inner innerTransactions. - * @param networkType The network type. - * @return {@link AggregateTransaction} + * @return List of innerTransactions included in the aggregate transaction. */ - public static AggregateTransaction createBonded(TransactionDeadline deadline, List innerTransactions, - NetworkType networkType) { - return new AggregateTransaction(networkType, TransactionType.AGGREGATE_BONDED, 2, deadline, BigInteger.valueOf(0), - innerTransactions, new ArrayList<>()); + public List getInnerTransactions() { + return innerTransactions; } /** - * Returns list of innerTransactions included in the aggregate transaction. + * Returns list of transaction cosigners signatures. * - * @return List of innerTransactions included in the aggregate transaction. + * @return List of transaction cosigners signatures. */ - public List getInnerTransactions() { - return innerTransactions; + public List getCosignatures() { + return cosignatures; } /** @@ -122,15 +107,6 @@ public boolean isSignedByAccount(PublicAccount publicAccount) { } } - /** - * Returns list of transaction cosigners signatures. - * - * @return List of transaction cosigners signatures. - */ - public List getCosignatures() { - return cosignatures; - } - /** * Sign transaction with cosignatories creating a new SignedTransaction. * @@ -165,7 +141,7 @@ public SignedTransaction signTransactionWithCosigners(Account initiatorAccount, } @Override - byte[] generateBytes() { + protected byte[] generateBytes() { FlatBufferBuilder builder = new FlatBufferBuilder(); BigInteger deadlineBigInt = BigInteger.valueOf(getDeadline().getInstant()); @@ -176,14 +152,14 @@ byte[] generateBytes() { } // expected size = header + transactions bytes count + transactions bytes - int size = HEADER_SIZE + 4 + transactionsBytes.length; + int size = getSerializedSize(); // Create Vectors int signatureVector = AggregateTransactionBuffer.createSignatureVector(builder, new byte[64]); int signerVector = AggregateTransactionBuffer.createSignerVector(builder, new byte[32]); int deadlineVector = AggregateTransactionBuffer.createDeadlineVector(builder, UInt64Utils.fromBigInteger(deadlineBigInt)); - int feeVector = AggregateTransactionBuffer.createMaxFeeVector(builder, UInt64Utils.fromBigInteger(getFee())); + int feeVector = AggregateTransactionBuffer.createMaxFeeVector(builder, UInt64Utils.fromBigInteger(getMaxFee())); int transactionsVector = AggregateTransactionBuffer.createTransactionsVector(builder, transactionsBytes); AggregateTransactionBuffer.startAggregateTransactionBuffer(builder); @@ -194,7 +170,7 @@ byte[] generateBytes() { AggregateTransactionBuffer.addType(builder, getType().getValue()); AggregateTransactionBuffer.addMaxFee(builder, feeVector); AggregateTransactionBuffer.addDeadline(builder, deadlineVector); - + AggregateTransactionBuffer.addTransactionsSize(builder, transactionsBytes.length); AggregateTransactionBuffer.addTransactions(builder, transactionsVector); @@ -206,4 +182,27 @@ byte[] generateBytes() { Validate.isTrue(output.length == size, "Serialized transaction has incorrect length: " + this.getClass()); return output; } + + /** + * calculate payload size excluding header + * + * @param innerTransactions list of transactions inside of this aggregate transacion + * @return the size + */ + public static int calculatePayloadSize(List innerTransactions) { + // sum sizes of inner transactions, subtract 80 as toAggregateTransactionBytes leaves out 80 bytes of header + int innerSize = innerTransactions.stream().mapToInt(Transaction::getSerializedSize).map(size -> size - 80).sum(); + // transactions size + transactions + return 4 + innerSize; + } + + @Override + protected int getPayloadSerializedSize() { + return calculatePayloadSize(getInnerTransactions()); + } + + @Override + protected Transaction copyForSigner(PublicAccount signer) { + throw new UnsupportedOperationException("Can not embed aggregate transaction into aggregate transaction"); + } } \ No newline at end of file diff --git a/src/main/java/io/proximax/sdk/model/transaction/AliasTransaction.java b/src/main/java/io/proximax/sdk/model/transaction/AliasTransaction.java index eeb28c93..54e5274a 100644 --- a/src/main/java/io/proximax/sdk/model/transaction/AliasTransaction.java +++ b/src/main/java/io/proximax/sdk/model/transaction/AliasTransaction.java @@ -37,63 +37,48 @@ * Transaction defining alias for mosaic or for account */ public class AliasTransaction extends Transaction { + private final Schema schema = new AliasTransactionSchema(); + private final Optional mosaicId; private final Optional
address; private final NamespaceId namespaceId; private final AliasAction aliasAction; - private final Schema schema = new AliasTransactionSchema(); - - public AliasTransaction(TransactionType transactionType, NetworkType networkType, Integer version, TransactionDeadline deadline, BigInteger fee, - Optional mosaicId, Optional
address, NamespaceId namespaceId, AliasAction action, String signature, PublicAccount signer, - TransactionInfo transactionInfo) { - this(transactionType, networkType, version, deadline, fee, mosaicId, address, namespaceId, action, Optional.of(signature), - Optional.of(signer), Optional.of(transactionInfo)); - } - - public AliasTransaction(TransactionType transactionType, NetworkType networkType, Integer version, TransactionDeadline deadline, BigInteger fee, - Optional mosaicId, Optional
address, NamespaceId namespaceId, AliasAction action) { - this(transactionType, networkType, version, deadline, fee, mosaicId, address, namespaceId, action, Optional.empty(), Optional.empty(), - Optional.empty()); - } - private AliasTransaction(TransactionType transactionType, NetworkType networkType, Integer version, TransactionDeadline deadline, BigInteger fee, - Optional mosaicId, Optional
address, NamespaceId namespaceId, AliasAction action, Optional signature, - Optional signer, Optional transactionInfo) { - super(transactionType, networkType, version, deadline, fee, signature, signer, transactionInfo); + /** + * @param type transaction type which has to be one of {@link TransactionType#MOSAIC_ALIAS} or + * {@link TransactionType#ADDRESS_ALIAS} + * @param networkType network type + * @param version transaction version. For latest {@link TransactionVersion#MOSAIC_ALIAS} or + * {@link TransactionVersion#ADDRESS_ALIAS} + * @param deadline transaction deadline + * @param maxFee transaction fee + * @param signature optional signature + * @param signer optional signer + * @param transactionInfo optional transaction info + * @param mosaicId optional Mosaic ID specified when mosaic alias is being created + * @param address optional address specified when address alias is being created + * @param namespaceId namespace Id to get an alias + * @param aliasAction link/unlink action + */ + public AliasTransaction(TransactionType type, NetworkType networkType, Integer version, TransactionDeadline deadline, + BigInteger maxFee, Optional signature, Optional signer, + Optional transactionInfo, Optional mosaicId, Optional
address, + NamespaceId namespaceId, AliasAction aliasAction) { + super(type, networkType, version, deadline, maxFee, signature, signer, transactionInfo); + // validate input Validate.notNull(mosaicId, "MosaicId must not be null"); Validate.notNull(namespaceId, "namespaceId must not be null"); - Validate.notNull(action, "action must not be null"); + Validate.notNull(aliasAction, "action must not be null"); Validate.isTrue(mosaicId.isPresent() != address.isPresent(), "Address or mosaic has to be specified exclusively"); + Validate.isTrue(mosaicId.isPresent() == (type == TransactionType.MOSAIC_ALIAS), + "Mosaic ID needs to be used with mosaic alias transaction type"); + Validate.isTrue(address.isPresent() == (type == TransactionType.ADDRESS_ALIAS), + "Address needs to be used with address alias transaction type"); + // make assignments this.mosaicId = mosaicId; this.address = address; this.namespaceId = namespaceId; - this.aliasAction = action; - } - - /** - * Create a mosaic creation transaction object. - * - * @param mosaicId id of the mosaic - * @param namespaceId id of the namespace to be aliased - * @param action alias action to perform - * @param deadline The deadline to include the transaction. - * @param networkType The network type. - * @return {@link AliasTransaction} - */ - public static AliasTransaction create(MosaicId mosaicId, NamespaceId namespaceId, AliasAction action, - TransactionDeadline deadline, NetworkType networkType) { - Validate.notNull(mosaicId, "mosaicId must not be null"); - Validate.notNull(namespaceId, "namespaceId must not be null"); - return new AliasTransaction(TransactionType.MOSAIC_ALIAS, networkType, TransactionVersion.MOSAIC_ALIAS.getValue(), deadline, - BigInteger.valueOf(0), Optional.of(mosaicId), Optional.empty(), namespaceId, action); - } - - public static AliasTransaction create(Address address, NamespaceId namespaceId, AliasAction action, - TransactionDeadline deadline, NetworkType networkType) { - Validate.notNull(address, "address must not be null"); - Validate.notNull(namespaceId, "namespaceId must not be null"); - return new AliasTransaction(TransactionType.ADDRESS_ALIAS, networkType, TransactionVersion.ADDRESS_ALIAS.getValue(), deadline, - BigInteger.valueOf(0), Optional.empty(), Optional.of(address), namespaceId, action); + this.aliasAction = aliasAction; } /** @@ -124,9 +109,9 @@ public AliasAction getAliasAction() { return aliasAction; } - byte[] generateBytes() { + protected byte[] generateBytes() { FlatBufferBuilder builder = new FlatBufferBuilder(); - + // prepare data for serialization BigInteger deadlineBigInt = BigInteger.valueOf(getDeadline().getInstant()); @@ -138,19 +123,19 @@ byte[] generateBytes() { } else { throw new IllegalStateException("Always has to be address or id"); } - + // Create Vectors int signatureOffset = AliasTransactionBuffer.createSignatureVector(builder, new byte[64]); int signerOffset = AliasTransactionBuffer.createSignerVector(builder, new byte[32]); int deadlineOffset = AliasTransactionBuffer.createDeadlineVector(builder, UInt64Utils.fromBigInteger(deadlineBigInt)); - int feeOffset = AliasTransactionBuffer.createMaxFeeVector(builder, UInt64Utils.fromBigInteger(getFee())); - int namespaceIdVector = AliasTransactionBuffer.createNamespaceIdVector(builder, + int feeOffset = AliasTransactionBuffer.createMaxFeeVector(builder, UInt64Utils.fromBigInteger(getMaxFee())); + int namespaceIdOffset = AliasTransactionBuffer.createNamespaceIdVector(builder, UInt64Utils.fromBigInteger(namespaceId.getId())); int aliasIdOffset = AliasTransactionBuffer.createAliasIdVector(builder, aliasIdBytes); - + // header, 2 uint64 and int - int totalSize = HEADER_SIZE + aliasIdBytes.length + 8 + 1; + int totalSize = getSerializedSize(); AliasTransactionBuffer.startAliasTransactionBuffer(builder); AliasTransactionBuffer.addDeadline(builder, deadlineOffset); @@ -162,9 +147,9 @@ byte[] generateBytes() { AliasTransactionBuffer.addVersion(builder, getTxVersionforSerialization()); AliasTransactionBuffer.addAliasId(builder, aliasIdOffset); - AliasTransactionBuffer.addNamespaceId(builder, namespaceIdVector); + AliasTransactionBuffer.addNamespaceId(builder, namespaceIdOffset); AliasTransactionBuffer.addActionType(builder, aliasAction.getCode()); - + int codedTransaction = AliasTransactionBuffer.endAliasTransactionBuffer(builder); builder.finish(codedTransaction); @@ -173,4 +158,28 @@ byte[] generateBytes() { Validate.isTrue(output.length == totalSize, "Serialized transaction has incorrect length: " + this.getClass()); return output; } + + /** + * calculate payload size excluding header + * + * @param isForAddress try if address alias is created, false otherwise + * @return the size + */ + public static int calculatePayloadSize(boolean isForAddress) { + // alias is either 25 bytes of address or 8 bytes of mosaic ID + int aliasIdSize = isForAddress ? 25 : 8; + // alias ID + namespace ID + action + return aliasIdSize + 8 + 1; + } + + @Override + protected int getPayloadSerializedSize() { + return calculatePayloadSize(address.isPresent()); + } + + @Override + protected Transaction copyForSigner(PublicAccount signer) { + return new AliasTransaction(getType(), getNetworkType(), getVersion(), getDeadline(), getMaxFee(), getSignature(), + Optional.of(signer), getTransactionInfo(), getMosaicId(), getAddress(), getNamespaceId(), getAliasAction()); + } } diff --git a/src/main/java/io/proximax/sdk/model/transaction/BlockchainConfigTransaction.java b/src/main/java/io/proximax/sdk/model/transaction/BlockchainConfigTransaction.java index b7c7a3aa..ed3d3c75 100644 --- a/src/main/java/io/proximax/sdk/model/transaction/BlockchainConfigTransaction.java +++ b/src/main/java/io/proximax/sdk/model/transaction/BlockchainConfigTransaction.java @@ -41,22 +41,22 @@ public class BlockchainConfigTransaction extends Transaction { private final String supportedEntityVersions; /** - * @param networkType - * @param version - * @param deadline - * @param fee - * @param signature - * @param signer - * @param transactionInfo - * @param applyHeightDelta - * @param blockchainConfig - * @param supportedEntityVersions + * @param networkType network type + * @param version transaction version. Use {@link TransactionVersion#BLOCKCHAIN_CONFIG} for current version + * @param deadline transaction deadline + * @param maxFee transaction fee + * @param signature optional signature + * @param signer optional signer + * @param transactionInfo optional transaction info + * @param applyHeightDelta number of blocks after which the configuration becomes valid + * @param blockchainConfig string matching the content of the configuration file + * @param supportedEntityVersions JSON string with supported entity versions */ public BlockchainConfigTransaction(NetworkType networkType, Integer version, TransactionDeadline deadline, - BigInteger fee, Optional signature, Optional signer, + BigInteger maxFee, Optional signature, Optional signer, Optional transactionInfo, BigInteger applyHeightDelta, String blockchainConfig, String supportedEntityVersions) { - super(TransactionType.BLOCKCHAIN_CONFIG, networkType, version, deadline, fee, signature, signer, transactionInfo); + super(TransactionType.BLOCKCHAIN_CONFIG, networkType, version, deadline, maxFee, signature, signer, transactionInfo); // basic input validations Validate.notNull(applyHeightDelta); Validate.notNull(blockchainConfig); @@ -67,21 +67,6 @@ public BlockchainConfigTransaction(NetworkType networkType, Integer version, Tra this.supportedEntityVersions = supportedEntityVersions; } - /** - * @param applyHeightDelta number of blocks after which the configuration becomes valid - * @param blockchainConfig string matching the content of the configuration file - * @param supportedEntityVersions JSON string with supported entity versions - * @param networkType type of the network - * @param deadline transaction deadline - * @return the transaction instance - */ - public static BlockchainConfigTransaction create(BigInteger applyHeightDelta, String blockchainConfig, - String supportedEntityVersions, NetworkType networkType, TransactionDeadline deadline) { - return new BlockchainConfigTransaction(networkType, TransactionVersion.BLOCKCHAIN_CONFIG.getValue(), deadline, - BigInteger.ZERO, Optional.empty(), Optional.empty(), Optional.empty(), applyHeightDelta, blockchainConfig, - supportedEntityVersions); - } - /** * @return the applyHeightDelta */ @@ -103,7 +88,7 @@ public String getSupportedEntityVersions() { return supportedEntityVersions; } - byte[] generateBytes() { + protected byte[] generateBytes() { FlatBufferBuilder builder = new FlatBufferBuilder(); // prepare data for serialization @@ -116,15 +101,15 @@ byte[] generateBytes() { int signerOffset = CatapultConfigTransactionBuffer.createSignerVector(builder, new byte[32]); int deadlineOffset = CatapultConfigTransactionBuffer.createDeadlineVector(builder, UInt64Utils.fromBigInteger(deadlineBigInt)); - int feeOffset = CatapultConfigTransactionBuffer.createMaxFeeVector(builder, UInt64Utils.fromBigInteger(getFee())); + int feeOffset = CatapultConfigTransactionBuffer.createMaxFeeVector(builder, + UInt64Utils.fromBigInteger(getMaxFee())); // specific fields int applyHeightOffset = CatapultConfigTransactionBuffer.createApplyHeightDeltaVector(builder, UInt64Utils.fromBigInteger(getApplyHeightDelta())); int confgOffset = CatapultConfigTransactionBuffer.createBlockChainConfigVector(builder, configBytes); int entityOffset = CatapultConfigTransactionBuffer.createSupportedEntityVersionsVector(builder, entityBytes); - // header, 2 uint64 and int - int size = HEADER_SIZE + 8 + 2 + 2 + configBytes.length + entityBytes.length; + int size = getSerializedSize(); CatapultConfigTransactionBuffer.startCatapultConfigTransactionBuffer(builder); CatapultConfigTransactionBuffer.addDeadline(builder, deadlineOffset); @@ -149,4 +134,29 @@ byte[] generateBytes() { Validate.isTrue(output.length == size, "Serialized transaction has incorrect length: " + this.getClass()); return output; } + + /** + * calculate the payload size excluding the header + * + * @param configBytesLength number of bytes of configuration + * @param entityBytesLength number of bytes of supported entities + * @return the size + */ + public static int calculatePayloadSize(int configBytesLength, int entityBytesLength) { + // height offset + size of config + config + size of entities + entities + return 8 + 2 + configBytesLength + 2 + entityBytesLength; + } + + @Override + protected int getPayloadSerializedSize() { + return calculatePayloadSize(StringUtils.getBytes(getBlockchainConfig()).length, + StringUtils.getBytes(getSupportedEntityVersions()).length); + } + + @Override + protected Transaction copyForSigner(PublicAccount signer) { + return new BlockchainConfigTransaction(getNetworkType(), getVersion(), getDeadline(), getMaxFee(), getSignature(), + Optional.of(signer), getTransactionInfo(), getApplyHeightDelta(), getBlockchainConfig(), + getSupportedEntityVersions()); + } } diff --git a/src/main/java/io/proximax/sdk/model/transaction/BlockchainUpgradeTransaction.java b/src/main/java/io/proximax/sdk/model/transaction/BlockchainUpgradeTransaction.java index 6712c4e1..66e679bb 100644 --- a/src/main/java/io/proximax/sdk/model/transaction/BlockchainUpgradeTransaction.java +++ b/src/main/java/io/proximax/sdk/model/transaction/BlockchainUpgradeTransaction.java @@ -39,42 +39,35 @@ * By default the upgrade period is required to be at least 360 */ public class BlockchainUpgradeTransaction extends Transaction { + private final Schema schema = new BlockchainUpgradeTransactionSchema(); private final BigInteger upgradePeriod; private final BlockchainVersion newVersion; - private final Schema schema = new BlockchainUpgradeTransactionSchema(); - /** - * @param networkType - * @param version - * @param deadline - * @param fee - * @param signature - * @param signer - * @param transactionInfo + * @param networkType network type + * @param version transaction version. Use {@link TransactionVersion#BLOCKCHAIN_UPGRADE} for current version + * @param deadline transaction deadline + * @param maxFee transaction fee + * @param signature optional signature + * @param signer optional signer + * @param transactionInfo optional transaction info * @param upgradePeriod period after version is enforced. Default minimum is 360 * @param newVersion new node version which will be enforced after upgrade period elapses */ public BlockchainUpgradeTransaction(NetworkType networkType, Integer version, TransactionDeadline deadline, - BigInteger fee, Optional signature, Optional signer, + BigInteger maxFee, Optional signature, Optional signer, Optional transactionInfo, BigInteger upgradePeriod, BlockchainVersion newVersion) { - super(TransactionType.BLOCKCHAIN_UPGRADE, networkType, version, deadline, fee, signature, signer, + super(TransactionType.BLOCKCHAIN_UPGRADE, networkType, version, deadline, maxFee, signature, signer, transactionInfo); - // basic validations - Validate.notNull(upgradePeriod); - Validate.notNull(newVersion); - // make assignments + // validations + Validate.notNull(upgradePeriod, "upgrade period is mandatory"); + Validate.notNull(newVersion, "new version is required"); + // assignments this.upgradePeriod = upgradePeriod; this.newVersion = newVersion; } - public static BlockchainUpgradeTransaction create(BigInteger upgradePeriod, BlockchainVersion newVersion, - TransactionDeadline deadline, NetworkType networkType) { - return new BlockchainUpgradeTransaction(networkType, TransactionVersion.BLOCKCHAIN_UPGRADE.getValue(), deadline, - BigInteger.ZERO, Optional.empty(), Optional.empty(), Optional.empty(), upgradePeriod, newVersion); - } - /** * @return the upgradePeriod after which the version becomes required for block generation */ @@ -90,7 +83,7 @@ public BlockchainVersion getNewVersion() { } @Override - byte[] generateBytes() { + protected byte[] generateBytes() { FlatBufferBuilder builder = new FlatBufferBuilder(); // prepare data for serialization @@ -102,14 +95,13 @@ byte[] generateBytes() { int deadlineOffset = CatapultUpgradeTransactionBuffer.createDeadlineVector(builder, UInt64Utils.fromBigInteger(deadlineBigInt)); int feeOffset = CatapultUpgradeTransactionBuffer.createMaxFeeVector(builder, - UInt64Utils.fromBigInteger(getFee())); + UInt64Utils.fromBigInteger(getMaxFee())); int upgradePeriodOffset = CatapultUpgradeTransactionBuffer.createUpgradePeriodVector(builder, UInt64Utils.fromBigInteger(getUpgradePeriod())); int newCatapultVersionOffset = CatapultUpgradeTransactionBuffer.createNewCatapultVersionVector(builder, UInt64Utils.fromBigInteger(getNewVersion().getVersionValue())); - // header, 2 uint64 - int size = HEADER_SIZE + 8 + 8; + int size = getSerializedSize(); CatapultUpgradeTransactionBuffer.startCatapultUpgradeTransactionBuffer(builder); CatapultUpgradeTransactionBuffer.addDeadline(builder, deadlineOffset); @@ -131,4 +123,25 @@ byte[] generateBytes() { Validate.isTrue(output.length == size, "Serialized transaction has incorrect length: " + this.getClass()); return output; } + + /** + * calculate payload size excluding header + * + * @return size + */ + public static int calculatePayloadSize() { + // period offset + version + return 8 + 8; + } + + @Override + protected int getPayloadSerializedSize() { + return calculatePayloadSize(); + } + + @Override + protected Transaction copyForSigner(PublicAccount signer) { + return new BlockchainUpgradeTransaction(getNetworkType(), getVersion(), getDeadline(), getMaxFee(), + getSignature(), Optional.of(signer), getTransactionInfo(), getUpgradePeriod(), getNewVersion()); + } } diff --git a/src/main/java/io/proximax/sdk/model/transaction/DeadlineRaw.java b/src/main/java/io/proximax/sdk/model/transaction/DeadlineRaw.java index ba079fed..0bc34183 100644 --- a/src/main/java/io/proximax/sdk/model/transaction/DeadlineRaw.java +++ b/src/main/java/io/proximax/sdk/model/transaction/DeadlineRaw.java @@ -26,7 +26,7 @@ public DeadlineRaw(BigInteger deadline) { /** * create new deadline instance specifying duration since current time * - * @param duration duration after current time + * @param duration millisecond duration after current time * @return deadline representing specified time */ public static TransactionDeadline startNow(BigInteger duration) { diff --git a/src/main/java/io/proximax/sdk/model/transaction/LockFundsTransaction.java b/src/main/java/io/proximax/sdk/model/transaction/LockFundsTransaction.java index 87b98f99..770b4ee6 100644 --- a/src/main/java/io/proximax/sdk/model/transaction/LockFundsTransaction.java +++ b/src/main/java/io/proximax/sdk/model/transaction/LockFundsTransaction.java @@ -31,116 +31,137 @@ import io.proximax.sdk.utils.dto.UInt64Utils; /** - * Lock funds transaction is used before sending an Aggregate bonded transaction, as a deposit to announce the transaction. - * When aggregate bonded transaction is confirmed funds are returned to LockFundsTransaction signer. + * Lock funds transaction is used before sending an Aggregate bonded transaction, as a deposit to announce the + * transaction. When aggregate bonded transaction is confirmed funds are returned to LockFundsTransaction signer. * * @since 1.0 */ public class LockFundsTransaction extends Transaction { - private final Mosaic mosaic; - private final BigInteger duration; - private final SignedTransaction signedTransaction; - private final Schema schema = new LockFundsTransactionSchema(); - - public LockFundsTransaction(NetworkType networkType, Integer version, TransactionDeadline deadline, BigInteger fee, Mosaic mosaic, BigInteger duration, SignedTransaction signedTransaction, String signature, PublicAccount signer, TransactionInfo transactionInfo) { - this(networkType, version, deadline, fee, mosaic, duration, signedTransaction, Optional.of(signature), Optional.of(signer), Optional.of(transactionInfo)); - } - - public LockFundsTransaction(NetworkType networkType, Integer version, TransactionDeadline deadline, BigInteger fee, Mosaic mosaic, BigInteger duration, SignedTransaction signedTransaction) { - this(networkType, version, deadline, fee, mosaic, duration, signedTransaction, Optional.empty(), Optional.empty(), Optional.empty()); - } - - private LockFundsTransaction(NetworkType networkType, Integer version, TransactionDeadline deadline, BigInteger fee, Mosaic mosaic, BigInteger duration, SignedTransaction signedTransaction, Optional signature, Optional signer, Optional transactionInfo) { - super(TransactionType.LOCK, networkType, version, deadline, fee, signature, signer, transactionInfo); - Validate.notNull(mosaic, "Mosaic must not be null"); - Validate.notNull(duration, "Duration must not be null"); - Validate.notNull(signedTransaction, "Signed transaction must not be null"); - this.mosaic = mosaic; - this.duration = duration; - this.signedTransaction = signedTransaction; - if (signedTransaction.getType() != TransactionType.AGGREGATE_BONDED) { - throw new IllegalArgumentException("Signed transaction must be Aggregate Bonded Transaction"); - } - } - - /** - * Create a lock funds transaction object. - * @param deadline The deadline to include the transaction. - * @param mosaic The locked mosaic. - * @param duration The funds lock duration. - * @param signedTransaction The signed transaction for which funds are locked. - * @param networkType The network type. - * @return a LockFundsTransaction instance - */ - public static LockFundsTransaction create(TransactionDeadline deadline, Mosaic mosaic, BigInteger duration, SignedTransaction signedTransaction, NetworkType networkType) { - return new LockFundsTransaction(networkType, 1, deadline, BigInteger.valueOf(0), mosaic, duration, signedTransaction); - } - - /** - * Returns locked mosaic. - * - * @return locked mosaic. - */ - public Mosaic getMosaic() { return mosaic; } - - /** - * Returns funds lock duration in number of blocks. - * - * @return funds lock duration in number of blocks. - */ - public BigInteger getDuration() { return duration; } - - /** - * Returns signed transaction for which funds are locked. - * - * @return signed transaction for which funds are locked. - */ - public SignedTransaction getSignedTransaction() { return signedTransaction; } - - @Override - byte[] generateBytes() { - FlatBufferBuilder builder = new FlatBufferBuilder(); - BigInteger deadlineBigInt = BigInteger.valueOf(getDeadline().getInstant()); - - // Create Vectors - int signatureVector = LockFundsTransactionBuffer.createSignatureVector(builder, new byte[64]); - int signerVector = LockFundsTransactionBuffer.createSignerVector(builder, new byte[32]); - int deadlineVector = LockFundsTransactionBuffer.createDeadlineVector(builder, UInt64Utils.fromBigInteger(deadlineBigInt)); - int feeVector = LockFundsTransactionBuffer.createMaxFeeVector(builder, UInt64Utils.fromBigInteger(getFee())); - int mosaicIdVector = LockFundsTransactionBuffer.createMosaicIdVector(builder, UInt64Utils.fromBigInteger(mosaic.getId().getId())); - int mosaicAmountVector = LockFundsTransactionBuffer.createMosaicAmountVector(builder, UInt64Utils.fromBigInteger(mosaic.getAmount())); - int durationVector = LockFundsTransactionBuffer.createDurationVector(builder, UInt64Utils.fromBigInteger(duration)); - - int hashVector = LockFundsTransactionBuffer.createHashVector(builder, Hex.decode(signedTransaction.getHash())); - - // header, mosaic id, amount, duration, hash - int size = HEADER_SIZE + 8 + 8 + 8 + 32; - - LockFundsTransactionBuffer.startLockFundsTransactionBuffer(builder); - LockFundsTransactionBuffer.addSize(builder, size); - LockFundsTransactionBuffer.addSignature(builder, signatureVector); - LockFundsTransactionBuffer.addSigner(builder, signerVector); - LockFundsTransactionBuffer.addVersion(builder, getTxVersionforSerialization()); - LockFundsTransactionBuffer.addType(builder, getType().getValue()); - LockFundsTransactionBuffer.addMaxFee(builder, feeVector); - LockFundsTransactionBuffer.addDeadline(builder, deadlineVector); - - LockFundsTransactionBuffer.addMosaicId(builder, mosaicIdVector); - LockFundsTransactionBuffer.addMosaicAmount(builder, mosaicAmountVector); - LockFundsTransactionBuffer.addDuration(builder, durationVector); - LockFundsTransactionBuffer.addHash(builder, hashVector); - - int codedLockFunds = LockFundsTransactionBuffer.endLockFundsTransactionBuffer(builder); - builder.finish(codedLockFunds); - - // validate size - byte[] output = schema.serialize(builder.sizedByteArray()); - Validate.isTrue(output.length == size, "Serialized transaction has incorrect length: " + this.getClass()); - return output; } + private final Schema schema = new LockFundsTransactionSchema(); + + private final Mosaic mosaic; + private final BigInteger duration; + private final SignedTransaction signedTransaction; + + /** + * @param networkType + * @param version + * @param deadline + * @param maxFee + * @param signature + * @param signer + * @param transactionInfo + * @param mosaic + * @param duration + * @param signedTransaction + */ + public LockFundsTransaction(NetworkType networkType, Integer version, TransactionDeadline deadline, + BigInteger maxFee, Optional signature, Optional signer, + Optional transactionInfo, Mosaic mosaic, BigInteger duration, + SignedTransaction signedTransaction) { + super(TransactionType.LOCK, networkType, version, deadline, maxFee, signature, signer, transactionInfo); + Validate.notNull(mosaic, "Mosaic must not be null"); + Validate.notNull(duration, "Duration must not be null"); + Validate.notNull(signedTransaction, "Signed transaction must not be null"); + Validate.isTrue(signedTransaction.getType() == TransactionType.AGGREGATE_BONDED, + "Signed transaction must be Aggregate Bonded Transaction"); + this.mosaic = mosaic; + this.duration = duration; + this.signedTransaction = signedTransaction; + } + + /** + * Returns locked mosaic. + * + * @return locked mosaic. + */ + public Mosaic getMosaic() { + return mosaic; + } + + /** + * Returns funds lock duration in number of blocks. + * + * @return funds lock duration in number of blocks. + */ + public BigInteger getDuration() { + return duration; + } + + /** + * Returns signed transaction for which funds are locked. + * + * @return signed transaction for which funds are locked. + */ + public SignedTransaction getSignedTransaction() { + return signedTransaction; + } + + @Override + protected byte[] generateBytes() { + FlatBufferBuilder builder = new FlatBufferBuilder(); + BigInteger deadlineBigInt = BigInteger.valueOf(getDeadline().getInstant()); + + // Create Vectors + int signatureVector = LockFundsTransactionBuffer.createSignatureVector(builder, new byte[64]); + int signerVector = LockFundsTransactionBuffer.createSignerVector(builder, new byte[32]); + int deadlineVector = LockFundsTransactionBuffer.createDeadlineVector(builder, + UInt64Utils.fromBigInteger(deadlineBigInt)); + int feeVector = LockFundsTransactionBuffer.createMaxFeeVector(builder, UInt64Utils.fromBigInteger(getMaxFee())); + int mosaicIdVector = LockFundsTransactionBuffer.createMosaicIdVector(builder, + UInt64Utils.fromBigInteger(mosaic.getId().getId())); + int mosaicAmountVector = LockFundsTransactionBuffer.createMosaicAmountVector(builder, + UInt64Utils.fromBigInteger(mosaic.getAmount())); + int durationVector = LockFundsTransactionBuffer.createDurationVector(builder, + UInt64Utils.fromBigInteger(duration)); + + int hashVector = LockFundsTransactionBuffer.createHashVector(builder, Hex.decode(signedTransaction.getHash())); + + int size = getSerializedSize(); + + LockFundsTransactionBuffer.startLockFundsTransactionBuffer(builder); + LockFundsTransactionBuffer.addSize(builder, size); + LockFundsTransactionBuffer.addSignature(builder, signatureVector); + LockFundsTransactionBuffer.addSigner(builder, signerVector); + LockFundsTransactionBuffer.addVersion(builder, getTxVersionforSerialization()); + LockFundsTransactionBuffer.addType(builder, getType().getValue()); + LockFundsTransactionBuffer.addMaxFee(builder, feeVector); + LockFundsTransactionBuffer.addDeadline(builder, deadlineVector); + + LockFundsTransactionBuffer.addMosaicId(builder, mosaicIdVector); + LockFundsTransactionBuffer.addMosaicAmount(builder, mosaicAmountVector); + LockFundsTransactionBuffer.addDuration(builder, durationVector); + LockFundsTransactionBuffer.addHash(builder, hashVector); + + int codedLockFunds = LockFundsTransactionBuffer.endLockFundsTransactionBuffer(builder); + builder.finish(codedLockFunds); + + // validate size + byte[] output = schema.serialize(builder.sizedByteArray()); + Validate.isTrue(output.length == size, "Serialized transaction has incorrect length: " + this.getClass()); + return output; + } @Override public String toString() { return "LockFundsTransaction [mosaic=" + mosaic + ", duration=" + duration + ", signedTransaction=" + signedTransaction + ", schema=" + schema + "]"; } + + public static int calculatePayloadSize() { + // mosaic id, amount, duration, hash + return 8 + 8 + 8 + 32; + } + + @Override + protected int getPayloadSerializedSize() { + return calculatePayloadSize(); + } + + @Override + protected Transaction copyForSigner(PublicAccount signer) { + return new LockFundsTransaction(getNetworkType(), getVersion(), getDeadline(), getMaxFee(), + getSignature(), Optional.of(signer), getTransactionInfo(), getMosaic(), + getDuration(), getSignedTransaction()); + } } diff --git a/src/main/java/io/proximax/sdk/model/transaction/ModifyAccountPropertyTransaction.java b/src/main/java/io/proximax/sdk/model/transaction/ModifyAccountPropertyTransaction.java index 92f3a40b..5a82148e 100644 --- a/src/main/java/io/proximax/sdk/model/transaction/ModifyAccountPropertyTransaction.java +++ b/src/main/java/io/proximax/sdk/model/transaction/ModifyAccountPropertyTransaction.java @@ -8,6 +8,7 @@ import java.math.BigInteger; import java.nio.ByteBuffer; import java.nio.ByteOrder; +import java.util.Collections; import java.util.List; import java.util.Optional; @@ -31,82 +32,31 @@ */ public abstract class ModifyAccountPropertyTransaction extends Transaction { private final ModifyAccountPropertyTransactionSchema schema = new ModifyAccountPropertyTransactionSchema(); - + private final AccountPropertyType propertyType; private final List> modifications; - + /** - * Create new transaction to modify account property - * - * @param transactionType transaction type - * @param networkType network type - * @param version version - * @param deadline deadline - * @param maxFee max fee - * @param propertyType type of the account property - * @param propertyModifications modifications to the account property - * @param signature optional signature - * @param signer optional signer - * @param transactionInfo optional transaction info + * @param type + * @param networkType + * @param version + * @param deadline + * @param maxFee + * @param signature + * @param signer + * @param transactionInfo + * @param propertyType + * @param modifications */ - private ModifyAccountPropertyTransaction(TransactionType transactionType, NetworkType networkType, Integer version, - TransactionDeadline deadline, BigInteger maxFee, AccountPropertyType propertyType, List> propertyModifications, Optional signature, - Optional signer, Optional transactionInfo) { - super(transactionType, networkType, version, deadline, maxFee, signature, signer, transactionInfo); - Validate.notNull(propertyType, "propertyType must not be null"); - Validate.notEmpty(propertyModifications, "modifications must not be empty"); + public ModifyAccountPropertyTransaction(TransactionType type, NetworkType networkType, Integer version, + TransactionDeadline deadline, BigInteger maxFee, Optional signature, Optional signer, + Optional transactionInfo, AccountPropertyType propertyType, + List> modifications) { + super(type, networkType, version, deadline, maxFee, signature, signer, transactionInfo); this.propertyType = propertyType; - this.modifications = propertyModifications; + this.modifications = Collections.unmodifiableList(modifications); } - /** - * create new transaction to modify address account properties - * - * @param networkType network type - * @param deadline transaction deadline - * @param maxFee maximum fee - * @param propertyType property type - * @param propertyModifications property modifications - * @return the transaction instance - */ - public static ModifyAccountPropertyTransaction
createForAddress(TransactionDeadline deadline, BigInteger maxFee, - AccountPropertyType propertyType, - List> propertyModifications, NetworkType networkType) { - return new AddressModification(networkType, TransactionVersion.ACCOUNT_PROPERTIES_ADDRESS.getValue(), deadline, maxFee, propertyType, propertyModifications, Optional.empty(), Optional.empty(), Optional.empty()); - } - - /** - * create new transaction to modify mosaic account properties - * - * @param networkType network type - * @param deadline transaction deadline - * @param maxFee maximum fee - * @param propertyType property type - * @param propertyModifications property modifications - * @return the transaction instance - */ - public static ModifyAccountPropertyTransaction createForMosaic(TransactionDeadline deadline, BigInteger maxFee, - AccountPropertyType propertyType, - List> propertyModifications, NetworkType networkType) { - return new MosaicModification(networkType, TransactionVersion.ACCOUNT_PROPERTIES_MOSAIC.getValue(), deadline, maxFee, propertyType, propertyModifications, Optional.empty(), Optional.empty(), Optional.empty()); - } - - /** - * create new transaction to modify entity type account properties - * - * @param networkType network type - * @param deadline transaction deadline - * @param maxFee maximum fee - * @param propertyType property type - * @param propertyModifications property modifications - * @return the transaction instance - */ - public static ModifyAccountPropertyTransaction createForEntityType(TransactionDeadline deadline, BigInteger maxFee, - AccountPropertyType propertyType, - List> propertyModifications, NetworkType networkType) { - return new EntityTypeModification(networkType, TransactionVersion.ACCOUNT_PROPERTIES_MOSAIC.getValue(), deadline, maxFee, propertyType, propertyModifications, Optional.empty(), Optional.empty(), Optional.empty()); - } - /** * @return the account property type */ @@ -120,26 +70,28 @@ public AccountPropertyType getPropertyType() { public List> getPropertyModifications() { return modifications; } - + /** - *

serialize account property modification value to byte array

+ *

+ * serialize account property modification value to byte array + *

* - *

NOTE that implementation should also verify that the size of byte array is expected per server requirements

+ *

+ * NOTE that implementation should also verify that the size of byte array is expected per server requirements + *

* * @param mod account property modification * @return byte array of expected size */ protected abstract byte[] getValueBytesFromModification(AccountPropertyModification mod); - + @Override - byte[] generateBytes() { + protected byte[] generateBytes() { FlatBufferBuilder builder = new FlatBufferBuilder(); // prepare data for serialization BigInteger deadlineBigInt = BigInteger.valueOf(getDeadline().getInstant()); - // track the size of the whole transaction - int totalSize = 0; // load modifications int[] modificationOffsets = new int[modifications.size()]; for (int i = 0; i < modificationOffsets.length; i++) { @@ -150,11 +102,6 @@ byte[] generateBytes() { // prepare vectors for collections int valueOffset = PropertyModificationBuffer.createValueVector(builder, valueBytes); - // compute number of bytes: modType + value bytes - int modSize = 1 + valueBytes.length; - // increase total size - totalSize += modSize; - // populate flat-buffer PropertyModificationBuffer.startPropertyModificationBuffer(builder); PropertyModificationBuffer.addValue(builder, valueOffset); @@ -167,11 +114,13 @@ byte[] generateBytes() { int signerOffset = AccountPropertiesTransactionBuffer.createSignerVector(builder, new byte[32]); int deadlineOffset = AccountPropertiesTransactionBuffer.createDeadlineVector(builder, UInt64Utils.fromBigInteger(deadlineBigInt)); - int feeOffset = AccountPropertiesTransactionBuffer.createMaxFeeVector(builder, UInt64Utils.fromBigInteger(getFee())); - int modificationsOffset = AccountPropertiesTransactionBuffer.createModificationsVector(builder, modificationOffsets); + int feeOffset = AccountPropertiesTransactionBuffer.createMaxFeeVector(builder, + UInt64Utils.fromBigInteger(getMaxFee())); + int modificationsOffset = AccountPropertiesTransactionBuffer.createModificationsVector(builder, + modificationOffsets); // add size of the header + size of prop type (1) + size of mod count (1) - totalSize += HEADER_SIZE + 1 + 1; + int totalSize = getSerializedSize(); AccountPropertiesTransactionBuffer.startAccountPropertiesTransactionBuffer(builder); AccountPropertiesTransactionBuffer.addDeadline(builder, deadlineOffset); @@ -194,7 +143,7 @@ byte[] generateBytes() { Validate.isTrue(output.length == totalSize, "Serialized transaction has incorrect length: " + this.getClass()); return output; } - + /** * Address account property modification transaction implementation */ @@ -202,28 +151,22 @@ public static class AddressModification extends ModifyAccountPropertyTransaction private static final int VALUE_BYTES_LENGTH = 25; /** - *

Account property modification for address

- * - *

use - * {@link ModifyAccountPropertyTransaction#createForAddress(TransactionDeadline, BigInteger, AccountPropertyType, List, NetworkType)} - * to create new transaction to modify account property

- * - * @param networkType networkType - * @param version version - * @param deadline deadline - * @param maxFee max fee - * @param propertyType property type - * @param propertyModifications list of property modifications - * @param signature optional signature - * @param signer optional signer - * @param transactionInfo optional transaction info + * @param networkType + * @param version + * @param deadline + * @param maxFee + * @param signature + * @param signer + * @param transactionInfo + * @param propertyType + * @param modifications */ public AddressModification(NetworkType networkType, Integer version, TransactionDeadline deadline, - BigInteger maxFee, AccountPropertyType propertyType, - List> propertyModifications, Optional signature, - Optional signer, Optional transactionInfo) { - super(TransactionType.ACCOUNT_PROPERTIES_ADDRESS, networkType, version, deadline, maxFee, propertyType, - propertyModifications, signature, signer, transactionInfo); + BigInteger maxFee, Optional signature, Optional signer, + Optional transactionInfo, AccountPropertyType propertyType, + List> modifications) { + super(TransactionType.ACCOUNT_PROPERTIES_ADDRESS, networkType, version, deadline, maxFee, signature, signer, + transactionInfo, propertyType, modifications); } @Override @@ -239,36 +182,55 @@ protected byte[] getValueBytesFromModification(AccountPropertyModification>) getPropertyModifications()); + } + } - + /** * Mosaic account property modification transaction implementation */ public static class MosaicModification extends ModifyAccountPropertyTransaction { private static final int VALUE_BYTES_LENGTH = 8; + /** - *

Account property modification for mosaic

- * - *

use - * {@link ModifyAccountPropertyTransaction#createForMosaic(TransactionDeadline, BigInteger, AccountPropertyType, List, NetworkType)} - * to create new transaction to modify account property

- * - * @param networkType networkType - * @param version version - * @param deadline deadline - * @param maxFee max fee - * @param propertyType property type - * @param list list of property modifications - * @param signature optional signature - * @param signer optional signer - * @param transactionInfo optional transaction info + * @param networkType + * @param version + * @param deadline + * @param maxFee + * @param signature + * @param signer + * @param transactionInfo + * @param propertyType + * @param modifications */ public MosaicModification(NetworkType networkType, Integer version, TransactionDeadline deadline, - BigInteger maxFee, AccountPropertyType propertyType, - List> list, Optional signature, - Optional signer, Optional transactionInfo) { - super(TransactionType.ACCOUNT_PROPERTIES_MOSAIC, networkType, version, deadline, maxFee, propertyType, - list, signature, signer, transactionInfo); + BigInteger maxFee, Optional signature, Optional signer, + Optional transactionInfo, AccountPropertyType propertyType, + List> modifications) { + super(TransactionType.ACCOUNT_PROPERTIES_MOSAIC, networkType, version, deadline, maxFee, signature, signer, + transactionInfo, propertyType, modifications); } @Override @@ -284,45 +246,86 @@ protected byte[] getValueBytesFromModification(AccountPropertyModification>) getPropertyModifications()); + } } - + /** * Transaction type account property modification transaction implementation */ public static class EntityTypeModification extends ModifyAccountPropertyTransaction { private static final int VALUE_BYTES_LENGTH = 2; + /** - *

Account property modification for mosaic

- * - *

use - * {@link ModifyAccountPropertyTransaction#createForMosaic(TransactionDeadline, BigInteger, AccountPropertyType, List, NetworkType)} - * to create new transaction to modify account property

- * - * @param networkType networkType - * @param version version - * @param deadline deadline - * @param maxFee max fee - * @param propertyType property type - * @param propertyModifications list of property modifications - * @param signature optional signature - * @param signer optional signer - * @param transactionInfo optional transaction info + * @param networkType + * @param version + * @param deadline + * @param maxFee + * @param signature + * @param signer + * @param transactionInfo + * @param propertyType + * @param modifications */ public EntityTypeModification(NetworkType networkType, Integer version, TransactionDeadline deadline, - BigInteger maxFee, AccountPropertyType propertyType, - List> propertyModifications, Optional signature, - Optional signer, Optional transactionInfo) { - super(TransactionType.ACCOUNT_PROPERTIES_ENTITY_TYPE, networkType, version, deadline, maxFee, propertyType, - propertyModifications, signature, signer, transactionInfo); + BigInteger maxFee, Optional signature, Optional signer, + Optional transactionInfo, AccountPropertyType propertyType, + List> modifications) { + super(TransactionType.ACCOUNT_PROPERTIES_ENTITY_TYPE, networkType, version, deadline, maxFee, signature, + signer, transactionInfo, propertyType, modifications); } @Override protected byte[] getValueBytesFromModification(AccountPropertyModification mod) { // get the bytes from string byte[] valueBytes = new byte[VALUE_BYTES_LENGTH]; - ByteBuffer.wrap(valueBytes).order(ByteOrder.LITTLE_ENDIAN).putShort((short)mod.getValue().getValue()); + ByteBuffer.wrap(valueBytes).order(ByteOrder.LITTLE_ENDIAN).putShort((short) mod.getValue().getValue()); // return the value return valueBytes; } + + /** + * calculate the payload size + * + * @param modCount number of address modifications + * @return the size + */ + public static int calculatePayloadSize(int modCount) { + // property type, mod count, mods + return 1 + 1 + (1 + VALUE_BYTES_LENGTH) * modCount; + } + + @Override + protected int getPayloadSerializedSize() { + return calculatePayloadSize(getPropertyModifications().size()); + } + + @Override + protected Transaction copyForSigner(PublicAccount signer) { + return new EntityTypeModification(getNetworkType(), getVersion(), getDeadline(), getMaxFee(), getSignature(), + Optional.of(signer), getTransactionInfo(), getPropertyType(), + (List>) getPropertyModifications()); + } } } diff --git a/src/main/java/io/proximax/sdk/model/transaction/ModifyContractTransaction.java b/src/main/java/io/proximax/sdk/model/transaction/ModifyContractTransaction.java index 6fff3eff..1a6c9abb 100644 --- a/src/main/java/io/proximax/sdk/model/transaction/ModifyContractTransaction.java +++ b/src/main/java/io/proximax/sdk/model/transaction/ModifyContractTransaction.java @@ -6,6 +6,7 @@ package io.proximax.sdk.model.transaction; import java.math.BigInteger; +import java.util.Collections; import java.util.List; import java.util.Optional; @@ -21,20 +22,23 @@ import io.proximax.sdk.utils.dto.UInt64Utils; /** - *

Contract modification transaction can be used to create or change contract

- *

Contract changes contract account to N of N multisignature account where cosignatories are the verifiers

+ *

+ * Contract modification transaction can be used to create or change contract + *

+ *

+ * Contract changes contract account to N of N multisignature account where cosignatories are the verifiers + *

*/ public class ModifyContractTransaction extends Transaction { - private final ModifyContractTransactionSchema schema = new ModifyContractTransactionSchema(); - + private final BigInteger durationDelta; private final String contentHash; - + private final List customersModifications; private final List executorsModifications; private final List verifiersModifications; - + /** * create new contract modification transaction * @@ -51,68 +55,91 @@ public class ModifyContractTransaction extends Transaction { * @param executorsModifications changes to the list of executors * @param verifiersModifications changes to the list of verifiers */ - public ModifyContractTransaction(NetworkType networkType, Integer transactionVersion, - TransactionDeadline deadline, BigInteger maxFee, Optional signature, Optional signer, + public ModifyContractTransaction(NetworkType networkType, Integer transactionVersion, TransactionDeadline deadline, + BigInteger maxFee, Optional signature, Optional signer, Optional transactionInfo, BigInteger durationDelta, String contentHash, List customersModifications, List executorsModifications, List verifiersModifications) { - super(TransactionType.MODIFY_CONTRACT, networkType, transactionVersion, deadline, maxFee, signature, signer, transactionInfo); + super(TransactionType.MODIFY_CONTRACT, networkType, transactionVersion, deadline, maxFee, signature, signer, + transactionInfo); + // validations + Validate.notNull(durationDelta, "durationDelta can not be null"); + Validate.notNull(contentHash, "contentHash can not be null"); + Validate.notNull(customersModifications, "customersModifications can not be null"); + Validate.notNull(executorsModifications, "executorsModifications can not be null"); + Validate.notNull(verifiersModifications, "verifiersModifications can not be null"); + // assignments this.durationDelta = durationDelta; this.contentHash = contentHash; - this.customersModifications = customersModifications; - this.executorsModifications = executorsModifications; - this.verifiersModifications = verifiersModifications; + this.customersModifications = Collections.unmodifiableList(customersModifications); + this.executorsModifications = Collections.unmodifiableList(executorsModifications); + this.verifiersModifications = Collections.unmodifiableList(verifiersModifications); } /** - * create new contract modification transaction - * - * @param networkType network type - * @param deadline transaction deadline - * @param maxFee maximum fee - * @param durationDelta change of the contract duration (+/-) - * @param contentHash contract content hash - * @param customersModifications changes to the list of customers - * @param executorsModifications changes to the list of executors - * @param verifiersModifications changes to the list of verifiers - * @return the contract modification transaction ready to be signed and announced + * @return the durationDelta */ - public static ModifyContractTransaction create(TransactionDeadline deadline, BigInteger maxFee, BigInteger durationDelta, String contentHash, - List customersModifications, - List executorsModifications, - List verifiersModifications, NetworkType networkType) { - return new ModifyContractTransaction(networkType, TransactionVersion.MODIFY_CONTRACT.getValue(), deadline, maxFee, Optional.empty(), Optional.empty(), - Optional.empty(), durationDelta, contentHash, customersModifications, executorsModifications, - verifiersModifications); + public BigInteger getDurationDelta() { + return durationDelta; } - + + /** + * @return the contentHash + */ + public String getContentHash() { + return contentHash; + } + + /** + * @return the customersModifications + */ + public List getCustomersModifications() { + return customersModifications; + } + + /** + * @return the executorsModifications + */ + public List getExecutorsModifications() { + return executorsModifications; + } + + /** + * @return the verifiersModifications + */ + public List getVerifiersModifications() { + return verifiersModifications; + } + @Override - byte[] generateBytes() { + protected byte[] generateBytes() { FlatBufferBuilder builder = new FlatBufferBuilder(); BigInteger deadlineBigInt = BigInteger.valueOf(getDeadline().getInstant()); // Create Modifications - int[] customersBuffer = createCosigModificationVector(builder, customersModifications); - int[] executorsBuffer = createCosigModificationVector(builder, executorsModifications); - int[] verifiersBuffer = createCosigModificationVector(builder, verifiersModifications); + int[] customersBuffer = createCosigModificationVector(builder, getCustomersModifications()); + int[] executorsBuffer = createCosigModificationVector(builder, getExecutorsModifications()); + int[] verifiersBuffer = createCosigModificationVector(builder, getVerifiersModifications()); // serialize content hash to byte array - byte[] contentHashBytes = HexEncoder.getBytes(contentHash); - + byte[] contentHashBytes = contentHashToBytes(getContentHash()); + // Create Vectors int signatureOffset = ModifyContractTransactionBuffer.createSignatureVector(builder, new byte[64]); int signerOffset = ModifyContractTransactionBuffer.createSignerVector(builder, new byte[32]); - int deadlineOffset = ModifyContractTransactionBuffer.createDeadlineVector(builder, UInt64Utils.fromBigInteger(deadlineBigInt)); - int feeOffset = ModifyContractTransactionBuffer.createMaxFeeVector(builder, UInt64Utils.fromBigInteger(getFee())); - int durationDeltaOffset = ModifyContractTransactionBuffer.createDurationDeltaVector(builder, UInt64Utils.fromBigInteger(durationDelta)); + int deadlineOffset = ModifyContractTransactionBuffer.createDeadlineVector(builder, + UInt64Utils.fromBigInteger(deadlineBigInt)); + int feeOffset = ModifyContractTransactionBuffer.createMaxFeeVector(builder, + UInt64Utils.fromBigInteger(getMaxFee())); + int durationDeltaOffset = ModifyContractTransactionBuffer.createDurationDeltaVector(builder, + UInt64Utils.fromBigInteger(getDurationDelta())); int hashOffset = ModifyContractTransactionBuffer.createHashVector(builder, contentHashBytes); int customersOffset = ModifyContractTransactionBuffer.createCustomersVector(builder, customersBuffer); int executorsOffset = ModifyContractTransactionBuffer.createExecutorsVector(builder, executorsBuffer); int verifiersOffset = ModifyContractTransactionBuffer.createVerifiersVector(builder, verifiersBuffer); - // header + duration delta + hash length + 3 modification lengths + 33 bytes per every modification (1 byte mod type + 32 bytes public key) - int totalSize = HEADER_SIZE + 8 + contentHashBytes.length + 3 + 33 * (customersBuffer.length + executorsBuffer.length + verifiersBuffer.length); + int totalSize = getSerializedSize(); // standard transaction information ModifyContractTransactionBuffer.startModifyContractTransactionBuffer(builder); @@ -142,7 +169,17 @@ byte[] generateBytes() { Validate.isTrue(output.length == totalSize, "Serialized transaction has incorrect length: " + this.getClass()); return output; } - + + /** + * serialize hexadecimal string with content hash to byte array + * + * @param hash hexadecimal string + * @return byte array + */ + private static byte[] contentHashToBytes(String hash) { + return HexEncoder.getBytes(hash); + } + /** * create vector for cosignatory modifications * @@ -150,57 +187,47 @@ byte[] generateBytes() { * @param modifications list of cosignatory modifications * @return array of buffer offsets for modification */ - private static int[] createCosigModificationVector(FlatBufferBuilder builder, List modifications) { + private static int[] createCosigModificationVector(FlatBufferBuilder builder, + List modifications) { // create array for vector offsets int[] modificationsBuffers = new int[modifications.size()]; // go over all modifications and prepare the buffers for (int i = 0; i < modifications.size(); ++i) { - MultisigCosignatoryModification multisigCosignatoryModification = modifications.get(i); - // serialize public key - byte[] cosignatoryPublicKeyBytes = HexEncoder.getBytes(multisigCosignatoryModification.getCosignatoryPublicAccount().getPublicKey()); - // get vector offset for the public key - int cosignatoryPublicKeyOffset = CosignatoryModificationBuffer.createCosignatoryPublicKeyVector(builder, cosignatoryPublicKeyBytes); - // create buffer and add it to the array - CosignatoryModificationBuffer.startCosignatoryModificationBuffer(builder); - CosignatoryModificationBuffer.addType(builder, multisigCosignatoryModification.getType().getValue()); - CosignatoryModificationBuffer.addCosignatoryPublicKey(builder, cosignatoryPublicKeyOffset); - modificationsBuffers[i] = CosignatoryModificationBuffer.endCosignatoryModificationBuffer(builder); + MultisigCosignatoryModification multisigCosignatoryModification = modifications.get(i); + // serialize public key + byte[] cosignatoryPublicKeyBytes = HexEncoder + .getBytes(multisigCosignatoryModification.getCosignatoryPublicAccount().getPublicKey()); + // get vector offset for the public key + int cosignatoryPublicKeyOffset = CosignatoryModificationBuffer.createCosignatoryPublicKeyVector(builder, + cosignatoryPublicKeyBytes); + // create buffer and add it to the array + CosignatoryModificationBuffer.startCosignatoryModificationBuffer(builder); + CosignatoryModificationBuffer.addType(builder, multisigCosignatoryModification.getType().getValue()); + CosignatoryModificationBuffer.addCosignatoryPublicKey(builder, cosignatoryPublicKeyOffset); + modificationsBuffers[i] = CosignatoryModificationBuffer.endCosignatoryModificationBuffer(builder); } return modificationsBuffers; } - /** - * @return the durationDelta - */ - public BigInteger getDurationDelta() { - return durationDelta; - } - - /** - * @return the contentHash - */ - public String getContentHash() { - return contentHash; - } - - /** - * @return the customersModifications - */ - public List getCustomersModifications() { - return customersModifications; + public static int calculatePayloadSize(String contentHash, int customerCount, int executorsCount, + int verifiersCount) { + // duration delta + hash length + 3 modification lengths + 33 bytes per every modification (1 byte mod type + 32 + // bytes public key) + return 8 + contentHashToBytes(contentHash).length + 3 + 33 * (customerCount + executorsCount + verifiersCount); } - /** - * @return the executorsModifications - */ - public List getExecutorsModifications() { - return executorsModifications; + @Override + protected int getPayloadSerializedSize() { + return calculatePayloadSize(getContentHash(), + getCustomersModifications().size(), + getExecutorsModifications().size(), + getVerifiersModifications().size()); } - /** - * @return the verifiersModifications - */ - public List getVerifiersModifications() { - return verifiersModifications; + @Override + protected Transaction copyForSigner(PublicAccount signer) { + return new ModifyContractTransaction(getNetworkType(), getVersion(), getDeadline(), getMaxFee(), getSignature(), + Optional.of(signer), getTransactionInfo(), getDurationDelta(), getContentHash(), + getCustomersModifications(), getExecutorsModifications(), getVerifiersModifications()); } } diff --git a/src/main/java/io/proximax/sdk/model/transaction/ModifyMetadataTransaction.java b/src/main/java/io/proximax/sdk/model/transaction/ModifyMetadataTransaction.java index 326f3952..2bc0c55c 100644 --- a/src/main/java/io/proximax/sdk/model/transaction/ModifyMetadataTransaction.java +++ b/src/main/java/io/proximax/sdk/model/transaction/ModifyMetadataTransaction.java @@ -20,6 +20,7 @@ import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.nio.charset.StandardCharsets; +import java.util.Collections; import java.util.List; import java.util.Optional; @@ -28,6 +29,7 @@ import com.google.flatbuffers.FlatBufferBuilder; import io.proximax.core.utils.Base32Encoder; +import io.proximax.core.utils.StringUtils; import io.proximax.sdk.gen.buffers.MetadataModificationBuffer; import io.proximax.sdk.gen.buffers.ModifyMetadataTransactionBuffer; import io.proximax.sdk.model.account.Address; @@ -37,67 +39,47 @@ import io.proximax.sdk.model.metadata.MetadataModification; import io.proximax.sdk.model.metadata.MetadataModificationType; import io.proximax.sdk.model.metadata.MetadataType; -import io.proximax.sdk.model.mosaic.MosaicId; -import io.proximax.sdk.model.namespace.NamespaceId; import io.proximax.sdk.utils.dto.UInt64Utils; /** * Transaction requesting modification of metadata */ public class ModifyMetadataTransaction extends Transaction { + private final Schema schema = new ModifyMetadataTransactionSchema(); + private final MetadataType metadataType; private final Optional metadataId; private final Optional
address; private final List modifications; - private final Schema schema = new ModifyMetadataTransactionSchema(); - public ModifyMetadataTransaction(TransactionType transactionType, NetworkType networkType, - Integer transactionVersion, TransactionDeadline deadline, BigInteger fee, Optional metadataId, - Optional
address, MetadataType metadataType, List modifications, String signature, - PublicAccount signer, TransactionInfo transactionInfo) { - this(transactionType, networkType, transactionVersion, deadline, fee, metadataId, address, - metadataType, modifications, Optional.of(signature), Optional.of(signer), Optional.of(transactionInfo)); - } - - private ModifyMetadataTransaction(TransactionType transactionType, NetworkType networkType, TransactionDeadline deadline, - Optional metadataId, Optional
address, MetadataType metadataType, - List modifications) { - this(transactionType, networkType, TransactionVersion.METADATA_MODIFICATION.getValue(), deadline, BigInteger.ZERO, - metadataId, address, metadataType, modifications, Optional.empty(), Optional.empty(), Optional.empty()); - } - - private ModifyMetadataTransaction(TransactionType transactionType, NetworkType networkType, Integer version, - TransactionDeadline deadline, BigInteger fee, Optional metadataId, Optional
address, - MetadataType metadataType, List modifications, Optional signature, - Optional signer, Optional transactionInfo) { - super(transactionType, networkType, version, deadline, fee, signature, signer, transactionInfo); - Validate.notNull(metadataType, "metadataType must not be null"); - Validate.notNull(metadataId, "metadataId must not be null"); - Validate.notNull(address, "address must not be null"); - Validate.notNull(modifications, "modifications must not be null"); - Validate.isTrue(metadataId.isPresent() != address.isPresent(), "specify metadata id or address exclusively"); + /** + * @param type + * @param networkType + * @param version + * @param deadline + * @param maxFee + * @param signature + * @param signer + * @param transactionInfo + * @param metadataType + * @param metadataId + * @param address + * @param modifications + */ + public ModifyMetadataTransaction(TransactionType type, NetworkType networkType, Integer version, + TransactionDeadline deadline, BigInteger maxFee, Optional signature, Optional signer, + Optional transactionInfo, MetadataType metadataType, Optional metadataId, + Optional
address, List modifications) { + super(type, networkType, version, deadline, maxFee, signature, signer, transactionInfo); + // validations + Validate.notNull(metadataType, "metadataType can not be null"); + Validate.isTrue(address.isPresent() != metadataId.isPresent(), "Has to be either address or metadata"); + Validate.notNull(modifications, "modifications can not be null"); + // assignments + this.metadataType = metadataType; this.metadataId = metadataId; this.address = address; - this.metadataType = metadataType; - this.modifications = modifications; - } - - public static ModifyMetadataTransaction createForMosaic(TransactionDeadline deadline, MosaicId mosaicId, - List modifications, NetworkType networkType) { - return new ModifyMetadataTransaction(TransactionType.MODIFY_MOSAIC_METADATA, networkType, deadline, - Optional.of(mosaicId), Optional.empty(), MetadataType.MOSAIC, modifications); - } - - public static ModifyMetadataTransaction createForNamespace(TransactionDeadline deadline, NamespaceId namespaceId, - List modifications, NetworkType networkType) { - return new ModifyMetadataTransaction(TransactionType.MODIFY_NAMESPACE_METADATA, networkType, deadline, - Optional.of(namespaceId), Optional.empty(), MetadataType.NAMESPACE, modifications); - } - - public static ModifyMetadataTransaction createForAddress(TransactionDeadline deadline, Address address, - List modifications, NetworkType networkType) { - return new ModifyMetadataTransaction(TransactionType.MODIFY_ADDRESS_METADATA, networkType, deadline, - Optional.empty(), Optional.of(address), MetadataType.ADDRESS, modifications); + this.modifications = Collections.unmodifiableList(modifications); } /** @@ -128,7 +110,7 @@ public List getModifications() { return modifications; } - byte[] generateBytes() { + protected byte[] generateBytes() { FlatBufferBuilder builder = new FlatBufferBuilder(); // prepare data for serialization @@ -142,8 +124,6 @@ byte[] generateBytes() { throw new IllegalStateException("Always has to be address or id"); } - // track the size of the whole metadata modification - int totalSize = 0; // load modifications int[] modificationOffsets = new int[modifications.size()]; for (int i = 0; i < modificationOffsets.length; i++) { @@ -165,8 +145,6 @@ byte[] generateBytes() { // compute number of bytes: size + modType + keySize + valueSize + key + value int modSize = 4 + 1 + 1 + 2 + keyBytes.length + valueBytes.length; - // increase total size - totalSize += modSize; // populate flat-buffer MetadataModificationBuffer.startMetadataModificationBuffer(builder); @@ -184,12 +162,13 @@ byte[] generateBytes() { int signerOffset = ModifyMetadataTransactionBuffer.createSignerVector(builder, new byte[32]); int deadlineOffset = ModifyMetadataTransactionBuffer.createDeadlineVector(builder, UInt64Utils.fromBigInteger(deadlineBigInt)); - int feeOffset = ModifyMetadataTransactionBuffer.createMaxFeeVector(builder, UInt64Utils.fromBigInteger(getFee())); + int feeOffset = ModifyMetadataTransactionBuffer.createMaxFeeVector(builder, + UInt64Utils.fromBigInteger(getMaxFee())); int metadataIdOffset = ModifyMetadataTransactionBuffer.createMetadataIdVector(builder, metadataIdBytes); int modificationsOffset = ModifyMetadataTransactionBuffer.createModificationsVector(builder, modificationOffsets); // add size of stuff with constant size and size of metadata id - totalSize += HEADER_SIZE + metadataIdBytes.length + 1; + int totalSize = getSerializedSize(); ModifyMetadataTransactionBuffer.startModifyMetadataTransactionBuffer(builder); ModifyMetadataTransactionBuffer.addDeadline(builder, deadlineOffset); @@ -212,4 +191,47 @@ byte[] generateBytes() { Validate.isTrue(output.length == totalSize, "Serialized transaction has incorrect length: " + this.getClass()); return output; } + + /** + * calculate size of modification + * + * @param mod the modification + * @return the size + */ + private static int calculateModSize(MetadataModification mod) { + int keySize = StringUtils.getBytes(mod.getField().getKey()).length; + // remove does not have value + int valueSize = mod.getType() == MetadataModificationType.REMOVE ? 0 + : StringUtils.getBytes(mod.getField().getValue()).length; + // compute number of bytes: size + modType + keySize + valueSize + key + value + return 4 + 1 + 1 + 2 + keySize + valueSize; + } + + /** + * calculate payload size + * + * @param isAddressMetadata true if address, false otherwise + * @param mods modifications + * + * @return size + */ + public static int calculatePayloadSize(boolean isAddressMetadata, List mods) { + // 25 bytes for address 8 bytes for uint64 + int metaIdSize = isAddressMetadata ? 25 : 8; + int modsSize = mods.stream().mapToInt(ModifyMetadataTransaction::calculateModSize).sum(); + // id + mod size + mods + return metaIdSize + 1 + modsSize; + } + + @Override + protected int getPayloadSerializedSize() { + return calculatePayloadSize(getAddress().isPresent(), getModifications()); + } + + @Override + protected Transaction copyForSigner(PublicAccount signer) { + return new ModifyMetadataTransaction(getType(), getNetworkType(), getVersion(), getDeadline(), getMaxFee(), + getSignature(), Optional.of(signer), getTransactionInfo(), getMetadataType(), getMetadataId(), getAddress(), + getModifications()); + } } diff --git a/src/main/java/io/proximax/sdk/model/transaction/ModifyMultisigAccountTransaction.java b/src/main/java/io/proximax/sdk/model/transaction/ModifyMultisigAccountTransaction.java index ccea1c5b..87a1ba52 100644 --- a/src/main/java/io/proximax/sdk/model/transaction/ModifyMultisigAccountTransaction.java +++ b/src/main/java/io/proximax/sdk/model/transaction/ModifyMultisigAccountTransaction.java @@ -17,6 +17,7 @@ package io.proximax.sdk.model.transaction; import java.math.BigInteger; +import java.util.Collections; import java.util.List; import java.util.Optional; @@ -32,123 +33,145 @@ import io.proximax.sdk.utils.dto.UInt64Utils; /** - * Modify multisig account transactions are part of the NEM's multisig account system. - * A modify multisig account transaction holds an array of multisig cosignatory modifications, min number of signatures to approve a transaction and a min number of signatures to remove a cosignatory. - * - * @since 1.0 + * Modify multisig account transactions are part of the NEM's multisig account system. A modify multisig account + * transaction holds an array of multisig cosignatory modifications, min number of signatures to approve a transaction + * and a min number of signatures to remove a cosignatory. */ public class ModifyMultisigAccountTransaction extends Transaction { - private final int minApprovalDelta; - private final int minRemovalDelta; - private final List modifications; - private final Schema schema = new ModifyMultisigAccountTransactionSchema(); - - public ModifyMultisigAccountTransaction(NetworkType networkType, Integer version, TransactionDeadline deadline, BigInteger fee, int minApprovalDelta, int minRemovalDelta, List modifications, String signature, PublicAccount signer, TransactionInfo transactionInfo) { - this(networkType, version, deadline, fee, minApprovalDelta, minRemovalDelta, modifications, Optional.of(signature), Optional.of(signer), Optional.of(transactionInfo)); - } - - public ModifyMultisigAccountTransaction(NetworkType networkType, Integer version, TransactionDeadline deadline, BigInteger fee, int minApprovalDelta, int minRemovalDelta, List modifications) { - this(networkType, version, deadline, fee, minApprovalDelta, minRemovalDelta, modifications, Optional.empty(), Optional.empty(), Optional.empty()); - } - - private ModifyMultisigAccountTransaction(NetworkType networkType, Integer version, TransactionDeadline deadline, BigInteger fee, int minApprovalDelta, int minRemovalDelta, List modifications, Optional signature, Optional signer, Optional transactionInfo) { - super(TransactionType.MODIFY_MULTISIG_ACCOUNT, networkType, version, deadline, fee, signature, signer, transactionInfo); - Validate.notNull(modifications, "Modifications must not be null"); - this.minApprovalDelta = minApprovalDelta; - this.minRemovalDelta = minRemovalDelta; - this.modifications = modifications; - } - - /** - * Create a modify multisig account transaction object. - * - * @param deadline The deadline to include the transaction. - * @param minApprovalDelta The min approval relative change. - * @param minRemovalDelta The min removal relative change. - * @param modifications The list of modifications. - * @param networkType The network type. - * @return {@link ModifyMultisigAccountTransaction} - */ - - public static ModifyMultisigAccountTransaction create(TransactionDeadline deadline, int minApprovalDelta, int minRemovalDelta, List modifications, NetworkType networkType) { - return new ModifyMultisigAccountTransaction(networkType, 3, deadline, BigInteger.valueOf(0), minApprovalDelta, minRemovalDelta, modifications); - } - - /** - * Return number of signatures needed to approve a transaction. - * If we are modifying and existing multi-signature account this indicates the relative change of the minimum cosignatories. - * - * @return int - */ - public int getMinApprovalDelta() { - return minApprovalDelta; - } - - /** - * Return number of signatures needed to remove a cosignatory. - * If we are modifying and existing multi-signature account this indicates the relative change of the minimum cosignatories. - * - * @return int - */ - public int getMinRemovalDelta() { - return minRemovalDelta; - } - - /** - * The List of cosigner accounts added or removed from the multi-signature account. - * - * @return modifications in this transaction - */ - public List getModifications() { - return modifications; - } - - byte[] generateBytes() { - FlatBufferBuilder builder = new FlatBufferBuilder(); - BigInteger deadlineBigInt = BigInteger.valueOf(getDeadline().getInstant()); - - // Create Modifications - int[] modificationsBuffers = new int[modifications.size()]; - for (int i = 0; i < modifications.size(); ++i) { - MultisigCosignatoryModification multisigCosignatoryModification = modifications.get(i); - byte[] byteCosignatoryPublicKey = HexEncoder.getBytes(multisigCosignatoryModification.getCosignatoryPublicAccount().getPublicKey()); - int cosignatoryPublicKey = CosignatoryModificationBuffer.createCosignatoryPublicKeyVector(builder, byteCosignatoryPublicKey); - CosignatoryModificationBuffer.startCosignatoryModificationBuffer(builder); - CosignatoryModificationBuffer.addType(builder, multisigCosignatoryModification.getType().getValue()); - CosignatoryModificationBuffer.addCosignatoryPublicKey(builder, cosignatoryPublicKey); - modificationsBuffers[i] = CosignatoryModificationBuffer.endCosignatoryModificationBuffer(builder); - } - - // Create Vectors - int signatureVector = ModifyMultisigAccountTransactionBuffer.createSignatureVector(builder, new byte[64]); - int signerVector = ModifyMultisigAccountTransactionBuffer.createSignerVector(builder, new byte[32]); - int deadlineVector = ModifyMultisigAccountTransactionBuffer.createDeadlineVector(builder, UInt64Utils.fromBigInteger(deadlineBigInt)); - int feeVector = ModifyMultisigAccountTransactionBuffer.createMaxFeeVector(builder, UInt64Utils.fromBigInteger(getFee())); - int modificationsVector = ModifyMultisigAccountTransactionBuffer.createModificationsVector(builder, modificationsBuffers); - - // header, min approval, min removal, mod count, mod (type, pub key) * count - int size = HEADER_SIZE + 1 + 1 + 1 + (1 + 32) * modifications.size(); - - ModifyMultisigAccountTransactionBuffer.startModifyMultisigAccountTransactionBuffer(builder); - ModifyMultisigAccountTransactionBuffer.addSize(builder, size); - ModifyMultisigAccountTransactionBuffer.addSignature(builder, signatureVector); - ModifyMultisigAccountTransactionBuffer.addSigner(builder, signerVector); - ModifyMultisigAccountTransactionBuffer.addVersion(builder, getTxVersionforSerialization()); - ModifyMultisigAccountTransactionBuffer.addType(builder, getType().getValue()); - ModifyMultisigAccountTransactionBuffer.addMaxFee(builder, feeVector); - ModifyMultisigAccountTransactionBuffer.addDeadline(builder, deadlineVector); - - ModifyMultisigAccountTransactionBuffer.addMinApprovalDelta(builder, (byte)minApprovalDelta); - ModifyMultisigAccountTransactionBuffer.addMinRemovalDelta(builder, (byte)minRemovalDelta); - ModifyMultisigAccountTransactionBuffer.addNumModifications(builder, modifications.size()); - ModifyMultisigAccountTransactionBuffer.addModifications(builder, modificationsVector); - - int codedTransaction = ModifyMultisigAccountTransactionBuffer.endModifyMultisigAccountTransactionBuffer(builder); - builder.finish(codedTransaction); - - // validate size - byte[] output = schema.serialize(builder.sizedByteArray()); - Validate.isTrue(output.length == size, "Serialized transaction has incorrect length: " + this.getClass()); - return output; - } + private final Schema schema = new ModifyMultisigAccountTransactionSchema(); + + private final int minApprovalDelta; + private final int minRemovalDelta; + private final List modifications; + + /** + * @param networkType network type + * @param version transaction version. Use {@link TransactionVersion#MODIFY_MULTISIG_ACCOUNT} for current version + * @param deadline transaction deadline + * @param maxFee transaction fee + * @param signature optional signature + * @param signer optional signer + * @param transactionInfo optional transaction info + * @param minApprovalDelta minimum number of cosignatures for transaction approval + * @param minRemovalDelta minimum number of cosignatures for cosignatory removal + * @param modifications + */ + public ModifyMultisigAccountTransaction(NetworkType networkType, Integer version, TransactionDeadline deadline, + BigInteger maxFee, Optional signature, Optional signer, + Optional transactionInfo, int minApprovalDelta, int minRemovalDelta, + List modifications) { + super(TransactionType.MODIFY_MULTISIG_ACCOUNT, networkType, version, deadline, maxFee, signature, signer, + transactionInfo); + // validations + Validate.notNull(modifications, "Modifications must not be null"); + // assignments + this.minApprovalDelta = minApprovalDelta; + this.minRemovalDelta = minRemovalDelta; + this.modifications = Collections.unmodifiableList(modifications); + } + + /** + * Return number of signatures needed to approve a transaction. If we are modifying and existing multi-signature + * account this indicates the relative change of the minimum cosignatories. + * + * @return int + */ + public int getMinApprovalDelta() { + return minApprovalDelta; + } + + /** + * Return number of signatures needed to remove a cosignatory. If we are modifying and existing multi-signature + * account this indicates the relative change of the minimum cosignatories. + * + * @return int + */ + public int getMinRemovalDelta() { + return minRemovalDelta; + } + + /** + * The List of cosigner accounts added or removed from the multi-signature account. + * + * @return modifications in this transaction + */ + public List getModifications() { + return modifications; + } + + protected byte[] generateBytes() { + FlatBufferBuilder builder = new FlatBufferBuilder(); + BigInteger deadlineBigInt = BigInteger.valueOf(getDeadline().getInstant()); + + // Create Modifications + int[] modificationsBuffers = new int[getModifications().size()]; + for (int i = 0; i < getModifications().size(); ++i) { + MultisigCosignatoryModification multisigCosignatoryModification = getModifications().get(i); + byte[] byteCosignatoryPublicKey = HexEncoder + .getBytes(multisigCosignatoryModification.getCosignatoryPublicAccount().getPublicKey()); + int cosignatoryPublicKey = CosignatoryModificationBuffer.createCosignatoryPublicKeyVector(builder, + byteCosignatoryPublicKey); + CosignatoryModificationBuffer.startCosignatoryModificationBuffer(builder); + CosignatoryModificationBuffer.addType(builder, multisigCosignatoryModification.getType().getValue()); + CosignatoryModificationBuffer.addCosignatoryPublicKey(builder, cosignatoryPublicKey); + modificationsBuffers[i] = CosignatoryModificationBuffer.endCosignatoryModificationBuffer(builder); + } + + // Create Vectors + int signatureVector = ModifyMultisigAccountTransactionBuffer.createSignatureVector(builder, new byte[64]); + int signerVector = ModifyMultisigAccountTransactionBuffer.createSignerVector(builder, new byte[32]); + int deadlineVector = ModifyMultisigAccountTransactionBuffer.createDeadlineVector(builder, + UInt64Utils.fromBigInteger(deadlineBigInt)); + int feeVector = ModifyMultisigAccountTransactionBuffer.createMaxFeeVector(builder, + UInt64Utils.fromBigInteger(getMaxFee())); + int modificationsVector = ModifyMultisigAccountTransactionBuffer.createModificationsVector(builder, + modificationsBuffers); + + int size = getSerializedSize(); + + ModifyMultisigAccountTransactionBuffer.startModifyMultisigAccountTransactionBuffer(builder); + ModifyMultisigAccountTransactionBuffer.addSize(builder, size); + ModifyMultisigAccountTransactionBuffer.addSignature(builder, signatureVector); + ModifyMultisigAccountTransactionBuffer.addSigner(builder, signerVector); + ModifyMultisigAccountTransactionBuffer.addVersion(builder, getTxVersionforSerialization()); + ModifyMultisigAccountTransactionBuffer.addType(builder, getType().getValue()); + ModifyMultisigAccountTransactionBuffer.addMaxFee(builder, feeVector); + ModifyMultisigAccountTransactionBuffer.addDeadline(builder, deadlineVector); + + ModifyMultisigAccountTransactionBuffer.addMinApprovalDelta(builder, (byte) getMinApprovalDelta()); + ModifyMultisigAccountTransactionBuffer.addMinRemovalDelta(builder, (byte) getMinRemovalDelta()); + ModifyMultisigAccountTransactionBuffer.addNumModifications(builder, getModifications().size()); + ModifyMultisigAccountTransactionBuffer.addModifications(builder, modificationsVector); + + int codedTransaction = ModifyMultisigAccountTransactionBuffer.endModifyMultisigAccountTransactionBuffer(builder); + builder.finish(codedTransaction); + + // validate size + byte[] output = schema.serialize(builder.sizedByteArray()); + Validate.isTrue(output.length == size, "Serialized transaction has incorrect length: " + this.getClass()); + return output; + } + + /** + * calculate size of payload without header + * + * @param modificationCount number of multisig modifications + * @return size + */ + public static int calculatePayloadSize(int modificationCount) { + // min approval, min removal, mod count, mod (type, pub key) * count + return 1 + 1 + 1 + (1 + 32) * modificationCount; + } + + @Override + protected int getPayloadSerializedSize() { + return calculatePayloadSize(getModifications().size()); + } + + @Override + protected Transaction copyForSigner(PublicAccount signer) { + return new ModifyMultisigAccountTransaction(getNetworkType(), getVersion(), getDeadline(), getMaxFee(), + getSignature(), Optional.of(signer), getTransactionInfo(), getMinApprovalDelta(), getMinRemovalDelta(), + getModifications()); + } } diff --git a/src/main/java/io/proximax/sdk/model/transaction/MosaicDefinitionTransaction.java b/src/main/java/io/proximax/sdk/model/transaction/MosaicDefinitionTransaction.java index 39dffce7..322a50b5 100644 --- a/src/main/java/io/proximax/sdk/model/transaction/MosaicDefinitionTransaction.java +++ b/src/main/java/io/proximax/sdk/model/transaction/MosaicDefinitionTransaction.java @@ -43,54 +43,40 @@ * @since 1.0 */ public class MosaicDefinitionTransaction extends Transaction { + private final Schema schema = new MosaicDefinitionTransactionSchema(); + private final MosaicNonce nonce; private final MosaicId mosaicId; private final MosaicProperties mosaicProperties; - private final Schema schema = new MosaicDefinitionTransactionSchema(); - - public MosaicDefinitionTransaction(NetworkType networkType, Integer version, TransactionDeadline deadline, BigInteger fee, - MosaicNonce nonce, MosaicId mosaicId, MosaicProperties mosaicProperties, String signature, PublicAccount signer, - TransactionInfo transactionInfo) { - this(networkType, version, deadline, fee, nonce, mosaicId, mosaicProperties, Optional.of(signature), Optional.of(signer), - Optional.of(transactionInfo)); - } - - public MosaicDefinitionTransaction(NetworkType networkType, Integer version, TransactionDeadline deadline, BigInteger fee, - MosaicNonce nonce, MosaicId mosaicId, MosaicProperties mosaicProperties) { - this(networkType, version, deadline, fee, nonce, mosaicId, mosaicProperties, Optional.empty(), Optional.empty(), - Optional.empty()); - } - private MosaicDefinitionTransaction(NetworkType networkType, Integer version, TransactionDeadline deadline, BigInteger fee, - MosaicNonce nonce, MosaicId mosaicId, MosaicProperties mosaicProperties, Optional signature, - Optional signer, Optional transactionInfo) { - super(TransactionType.MOSAIC_DEFINITION, networkType, version, deadline, fee, signature, signer, transactionInfo); + /** + * @param networkType + * @param version + * @param deadline + * @param maxFee + * @param signature + * @param signer + * @param transactionInfo + * @param nonce + * @param mosaicId + * @param mosaicProperties + */ + public MosaicDefinitionTransaction(NetworkType networkType, Integer version, TransactionDeadline deadline, + BigInteger maxFee, Optional signature, Optional signer, + Optional transactionInfo, MosaicNonce nonce, MosaicId mosaicId, + MosaicProperties mosaicProperties) { + super(TransactionType.MOSAIC_DEFINITION, networkType, version, deadline, maxFee, signature, signer, + transactionInfo); + // validations Validate.notNull(nonce, "nonce must not be null"); Validate.notNull(mosaicId, "MosaicId must not be null"); Validate.notNull(mosaicProperties, "MosaicProperties must not be null"); + // assignments + this.nonce = nonce; this.mosaicId = mosaicId; this.mosaicProperties = mosaicProperties; - this.nonce = nonce; } - /** - * Create a mosaic creation transaction object. - * - * @param nonce mosaic nonce allowing one account to have multiple mosaics - * @param mosaicId id of the mosaic to be created - * @param deadline The deadline to include the transaction. - * @param mosaicProperties The mosaic properties. - * @param networkType The network type. - * @return {@link MosaicDefinitionTransaction} - */ - public static MosaicDefinitionTransaction create(MosaicNonce nonce, MosaicId mosaicId, TransactionDeadline deadline, - MosaicProperties mosaicProperties, NetworkType networkType) { - Validate.notNull(mosaicId, "MosaicId must not be null"); - return new MosaicDefinitionTransaction(networkType, TransactionVersion.MOSAIC_DEFINITION.getValue(), deadline, - BigInteger.valueOf(0), nonce, mosaicId, mosaicProperties); - } - - /** * Returns mosaic id generated from namespace name and mosaic name. * @@ -118,7 +104,7 @@ public MosaicProperties getMosaicProperties() { return mosaicProperties; } - byte[] generateBytes() { + protected byte[] generateBytes() { FlatBufferBuilder builder = new FlatBufferBuilder(); BigInteger deadlineBigInt = BigInteger.valueOf(getDeadline().getInstant()); // get value for flags field @@ -136,7 +122,7 @@ byte[] generateBytes() { if (duration.isPresent()) { propertyList.add(new ImmutablePair<>(MosaicPropertyId.DURATION, duration.get())); } - int[] optinalPropertiesVector = new int[propertyList.size()]; + int[] optionalPropertyVectors = new int[propertyList.size()]; for (int i = 0; i < propertyList.size(); i++) { Pair property = propertyList.get(i); // prepare offset for the value @@ -145,7 +131,7 @@ byte[] generateBytes() { MosaicProperty.startMosaicProperty(builder); MosaicProperty.addMosaicPropertyId(builder, property.getKey().getCode()); MosaicProperty.addValue(builder, valueOffset); - optinalPropertiesVector[i] = MosaicProperty.endMosaicProperty(builder); + optionalPropertyVectors[i] = MosaicProperty.endMosaicProperty(builder); } // Create Vectors int signatureVector = MosaicDefinitionTransactionBuffer.createSignatureVector(builder, new byte[64]); @@ -153,14 +139,14 @@ byte[] generateBytes() { int deadlineVector = MosaicDefinitionTransactionBuffer.createDeadlineVector(builder, UInt64Utils.fromBigInteger(deadlineBigInt)); int feeVector = MosaicDefinitionTransactionBuffer.createMaxFeeVector(builder, - UInt64Utils.fromBigInteger(getFee())); + UInt64Utils.fromBigInteger(getMaxFee())); int mosaicIdVector = MosaicDefinitionTransactionBuffer.createMosaicIdVector(builder, UInt64Utils.fromBigInteger(mosaicId.getId())); int optionalPropertiesVector = MosaicDefinitionTransactionBuffer.createOptionalPropertiesVector(builder, - optinalPropertiesVector); + optionalPropertyVectors); // header + nonce + id + numOptProp + flags + divisibility + (id + value)*numOptProp - int size = HEADER_SIZE + 4 + 8 + 1 + 1 + 1 + (1 + 8) * optinalPropertiesVector.length; + int size = getSerializedSize(); MosaicDefinitionTransactionBuffer.startMosaicDefinitionTransactionBuffer(builder); MosaicDefinitionTransactionBuffer.addSize(builder, size); @@ -173,7 +159,7 @@ byte[] generateBytes() { MosaicDefinitionTransactionBuffer.addMosaicNonce(builder, nonce.getNonceAsInt()); MosaicDefinitionTransactionBuffer.addMosaicId(builder, mosaicIdVector); - MosaicDefinitionTransactionBuffer.addNumOptionalProperties(builder, optinalPropertiesVector.length); + MosaicDefinitionTransactionBuffer.addNumOptionalProperties(builder, optionalPropertyVectors.length); MosaicDefinitionTransactionBuffer.addFlags(builder, flags); MosaicDefinitionTransactionBuffer.addDivisibility(builder, mosaicProperties.getDivisibility()); MosaicDefinitionTransactionBuffer.addOptionalProperties(builder, optionalPropertiesVector); @@ -186,4 +172,19 @@ byte[] generateBytes() { Validate.isTrue(output.length == size, "Serialized transaction has incorrect length: " + this.getClass()); return output; } + + public static int calculatePayloadSize(int numOptionalProperties) { + return 4 + 8 + 1 + 1 + 1 + (1 + 8) * numOptionalProperties; + } + + @Override + protected int getPayloadSerializedSize() { + return calculatePayloadSize(getMosaicProperties().getDuration().isPresent() ? 1 : 0); + } + + @Override + protected Transaction copyForSigner(PublicAccount signer) { + return new MosaicDefinitionTransaction(getNetworkType(), getVersion(), getDeadline(), getMaxFee(), getSignature(), + Optional.of(signer), getTransactionInfo(), getNonce(), getMosaicId(), getMosaicProperties()); + } } diff --git a/src/main/java/io/proximax/sdk/model/transaction/MosaicSupplyChangeTransaction.java b/src/main/java/io/proximax/sdk/model/transaction/MosaicSupplyChangeTransaction.java index 8ab6f308..7834012c 100644 --- a/src/main/java/io/proximax/sdk/model/transaction/MosaicSupplyChangeTransaction.java +++ b/src/main/java/io/proximax/sdk/model/transaction/MosaicSupplyChangeTransaction.java @@ -31,111 +31,125 @@ import io.proximax.sdk.utils.dto.UInt64Utils; /** - * In case a mosaic has the flag 'supplyMutable' set to true, the creator of the mosaic can change the supply, - * i.e. increase or decrease the supply. - * - * @since 1.0 + * In case a mosaic has the flag 'supplyMutable' set to true, the creator of the mosaic can change the supply, i.e. + * increase or decrease the supply. */ public class MosaicSupplyChangeTransaction extends Transaction { - private final MosaicId mosaicId; - private final MosaicSupplyType mosaicSupplyType; - private final BigInteger delta; - private final Schema schema = new MosaicSupplyChangeTransactionSchema(); - - - public MosaicSupplyChangeTransaction(NetworkType networkType, Integer version, TransactionDeadline deadline, BigInteger fee, MosaicId mosaicId, MosaicSupplyType mosaicSupplyType, BigInteger delta, String signature, PublicAccount signer, TransactionInfo transactionInfo) { - this(networkType, version, deadline, fee, mosaicId, mosaicSupplyType, delta, Optional.of(signature), Optional.of(signer), Optional.of(transactionInfo)); - } - - public MosaicSupplyChangeTransaction(NetworkType networkType, Integer version, TransactionDeadline deadline, BigInteger fee, MosaicId mosaicId, MosaicSupplyType mosaicSupplyType, BigInteger delta) { - this(networkType, version, deadline, fee, mosaicId, mosaicSupplyType, delta, Optional.empty(), Optional.empty(), Optional.empty()); - } - - private MosaicSupplyChangeTransaction(NetworkType networkType, Integer version, TransactionDeadline deadline, BigInteger fee, MosaicId mosaicId, MosaicSupplyType mosaicSupplyType, BigInteger delta, Optional signature, Optional signer, Optional transactionInfo) { - super(TransactionType.MOSAIC_SUPPLY_CHANGE, networkType, version, deadline, fee, signature, signer, transactionInfo); - Validate.notNull(mosaicId, "MosaicId must not be null"); - Validate.notNull(mosaicSupplyType, "MosaicSupplyType must not be null"); - Validate.notNull(delta, "Delta must not be null"); - this.mosaicId = mosaicId; - this.mosaicSupplyType = mosaicSupplyType; - this.delta = delta; - } - - /** - * Create a mosaic supply change transaction object. - * - * @param deadline The deadline to include the transaction. - * @param mosaicId The mosaic id. - * @param mosaicSupplyType The supply type. - * @param delta The supply change in units for the mosaic. - * @param networkType The network type. - * @return {@link MosaicSupplyChangeTransaction} - */ - public static MosaicSupplyChangeTransaction create(TransactionDeadline deadline, MosaicId mosaicId, MosaicSupplyType mosaicSupplyType, BigInteger delta, NetworkType networkType) { - return new MosaicSupplyChangeTransaction(networkType, 2, deadline, BigInteger.valueOf(0), mosaicId, mosaicSupplyType, delta); - } - - /** - * Returns mosaic id. - * - * @return BigInteger - */ - public MosaicId getMosaicId() { - return mosaicId; - } - - /** - * Returns mosaic supply type. - * - * @return {@link MosaicSupplyType} - */ - public MosaicSupplyType getMosaicSupplyType() { - return mosaicSupplyType; - } - - /** - * Returns amount of mosaics added or removed. - * - * @return BigInteger - */ - public BigInteger getDelta() { - return delta; - } - - byte[] generateBytes() { - FlatBufferBuilder builder = new FlatBufferBuilder(); - BigInteger deadlineBigInt = BigInteger.valueOf(getDeadline().getInstant()); - - // Create Vectors - int signatureVector = MosaicSupplyChangeTransactionBuffer.createSignatureVector(builder, new byte[64]); - int signerVector = MosaicSupplyChangeTransactionBuffer.createSignerVector(builder, new byte[32]); - int deadlineVector = MosaicSupplyChangeTransactionBuffer.createDeadlineVector(builder, UInt64Utils.fromBigInteger(deadlineBigInt)); - int feeVector = MosaicSupplyChangeTransactionBuffer.createMaxFeeVector(builder, UInt64Utils.fromBigInteger(getFee())); - int mosaicIdVector = MosaicSupplyChangeTransactionBuffer.createMosaicIdVector(builder, UInt64Utils.fromBigInteger(mosaicId.getId())); - int deltaVector = MosaicSupplyChangeTransactionBuffer.createDeltaVector(builder, UInt64Utils.fromBigInteger(delta)); - - // header, mosaic id, supply type, delta - int size = HEADER_SIZE + 8 + 1 + 8; - - MosaicSupplyChangeTransactionBuffer.startMosaicSupplyChangeTransactionBuffer(builder); - MosaicSupplyChangeTransactionBuffer.addSize(builder, size); - MosaicSupplyChangeTransactionBuffer.addSignature(builder, signatureVector); - MosaicSupplyChangeTransactionBuffer.addSigner(builder, signerVector); - MosaicSupplyChangeTransactionBuffer.addVersion(builder, getTxVersionforSerialization()); - MosaicSupplyChangeTransactionBuffer.addType(builder, getType().getValue()); - MosaicSupplyChangeTransactionBuffer.addMaxFee(builder, feeVector); - MosaicSupplyChangeTransactionBuffer.addDeadline(builder, deadlineVector); - - MosaicSupplyChangeTransactionBuffer.addMosaicId(builder, mosaicIdVector); - MosaicSupplyChangeTransactionBuffer.addDirection(builder, mosaicSupplyType.getValue()); - MosaicSupplyChangeTransactionBuffer.addDelta(builder, deltaVector); - - int codedTransaction = MosaicSupplyChangeTransactionBuffer.endMosaicSupplyChangeTransactionBuffer(builder); - builder.finish(codedTransaction); - - // validate size - byte[] output = schema.serialize(builder.sizedByteArray()); - Validate.isTrue(output.length == size, "Serialized transaction has incorrect length: " + this.getClass()); - return output; - } + private final Schema schema = new MosaicSupplyChangeTransactionSchema(); + + private final MosaicId mosaicId; + private final MosaicSupplyType mosaicSupplyType; + private final BigInteger delta; + + /** + * @param networkType + * @param version + * @param deadline + * @param maxFee + * @param signature + * @param signer + * @param transactionInfo + * @param mosaicId + * @param mosaicSupplyType + * @param delta + */ + public MosaicSupplyChangeTransaction(NetworkType networkType, Integer version, TransactionDeadline deadline, + BigInteger maxFee, Optional signature, Optional signer, + Optional transactionInfo, MosaicId mosaicId, MosaicSupplyType mosaicSupplyType, + BigInteger delta) { + super(TransactionType.MOSAIC_SUPPLY_CHANGE, networkType, version, deadline, maxFee, signature, signer, + transactionInfo); + // validations + Validate.notNull(mosaicId, "MosaicId must not be null"); + Validate.notNull(mosaicSupplyType, "MosaicSupplyType must not be null"); + Validate.notNull(delta, "Delta must not be null"); + // assignments + this.mosaicId = mosaicId; + this.mosaicSupplyType = mosaicSupplyType; + this.delta = delta; + } + + /** + * Returns mosaic id. + * + * @return BigInteger + */ + public MosaicId getMosaicId() { + return mosaicId; + } + + /** + * Returns mosaic supply type. + * + * @return {@link MosaicSupplyType} + */ + public MosaicSupplyType getMosaicSupplyType() { + return mosaicSupplyType; + } + + /** + * Returns amount of mosaics added or removed. + * + * @return BigInteger + */ + public BigInteger getDelta() { + return delta; + } + + protected byte[] generateBytes() { + FlatBufferBuilder builder = new FlatBufferBuilder(); + BigInteger deadlineBigInt = BigInteger.valueOf(getDeadline().getInstant()); + + // Create Vectors + int signatureVector = MosaicSupplyChangeTransactionBuffer.createSignatureVector(builder, new byte[64]); + int signerVector = MosaicSupplyChangeTransactionBuffer.createSignerVector(builder, new byte[32]); + int deadlineVector = MosaicSupplyChangeTransactionBuffer.createDeadlineVector(builder, + UInt64Utils.fromBigInteger(deadlineBigInt)); + int feeVector = MosaicSupplyChangeTransactionBuffer.createMaxFeeVector(builder, + UInt64Utils.fromBigInteger(getMaxFee())); + int mosaicIdVector = MosaicSupplyChangeTransactionBuffer.createMosaicIdVector(builder, + UInt64Utils.fromBigInteger(mosaicId.getId())); + int deltaVector = MosaicSupplyChangeTransactionBuffer.createDeltaVector(builder, + UInt64Utils.fromBigInteger(delta)); + + int size = getSerializedSize(); + + MosaicSupplyChangeTransactionBuffer.startMosaicSupplyChangeTransactionBuffer(builder); + MosaicSupplyChangeTransactionBuffer.addSize(builder, size); + MosaicSupplyChangeTransactionBuffer.addSignature(builder, signatureVector); + MosaicSupplyChangeTransactionBuffer.addSigner(builder, signerVector); + MosaicSupplyChangeTransactionBuffer.addVersion(builder, getTxVersionforSerialization()); + MosaicSupplyChangeTransactionBuffer.addType(builder, getType().getValue()); + MosaicSupplyChangeTransactionBuffer.addMaxFee(builder, feeVector); + MosaicSupplyChangeTransactionBuffer.addDeadline(builder, deadlineVector); + + MosaicSupplyChangeTransactionBuffer.addMosaicId(builder, mosaicIdVector); + MosaicSupplyChangeTransactionBuffer.addDirection(builder, mosaicSupplyType.getValue()); + MosaicSupplyChangeTransactionBuffer.addDelta(builder, deltaVector); + + int codedTransaction = MosaicSupplyChangeTransactionBuffer.endMosaicSupplyChangeTransactionBuffer(builder); + builder.finish(codedTransaction); + + // validate size + byte[] output = schema.serialize(builder.sizedByteArray()); + Validate.isTrue(output.length == size, "Serialized transaction has incorrect length: " + this.getClass()); + return output; + } + + public static int calculatePayloadSize() { + // mosaic id, supply type, delta + return 8 + 1 + 8; + } + + @Override + protected int getPayloadSerializedSize() { + return calculatePayloadSize(); + } + + @Override + protected Transaction copyForSigner(PublicAccount signer) { + return new MosaicSupplyChangeTransaction(getNetworkType(), getVersion(), getDeadline(), getMaxFee(), + getSignature(), Optional.of(signer), getTransactionInfo(), getMosaicId(), getMosaicSupplyType(), + getDelta()); + } } diff --git a/src/main/java/io/proximax/sdk/model/transaction/RegisterNamespaceTransaction.java b/src/main/java/io/proximax/sdk/model/transaction/RegisterNamespaceTransaction.java index 5dd1b406..2aa0f89e 100644 --- a/src/main/java/io/proximax/sdk/model/transaction/RegisterNamespaceTransaction.java +++ b/src/main/java/io/proximax/sdk/model/transaction/RegisterNamespaceTransaction.java @@ -31,154 +31,163 @@ import io.proximax.sdk.utils.dto.UInt64Utils; /** - * Accounts can rent a namespace for an amount of blocks and after a this renew the contract. - * This is done via a RegisterNamespaceTransaction. - * - * @since 1.0 + * Accounts can rent a namespace for an amount of blocks and after a this renew the contract. This is done via a + * RegisterNamespaceTransaction. */ public class RegisterNamespaceTransaction extends Transaction { - private final String namespaceName; - private final NamespaceId namespaceId; - private final Optional duration; - private final Optional parentId; - private final NamespaceType namespaceType; - private final Schema schema = new RegisterNamespaceTransactionSchema(); - - public RegisterNamespaceTransaction(NetworkType networkType, Integer version, TransactionDeadline deadline, BigInteger fee, String namespaceName, NamespaceId namespaceId, NamespaceType namespaceType, Optional duration, Optional parentId, String signature, PublicAccount signer, TransactionInfo transactionInfo) { - this(networkType, version, deadline, fee, namespaceName, namespaceId, namespaceType, duration, parentId, Optional.of(signature), Optional.of(signer), Optional.of(transactionInfo)); - } - - public RegisterNamespaceTransaction(NetworkType networkType, Integer version, TransactionDeadline deadline, BigInteger fee, String namespaceName, NamespaceId namespaceId, NamespaceType namespaceType, Optional duration, Optional parentId) { - this(networkType, version, deadline, fee, namespaceName, namespaceId, namespaceType, duration, parentId, Optional.empty(), Optional.empty(), Optional.empty()); - } - - private RegisterNamespaceTransaction(NetworkType networkType, Integer version, TransactionDeadline deadline, BigInteger fee, String namespaceName, NamespaceId namespaceId, NamespaceType namespaceType, Optional duration, Optional parentId, Optional signature, Optional signer, Optional transactionInfo) { - super(TransactionType.REGISTER_NAMESPACE, networkType, version, deadline, fee, signature, signer, transactionInfo); - Validate.notNull(namespaceName, "NamespaceName must not be null"); - Validate.notNull(namespaceType, "NamespaceType must not be null"); - Validate.notNull(namespaceId, "NamespaceId must not be null"); - if (namespaceType == NamespaceType.RootNamespace) { - Validate.notNull(duration, "Duration must not be null"); - } else { - Validate.notNull(parentId, "ParentId must not be null"); - } - this.namespaceName = namespaceName; - this.namespaceType = namespaceType; - this.namespaceId = namespaceId; - this.duration = duration; - this.parentId = parentId; - } - - /** - * Create a root namespace object. - * - * @param deadline The deadline to include the transaction. - * @param namespaceName The namespace name. - * @param duration The duration of the namespace. - * @param networkType The network type. - * @return instance of RegisterNamespaceTransaction - */ - public static RegisterNamespaceTransaction createRootNamespace(TransactionDeadline deadline, String namespaceName, BigInteger duration, NetworkType networkType) { - Validate.notNull(namespaceName, "NamespaceName must not be null"); - return new RegisterNamespaceTransaction(networkType, 2, deadline, BigInteger.valueOf(0), namespaceName, new NamespaceId(IdGenerator.generateNamespaceId(namespaceName)), NamespaceType.RootNamespace, Optional.of(duration), Optional.empty()); - } - - /** - * Create a sub namespace object. - * - * @param deadline - The deadline to include the transaction. - * @param namespaceName - The namespace name. - * @param parentId - The parent id name. - * @param networkType - The network type. - * @return instance of RegisterNamespaceTransaction - */ - public static RegisterNamespaceTransaction createSubNamespace(TransactionDeadline deadline, String namespaceName, NamespaceId parentId, NetworkType networkType) { - Validate.notNull(namespaceName, "NamespaceName must not be null"); - Validate.notNull(parentId, "ParentId must not be null"); - return new RegisterNamespaceTransaction(networkType, 2, deadline, BigInteger.valueOf(0), namespaceName, new NamespaceId(IdGenerator.generateSubNamespaceIdFromParentId(parentId.getId(), namespaceName)), NamespaceType.SubNamespace, Optional.empty(), Optional.of(parentId)); - } - - - /** - * Returns namespace name. - * - * @return namespace name - */ - public String getNamespaceName() { - return namespaceName; - } - - /** - * Returns id of the namespace derived from namespaceName. - * When creating a sub namespace the namespaceId is derived from namespaceName and parentId. - * - * @return namespace id - */ - public NamespaceId getNamespaceId() { - return namespaceId; - } - - /** - * Returns number of blocks a namespace is active. - * - * @return namespace renting duration - */ - public Optional getDuration() { return duration; } - - /** - * The id of the parent sub namespace. - * - * @return sub namespace - */ - public Optional getParentId() { return parentId; } - - /** - * Returns namespace type either RootNamespace or SubNamespace. - * - * @return namespace type - */ - public NamespaceType getNamespaceType() { - return namespaceType; - } - - byte[] generateBytes() { - FlatBufferBuilder builder = new FlatBufferBuilder(); - BigInteger deadlineBigInt = BigInteger.valueOf(getDeadline().getInstant()); - - // Create Vectors - int signatureVector = RegisterNamespaceTransactionBuffer.createSignatureVector(builder, new byte[64]); - int signerVector = RegisterNamespaceTransactionBuffer.createSignerVector(builder, new byte[32]); - int deadlineVector = RegisterNamespaceTransactionBuffer.createDeadlineVector(builder, UInt64Utils.fromBigInteger(deadlineBigInt)); - int feeVector = RegisterNamespaceTransactionBuffer.createMaxFeeVector(builder, UInt64Utils.fromBigInteger(getFee())); - int namespaceIdVector = RegisterNamespaceTransactionBuffer.createNamespaceIdVector(builder, UInt64Utils.fromBigInteger(namespaceId.getId())); - int durationParentIdVector = RegisterNamespaceTransactionBuffer.createDurationParentIdVector(builder, getNamespaceType() == NamespaceType.RootNamespace ? UInt64Utils.fromBigInteger(duration.get()) : UInt64Utils.fromBigInteger(parentId.get().getId())); - int name = builder.createString(namespaceName); - - // header, ns type, duration, ns id, name size, name - int size = HEADER_SIZE + 1 + 8 + 8 + 1 + namespaceName.length(); - - - RegisterNamespaceTransactionBuffer.startRegisterNamespaceTransactionBuffer(builder); - RegisterNamespaceTransactionBuffer.addSize(builder, size); - RegisterNamespaceTransactionBuffer.addSignature(builder, signatureVector); - RegisterNamespaceTransactionBuffer.addSigner(builder, signerVector); - RegisterNamespaceTransactionBuffer.addVersion(builder, getTxVersionforSerialization()); - RegisterNamespaceTransactionBuffer.addType(builder, getType().getValue()); - RegisterNamespaceTransactionBuffer.addMaxFee(builder, feeVector); - RegisterNamespaceTransactionBuffer.addDeadline(builder, deadlineVector); - - RegisterNamespaceTransactionBuffer.addNamespaceType(builder, getNamespaceType().getValue()); - RegisterNamespaceTransactionBuffer.addDurationParentId(builder, durationParentIdVector); - RegisterNamespaceTransactionBuffer.addNamespaceId(builder, namespaceIdVector); - RegisterNamespaceTransactionBuffer.addNamespaceNameSize(builder, namespaceName.length()); - RegisterNamespaceTransactionBuffer.addNamespaceName(builder, name); - - int codedTransaction = RegisterNamespaceTransactionBuffer.endRegisterNamespaceTransactionBuffer(builder); - builder.finish(codedTransaction); - - // validate size - byte[] output = schema.serialize(builder.sizedByteArray()); - Validate.isTrue(output.length == size, "Serialized transaction has incorrect length: " + this.getClass()); - return output; - } + private final Schema schema = new RegisterNamespaceTransactionSchema(); + + private final String namespaceName; + private final NamespaceId namespaceId; + private final Optional duration; + private final Optional parentId; + private final NamespaceType namespaceType; + + + /** + * @param networkType + * @param version + * @param deadline + * @param maxFee + * @param signature + * @param signer + * @param transactionInfo + * @param namespaceName + * @param namespaceId + * @param duration + * @param parentId + * @param namespaceType + */ + public RegisterNamespaceTransaction(NetworkType networkType, Integer version, + TransactionDeadline deadline, BigInteger maxFee, Optional signature, Optional signer, + Optional transactionInfo, String namespaceName, NamespaceId namespaceId, + Optional duration, Optional parentId, NamespaceType namespaceType) { + super(TransactionType.REGISTER_NAMESPACE, networkType, version, deadline, maxFee, signature, signer, transactionInfo); + // validations + Validate.notNull(namespaceName, "NamespaceName must not be null"); + Validate.notNull(namespaceType, "NamespaceType must not be null"); + Validate.notNull(namespaceId, "NamespaceId must not be null"); + if (namespaceType == NamespaceType.RootNamespace) { + Validate.notNull(duration, "Duration must not be null"); + } else { + Validate.notNull(parentId, "ParentId must not be null"); + } + // assignments + this.namespaceName = namespaceName; + this.namespaceId = namespaceId; + this.duration = duration; + this.parentId = parentId; + this.namespaceType = namespaceType; + } + + /** + * Returns namespace name. + * + * @return namespace name + */ + public String getNamespaceName() { + return namespaceName; + } + + /** + * Returns id of the namespace derived from namespaceName. When creating a sub namespace the namespaceId is derived + * from namespaceName and parentId. + * + * @return namespace id + */ + public NamespaceId getNamespaceId() { + return namespaceId; + } + + /** + * Returns number of blocks a namespace is active. + * + * @return namespace renting duration + */ + public Optional getDuration() { + return duration; + } + + /** + * The id of the parent sub namespace. + * + * @return sub namespace + */ + public Optional getParentId() { + return parentId; + } + + /** + * Returns namespace type either RootNamespace or SubNamespace. + * + * @return namespace type + */ + public NamespaceType getNamespaceType() { + return namespaceType; + } + + protected byte[] generateBytes() { + FlatBufferBuilder builder = new FlatBufferBuilder(); + BigInteger deadlineBigInt = BigInteger.valueOf(getDeadline().getInstant()); + + // Create Vectors + int signatureVector = RegisterNamespaceTransactionBuffer.createSignatureVector(builder, new byte[64]); + int signerVector = RegisterNamespaceTransactionBuffer.createSignerVector(builder, new byte[32]); + int deadlineVector = RegisterNamespaceTransactionBuffer.createDeadlineVector(builder, + UInt64Utils.fromBigInteger(deadlineBigInt)); + int feeVector = RegisterNamespaceTransactionBuffer.createMaxFeeVector(builder, + UInt64Utils.fromBigInteger(getMaxFee())); + int namespaceIdVector = RegisterNamespaceTransactionBuffer.createNamespaceIdVector(builder, + UInt64Utils.fromBigInteger(namespaceId.getId())); + int durationParentIdVector = RegisterNamespaceTransactionBuffer.createDurationParentIdVector(builder, + getNamespaceType() == NamespaceType.RootNamespace ? UInt64Utils.fromBigInteger(duration.get()) + : UInt64Utils.fromBigInteger(parentId.get().getId())); + int name = builder.createString(namespaceName); + + int size = getSerializedSize(); + + RegisterNamespaceTransactionBuffer.startRegisterNamespaceTransactionBuffer(builder); + RegisterNamespaceTransactionBuffer.addSize(builder, size); + RegisterNamespaceTransactionBuffer.addSignature(builder, signatureVector); + RegisterNamespaceTransactionBuffer.addSigner(builder, signerVector); + RegisterNamespaceTransactionBuffer.addVersion(builder, getTxVersionforSerialization()); + RegisterNamespaceTransactionBuffer.addType(builder, getType().getValue()); + RegisterNamespaceTransactionBuffer.addMaxFee(builder, feeVector); + RegisterNamespaceTransactionBuffer.addDeadline(builder, deadlineVector); + + RegisterNamespaceTransactionBuffer.addNamespaceType(builder, getNamespaceType().getValue()); + RegisterNamespaceTransactionBuffer.addDurationParentId(builder, durationParentIdVector); + RegisterNamespaceTransactionBuffer.addNamespaceId(builder, namespaceIdVector); + RegisterNamespaceTransactionBuffer.addNamespaceNameSize(builder, namespaceName.length()); + RegisterNamespaceTransactionBuffer.addNamespaceName(builder, name); + + int codedTransaction = RegisterNamespaceTransactionBuffer.endRegisterNamespaceTransactionBuffer(builder); + builder.finish(codedTransaction); + + // validate size + byte[] output = schema.serialize(builder.sizedByteArray()); + Validate.isTrue(output.length == size, "Serialized transaction has incorrect length: " + this.getClass()); + return output; + } + + /** + * calculate payload size excluding header + * + * @param namespaceNameLength length of the namespace name + * @return the size + */ + public static int calculatePayloadSize(int namespaceNameLength) { + // ns type, duration, ns id, name size, name + return 1 + 8 + 8 + 1 + namespaceNameLength; + } + + @Override + protected int getPayloadSerializedSize() { + return calculatePayloadSize(getNamespaceName().length()); + } + + @Override + protected Transaction copyForSigner(PublicAccount signer) { + return new RegisterNamespaceTransaction(getNetworkType(), getVersion(), getDeadline(), getMaxFee(), getSignature(), Optional.of(signer), getTransactionInfo(), getNamespaceName(), getNamespaceId(), getDuration(), getParentId(), getNamespaceType()); + } } diff --git a/src/main/java/io/proximax/sdk/model/transaction/SecretLockTransaction.java b/src/main/java/io/proximax/sdk/model/transaction/SecretLockTransaction.java index 9903add1..977fc0a4 100644 --- a/src/main/java/io/proximax/sdk/model/transaction/SecretLockTransaction.java +++ b/src/main/java/io/proximax/sdk/model/transaction/SecretLockTransaction.java @@ -33,132 +33,157 @@ import io.proximax.sdk.utils.dto.UInt64Utils; public class SecretLockTransaction extends Transaction { - private final Mosaic mosaic; - private final BigInteger duration; - private final HashType hashType; - private final String secret; - private final Address recipient; - private final Schema schema = new SecretLockTransactionSchema(); - - public SecretLockTransaction(NetworkType networkType, Integer version, TransactionDeadline deadline, BigInteger fee, Mosaic mosaic, BigInteger duration, HashType hashType, String secret, Address recipient, String signature, PublicAccount signer, TransactionInfo transactionInfo) { - this(networkType, version, deadline, fee, mosaic, duration, hashType, secret, recipient, Optional.of(signature), Optional.of(signer), Optional.of(transactionInfo)); - } - - public SecretLockTransaction(NetworkType networkType, Integer version, TransactionDeadline deadline, BigInteger fee, Mosaic mosaic, BigInteger duration, HashType hashType, String secret, Address recipient) { - this(networkType, version, deadline, fee, mosaic, duration, hashType, secret, recipient, Optional.empty(), Optional.empty(), Optional.empty()); - } - - public SecretLockTransaction(NetworkType networkType, Integer version, TransactionDeadline deadline, BigInteger fee, Mosaic mosaic, BigInteger duration, HashType hashType, String secret, Address recipient, Optional signature, Optional signer, Optional transactionInfo) { - super(TransactionType.SECRET_LOCK, networkType, version, deadline, fee, signature, signer, transactionInfo); - Validate.notNull(mosaic, "Mosaic must not be null"); - Validate.notNull(duration, "Duration must not be null"); - Validate.notNull(secret, "Secret must not be null"); - Validate.notNull(recipient, "Recipient must not be null"); - if (!hashType.validate(secret)) { - throw new IllegalArgumentException("HashType and Secret have incompatible length or not hexadecimal string"); - } - this.mosaic = mosaic; - this.duration = duration; - this.hashType = hashType; - this.secret = secret; - this.recipient = recipient; - } - - /** - * Create a secret lock transaction object. - * - * @param deadline The deadline to include the transaction. - * @param mosaic The locked mosaic. - * @param duration The duration for the funds to be released or returned. - * @param hashType The hash algorithm secret is generated with. - * @param secret The proof hashed. - * @param recipient The recipient of the funds. - * @param networkType The network type. - * - * @return a SecretLockTransaction instance - */ - public static SecretLockTransaction create(TransactionDeadline deadline, Mosaic mosaic, BigInteger duration, HashType hashType, String secret, Address recipient, NetworkType networkType) { - return new SecretLockTransaction(networkType, 1, deadline, BigInteger.valueOf(0), mosaic, duration, hashType, secret, recipient); - } - - /** - * Returns locked mosaic. - * - * @return locked mosaic. - */ - public Mosaic getMosaic() { return mosaic; } - - /** - * Returns duration for the funds to be released or returned. - * - * @return duration for the funds to be released or returned. - */ - public BigInteger getDuration() { return duration; } - - /** - * Returns the hash algorithm, secret is generated with. - * - * @return the hash algorithm, secret is generated with. - */ - public HashType getHashType() { return hashType; } - - /** - * Returns the proof hashed. - * - * @return the proof hashed. - */ - public String getSecret() { return secret; } - - /** - * Returns the recipient of the funds. - * - * @return the recipient of the funds. - */ - public Address getRecipient() { return recipient; } - - @Override - byte[] generateBytes() { - FlatBufferBuilder builder = new FlatBufferBuilder(); - BigInteger deadlineBigInt = BigInteger.valueOf(getDeadline().getInstant()); - - // Create Vectors - int signatureVector = SecretLockTransactionBuffer.createSignatureVector(builder, new byte[64]); - int signerVector = SecretLockTransactionBuffer.createSignerVector(builder, new byte[32]); - int deadlineVector = SecretLockTransactionBuffer.createDeadlineVector(builder, UInt64Utils.fromBigInteger(deadlineBigInt)); - int feeVector = SecretLockTransactionBuffer.createMaxFeeVector(builder, UInt64Utils.fromBigInteger(getFee())); - int mosaicIdVector = SecretLockTransactionBuffer.createMosaicIdVector(builder, UInt64Utils.fromBigInteger(mosaic.getId().getId())); - int mosaicAmountVector = SecretLockTransactionBuffer.createMosaicAmountVector(builder, UInt64Utils.fromBigInteger(mosaic.getAmount())); - int durationVector = SecretLockTransactionBuffer.createDurationVector(builder, UInt64Utils.fromBigInteger(duration)); - int secretVector = SecretLockTransactionBuffer.createSecretVector(builder, Hex.decode(secret)); - - byte[] address = Base32Encoder.getBytes(getRecipient().plain()); - int recipientVector = SecretLockTransactionBuffer.createRecipientVector(builder, address); - - // header + mosaicID, amount, duration, hash algo, secret, recipient - int size = HEADER_SIZE + 8 + 8 + 8 + 1 + 32 + 25; - - SecretLockTransactionBuffer.startSecretLockTransactionBuffer(builder); - SecretLockTransactionBuffer.addSize(builder, size); - SecretLockTransactionBuffer.addSignature(builder, signatureVector); - SecretLockTransactionBuffer.addSigner(builder, signerVector); - SecretLockTransactionBuffer.addVersion(builder, getTxVersionforSerialization()); - SecretLockTransactionBuffer.addType(builder, getType().getValue()); - SecretLockTransactionBuffer.addMaxFee(builder, feeVector); - SecretLockTransactionBuffer.addDeadline(builder, deadlineVector); - - SecretLockTransactionBuffer.addMosaicId(builder, mosaicIdVector); - SecretLockTransactionBuffer.addMosaicAmount(builder, mosaicAmountVector); - SecretLockTransactionBuffer.addDuration(builder, durationVector); - SecretLockTransactionBuffer.addHashAlgorithm(builder, hashType.getValue()); - SecretLockTransactionBuffer.addSecret(builder, secretVector); - SecretLockTransactionBuffer.addRecipient(builder, recipientVector); - - int codedSecretLock = SecretLockTransactionBuffer.endSecretLockTransactionBuffer(builder); - builder.finish(codedSecretLock); - - // validate size - byte[] output = schema.serialize(builder.sizedByteArray()); - Validate.isTrue(output.length == size, "Serialized transaction has incorrect length: " + this.getClass()); - return output; - } + private final Schema schema = new SecretLockTransactionSchema(); + + private final Mosaic mosaic; + private final BigInteger duration; + private final HashType hashType; + private final String secret; + private final Address recipient; + + /** + * @param networkType network type + * @param version transaction version. Use {@link TransactionVersion#MODIFY_MULTISIG_ACCOUNT} for current version + * @param deadline transaction deadline + * @param maxFee transaction fee + * @param signature optional signature + * @param signer optional signer + * @param transactionInfo optional transaction info + * @param mosaic mosaic amount to lock + * @param duration duration of the lock in block count + * @param hashType type of the hashing function + * @param secret secret + * @param recipient recipient of the locked funds + */ + public SecretLockTransaction(NetworkType networkType, Integer version, TransactionDeadline deadline, + BigInteger maxFee, Optional signature, Optional signer, + Optional transactionInfo, Mosaic mosaic, BigInteger duration, HashType hashType, + String secret, Address recipient) { + super(TransactionType.SECRET_LOCK, networkType, version, deadline, maxFee, signature, signer, transactionInfo); + // validations + Validate.notNull(mosaic, "Mosaic must not be null"); + Validate.notNull(duration, "Duration must not be null"); + Validate.notNull(secret, "Secret must not be null"); + Validate.notNull(recipient, "Recipient must not be null"); + if (!hashType.validate(secret)) { + throw new IllegalArgumentException("HashType and Secret have incompatible length or not hexadecimal string"); + } + // assignments + this.mosaic = mosaic; + this.duration = duration; + this.hashType = hashType; + this.secret = secret; + this.recipient = recipient; + } + + /** + * Returns locked mosaic. + * + * @return locked mosaic. + */ + public Mosaic getMosaic() { + return mosaic; + } + + /** + * Returns duration for the funds to be released or returned. + * + * @return duration for the funds to be released or returned. + */ + public BigInteger getDuration() { + return duration; + } + + /** + * Returns the hash algorithm, secret is generated with. + * + * @return the hash algorithm, secret is generated with. + */ + public HashType getHashType() { + return hashType; + } + + /** + * Returns the proof hashed. + * + * @return the proof hashed. + */ + public String getSecret() { + return secret; + } + + /** + * Returns the recipient of the funds. + * + * @return the recipient of the funds. + */ + public Address getRecipient() { + return recipient; + } + + @Override + protected byte[] generateBytes() { + FlatBufferBuilder builder = new FlatBufferBuilder(); + BigInteger deadlineBigInt = BigInteger.valueOf(getDeadline().getInstant()); + + // Create Vectors + int signatureVector = SecretLockTransactionBuffer.createSignatureVector(builder, new byte[64]); + int signerVector = SecretLockTransactionBuffer.createSignerVector(builder, new byte[32]); + int deadlineVector = SecretLockTransactionBuffer.createDeadlineVector(builder, + UInt64Utils.fromBigInteger(deadlineBigInt)); + int feeVector = SecretLockTransactionBuffer.createMaxFeeVector(builder, UInt64Utils.fromBigInteger(getMaxFee())); + int mosaicIdVector = SecretLockTransactionBuffer.createMosaicIdVector(builder, + UInt64Utils.fromBigInteger(mosaic.getId().getId())); + int mosaicAmountVector = SecretLockTransactionBuffer.createMosaicAmountVector(builder, + UInt64Utils.fromBigInteger(mosaic.getAmount())); + int durationVector = SecretLockTransactionBuffer.createDurationVector(builder, + UInt64Utils.fromBigInteger(duration)); + int secretVector = SecretLockTransactionBuffer.createSecretVector(builder, Hex.decode(secret)); + + byte[] address = Base32Encoder.getBytes(getRecipient().plain()); + int recipientVector = SecretLockTransactionBuffer.createRecipientVector(builder, address); + + int size = getSerializedSize(); + + SecretLockTransactionBuffer.startSecretLockTransactionBuffer(builder); + SecretLockTransactionBuffer.addSize(builder, size); + SecretLockTransactionBuffer.addSignature(builder, signatureVector); + SecretLockTransactionBuffer.addSigner(builder, signerVector); + SecretLockTransactionBuffer.addVersion(builder, getTxVersionforSerialization()); + SecretLockTransactionBuffer.addType(builder, getType().getValue()); + SecretLockTransactionBuffer.addMaxFee(builder, feeVector); + SecretLockTransactionBuffer.addDeadline(builder, deadlineVector); + + SecretLockTransactionBuffer.addMosaicId(builder, mosaicIdVector); + SecretLockTransactionBuffer.addMosaicAmount(builder, mosaicAmountVector); + SecretLockTransactionBuffer.addDuration(builder, durationVector); + SecretLockTransactionBuffer.addHashAlgorithm(builder, hashType.getValue()); + SecretLockTransactionBuffer.addSecret(builder, secretVector); + SecretLockTransactionBuffer.addRecipient(builder, recipientVector); + + int codedSecretLock = SecretLockTransactionBuffer.endSecretLockTransactionBuffer(builder); + builder.finish(codedSecretLock); + + // validate size + byte[] output = schema.serialize(builder.sizedByteArray()); + Validate.isTrue(output.length == size, "Serialized transaction has incorrect length: " + this.getClass()); + return output; + } + + public static int calculatePayloadSize() { + // mosaicID, amount, duration, hash algo, secret, recipient + return 8 + 8 + 8 + 1 + 32 + 25; + } + + @Override + protected int getPayloadSerializedSize() { + return calculatePayloadSize(); + } + + @Override + protected Transaction copyForSigner(PublicAccount signer) { + return new SecretLockTransaction(getNetworkType(), getVersion(), getDeadline(), getMaxFee(), getSignature(), + Optional.of(signer), getTransactionInfo(), getMosaic(), getDuration(), getHashType(), getSecret(), + getRecipient()); + } } diff --git a/src/main/java/io/proximax/sdk/model/transaction/SecretProofTransaction.java b/src/main/java/io/proximax/sdk/model/transaction/SecretProofTransaction.java index 72f4e668..5d67ead8 100644 --- a/src/main/java/io/proximax/sdk/model/transaction/SecretProofTransaction.java +++ b/src/main/java/io/proximax/sdk/model/transaction/SecretProofTransaction.java @@ -30,72 +30,73 @@ import io.proximax.sdk.utils.dto.UInt64Utils; public class SecretProofTransaction extends Transaction { - private final HashType hashType; - private final String secret; - private final String proof; - private final Recipient recipient; - private final Schema schema = new SecretProofTransactionSchema(); - - public SecretProofTransaction(NetworkType networkType, Integer version, TransactionDeadline deadline, BigInteger fee, HashType hashType, Recipient recipient, String secret, String proof, String signature, PublicAccount signer, TransactionInfo transactionInfo) { - this(networkType, version, deadline, fee, hashType, recipient, secret, proof, Optional.of(signature), Optional.of(signer), Optional.of(transactionInfo)); - } - - public SecretProofTransaction(NetworkType networkType, Integer version, TransactionDeadline deadline, BigInteger fee, HashType hashType, Recipient recipient, String secret, String proof) { - this(networkType, version, deadline, fee, hashType, recipient, secret, proof, Optional.empty(), Optional.empty(), Optional.empty()); - } - - public SecretProofTransaction(NetworkType networkType, Integer version, TransactionDeadline deadline, BigInteger fee, HashType hashType, Recipient recipient, String secret, String proof, Optional signature, Optional signer, Optional transactionInfo) { - super(TransactionType.SECRET_PROOF, networkType, version, deadline, fee, signature, signer, transactionInfo); - Validate.notNull(secret, "Secret must not be null"); - Validate.notNull(proof, "Proof must not be null"); - Validate.notNull(recipient, "Recipient must not be null"); - if (!hashType.validate(secret)) { - throw new IllegalArgumentException("HashType and Secret have incompatible length or not hexadecimal string"); - } - this.hashType = hashType; - this.secret = secret; - this.recipient = recipient; - this.proof = proof; - } - - /** - * Create a secret proof transaction object. - * - * @param deadline The deadline to include the transaction. - * @param hashType The hash algorithm secret is generated with. - * @param recipient The recipient of the locked mosaic - * @param secret The seed proof hashed. - * @param proof The seed proof. - * @param networkType The network type. - * - * @return a SecretLockTransaction instance - */ - public static SecretProofTransaction create(TransactionDeadline deadline, HashType hashType, Recipient recipient, String secret, String proof, NetworkType networkType) { - return new SecretProofTransaction(networkType, 1, deadline, BigInteger.valueOf(0), hashType, recipient, secret, proof); - } - - /** - * Returns the hash algorithm secret is generated with. - * - * @return the hash algorithm secret is generated with. - */ - public HashType getHashType() { return hashType; } - - /** - * Returns the proof hashed. - * - * @return the proof hashed. - */ - public String getSecret() { return secret; } - - /** - * Returns proof. - * - * @return proof. - */ - public String getProof() { return proof; } - - /** + private final Schema schema = new SecretProofTransactionSchema(); + + private final HashType hashType; + private final String secret; + private final String proof; + private final Recipient recipient; + + /** + * @param networkType network type + * @param version transaction version. Use {@link TransactionVersion#SECRET_PROOF} for current version + * @param deadline transaction deadline + * @param maxFee transaction fee + * @param signature optional signature + * @param signer optional signer + * @param transactionInfo optional transaction info + * @param hashType hashing function used + * @param secret hash of the secret value + * @param proof the secret value + * @param recipient recipient of the transfer + */ + public SecretProofTransaction(NetworkType networkType, Integer version, TransactionDeadline deadline, + BigInteger maxFee, Optional signature, Optional signer, + Optional transactionInfo, HashType hashType, String secret, String proof, + Recipient recipient) { + super(TransactionType.SECRET_PROOF, networkType, version, deadline, maxFee, signature, signer, transactionInfo); + // validations + Validate.notNull(secret, "Secret must not be null"); + Validate.notNull(proof, "Proof must not be null"); + Validate.notNull(recipient, "Recipient must not be null"); + if (!hashType.validate(secret)) { + throw new IllegalArgumentException("HashType and Secret have incompatible length or not hexadecimal string"); + } + // assignments + this.hashType = hashType; + this.secret = secret; + this.proof = proof; + this.recipient = recipient; + } + + /** + * Returns the hash algorithm secret is generated with. + * + * @return the hash algorithm secret is generated with. + */ + public HashType getHashType() { + return hashType; + } + + /** + * Returns the proof hashed. + * + * @return the proof hashed. + */ + public String getSecret() { + return secret; + } + + /** + * Returns proof. + * + * @return proof. + */ + public String getProof() { + return proof; + } + + /** * @return the recipient */ public Recipient getRecipient() { @@ -103,47 +104,68 @@ public Recipient getRecipient() { } @Override - byte[] generateBytes() { - FlatBufferBuilder builder = new FlatBufferBuilder(); - BigInteger deadlineBigInt = BigInteger.valueOf(getDeadline().getInstant()); - - byte[] recipientBytes = recipient.getBytes(); - byte[] proofBytes = Hex.decode(proof); - // Create Vectors - int signatureVector = SecretProofTransactionBuffer.createSignatureVector(builder, new byte[64]); - int signerVector = SecretProofTransactionBuffer.createSignerVector(builder, new byte[32]); - int deadlineVector = SecretProofTransactionBuffer.createDeadlineVector(builder, UInt64Utils.fromBigInteger(deadlineBigInt)); - int feeVector = SecretProofTransactionBuffer.createMaxFeeVector(builder, UInt64Utils.fromBigInteger(getFee())); - int secretVector = SecretProofTransactionBuffer.createSecretVector(builder, Hex.decode(secret)); - int recipientVector = SecretProofTransactionBuffer.createRecipientVector(builder, recipientBytes); - int proofVector = SecretProofTransactionBuffer.createProofVector(builder, proofBytes); - - int size = HEADER_SIZE + - 35 + - // recipient - recipientBytes.length + - // proof length - proofBytes.length; - SecretProofTransactionBuffer.startSecretProofTransactionBuffer(builder); - SecretProofTransactionBuffer.addSize(builder, size); - SecretProofTransactionBuffer.addSignature(builder, signatureVector); - SecretProofTransactionBuffer.addSigner(builder, signerVector); - SecretProofTransactionBuffer.addVersion(builder, getTxVersionforSerialization()); - SecretProofTransactionBuffer.addType(builder, getType().getValue()); - SecretProofTransactionBuffer.addMaxFee(builder, feeVector); - SecretProofTransactionBuffer.addDeadline(builder, deadlineVector); - SecretProofTransactionBuffer.addHashAlgorithm(builder, hashType.getValue()); - SecretProofTransactionBuffer.addSecret(builder, secretVector); - SecretProofTransactionBuffer.addRecipient(builder, recipientVector); - SecretProofTransactionBuffer.addProofSize(builder, proofBytes.length); - SecretProofTransactionBuffer.addProof(builder, proofVector); - - int codedSecretProof = SecretProofTransactionBuffer.endSecretProofTransactionBuffer(builder); - builder.finish(codedSecretProof); - - // validate size - byte[] output = schema.serialize(builder.sizedByteArray()); - Validate.isTrue(output.length == size, "Serialized transaction has incorrect length: " + this.getClass()); - return output; - } + protected byte[] generateBytes() { + FlatBufferBuilder builder = new FlatBufferBuilder(); + BigInteger deadlineBigInt = BigInteger.valueOf(getDeadline().getInstant()); + + byte[] recipientBytes = recipient.getBytes(); + byte[] proofBytes = Hex.decode(proof); + // Create Vectors + int signatureVector = SecretProofTransactionBuffer.createSignatureVector(builder, new byte[64]); + int signerVector = SecretProofTransactionBuffer.createSignerVector(builder, new byte[32]); + int deadlineVector = SecretProofTransactionBuffer.createDeadlineVector(builder, + UInt64Utils.fromBigInteger(deadlineBigInt)); + int feeVector = SecretProofTransactionBuffer.createMaxFeeVector(builder, UInt64Utils.fromBigInteger(getMaxFee())); + int secretVector = SecretProofTransactionBuffer.createSecretVector(builder, Hex.decode(secret)); + int recipientVector = SecretProofTransactionBuffer.createRecipientVector(builder, recipientBytes); + int proofVector = SecretProofTransactionBuffer.createProofVector(builder, proofBytes); + + int size = getSerializedSize(); + + SecretProofTransactionBuffer.startSecretProofTransactionBuffer(builder); + SecretProofTransactionBuffer.addSize(builder, size); + SecretProofTransactionBuffer.addSignature(builder, signatureVector); + SecretProofTransactionBuffer.addSigner(builder, signerVector); + SecretProofTransactionBuffer.addVersion(builder, getTxVersionforSerialization()); + SecretProofTransactionBuffer.addType(builder, getType().getValue()); + SecretProofTransactionBuffer.addMaxFee(builder, feeVector); + SecretProofTransactionBuffer.addDeadline(builder, deadlineVector); + + SecretProofTransactionBuffer.addHashAlgorithm(builder, hashType.getValue()); + SecretProofTransactionBuffer.addSecret(builder, secretVector); + SecretProofTransactionBuffer.addRecipient(builder, recipientVector); + SecretProofTransactionBuffer.addProofSize(builder, proofBytes.length); + SecretProofTransactionBuffer.addProof(builder, proofVector); + + int codedSecretProof = SecretProofTransactionBuffer.endSecretProofTransactionBuffer(builder); + builder.finish(codedSecretProof); + + // validate size + byte[] output = schema.serialize(builder.sizedByteArray()); + Validate.isTrue(output.length == size, "Serialized transaction has incorrect length: " + this.getClass()); + return output; + } + + /** + * calculate payload size excluding the header + * + * @param recipient lock recipient + * @param proof proof + * @return the size + */ + public static int calculatePayloadSize(Recipient recipient, String proof) { + // 1 hash type + 32 secret + 2 proof size + recipient + proof + return 35 + recipient.getBytes().length + Hex.decode(proof).length; + } + + @Override + protected int getPayloadSerializedSize() { + return calculatePayloadSize(getRecipient(), getProof()); + } + + @Override + protected Transaction copyForSigner(PublicAccount signer) { + return new SecretProofTransaction(getNetworkType(), getVersion(), getDeadline(), getMaxFee(), getSignature(), + Optional.of(signer), getTransactionInfo(), getHashType(), getSecret(), getProof(), getRecipient()); + } } diff --git a/src/main/java/io/proximax/sdk/model/transaction/Transaction.java b/src/main/java/io/proximax/sdk/model/transaction/Transaction.java index 82c1cd20..b77e6b62 100644 --- a/src/main/java/io/proximax/sdk/model/transaction/Transaction.java +++ b/src/main/java/io/proximax/sdk/model/transaction/Transaction.java @@ -37,275 +37,308 @@ * @since 1.0 */ public abstract class Transaction { - /** standard transaction header size */ - public static final int HEADER_SIZE = 122; - - private final TransactionType type; - private final NetworkType networkType; - private final Integer version; - private final TransactionDeadline deadline; - private final BigInteger fee; - private final Optional signature; - private Optional signer; - private final Optional transactionInfo; - - /** - * Constructor - * - * @param type Transaction type. - * @param networkType Network type. - * @param version Transaction version. - * @param deadline Transaction deadline. - * @param fee Transaction fee. - * @param signature Transaction signature. - * @param signer Transaction signer. - * @param transactionInfo Transaction meta data info. - */ - public Transaction(TransactionType type, NetworkType networkType, Integer version, TransactionDeadline deadline, BigInteger fee, Optional signature, Optional signer, Optional transactionInfo) { - Validate.notNull(type, "Type must not be null"); - Validate.notNull(networkType, "NetworkType must not be null"); - Validate.notNull(version, "Version must not be null"); - Validate.notNull(deadline, "Deadline must not be null"); - Validate.notNull(fee, "Fee must not be null"); - this.type = type; - this.networkType = networkType; - this.version = version; - this.deadline = deadline; - this.fee = fee; - - this.signature = signature; - this.signer = signer; - this.transactionInfo = transactionInfo; - } - - /** - * Generates hash for a serialized transaction payload. - * - * @param payloadBytes Transaction payload as byte array - * @param generationHashBytes the network generation hash - * @return generated transaction hash. - */ - public static String createTransactionHash(byte[] payloadBytes, byte[] generationHashBytes) { - // expected size is payload - 4 bytes - byte[] signingBytes = new byte[payloadBytes.length - 4]; - // 32 bytes = skip 4 bytes and take half of the signature - System.arraycopy(payloadBytes, 4, signingBytes, 0, 32); - // 32 bytes = skip second half of signature and take signer - System.arraycopy(payloadBytes, 68, signingBytes, 32, 32); - // 32 bytes = generation hash - System.arraycopy(generationHashBytes, 0, signingBytes, 64, 32); - // remainder - System.arraycopy(payloadBytes, 100, signingBytes, 96, payloadBytes.length - 100); - - // hash and encode as upper-case hexadecimal string - byte[] result = Hashes.sha3_256(signingBytes); - return Hex.toHexString(result).toUpperCase(); - } - - /** - * Returns the transaction type. - * - * @return transaction type - */ - public TransactionType getType() { - return type; - } - - /** - * Returns the network type. - * - * @return the network type - */ - public NetworkType getNetworkType() { - return networkType; - } - - /** - * Returns the transaction version. - * - * @return transaction version - */ - public Integer getVersion() { - return version; - } - - /** - * Returns the deadline to include the transaction. - * - * @return deadline to include transaction into a block. - */ - public TransactionDeadline getDeadline() { - return deadline; - } - - /** - * Returns the fee for the transaction. The higher the fee, the higher the priority of the transaction. - * Transactions with high priority get included in a block before transactions with lower priority. - * - * @return fee amount - */ - public BigInteger getFee() { - return fee; - } - - /** - * Returns the transaction signature (missing if part of an aggregate transaction). - * - * @return transaction signature - */ - public Optional getSignature() { return signature; } - - /** - * Returns the transaction creator public account. - * - * @return signer public account - */ - public Optional getSigner() { return signer; } - - /** - * Returns meta data object contains additional information about the transaction. - * - * @return transaction meta data info. - */ - public Optional getTransactionInfo() { return transactionInfo; } - - /** - * generate byte array with serialized form of transaction - * - * @return byte array - */ - abstract byte[] generateBytes(); - - /** - * Serialize and sign transaction creating a new SignedTransaction. - * - * @param account The account to sign the transaction. - * @param generationHash network generation hash retrieved from block 1 - * @return {@link SignedTransaction} - */ - public SignedTransaction signWith(Account account, String generationHash) { - // 32 bytes of the generation hash - byte[] generationHashBytes = Hex.decode(generationHash); - byte[] bytes = this.generateBytes(); - // ignore first 4 + 64 + 32 bytes from the serialized form and concat with 32 bytes of generation hash - byte[] signingBytes = new byte[bytes.length - 100 + 32]; - System.arraycopy(generationHashBytes, 0, signingBytes, 0, 32); - System.arraycopy(bytes, 100, signingBytes, 32, bytes.length - 100); - - // sign the byte array with generation hash and serialized transaction - Signature transSignature = new Signer(account.getKeyPair()).sign(signingBytes); - - // create payload - byte[] payload = new byte[bytes.length]; - // 4 bytes = size - System.arraycopy(bytes, 0, payload, 0, 4); - // 64 bytes = signature - byte[] transSignatureBytes = transSignature.getBytes(); - System.arraycopy(transSignatureBytes, 0, payload, 4, transSignatureBytes.length); - // 32 bytes = signer - byte[] rawSignerPublicKey = account.getKeyPair().getPublicKey().getRaw(); - System.arraycopy(rawSignerPublicKey, 0, payload, 64 + 4, rawSignerPublicKey.length); - // append remainder of the transaction bytes - System.arraycopy(bytes, 100, payload, 100, bytes.length - 100); - - // compute transaction hash - String hash = Transaction.createTransactionHash(payload, generationHashBytes); - - // return signed transaction - return new SignedTransaction(Hex.toHexString(payload).toUpperCase(), hash, type); - } - - /** - * Takes a transaction and formats bytes to be included in an aggregate transaction. - * - * @return transaction with signer serialized to be part of an aggregate transaction - */ - byte[] toAggregateTransactionBytes() { - // decode signer from hex to byte array - byte[] signerBytes = Hex.decode(this.signer.orElseThrow(() -> new IllegalStateException("missing signer")).getPublicKey()); - // serialize the transaction - byte[] bytes = this.generateBytes(); - // we will be removing header (122) and adding size (4), signer (32), version (4), trans type(2) - byte[] resultBytes = new byte[bytes.length - 122 + 4 + 32 + 4 + 2]; - - // prepare size of this as embedded transaction - byte[] sizeBytes = BigInteger.valueOf(resultBytes.length).toByteArray(); - ArrayUtils.reverse(sizeBytes); - - // write size of the aggregate transaction bytes - can be less than 4 bytes - System.arraycopy(sizeBytes, 0, resultBytes, 0, sizeBytes.length); - // at position 4 start writing 32 bytes of signer - System.arraycopy(signerBytes, 0, resultBytes, 4, 32); - // version is expected to start at position 100 and be 4 bytes, then take next 2 bytes - System.arraycopy(bytes, 100, resultBytes, 4 + 32, 6); - // copy remaining data after header - System.arraycopy(bytes, 122, resultBytes, 4 + 32 + 6, bytes.length - 122); - - return resultBytes; - } - - /** - * Convert an aggregate transaction to an inner transaction including transaction signer. - * - * @param signer Transaction signer. - * @return instance of Transaction with signer - */ - public Transaction toAggregate(PublicAccount signer) { - this.signer = Optional.of(signer); - return this; - } - - /** - * Returns if a transaction is pending to be included in a block. - * - * @return if a transaction is pending to be included in a block - */ - public boolean isUnconfirmed() { - return this.transactionInfo.isPresent() && this.transactionInfo.get().getHeight().equals(BigInteger.valueOf(0)) && this.transactionInfo.get().getHash().equals(this.transactionInfo.get().getMerkleComponentHash()); - } - - /** - * Return if a transaction is included in a block. - * - * @return if a transaction is included in a block - */ - public boolean isConfirmed() { - return this.transactionInfo.isPresent() && this.transactionInfo.get().getHeight().intValue() > 0; - } - - /** - * Returns if a transaction has missing signatures. - * - * @return if a transaction has missing signatures - */ - public boolean hasMissingSignatures() { - return this.transactionInfo.isPresent() && this.transactionInfo.get().getHeight().equals(BigInteger.valueOf(0)) && !this.transactionInfo.get().getHash().equals(this.transactionInfo.get().getMerkleComponentHash()); - } - - /** - * Returns if a transaction is not known by the network. - * - * @return if a transaction is not known by the network - */ - public boolean isUnannounced() { - return !this.transactionInfo.isPresent(); - } - - /** - * get value of the version field for serialization - * - * @return 4 bytes - */ - protected int getTxVersionforSerialization() { - return TransactionMappingUtils.serializeVersion(getVersion(), getNetworkType().getValue()); - } - + /** standard transaction header size */ + public static final int HEADER_SIZE = 122; + + private final TransactionType type; + private final NetworkType networkType; + private final Integer version; + private final TransactionDeadline deadline; + private final BigInteger maxFee; + private final Optional signature; + private final Optional signer; + private final Optional transactionInfo; + + /** + * Constructor + * + * @param type Transaction type. + * @param networkType Network type. + * @param version Transaction version. + * @param deadline Transaction deadline. + * @param maxFee Transaction fee. + * @param signature Transaction signature. + * @param signer Transaction signer. + * @param transactionInfo Transaction meta data info. + */ + public Transaction(TransactionType type, NetworkType networkType, Integer version, TransactionDeadline deadline, + BigInteger maxFee, Optional signature, Optional signer, + Optional transactionInfo) { + Validate.notNull(type, "Type must not be null"); + Validate.notNull(networkType, "NetworkType must not be null"); + Validate.notNull(version, "Version must not be null"); + Validate.notNull(deadline, "Deadline must not be null"); + Validate.notNull(maxFee, "MaxFee must not be null"); + this.type = type; + this.networkType = networkType; + this.version = version; + this.deadline = deadline; + this.maxFee = maxFee; + this.signature = signature; + this.signer = signer; + this.transactionInfo = transactionInfo; + } + + /** + * Generates hash for a serialized transaction payload. + * + * @param payloadBytes Transaction payload as byte array + * @param generationHashBytes the network generation hash + * @return generated transaction hash. + */ + public static String createTransactionHash(byte[] payloadBytes, byte[] generationHashBytes) { + // expected size is payload - 4 bytes + byte[] signingBytes = new byte[payloadBytes.length - 4]; + // 32 bytes = skip 4 bytes and take half of the signature + System.arraycopy(payloadBytes, 4, signingBytes, 0, 32); + // 32 bytes = skip second half of signature and take signer + System.arraycopy(payloadBytes, 68, signingBytes, 32, 32); + // 32 bytes = generation hash + System.arraycopy(generationHashBytes, 0, signingBytes, 64, 32); + // remainder + System.arraycopy(payloadBytes, 100, signingBytes, 96, payloadBytes.length - 100); + + // hash and encode as upper-case hexadecimal string + byte[] result = Hashes.sha3_256(signingBytes); + return Hex.toHexString(result).toUpperCase(); + } + + /** + * Returns the transaction type. + * + * @return transaction type + */ + public TransactionType getType() { + return type; + } + + /** + * Returns the network type. + * + * @return the network type + */ + public NetworkType getNetworkType() { + return networkType; + } + + /** + * Returns the transaction version. + * + * @return transaction version + */ + public Integer getVersion() { + return version; + } + + /** + * Returns the deadline to include the transaction. + * + * @return deadline to include transaction into a block. + */ + public TransactionDeadline getDeadline() { + return deadline; + } + + /** + * Returns the fee for the transaction. The higher the fee, the higher the priority of the transaction. Transactions + * with high priority get included in a block before transactions with lower priority. + * + * @return fee amount + */ + public BigInteger getMaxFee() { + return maxFee; + } + + /** + * Returns the transaction signature (missing if part of an aggregate transaction). + * + * @return transaction signature + */ + public Optional getSignature() { + return signature; + } + + /** + * Returns the transaction creator public account. + * + * @return signer public account + */ + public Optional getSigner() { + return signer; + } + + /** + * Returns meta data object contains additional information about the transaction. + * + * @return transaction meta data info. + */ + public Optional getTransactionInfo() { + return transactionInfo; + } + + /** + * get number of bytes the transaction will get serialized to + * + * @return the number of bytes after serialization + */ + protected int getSerializedSize() { + return HEADER_SIZE + getPayloadSerializedSize(); + } + + /** + * payload size is number of bytes to which the actual transaction data will be serialized to. This does not include + * transaction header. + * + * @return size of serialized payload + */ + protected abstract int getPayloadSerializedSize(); + + /** + * generate byte array with serialized form of transaction + * + * @return byte array + */ + protected abstract byte[] generateBytes(); + + /** + * create copy of he transaction but swap original signer for the one provided + * + * @param signer signer to use for the copy of transaction + * @return the transaction instance + */ + protected abstract Transaction copyForSigner(PublicAccount signer); + + /** + * Serialize and sign transaction creating a new SignedTransaction. + * + * @param account The account to sign the transaction. + * @param generationHash network generation hash retrieved from block 1 + * @return {@link SignedTransaction} + */ + public SignedTransaction signWith(Account account, String generationHash) { + // 32 bytes of the generation hash + byte[] generationHashBytes = Hex.decode(generationHash); + byte[] bytes = this.generateBytes(); + // ignore first 4 + 64 + 32 bytes from the serialized form and concat with 32 bytes of generation hash + byte[] signingBytes = new byte[bytes.length - 100 + 32]; + System.arraycopy(generationHashBytes, 0, signingBytes, 0, 32); + System.arraycopy(bytes, 100, signingBytes, 32, bytes.length - 100); + + // sign the byte array with generation hash and serialized transaction + Signature transSignature = new Signer(account.getKeyPair()).sign(signingBytes); + + // create payload + byte[] payload = new byte[bytes.length]; + // 4 bytes = size + System.arraycopy(bytes, 0, payload, 0, 4); + // 64 bytes = signature + byte[] transSignatureBytes = transSignature.getBytes(); + System.arraycopy(transSignatureBytes, 0, payload, 4, transSignatureBytes.length); + // 32 bytes = signer + byte[] rawSignerPublicKey = account.getKeyPair().getPublicKey().getRaw(); + System.arraycopy(rawSignerPublicKey, 0, payload, 64 + 4, rawSignerPublicKey.length); + // append remainder of the transaction bytes + System.arraycopy(bytes, 100, payload, 100, bytes.length - 100); + + // compute transaction hash + String hash = Transaction.createTransactionHash(payload, generationHashBytes); + + // return signed transaction + return new SignedTransaction(Hex.toHexString(payload).toUpperCase(), hash, type); + } + + /** + * Takes a transaction and formats bytes to be included in an aggregate transaction. + * + * @return transaction with signer serialized to be part of an aggregate transaction + */ + byte[] toAggregateTransactionBytes() { + // decode signer from hex to byte array + byte[] signerBytes = Hex.decode(this.getSigner() + .orElseThrow(() -> new IllegalStateException("Missing signer! Call toAggregate")).getPublicKey()); + // serialize the transaction + byte[] bytes = this.generateBytes(); + // we will be removing header (122) and adding size (4), signer (32), version (4), trans type(2) + byte[] resultBytes = new byte[bytes.length - 122 + 4 + 32 + 4 + 2]; + + // prepare size of this as embedded transaction + byte[] sizeBytes = BigInteger.valueOf(resultBytes.length).toByteArray(); + ArrayUtils.reverse(sizeBytes); + + // write size of the aggregate transaction bytes - can be less than 4 bytes + System.arraycopy(sizeBytes, 0, resultBytes, 0, sizeBytes.length); + // at position 4 start writing 32 bytes of signer + System.arraycopy(signerBytes, 0, resultBytes, 4, 32); + // version is expected to start at position 100 and be 4 bytes, then take next 2 bytes + System.arraycopy(bytes, 100, resultBytes, 4 + 32, 6); + // copy remaining data after header + System.arraycopy(bytes, 122, resultBytes, 4 + 32 + 6, bytes.length - 122); + + return resultBytes; + } + + /** + * Convert an aggregate transaction to an inner transaction including transaction signer. + * + * @param signer Transaction signer. + * @return instance of Transaction with signer + */ + public Transaction toAggregate(PublicAccount signer) { + return copyForSigner(signer); + } + + /** + * Returns if a transaction is pending to be included in a block. + * + * @return if a transaction is pending to be included in a block + */ + public boolean isUnconfirmed() { + return this.transactionInfo.isPresent() && this.transactionInfo.get().getHeight().equals(BigInteger.valueOf(0)) + && this.transactionInfo.get().getHash().equals(this.transactionInfo.get().getMerkleComponentHash()); + } + + /** + * Return if a transaction is included in a block. + * + * @return if a transaction is included in a block + */ + public boolean isConfirmed() { + return this.transactionInfo.isPresent() && this.transactionInfo.get().getHeight().intValue() > 0; + } + + /** + * Returns if a transaction has missing signatures. + * + * @return if a transaction has missing signatures + */ + public boolean hasMissingSignatures() { + return this.transactionInfo.isPresent() && this.transactionInfo.get().getHeight().equals(BigInteger.valueOf(0)) + && !this.transactionInfo.get().getHash().equals(this.transactionInfo.get().getMerkleComponentHash()); + } + + /** + * Returns if a transaction is not known by the network. + * + * @return if a transaction is not known by the network + */ + public boolean isUnannounced() { + return !this.transactionInfo.isPresent(); + } + + /** + * get value of the version field for serialization + * + * @return 4 bytes + */ + protected int getTxVersionforSerialization() { + return TransactionMappingUtils.serializeVersion(getVersion(), getNetworkType().getValue()); + } + @Override public String toString() { return "Transaction [type=" + type + ", networkType=" + networkType + ", version=" + version + ", deadline=" - + deadline + ", fee=" + fee + ", signature=" + signature + ", signer=" + signer + ", transactionInfo=" + + deadline + ", maxFee=" + maxFee + ", signature=" + signature + ", signer=" + signer + ", transactionInfo=" + transactionInfo + "]"; } - - + } diff --git a/src/main/java/io/proximax/sdk/model/transaction/TransferTransaction.java b/src/main/java/io/proximax/sdk/model/transaction/TransferTransaction.java index 1b23bfcb..e3b54eca 100644 --- a/src/main/java/io/proximax/sdk/model/transaction/TransferTransaction.java +++ b/src/main/java/io/proximax/sdk/model/transaction/TransferTransaction.java @@ -27,11 +27,9 @@ import io.proximax.sdk.gen.buffers.MessageBuffer; import io.proximax.sdk.gen.buffers.MosaicBuffer; import io.proximax.sdk.gen.buffers.TransferTransactionBuffer; -import io.proximax.sdk.model.account.Address; import io.proximax.sdk.model.account.PublicAccount; import io.proximax.sdk.model.blockchain.NetworkType; import io.proximax.sdk.model.mosaic.Mosaic; -import io.proximax.sdk.model.namespace.NamespaceId; import io.proximax.sdk.utils.dto.UInt64Utils; /** @@ -40,168 +38,167 @@ * @since 1.0 */ public class TransferTransaction extends Transaction { - private final Recipient recipient; - private final List mosaics; - private final Message message; - private final Schema schema = new TransferTransactionSchema(); - - public TransferTransaction(NetworkType networkType, Integer version, TransactionDeadline deadline, BigInteger fee, Recipient recipient, List mosaics, Message message, String signature, PublicAccount signer, TransactionInfo transactionInfo) { - this(networkType, version, deadline, fee, recipient, mosaics, message, Optional.of(signature), Optional.of(signer), Optional.of(transactionInfo)); - } - - public TransferTransaction(NetworkType networkType, Integer version, TransactionDeadline deadline, BigInteger fee, Recipient recipient, List mosaics, Message message) { - this(networkType, version, deadline, fee, recipient, mosaics, message, Optional.empty(), Optional.empty(), Optional.empty()); - } - - private TransferTransaction(NetworkType networkType, Integer version, TransactionDeadline deadline, BigInteger fee, Recipient recipient, List mosaics, Message message, Optional signature, Optional signer, Optional transactionInfo) { - super(TransactionType.TRANSFER, networkType, version, deadline, fee, signature, signer, transactionInfo); - Validate.notNull(recipient, "Recipient must not be null"); - Validate.notNull(mosaics, "Mosaics must not be null"); - Validate.notNull(message, "Message must not be null"); - this.recipient = recipient; - this.mosaics = mosaics; - this.message = message; - } - - /** - * Create a transfer transaction object. - * - * @param deadline - The deadline to include the transaction. - * @param recipient - The recipient of the transaction. - * @param mosaics - The array of mosaics. - * @param message - The transaction message. - * @param networkType - The network type. - * @return a TransferTransaction instance - */ - public static TransferTransaction create(TransactionDeadline deadline, Recipient recipient, List mosaics, Message message, NetworkType networkType) { - return new TransferTransaction(networkType, TransactionVersion.TRANSFER.getValue(), deadline, BigInteger.valueOf(0), recipient, mosaics, message); - } - - /** - * Create a transfer transaction object for specified Address recipient - * - * @param deadline - The deadline to include the transaction. - * @param address - The recipient address of the transaction. - * @param mosaics - The array of mosaics. - * @param message - The transaction message. - * @param networkType - The network type. - * @return a TransferTransaction instance - */ - public static TransferTransaction create(TransactionDeadline deadline, Address address, List mosaics, Message message, NetworkType networkType) { - return new TransferTransaction(networkType, TransactionVersion.TRANSFER.getValue(), deadline, BigInteger.valueOf(0), Recipient.from(address), mosaics, message); - } - - /** - * Create a transfer transaction object for specified NamespaceId recipient - it is assumed that given namespace ID has alias to an account - * - * @param deadline - The deadline to include the transaction. - * @param namespaceId - The recipient namespace of the transaction. - * @param mosaics - The array of mosaics. - * @param message - The transaction message. - * @param networkType - The network type. - * @return a TransferTransaction instance - */ - public static TransferTransaction create(TransactionDeadline deadline, NamespaceId namespaceId, List mosaics, Message message, NetworkType networkType) { - return new TransferTransaction(networkType, TransactionVersion.TRANSFER.getValue(), deadline, BigInteger.valueOf(0), Recipient.from(namespaceId), mosaics, message); - } - - /** - * Returns the recipient. - * - * @return recipient - */ - public Recipient getRecipient() { - return recipient; - } - - /** - * Returns list of mosaic objects. - * - * @return list of mosaics in the transfer - */ - public List getMosaics() { - return mosaics; - } - - /** - * Returns transaction message. - * - * @return Message - */ - public Message getMessage() { - return message; - } - - byte[] generateBytes() { - FlatBufferBuilder builder = new FlatBufferBuilder(); - BigInteger deadlineBigInt = BigInteger.valueOf(getDeadline().getInstant()); - - // Create Message - byte[] bytePayload = message.getEncodedPayload(); - int payload = MessageBuffer.createPayloadVector(builder, bytePayload); - MessageBuffer.startMessageBuffer(builder); - MessageBuffer.addType(builder, message.getTypeCode()); - MessageBuffer.addPayload(builder, payload); - int messageVector = MessageBuffer.endMessageBuffer(builder); - - // Create Mosaics - int[] mosaicBuffers = new int[mosaics.size()]; - for (int i = 0; i < mosaics.size(); ++i) { - Mosaic mosaic = mosaics.get(i); - int id = MosaicBuffer.createIdVector(builder, UInt64Utils.fromBigInteger(mosaic.getId().getId())); - int amount = MosaicBuffer.createAmountVector(builder, UInt64Utils.fromBigInteger(mosaic.getAmount())); - MosaicBuffer.startMosaicBuffer(builder); - MosaicBuffer.addId(builder, id); - MosaicBuffer.addAmount(builder, amount); - mosaicBuffers[i] = MosaicBuffer.endMosaicBuffer(builder); - } - - // serialize the recipient - byte[] recipientBytes = recipient.getBytes(); - // Create Vectors - int signatureVector = TransferTransactionBuffer.createSignatureVector(builder, new byte[64]); - int signerVector = TransferTransactionBuffer.createSignerVector(builder, new byte[32]); - int deadlineVector = TransferTransactionBuffer.createDeadlineVector(builder, UInt64Utils.fromBigInteger(deadlineBigInt)); - int feeVector = TransferTransactionBuffer.createMaxFeeVector(builder, UInt64Utils.fromBigInteger(getFee())); - int recipientVector = TransferTransactionBuffer.createRecipientVector(builder, recipientBytes); - int mosaicsVector = TransferTransactionBuffer.createMosaicsVector(builder, mosaicBuffers); - - // total size of transaction - int size = HEADER_SIZE + - // recipient is always 25 bytes - 25 + - // message size is short - 2 + - // message type byte - 1 + - // number of mosaics - 1 + - // each mosaic has id and amount, both 8byte uint64 - ((8 + 8) * mosaics.size()) + - // number of message bytes - bytePayload.length; - - TransferTransactionBuffer.startTransferTransactionBuffer(builder); - TransferTransactionBuffer.addSize(builder, size); - TransferTransactionBuffer.addSignature(builder, signatureVector); - TransferTransactionBuffer.addSigner(builder, signerVector); - TransferTransactionBuffer.addVersion(builder, getTxVersionforSerialization()); - TransferTransactionBuffer.addType(builder, getType().getValue()); - TransferTransactionBuffer.addMaxFee(builder, feeVector); - TransferTransactionBuffer.addDeadline(builder, deadlineVector); - - TransferTransactionBuffer.addRecipient(builder, recipientVector); - TransferTransactionBuffer.addNumMosaics(builder, mosaics.size()); - TransferTransactionBuffer.addMessageSize(builder, bytePayload.length + 1); - TransferTransactionBuffer.addMessage(builder, messageVector); - TransferTransactionBuffer.addMosaics(builder, mosaicsVector); - - int codedTransfer = TransferTransactionBuffer.endTransferTransactionBuffer(builder); - builder.finish(codedTransfer); - - // validate size - byte[] output = schema.serialize(builder.sizedByteArray()); - Validate.isTrue(output.length == size, "Serialized transaction has incorrect length: " + this.getClass()); - return output; - } + private final Schema schema = new TransferTransactionSchema(); + + private final Recipient recipient; + private final List mosaics; + private final Message message; + + /** + * @param networkType network type + * @param version transaction version. Use {@link TransactionVersion#TRANSFER} for current version + * @param deadline transaction deadline + * @param maxFee transaction fee + * @param signature optional signature + * @param signer optional signer + * @param transactionInfo optional transaction info + * @param recipient transfer recipient + * @param mosaics list of mosaic values that is to be transferred + * @param message message + */ + public TransferTransaction(NetworkType networkType, Integer version, TransactionDeadline deadline, BigInteger maxFee, + Optional signature, Optional signer, Optional transactionInfo, + Recipient recipient, List mosaics, Message message) { + super(TransactionType.TRANSFER, networkType, version, deadline, maxFee, signature, signer, transactionInfo); + Validate.notNull(recipient, "Recipient must not be null"); + Validate.notNull(mosaics, "Mosaics must not be null"); + Validate.notNull(message, "Message must not be null"); + this.recipient = recipient; + this.mosaics = mosaics; + this.message = message; + } + + /** + * Returns the recipient. + * + * @return recipient + */ + public Recipient getRecipient() { + return recipient; + } + + /** + * Returns list of mosaic objects. + * + * @return list of mosaics in the transfer + */ + public List getMosaics() { + return mosaics; + } + + /** + * Returns transaction message. + * + * @return Message + */ + public Message getMessage() { + return message; + } + + @Override + protected byte[] generateBytes() { + FlatBufferBuilder builder = new FlatBufferBuilder(); + BigInteger deadlineBigInt = BigInteger.valueOf(getDeadline().getInstant()); + + // Create Message + byte[] payloadBytes = serializeMessage(getMessage()); + int payload = MessageBuffer.createPayloadVector(builder, payloadBytes); + MessageBuffer.startMessageBuffer(builder); + MessageBuffer.addType(builder, message.getTypeCode()); + MessageBuffer.addPayload(builder, payload); + int messageVector = MessageBuffer.endMessageBuffer(builder); + + // Create Mosaics + int[] mosaicBuffers = new int[mosaics.size()]; + for (int i = 0; i < mosaics.size(); ++i) { + Mosaic mosaic = mosaics.get(i); + int id = MosaicBuffer.createIdVector(builder, UInt64Utils.fromBigInteger(mosaic.getId().getId())); + int amount = MosaicBuffer.createAmountVector(builder, UInt64Utils.fromBigInteger(mosaic.getAmount())); + MosaicBuffer.startMosaicBuffer(builder); + MosaicBuffer.addId(builder, id); + MosaicBuffer.addAmount(builder, amount); + mosaicBuffers[i] = MosaicBuffer.endMosaicBuffer(builder); + } + + // serialize the recipient + byte[] recipientBytes = recipient.getBytes(); + // Create Vectors + int signatureVector = TransferTransactionBuffer.createSignatureVector(builder, new byte[64]); + int signerVector = TransferTransactionBuffer.createSignerVector(builder, new byte[32]); + int deadlineVector = TransferTransactionBuffer.createDeadlineVector(builder, + UInt64Utils.fromBigInteger(deadlineBigInt)); + int feeVector = TransferTransactionBuffer.createMaxFeeVector(builder, UInt64Utils.fromBigInteger(getMaxFee())); + int recipientVector = TransferTransactionBuffer.createRecipientVector(builder, recipientBytes); + int mosaicsVector = TransferTransactionBuffer.createMosaicsVector(builder, mosaicBuffers); + + // total size of transaction + int size = getSerializedSize(); + + TransferTransactionBuffer.startTransferTransactionBuffer(builder); + TransferTransactionBuffer.addSize(builder, size); + TransferTransactionBuffer.addSignature(builder, signatureVector); + TransferTransactionBuffer.addSigner(builder, signerVector); + TransferTransactionBuffer.addVersion(builder, getTxVersionforSerialization()); + TransferTransactionBuffer.addType(builder, getType().getValue()); + TransferTransactionBuffer.addMaxFee(builder, feeVector); + TransferTransactionBuffer.addDeadline(builder, deadlineVector); + + TransferTransactionBuffer.addRecipient(builder, recipientVector); + TransferTransactionBuffer.addNumMosaics(builder, mosaics.size()); + TransferTransactionBuffer.addMessageSize(builder, payloadBytes.length + 1); + TransferTransactionBuffer.addMessage(builder, messageVector); + TransferTransactionBuffer.addMosaics(builder, mosaicsVector); + + int codedTransfer = TransferTransactionBuffer.endTransferTransactionBuffer(builder); + builder.finish(codedTransfer); + + // validate size + byte[] output = schema.serialize(builder.sizedByteArray()); + Validate.isTrue(output.length == size, "Serialized transaction has incorrect length: " + this.getClass()); + return output; + } + + @Override + protected Transaction copyForSigner(PublicAccount signer) { + return new TransferTransaction(getNetworkType(), getVersion(), getDeadline(), getMaxFee(), getSignature(), + Optional.of(signer), getTransactionInfo(), getRecipient(), getMosaics(), getMessage()); + } + + /** + * calculate payload size by specifying items with variable size + * + * @param message transaction message + * @param mosaicCount number of mosaics that will be transferred + * @return size of the payload excluding message header + */ + public static int calculatePayloadSize(Message message, int mosaicCount) { + return + // recipient is always 25 bytes + 25 + + // message size is short + 2 + + // message type byte + 1 + + // number of mosaics + 1 + + // each mosaic has id and amount, both 8byte uint64 + ((8 + 8) * mosaicCount) + + // number of message bytes + serializeMessage(message).length; + } + + /** + * serialize the message into byte array + * + * @param message the message + * @return byte array representing the message + */ + protected static byte[] serializeMessage(Message message) { + return message.getEncodedPayload(); + } + + @Override + protected int getPayloadSerializedSize() { + return calculatePayloadSize(getMessage(), getMosaics().size()); + } } diff --git a/src/main/java/io/proximax/sdk/model/transaction/builder/AccountLinkTransactionBuilder.java b/src/main/java/io/proximax/sdk/model/transaction/builder/AccountLinkTransactionBuilder.java new file mode 100644 index 00000000..a508f5fd --- /dev/null +++ b/src/main/java/io/proximax/sdk/model/transaction/builder/AccountLinkTransactionBuilder.java @@ -0,0 +1,104 @@ +/* + * Copyright 2019 ProximaX Limited. All rights reserved. + * Use of this source code is governed by the Apache 2.0 + * license that can be found in the LICENSE file. + */ +package io.proximax.sdk.model.transaction.builder; + +import java.math.BigInteger; + +import io.proximax.sdk.model.account.PublicAccount; +import io.proximax.sdk.model.transaction.AccountLinkAction; +import io.proximax.sdk.model.transaction.AccountLinkTransaction; +import io.proximax.sdk.model.transaction.TransactionType; +import io.proximax.sdk.model.transaction.TransactionVersion; + +/** + * builder for {@link AccountLinkTransaction} + */ +public class AccountLinkTransactionBuilder + extends TransactionBuilder { + + private PublicAccount remoteAccount; + private AccountLinkAction action; + + public AccountLinkTransactionBuilder() { + super(TransactionType.ACCOUNT_LINK, TransactionVersion.ACCOUNT_LINK.getValue()); + } + + @Override + protected AccountLinkTransactionBuilder self() { + return this; + } + + @Override + public AccountLinkTransaction build() { + // use or calculate maxFee + BigInteger maxFee = getMaxFee().orElseGet( + () -> getMaxFeeCalculation(AccountLinkTransaction.calculatePayloadSize())); + // create transaction instance + return new AccountLinkTransaction(getNetworkType(), getVersion(), getDeadline(), maxFee, getSignature(), + getSigner(), getTransactionInfo(), getRemoteAccount(), getAction()); + } + + // ------------------------------------- setters ---------------------------------------------// + /** + * define the remote account to link/unlink to/from + * + * @param remoteAccount linked account + * @return self + */ + public AccountLinkTransactionBuilder remoteAccount(PublicAccount remoteAccount) { + this.remoteAccount = remoteAccount; + return self(); + } + + /** + * the link/unlink action to perform + * + * @param action the action + * @return self + */ + public AccountLinkTransactionBuilder action(AccountLinkAction action) { + this.action = action; + return self(); + } + + // -------------------------------------- getters --------------------------------------------// + + /** + * @return the remoteAccount + */ + public PublicAccount getRemoteAccount() { + return remoteAccount; + } + + /** + * @return the action + */ + public AccountLinkAction getAction() { + return action; + } + + // -------------------------------------- convenience --------------------------------------------// + + /** + * link remote account + * + * @param remoteAccount the account + * @return self + */ + public AccountLinkTransactionBuilder link(PublicAccount remoteAccount) { + return action(AccountLinkAction.LINK).remoteAccount(remoteAccount); + } + + /** + * unlink remote account + * + * @param remoteAccount the account + * @return self + */ + public AccountLinkTransactionBuilder unlink(PublicAccount remoteAccount) { + return action(AccountLinkAction.UNLINK).remoteAccount(remoteAccount); + } +} diff --git a/src/main/java/io/proximax/sdk/model/transaction/builder/AggregateTransactionBuilder.java b/src/main/java/io/proximax/sdk/model/transaction/builder/AggregateTransactionBuilder.java new file mode 100644 index 00000000..d7cf00c2 --- /dev/null +++ b/src/main/java/io/proximax/sdk/model/transaction/builder/AggregateTransactionBuilder.java @@ -0,0 +1,121 @@ +/* + * Copyright 2019 ProximaX Limited. All rights reserved. + * Use of this source code is governed by the Apache 2.0 + * license that can be found in the LICENSE file. + */ +package io.proximax.sdk.model.transaction.builder; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import io.proximax.sdk.model.transaction.AggregateTransaction; +import io.proximax.sdk.model.transaction.AggregateTransactionCosignature; +import io.proximax.sdk.model.transaction.Transaction; +import io.proximax.sdk.model.transaction.TransactionType; +import io.proximax.sdk.model.transaction.TransactionVersion; + +/** + * builder for {@link AggregateTransaction} + */ +public class AggregateTransactionBuilder extends TransactionBuilder { + + private List innerTransactions; + private List cosignatures; + + private AggregateTransactionBuilder(TransactionType type, Integer version) { + super(type, version); + // provide empty lists as defaults + this.innerTransactions = new ArrayList<>(); + this.cosignatures = new ArrayList<>(); + } + + public static AggregateTransactionBuilder createBonded() { + return new AggregateTransactionBuilder(TransactionType.AGGREGATE_BONDED, + TransactionVersion.AGGREGATE_BONDED.getValue()); + } + + public static AggregateTransactionBuilder createComplete() { + return new AggregateTransactionBuilder(TransactionType.AGGREGATE_COMPLETE, + TransactionVersion.AGGREGATE_COMPLETE.getValue()); + } + + @Override + protected AggregateTransactionBuilder self() { + return this; + } + + @Override + public AggregateTransaction build() { + // use or calculate maxFee + BigInteger maxFee = getMaxFee().orElseGet( + () -> getMaxFeeCalculation(AggregateTransaction.calculatePayloadSize(getInnerTransactions()))); + // create transaction instance + return new AggregateTransaction(getType(), getNetworkType(), getVersion(), getDeadline(), maxFee, + getSignature(), getSigner(), getTransactionInfo(), getInnerTransactions(), + getCosignatures()); + } + + // ------------------------------------- setters ---------------------------------------------// + + /** + * set list of inner transactions + * + * @param innerTransactions inner transactions + * @return the builder + */ + public AggregateTransactionBuilder innerTransactions(List innerTransactions) { + this.innerTransactions = innerTransactions; + return self(); + } + + /** + * set list of available cosignatures + * + * @param cosignatures list of cosignatures + * @return the builder + */ + public AggregateTransactionBuilder cosignatures(List cosignatures) { + this.cosignatures = cosignatures; + return self(); + } + + // -------------------------------------- getters --------------------------------------------// + + /** + * @return the innerTransactions + */ + public List getInnerTransactions() { + return innerTransactions; + } + + /** + * @return the cosignatures + */ + public List getCosignatures() { + return cosignatures; + } + + // -------------------------------------- convenience --------------------------------------------// + + /** + * set list of inner transactions + * + * @param innerTransactions inner transactions + * @return the builder + */ + public AggregateTransactionBuilder innerTransactions(Transaction ... innerTransactions) { + return innerTransactions(Arrays.asList(innerTransactions)); + } + + /** + * set list of cosignatures + * + * @param cosignatures cosignatures + * @return the builder + */ + public AggregateTransactionBuilder cosignatures(AggregateTransactionCosignature ... cosignatures) { + return cosignatures(Arrays.asList(cosignatures)); + } +} diff --git a/src/main/java/io/proximax/sdk/model/transaction/builder/AliasTransactionBuilder.java b/src/main/java/io/proximax/sdk/model/transaction/builder/AliasTransactionBuilder.java new file mode 100644 index 00000000..23655268 --- /dev/null +++ b/src/main/java/io/proximax/sdk/model/transaction/builder/AliasTransactionBuilder.java @@ -0,0 +1,183 @@ +/* + * Copyright 2019 ProximaX Limited. All rights reserved. + * Use of this source code is governed by the Apache 2.0 + * license that can be found in the LICENSE file. + */ +package io.proximax.sdk.model.transaction.builder; + +import java.math.BigInteger; +import java.util.Optional; + +import org.apache.commons.lang3.Validate; + +import io.proximax.sdk.model.account.Address; +import io.proximax.sdk.model.alias.AliasAction; +import io.proximax.sdk.model.mosaic.MosaicId; +import io.proximax.sdk.model.namespace.NamespaceId; +import io.proximax.sdk.model.transaction.AliasTransaction; +import io.proximax.sdk.model.transaction.TransactionType; +import io.proximax.sdk.model.transaction.TransactionVersion; + +/** + * builder for {@link AliasTransaction} + */ +public class AliasTransactionBuilder extends TransactionBuilder { + + private Optional mosaicId; + private Optional
address; + private NamespaceId namespaceId; + private AliasAction aliasAction; + + private AliasTransactionBuilder(TransactionType type, Integer version) { + super(type, version); + // defaults + mosaicId = Optional.empty(); + address = Optional.empty(); + } + + public static AliasTransactionBuilder createForAddress() { + return new AliasTransactionBuilder(TransactionType.ADDRESS_ALIAS, TransactionVersion.ADDRESS_ALIAS.getValue()); + } + + public static AliasTransactionBuilder createForMosaic() { + return new AliasTransactionBuilder(TransactionType.MOSAIC_ALIAS, TransactionVersion.MOSAIC_ALIAS.getValue()); + } + + @Override + protected AliasTransactionBuilder self() { + return this; + } + + @Override + public AliasTransaction build() { + // use or calculate maxFee + BigInteger maxFee = getMaxFee() + .orElseGet(() -> getMaxFeeCalculation(AliasTransaction.calculatePayloadSize(getAddress().isPresent()))); + // create transaction instance + return new AliasTransaction(getType(), getNetworkType(), getVersion(), getDeadline(), maxFee, getSignature(), + getSigner(), getTransactionInfo(), getMosaicId(), getAddress(), getNamespaceId(), getAliasAction()); + } + + // ------------------------------------- setters ---------------------------------------------// + + /** + * define mosaic ID for which alias is to be created + * + * @param mosaicId id of the mosaic + * @return self + */ + public AliasTransactionBuilder mosaicId(MosaicId mosaicId) { + Validate.isTrue(getType() == TransactionType.MOSAIC_ALIAS, + "Mosaic ID alias can be created only by mosaic alias builder"); + this.mosaicId = Optional.of(mosaicId); + return self(); + } + + /** + * specify address for which the alias is to be created + * + * @param address the address + * @return self + */ + public AliasTransactionBuilder address(Address address) { + Validate.isTrue(getType() == TransactionType.ADDRESS_ALIAS, + "Address alias can be created only by address alias builder"); + this.address = Optional.of(address); + return self(); + } + + /** + * specify namespace ID which will be having alias to either address or mosaic + * + * @param namespaceId target namespace ID + * @return self + */ + public AliasTransactionBuilder namespaceId(NamespaceId namespaceId) { + this.namespaceId = namespaceId; + return self(); + } + + /** + * action to perform with the alias + * + * @param aliasAction link or unlink + * @return self + */ + public AliasTransactionBuilder aliasAction(AliasAction aliasAction) { + this.aliasAction = aliasAction; + return self(); + } + + // -------------------------------------- getters --------------------------------------------// + + /** + * @return the mosaicId + */ + public Optional getMosaicId() { + return mosaicId; + } + + /** + * @return the address + */ + public Optional
getAddress() { + return address; + } + + /** + * @return the namespaceId + */ + public NamespaceId getNamespaceId() { + return namespaceId; + } + + /** + * @return the aliasAction + */ + public AliasAction getAliasAction() { + return aliasAction; + } + + // -------------------------------------- convenience --------------------------------------------// + + /** + * create alias for mosaic ID + * + * @param mosaicId the mosaic ID + * @return self + */ + public AliasTransactionBuilder link(MosaicId mosaicId) { + return aliasAction(AliasAction.LINK).mosaicId(mosaicId); + } + + /** + * create alias for the address + * + * @param address the address + * @return self + */ + public AliasTransactionBuilder link(Address address) { + return aliasAction(AliasAction.LINK).address(address); + } + + /** + * remove alias from mosaic ID + * + * @param mosaicId the mosaic ID + * @return self + */ + public AliasTransactionBuilder unlink(MosaicId mosaicId) { + return aliasAction(AliasAction.UNLINK).mosaicId(mosaicId); + } + + /** + * remove link from the address + * + * @param address the address + * @return self + */ + public AliasTransactionBuilder unlink(Address address) { + return aliasAction(AliasAction.UNLINK).address(address); + } + +} diff --git a/src/main/java/io/proximax/sdk/model/transaction/builder/BlockchainConfigTransactionBuilder.java b/src/main/java/io/proximax/sdk/model/transaction/builder/BlockchainConfigTransactionBuilder.java new file mode 100644 index 00000000..4d845e27 --- /dev/null +++ b/src/main/java/io/proximax/sdk/model/transaction/builder/BlockchainConfigTransactionBuilder.java @@ -0,0 +1,106 @@ +/* + * Copyright 2019 ProximaX Limited. All rights reserved. + * Use of this source code is governed by the Apache 2.0 + * license that can be found in the LICENSE file. + */ +package io.proximax.sdk.model.transaction.builder; + +import java.math.BigInteger; + +import io.proximax.core.utils.StringUtils; +import io.proximax.sdk.model.transaction.BlockchainConfigTransaction; +import io.proximax.sdk.model.transaction.TransactionType; +import io.proximax.sdk.model.transaction.TransactionVersion; + +/** + * builder for {@link BlockchainConfigTransactionBuilder} + */ +public class BlockchainConfigTransactionBuilder + extends TransactionBuilder { + + private BigInteger applyHeightDelta; + private String blockchainConfig; + private String supportedEntityVersions; + + public BlockchainConfigTransactionBuilder() { + super(TransactionType.BLOCKCHAIN_CONFIG, TransactionVersion.BLOCKCHAIN_CONFIG.getValue()); + } + + @Override + protected BlockchainConfigTransactionBuilder self() { + return this; + } + + @Override + public BlockchainConfigTransaction build() { + // use or calculate maxFee + BigInteger maxFee = getMaxFee().orElseGet(() -> getMaxFeeCalculation( + BlockchainConfigTransaction.calculatePayloadSize(StringUtils.getBytes(getBlockchainConfig()).length, + StringUtils.getBytes(getSupportedEntityVersions()).length))); + // create transaction instance + return new BlockchainConfigTransaction(getNetworkType(), getVersion(), getDeadline(), maxFee, getSignature(), + getSigner(), getTransactionInfo(), getApplyHeightDelta(), getBlockchainConfig(), + getSupportedEntityVersions()); + } + + // ------------------------------------- setters ---------------------------------------------// + + /** + * number of blocks after which specified configuration will become valid + * + * @param applyHeightDelta number of blocks + * @return self + */ + public BlockchainConfigTransactionBuilder applyHeightDelta(BigInteger applyHeightDelta) { + this.applyHeightDelta = applyHeightDelta; + return self(); + } + + /** + * configuration in the format of property file + * + * @param blockchainConfig the configuration + * @return self + */ + public BlockchainConfigTransactionBuilder blockchainConfig(String blockchainConfig) { + this.blockchainConfig = blockchainConfig; + return self(); + } + + /** + * JSON string representing supported entity versions + * + * @param supportedEntityVersions JSON string + * @return self + */ + public BlockchainConfigTransactionBuilder supportedEntityVersions(String supportedEntityVersions) { + this.supportedEntityVersions = supportedEntityVersions; + return self(); + } + + // -------------------------------------- getters --------------------------------------------// + + /** + * @return the applyHeightDelta + */ + public BigInteger getApplyHeightDelta() { + return applyHeightDelta; + } + + /** + * @return the blockchainConfig + */ + public String getBlockchainConfig() { + return blockchainConfig; + } + + /** + * @return the supportedEntityVersions + */ + public String getSupportedEntityVersions() { + return supportedEntityVersions; + } + + // -------------------------------------- convenience --------------------------------------------// + +} diff --git a/src/main/java/io/proximax/sdk/model/transaction/builder/BlockchainUpgradeTransactionBuilder.java b/src/main/java/io/proximax/sdk/model/transaction/builder/BlockchainUpgradeTransactionBuilder.java new file mode 100644 index 00000000..e456bc6d --- /dev/null +++ b/src/main/java/io/proximax/sdk/model/transaction/builder/BlockchainUpgradeTransactionBuilder.java @@ -0,0 +1,86 @@ +/* + * Copyright 2019 ProximaX Limited. All rights reserved. + * Use of this source code is governed by the Apache 2.0 + * license that can be found in the LICENSE file. + */ +package io.proximax.sdk.model.transaction.builder; + +import java.math.BigInteger; + +import io.proximax.sdk.model.blockchain.BlockchainVersion; +import io.proximax.sdk.model.transaction.BlockchainUpgradeTransaction; +import io.proximax.sdk.model.transaction.TransactionType; +import io.proximax.sdk.model.transaction.TransactionVersion; + +/** + * builder for {@link BlockchainUpgradeTransaction} + */ +public class BlockchainUpgradeTransactionBuilder + extends TransactionBuilder { + + private BigInteger upgradePeriod; + private BlockchainVersion newVersion; + + public BlockchainUpgradeTransactionBuilder() { + super(TransactionType.BLOCKCHAIN_UPGRADE, TransactionVersion.BLOCKCHAIN_UPGRADE.getValue()); + // defaults + } + + @Override + protected BlockchainUpgradeTransactionBuilder self() { + return this; + } + + @Override + public BlockchainUpgradeTransaction build() { + // use or calculate maxFee + BigInteger maxFee = getMaxFee() + .orElseGet(() -> getMaxFeeCalculation(BlockchainUpgradeTransaction.calculatePayloadSize())); + // create transaction instance + return new BlockchainUpgradeTransaction(getNetworkType(), getVersion(), getDeadline(), maxFee, getSignature(), + getSigner(), getTransactionInfo(), getUpgradePeriod(), getNewVersion()); + } + + // ------------------------------------- setters ---------------------------------------------// + + /** + * number of blocks after which the new version will be required if node wants to generate new block + * + * @param upgradePeriod number of blocks + * @return self + */ + public BlockchainUpgradeTransactionBuilder upgradePeriod(BigInteger upgradePeriod) { + this.upgradePeriod = upgradePeriod; + return self(); + } + + /** + * new blockchain version which will eventually need to be matched by node versions + * + * @param newVersion new blockchain version + * @return self + */ + public BlockchainUpgradeTransactionBuilder newVersion(BlockchainVersion newVersion) { + this.newVersion = newVersion; + return self(); + } + + // -------------------------------------- getters --------------------------------------------// + + /** + * @return the upgradePeriod + */ + public BigInteger getUpgradePeriod() { + return upgradePeriod; + } + + /** + * @return the newVersion + */ + public BlockchainVersion getNewVersion() { + return newVersion; + } + + // -------------------------------------- convenience --------------------------------------------// + +} diff --git a/src/main/java/io/proximax/sdk/model/transaction/builder/LockFundsTransactionBuilder.java b/src/main/java/io/proximax/sdk/model/transaction/builder/LockFundsTransactionBuilder.java new file mode 100644 index 00000000..eccd7a87 --- /dev/null +++ b/src/main/java/io/proximax/sdk/model/transaction/builder/LockFundsTransactionBuilder.java @@ -0,0 +1,115 @@ +/* + * Copyright 2019 ProximaX Limited. All rights reserved. + * Use of this source code is governed by the Apache 2.0 + * license that can be found in the LICENSE file. + */ +package io.proximax.sdk.model.transaction.builder; + +import java.math.BigInteger; + +import io.proximax.sdk.model.mosaic.Mosaic; +import io.proximax.sdk.model.mosaic.NetworkCurrencyMosaic; +import io.proximax.sdk.model.transaction.LockFundsTransaction; +import io.proximax.sdk.model.transaction.SignedTransaction; +import io.proximax.sdk.model.transaction.TransactionType; +import io.proximax.sdk.model.transaction.TransactionVersion; + +/** + * builder for {@link LockFundsTransaction} + */ +public class LockFundsTransactionBuilder + extends TransactionBuilder { + + private Mosaic mosaic; + private BigInteger duration; + private SignedTransaction signedTransaction; + + public LockFundsTransactionBuilder() { + super(TransactionType.LOCK, TransactionVersion.LOCK.getValue()); + } + + @Override + protected LockFundsTransactionBuilder self() { + return this; + } + + @Override + public LockFundsTransaction build() { + // use or calculate maxFee + BigInteger maxFee = getMaxFee().orElseGet( + () -> getMaxFeeCalculation(LockFundsTransaction.calculatePayloadSize())); + // create transaction instance + return new LockFundsTransaction(getNetworkType(), getVersion(), getDeadline(), maxFee, getSignature(), getSigner(), getTransactionInfo(), getMosaic(), getDuration(), getSignedTransaction()); + } + + + // ------------------------------------- setters ---------------------------------------------// + + /** + * set mosaic defining what to lock + * + * @param mosaic mosaic to lock + * @return self + */ + public LockFundsTransactionBuilder mosaic(Mosaic mosaic) { + this.mosaic = mosaic; + return self(); + } + + /** + * set duration of the lock + * + * @param duration the duration in number of blocks + * @return self + */ + public LockFundsTransactionBuilder duration(BigInteger duration) { + this.duration = duration; + return self(); + } + + /** + * set signed transaction which is the lock for + * + * @param signedTransaction the transaction + * @return self + */ + public LockFundsTransactionBuilder signedTransaction(SignedTransaction signedTransaction) { + this.signedTransaction = signedTransaction; + return self(); + } + + // -------------------------------------- getters --------------------------------------------// + + /** + * @return the mosaic + */ + public Mosaic getMosaic() { + return mosaic; + } + + /** + * @return the duration + */ + public BigInteger getDuration() { + return duration; + } + + /** + * @return the signedTransaction + */ + public SignedTransaction getSignedTransaction() { + return signedTransaction; + } + + // -------------------------------------- convenience --------------------------------------------// + + /** + * lock 10 network currency for specified duration. this is convenience for aggregate transaction locks + * + * @param duration the duration in number of blocks + * @return self + */ + public LockFundsTransactionBuilder aggregate(BigInteger duration) { + return mosaic(NetworkCurrencyMosaic.TEN).duration(duration); + } +} diff --git a/src/main/java/io/proximax/sdk/model/transaction/builder/ModifyAccountPropertyAddressTransactionBuilder.java b/src/main/java/io/proximax/sdk/model/transaction/builder/ModifyAccountPropertyAddressTransactionBuilder.java new file mode 100644 index 00000000..b89682ba --- /dev/null +++ b/src/main/java/io/proximax/sdk/model/transaction/builder/ModifyAccountPropertyAddressTransactionBuilder.java @@ -0,0 +1,34 @@ +/* + * Copyright 2019 ProximaX Limited. All rights reserved. + * Use of this source code is governed by the Apache 2.0 + * license that can be found in the LICENSE file. + */ +package io.proximax.sdk.model.transaction.builder; + +import java.math.BigInteger; + +import io.proximax.sdk.model.account.Address; +import io.proximax.sdk.model.transaction.ModifyAccountPropertyTransaction; +import io.proximax.sdk.model.transaction.TransactionType; +import io.proximax.sdk.model.transaction.TransactionVersion; + +/** + * Builder for account address property modification + */ +public class ModifyAccountPropertyAddressTransactionBuilder extends ModifyAccountPropertyTransactionBuilder
{ + + public ModifyAccountPropertyAddressTransactionBuilder() { + super(TransactionType.ACCOUNT_PROPERTIES_ADDRESS, TransactionVersion.ACCOUNT_PROPERTIES_ADDRESS.getValue()); + } + + @Override + public ModifyAccountPropertyTransaction
build() { + // use or calculate maxFee + BigInteger maxFee = getMaxFee().orElseGet(() -> getMaxFeeCalculation( + ModifyAccountPropertyTransaction.AddressModification.calculatePayloadSize(getModifications().size()))); + // create transaction instance + return new ModifyAccountPropertyTransaction.AddressModification(getNetworkType(), getVersion(), getDeadline(), + maxFee, getSignature(), getSigner(), getTransactionInfo(), getPropertyType(), getModifications()); + } + +} diff --git a/src/main/java/io/proximax/sdk/model/transaction/builder/ModifyAccountPropertyEntityTransactionBuilder.java b/src/main/java/io/proximax/sdk/model/transaction/builder/ModifyAccountPropertyEntityTransactionBuilder.java new file mode 100644 index 00000000..ae727c29 --- /dev/null +++ b/src/main/java/io/proximax/sdk/model/transaction/builder/ModifyAccountPropertyEntityTransactionBuilder.java @@ -0,0 +1,34 @@ +/* + * Copyright 2019 ProximaX Limited. All rights reserved. + * Use of this source code is governed by the Apache 2.0 + * license that can be found in the LICENSE file. + */ +package io.proximax.sdk.model.transaction.builder; + +import java.math.BigInteger; + +import io.proximax.sdk.model.transaction.ModifyAccountPropertyTransaction; +import io.proximax.sdk.model.transaction.TransactionType; +import io.proximax.sdk.model.transaction.TransactionVersion; + +/** + * Builder for account address property modification + */ +public class ModifyAccountPropertyEntityTransactionBuilder + extends ModifyAccountPropertyTransactionBuilder { + + public ModifyAccountPropertyEntityTransactionBuilder() { + super(TransactionType.ACCOUNT_PROPERTIES_ENTITY_TYPE, + TransactionVersion.ACCOUNT_PROPERTIES_ENTITY_TYPE.getValue()); + } + + @Override + public ModifyAccountPropertyTransaction build() { + // use or calculate maxFee + BigInteger maxFee = getMaxFee().orElseGet(() -> getMaxFeeCalculation( + ModifyAccountPropertyTransaction.EntityTypeModification.calculatePayloadSize(getModifications().size()))); + // create transaction instance + return new ModifyAccountPropertyTransaction.EntityTypeModification(getNetworkType(), getVersion(), getDeadline(), + maxFee, getSignature(), getSigner(), getTransactionInfo(), getPropertyType(), getModifications()); + } +} diff --git a/src/main/java/io/proximax/sdk/model/transaction/builder/ModifyAccountPropertyMosaicTransactionBuilder.java b/src/main/java/io/proximax/sdk/model/transaction/builder/ModifyAccountPropertyMosaicTransactionBuilder.java new file mode 100644 index 00000000..93775da4 --- /dev/null +++ b/src/main/java/io/proximax/sdk/model/transaction/builder/ModifyAccountPropertyMosaicTransactionBuilder.java @@ -0,0 +1,34 @@ +/* + * Copyright 2019 ProximaX Limited. All rights reserved. + * Use of this source code is governed by the Apache 2.0 + * license that can be found in the LICENSE file. + */ +package io.proximax.sdk.model.transaction.builder; + +import java.math.BigInteger; + +import io.proximax.sdk.model.transaction.ModifyAccountPropertyTransaction; +import io.proximax.sdk.model.transaction.TransactionType; +import io.proximax.sdk.model.transaction.TransactionVersion; +import io.proximax.sdk.model.transaction.UInt64Id; + +/** + * Builder for account address property modification + */ +public class ModifyAccountPropertyMosaicTransactionBuilder extends ModifyAccountPropertyTransactionBuilder { + + public ModifyAccountPropertyMosaicTransactionBuilder() { + super(TransactionType.ACCOUNT_PROPERTIES_ADDRESS, TransactionVersion.ACCOUNT_PROPERTIES_ADDRESS.getValue()); + } + + @Override + public ModifyAccountPropertyTransaction build() { + // use or calculate maxFee + BigInteger maxFee = getMaxFee().orElseGet(() -> getMaxFeeCalculation( + ModifyAccountPropertyTransaction.MosaicModification.calculatePayloadSize(getModifications().size()))); + // create transaction instance + return new ModifyAccountPropertyTransaction.MosaicModification(getNetworkType(), getVersion(), getDeadline(), + maxFee, getSignature(), getSigner(), getTransactionInfo(), getPropertyType(), getModifications()); + } + +} diff --git a/src/main/java/io/proximax/sdk/model/transaction/builder/ModifyAccountPropertyTransactionBuilder.java b/src/main/java/io/proximax/sdk/model/transaction/builder/ModifyAccountPropertyTransactionBuilder.java new file mode 100644 index 00000000..55f8683b --- /dev/null +++ b/src/main/java/io/proximax/sdk/model/transaction/builder/ModifyAccountPropertyTransactionBuilder.java @@ -0,0 +1,73 @@ +/* + * Copyright 2019 ProximaX Limited. All rights reserved. + * Use of this source code is governed by the Apache 2.0 + * license that can be found in the LICENSE file. + */ +package io.proximax.sdk.model.transaction.builder; + +import java.util.ArrayList; +import java.util.List; + +import io.proximax.sdk.model.account.props.AccountPropertyModification; +import io.proximax.sdk.model.account.props.AccountPropertyType; +import io.proximax.sdk.model.transaction.ModifyAccountPropertyTransaction; +import io.proximax.sdk.model.transaction.TransactionType; + +/** + * builder for {@link ModifyAccountPropertyTransaction} + */ +public abstract class ModifyAccountPropertyTransactionBuilder extends TransactionBuilder, ModifyAccountPropertyTransaction> { + + private AccountPropertyType propertyType; + private List> modifications; + + public ModifyAccountPropertyTransactionBuilder(TransactionType type, Integer version) { + super(type, version); + // provide empty lists as defaults + this.modifications = new ArrayList<>(); + } + + @Override + protected ModifyAccountPropertyTransactionBuilder self() { + return this; + } + + // ------------------------------------- setters ---------------------------------------------// + + /** + * @param propertyType the propertyType to set + * @return self + */ + public ModifyAccountPropertyTransactionBuilder propertyType(AccountPropertyType propertyType) { + this.propertyType = propertyType; + return self(); + } + + /** + * @param modifications the modifications to set + * @return self + */ + public ModifyAccountPropertyTransactionBuilder modifications(List> modifications) { + this.modifications = modifications; + return self(); + } + + // ------------------------------------- getters ---------------------------------------------// + + /** + * @return the propertyType + */ + public AccountPropertyType getPropertyType() { + return propertyType; + } + + /** + * @return the modifications + */ + public List> getModifications() { + return modifications; + } + + // -------------------------------------- convenience --------------------------------------------// + +} diff --git a/src/main/java/io/proximax/sdk/model/transaction/builder/ModifyContractTransactionBuilder.java b/src/main/java/io/proximax/sdk/model/transaction/builder/ModifyContractTransactionBuilder.java new file mode 100644 index 00000000..ab5f0c68 --- /dev/null +++ b/src/main/java/io/proximax/sdk/model/transaction/builder/ModifyContractTransactionBuilder.java @@ -0,0 +1,140 @@ +/* + * Copyright 2019 ProximaX Limited. All rights reserved. + * Use of this source code is governed by the Apache 2.0 + * license that can be found in the LICENSE file. + */ +package io.proximax.sdk.model.transaction.builder; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import io.proximax.sdk.model.transaction.ModifyContractTransaction; +import io.proximax.sdk.model.transaction.MultisigCosignatoryModification; +import io.proximax.sdk.model.transaction.TransactionType; +import io.proximax.sdk.model.transaction.TransactionVersion; + +/** + * builder for {@link ModifyContractTransaction} + */ +public class ModifyContractTransactionBuilder + extends TransactionBuilder { + + private BigInteger durationDelta; + private String contentHash; + private List customersModifications; + private List executorsModifications; + private List verifiersModifications; + + public ModifyContractTransactionBuilder() { + super(TransactionType.MODIFY_CONTRACT, TransactionVersion.MODIFY_CONTRACT.getValue()); + // defaults + customersModifications = new ArrayList<>(); + executorsModifications = new ArrayList<>(); + verifiersModifications = new ArrayList<>(); + } + + @Override + protected ModifyContractTransactionBuilder self() { + return this; + } + + @Override + public ModifyContractTransaction build() { + // use or calculate maxFee + BigInteger maxFee = getMaxFee() + .orElseGet(() -> getMaxFeeCalculation(ModifyContractTransaction.calculatePayloadSize(getContentHash(), + getCustomersModifications().size(), + getExecutorsModifications().size(), + getVerifiersModifications().size()))); + // create transaction instance + return new ModifyContractTransaction(getNetworkType(), getVersion(), getDeadline(), maxFee, getSignature(), + getSigner(), getTransactionInfo(), getDurationDelta(), getContentHash(), getCustomersModifications(), + getExecutorsModifications(), getVerifiersModifications()); + } + + // ------------------------------------- setters ---------------------------------------------// + + public ModifyContractTransactionBuilder durationDelta(BigInteger durationDelta) { + this.durationDelta = durationDelta; + return self(); + } + + public ModifyContractTransactionBuilder contentHash(String contentHash) { + this.contentHash = contentHash; + return self(); + } + + public ModifyContractTransactionBuilder customersModifications( + List customersModifications) { + this.customersModifications = customersModifications; + return self(); + } + + public ModifyContractTransactionBuilder executorsModifications( + List executorsModifications) { + this.executorsModifications = executorsModifications; + return self(); + } + + public ModifyContractTransactionBuilder verifiersModifications( + List verifiersModifications) { + this.verifiersModifications = verifiersModifications; + return self(); + } + + // -------------------------------------- getters --------------------------------------------// + + /** + * @return the durationDelta + */ + public BigInteger getDurationDelta() { + return durationDelta; + } + + /** + * @return the contentHash + */ + public String getContentHash() { + return contentHash; + } + + /** + * @return the customersModifications + */ + public List getCustomersModifications() { + return customersModifications; + } + + /** + * @return the executorsModifications + */ + public List getExecutorsModifications() { + return executorsModifications; + } + + /** + * @return the verifiersModifications + */ + public List getVerifiersModifications() { + return verifiersModifications; + } + + // -------------------------------------- convenience --------------------------------------------// + + public ModifyContractTransactionBuilder customersModifications( + MultisigCosignatoryModification... customersModifications) { + return customersModifications(Arrays.asList(customersModifications)); + } + + public ModifyContractTransactionBuilder executorsModifications( + MultisigCosignatoryModification... executorsModifications) { + return executorsModifications(Arrays.asList(executorsModifications)); + } + + public ModifyContractTransactionBuilder verifiersModifications( + MultisigCosignatoryModification... verifiersModifications) { + return verifiersModifications(Arrays.asList(verifiersModifications)); + } +} diff --git a/src/main/java/io/proximax/sdk/model/transaction/builder/ModifyMetadataTransactionBuilder.java b/src/main/java/io/proximax/sdk/model/transaction/builder/ModifyMetadataTransactionBuilder.java new file mode 100644 index 00000000..5d25bf24 --- /dev/null +++ b/src/main/java/io/proximax/sdk/model/transaction/builder/ModifyMetadataTransactionBuilder.java @@ -0,0 +1,159 @@ +/* + * Copyright 2019 ProximaX Limited. All rights reserved. + * Use of this source code is governed by the Apache 2.0 + * license that can be found in the LICENSE file. + */ +package io.proximax.sdk.model.transaction.builder; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Optional; + +import io.proximax.sdk.model.account.Address; +import io.proximax.sdk.model.metadata.MetadataModification; +import io.proximax.sdk.model.metadata.MetadataType; +import io.proximax.sdk.model.mosaic.MosaicId; +import io.proximax.sdk.model.namespace.NamespaceId; +import io.proximax.sdk.model.transaction.ModifyMetadataTransaction; +import io.proximax.sdk.model.transaction.TransactionType; +import io.proximax.sdk.model.transaction.TransactionVersion; +import io.proximax.sdk.model.transaction.UInt64Id; + +/** + * builder for {@link ModifyMetadataTransaction} + */ +public class ModifyMetadataTransactionBuilder + extends TransactionBuilder { + + private MetadataType metadataType; + private Optional metadataId; + private Optional
address; + private List modifications; + + public ModifyMetadataTransactionBuilder() { + super(null, TransactionVersion.METADATA_MODIFICATION.getValue()); + // defaults + metadataId = Optional.empty(); + address = Optional.empty(); + modifications = new ArrayList<>(); + } + + @Override + protected ModifyMetadataTransactionBuilder self() { + return this; + } + + @Override + public ModifyMetadataTransaction build() { + // use or calculate maxFee + BigInteger maxFee = getMaxFee().orElseGet(() -> getMaxFeeCalculation( + ModifyMetadataTransaction.calculatePayloadSize(getAddress().isPresent(), getModifications()))); + // create transaction instance + return new ModifyMetadataTransaction(getType(), getNetworkType(), getVersion(), getDeadline(), maxFee, + getSignature(), getSigner(), getTransactionInfo(), getMetadataType(), getMetadataId(), getAddress(), + getModifications()); + } + + // ------------------------------------- setters ---------------------------------------------// + + /** + * specify address for which the metadata modification will happen + * + * @param address the address + * @return self + */ + public ModifyMetadataTransactionBuilder metadataId(Address address) { + this.address = Optional.of(address); + return self(); + } + + /** + * specify address for which the metadata modification will happen + * + * @param id mosaic ID or namespace ID + * @return self + */ + public ModifyMetadataTransactionBuilder metadataId(UInt64Id id) { + this.metadataId = Optional.of(id); + return self(); + } + + /** + * specify the metadata type + * + * @param type the type of metadata + * @return self + */ + public ModifyMetadataTransactionBuilder metadataType(MetadataType type) { + this.metadataType = type; + return self(); + } + + /** + * set metadata modifications + * + * @param modifications the modifications + * @return self + */ + public ModifyMetadataTransactionBuilder modifications(List modifications) { + this.modifications = modifications; + return self(); + } + + // -------------------------------------- getters --------------------------------------------// + + /** + * @return the metadataType + */ + public MetadataType getMetadataType() { + return metadataType; + } + + /** + * @return the metadataId + */ + public Optional getMetadataId() { + return metadataId; + } + + /** + * @return the address + */ + public Optional
getAddress() { + return address; + } + + /** + * @return the modifications + */ + public List getModifications() { + return modifications; + } + + // -------------------------------------- convenience --------------------------------------------// + + public ModifyMetadataTransactionBuilder forAddress(Address address) { + return type(TransactionType.MODIFY_ADDRESS_METADATA).metadataType(MetadataType.ADDRESS).metadataId(address); + } + + public ModifyMetadataTransactionBuilder forMosaic(MosaicId mosaicId) { + return type(TransactionType.MODIFY_MOSAIC_METADATA).metadataType(MetadataType.MOSAIC).metadataId(mosaicId); + } + + public ModifyMetadataTransactionBuilder forNamespace(NamespaceId namespaceId) { + return type(TransactionType.MODIFY_NAMESPACE_METADATA).metadataType(MetadataType.NAMESPACE) + .metadataId(namespaceId); + } + + /** + * set metadata modifications + * + * @param modifications the modifications + * @return self + */ + public ModifyMetadataTransactionBuilder modifications(MetadataModification ... modifications) { + return modifications(Arrays.asList(modifications)); + } +} diff --git a/src/main/java/io/proximax/sdk/model/transaction/builder/ModifyMultisigAccountTransactionBuilder.java b/src/main/java/io/proximax/sdk/model/transaction/builder/ModifyMultisigAccountTransactionBuilder.java new file mode 100644 index 00000000..c9cbd89c --- /dev/null +++ b/src/main/java/io/proximax/sdk/model/transaction/builder/ModifyMultisigAccountTransactionBuilder.java @@ -0,0 +1,120 @@ +/* + * Copyright 2019 ProximaX Limited. All rights reserved. + * Use of this source code is governed by the Apache 2.0 + * license that can be found in the LICENSE file. + */ +package io.proximax.sdk.model.transaction.builder; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import io.proximax.sdk.model.transaction.ModifyMultisigAccountTransaction; +import io.proximax.sdk.model.transaction.MultisigCosignatoryModification; +import io.proximax.sdk.model.transaction.TransactionType; +import io.proximax.sdk.model.transaction.TransactionVersion; + +/** + * builder for {@link ModifyMultisigAccountTransaction} + */ +public class ModifyMultisigAccountTransactionBuilder + extends TransactionBuilder { + + private int minApprovalDelta; + private int minRemovalDelta; + private List modifications; + + public ModifyMultisigAccountTransactionBuilder() { + super(TransactionType.MODIFY_MULTISIG_ACCOUNT, TransactionVersion.MODIFY_MULTISIG_ACCOUNT.getValue()); + // defaults + minApprovalDelta = 0; + minRemovalDelta = 0; + modifications = new ArrayList<>(); + } + + @Override + protected ModifyMultisigAccountTransactionBuilder self() { + return this; + } + + @Override + public ModifyMultisigAccountTransaction build() { + // use or calculate maxFee + BigInteger maxFee = getMaxFee() + .orElseGet(() -> getMaxFeeCalculation(ModifyMultisigAccountTransaction.calculatePayloadSize(getModifications().size()))); + // create transaction instance + return new ModifyMultisigAccountTransaction(getNetworkType(), getVersion(), getDeadline(), maxFee, getSignature(), + getSigner(), getTransactionInfo(), getMinApprovalDelta(), getMinRemovalDelta(), getModifications()); + } + + // ------------------------------------- setters ---------------------------------------------// + + /** + * change in minimum number of cosignatory approvals of transactions + * + * @param minApprovalDelta change in min approvals + * @return self + */ + public ModifyMultisigAccountTransactionBuilder minApprovalDelta(int minApprovalDelta) { + this.minApprovalDelta = minApprovalDelta; + return self(); + } + + /** + * change in minimum number of cosignatory approvals for removal of cosignatory + * @param minRemovalDelta change in minimum removals + * @return self + */ + public ModifyMultisigAccountTransactionBuilder minRemovalDelta(int minRemovalDelta) { + this.minRemovalDelta = minRemovalDelta; + return self(); + } + + /** + * changes in list of cosignatories for the account + * + * @param modifications list of changes + * @return self + */ + public ModifyMultisigAccountTransactionBuilder modifications(List modifications) { + this.modifications = modifications; + return self(); + } + + // -------------------------------------- getters --------------------------------------------// + + /** + * @return the minApprovalDelta + */ + public int getMinApprovalDelta() { + return minApprovalDelta; + } + + /** + * @return the minRemovalDelta + */ + public int getMinRemovalDelta() { + return minRemovalDelta; + } + + /** + * @return the modifications + */ + public List getModifications() { + return modifications; + } + + // -------------------------------------- convenience --------------------------------------------// + + /** + * changes in list of cosignatories for the account + * + * @param modifications changes + * @return self + */ + public ModifyMultisigAccountTransactionBuilder modifications(MultisigCosignatoryModification ... modifications) { + return modifications(Arrays.asList(modifications)); + } + +} diff --git a/src/main/java/io/proximax/sdk/model/transaction/builder/MosaicDefinitionTransactionBuilder.java b/src/main/java/io/proximax/sdk/model/transaction/builder/MosaicDefinitionTransactionBuilder.java new file mode 100644 index 00000000..38923ed1 --- /dev/null +++ b/src/main/java/io/proximax/sdk/model/transaction/builder/MosaicDefinitionTransactionBuilder.java @@ -0,0 +1,107 @@ +/* + * Copyright 2019 ProximaX Limited. All rights reserved. + * Use of this source code is governed by the Apache 2.0 + * license that can be found in the LICENSE file. + */ +package io.proximax.sdk.model.transaction.builder; + +import java.math.BigInteger; + +import io.proximax.sdk.model.mosaic.MosaicId; +import io.proximax.sdk.model.mosaic.MosaicNonce; +import io.proximax.sdk.model.mosaic.MosaicProperties; +import io.proximax.sdk.model.transaction.MosaicDefinitionTransaction; +import io.proximax.sdk.model.transaction.TransactionType; +import io.proximax.sdk.model.transaction.TransactionVersion; + +/** + * builder for {@link MosaicDefinitionTransaction} + */ +public class MosaicDefinitionTransactionBuilder + extends TransactionBuilder { + + private MosaicNonce nonce; + private MosaicId mosaicId; + private MosaicProperties mosaicProperties; + + public MosaicDefinitionTransactionBuilder() { + super(TransactionType.MOSAIC_DEFINITION, TransactionVersion.MOSAIC_DEFINITION.getValue()); + // defaults + } + + @Override + protected MosaicDefinitionTransactionBuilder self() { + return this; + } + + @Override + public MosaicDefinitionTransaction build() { + // use or calculate maxFee + BigInteger maxFee = getMaxFee().orElseGet(() -> getMaxFeeCalculation( + MosaicDefinitionTransaction.calculatePayloadSize(getMosaicProperties().getDuration().isPresent() ? 1 : 0))); + // create transaction instance + return new MosaicDefinitionTransaction(getNetworkType(), getVersion(), getDeadline(), maxFee, getSignature(), + getSigner(), getTransactionInfo(), getNonce(), getMosaicId(), getMosaicProperties()); + } + + // -------------------------------------- setters --------------------------------------------// + + /** + * define nonce. Nonce is random number ensuring the uniqueness of the mosaic ID + * + * @param nonce the nonce + * @return self + */ + public MosaicDefinitionTransactionBuilder nonce(MosaicNonce nonce) { + this.nonce = nonce; + return self(); + } + + /** + * define mosaic ID + * + * @param mosaicId desired mosaic ID + * @return self + */ + public MosaicDefinitionTransactionBuilder mosaicId(MosaicId mosaicId) { + this.mosaicId = mosaicId; + return self(); + } + + /** + * define mosaic properties + * + * @param mosaicProperties the mosaic properties + * @return self + */ + public MosaicDefinitionTransactionBuilder mosaicProperties(MosaicProperties mosaicProperties) { + this.mosaicProperties = mosaicProperties; + return self(); + } + + // -------------------------------------- getters --------------------------------------------// + + /** + * @return the nonce + */ + public MosaicNonce getNonce() { + return nonce; + } + + /** + * @return the mosaicId + */ + public MosaicId getMosaicId() { + return mosaicId; + } + + /** + * @return the mosaicProperties + */ + public MosaicProperties getMosaicProperties() { + return mosaicProperties; + } + + // -------------------------------------- convenience --------------------------------------------// + +} \ No newline at end of file diff --git a/src/main/java/io/proximax/sdk/model/transaction/builder/MosaicSupplyChangeTransactionBuilder.java b/src/main/java/io/proximax/sdk/model/transaction/builder/MosaicSupplyChangeTransactionBuilder.java new file mode 100644 index 00000000..e96bbc24 --- /dev/null +++ b/src/main/java/io/proximax/sdk/model/transaction/builder/MosaicSupplyChangeTransactionBuilder.java @@ -0,0 +1,128 @@ +/* + * Copyright 2019 ProximaX Limited. All rights reserved. + * Use of this source code is governed by the Apache 2.0 + * license that can be found in the LICENSE file. + */ +package io.proximax.sdk.model.transaction.builder; + +import java.math.BigInteger; + +import io.proximax.sdk.model.mosaic.MosaicId; +import io.proximax.sdk.model.mosaic.MosaicSupplyType; +import io.proximax.sdk.model.transaction.MosaicSupplyChangeTransaction; +import io.proximax.sdk.model.transaction.TransactionType; +import io.proximax.sdk.model.transaction.TransactionVersion; + +/** + * builder for {@link MosaicSupplyChangeTransaction} + */ +public class MosaicSupplyChangeTransactionBuilder + extends TransactionBuilder { + + private MosaicId mosaicId; + private MosaicSupplyType mosaicSupplyType; + private BigInteger delta; + + public MosaicSupplyChangeTransactionBuilder() { + super(TransactionType.MOSAIC_SUPPLY_CHANGE, TransactionVersion.MOSAIC_SUPPLY_CHANGE.getValue()); + } + + @Override + protected MosaicSupplyChangeTransactionBuilder self() { + return this; + } + + @Override + public MosaicSupplyChangeTransaction build() { + // use or calculate maxFee + BigInteger maxFee = getMaxFee() + .orElseGet(() -> getMaxFeeCalculation(MosaicSupplyChangeTransaction.calculatePayloadSize())); + // create transaction instance + return new MosaicSupplyChangeTransaction(getNetworkType(), getVersion(), getDeadline(), maxFee, getSignature(), + getSigner(), getTransactionInfo(), getMosaicId(), getMosaicSupplyType(), getDelta()); + } + + // ------------------------------------- setters ---------------------------------------------// + + /** + * define mosaic ID to change supply for + * + * @param mosaicId the mosaic ID + * @return self + */ + public MosaicSupplyChangeTransactionBuilder mosaicId(MosaicId mosaicId) { + this.mosaicId = mosaicId; + return self(); + } + + /** + * define type of the change to the mosaic supply + * + * @param mosaicSupplyType the change type + * @return self + */ + public MosaicSupplyChangeTransactionBuilder mosaicSupplyType(MosaicSupplyType mosaicSupplyType) { + this.mosaicSupplyType = mosaicSupplyType; + return self(); + } + + /** + * define the change to the supply as delta + * + * @param delta the delta from current state + * @return self + */ + public MosaicSupplyChangeTransactionBuilder delta(BigInteger delta) { + this.delta = delta; + return self(); + } + + // -------------------------------------- getters --------------------------------------------// + + /** + * @return the mosaicId + */ + public MosaicId getMosaicId() { + return mosaicId; + } + + /** + * @return the mosaicSupplyType + */ + public MosaicSupplyType getMosaicSupplyType() { + return mosaicSupplyType; + } + + /** + * @return the delta + */ + public BigInteger getDelta() { + return delta; + } + + // -------------------------------------- convenience --------------------------------------------// + + /** + * increase supply for specified mosaic ID + * + * @param mosaicId the mosaic ID to increase supply for + * @return self + */ + public MosaicSupplyChangeTransactionBuilder increaseSupplyFor(MosaicId mosaicId) { + mosaicSupplyType(MosaicSupplyType.INCREASE); + mosaicId(mosaicId); + return self(); + } + + /** + * decrease supply for specified mosaic ID + * + * @param mosaicId the mosaic ID to decrease supply for + * @return self + */ + public MosaicSupplyChangeTransactionBuilder decreaseSupplyFor(MosaicId mosaicId) { + mosaicSupplyType(MosaicSupplyType.DECREASE); + mosaicId(mosaicId); + return self(); + } +} diff --git a/src/main/java/io/proximax/sdk/model/transaction/builder/RegisterNamespaceTransactionBuilder.java b/src/main/java/io/proximax/sdk/model/transaction/builder/RegisterNamespaceTransactionBuilder.java new file mode 100644 index 00000000..7ac20ecb --- /dev/null +++ b/src/main/java/io/proximax/sdk/model/transaction/builder/RegisterNamespaceTransactionBuilder.java @@ -0,0 +1,176 @@ +/* + * Copyright 2019 ProximaX Limited. All rights reserved. + * Use of this source code is governed by the Apache 2.0 + * license that can be found in the LICENSE file. + */ +package io.proximax.sdk.model.transaction.builder; + +import java.math.BigInteger; +import java.util.Optional; + +import io.proximax.sdk.model.namespace.NamespaceId; +import io.proximax.sdk.model.namespace.NamespaceType; +import io.proximax.sdk.model.transaction.IdGenerator; +import io.proximax.sdk.model.transaction.RegisterNamespaceTransaction; +import io.proximax.sdk.model.transaction.TransactionType; +import io.proximax.sdk.model.transaction.TransactionVersion; + +/** + * builder for {@link RegisterNamespaceTransaction} + */ +public class RegisterNamespaceTransactionBuilder + extends TransactionBuilder { + + private String namespaceName; + private NamespaceId namespaceId; + private Optional duration; + private Optional parentId; + private NamespaceType namespaceType; + + public RegisterNamespaceTransactionBuilder() { + super(TransactionType.REGISTER_NAMESPACE, TransactionVersion.REGISTER_NAMESPACE.getValue()); + // defaults + duration = Optional.empty(); + parentId = Optional.empty(); + } + + @Override + protected RegisterNamespaceTransactionBuilder self() { + return this; + } + + @Override + public RegisterNamespaceTransaction build() { + // use or calculate maxFee + BigInteger maxFee = getMaxFee().orElseGet( + () -> getMaxFeeCalculation(RegisterNamespaceTransaction.calculatePayloadSize(getNamespaceName().length()))); + // create transaction instance + return new RegisterNamespaceTransaction(getNetworkType(), getVersion(), getDeadline(), maxFee, getSignature(), + getSigner(), getTransactionInfo(), getNamespaceName(), getNamespaceId(), getDuration(), getParentId(), + getNamespaceType()); + } + + // -------------------------------------- setters --------------------------------------------// + + /** + * name of the namespace to register + * + * @param namespaceName the name + * @return self + */ + public RegisterNamespaceTransactionBuilder namespaceName(String namespaceName) { + this.namespaceName = namespaceName; + return self(); + } + + /** + * ID of the namespace to register + * + * @param namespaceId the id + * @return self + */ + public RegisterNamespaceTransactionBuilder namespaceId(NamespaceId namespaceId) { + this.namespaceId = namespaceId; + return self(); + } + + /** + * duration of the namespace existence in block count + * + * @param duration number of blocks + * @return self + */ + public RegisterNamespaceTransactionBuilder duration(BigInteger duration) { + this.duration = Optional.of(duration); + return self(); + } + + /** + * if registering sub-namespace then define parent + * + * @param parentId parent namespace of this sub-namespace + * @return self + */ + public RegisterNamespaceTransactionBuilder parentId(NamespaceId parentId) { + this.parentId = Optional.of(parentId); + return self(); + } + + /** + * type of the namespace - root/sub + * + * @param namespaceType namespace type + * @return self + */ + public RegisterNamespaceTransactionBuilder namespaceType(NamespaceType namespaceType) { + this.namespaceType = namespaceType; + return self(); + } + + // -------------------------------------- getters --------------------------------------------// + + /** + * @return the namespaceName + */ + public String getNamespaceName() { + return namespaceName; + } + + /** + * @return the namespaceId + */ + public NamespaceId getNamespaceId() { + return namespaceId; + } + + /** + * @return the duration + */ + public Optional getDuration() { + return duration; + } + + /** + * @return the parentId + */ + public Optional getParentId() { + return parentId; + } + + /** + * @return the namespaceType + */ + public NamespaceType getNamespaceType() { + return namespaceType; + } + + // -------------------------------------- convenience --------------------------------------------// + + /** + * create root namespace + * + * @param name name of the namespace + * @return self + */ + public RegisterNamespaceTransactionBuilder rootNamespace(String name) { + namespaceType(NamespaceType.RootNamespace); + namespaceName(name); + namespaceId(new NamespaceId(name)); + return self(); + } + + /** + * create sub-namespace + * + * @param parentId parent of the new sub-namespace + * @param name name of the new sub-namespace + * @return self + */ + public RegisterNamespaceTransactionBuilder subNamespace(NamespaceId parentId, String name) { + namespaceType(NamespaceType.SubNamespace); + parentId(parentId); + namespaceName(name); + namespaceId(new NamespaceId(IdGenerator.generateSubNamespaceIdFromParentId(parentId.getId(), name))); + return self(); + } +} \ No newline at end of file diff --git a/src/main/java/io/proximax/sdk/model/transaction/builder/SecretLockTransactionBuilder.java b/src/main/java/io/proximax/sdk/model/transaction/builder/SecretLockTransactionBuilder.java new file mode 100644 index 00000000..0683a616 --- /dev/null +++ b/src/main/java/io/proximax/sdk/model/transaction/builder/SecretLockTransactionBuilder.java @@ -0,0 +1,154 @@ +/* + * Copyright 2019 ProximaX Limited. All rights reserved. + * Use of this source code is governed by the Apache 2.0 + * license that can be found in the LICENSE file. + */ +package io.proximax.sdk.model.transaction.builder; + +import java.math.BigInteger; + +import io.proximax.sdk.model.account.Address; +import io.proximax.sdk.model.mosaic.Mosaic; +import io.proximax.sdk.model.transaction.HashType; +import io.proximax.sdk.model.transaction.SecretLockTransaction; +import io.proximax.sdk.model.transaction.TransactionType; +import io.proximax.sdk.model.transaction.TransactionVersion; + +/** + * builder for {@link SecretLockTransaction} + */ +public class SecretLockTransactionBuilder + extends TransactionBuilder { + + private Mosaic mosaic; + private BigInteger duration; + private HashType hashType; + private String secret; + private Address recipient; + + public SecretLockTransactionBuilder() { + super(TransactionType.SECRET_LOCK, TransactionVersion.SECRET_LOCK.getValue()); + } + + @Override + protected SecretLockTransactionBuilder self() { + return this; + } + + @Override + public SecretLockTransaction build() { + // use or calculate maxFee + BigInteger maxFee = getMaxFee() + .orElseGet(() -> getMaxFeeCalculation(SecretLockTransaction.calculatePayloadSize())); + // create transaction instance + return new SecretLockTransaction(getNetworkType(), getVersion(), getDeadline(), maxFee, getSignature(), + getSigner(), getTransactionInfo(), getMosaic(), getDuration(), getHashType(), getSecret(), getRecipient()); + } + + // ------------------------------------- setters ---------------------------------------------// + + /** + * mosaic amount to lock + * + * @param mosaic locked mosaic + * @return self + */ + public SecretLockTransactionBuilder mosaic(Mosaic mosaic) { + this.mosaic = mosaic; + return self(); + } + + /** + * duration of the lock in number of blocks + * + * @param duration number of blocks + * @return self + */ + public SecretLockTransactionBuilder duration(BigInteger duration) { + this.duration = duration; + return self(); + } + + /** + * type of used hashing function + * + * @param hashType hash function + * @return self + */ + public SecretLockTransactionBuilder hashType(HashType hashType) { + this.hashType = hashType; + return self(); + } + + /** + * lock secret + * + * @param secret the secret + * @return self + */ + public SecretLockTransactionBuilder secret(String secret) { + this.secret = secret; + return self(); + } + + /** + * recipient of the locked mosaic + * + * @param recipient the recipient + * @return self + */ + public SecretLockTransactionBuilder recipient(Address recipient) { + this.recipient = recipient; + return self(); + } + + // -------------------------------------- getters --------------------------------------------// + + /** + * @return the mosaic + */ + public Mosaic getMosaic() { + return mosaic; + } + + /** + * @return the duration + */ + public BigInteger getDuration() { + return duration; + } + + /** + * @return the hashType + */ + public HashType getHashType() { + return hashType; + } + + /** + * @return the secret + */ + public String getSecret() { + return secret; + } + + /** + * @return the recipient + */ + public Address getRecipient() { + return recipient; + } + + // -------------------------------------- convenience --------------------------------------------// + + /** + * specify lock secret along with the corresponding hash type + * + * @param hashType hashing function used to hash proof to create secret + * @param secret the secret + * @return self + */ + public SecretLockTransactionBuilder secret(HashType hashType, String secret) { + return hashType(hashType).secret(secret); + } +} diff --git a/src/main/java/io/proximax/sdk/model/transaction/builder/SecretProofTransactionBuilder.java b/src/main/java/io/proximax/sdk/model/transaction/builder/SecretProofTransactionBuilder.java new file mode 100644 index 00000000..7646183a --- /dev/null +++ b/src/main/java/io/proximax/sdk/model/transaction/builder/SecretProofTransactionBuilder.java @@ -0,0 +1,134 @@ +/* + * Copyright 2019 ProximaX Limited. All rights reserved. + * Use of this source code is governed by the Apache 2.0 + * license that can be found in the LICENSE file. + */ +package io.proximax.sdk.model.transaction.builder; + +import java.math.BigInteger; + +import io.proximax.sdk.model.transaction.HashType; +import io.proximax.sdk.model.transaction.Recipient; +import io.proximax.sdk.model.transaction.SecretProofTransaction; +import io.proximax.sdk.model.transaction.TransactionType; +import io.proximax.sdk.model.transaction.TransactionVersion; + +/** + * builder for {@link SecretProofTransaction} + */ +public class SecretProofTransactionBuilder + extends TransactionBuilder { + + private HashType hashType; + private String secret; + private String proof; + private Recipient recipient; + + public SecretProofTransactionBuilder() { + super(TransactionType.SECRET_PROOF, TransactionVersion.SECRET_PROOF.getValue()); + } + + @Override + protected SecretProofTransactionBuilder self() { + return this; + } + + @Override + public SecretProofTransaction build() { + // use or calculate maxFee + BigInteger maxFee = getMaxFee().orElseGet( + () -> getMaxFeeCalculation(SecretProofTransaction.calculatePayloadSize(getRecipient(), getProof()))); + // create transaction instance + return new SecretProofTransaction(getNetworkType(), getVersion(), getDeadline(), maxFee, getSignature(), + getSigner(), getTransactionInfo(), getHashType(), getSecret(), getProof(), getRecipient()); + } + + // ------------------------------------- setters ---------------------------------------------// + + /** + * type of used hashing function + * + * @param hashType hash function + * @return self + */ + public SecretProofTransactionBuilder hashType(HashType hashType) { + this.hashType = hashType; + return self(); + } + + /** + * lock secret + * + * @param secret the secret + * @return self + */ + public SecretProofTransactionBuilder secret(String secret) { + this.secret = secret; + return self(); + } + + /** + * recipient of the locked mosaic + * + * @param recipient the recipient + * @return self + */ + public SecretProofTransactionBuilder recipient(Recipient recipient) { + this.recipient = recipient; + return self(); + } + + /** + * proof of the secret + * + * @param proof the proof to set + * @return self + */ + public SecretProofTransactionBuilder proof(String proof) { + this.proof = proof; + return self(); + } + + // -------------------------------------- getters --------------------------------------------// + + /** + * @return the hashType + */ + public HashType getHashType() { + return hashType; + } + + /** + * @return the secret + */ + public String getSecret() { + return secret; + } + + /** + * @return the recipient + */ + public Recipient getRecipient() { + return recipient; + } + + /** + * @return the proof + */ + public String getProof() { + return proof; + } + + // -------------------------------------- convenience --------------------------------------------// + + /** + * specify lock secret along with the corresponding hash type + * + * @param hashType hashing function used to hash proof to create secret + * @param secret the secret + * @return self + */ + public SecretProofTransactionBuilder secret(HashType hashType, String secret) { + return hashType(hashType).secret(secret); + } +} diff --git a/src/main/java/io/proximax/sdk/model/transaction/builder/TransactionBuilder.java b/src/main/java/io/proximax/sdk/model/transaction/builder/TransactionBuilder.java new file mode 100644 index 00000000..f2b240be --- /dev/null +++ b/src/main/java/io/proximax/sdk/model/transaction/builder/TransactionBuilder.java @@ -0,0 +1,230 @@ +/* + * Copyright 2019 ProximaX Limited. All rights reserved. + * Use of this source code is governed by the Apache 2.0 + * license that can be found in the LICENSE file. + */ +package io.proximax.sdk.model.transaction.builder; + +import java.math.BigInteger; +import java.util.Optional; + +import io.proximax.sdk.FeeCalculationStrategy; +import io.proximax.sdk.model.account.PublicAccount; +import io.proximax.sdk.model.blockchain.NetworkType; +import io.proximax.sdk.model.transaction.DeadlineRaw; +import io.proximax.sdk.model.transaction.Transaction; +import io.proximax.sdk.model.transaction.TransactionDeadline; +import io.proximax.sdk.model.transaction.TransactionInfo; +import io.proximax.sdk.model.transaction.TransactionType; + +/** + * Transaction builder is base class implementing builder pattern to construct instance of transaction. It is bases of + * specialized transaction builders for all types of transactions + */ +public abstract class TransactionBuilder, T extends Transaction> { + + private TransactionType type; + private Integer version; + private NetworkType networkType; + private Optional maxFee; + private Optional signature; + private Optional signer; + private Optional transactionInfo; + private Optional feeCalculationStrategy; + // fixed deadline + private Optional deadline; + // duration to generate deadline from the time of call to build + private Optional deadlineMillis; + + /** + * @param type + * @param version + */ + public TransactionBuilder(TransactionType type, Integer version) { + this.type = type; + this.version = version; + // initialize defaults + maxFee = Optional.empty(); + signature = Optional.empty(); + signer = Optional.empty(); + transactionInfo = Optional.empty(); + feeCalculationStrategy = Optional.empty(); + deadline = Optional.empty(); + deadlineMillis = Optional.empty(); + } + + /** + * every builder needs to return instance of itself so that type-safe builder can be constructed + * + * @return reference to itself + */ + protected abstract B self(); + + /** + * every builder needs to provide build method that creates instance of the transaction + * + * @return the instance of the transaction + */ + public abstract T build(); + + /** + * calculate maxFee using fee calculation strategy or return 0 maxFee if no strategy was provided + * + * @param transactionPayloadSize size of transaction in bytes excluding header + * @return the maxFee + */ + protected BigInteger getMaxFeeCalculation(int transactionPayloadSize) { + return feeCalculationStrategy.orElse(FeeCalculationStrategy.ZERO).calculateFee(Transaction.HEADER_SIZE + transactionPayloadSize); + } + + // ----------------------------------------- setters --------------------------------------// + + /** + * @param type the type to set + */ + public B type(TransactionType type) { + this.type = type; + return self(); + } + + /** + * @param version the version to set + */ + public B version(Integer version) { + this.version = version; + return self(); + } + + /** + * @param networkType the networkType to set + */ + public B networkType(NetworkType networkType) { + this.networkType = networkType; + return self(); + } + + /** + * @param deadline the fixed deadline to use + */ + public B deadline(TransactionDeadline deadline) { + this.deadline = Optional.of(deadline); + return self(); + } + + /** + * @param deadlineMillis the deadline specified as duration in milliseconds after {@link TransactionBuilder#build()} + * is invoked + */ + public B deadlineDuration(BigInteger deadlineMillis) { + this.deadlineMillis = Optional.of(deadlineMillis); + return self(); + } + + /** + * @param maxFee the maxFee to set + */ + public B maxFee(BigInteger maxFee) { + this.maxFee = Optional.of(maxFee); + return self(); + } + + /** + * @param signature the signature to set + */ + public B signature(String signature) { + this.signature = Optional.of(signature); + return self(); + } + + /** + * @param signer the signer to set + */ + public B signer(PublicAccount signer) { + this.signer = Optional.of(signer); + return self(); + } + + /** + * @param transactionInfo the transactionInfo to set + */ + public B transactionInfo(TransactionInfo transactionInfo) { + this.transactionInfo = Optional.of(transactionInfo); + return self(); + } + + /** + * @param feeCalculationStrategy the feeCalculationStrategy to set + */ + public B feeCalculationStrategy(FeeCalculationStrategy feeCalculationStrategy) { + this.feeCalculationStrategy = Optional.of(feeCalculationStrategy); + return self(); + } + + // -------------------------------------- getters ---------------------------------------// + + /** + * @return the type + */ + public TransactionType getType() { + return type; + } + + /** + * @return the version + */ + public Integer getVersion() { + return version; + } + + /** + * @return the networkType + */ + public NetworkType getNetworkType() { + return networkType; + } + + /** + * @return the maxFee + */ + public Optional getMaxFee() { + return maxFee; + } + + /** + * @return the signature + */ + public Optional getSignature() { + return signature; + } + + /** + * @return the signer + */ + public Optional getSigner() { + return signer; + } + + /** + * @return the transactionInfo + */ + public Optional getTransactionInfo() { + return transactionInfo; + } + + /** + * @return the feeCalculationStrategy + */ + public Optional getFeeCalculationStrategy() { + return feeCalculationStrategy; + } + + /** + * @return the deadline + */ + public TransactionDeadline getDeadline() { + final Optional duration = deadlineMillis; + return deadline.orElseGet(() -> DeadlineRaw.startNow( + duration.orElseThrow(() -> new IllegalStateException("fixed or millis deadline needs to be specified")))); + } + +} diff --git a/src/main/java/io/proximax/sdk/model/transaction/builder/TransactionBuilderFactory.java b/src/main/java/io/proximax/sdk/model/transaction/builder/TransactionBuilderFactory.java new file mode 100644 index 00000000..8b561605 --- /dev/null +++ b/src/main/java/io/proximax/sdk/model/transaction/builder/TransactionBuilderFactory.java @@ -0,0 +1,307 @@ +/* + * Copyright 2019 ProximaX Limited. All rights reserved. + * Use of this source code is governed by the Apache 2.0 + * license that can be found in the LICENSE file. + */ +package io.proximax.sdk.model.transaction.builder; + +import java.math.BigInteger; + +import io.proximax.sdk.FeeCalculationStrategy; +import io.proximax.sdk.model.blockchain.NetworkType; + +/** + * Central factory to instantiate transaction builders for all transaction types + */ +public class TransactionBuilderFactory { + private NetworkType networkType; + private BigInteger deadlineMillis; + private FeeCalculationStrategy feeCalculationStrategy; + + /** + * @return the networkType + */ + public NetworkType getNetworkType() { + return networkType; + } + + /** + * @param networkType the networkType to set + * @return this factory + */ + public TransactionBuilderFactory setNetworkType(NetworkType networkType) { + this.networkType = networkType; + return this; + } + + /** + * @return the deadline in milliseconds + */ + public BigInteger getDeadlineMillis() { + return deadlineMillis; + } + + /** + * set default builder transaction deadline specified as milliseconds elapsed from the time when + * {@link TransactionBuilder#build()} is invoked + * + * @param deadlineMillis the deadlineMillis to set + * @return this factory + */ + public TransactionBuilderFactory setDeadlineMillis(BigInteger deadlineMillis) { + this.deadlineMillis = deadlineMillis; + return this; + } + + /** + * @return the default fee calculation strategy + */ + public FeeCalculationStrategy getFeeCalculationStrategy() { + return feeCalculationStrategy; + } + + /** + * @param feeCalculationStrategy the feeCalculationStrategy to set + * @return this factory + */ + public TransactionBuilderFactory setFeeCalculationStrategy(FeeCalculationStrategy feeCalculationStrategy) { + this.feeCalculationStrategy = feeCalculationStrategy; + return this; + } + + /** + * initialize default values for the builder + * + * @param builder + */ + protected void initDefaults(TransactionBuilder builder) { + builder.networkType(networkType); + if (feeCalculationStrategy != null) { + builder.feeCalculationStrategy(feeCalculationStrategy); + } + if (deadlineMillis != null) { + builder.deadlineDuration(deadlineMillis); + } + } + + // ------------------------------ retrieve specific transaction builders ------------------------------- // + /** + * create builder for transfer transaction + * + * @return the builder + */ + public TransferTransactionBuilder transfer() { + TransferTransactionBuilder builder = new TransferTransactionBuilder(); + initDefaults(builder); + return builder; + } + + /** + * create builder for account link transaction + * + * @return the builder + */ + public AccountLinkTransactionBuilder accountLink() { + AccountLinkTransactionBuilder builder = new AccountLinkTransactionBuilder(); + initDefaults(builder); + return builder; + } + + /** + * create builder for aggregate bonded transaction + * + * @return the builder + */ + public AggregateTransactionBuilder aggregateBonded() { + AggregateTransactionBuilder builder = AggregateTransactionBuilder.createBonded(); + initDefaults(builder); + return builder; + } + + /** + * create builder for aggregate complete transaction + * + * @return the builder + */ + public AggregateTransactionBuilder aggregateComplete() { + AggregateTransactionBuilder builder = AggregateTransactionBuilder.createComplete(); + initDefaults(builder); + return builder; + } + + /** + * create builder for mosaic alias transaction + * + * @return the builder + */ + public AliasTransactionBuilder aliasMosaic() { + AliasTransactionBuilder builder = AliasTransactionBuilder.createForMosaic(); + initDefaults(builder); + return builder; + } + + /** + * create builder for address alias transaction + * + * @return the builder + */ + public AliasTransactionBuilder aliasAddress() { + AliasTransactionBuilder builder = AliasTransactionBuilder.createForAddress(); + initDefaults(builder); + return builder; + } + + /** + * create builder for lock funds transaction + * + * @return the builder + */ + public LockFundsTransactionBuilder lockFunds() { + LockFundsTransactionBuilder builder = new LockFundsTransactionBuilder(); + initDefaults(builder); + return builder; + } + + /** + * create builder for register namespace transaction + * + * @return the builder + */ + public RegisterNamespaceTransactionBuilder registerNamespace() { + RegisterNamespaceTransactionBuilder builder = new RegisterNamespaceTransactionBuilder(); + initDefaults(builder); + return builder; + } + + /** + * create builder for mosaic definition transaction + * + * @return the builder + */ + public MosaicDefinitionTransactionBuilder mosaicDefinition() { + MosaicDefinitionTransactionBuilder builder = new MosaicDefinitionTransactionBuilder(); + initDefaults(builder); + return builder; + } + + /** + * create builder for mosaic supply change transaction + * + * @return the builder + */ + public MosaicSupplyChangeTransactionBuilder mosaicSupplyChange() { + MosaicSupplyChangeTransactionBuilder builder = new MosaicSupplyChangeTransactionBuilder(); + initDefaults(builder); + return builder; + } + + /** + * create builder for blockchain config transaction + * + * @return the builder + */ + public BlockchainConfigTransactionBuilder blockchainConfig() { + BlockchainConfigTransactionBuilder builder = new BlockchainConfigTransactionBuilder(); + initDefaults(builder); + return builder; + } + + /** + * create builder for blockchain upgrade transaction + * + * @return the builder + */ + public BlockchainUpgradeTransactionBuilder blockchainUpgrade() { + BlockchainUpgradeTransactionBuilder builder = new BlockchainUpgradeTransactionBuilder(); + initDefaults(builder); + return builder; + } + + /** + * create builder for blockchain upgrade transaction + * + * @return the builder + */ + public ModifyContractTransactionBuilder modifyContract() { + ModifyContractTransactionBuilder builder = new ModifyContractTransactionBuilder(); + initDefaults(builder); + return builder; + } + + /** + * create builder for multisig account modification transaction + * + * @return the builder + */ + public ModifyMultisigAccountTransactionBuilder multisigModification() { + ModifyMultisigAccountTransactionBuilder builder = new ModifyMultisigAccountTransactionBuilder(); + initDefaults(builder); + return builder; + } + + /** + * create builder for secret lock transaction + * + * @return the builder + */ + public SecretLockTransactionBuilder secretLock() { + SecretLockTransactionBuilder builder = new SecretLockTransactionBuilder(); + initDefaults(builder); + return builder; + } + + /** + * create builder for secret proof transaction + * + * @return the builder + */ + public SecretProofTransactionBuilder secretProof() { + SecretProofTransactionBuilder builder = new SecretProofTransactionBuilder(); + initDefaults(builder); + return builder; + } + + /** + * create builder for address account property modification transaction + * + * @return the builder + */ + public ModifyAccountPropertyAddressTransactionBuilder accountPropAddress() { + ModifyAccountPropertyAddressTransactionBuilder builder = new ModifyAccountPropertyAddressTransactionBuilder(); + initDefaults(builder); + return builder; + } + + /** + * create builder for entity type account property modification transaction + * + * @return the builder + */ + public ModifyAccountPropertyEntityTransactionBuilder accountPropEntityType() { + ModifyAccountPropertyEntityTransactionBuilder builder = new ModifyAccountPropertyEntityTransactionBuilder(); + initDefaults(builder); + return builder; + } + + /** + * create builder for mosaic account property modification transaction + * + * @return the builder + */ + public ModifyAccountPropertyMosaicTransactionBuilder accountPropMosaic() { + ModifyAccountPropertyMosaicTransactionBuilder builder = new ModifyAccountPropertyMosaicTransactionBuilder(); + initDefaults(builder); + return builder; + } + + /** + * create builder for metadata modification transaction + * + * @return the builder + */ + public ModifyMetadataTransactionBuilder modifyMetadata() { + ModifyMetadataTransactionBuilder builder = new ModifyMetadataTransactionBuilder(); + initDefaults(builder); + return builder; + } +} diff --git a/src/main/java/io/proximax/sdk/model/transaction/builder/TransferTransactionBuilder.java b/src/main/java/io/proximax/sdk/model/transaction/builder/TransferTransactionBuilder.java new file mode 100644 index 00000000..2ab4568e --- /dev/null +++ b/src/main/java/io/proximax/sdk/model/transaction/builder/TransferTransactionBuilder.java @@ -0,0 +1,151 @@ +/* + * Copyright 2019 ProximaX Limited. All rights reserved. + * Use of this source code is governed by the Apache 2.0 + * license that can be found in the LICENSE file. + */ +package io.proximax.sdk.model.transaction.builder; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import io.proximax.sdk.model.account.Address; +import io.proximax.sdk.model.mosaic.Mosaic; +import io.proximax.sdk.model.namespace.NamespaceId; +import io.proximax.sdk.model.transaction.Message; +import io.proximax.sdk.model.transaction.PlainMessage; +import io.proximax.sdk.model.transaction.Recipient; +import io.proximax.sdk.model.transaction.TransactionType; +import io.proximax.sdk.model.transaction.TransactionVersion; +import io.proximax.sdk.model.transaction.TransferTransaction; + +/** + * builder for {@link TransferTransaction} + */ +public class TransferTransactionBuilder extends TransactionBuilder { + private Recipient recipient; + private List mosaics; + private Message message; + + public TransferTransactionBuilder() { + super(TransactionType.TRANSFER, TransactionVersion.TRANSFER.getValue()); + // make default message empty + message = PlainMessage.Empty; + // make the list of mosaics to transfer empty + mosaics = new ArrayList<>(); + } + + @Override + protected TransferTransactionBuilder self() { + return this; + } + + @Override + public TransferTransaction build() { + // use or calculate maxFee + BigInteger maxFee = getMaxFee().orElseGet( + () -> getMaxFeeCalculation(TransferTransaction.calculatePayloadSize(getMessage(), getMosaics().size()))); + // create transaction instance + return new TransferTransaction(getNetworkType(), getVersion(), getDeadline(), maxFee, getSignature(), getSigner(), + getTransactionInfo(), getRecipient(), getMosaics(), getMessage()); + } + + // ------------------------------------ setters ------------------------------------// + + /** + * transfer recipient + * + * @param recipient the recipient + * @return self + */ + public TransferTransactionBuilder recipient(Recipient recipient) { + this.recipient = recipient; + return this; + } + + /** + * mosaics to be transferred to recipient + * + * @param mosaics list of mosaics for transfer + * @return self + */ + public TransferTransactionBuilder mosaics(List mosaics) { + this.mosaics = mosaics; + return this; + } + + /** + * transfer message for the recipient + * + * @param message the message + * @return self + */ + public TransferTransactionBuilder message(Message message) { + this.message = message; + return this; + } + + // ------------------------------------------- getters ------------------------------------------// + /** + * @return the recipient + */ + public Recipient getRecipient() { + return recipient; + } + + /** + * @return the mosaics + */ + public List getMosaics() { + return mosaics; + } + + /** + * @return the message + */ + public Message getMessage() { + return message; + } + + // ----------------------------------------- convenience methods -------------------------------------// + + /** + * convenience call to {@link TransferTransactionBuilder#recipient(Recipient)} + * + * @param recipient the recipient to set + * @return self + */ + public TransferTransactionBuilder to(Recipient recipient) { + return recipient(recipient); + } + + /** + * convenience call to {@link TransferTransactionBuilder#recipient(Recipient)} + * + * @param address the recipient to set + * @return self + */ + public TransferTransactionBuilder to(Address address) { + return recipient(Recipient.from(address)); + } + + /** + * convenience call to {@link TransferTransactionBuilder#recipient(Recipient)} + * + * @param namespaceId the recipient to set + * @return self + */ + public TransferTransactionBuilder to(NamespaceId namespaceId) { + return recipient(Recipient.from(namespaceId)); + } + + /** + * @param mosaics the mosaics to set + * @return self + */ + public TransferTransactionBuilder mosaics(Mosaic ... mosaics) { + return mosaics(Arrays.asList(mosaics)); + } + +} diff --git a/src/test/java/io/proximax/sdk/BlockchainApiTest.java b/src/test/java/io/proximax/sdk/BlockchainApiTest.java index 5a0a4163..75152fcb 100644 --- a/src/test/java/io/proximax/sdk/BlockchainApiTest.java +++ b/src/test/java/io/proximax/sdk/BlockchainApiTest.java @@ -23,17 +23,26 @@ import org.junit.jupiter.api.Test; import io.proximax.sdk.model.blockchain.NetworkType; +import io.proximax.sdk.model.transaction.builder.TransactionBuilderFactory; /** * test main API */ class BlockchainApiTest { - + private static final NetworkType NETWORK = NetworkType.MAIN_NET; + @Test void testApiConstructor() throws MalformedURLException { - BlockchainApi api = new BlockchainApi(new URL("http://localhost:3000"), NetworkType.MAIN_NET); + BlockchainApi api = new BlockchainApi(new URL("http://localhost:3000"), NETWORK); assertEquals(new URL("http://localhost:3000"), api.getUrl()); - assertEquals(NetworkType.MAIN_NET, api.getNetworkType()); + assertEquals(NETWORK, api.getNetworkType()); } + @Test + void testRetrieveTransactionFactory() throws MalformedURLException { + BlockchainApi api = new BlockchainApi(new URL("http://localhost:3000"), NETWORK); + + TransactionBuilderFactory fac = api.transact(); + assertEquals(NETWORK, fac.getNetworkType()); + } } diff --git a/src/test/java/io/proximax/sdk/infrastructure/TransactionMappingTest.java b/src/test/java/io/proximax/sdk/infrastructure/TransactionMappingTest.java index 3816d35f..241eca49 100644 --- a/src/test/java/io/proximax/sdk/infrastructure/TransactionMappingTest.java +++ b/src/test/java/io/proximax/sdk/infrastructure/TransactionMappingTest.java @@ -134,7 +134,7 @@ private void validateStandaloneTransaction(Transaction transaction, JsonObject t assertTrue(transaction.getVersion() == version); int networkType = TransactionMappingUtils.extractNetworkType(getFieldOfObject(transactionDTO, "transaction", "version")).getValue(); assertTrue(transaction.getNetworkType().getValue() == networkType); - assertEquals(TransactionMappingUtils.extractFee(transactionDTO.get("transaction").getAsJsonObject()), transaction.getFee()); + assertEquals(TransactionMappingUtils.extractFee(transactionDTO.get("transaction").getAsJsonObject()), transaction.getMaxFee()); assertNotNull(transaction.getDeadline()); if (transaction.getType() == TransactionType.TRANSFER) { @@ -185,7 +185,7 @@ private void validateAggregateTransaction(AggregateTransaction aggregateTransact assertTrue(aggregateTransaction.getNetworkType().getValue() == networkType); assertTrue(aggregateTransaction.getType().getValue() == getFieldOfObject(aggregateTransactionDTO, "transaction", "type").getAsInt()); assertEquals(extractBigInteger(getFieldOfObject(aggregateTransactionDTO, "transaction", "fee").getAsJsonArray()), - aggregateTransaction.getFee()); + aggregateTransaction.getMaxFee()); assertNotNull(aggregateTransaction.getDeadline()); diff --git a/src/test/java/io/proximax/sdk/model/account/AccountTest.java b/src/test/java/io/proximax/sdk/model/account/AccountTest.java index 694179c4..9ca271ad 100644 --- a/src/test/java/io/proximax/sdk/model/account/AccountTest.java +++ b/src/test/java/io/proximax/sdk/model/account/AccountTest.java @@ -21,7 +21,6 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import java.math.BigInteger; -import java.util.Collections; import org.junit.jupiter.api.Test; @@ -31,82 +30,85 @@ import io.proximax.sdk.model.mosaic.Mosaic; import io.proximax.sdk.model.mosaic.MosaicId; import io.proximax.sdk.model.transaction.FakeDeadline; -import io.proximax.sdk.model.transaction.PlainMessage; import io.proximax.sdk.model.transaction.SignedTransaction; import io.proximax.sdk.model.transaction.TransferTransaction; +import io.proximax.sdk.model.transaction.builder.TransactionBuilderFactory; class AccountTest { - @Test - void shouldCreateAccountViaConstructor() { - Account account = new Account("787225aaff3d2c71f4ffa32d4f19ec4922f3cd869747f267378f81f8e3fcb12d", NetworkType.MIJIN_TEST); - assertEquals("SDRDGFTDLLCB67D4HPGIMIHPNSRYRJRT7DOBGWZY", account.getAddress().plain()); - assertEquals("1026D70E1954775749C6811084D6450A3184D977383F0E4282CD47118AF37755", account.getPublicKey()); - assertEquals("787225AAFF3D2C71F4FFA32D4F19EC4922F3CD869747F267378F81F8E3FCB12D", account.getPrivateKey()); - } + @Test + void shouldCreateAccountViaConstructor() { + Account account = new Account("787225aaff3d2c71f4ffa32d4f19ec4922f3cd869747f267378f81f8e3fcb12d", + NetworkType.MIJIN_TEST); + assertEquals("SDRDGFTDLLCB67D4HPGIMIHPNSRYRJRT7DOBGWZY", account.getAddress().plain()); + assertEquals("1026D70E1954775749C6811084D6450A3184D977383F0E4282CD47118AF37755", account.getPublicKey()); + assertEquals("787225AAFF3D2C71F4FFA32D4F19EC4922F3CD869747F267378F81F8E3FCB12D", account.getPrivateKey()); + } - @Test - void shouldCreateAccountViaStaticConstructor() { - Account account = Account.createFromPrivateKey("787225AAFF3D2C71F4FFA32D4F19EC4922F3CD869747F267378F81F8E3FCB12D", NetworkType.MIJIN_TEST); - assertEquals("787225AAFF3D2C71F4FFA32D4F19EC4922F3CD869747F267378F81F8E3FCB12D", account.getPrivateKey()); - assertEquals("SDRDGFTDLLCB67D4HPGIMIHPNSRYRJRT7DOBGWZY", account.getAddress().plain()); - assertEquals("1026D70E1954775749C6811084D6450A3184D977383F0E4282CD47118AF37755", account.getPublicKey()); - } + @Test + void shouldCreateAccountViaStaticConstructor() { + Account account = Account.createFromPrivateKey("787225AAFF3D2C71F4FFA32D4F19EC4922F3CD869747F267378F81F8E3FCB12D", + NetworkType.MIJIN_TEST); + assertEquals("787225AAFF3D2C71F4FFA32D4F19EC4922F3CD869747F267378F81F8E3FCB12D", account.getPrivateKey()); + assertEquals("SDRDGFTDLLCB67D4HPGIMIHPNSRYRJRT7DOBGWZY", account.getAddress().plain()); + assertEquals("1026D70E1954775749C6811084D6450A3184D977383F0E4282CD47118AF37755", account.getPublicKey()); + } + @Test + void shouldCreateAccountViaStaticConstructor2() { + Account account = Account.createFromPrivateKey("5098D500390934F81EA416D9A2F50F276DE446E28488E1801212931E3470DA31", + NetworkType.MIJIN_TEST); + assertEquals("5098D500390934F81EA416D9A2F50F276DE446E28488E1801212931E3470DA31", account.getPrivateKey()); + assertEquals("9B800145F7228CE0014FC6FB44AD899BFCAD7B0CDF48DB63A7CC7299E373D734", account.getPublicKey()); + assertEquals("SAQC5A-K6X2K6-YYAI4L-2TQI2T-4ZRWAO-URYDYT-UO77", account.getAddress().pretty()); + } - @Test - void shouldCreateAccountViaStaticConstructor2() { - Account account = Account.createFromPrivateKey("5098D500390934F81EA416D9A2F50F276DE446E28488E1801212931E3470DA31", NetworkType.MIJIN_TEST); - assertEquals("5098D500390934F81EA416D9A2F50F276DE446E28488E1801212931E3470DA31", account.getPrivateKey()); - assertEquals("9B800145F7228CE0014FC6FB44AD899BFCAD7B0CDF48DB63A7CC7299E373D734", account.getPublicKey()); - assertEquals("SAQC5A-K6X2K6-YYAI4L-2TQI2T-4ZRWAO-URYDYT-UO77", account.getAddress().pretty()); - } + @Test + void shouldCreateAccountViaStaticConstructor3() { + Account account = Account.createFromPrivateKey("B8AFAE6F4AD13A1B8AAD047B488E0738A437C7389D4FF30C359AC068910C1D59", + NetworkType.MIJIN_TEST); + assertEquals("B8AFAE6F4AD13A1B8AAD047B488E0738A437C7389D4FF30C359AC068910C1D59", account.getPrivateKey()); + assertEquals("68B3FBB18729C1FDE225C57F8CE080FA828F0067E451A3FD81FA628842B0B763", account.getPublicKey()); + assertEquals("SBE6CS7LZKJXLDVTNAC3VZ3AUVZDTF3PACNFIXFN", account.getAddress().plain()); + } - @Test - void shouldCreateAccountViaStaticConstructor3() { - Account account = Account.createFromPrivateKey("B8AFAE6F4AD13A1B8AAD047B488E0738A437C7389D4FF30C359AC068910C1D59", NetworkType.MIJIN_TEST); - assertEquals("B8AFAE6F4AD13A1B8AAD047B488E0738A437C7389D4FF30C359AC068910C1D59", account.getPrivateKey()); - assertEquals("68B3FBB18729C1FDE225C57F8CE080FA828F0067E451A3FD81FA628842B0B763", account.getPublicKey()); - assertEquals("SBE6CS7LZKJXLDVTNAC3VZ3AUVZDTF3PACNFIXFN", account.getAddress().plain()); - } + @Test + void generateNewAccountTest() { + Account account = Account.generateNewAccount(NetworkType.MIJIN_TEST); + assertNotEquals(account.getPrivateKey(), null); + assertNotEquals(account.getPublicKey(), null); + assertEquals(64, account.getPrivateKey().length()); + } - @Test - void generateNewAccountTest(){ - Account account = Account.generateNewAccount(NetworkType.MIJIN_TEST); - assertNotEquals(account.getPrivateKey(),null); - assertNotEquals(account.getPublicKey(), null); - assertEquals(64, account.getPrivateKey().length()); - } + @Test + void shouldSignTransaction() { + Account account = new Account("787225aaff3d2c71f4ffa32d4f19ec4922f3cd869747f267378f81f8e3fcb12d", + NetworkType.MIJIN_TEST); + TransferTransaction transferTransaction = new TransactionBuilderFactory().transfer() + .mosaics(new Mosaic(new MosaicId(new BigInteger("95442763262823")), BigInteger.valueOf(100))) + .to(new Address("SDUP5PLHDXKBX3UU5Q52LAY4WYEKGEWC6IB3VBFM", NetworkType.MIJIN_TEST)) + .networkType(NetworkType.MIJIN_TEST).deadline(new FakeDeadline()).build(); - @Test - void shouldSignTransaction() { - Account account = new Account("787225aaff3d2c71f4ffa32d4f19ec4922f3cd869747f267378f81f8e3fcb12d", NetworkType.MIJIN_TEST); - TransferTransaction transferTransaction = TransferTransaction.create( - new FakeDeadline(), - new Address("SDUP5PLHDXKBX3UU5Q52LAY4WYEKGEWC6IB3VBFM", NetworkType.MIJIN_TEST), - Collections.singletonList( - new Mosaic(new MosaicId(new BigInteger("95442763262823")), BigInteger.valueOf(100)) - ), - PlainMessage.Empty, - NetworkType.MIJIN_TEST - ); + SignedTransaction signedTransaction = account.sign(transferTransaction, + "7B631D803F912B00DC0CBED3014BBD17A302BA50B99D233B9C2D9533B842ABDF"); + assertEquals( + "A700000012714D1BA6A1169BBEC67ADE7B77D107BA81D22CB90AF46AC398549FEE693F21228F94FBEDE0122318408F8247FEEBD753D6D6EF9F243E0E0507B38922B222081026D70E1954775749C6811084D6450A3184D977383F0E4282CD47118AF377550300009054410000000000000000010000000000000090E8FEBD671DD41BEE94EC3BA5831CB608A312C2F203BA84AC01000100672B0000CE5600006400000000000000", + signedTransaction.getPayload()); + assertEquals("00E440438762F09A150235494F9C11F074F310D102CB708751C712B4A84F810A", signedTransaction.getHash()); + } - SignedTransaction signedTransaction = account.sign(transferTransaction, "7B631D803F912B00DC0CBED3014BBD17A302BA50B99D233B9C2D9533B842ABDF"); - assertEquals("A700000012714D1BA6A1169BBEC67ADE7B77D107BA81D22CB90AF46AC398549FEE693F21228F94FBEDE0122318408F8247FEEBD753D6D6EF9F243E0E0507B38922B222081026D70E1954775749C6811084D6450A3184D977383F0E4282CD47118AF377550300009054410000000000000000010000000000000090E8FEBD671DD41BEE94EC3BA5831CB608A312C2F203BA84AC01000100672B0000CE5600006400000000000000", signedTransaction.getPayload()); - assertEquals("00E440438762F09A150235494F9C11F074F310D102CB708751C712B4A84F810A", signedTransaction.getHash()); - } + @Test + void shouldAcceptKeyPairAsConstructor() { + KeyPair random = KeyPair.random(new Ed25519CryptoEngine()); + Account account = new Account(random, NetworkType.MIJIN_TEST); + assertEquals(random.getPrivateKey().toString().toUpperCase(), account.getPrivateKey()); + assertEquals(account.getAddress().getNetworkType(), NetworkType.MIJIN_TEST); + } - @Test - void shouldAcceptKeyPairAsConstructor() { - KeyPair random = KeyPair.random(new Ed25519CryptoEngine()); - Account account = new Account(random, NetworkType.MIJIN_TEST); - assertEquals(random.getPrivateKey().toString().toUpperCase(), account.getPrivateKey()); - assertEquals(account.getAddress().getNetworkType(), NetworkType.MIJIN_TEST); - } - - @Test - void checkToString() { - Account account = new Account("787225aaff3d2c71f4ffa32d4f19ec4922f3cd869747f267378f81f8e3fcb12d", NetworkType.MIJIN_TEST); - assertTrue(account.toString().startsWith("Account")); - } + @Test + void checkToString() { + Account account = new Account("787225aaff3d2c71f4ffa32d4f19ec4922f3cd869747f267378f81f8e3fcb12d", + NetworkType.MIJIN_TEST); + assertTrue(account.toString().startsWith("Account")); + } } diff --git a/src/test/java/io/proximax/sdk/model/transaction/AccountLinkTransactionTest.java b/src/test/java/io/proximax/sdk/model/transaction/AccountLinkTransactionTest.java index 4a9cf57b..423d0970 100644 --- a/src/test/java/io/proximax/sdk/model/transaction/AccountLinkTransactionTest.java +++ b/src/test/java/io/proximax/sdk/model/transaction/AccountLinkTransactionTest.java @@ -7,10 +7,10 @@ import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; import java.io.IOException; import java.math.BigInteger; +import java.util.Optional; import org.junit.jupiter.api.Test; @@ -25,8 +25,9 @@ */ class AccountLinkTransactionTest extends ResourceBasedTest { private static final NetworkType NETWORK_TYPE = NetworkType.MAIN_NET; - private static final PublicAccount REMOTE_ACCOUNT = new PublicAccount("3fc8ba10229ab5778d05d9c4b7f56676a88bf9295c185acfc0f961db5408cafe", NETWORK_TYPE); - + private static final PublicAccount REMOTE_ACCOUNT = new PublicAccount( + "3fc8ba10229ab5778d05d9c4b7f56676a88bf9295c185acfc0f961db5408cafe", NETWORK_TYPE); + @Test void testFullConstructor() { TransactionDeadline deadline = new FakeDeadline(); @@ -34,64 +35,45 @@ void testFullConstructor() { PublicAccount signer = new Account(new KeyPair(), NETWORK_TYPE).getPublicAccount(); TransactionInfo transactionInfo = TransactionInfo.create(BigInteger.TEN, "hash", "merkle"); String signature = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; - AccountLinkTransaction trans = new AccountLinkTransaction(remoteAccount, AccountLinkAction.LINK, NETWORK_TYPE, 7, - deadline, BigInteger.ONE, signature, signer, transactionInfo); + AccountLinkTransaction trans = new AccountLinkTransaction(NETWORK_TYPE, 7, deadline, BigInteger.ONE, + Optional.of(signature), Optional.of(signer), Optional.of(transactionInfo), remoteAccount, + AccountLinkAction.LINK); // assert object attributes assertEquals(remoteAccount, trans.getRemoteAccount()); assertEquals(AccountLinkAction.LINK, trans.getAction()); assertEquals(NETWORK_TYPE, trans.getNetworkType()); assertEquals(7, trans.getVersion()); assertEquals(deadline, trans.getDeadline()); - assertEquals(BigInteger.ONE, trans.getFee()); + assertEquals(BigInteger.ONE, trans.getMaxFee()); assertEquals(signature, trans.getSignature().orElse("missing")); assertEquals(signer, trans.getSigner().orElse(null)); assertEquals(transactionInfo, trans.getTransactionInfo().orElse(null)); } - @Test - void testShortConstructor() { - TransactionDeadline deadline = new FakeDeadline(); - PublicAccount remoteAccount = new Account(new KeyPair(), NETWORK_TYPE).getPublicAccount(); - AccountLinkTransaction trans = new AccountLinkTransaction(remoteAccount, AccountLinkAction.LINK, NETWORK_TYPE, - deadline, BigInteger.ONE); - // assert object attributes - assertEquals(remoteAccount, trans.getRemoteAccount()); - assertEquals(AccountLinkAction.LINK, trans.getAction()); - assertEquals(NETWORK_TYPE, trans.getNetworkType()); - assertEquals(TransactionVersion.ACCOUNT_LINK.getValue(), trans.getVersion()); - assertEquals(deadline, trans.getDeadline()); - assertEquals(BigInteger.ONE, trans.getFee()); - assertFalse(trans.getSignature().isPresent()); - assertFalse(trans.getSigner().isPresent()); - assertFalse(trans.getTransactionInfo().isPresent()); - } - - @Test - void testStaticConstructor() { - TransactionDeadline deadline = new FakeDeadline(); - PublicAccount remoteAccount = new Account(new KeyPair(), NETWORK_TYPE).getPublicAccount(); - AccountLinkTransaction trans = AccountLinkTransaction - .create(deadline, BigInteger.ONE, remoteAccount, AccountLinkAction.LINK, NETWORK_TYPE); - // assert object attributes - assertEquals(remoteAccount, trans.getRemoteAccount()); - assertEquals(AccountLinkAction.LINK, trans.getAction()); - assertEquals(NETWORK_TYPE, trans.getNetworkType()); - assertEquals(TransactionVersion.ACCOUNT_LINK.getValue(), trans.getVersion()); - assertEquals(deadline, trans.getDeadline()); - assertEquals(BigInteger.ONE, trans.getFee()); - assertFalse(trans.getSignature().isPresent()); - assertFalse(trans.getSigner().isPresent()); - assertFalse(trans.getTransactionInfo().isPresent()); - } - @Test void serialization() throws IOException { TransactionDeadline deadline = new FakeDeadline(); - AccountLinkTransaction trans = AccountLinkTransaction - .create(deadline, BigInteger.ONE, REMOTE_ACCOUNT, AccountLinkAction.LINK, NETWORK_TYPE); + AccountLinkTransaction trans = new AccountLinkTransaction(NETWORK_TYPE, 7, deadline, BigInteger.ONE, + Optional.empty(), Optional.empty(), Optional.empty(), REMOTE_ACCOUNT, + AccountLinkAction.LINK); // serialize byte[] actual = trans.generateBytes(); // saveBytes("account_link", actual); assertArrayEquals(loadBytes("account_link"), actual); } + + @Test + void checkCopyToSigner() { + TransactionDeadline deadline = new FakeDeadline(); + PublicAccount remoteAccount = new Account(new KeyPair(), NETWORK_TYPE).getPublicAccount(); + PublicAccount signer = new Account(new KeyPair(), NETWORK_TYPE).getPublicAccount(); + TransactionInfo transactionInfo = TransactionInfo.create(BigInteger.TEN, "hash", "merkle"); + String signature = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"; + AccountLinkTransaction trans = new AccountLinkTransaction(NETWORK_TYPE, 7, deadline, BigInteger.ONE, + Optional.of(signature), Optional.of(signer), Optional.of(transactionInfo), remoteAccount, + AccountLinkAction.LINK); + + Transaction t = trans.copyForSigner(remoteAccount); + assertEquals(Optional.of(remoteAccount), t.getSigner()); + } } diff --git a/src/test/java/io/proximax/sdk/model/transaction/AggregateTransactionCosignatureTest.java b/src/test/java/io/proximax/sdk/model/transaction/AggregateTransactionCosignatureTest.java index ca48c6d9..a7c73d60 100644 --- a/src/test/java/io/proximax/sdk/model/transaction/AggregateTransactionCosignatureTest.java +++ b/src/test/java/io/proximax/sdk/model/transaction/AggregateTransactionCosignatureTest.java @@ -25,12 +25,16 @@ public class AggregateTransactionCosignatureTest { - - @Test - void createAnAggregateCosignatureViaConstructor() { - AggregateTransactionCosignature aggregateTransactionCosignature = new AggregateTransactionCosignature("signature", new PublicAccount("9A49366406ACA952B88BADF5F1E9BE6CE4968141035A60BE503273EA65456B24", NetworkType.MIJIN_TEST)); - - assertEquals("signature", aggregateTransactionCosignature.getSignature()); - assertEquals(new PublicAccount("9A49366406ACA952B88BADF5F1E9BE6CE4968141035A60BE503273EA65456B24", NetworkType.MIJIN_TEST), aggregateTransactionCosignature.getSigner()); - } + @Test + void createAnAggregateCosignatureViaConstructor() { + AggregateTransactionCosignature aggregateTransactionCosignature = new AggregateTransactionCosignature("signature", + new PublicAccount("9A49366406ACA952B88BADF5F1E9BE6CE4968141035A60BE503273EA65456B24", + NetworkType.MIJIN_TEST)); + + assertEquals("signature", aggregateTransactionCosignature.getSignature()); + assertEquals( + new PublicAccount("9A49366406ACA952B88BADF5F1E9BE6CE4968141035A60BE503273EA65456B24", + NetworkType.MIJIN_TEST), + aggregateTransactionCosignature.getSigner()); + } } diff --git a/src/test/java/io/proximax/sdk/model/transaction/AggregateTransactionTest.java b/src/test/java/io/proximax/sdk/model/transaction/AggregateTransactionTest.java index f3aedee6..fc26691c 100644 --- a/src/test/java/io/proximax/sdk/model/transaction/AggregateTransactionTest.java +++ b/src/test/java/io/proximax/sdk/model/transaction/AggregateTransactionTest.java @@ -19,6 +19,7 @@ import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; @@ -26,6 +27,7 @@ import java.time.temporal.ChronoUnit; import java.util.Arrays; import java.util.Collections; +import java.util.Optional; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; @@ -40,102 +42,115 @@ import io.proximax.sdk.model.blockchain.NetworkType; import io.proximax.sdk.model.mosaic.Mosaic; import io.proximax.sdk.model.mosaic.NetworkCurrencyMosaic; +import io.proximax.sdk.model.transaction.builder.TransactionBuilderFactory; import io.proximax.sdk.utils.GsonUtils; public class AggregateTransactionTest extends ResourceBasedTest { - @Test - void createAAggregateTransactionViaStaticConstructor() { - - TransferTransaction transferTx = TransferTransaction.create( - new Deadline(2, ChronoUnit.HOURS), - new Address("SDGLFW-DSHILT-IUHGIB-H5UGX2-VYF5VN-JEKCCD-BR26", NetworkType.MIJIN_TEST), - Collections.emptyList(), - PlainMessage.Empty, - NetworkType.MIJIN_TEST - ); - - AggregateTransaction aggregateTx = AggregateTransaction.createComplete( - new Deadline(2, ChronoUnit.HOURS), - Arrays.asList(transferTx.toAggregate(new PublicAccount("9A49366406ACA952B88BADF5F1E9BE6CE4968141035A60BE503273EA65456B24", NetworkType.MIJIN_TEST))), - NetworkType.MIJIN_TEST); - - assertEquals(NetworkType.MIJIN_TEST, aggregateTx.getNetworkType()); - assertTrue(2 == aggregateTx.getVersion()); - long nowSinceNemesis = new Deadline(0, ChronoUnit.SECONDS).getInstant(); - assertTrue(nowSinceNemesis < aggregateTx.getDeadline().getInstant()); - assertEquals(BigInteger.valueOf(0), aggregateTx.getFee()); - assertEquals(1, aggregateTx.getInnerTransactions().size()); - } - - @Test - void serialization() throws IOException { - - TransferTransaction transferTx = TransferTransaction.create( - new FakeDeadline(), - new Address("SBILTA367K2LX2FEXG5TFWAS7GEFYAGY7QLFBYKC", NetworkType.MIJIN_TEST), - Collections.singletonList( - new Mosaic(NetworkCurrencyMosaic.ID, BigInteger.valueOf(10000000)) - ), - PlainMessage.Empty, - NetworkType.MIJIN_TEST - ); - - AggregateTransaction aggregateTx = AggregateTransaction.createComplete( - new FakeDeadline(), - Collections.singletonList(transferTx.toAggregate(new PublicAccount("846B4439154579A5903B1459C9CF69CB8153F6D0110A7A0ED61DE29AE4810BF2", NetworkType.MIJIN_TEST))), - NetworkType.MIJIN_TEST - ); - - byte[] actual = aggregateTx.generateBytes(); + @Test + void createAAggregateTransactionViaStaticConstructor() { + + TransferTransaction transferTx = new TransferTransaction(NetworkType.MIJIN_TEST, 3, + new Deadline(2, ChronoUnit.HOURS), BigInteger.ZERO, Optional.empty(), Optional.empty(), Optional.empty(), + Recipient.from(new Address("SDGLFW-DSHILT-IUHGIB-H5UGX2-VYF5VN-JEKCCD-BR26", NetworkType.MIJIN_TEST)), + Collections.emptyList(), PlainMessage.Empty); + + PublicAccount innerSigner = new PublicAccount("9A49366406ACA952B88BADF5F1E9BE6CE4968141035A60BE503273EA65456B24", + NetworkType.MIJIN_TEST); + + AggregateTransaction aggregateTx = new TransactionBuilderFactory().aggregateComplete() + .innerTransactions(transferTx.toAggregate(innerSigner)).deadline(new Deadline(2, ChronoUnit.HOURS)) + .networkType(NetworkType.MIJIN_TEST).build(); + + assertEquals(NetworkType.MIJIN_TEST, aggregateTx.getNetworkType()); + assertTrue(2 == aggregateTx.getVersion()); + long nowSinceNemesis = new Deadline(0, ChronoUnit.SECONDS).getInstant(); + assertTrue(nowSinceNemesis < aggregateTx.getDeadline().getInstant()); + assertEquals(BigInteger.valueOf(0), aggregateTx.getMaxFee()); + assertEquals(1, aggregateTx.getInnerTransactions().size()); + } + + @Test + void serialization() throws IOException { + TransferTransaction transferTx = new TransferTransaction(NetworkType.MIJIN_TEST, 3, + new FakeDeadline(), BigInteger.ZERO, Optional.empty(), Optional.empty(), Optional.empty(), + Recipient.from(new Address("SBILTA367K2LX2FEXG5TFWAS7GEFYAGY7QLFBYKC", NetworkType.MIJIN_TEST)), + Collections.singletonList(new Mosaic(NetworkCurrencyMosaic.ID, BigInteger.valueOf(10000000))), PlainMessage.Empty); + + PublicAccount innerSigner = new PublicAccount("846B4439154579A5903B1459C9CF69CB8153F6D0110A7A0ED61DE29AE4810BF2", + NetworkType.MIJIN_TEST); + AggregateTransaction aggregateTx = new TransactionBuilderFactory().aggregateComplete() + .innerTransactions(transferTx.toAggregate(innerSigner)).deadline(new FakeDeadline()) + .networkType(NetworkType.MIJIN_TEST).build(); + + byte[] actual = aggregateTx.generateBytes(); // saveBytes("aggregate_trans", actual); - assertArrayEquals(loadBytes("aggregate_trans"), actual); - } - - @Test - void shouldCreateAggregateTransactionAndSignWithMultipleCosignatories() { - - TransferTransaction transferTx = TransferTransaction.create( - new FakeDeadline(), - new Address("SBILTA367K2LX2FEXG5TFWAS7GEFYAGY7QLFBYKC", NetworkType.MIJIN_TEST), - Arrays.asList(), - new PlainMessage("test-message"), - NetworkType.MIJIN_TEST - ); - - AggregateTransaction aggregateTx = AggregateTransaction.createComplete( - new FakeDeadline(), - Collections.singletonList(transferTx.toAggregate(new PublicAccount("B694186EE4AB0558CA4AFCFDD43B42114AE71094F5A1FC4A913FE9971CACD21D", NetworkType.MIJIN_TEST))), - NetworkType.MIJIN_TEST - ); - - Account cosignatoryAccount = new Account("2a2b1f5d366a5dd5dc56c3c757cf4fe6c66e2787087692cf329d7a49a594658b", NetworkType.MIJIN_TEST); - Account cosignatoryAccount2 = new Account("b8afae6f4ad13a1b8aad047b488e0738a437c7389d4ff30c359ac068910c1d59", NetworkType.MIJIN_TEST); // TODO bug with private key - - SignedTransaction signedTransaction = cosignatoryAccount.signTransactionWithCosignatories(aggregateTx, "7B631D803F912B00DC0CBED3014BBD17A302BA50B99D233B9C2D9533B842ABDF", Arrays.asList(cosignatoryAccount2)); - - assertEquals("31010000", signedTransaction.getPayload().substring(0, 8)); - assertEquals("0000530000005300", signedTransaction.getPayload().substring(240, 256)); - //assertEquals("039054419050B9837EFAB4BBE8A4B9BB32D812F9885C00D8FC1650E1420D000000746573742D6D65737361676568B3FBB18729C1FDE225C57F8CE080FA828F0067E451A3FD81FA628842B0B763", signedTransaction.getPayload().substring(320, 474)); - - } - - @Test - @Disabled - void shouldFindAccountInAsASignerOfTheTransaction() { - JsonObject aggregateTransferTransactionDTO = GsonUtils.mapToJsonObject("{\"meta\":{\"hash\":\"671653C94E2254F2A23EFEDB15D67C38332AED1FBD24B063C0A8E675582B6A96\",\"height\":[18160,0],\"id\":\"5A0069D83F17CF0001777E55\",\"index\":0,\"merkleComponentHash\":\"81E5E7AE49998802DABC816EC10158D3A7879702FF29084C2C992CD1289877A7\"},\"transaction\":{\"cosignatures\":[{\"signature\":\"5780C8DF9D46BA2BCF029DCC5D3BF55FE1CB5BE7ABCF30387C4637DDEDFC2152703CA0AD95F21BB9B942F3CC52FCFC2064C7B84CF60D1A9E69195F1943156C07\",\"signer\":\"A5F82EC8EBB341427B6785C8111906CD0DF18838FB11B51CE0E18B5E79DFF630\"}],\"deadline\":[3266625578,11],\"fee\":[0,0],\"signature\":\"939673209A13FF82397578D22CC96EB8516A6760C894D9B7535E3A1E068007B9255CFA9A914C97142A7AE18533E381C846B69D2AE0D60D1DC8A55AD120E2B606\",\"signer\":\"7681ED5023141D9CDCF184E5A7B60B7D466739918ED5DA30F7E71EA7B86EFF2D\",\"transactions\":[{\"meta\":{\"aggregateHash\":\"3D28C804EDD07D5A728E5C5FFEC01AB07AFA5766AE6997B38526D36015A4D006\",\"aggregateId\":\"5A0069D83F17CF0001777E55\",\"height\":[18160,0],\"id\":\"5A0069D83F17CF0001777E56\",\"index\":0},\"transaction\":{\"message\":{\"payload\":\"746573742D6D657373616765\",\"type\":0},\"mosaics\":[{\"amount\":[3863990592,95248],\"id\":[3646934825,3576016193]}],\"recipient\":\"9050B9837EFAB4BBE8A4B9BB32D812F9885C00D8FC1650E142\",\"signer\":\"B4F12E7C9F6946091E2CB8B6D3A12B50D17CCBBF646386EA27CE2946A7423DCF\",\"type\":16724,\"version\":36867}}],\"type\":16705,\"version\":36867}}"); - - AggregateTransaction aggregateTransferTransaction = (AggregateTransaction) new TransactionMapping().apply(aggregateTransferTransactionDTO); - - assertTrue(aggregateTransferTransaction.isSignedByAccount( - PublicAccount.createFromPublicKey("A5F82EC8EBB341427B6785C8111906CD0DF18838FB11B51CE0E18B5E79DFF630", - NetworkType.MIJIN_TEST))); - assertTrue(aggregateTransferTransaction.isSignedByAccount( - PublicAccount.createFromPublicKey("7681ED5023141D9CDCF184E5A7B60B7D466739918ED5DA30F7E71EA7B86EFF2D", - NetworkType.MIJIN_TEST))); - assertFalse(aggregateTransferTransaction.isSignedByAccount( - PublicAccount.createFromPublicKey("B4F12E7C9F6946091E2CB8B6D3A12B50D17CCBBF646386EA27CE2946A7423DCF", - NetworkType.MIJIN_TEST))); - - } + assertArrayEquals(loadBytes("aggregate_trans"), actual); + } + + @Test + void shouldCreateAggregateTransactionAndSignWithMultipleCosignatories() { + TransferTransaction transferTx = new TransferTransaction(NetworkType.MIJIN_TEST, 3, + new FakeDeadline(), BigInteger.ZERO, Optional.empty(), Optional.empty(), Optional.empty(), + Recipient.from(new Address("SBILTA367K2LX2FEXG5TFWAS7GEFYAGY7QLFBYKC", NetworkType.MIJIN_TEST)), + Arrays.asList(), new PlainMessage("test-message")); + + PublicAccount innerSigner = new PublicAccount("B694186EE4AB0558CA4AFCFDD43B42114AE71094F5A1FC4A913FE9971CACD21D", + NetworkType.MIJIN_TEST); + AggregateTransaction aggregateTx = new TransactionBuilderFactory().aggregateComplete() + .innerTransactions(transferTx.toAggregate(innerSigner)).deadline(new FakeDeadline()) + .networkType(NetworkType.MIJIN_TEST).build(); + + Account cosignatoryAccount = new Account("2a2b1f5d366a5dd5dc56c3c757cf4fe6c66e2787087692cf329d7a49a594658b", + NetworkType.MIJIN_TEST); + Account cosignatoryAccount2 = new Account("b8afae6f4ad13a1b8aad047b488e0738a437c7389d4ff30c359ac068910c1d59", + NetworkType.MIJIN_TEST); + + SignedTransaction signedTransaction = cosignatoryAccount.signTransactionWithCosignatories(aggregateTx, + "7B631D803F912B00DC0CBED3014BBD17A302BA50B99D233B9C2D9533B842ABDF", + Arrays.asList(cosignatoryAccount2)); + + assertEquals("31010000", signedTransaction.getPayload().substring(0, 8)); + assertEquals("0000530000005300", signedTransaction.getPayload().substring(240, 256)); + // assertEquals("039054419050B9837EFAB4BBE8A4B9BB32D812F9885C00D8FC1650E1420D000000746573742D6D65737361676568B3FBB18729C1FDE225C57F8CE080FA828F0067E451A3FD81FA628842B0B763", + // signedTransaction.getPayload().substring(320, 474)); + + } + + @Test + void checkCopyToSigner() { + TransferTransaction transferTx = new TransferTransaction(NetworkType.MIJIN_TEST, 3, + new FakeDeadline(), BigInteger.ZERO, Optional.empty(), Optional.empty(), Optional.empty(), + Recipient.from(new Address("SBILTA367K2LX2FEXG5TFWAS7GEFYAGY7QLFBYKC", NetworkType.MIJIN_TEST)), + Arrays.asList(), new PlainMessage("test-message")); + + PublicAccount innerSigner = new PublicAccount("B694186EE4AB0558CA4AFCFDD43B42114AE71094F5A1FC4A913FE9971CACD21D", + NetworkType.MIJIN_TEST); + AggregateTransaction aggregateTx = new TransactionBuilderFactory().aggregateComplete() + .innerTransactions(transferTx.toAggregate(innerSigner)).deadline(new FakeDeadline()) + .networkType(NetworkType.MIJIN_TEST).build(); + + assertThrows(UnsupportedOperationException.class, () -> aggregateTx.copyForSigner(innerSigner)); + } + + @Test + @Disabled + void shouldFindAccountInAsASignerOfTheTransaction() { + JsonObject aggregateTransferTransactionDTO = GsonUtils.mapToJsonObject( + "{\"meta\":{\"hash\":\"671653C94E2254F2A23EFEDB15D67C38332AED1FBD24B063C0A8E675582B6A96\",\"height\":[18160,0],\"id\":\"5A0069D83F17CF0001777E55\",\"index\":0,\"merkleComponentHash\":\"81E5E7AE49998802DABC816EC10158D3A7879702FF29084C2C992CD1289877A7\"},\"transaction\":{\"cosignatures\":[{\"signature\":\"5780C8DF9D46BA2BCF029DCC5D3BF55FE1CB5BE7ABCF30387C4637DDEDFC2152703CA0AD95F21BB9B942F3CC52FCFC2064C7B84CF60D1A9E69195F1943156C07\",\"signer\":\"A5F82EC8EBB341427B6785C8111906CD0DF18838FB11B51CE0E18B5E79DFF630\"}],\"deadline\":[3266625578,11],\"fee\":[0,0],\"signature\":\"939673209A13FF82397578D22CC96EB8516A6760C894D9B7535E3A1E068007B9255CFA9A914C97142A7AE18533E381C846B69D2AE0D60D1DC8A55AD120E2B606\",\"signer\":\"7681ED5023141D9CDCF184E5A7B60B7D466739918ED5DA30F7E71EA7B86EFF2D\",\"transactions\":[{\"meta\":{\"aggregateHash\":\"3D28C804EDD07D5A728E5C5FFEC01AB07AFA5766AE6997B38526D36015A4D006\",\"aggregateId\":\"5A0069D83F17CF0001777E55\",\"height\":[18160,0],\"id\":\"5A0069D83F17CF0001777E56\",\"index\":0},\"transaction\":{\"message\":{\"payload\":\"746573742D6D657373616765\",\"type\":0},\"mosaics\":[{\"amount\":[3863990592,95248],\"id\":[3646934825,3576016193]}],\"recipient\":\"9050B9837EFAB4BBE8A4B9BB32D812F9885C00D8FC1650E142\",\"signer\":\"B4F12E7C9F6946091E2CB8B6D3A12B50D17CCBBF646386EA27CE2946A7423DCF\",\"type\":16724,\"version\":36867}}],\"type\":16705,\"version\":36867}}"); + + AggregateTransaction aggregateTransferTransaction = (AggregateTransaction) new TransactionMapping() + .apply(aggregateTransferTransactionDTO); + + assertTrue(aggregateTransferTransaction.isSignedByAccount( + PublicAccount.createFromPublicKey("A5F82EC8EBB341427B6785C8111906CD0DF18838FB11B51CE0E18B5E79DFF630", + NetworkType.MIJIN_TEST))); + assertTrue(aggregateTransferTransaction.isSignedByAccount( + PublicAccount.createFromPublicKey("7681ED5023141D9CDCF184E5A7B60B7D466739918ED5DA30F7E71EA7B86EFF2D", + NetworkType.MIJIN_TEST))); + assertFalse(aggregateTransferTransaction.isSignedByAccount( + PublicAccount.createFromPublicKey("B4F12E7C9F6946091E2CB8B6D3A12B50D17CCBBF646386EA27CE2946A7423DCF", + NetworkType.MIJIN_TEST))); + + } } diff --git a/src/test/java/io/proximax/sdk/model/transaction/AliasTransactionTest.java b/src/test/java/io/proximax/sdk/model/transaction/AliasTransactionTest.java index 670abb64..940fe8a0 100644 --- a/src/test/java/io/proximax/sdk/model/transaction/AliasTransactionTest.java +++ b/src/test/java/io/proximax/sdk/model/transaction/AliasTransactionTest.java @@ -16,7 +16,9 @@ import org.junit.jupiter.api.Test; +import io.proximax.core.crypto.KeyPair; import io.proximax.sdk.ResourceBasedTest; +import io.proximax.sdk.model.account.Account; import io.proximax.sdk.model.account.Address; import io.proximax.sdk.model.account.PublicAccount; import io.proximax.sdk.model.alias.AliasAction; @@ -31,16 +33,14 @@ class AliasTransactionTest extends ResourceBasedTest { @Test void genericConstructor() { - Deadline deadLine = new FakeDeadline(); - AliasTransaction trans = new AliasTransaction(TransactionType.ADDRESS_ALIAS, NetworkType.MIJIN, 63, deadLine, - BigInteger.valueOf(765), Optional.empty(), Optional.of(new Address("MADDR", - NetworkType.MIJIN)), new NamespaceId("something"), AliasAction.LINK, - "sign", new PublicAccount("", NetworkType.MIJIN), - TransactionInfo.create(BigInteger.ONE, "infohash", "merklehash")); + AliasTransaction trans = new AliasTransaction(TransactionType.ADDRESS_ALIAS, NetworkType.MIJIN, + TransactionVersion.ADDRESS_ALIAS.getValue(), new FakeDeadline(), BigInteger.ZERO, Optional.empty(), + Optional.empty(), Optional.empty(), Optional.empty(), + Optional.of(new Address("MB3KUBHATFCPV7UZQLWAQ2EUR6SIHBSBEOEDDDF5", NetworkType.MIJIN)), new NamespaceId("something"), AliasAction.LINK); // run assertions assertFalse(trans.getMosaicId().isPresent()); - assertEquals(new Address("MADDR", NetworkType.MIJIN), trans.getAddress().orElseThrow(AssertionError::new)); + assertEquals(new Address("MB3KUBHATFCPV7UZQLWAQ2EUR6SIHBSBEOEDDDF5", NetworkType.MIJIN), trans.getAddress().orElseThrow(AssertionError::new)); assertEquals(new NamespaceId("something"), trans.getNamespaceId()); assertEquals(AliasAction.LINK, trans.getAliasAction()); } @@ -48,44 +48,24 @@ void genericConstructor() { @Test void genericConstructorThrows() { assertThrows(IllegalArgumentException.class, - () -> new AliasTransaction(TransactionType.ADDRESS_ALIAS, NetworkType.MIJIN, 63, new FakeDeadline(), - BigInteger.valueOf(765), Optional.empty(), Optional.empty(), new NamespaceId("something"), - AliasAction.LINK, "sign", new PublicAccount("", NetworkType.MIJIN), - TransactionInfo.create(BigInteger.ONE, "infohash", "merklehash"))); + () -> new AliasTransaction(TransactionType.MOSAIC_ALIAS, NetworkType.MIJIN, + TransactionVersion.ADDRESS_ALIAS.getValue(), new FakeDeadline(), BigInteger.ZERO, Optional.empty(), + Optional.empty(), Optional.empty(), Optional.empty(), + Optional.of(new Address("MB3KUBHATFCPV7UZQLWAQ2EUR6SIHBSBEOEDDDF3", NetworkType.MIJIN)), new NamespaceId("testest"), AliasAction.LINK)); assertThrows(IllegalArgumentException.class, - () -> new AliasTransaction(TransactionType.ADDRESS_ALIAS, NetworkType.MIJIN, 63, new FakeDeadline(), - BigInteger.valueOf(765), Optional.of(new MosaicId(BigInteger.ONE)), - Optional.of(new Address("MADDR", NetworkType.MIJIN)), new NamespaceId("something"), AliasAction.LINK, - "sign", new PublicAccount("", NetworkType.MIJIN), - TransactionInfo.create(BigInteger.ONE, "infohash", "merklehash"))); - } - - @Test - void addressConstructor() { - AliasTransaction trans = AliasTransaction.create(new Address("MADDR", - NetworkType.MIJIN), new NamespaceId("testest"), AliasAction.LINK, new FakeDeadline(), NetworkType.MIJIN); - // run assertions - assertFalse(trans.getMosaicId().isPresent()); - assertEquals(new Address("MADDR", NetworkType.MIJIN), trans.getAddress().orElseThrow(AssertionError::new)); - assertEquals(new NamespaceId("testest"), trans.getNamespaceId()); - assertEquals(AliasAction.LINK, trans.getAliasAction()); - } - - @Test - void mosaicConstructor() { - AliasTransaction trans = AliasTransaction.create(new MosaicId( - BigInteger.ONE), new NamespaceId("testest"), AliasAction.UNLINK, new FakeDeadline(), NetworkType.MIJIN); - assertEquals(new MosaicId(BigInteger.ONE), trans.getMosaicId().orElseThrow(AssertionError::new)); - // run assertions - assertFalse(trans.getAddress().isPresent()); - assertEquals(new NamespaceId("testest"), trans.getNamespaceId()); - assertEquals(AliasAction.UNLINK, trans.getAliasAction()); + () -> new AliasTransaction(TransactionType.ADDRESS_ALIAS, NetworkType.MIJIN, + TransactionVersion.ADDRESS_ALIAS.getValue(), new FakeDeadline(), BigInteger.ZERO, + Optional.empty(), Optional.empty(), Optional.empty(), Optional.of(new MosaicId( + BigInteger.ONE)), + Optional.empty(), new NamespaceId("testest"), AliasAction.LINK)); } @Test void addressSerialization() throws IOException { - AliasTransaction trans = AliasTransaction.create(new Address("MADDR", - NetworkType.MIJIN), new NamespaceId("testest"), AliasAction.LINK, new FakeDeadline(), NetworkType.MIJIN); + AliasTransaction trans = new AliasTransaction(TransactionType.ADDRESS_ALIAS, NetworkType.MIJIN, + TransactionVersion.ADDRESS_ALIAS.getValue(), new FakeDeadline(), BigInteger.ZERO, + Optional.empty(), Optional.empty(), Optional.empty(), Optional.empty(), + Optional.of(new Address("MB3KUBHATFCPV7UZQLWAQ2EUR6SIHBSBEOEDDDF3", NetworkType.MIJIN)), new NamespaceId("testest"), AliasAction.LINK); // generated by saveBytes byte[] actual = trans.generateBytes(); // saveBytes("link_address", actual); @@ -94,12 +74,28 @@ void addressSerialization() throws IOException { @Test void mosaicSerialization() throws IOException { - AliasTransaction trans = AliasTransaction.create(new MosaicId( - BigInteger.ONE), new NamespaceId("testest"), AliasAction.LINK, new FakeDeadline(), NetworkType.MIJIN); + AliasTransaction trans = new AliasTransaction(TransactionType.MOSAIC_ALIAS, NetworkType.MIJIN, + TransactionVersion.ADDRESS_ALIAS.getValue(), new FakeDeadline(), BigInteger.ZERO, + Optional.empty(), Optional.empty(), Optional.empty(), Optional.of(new MosaicId( + BigInteger.ONE)), + Optional.empty(), new NamespaceId("testest"), AliasAction.LINK); // generated by saveBytes byte[] actual = trans.generateBytes(); // saveBytes("link_mosaic", actual); assertArrayEquals(loadBytes("link_mosaic"), actual); } + @Test + void checkCopyToSigner() { + PublicAccount remoteAccount = new Account(new KeyPair(), NetworkType.MIJIN).getPublicAccount(); + + AliasTransaction trans = new AliasTransaction(TransactionType.MOSAIC_ALIAS, NetworkType.MIJIN, + TransactionVersion.ADDRESS_ALIAS.getValue(), new FakeDeadline(), BigInteger.ZERO, + Optional.empty(), Optional.empty(), Optional.empty(), Optional.of(new MosaicId( + BigInteger.ONE)), + Optional.empty(), new NamespaceId("testest"), AliasAction.LINK); + + Transaction t = trans.copyForSigner(remoteAccount); + assertEquals(Optional.of(remoteAccount), t.getSigner()); + } } diff --git a/src/test/java/io/proximax/sdk/model/transaction/BlockchainConfigTransactionTest.java b/src/test/java/io/proximax/sdk/model/transaction/BlockchainConfigTransactionTest.java index cd9a00cb..197f5991 100644 --- a/src/test/java/io/proximax/sdk/model/transaction/BlockchainConfigTransactionTest.java +++ b/src/test/java/io/proximax/sdk/model/transaction/BlockchainConfigTransactionTest.java @@ -10,10 +10,14 @@ import java.io.IOException; import java.math.BigInteger; +import java.util.Optional; import org.junit.jupiter.api.Test; +import io.proximax.core.crypto.KeyPair; import io.proximax.sdk.ResourceBasedTest; +import io.proximax.sdk.model.account.Account; +import io.proximax.sdk.model.account.PublicAccount; import io.proximax.sdk.model.blockchain.NetworkType; /** @@ -25,12 +29,9 @@ class BlockchainConfigTransactionTest extends ResourceBasedTest { void testConstructor() throws IOException { String conf = getResourceAsString("config/blockchain.properties"); String entities = getResourceAsString("config/entities.json"); - BlockchainConfigTransaction trans = BlockchainConfigTransaction.create( - BigInteger.valueOf(3), - conf, - entities, - NetworkType.MIJIN, - new FakeDeadline()); + BlockchainConfigTransaction trans = new BlockchainConfigTransaction(NetworkType.MIJIN, 1, new FakeDeadline(), + BigInteger.ZERO, Optional.empty(), Optional.empty(), Optional.empty(), BigInteger.valueOf(3), conf, + entities); assertEquals(BigInteger.valueOf(3), trans.getApplyHeightDelta()); assertEquals(conf, trans.getBlockchainConfig()); @@ -41,15 +42,26 @@ void testConstructor() throws IOException { void serialization() throws IOException { String conf = getResourceAsString("config/blockchain.properties"); String entities = getResourceAsString("config/entities.json"); - BlockchainConfigTransaction trans = BlockchainConfigTransaction.create( - BigInteger.valueOf(3), - conf, - entities, - NetworkType.MIJIN, - new FakeDeadline()); - + BlockchainConfigTransaction trans = new BlockchainConfigTransaction(NetworkType.MIJIN, 1, new FakeDeadline(), + BigInteger.ZERO, Optional.empty(), Optional.empty(), Optional.empty(), BigInteger.valueOf(3), conf, + entities); + byte[] actual = trans.generateBytes(); // saveBytes("config_transaction", actual); assertArrayEquals(loadBytes("config_transaction"), actual); } + + @Test + void checkCopyToSigner() throws IOException { + PublicAccount remoteAccount = new Account(new KeyPair(), NetworkType.MIJIN).getPublicAccount(); + + String conf = getResourceAsString("config/blockchain.properties"); + String entities = getResourceAsString("config/entities.json"); + BlockchainConfigTransaction trans = new BlockchainConfigTransaction(NetworkType.MIJIN, 1, new FakeDeadline(), + BigInteger.ZERO, Optional.empty(), Optional.empty(), Optional.empty(), BigInteger.valueOf(3), conf, + entities); + + Transaction t = trans.copyForSigner(remoteAccount); + assertEquals(Optional.of(remoteAccount), t.getSigner()); + } } diff --git a/src/test/java/io/proximax/sdk/model/transaction/BlockchainUpgradeTransactionTest.java b/src/test/java/io/proximax/sdk/model/transaction/BlockchainUpgradeTransactionTest.java index 5d213fa0..9a09768b 100644 --- a/src/test/java/io/proximax/sdk/model/transaction/BlockchainUpgradeTransactionTest.java +++ b/src/test/java/io/proximax/sdk/model/transaction/BlockchainUpgradeTransactionTest.java @@ -10,10 +10,14 @@ import java.io.IOException; import java.math.BigInteger; +import java.util.Optional; import org.junit.jupiter.api.Test; +import io.proximax.core.crypto.KeyPair; import io.proximax.sdk.ResourceBasedTest; +import io.proximax.sdk.model.account.Account; +import io.proximax.sdk.model.account.PublicAccount; import io.proximax.sdk.model.blockchain.BlockchainVersion; import io.proximax.sdk.model.blockchain.NetworkType; @@ -24,8 +28,9 @@ class BlockchainUpgradeTransactionTest extends ResourceBasedTest { @Test void testConstructor() { - BlockchainUpgradeTransaction trans = BlockchainUpgradeTransaction - .create(BigInteger.ONE, new BlockchainVersion(1, 2, 3, 4), new FakeDeadline(), NetworkType.MIJIN); + BlockchainUpgradeTransaction trans = new BlockchainUpgradeTransaction(NetworkType.MIJIN, 1, new FakeDeadline(), + BigInteger.ZERO, Optional.empty(), Optional.empty(), Optional.empty(), BigInteger.ONE, + new BlockchainVersion(1, 2, 3, 4)); assertEquals(BigInteger.ONE, trans.getUpgradePeriod()); assertEquals(new BlockchainVersion(1, 2, 3, 4), trans.getNewVersion()); @@ -33,12 +38,24 @@ void testConstructor() { @Test void serialization() throws IOException { - BlockchainUpgradeTransaction trans = BlockchainUpgradeTransaction - .create(BigInteger.ONE, new BlockchainVersion(1, 2, 3, 4), new FakeDeadline(), NetworkType.MIJIN); + BlockchainUpgradeTransaction trans = new BlockchainUpgradeTransaction(NetworkType.MIJIN, 1, new FakeDeadline(), + BigInteger.ZERO, Optional.empty(), Optional.empty(), Optional.empty(), BigInteger.ONE, + new BlockchainVersion(1, 2, 3, 4)); byte[] actual = trans.generateBytes(); // saveBytes("blockchain_upgrade", actual); assertArrayEquals(actual, loadBytes("blockchain_upgrade")); } + @Test + void checkCopyToSigner() throws IOException { + PublicAccount remoteAccount = new Account(new KeyPair(), NetworkType.MIJIN).getPublicAccount(); + + BlockchainUpgradeTransaction trans = new BlockchainUpgradeTransaction(NetworkType.MIJIN, 1, new FakeDeadline(), + BigInteger.ZERO, Optional.empty(), Optional.empty(), Optional.empty(), BigInteger.ONE, + new BlockchainVersion(1, 2, 3, 4)); + + Transaction t = trans.copyForSigner(remoteAccount); + assertEquals(Optional.of(remoteAccount), t.getSigner()); + } } diff --git a/src/test/java/io/proximax/sdk/model/transaction/CosignatureTransactionTest.java b/src/test/java/io/proximax/sdk/model/transaction/CosignatureTransactionTest.java index 6e90ee52..758aa510 100644 --- a/src/test/java/io/proximax/sdk/model/transaction/CosignatureTransactionTest.java +++ b/src/test/java/io/proximax/sdk/model/transaction/CosignatureTransactionTest.java @@ -20,8 +20,10 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; +import java.math.BigInteger; import java.time.temporal.ChronoUnit; import java.util.Collections; +import java.util.Optional; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Disabled; @@ -64,7 +66,8 @@ void createACosignatureTransactionViaConstructor() throws Exception { @Test void shouldThrowExceptionWhenTransactionToCosignHasNotBeenAnnunced() throws Exception { - AggregateTransaction aggregateTransaction = AggregateTransaction.createComplete(Deadline.create(2, ChronoUnit.HOURS), Collections.emptyList(), NetworkType.MIJIN_TEST); + AggregateTransaction aggregateTransaction = new AggregateTransaction(TransactionType.AGGREGATE_COMPLETE, NetworkType.MIJIN_TEST, 1, Deadline.create(2, ChronoUnit.HOURS), BigInteger.ZERO, + Optional.empty(), Optional.empty(), Optional.empty(), Collections.emptyList(), Collections.emptyList()); assertThrows(IllegalArgumentException.class, ()->{CosignatureTransaction.create(aggregateTransaction);}, "Transaction to cosign should be announced before being able to cosign it"); diff --git a/src/test/java/io/proximax/sdk/model/transaction/FakeTransferTransaction.java b/src/test/java/io/proximax/sdk/model/transaction/FakeTransferTransaction.java index bcdfcb6b..ef1fc324 100644 --- a/src/test/java/io/proximax/sdk/model/transaction/FakeTransferTransaction.java +++ b/src/test/java/io/proximax/sdk/model/transaction/FakeTransferTransaction.java @@ -24,16 +24,33 @@ public class FakeTransferTransaction extends Transaction { - public FakeTransferTransaction(NetworkType networkType, Integer version, Deadline deadline, BigInteger fee, String signature, PublicAccount signer, TransactionInfo transactionInfo) { - super(TransactionType.TRANSFER, networkType, version, deadline, fee, Optional.of(signature), Optional.of(signer), Optional.of(transactionInfo)); - } - - public FakeTransferTransaction(NetworkType networkType, Integer version, Deadline deadline, BigInteger fee) { - super(TransactionType.TRANSFER, networkType, version, deadline, fee, Optional.empty(), Optional.empty(), Optional.empty()); - } - - @Override - byte[] generateBytes() { - throw new Error("Method no implemented"); - } + public FakeTransferTransaction(NetworkType networkType, Integer version, + TransactionDeadline deadline, BigInteger maxFee, Optional signature, Optional signer, + Optional transactionInfo) { + super(TransactionType.TRANSFER, networkType, version, deadline, maxFee, signature, signer, transactionInfo); + } + + public FakeTransferTransaction(NetworkType networkType, Integer version, TransactionDeadline deadline, BigInteger maxFee) { + this(networkType, version, deadline, maxFee, Optional.empty(), Optional.empty(), Optional.empty()); + } + + public FakeTransferTransaction(NetworkType networkType, Integer version, TransactionDeadline deadline, BigInteger maxFee, + String signature, PublicAccount signer, TransactionInfo info) { + this(networkType, version, deadline, maxFee, Optional.of(signature), Optional.of(signer), Optional.of(info)); + } + + @Override + protected byte[] generateBytes() { + throw new UnsupportedOperationException("Method no implemented"); + } + + @Override + protected int getPayloadSerializedSize() { + throw new UnsupportedOperationException("Method no implemented"); + } + + @Override + protected Transaction copyForSigner(PublicAccount signer) { + throw new UnsupportedOperationException("Method no implemented"); + } } diff --git a/src/test/java/io/proximax/sdk/model/transaction/LockFundsTransactionTest.java b/src/test/java/io/proximax/sdk/model/transaction/LockFundsTransactionTest.java index 6d6c4a91..f2782869 100644 --- a/src/test/java/io/proximax/sdk/model/transaction/LockFundsTransactionTest.java +++ b/src/test/java/io/proximax/sdk/model/transaction/LockFundsTransactionTest.java @@ -24,11 +24,13 @@ import java.io.IOException; import java.math.BigDecimal; import java.math.BigInteger; +import java.util.Optional; import org.junit.jupiter.api.Test; import io.proximax.core.crypto.KeyPair; import io.proximax.sdk.ResourceBasedTest; +import io.proximax.sdk.model.account.Account; import io.proximax.sdk.model.account.PublicAccount; import io.proximax.sdk.model.blockchain.NetworkType; import io.proximax.sdk.model.mosaic.NetworkCurrencyMosaic; @@ -40,24 +42,12 @@ void constructor() { SignedTransaction signedTransaction = new SignedTransaction("payload", "8498B38D89C1DC8A448EA5824938FF828926CD9F7747B1844B59B4B6807E878B", TransactionType.AGGREGATE_BONDED); LockFundsTransaction tx = new LockFundsTransaction(NetworkType.MIJIN, 23, new FakeDeadline(), BigInteger.ONE, - NetworkCurrencyMosaic.TEN, BigInteger.valueOf(100), signedTransaction, - "signaturestring", new PublicAccount(new KeyPair().getPublicKey().getHexString(), NetworkType.MIJIN), - TransactionInfo.create(BigInteger.ONE, "infohash", "merklehash")); - assertEquals(NetworkCurrencyMosaic.createRelative(BigDecimal.valueOf(10)), tx.getMosaic()); - assertEquals(BigInteger.valueOf(100), tx.getDuration()); - assertEquals(signedTransaction, tx.getSignedTransaction()); - } + Optional.of("signaturestring"), + Optional.of(new PublicAccount(new KeyPair().getPublicKey().getHexString(), NetworkType.MIJIN)), + Optional.of(TransactionInfo.create(BigInteger.ONE, "infohash", "merklehash")), NetworkCurrencyMosaic.TEN, + BigInteger.valueOf(100), signedTransaction); - @Test - void staticConstructor() { - SignedTransaction signedTransaction = new SignedTransaction("payload", - "8498B38D89C1DC8A448EA5824938FF828926CD9F7747B1844B59B4B6807E878B", TransactionType.AGGREGATE_BONDED); - LockFundsTransaction tx = LockFundsTransaction.create(new FakeDeadline(), - NetworkCurrencyMosaic.TEN, - BigInteger.valueOf(100), - signedTransaction, - NetworkType.MIJIN_TEST); - assertEquals(NetworkCurrencyMosaic.TEN, tx.getMosaic()); + assertEquals(NetworkCurrencyMosaic.createRelative(BigDecimal.valueOf(10)), tx.getMosaic()); assertEquals(BigInteger.valueOf(100), tx.getDuration()); assertEquals(signedTransaction, tx.getSignedTransaction()); } @@ -66,11 +56,9 @@ void staticConstructor() { void serialization() throws IOException { SignedTransaction signedTransaction = new SignedTransaction("payload", "8498B38D89C1DC8A448EA5824938FF828926CD9F7747B1844B59B4B6807E878B", TransactionType.AGGREGATE_BONDED); - LockFundsTransaction lockFundstx = LockFundsTransaction.create(new FakeDeadline(), - NetworkCurrencyMosaic.TEN, - BigInteger.valueOf(100), - signedTransaction, - NetworkType.MIJIN_TEST); + LockFundsTransaction lockFundstx = new LockFundsTransaction(NetworkType.MIJIN_TEST, 1, new FakeDeadline(), + BigInteger.ZERO, Optional.empty(), Optional.empty(), Optional.empty(), NetworkCurrencyMosaic.TEN, + BigInteger.valueOf(100), signedTransaction); byte[] actual = lockFundstx.generateBytes(); // saveBytes("lock_funds", actual); assertArrayEquals(loadBytes("lock_funds"), actual); @@ -82,11 +70,9 @@ void shouldThrowExceptionWhenSignedTransactionIsNotTypeAggregateBonded() { SignedTransaction signedTransaction = new SignedTransaction("payload", "8498B38D89C1DC8A448EA5824938FF828926CD9F7747B1844B59B4B6807E878B", TransactionType.TRANSFER); assertThrows(IllegalArgumentException.class, - () -> LockFundsTransaction.create(new FakeDeadline(), - NetworkCurrencyMosaic.TEN, - BigInteger.valueOf(100), - signedTransaction, - NetworkType.MIJIN_TEST), + () -> new LockFundsTransaction(NetworkType.MIJIN_TEST, 1, new FakeDeadline(), + BigInteger.ZERO, Optional.empty(), Optional.empty(), Optional.empty(), NetworkCurrencyMosaic.TEN, + BigInteger.valueOf(100), signedTransaction), "Signed transaction must be Aggregate Bonded Transaction"); } @@ -94,11 +80,23 @@ void shouldThrowExceptionWhenSignedTransactionIsNotTypeAggregateBonded() { void checkToStringIsImplemented() { SignedTransaction signedTransaction = new SignedTransaction("payload", "8498B38D89C1DC8A448EA5824938FF828926CD9F7747B1844B59B4B6807E878B", TransactionType.AGGREGATE_BONDED); - LockFundsTransaction tx = LockFundsTransaction.create(new FakeDeadline(), - NetworkCurrencyMosaic.TEN, - BigInteger.valueOf(100), - signedTransaction, - NetworkType.MIJIN_TEST); + LockFundsTransaction tx = new LockFundsTransaction(NetworkType.MIJIN_TEST, 1, new FakeDeadline(), + BigInteger.ZERO, Optional.empty(), Optional.empty(), Optional.empty(), NetworkCurrencyMosaic.TEN, + BigInteger.valueOf(100), signedTransaction); assertTrue(tx.toString().startsWith("LockFundsTransaction ")); } + + @Test + void checkCopyToSigner() throws IOException { + PublicAccount remoteAccount = new Account(new KeyPair(), NetworkType.MIJIN).getPublicAccount(); + + SignedTransaction signedTransaction = new SignedTransaction("payload", + "8498B38D89C1DC8A448EA5824938FF828926CD9F7747B1844B59B4B6807E878B", TransactionType.AGGREGATE_BONDED); + LockFundsTransaction trans = new LockFundsTransaction(NetworkType.MIJIN_TEST, 1, new FakeDeadline(), + BigInteger.ZERO, Optional.empty(), Optional.empty(), Optional.empty(), NetworkCurrencyMosaic.TEN, + BigInteger.valueOf(100), signedTransaction); + + Transaction t = trans.copyForSigner(remoteAccount); + assertEquals(Optional.of(remoteAccount), t.getSigner()); + } } diff --git a/src/test/java/io/proximax/sdk/model/transaction/ModifyAccountPropertyTransactionTest.java b/src/test/java/io/proximax/sdk/model/transaction/ModifyAccountPropertyTransactionTest.java index 1db03a08..7ecc3502 100644 --- a/src/test/java/io/proximax/sdk/model/transaction/ModifyAccountPropertyTransactionTest.java +++ b/src/test/java/io/proximax/sdk/model/transaction/ModifyAccountPropertyTransactionTest.java @@ -11,11 +11,15 @@ import java.io.IOException; import java.math.BigInteger; import java.util.Arrays; +import java.util.Optional; import org.junit.jupiter.api.Test; +import io.proximax.core.crypto.KeyPair; import io.proximax.sdk.ResourceBasedTest; +import io.proximax.sdk.model.account.Account; import io.proximax.sdk.model.account.Address; +import io.proximax.sdk.model.account.PublicAccount; import io.proximax.sdk.model.account.props.AccountPropertyModification; import io.proximax.sdk.model.account.props.AccountPropertyModificationType; import io.proximax.sdk.model.account.props.AccountPropertyType; @@ -30,18 +34,16 @@ class ModifyAccountPropertyTransactionTest extends ResourceBasedTest { @Test void serializationAddress() throws IOException { Address address = Address.createFromRawAddress("SBMJIUDBTCFVS24UHGND2ZJ3OX5EFKIPESXCTWLO"); - System.out.println(address); Deadline deadline = new FakeDeadline(); - ModifyAccountPropertyTransaction
trans = ModifyAccountPropertyTransaction.createForAddress( - deadline, - BigInteger.ZERO, + + ModifyAccountPropertyTransaction
trans = new ModifyAccountPropertyTransaction.AddressModification( + NetworkType.MIJIN_TEST, 1, deadline, BigInteger.ZERO, Optional.empty(), Optional.empty(), Optional.empty(), AccountPropertyType.ALLOW_ADDRESS, - Arrays.asList(new AccountPropertyModification<>(AccountPropertyModificationType.ADD, address)), - NetworkType.MIJIN_TEST); + Arrays.asList(new AccountPropertyModification<>(AccountPropertyModificationType.ADD, address))); // check that values are as expected - assertEquals(BigInteger.ZERO, trans.getFee()); + assertEquals(BigInteger.ZERO, trans.getMaxFee()); assertEquals(TransactionType.ACCOUNT_PROPERTIES_ADDRESS, trans.getType()); - assertEquals(TransactionVersion.ACCOUNT_PROPERTIES_ADDRESS.getValue(), trans.getVersion()); + assertEquals(1, trans.getVersion()); assertEquals(deadline.getInstant(), trans.getDeadline().getInstant()); assertEquals(AccountPropertyType.ALLOW_ADDRESS, trans.getPropertyType()); assertEquals(NetworkType.MIJIN_TEST, trans.getNetworkType()); @@ -56,16 +58,15 @@ void serializationAddress() throws IOException { @Test void serializationMosaic() throws IOException { Deadline deadline = new FakeDeadline(); - ModifyAccountPropertyTransaction trans = ModifyAccountPropertyTransaction.createForMosaic( - deadline, - BigInteger.ZERO, + ModifyAccountPropertyTransaction trans = new ModifyAccountPropertyTransaction.MosaicModification( + NetworkType.MIJIN_TEST, 1, deadline, BigInteger.ZERO, Optional.empty(), Optional.empty(), Optional.empty(), AccountPropertyType.ALLOW_MOSAIC, - Arrays.asList(new AccountPropertyModification<>(AccountPropertyModificationType.ADD, new MosaicId(BigInteger.ONE))), - NetworkType.MIJIN_TEST); + Arrays.asList(new AccountPropertyModification<>(AccountPropertyModificationType.ADD, + new MosaicId(BigInteger.ONE)))); // check that values are as expected - assertEquals(BigInteger.ZERO, trans.getFee()); + assertEquals(BigInteger.ZERO, trans.getMaxFee()); assertEquals(TransactionType.ACCOUNT_PROPERTIES_MOSAIC, trans.getType()); - assertEquals(TransactionVersion.ACCOUNT_PROPERTIES_MOSAIC.getValue(), trans.getVersion()); + assertEquals(1, trans.getVersion()); assertEquals(deadline.getInstant(), trans.getDeadline().getInstant()); assertEquals(AccountPropertyType.ALLOW_MOSAIC, trans.getPropertyType()); assertEquals(NetworkType.MIJIN_TEST, trans.getNetworkType()); @@ -80,14 +81,12 @@ void serializationMosaic() throws IOException { @Test void serializationEntity() throws IOException { Deadline deadline = new FakeDeadline(); - ModifyAccountPropertyTransaction trans = ModifyAccountPropertyTransaction.createForEntityType( - deadline, - BigInteger.ZERO, - AccountPropertyType.BLOCK_TRANSACTION, - Arrays.asList(new AccountPropertyModification<>(AccountPropertyModificationType.ADD, TransactionType.LOCK)), - NetworkType.MIJIN_TEST); + ModifyAccountPropertyTransaction trans = new ModifyAccountPropertyTransaction.EntityTypeModification( + NetworkType.MIJIN_TEST, 1, deadline, BigInteger.ZERO, Optional.empty(), Optional.empty(), Optional.empty(), + AccountPropertyType.BLOCK_TRANSACTION, Arrays.asList( + new AccountPropertyModification<>(AccountPropertyModificationType.ADD, TransactionType.LOCK))); // check that values are as expected - assertEquals(BigInteger.ZERO, trans.getFee()); + assertEquals(BigInteger.ZERO, trans.getMaxFee()); assertEquals(TransactionType.ACCOUNT_PROPERTIES_ENTITY_TYPE, trans.getType()); assertEquals(TransactionVersion.ACCOUNT_PROPERTIES_ENTITY_TYPE.getValue(), trans.getVersion()); assertEquals(deadline.getInstant(), trans.getDeadline().getInstant()); @@ -101,4 +100,49 @@ void serializationEntity() throws IOException { assertArrayEquals(loadBytes("account_property_entity"), actual); } + + @Test + void checkCopyToSignerAddress() throws IOException { + PublicAccount remoteAccount = new Account(new KeyPair(), NetworkType.MIJIN).getPublicAccount(); + + Address address = Address.createFromRawAddress("SBMJIUDBTCFVS24UHGND2ZJ3OX5EFKIPESXCTWLO"); + Deadline deadline = new FakeDeadline(); + + ModifyAccountPropertyTransaction
trans = new ModifyAccountPropertyTransaction.AddressModification( + NetworkType.MIJIN_TEST, 1, deadline, BigInteger.ZERO, Optional.empty(), Optional.empty(), Optional.empty(), + AccountPropertyType.ALLOW_ADDRESS, + Arrays.asList(new AccountPropertyModification<>(AccountPropertyModificationType.ADD, address))); + + Transaction t = trans.copyForSigner(remoteAccount); + assertEquals(Optional.of(remoteAccount), t.getSigner()); + } + + @Test + void checkCopyToSignerMosaic() throws IOException { + PublicAccount remoteAccount = new Account(new KeyPair(), NetworkType.MIJIN).getPublicAccount(); + + Deadline deadline = new FakeDeadline(); + ModifyAccountPropertyTransaction trans = new ModifyAccountPropertyTransaction.MosaicModification( + NetworkType.MIJIN_TEST, 1, deadline, BigInteger.ZERO, Optional.empty(), Optional.empty(), Optional.empty(), + AccountPropertyType.ALLOW_MOSAIC, + Arrays.asList(new AccountPropertyModification<>(AccountPropertyModificationType.ADD, + new MosaicId(BigInteger.ONE)))); + + Transaction t = trans.copyForSigner(remoteAccount); + assertEquals(Optional.of(remoteAccount), t.getSigner()); + } + + @Test + void checkCopyToSignerentity() throws IOException { + PublicAccount remoteAccount = new Account(new KeyPair(), NetworkType.MIJIN).getPublicAccount(); + + Deadline deadline = new FakeDeadline(); + ModifyAccountPropertyTransaction trans = new ModifyAccountPropertyTransaction.EntityTypeModification( + NetworkType.MIJIN_TEST, 1, deadline, BigInteger.ZERO, Optional.empty(), Optional.empty(), Optional.empty(), + AccountPropertyType.BLOCK_TRANSACTION, Arrays.asList( + new AccountPropertyModification<>(AccountPropertyModificationType.ADD, TransactionType.LOCK))); + + Transaction t = trans.copyForSigner(remoteAccount); + assertEquals(Optional.of(remoteAccount), t.getSigner()); + } } diff --git a/src/test/java/io/proximax/sdk/model/transaction/ModifyContractTransactionTest.java b/src/test/java/io/proximax/sdk/model/transaction/ModifyContractTransactionTest.java index 1d87b64c..44889e7d 100644 --- a/src/test/java/io/proximax/sdk/model/transaction/ModifyContractTransactionTest.java +++ b/src/test/java/io/proximax/sdk/model/transaction/ModifyContractTransactionTest.java @@ -12,10 +12,13 @@ import java.io.IOException; import java.math.BigInteger; import java.util.Arrays; +import java.util.Optional; import org.junit.jupiter.api.Test; +import io.proximax.core.crypto.KeyPair; import io.proximax.sdk.ResourceBasedTest; +import io.proximax.sdk.model.account.Account; import io.proximax.sdk.model.account.PublicAccount; import io.proximax.sdk.model.blockchain.NetworkType; @@ -24,38 +27,48 @@ */ class ModifyContractTransactionTest extends ResourceBasedTest { private static final String PUBKEYHASH = "9d6dec37eae62bf2cdfa2c292c9e346027ca2e412706536be1b5cbf22043398e"; - + @Test void constructor() throws IOException { - ModifyContractTransaction trans = ModifyContractTransaction.create(new FakeDeadline(), - BigInteger.valueOf(324), - BigInteger.valueOf(5), - "CAFE", - Arrays.asList(MultisigCosignatoryModification.add(new PublicAccount(PUBKEYHASH, NetworkType.MIJIN))), - Arrays.asList(MultisigCosignatoryModification.remove(new PublicAccount(PUBKEYHASH, NetworkType.MIJIN))), - Arrays.asList(), - NetworkType.MIJIN); + ModifyContractTransaction trans = new ModifyContractTransaction(NetworkType.MIJIN, 3, new FakeDeadline(), BigInteger.valueOf(324), + Optional.empty(), Optional.empty(), Optional.empty(), BigInteger.valueOf(5), "CAFE", Arrays.asList(MultisigCosignatoryModification.add(new PublicAccount(PUBKEYHASH, NetworkType.MIJIN))), + Arrays.asList(MultisigCosignatoryModification.remove(new PublicAccount(PUBKEYHASH, NetworkType.MIJIN))), Arrays.asList()); assertEquals("CAFE", trans.getContentHash()); - assertEquals(Arrays.asList(MultisigCosignatoryModification.add(new PublicAccount(PUBKEYHASH, NetworkType.MIJIN))), trans.getCustomersModifications()); - assertEquals(Arrays.asList(MultisigCosignatoryModification.remove(new PublicAccount(PUBKEYHASH, NetworkType.MIJIN))), trans.getExecutorsModifications()); + assertEquals(Arrays.asList(MultisigCosignatoryModification.add(new PublicAccount(PUBKEYHASH, NetworkType.MIJIN))), + trans.getCustomersModifications()); + assertEquals( + Arrays.asList(MultisigCosignatoryModification.remove(new PublicAccount(PUBKEYHASH, NetworkType.MIJIN))), + trans.getExecutorsModifications()); assertTrue(trans.getVerifiersModifications().isEmpty()); assertEquals(BigInteger.valueOf(5), trans.getDurationDelta()); } - + @Test void serialization() throws IOException { - ModifyContractTransaction trans = ModifyContractTransaction.create(new FakeDeadline(), - BigInteger.valueOf(324), - BigInteger.valueOf(5), + ModifyContractTransaction trans = new ModifyContractTransaction(NetworkType.MIJIN, 3, new FakeDeadline(), + BigInteger.valueOf(324), Optional.empty(), Optional.empty(), Optional.empty(), BigInteger.valueOf(5), "CAFE", Arrays.asList(MultisigCosignatoryModification.add(new PublicAccount(PUBKEYHASH, NetworkType.MIJIN))), Arrays.asList(MultisigCosignatoryModification.remove(new PublicAccount(PUBKEYHASH, NetworkType.MIJIN))), - Arrays.asList(), - NetworkType.MIJIN); + Arrays.asList()); // used saveBytes to store the file data byte[] actual = trans.generateBytes(); // saveBytes("modify_contract", actual); assertArrayEquals(loadBytes("modify_contract"), actual); } + @Test + void checkCopyToSigner() throws IOException { + PublicAccount remoteAccount = new Account(new KeyPair(), NetworkType.MIJIN).getPublicAccount(); + + ModifyContractTransaction trans = new ModifyContractTransaction(NetworkType.MIJIN, 3, new FakeDeadline(), + BigInteger.valueOf(324), Optional.empty(), Optional.empty(), Optional.empty(), BigInteger.valueOf(5), + "CAFE", + Arrays.asList(MultisigCosignatoryModification.add(new PublicAccount(PUBKEYHASH, NetworkType.MIJIN))), + Arrays.asList(MultisigCosignatoryModification.remove(new PublicAccount(PUBKEYHASH, NetworkType.MIJIN))), + Arrays.asList()); + + Transaction t = trans.copyForSigner(remoteAccount); + assertEquals(Optional.of(remoteAccount), t.getSigner()); + } } diff --git a/src/test/java/io/proximax/sdk/model/transaction/ModifyMetadataTransactionTest.java b/src/test/java/io/proximax/sdk/model/transaction/ModifyMetadataTransactionTest.java index de3ac697..3b44a3d6 100644 --- a/src/test/java/io/proximax/sdk/model/transaction/ModifyMetadataTransactionTest.java +++ b/src/test/java/io/proximax/sdk/model/transaction/ModifyMetadataTransactionTest.java @@ -18,7 +18,9 @@ import org.junit.jupiter.api.Test; import org.opentest4j.AssertionFailedError; +import io.proximax.core.crypto.KeyPair; import io.proximax.sdk.ResourceBasedTest; +import io.proximax.sdk.model.account.Account; import io.proximax.sdk.model.account.Address; import io.proximax.sdk.model.account.PublicAccount; import io.proximax.sdk.model.blockchain.NetworkType; @@ -36,45 +38,54 @@ class ModifyMetadataTransactionTest extends ResourceBasedTest { void genericConstructor() { Deadline deadLine = new FakeDeadline(); ModifyMetadataTransaction trans = new ModifyMetadataTransaction(TransactionType.MODIFY_ADDRESS_METADATA, - NetworkType.MIJIN, 63, deadLine, BigInteger.valueOf(765), Optional.empty(), Optional.of(new Address("MHAH", NetworkType.MIJIN)), - MetadataType.ADDRESS, Arrays.asList(), "sign", new PublicAccount("", NetworkType.MIJIN), - TransactionInfo.create(BigInteger.ONE, "infohash", "merklehash")); + NetworkType.MIJIN, 63, deadLine, BigInteger.valueOf(765), Optional.of("sign"), + Optional.of(new PublicAccount("", NetworkType.MIJIN)), + Optional.of(TransactionInfo.create(BigInteger.ONE, "infohash", "merklehash")), MetadataType.ADDRESS, + Optional.empty(), Optional.of(new Address("MHAH", NetworkType.MIJIN)), Arrays.asList()); assertEquals(TransactionType.MODIFY_ADDRESS_METADATA, trans.getType()); assertEquals(NetworkType.MIJIN, trans.getNetworkType()); assertEquals(63, trans.getVersion()); assertEquals(deadLine, trans.getDeadline()); - assertEquals(BigInteger.valueOf(765), trans.getFee()); + assertEquals(BigInteger.valueOf(765), trans.getMaxFee()); assertFalse(trans.getMetadataId().isPresent()); assertEquals(new Address("MHAH", NetworkType.MIJIN), trans.getAddress().orElseThrow(AssertionFailedError::new)); assertEquals(MetadataType.ADDRESS, trans.getMetadataType()); assertEquals(Arrays.asList(), trans.getModifications()); assertEquals("sign", trans.getSignature().orElseThrow(AssertionFailedError::new)); assertEquals(new PublicAccount("", NetworkType.MIJIN), trans.getSigner().orElseThrow(AssertionFailedError::new)); - assertEquals(TransactionInfo.create(BigInteger.ONE, "infohash", "merklehash"), trans.getTransactionInfo().orElseThrow(AssertionFailedError::new)); + assertEquals(TransactionInfo.create(BigInteger.ONE, "infohash", "merklehash"), + trans.getTransactionInfo().orElseThrow(AssertionFailedError::new)); } - + @Test void assertFailureWhenTargetMissing() { - assertThrows(IllegalArgumentException.class, () -> new ModifyMetadataTransaction(TransactionType.MODIFY_ADDRESS_METADATA, - NetworkType.MIJIN, 63, new FakeDeadline(), BigInteger.valueOf(765), Optional.empty(), Optional.empty(), - MetadataType.ADDRESS, Arrays.asList(), "sign", new PublicAccount("", NetworkType.MIJIN), - TransactionInfo.create(BigInteger.ONE, "infohash", "merklehash"))); + assertThrows(IllegalArgumentException.class, + () -> new ModifyMetadataTransaction(TransactionType.MODIFY_ADDRESS_METADATA, NetworkType.MIJIN, 63, + new FakeDeadline(), BigInteger.valueOf(765), Optional.of("sign"), + Optional.of(new PublicAccount("", NetworkType.MIJIN)), + Optional.of(TransactionInfo.create(BigInteger.ONE, "infohash", "merklehash")), MetadataType.ADDRESS, + Optional.empty(), Optional.empty(), Arrays.asList())); } - + @Test void assertFailureWhenTargetOverspecified() { - assertThrows(IllegalArgumentException.class, () -> new ModifyMetadataTransaction(TransactionType.MODIFY_ADDRESS_METADATA, - NetworkType.MIJIN, 63, new FakeDeadline(), BigInteger.valueOf(765), Optional.of(new NamespaceId("hello")), Optional.of(new Address("MHAH", NetworkType.MIJIN)), - MetadataType.ADDRESS, Arrays.asList(), "sign", new PublicAccount("", NetworkType.MIJIN), - TransactionInfo.create(BigInteger.ONE, "infohash", "merklehash"))); + assertThrows(IllegalArgumentException.class, + () -> new ModifyMetadataTransaction(TransactionType.MODIFY_ADDRESS_METADATA, NetworkType.MIJIN, 63, + new FakeDeadline(), BigInteger.valueOf(765), Optional.of("sign"), + Optional.of(new PublicAccount("", NetworkType.MIJIN)), + Optional.of(TransactionInfo.create(BigInteger.ONE, "infohash", "merklehash")), MetadataType.ADDRESS, + Optional.of(new NamespaceId("testns")), Optional.of(new Address("MHAH", NetworkType.MIJIN)), + Arrays.asList())); } - + @Test void serializationAddress() throws IOException { - ModifyMetadataTransaction trans = ModifyMetadataTransaction.createForAddress(new FakeDeadline(), - new Address("SDUP5PLHDXKBX3UU5Q52LAY4WYEKGEWC6IB3VBFM", NetworkType.MIJIN_TEST), - Arrays.asList(MetadataModification.remove("keytoremove"), MetadataModification.add("addedkey", "value")), - NetworkType.MIJIN_TEST); + ModifyMetadataTransaction trans = new ModifyMetadataTransaction(TransactionType.MODIFY_ADDRESS_METADATA, + NetworkType.MIJIN_TEST, 1, new FakeDeadline(), BigInteger.ZERO, Optional.empty(), Optional.empty(), + Optional.empty(), MetadataType.ADDRESS, Optional.empty(), + Optional.of(new Address("SDUP5PLHDXKBX3UU5Q52LAY4WYEKGEWC6IB3VBFM", NetworkType.MIJIN_TEST)), + Arrays.asList(MetadataModification.remove("keytoremove"), MetadataModification.add("addedkey", "value"))); + byte[] actual = trans.generateBytes(); // used saveBytes to store the file data // saveBytes("modify_metadata_address", actual); @@ -83,10 +94,12 @@ void serializationAddress() throws IOException { @Test void serializationMosaic() throws IOException { - ModifyMetadataTransaction trans = ModifyMetadataTransaction.createForMosaic(new FakeDeadline(), - new MosaicId(BigInteger.ONE), - Arrays.asList(MetadataModification.remove("keytoremove"), MetadataModification.add("addedkey", "value")), - NetworkType.MIJIN_TEST); + ModifyMetadataTransaction trans = new ModifyMetadataTransaction(TransactionType.MODIFY_MOSAIC_METADATA, + NetworkType.MIJIN_TEST, 1, new FakeDeadline(), BigInteger.ZERO, Optional.empty(), Optional.empty(), + Optional.empty(), MetadataType.MOSAIC, Optional.of(new MosaicId(BigInteger.ONE)), + Optional.empty(), + Arrays.asList(MetadataModification.remove("keytoremove"), MetadataModification.add("addedkey", "value"))); + byte[] actual = trans.generateBytes(); // used saveBytes to store the file data // saveBytes("modify_metadata_mosaic", actual); @@ -95,14 +108,29 @@ void serializationMosaic() throws IOException { @Test void serializationNamespace() throws IOException { - ModifyMetadataTransaction trans = ModifyMetadataTransaction.createForNamespace(new FakeDeadline(), - new NamespaceId("testns"), - Arrays.asList(MetadataModification.remove("keytoremove"), MetadataModification.add("addedkey", "value")), - NetworkType.MIJIN_TEST); + ModifyMetadataTransaction trans = new ModifyMetadataTransaction(TransactionType.MODIFY_NAMESPACE_METADATA, + NetworkType.MIJIN_TEST, 1, new FakeDeadline(), BigInteger.ZERO, Optional.empty(), Optional.empty(), + Optional.empty(), MetadataType.NAMESPACE, Optional.of(new NamespaceId("testns")), + Optional.empty(), + Arrays.asList(MetadataModification.remove("keytoremove"), MetadataModification.add("addedkey", "value"))); + // used saveBytes to store the file data byte[] actual = trans.generateBytes(); // saveBytes("modify_metadata_namespace", actual); assertArrayEquals(loadBytes("modify_metadata_namespace"), actual); } + @Test + void checkCopyToSigner() throws IOException { + PublicAccount remoteAccount = new Account(new KeyPair(), NetworkType.MIJIN).getPublicAccount(); + + ModifyMetadataTransaction trans = new ModifyMetadataTransaction(TransactionType.MODIFY_NAMESPACE_METADATA, + NetworkType.MIJIN_TEST, 1, new FakeDeadline(), BigInteger.ZERO, Optional.empty(), Optional.empty(), + Optional.empty(), MetadataType.NAMESPACE, Optional.of(new NamespaceId("testns")), + Optional.empty(), + Arrays.asList(MetadataModification.remove("keytoremove"), MetadataModification.add("addedkey", "value"))); + + Transaction t = trans.copyForSigner(remoteAccount); + assertEquals(Optional.of(remoteAccount), t.getSigner()); + } } diff --git a/src/test/java/io/proximax/sdk/model/transaction/ModifyMultisigAccountTransactionTest.java b/src/test/java/io/proximax/sdk/model/transaction/ModifyMultisigAccountTransactionTest.java index 92b7f36d..b39efd59 100644 --- a/src/test/java/io/proximax/sdk/model/transaction/ModifyMultisigAccountTransactionTest.java +++ b/src/test/java/io/proximax/sdk/model/transaction/ModifyMultisigAccountTransactionTest.java @@ -25,6 +25,7 @@ import java.time.temporal.ChronoUnit; import java.util.Arrays; import java.util.Collections; +import java.util.Optional; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -35,47 +36,46 @@ class ModifyMultisigAccountTransactionTest extends ResourceBasedTest { - @Test - void createAMultisigModificationTransactionViaConstructor() { - ModifyMultisigAccountTransaction modifyMultisigAccountTransaction = ModifyMultisigAccountTransaction.create( - new Deadline(2, ChronoUnit.HOURS), - 2, - 1, - Collections.singletonList( - new MultisigCosignatoryModification(MultisigCosignatoryModificationType.ADD, - PublicAccount.createFromPublicKey("68b3fbb18729c1fde225c57f8ce080fa828f0067e451a3fd81fa628842b0b763", NetworkType.MIJIN_TEST)) - ), - NetworkType.MIJIN_TEST - ); + @Test + void createAMultisigModificationTransactionViaConstructor() { + ModifyMultisigAccountTransaction modifyMultisigAccountTransaction = new ModifyMultisigAccountTransaction( + NetworkType.MIJIN_TEST, 3, new Deadline(2, ChronoUnit.HOURS), BigInteger.ZERO, Optional.empty(), + Optional.empty(), Optional.empty(), 2, 1, + Collections.singletonList(new MultisigCosignatoryModification(MultisigCosignatoryModificationType.ADD, + PublicAccount.createFromPublicKey("68b3fbb18729c1fde225c57f8ce080fa828f0067e451a3fd81fa628842b0b763", + NetworkType.MIJIN_TEST)))); - assertEquals(NetworkType.MIJIN_TEST, modifyMultisigAccountTransaction.getNetworkType()); - assertTrue(3 == modifyMultisigAccountTransaction.getVersion()); - long nowSinceNemesis = new Deadline(0, ChronoUnit.SECONDS).getInstant(); - assertTrue(nowSinceNemesis < modifyMultisigAccountTransaction.getDeadline().getInstant()); - assertEquals(BigInteger.valueOf(0), modifyMultisigAccountTransaction.getFee()); - assertEquals(2, modifyMultisigAccountTransaction.getMinApprovalDelta()); - assertEquals(1, modifyMultisigAccountTransaction.getMinRemovalDelta()); - assertEquals("68b3fbb18729c1fde225c57f8ce080fa828f0067e451a3fd81fa628842b0b763", modifyMultisigAccountTransaction.getModifications().get(0).getCosignatoryPublicAccount().getPublicKey()); - assertEquals(MultisigCosignatoryModificationType.ADD, modifyMultisigAccountTransaction.getModifications().get(0).getType()); - } + assertEquals(NetworkType.MIJIN_TEST, modifyMultisigAccountTransaction.getNetworkType()); + assertTrue(3 == modifyMultisigAccountTransaction.getVersion()); + long nowSinceNemesis = new Deadline(0, ChronoUnit.SECONDS).getInstant(); + assertTrue(nowSinceNemesis < modifyMultisigAccountTransaction.getDeadline().getInstant()); + assertEquals(BigInteger.valueOf(0), modifyMultisigAccountTransaction.getMaxFee()); + assertEquals(2, modifyMultisigAccountTransaction.getMinApprovalDelta()); + assertEquals(1, modifyMultisigAccountTransaction.getMinRemovalDelta()); + assertEquals("68b3fbb18729c1fde225c57f8ce080fa828f0067e451a3fd81fa628842b0b763", + modifyMultisigAccountTransaction.getModifications().get(0).getCosignatoryPublicAccount().getPublicKey()); + assertEquals(MultisigCosignatoryModificationType.ADD, + modifyMultisigAccountTransaction.getModifications().get(0).getType()); + } - @Test - @DisplayName("Serialization") - void serialization() throws IOException { - ModifyMultisigAccountTransaction modifyMultisigAccountTransaction = ModifyMultisigAccountTransaction.create( - new FakeDeadline(), - 2, - 1, - Arrays.asList( - new MultisigCosignatoryModification(MultisigCosignatoryModificationType.ADD, PublicAccount.createFromPublicKey("68b3fbb18729c1fde225c57f8ce080fa828f0067e451a3fd81fa628842b0b763", NetworkType.MIJIN_TEST)), - new MultisigCosignatoryModification(MultisigCosignatoryModificationType.ADD, PublicAccount.createFromPublicKey("cf893ffcc47c33e7f68ab1db56365c156b0736824a0c1e273f9e00b8df8f01eb", NetworkType.MIJIN_TEST)) + @Test + @DisplayName("Serialization") + void serialization() throws IOException { + ModifyMultisigAccountTransaction modifyMultisigAccountTransaction = new ModifyMultisigAccountTransaction( + NetworkType.MIJIN_TEST, 3, new FakeDeadline(), BigInteger.ZERO, Optional.empty(), Optional.empty(), + Optional.empty(), 2, 1, + Arrays.asList(new MultisigCosignatoryModification(MultisigCosignatoryModificationType.ADD, + PublicAccount.createFromPublicKey("68b3fbb18729c1fde225c57f8ce080fa828f0067e451a3fd81fa628842b0b763", + NetworkType.MIJIN_TEST)), + new MultisigCosignatoryModification(MultisigCosignatoryModificationType.ADD, + PublicAccount.createFromPublicKey( + "cf893ffcc47c33e7f68ab1db56365c156b0736824a0c1e273f9e00b8df8f01eb", + NetworkType.MIJIN_TEST)) - ), - NetworkType.MIJIN_TEST - ); + )); - byte[] actual = modifyMultisigAccountTransaction.generateBytes(); + byte[] actual = modifyMultisigAccountTransaction.generateBytes(); // saveBytes("modify_multisig_trans", actual); - assertArrayEquals(loadBytes("modify_multisig_trans"), actual); - } + assertArrayEquals(loadBytes("modify_multisig_trans"), actual); + } } diff --git a/src/test/java/io/proximax/sdk/model/transaction/MosaicDefinitionTransactionTest.java b/src/test/java/io/proximax/sdk/model/transaction/MosaicDefinitionTransactionTest.java index 834c0e3b..87d53337 100644 --- a/src/test/java/io/proximax/sdk/model/transaction/MosaicDefinitionTransactionTest.java +++ b/src/test/java/io/proximax/sdk/model/transaction/MosaicDefinitionTransactionTest.java @@ -18,18 +18,14 @@ import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; import java.math.BigInteger; -import java.time.temporal.ChronoUnit; import java.util.Optional; import org.junit.jupiter.api.Test; -import io.proximax.core.crypto.KeyPair; import io.proximax.sdk.ResourceBasedTest; -import io.proximax.sdk.model.account.PublicAccount; import io.proximax.sdk.model.blockchain.NetworkType; import io.proximax.sdk.model.mosaic.MosaicId; import io.proximax.sdk.model.mosaic.MosaicNonce; @@ -40,33 +36,11 @@ class MosaicDefinitionTransactionTest extends ResourceBasedTest { @Test void constructor() { MosaicNonce nonce = new MosaicNonce(new byte[4]); - MosaicDefinitionTransaction mosaicCreationTx = new MosaicDefinitionTransaction(NetworkType.TEST_NET, 23, new FakeDeadline(), BigInteger.ONE, nonce, + MosaicDefinitionTransaction mosaicCreationTx = new MosaicDefinitionTransaction(NetworkType.MIJIN_TEST, 23, + new FakeDeadline(), BigInteger.ZERO, Optional.empty(), Optional.empty(), Optional.empty(), nonce, new MosaicId(nonce, "B4F12E7C9F6946091E2CB8B6D3A12B50D17CCBBF646386EA27CE2946A7423DCF"), - new MosaicProperties(true, true, 3, Optional.of(BigInteger.valueOf(10))),"signaturestring", - new PublicAccount(new KeyPair().getPublicKey().getHexString(), NetworkType.MIJIN), - TransactionInfo.create(BigInteger.ONE, "infohash", "merklehash")); - assertEquals(BigInteger.valueOf(992621222383397347l), mosaicCreationTx.getMosaicId().getId()); - assertEquals(true, mosaicCreationTx.getMosaicProperties().isSupplyMutable()); - assertEquals(true, mosaicCreationTx.getMosaicProperties().isTransferable()); - assertEquals(3, mosaicCreationTx.getMosaicProperties().getDivisibility()); - assertEquals(Optional.of(BigInteger.valueOf(10)), mosaicCreationTx.getMosaicProperties().getDuration()); - assertEquals(nonce, mosaicCreationTx.getNonce()); - } - - @Test - void createAMosaicCreationTransactionViaStaticConstructor() { - MosaicNonce nonce = new MosaicNonce(new byte[4]); - MosaicDefinitionTransaction mosaicCreationTx = MosaicDefinitionTransaction.create(nonce, - new MosaicId(nonce, "B4F12E7C9F6946091E2CB8B6D3A12B50D17CCBBF646386EA27CE2946A7423DCF"), - new Deadline(2, ChronoUnit.HOURS), - new MosaicProperties(true, true, 3, Optional.of(BigInteger.valueOf(10))), - NetworkType.TEST_NET); + new MosaicProperties(true, true, 3, Optional.of(BigInteger.valueOf(10)))); - assertEquals(NetworkType.TEST_NET, mosaicCreationTx.getNetworkType()); - assertEquals(TransactionVersion.MOSAIC_DEFINITION.getValue(), mosaicCreationTx.getVersion()); - long nowSinceNemesis = new Deadline(0, ChronoUnit.SECONDS).getInstant(); - assertTrue(nowSinceNemesis < mosaicCreationTx.getDeadline().getInstant()); - assertEquals(BigInteger.valueOf(0), mosaicCreationTx.getFee()); assertEquals(BigInteger.valueOf(992621222383397347l), mosaicCreationTx.getMosaicId().getId()); assertEquals(true, mosaicCreationTx.getMosaicProperties().isSupplyMutable()); assertEquals(true, mosaicCreationTx.getMosaicProperties().isTransferable()); @@ -78,12 +52,12 @@ void createAMosaicCreationTransactionViaStaticConstructor() { @Test void serialization() throws IOException { MosaicNonce nonce = MosaicNonce.createFromBigInteger(BigInteger.valueOf(7)); - MosaicDefinitionTransaction mosaicDefinitionTransaction = MosaicDefinitionTransaction.create(nonce, + MosaicDefinitionTransaction mosaicCreationTx = new MosaicDefinitionTransaction(NetworkType.MIJIN_TEST, 3, + new FakeDeadline(), BigInteger.ZERO, Optional.empty(), Optional.empty(), Optional.empty(), nonce, new MosaicId(nonce, "B4F12E7C9F6946091E2CB8B6D3A12B50D17CCBBF646386EA27CE2946A7423DCF"), - new FakeDeadline(), - new MosaicProperties(true, true, 4, Optional.of(BigInteger.valueOf(10000))), - NetworkType.MIJIN_TEST); - byte[] actual = mosaicDefinitionTransaction.generateBytes(); + new MosaicProperties(true, true, 4, Optional.of(BigInteger.valueOf(1000)))); + + byte[] actual = mosaicCreationTx.generateBytes(); // saveBytes("mosaic_definition", actual); assertArrayEquals(loadBytes("mosaic_definition"), actual); } diff --git a/src/test/java/io/proximax/sdk/model/transaction/MosaicSupplyChangeTransactionTest.java b/src/test/java/io/proximax/sdk/model/transaction/MosaicSupplyChangeTransactionTest.java index c00dd613..5c4821cc 100644 --- a/src/test/java/io/proximax/sdk/model/transaction/MosaicSupplyChangeTransactionTest.java +++ b/src/test/java/io/proximax/sdk/model/transaction/MosaicSupplyChangeTransactionTest.java @@ -23,6 +23,7 @@ import java.io.IOException; import java.math.BigInteger; import java.time.temporal.ChronoUnit; +import java.util.Optional; import org.junit.jupiter.api.DisplayName; import org.junit.jupiter.api.Test; @@ -34,40 +35,31 @@ class MosaicSupplyChangeTransactionTest extends ResourceBasedTest { - @Test - void createAMosaicSupplyChangeTransactionViaConstructor() { + @Test + void createAMosaicSupplyChangeTransactionViaConstructor() { + MosaicSupplyChangeTransaction mosaicSupplyChangeTx = new MosaicSupplyChangeTransaction(NetworkType.MIJIN_TEST, 2, + new Deadline(2, ChronoUnit.HOURS), BigInteger.ZERO, Optional.empty(), Optional.empty(), Optional.empty(), + new MosaicId(new BigInteger("6300565133566699912")), MosaicSupplyType.INCREASE, BigInteger.valueOf(10)); - MosaicSupplyChangeTransaction mosaicSupplyChangeTx = MosaicSupplyChangeTransaction.create( - new Deadline(2, ChronoUnit.HOURS), - new MosaicId(new BigInteger("6300565133566699912")), - MosaicSupplyType.INCREASE, - BigInteger.valueOf(10), - NetworkType.MIJIN_TEST - ); + assertEquals(NetworkType.MIJIN_TEST, mosaicSupplyChangeTx.getNetworkType()); + assertTrue(2 == mosaicSupplyChangeTx.getVersion()); + long nowSinceNemesis = new Deadline(0, ChronoUnit.SECONDS).getInstant(); + assertTrue(nowSinceNemesis < mosaicSupplyChangeTx.getDeadline().getInstant()); + assertEquals(BigInteger.valueOf(0), mosaicSupplyChangeTx.getMaxFee()); + assertEquals(new BigInteger("6300565133566699912"), mosaicSupplyChangeTx.getMosaicId().getId()); + assertEquals(MosaicSupplyType.INCREASE, mosaicSupplyChangeTx.getMosaicSupplyType()); + assertEquals(BigInteger.valueOf(10), mosaicSupplyChangeTx.getDelta()); + } - assertEquals(NetworkType.MIJIN_TEST, mosaicSupplyChangeTx.getNetworkType()); - assertTrue(2 == mosaicSupplyChangeTx.getVersion()); - long nowSinceNemesis = new Deadline(0, ChronoUnit.SECONDS).getInstant(); - assertTrue(nowSinceNemesis < mosaicSupplyChangeTx.getDeadline().getInstant()); - assertEquals(BigInteger.valueOf(0), mosaicSupplyChangeTx.getFee()); - assertEquals(new BigInteger("6300565133566699912"), mosaicSupplyChangeTx.getMosaicId().getId()); - assertEquals(MosaicSupplyType.INCREASE, mosaicSupplyChangeTx.getMosaicSupplyType()); - assertEquals(BigInteger.valueOf(10), mosaicSupplyChangeTx.getDelta()); - } + @Test + @DisplayName("Serialization") + void serialization() throws IOException { + MosaicSupplyChangeTransaction mosaicSupplyChangeTx = new MosaicSupplyChangeTransaction(NetworkType.MIJIN_TEST, 2, + new FakeDeadline(), BigInteger.ZERO, Optional.empty(), Optional.empty(), Optional.empty(), + new MosaicId(new BigInteger("6300565133566699912")), MosaicSupplyType.INCREASE, BigInteger.valueOf(10)); - @Test - @DisplayName("Serialization") - void serialization() throws IOException { - MosaicSupplyChangeTransaction mosaicSupplyChangeTransaction = MosaicSupplyChangeTransaction.create( - new FakeDeadline(), - new MosaicId(new BigInteger("6300565133566699912")), - MosaicSupplyType.INCREASE, - BigInteger.valueOf(10), - NetworkType.MIJIN_TEST - ); - - byte[] actual = mosaicSupplyChangeTransaction.generateBytes(); + byte[] actual = mosaicSupplyChangeTx.generateBytes(); // saveBytes("mosaic_supply_change", actual); - assertArrayEquals(loadBytes("mosaic_supply_change"), actual); - } + assertArrayEquals(loadBytes("mosaic_supply_change"), actual); + } } diff --git a/src/test/java/io/proximax/sdk/model/transaction/RegisterNamespaceTransactionTest.java b/src/test/java/io/proximax/sdk/model/transaction/RegisterNamespaceTransactionTest.java index c6cdff6b..9d98e543 100644 --- a/src/test/java/io/proximax/sdk/model/transaction/RegisterNamespaceTransactionTest.java +++ b/src/test/java/io/proximax/sdk/model/transaction/RegisterNamespaceTransactionTest.java @@ -18,18 +18,14 @@ import static org.junit.jupiter.api.Assertions.assertArrayEquals; import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; import java.math.BigInteger; -import java.time.temporal.ChronoUnit; import java.util.Optional; import org.junit.jupiter.api.Test; -import io.proximax.core.crypto.KeyPair; import io.proximax.sdk.ResourceBasedTest; -import io.proximax.sdk.model.account.PublicAccount; import io.proximax.sdk.model.blockchain.NetworkType; import io.proximax.sdk.model.namespace.NamespaceId; import io.proximax.sdk.model.namespace.NamespaceType; @@ -38,10 +34,11 @@ class RegisterNamespaceTransactionTest extends ResourceBasedTest { @Test void constructor() { - RegisterNamespaceTransaction tx = new RegisterNamespaceTransaction(NetworkType.MIJIN, 23, new FakeDeadline(), BigInteger.ONE, - "prx", new NamespaceId(new BigInteger("4635294387305441662")), NamespaceType.SubNamespace, Optional.of(BigInteger.ONE), Optional.of(new NamespaceId(BigInteger.TEN)), - "signaturestring", new PublicAccount(new KeyPair().getPublicKey().getHexString(), NetworkType.MIJIN), - TransactionInfo.create(BigInteger.ONE, "infohash", "merklehash")); + RegisterNamespaceTransaction tx = new RegisterNamespaceTransaction(NetworkType.MIJIN, 23, new FakeDeadline(), + BigInteger.ONE, Optional.empty(), Optional.empty(), Optional.empty(), "prx", + new NamespaceId(new BigInteger("4635294387305441662")), Optional.of(BigInteger.ONE), + Optional.of(new NamespaceId(BigInteger.TEN)), NamespaceType.SubNamespace); + assertEquals("prx", tx.getNamespaceName()); assertEquals(new NamespaceId(new BigInteger("4635294387305441662")), tx.getNamespaceId()); assertEquals(NamespaceType.SubNamespace, tx.getNamespaceType()); @@ -49,48 +46,12 @@ void constructor() { assertEquals(Optional.of(new NamespaceId(BigInteger.TEN)), tx.getParentId()); } - @Test - void createANamespaceCreationRootNamespaceTransactionViaStaticConstructor() { - RegisterNamespaceTransaction registerNamespaceTransaction = RegisterNamespaceTransaction.createRootNamespace( - new Deadline(2, ChronoUnit.HOURS), - "prx", - BigInteger.valueOf(2000), - NetworkType.MIJIN_TEST); - - assertEquals(NetworkType.MIJIN_TEST, registerNamespaceTransaction.getNetworkType()); - assertEquals(2, registerNamespaceTransaction.getVersion()); - long nowSinceNemesis = new Deadline(0, ChronoUnit.SECONDS).getInstant(); - assertTrue(nowSinceNemesis < registerNamespaceTransaction.getDeadline().getInstant()); - assertEquals(BigInteger.valueOf(0), registerNamespaceTransaction.getFee()); - assertEquals("prx", registerNamespaceTransaction.getNamespaceName()); - assertEquals(NamespaceType.RootNamespace, registerNamespaceTransaction.getNamespaceType()); - assertEquals(new BigInteger("-5661737225685060674"), registerNamespaceTransaction.getNamespaceId().getId()); - assertEquals(BigInteger.valueOf(2000), registerNamespaceTransaction.getDuration().get()); - } - - @Test - void createANamespaceCreationSubNamespaceTransactionViaStaticConstructor() { - RegisterNamespaceTransaction registerNamespaceTransaction = RegisterNamespaceTransaction.createSubNamespace( - new Deadline(2, ChronoUnit.HOURS), - "newnamespace", - new NamespaceId(new BigInteger("4635294387305441662")), - NetworkType.MIJIN_TEST); - - assertEquals(NetworkType.MIJIN_TEST, registerNamespaceTransaction.getNetworkType()); - assertEquals(2, registerNamespaceTransaction.getVersion()); - long nowSinceNemesis = new Deadline(0, ChronoUnit.SECONDS).getInstant(); - assertTrue(nowSinceNemesis < registerNamespaceTransaction.getDeadline().getInstant()); - assertEquals(BigInteger.valueOf(0), registerNamespaceTransaction.getFee()); - assertEquals("newnamespace", registerNamespaceTransaction.getNamespaceName()); - assertEquals(NamespaceType.SubNamespace, registerNamespaceTransaction.getNamespaceType()); - assertEquals(new BigInteger("-7487193294859220686"), registerNamespaceTransaction.getNamespaceId().getId()); - assertEquals(new BigInteger("4635294387305441662"), registerNamespaceTransaction.getParentId().get().getId()); - } - @Test void serializationRootNamespace() throws IOException { - RegisterNamespaceTransaction registerNamespaceTransaction = RegisterNamespaceTransaction - .createRootNamespace(new FakeDeadline(), "newnamespace", BigInteger.valueOf(10000), NetworkType.MIJIN_TEST); + RegisterNamespaceTransaction registerNamespaceTransaction = new RegisterNamespaceTransaction( + NetworkType.MIJIN_TEST, 2, new FakeDeadline(), BigInteger.ZERO, Optional.empty(), Optional.empty(), + Optional.empty(), "newnamespace", new NamespaceId(IdGenerator.generateNamespaceId("newnamespace")), + Optional.of(BigInteger.valueOf(10000)), Optional.empty(), NamespaceType.RootNamespace); byte[] actual = registerNamespaceTransaction.generateBytes(); // saveBytes("register_namespace_root", actual); @@ -99,11 +60,13 @@ void serializationRootNamespace() throws IOException { @Test void serializationSubNamespace() throws IOException { - RegisterNamespaceTransaction registerNamespaceTransaction = RegisterNamespaceTransaction.createSubNamespace( - new FakeDeadline(), - "subnamespace", - new NamespaceId(new BigInteger("4635294387305441662")), - NetworkType.MIJIN_TEST); + RegisterNamespaceTransaction registerNamespaceTransaction = new RegisterNamespaceTransaction( + NetworkType.MIJIN_TEST, 2, new FakeDeadline(), BigInteger.ZERO, Optional.empty(), Optional.empty(), + Optional.empty(), "subnamespace", + new NamespaceId(IdGenerator.generateSubNamespaceIdFromParentId(new BigInteger("4635294387305441662"), + "subnamespace")), + Optional.empty(), Optional.of(new NamespaceId(new BigInteger("4635294387305441662"))), + NamespaceType.SubNamespace); byte[] actual = registerNamespaceTransaction.generateBytes(); // saveBytes("register_namespace_child", actual); diff --git a/src/test/java/io/proximax/sdk/model/transaction/SecretLockTransactionTest.java b/src/test/java/io/proximax/sdk/model/transaction/SecretLockTransactionTest.java index 4512e56d..e927fe7f 100644 --- a/src/test/java/io/proximax/sdk/model/transaction/SecretLockTransactionTest.java +++ b/src/test/java/io/proximax/sdk/model/transaction/SecretLockTransactionTest.java @@ -22,13 +22,12 @@ import java.io.IOException; import java.math.BigInteger; +import java.util.Optional; import org.junit.jupiter.api.Test; -import io.proximax.core.crypto.KeyPair; import io.proximax.sdk.ResourceBasedTest; import io.proximax.sdk.model.account.Address; -import io.proximax.sdk.model.account.PublicAccount; import io.proximax.sdk.model.blockchain.NetworkType; import io.proximax.sdk.model.mosaic.NetworkCurrencyMosaic; @@ -37,12 +36,10 @@ public class SecretLockTransactionTest extends ResourceBasedTest { @Test void constructor() { String secret = "3fc8ba10229ab5778d05d9c4b7f56676a88bf9295c185acfc0f961db5408cafe"; - SecretLockTransaction tx = new SecretLockTransaction(NetworkType.MIJIN, 23, new FakeDeadline(), BigInteger.ONE, NetworkCurrencyMosaic.TEN, - BigInteger.valueOf(100), - HashType.SHA3_256, - secret, - Address.createFromRawAddress("SDUP5PLHDXKBX3UU5Q52LAY4WYEKGEWC6IB3VBFM"),"signaturestring", new PublicAccount(new KeyPair().getPublicKey().getHexString(), NetworkType.MIJIN), - TransactionInfo.create(BigInteger.ONE, "infohash", "merklehash")); + SecretLockTransaction tx = new SecretLockTransaction(NetworkType.MIJIN, 23, new FakeDeadline(), BigInteger.ONE, + Optional.empty(), Optional.empty(), Optional.empty(), NetworkCurrencyMosaic.TEN, BigInteger.valueOf(100), + HashType.SHA3_256, secret, Address.createFromRawAddress("SDUP5PLHDXKBX3UU5Q52LAY4WYEKGEWC6IB3VBFM")); + // make assertions assertEquals(NetworkCurrencyMosaic.TEN, tx.getMosaic()); assertEquals(BigInteger.valueOf(100), tx.getDuration()); @@ -54,13 +51,11 @@ void constructor() { @Test void serialization() throws IOException { String secret = "3fc8ba10229ab5778d05d9c4b7f56676a88bf9295c185acfc0f961db5408cafe"; - SecretLockTransaction secretLocktx = SecretLockTransaction.create(new FakeDeadline(), - NetworkCurrencyMosaic.TEN, - BigInteger.valueOf(100), - HashType.SHA3_256, - secret, - Address.createFromRawAddress("SDUP5PLHDXKBX3UU5Q52LAY4WYEKGEWC6IB3VBFM"), - NetworkType.MIJIN_TEST); + SecretLockTransaction secretLocktx = new SecretLockTransaction(NetworkType.MIJIN_TEST, 1, new FakeDeadline(), + BigInteger.ZERO, Optional.empty(), Optional.empty(), Optional.empty(), NetworkCurrencyMosaic.TEN, + BigInteger.valueOf(100), HashType.SHA3_256, secret, + Address.createFromRawAddress("SDUP5PLHDXKBX3UU5Q52LAY4WYEKGEWC6IB3VBFM")); + byte[] actual = secretLocktx.generateBytes(); // saveBytes("secret_lock", actual); assertArrayEquals(loadBytes("secret_lock"), actual); @@ -69,13 +64,10 @@ void serialization() throws IOException { @Test void shouldThrowErrorWhenSecretIsNotValid() { assertThrows(IllegalArgumentException.class, () -> { - SecretLockTransaction secretLocktx = SecretLockTransaction.create(new FakeDeadline(), - NetworkCurrencyMosaic.TEN, - BigInteger.valueOf(100), - HashType.SHA3_256, - "non valid hash", - Address.createFromRawAddress("SDUP5PLHDXKBX3UU5Q52LAY4WYEKGEWC6IB3VBFM"), - NetworkType.MIJIN_TEST); + SecretLockTransaction secretLocktx = new SecretLockTransaction(NetworkType.MIJIN_TEST, 1, new FakeDeadline(), + BigInteger.ZERO, Optional.empty(), Optional.empty(), Optional.empty(), NetworkCurrencyMosaic.TEN, + BigInteger.valueOf(100), HashType.SHA3_256, "this is not valid", + Address.createFromRawAddress("SDUP5PLHDXKBX3UU5Q52LAY4WYEKGEWC6IB3VBFM")); }, "not a valid secret"); } } diff --git a/src/test/java/io/proximax/sdk/model/transaction/SecretProofTransactionTest.java b/src/test/java/io/proximax/sdk/model/transaction/SecretProofTransactionTest.java index 8dd29aa5..7cea4fa6 100644 --- a/src/test/java/io/proximax/sdk/model/transaction/SecretProofTransactionTest.java +++ b/src/test/java/io/proximax/sdk/model/transaction/SecretProofTransactionTest.java @@ -22,6 +22,7 @@ import java.io.IOException; import java.math.BigInteger; +import java.util.Optional; import org.junit.jupiter.api.Test; @@ -38,10 +39,12 @@ void constructor() { String secret = "3fc8ba10229ab5778d05d9c4b7f56676a88bf9295c185acfc0f961db5408cafe"; String secretSeed = "9a493664"; Recipient recipient = Recipient.from(new Address("XY", NetworkType.MAIN_NET)); - SecretProofTransaction tx = new SecretProofTransaction(NetworkType.MIJIN, 23, new FakeDeadline(), BigInteger.ONE, - HashType.SHA3_256, recipient, secret, secretSeed, "signaturestring", - new PublicAccount(new KeyPair().getPublicKey().getHexString(), NetworkType.MIJIN), - TransactionInfo.create(BigInteger.ONE, "infohash", "merklehash")); + SecretProofTransaction tx = new SecretProofTransaction(NetworkType.MAIN_NET, 23, new FakeDeadline(), BigInteger.ONE, + Optional.of("signaturestring"), + Optional.of(new PublicAccount(new KeyPair().getPublicKey().getHexString(), NetworkType.MAIN_NET)), + Optional.of(TransactionInfo.create(BigInteger.ONE, "infohash", "merklehash")), HashType.SHA3_256, secret, + secretSeed, recipient); + assertEquals(secret, tx.getSecret()); assertEquals(secretSeed, tx.getProof()); assertEquals(HashType.SHA3_256, tx.getHashType()); @@ -53,8 +56,11 @@ void serialization() throws IOException { String secret = "3fc8ba10229ab5778d05d9c4b7f56676a88bf9295c185acfc0f961db5408cafe"; String secretSeed = "9a493664"; Recipient recipient = Recipient.from(new Address("XY", NetworkType.MAIN_NET)); - SecretProofTransaction secretProoftx = SecretProofTransaction - .create(new FakeDeadline(), HashType.SHA3_256, recipient, secret, secretSeed, NetworkType.MIJIN_TEST); + + SecretProofTransaction secretProoftx = new SecretProofTransaction(NetworkType.MAIN_NET, 1, new FakeDeadline(), + BigInteger.ONE, Optional.empty(), Optional.empty(), Optional.empty(), HashType.SHA3_256, secret, secretSeed, + recipient); + byte[] actual = secretProoftx.generateBytes(); // saveBytes("secret_proof", actual); assertArrayEquals(loadBytes("secret_proof"), actual); @@ -65,9 +71,8 @@ void shouldThrowErrorWhenSecretIsNotValid() { String proof = "B778A39A3663719DFC5E48C9D78431B1E45C2AF9DF538782BF199C189DABEAC7680ADA57DCEC8EEE91" + "C4E3BF3BFA9AF6FFDE90CD1D249D1C6121D7B759A001B1"; Recipient recipient = Recipient.from(new Address("XY", NetworkType.MAIN_NET)); - assertThrows(IllegalArgumentException.class, () -> { - SecretProofTransaction secretProoftx = SecretProofTransaction - .create(new FakeDeadline(), HashType.SHA3_256, recipient, "non valid hash", proof, NetworkType.MIJIN_TEST); - }, "not a valid secret"); + assertThrows(IllegalArgumentException.class, () -> new SecretProofTransaction(NetworkType.MAIN_NET, 1, new FakeDeadline(), + BigInteger.ONE, Optional.empty(), Optional.empty(), Optional.empty(), HashType.SHA3_256, "non valid hash", proof, + recipient), "not a valid secret"); } } diff --git a/src/test/java/io/proximax/sdk/model/transaction/TransferTransactionTest.java b/src/test/java/io/proximax/sdk/model/transaction/TransferTransactionTest.java index cc0454d0..0c05e17a 100644 --- a/src/test/java/io/proximax/sdk/model/transaction/TransferTransactionTest.java +++ b/src/test/java/io/proximax/sdk/model/transaction/TransferTransactionTest.java @@ -25,6 +25,7 @@ import java.math.BigInteger; import java.time.temporal.ChronoUnit; import java.util.Arrays; +import java.util.Optional; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.DisplayName; @@ -39,84 +40,78 @@ import io.proximax.sdk.model.mosaic.MosaicId; class TransferTransactionTest extends ResourceBasedTest { - static Account account; - - @BeforeAll - public static void setup() { - account = new Account("787225aaff3d2c71f4ffa32d4f19ec4922f3cd869747f267378f81f8e3fcb12d", NetworkType.MIJIN_TEST); - } - - @Test - void createATransferTransactionViaStaticConstructor() { - - TransferTransaction transferTx = TransferTransaction.create( - new Deadline(2, ChronoUnit.HOURS), - new Address("SDGLFW-DSHILT-IUHGIB-H5UGX2-VYF5VN-JEKCCD-BR26", NetworkType.MIJIN_TEST), - Arrays.asList(), - PlainMessage.Empty, - NetworkType.MIJIN_TEST - ); - - assertEquals(NetworkType.MIJIN_TEST, transferTx.getNetworkType()); - assertTrue(3 == transferTx.getVersion()); - long nowSinceNemesis = new Deadline(0, ChronoUnit.SECONDS).getInstant(); - assertTrue(nowSinceNemesis < transferTx.getDeadline().getInstant()); - assertEquals(BigInteger.valueOf(0), transferTx.getFee()); - assertTrue(new Address("SDGLFW-DSHILT-IUHGIB-H5UGX2-VYF5VN-JEKCCD-BR26", NetworkType.MIJIN_TEST) - .equals(transferTx.getRecipient().getAddress().orElseThrow(RuntimeException::new))); - assertEquals(0, transferTx.getMosaics().size()); - assertNotNull(transferTx.getMessage()); - } - - @Test - @DisplayName("Serialization") - void serialization() throws IOException { - TransferTransaction transferTransaction = TransferTransaction.create( - new FakeDeadline(), - new Address("SDUP5PLHDXKBX3UU5Q52LAY4WYEKGEWC6IB3VBFM", NetworkType.MIJIN_TEST), - Arrays.asList( - new Mosaic(new MosaicId(new BigInteger("95442763262823")), BigInteger.valueOf(100)) - ), - PlainMessage.Empty, - NetworkType.MIJIN_TEST - ); - byte[] actual = transferTransaction.generateBytes(); + static Account account; + + @BeforeAll + public static void setup() { + account = new Account("787225aaff3d2c71f4ffa32d4f19ec4922f3cd869747f267378f81f8e3fcb12d", NetworkType.MIJIN_TEST); + } + + @Test + void createATransferTransaction() { + + TransferTransaction transferTx = new TransferTransaction(NetworkType.MIJIN_TEST, 3, + new Deadline(2, ChronoUnit.HOURS), BigInteger.valueOf(37750), Optional.empty(), Optional.empty(), + Optional.empty(), + Recipient.from(new Address("SDGLFW-DSHILT-IUHGIB-H5UGX2-VYF5VN-JEKCCD-BR26", NetworkType.MIJIN_TEST)), + Arrays.asList(), PlainMessage.Empty); + + assertEquals(NetworkType.MIJIN_TEST, transferTx.getNetworkType()); + assertEquals(3, transferTx.getVersion()); + long nowSinceNemesis = new Deadline(0, ChronoUnit.SECONDS).getInstant(); + assertTrue(nowSinceNemesis < transferTx.getDeadline().getInstant()); + assertEquals(BigInteger.valueOf(37750), transferTx.getMaxFee()); + assertTrue(new Address("SDGLFW-DSHILT-IUHGIB-H5UGX2-VYF5VN-JEKCCD-BR26", NetworkType.MIJIN_TEST) + .equals(transferTx.getRecipient().getAddress().orElseThrow(RuntimeException::new))); + assertEquals(0, transferTx.getMosaics().size()); + assertNotNull(transferTx.getMessage()); + } + + @Test + @DisplayName("Serialization") + void serialization() throws IOException { + TransferTransaction transferTransaction = new TransferTransaction(NetworkType.MIJIN_TEST, 3, new FakeDeadline(), + BigInteger.ZERO, Optional.empty(), Optional.empty(), Optional.empty(), + Recipient.from(new Address("SDUP5PLHDXKBX3UU5Q52LAY4WYEKGEWC6IB3VBFM", NetworkType.MIJIN_TEST)), + Arrays.asList(new Mosaic(new MosaicId(new BigInteger("95442763262823")), BigInteger.valueOf(100))), + PlainMessage.Empty); + + byte[] actual = transferTransaction.generateBytes(); // saveBytes("transfer_trans", actual); - assertArrayEquals(loadBytes("transfer_trans"), actual); - } - - @Test - @DisplayName("To aggregate") - void toAggregate() throws IOException { - TransferTransaction transferTransaction = TransferTransaction.create( - new FakeDeadline(), - new Address("SDUP5PLHDXKBX3UU5Q52LAY4WYEKGEWC6IB3VBFM", NetworkType.MIJIN_TEST), - Arrays.asList( - new Mosaic(new MosaicId(new BigInteger("95442763262823")), BigInteger.valueOf(100)) - ), - PlainMessage.Empty, - NetworkType.MIJIN_TEST - ); - byte[] actual = transferTransaction.toAggregate(new PublicAccount("9A49366406ACA952B88BADF5F1E9BE6CE4968141035A60BE503273EA65456B24", NetworkType.MIJIN_TEST)).toAggregateTransactionBytes(); + assertArrayEquals(loadBytes("transfer_trans"), actual); + } + + @Test + @DisplayName("To aggregate") + void toAggregate() throws IOException { + TransferTransaction transferTransaction = new TransferTransaction(NetworkType.MIJIN_TEST, 3, new FakeDeadline(), + BigInteger.ZERO, Optional.empty(), Optional.empty(), Optional.empty(), + Recipient.from(new Address("SDUP5PLHDXKBX3UU5Q52LAY4WYEKGEWC6IB3VBFM", NetworkType.MIJIN_TEST)), + Arrays.asList(new Mosaic(new MosaicId(new BigInteger("95442763262823")), BigInteger.valueOf(100))), + PlainMessage.Empty); + + byte[] actual = transferTransaction + .toAggregate(new PublicAccount("9A49366406ACA952B88BADF5F1E9BE6CE4968141035A60BE503273EA65456B24", + NetworkType.MIJIN_TEST)) + .toAggregateTransactionBytes(); // saveBytes("transfer_trans_toagg", actual); - assertArrayEquals(loadBytes("transfer_trans_toagg"), actual); - } - - @Test - void serializeAndSignTransaction() { - TransferTransaction transferTransaction = TransferTransaction.create( - new FakeDeadline(), - new Address("SDUP5PLHDXKBX3UU5Q52LAY4WYEKGEWC6IB3VBFM", NetworkType.MIJIN_TEST), - Arrays.asList( - new Mosaic(new MosaicId(new BigInteger("95442763262823")), BigInteger.valueOf(100)) - ), - PlainMessage.Empty, - NetworkType.MIJIN_TEST - ); - - SignedTransaction signedTransaction = transferTransaction.signWith(account, "7B631D803F912B00DC0CBED3014BBD17A302BA50B99D233B9C2D9533B842ABDF"); - - assertEquals("A700000012714D1BA6A1169BBEC67ADE7B77D107BA81D22CB90AF46AC398549FEE693F21228F94FBEDE0122318408F8247FEEBD753D6D6EF9F243E0E0507B38922B222081026D70E1954775749C6811084D6450A3184D977383F0E4282CD47118AF377550300009054410000000000000000010000000000000090E8FEBD671DD41BEE94EC3BA5831CB608A312C2F203BA84AC01000100672B0000CE5600006400000000000000", signedTransaction.getPayload()); - assertEquals("00E440438762F09A150235494F9C11F074F310D102CB708751C712B4A84F810A", signedTransaction.getHash()); - } + assertArrayEquals(loadBytes("transfer_trans_toagg"), actual); + } + + @Test + void serializeAndSignTransaction() { + TransferTransaction transferTransaction = new TransferTransaction(NetworkType.MIJIN_TEST, 3, new FakeDeadline(), + BigInteger.ZERO, Optional.empty(), Optional.empty(), Optional.empty(), + Recipient.from(new Address("SDUP5PLHDXKBX3UU5Q52LAY4WYEKGEWC6IB3VBFM", NetworkType.MIJIN_TEST)), + Arrays.asList(new Mosaic(new MosaicId(new BigInteger("95442763262823")), BigInteger.valueOf(100))), + PlainMessage.Empty); + + SignedTransaction signedTransaction = transferTransaction.signWith(account, + "7B631D803F912B00DC0CBED3014BBD17A302BA50B99D233B9C2D9533B842ABDF"); + + assertEquals( + "A700000012714D1BA6A1169BBEC67ADE7B77D107BA81D22CB90AF46AC398549FEE693F21228F94FBEDE0122318408F8247FEEBD753D6D6EF9F243E0E0507B38922B222081026D70E1954775749C6811084D6450A3184D977383F0E4282CD47118AF377550300009054410000000000000000010000000000000090E8FEBD671DD41BEE94EC3BA5831CB608A312C2F203BA84AC01000100672B0000CE5600006400000000000000", + signedTransaction.getPayload()); + assertEquals("00E440438762F09A150235494F9C11F074F310D102CB708751C712B4A84F810A", signedTransaction.getHash()); + } } diff --git a/src/test/java/io/proximax/sdk/model/transaction/builder/AccountLinkTransactionBuilderTest.java b/src/test/java/io/proximax/sdk/model/transaction/builder/AccountLinkTransactionBuilderTest.java new file mode 100644 index 00000000..898a4bb6 --- /dev/null +++ b/src/test/java/io/proximax/sdk/model/transaction/builder/AccountLinkTransactionBuilderTest.java @@ -0,0 +1,58 @@ +/* + * Copyright 2019 ProximaX Limited. All rights reserved. + * Use of this source code is governed by the Apache 2.0 + * license that can be found in the LICENSE file. + */ +package io.proximax.sdk.model.transaction.builder; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.math.BigInteger; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import io.proximax.core.crypto.KeyPair; +import io.proximax.sdk.FeeCalculationStrategy; +import io.proximax.sdk.model.account.Account; +import io.proximax.sdk.model.account.PublicAccount; +import io.proximax.sdk.model.blockchain.NetworkType; +import io.proximax.sdk.model.transaction.AccountLinkAction; +import io.proximax.sdk.model.transaction.AccountLinkTransaction; + +/** + * {@link AccountLinkTransactionBuilder} tests + */ +class AccountLinkTransactionBuilderTest { + + private static final NetworkType NETWORK_TYPE = NetworkType.MIJIN_TEST; + + private AccountLinkTransactionBuilder builder; + + @BeforeEach + void setUp() { + builder = new AccountLinkTransactionBuilder(); + builder.networkType(NETWORK_TYPE); + builder.deadlineDuration(BigInteger.valueOf(60_000)); + builder.feeCalculationStrategy(FeeCalculationStrategy.MEDIUM); + } + + @Test + void testLink() { + PublicAccount pa = new Account(new KeyPair(), NETWORK_TYPE).getPublicAccount(); + AccountLinkTransaction trans = builder.link(pa).build(); + + assertEquals(AccountLinkAction.LINK, trans.getAction()); + assertEquals(pa, trans.getRemoteAccount()); + } + + @Test + void testUnlink() { + PublicAccount pa = new Account(new KeyPair(), NETWORK_TYPE).getPublicAccount(); + AccountLinkTransaction trans = builder.unlink(pa).build(); + + assertEquals(AccountLinkAction.UNLINK, trans.getAction()); + assertEquals(pa, trans.getRemoteAccount()); + } + +} diff --git a/src/test/java/io/proximax/sdk/model/transaction/builder/AggregateTransactionBuilderTest.java b/src/test/java/io/proximax/sdk/model/transaction/builder/AggregateTransactionBuilderTest.java new file mode 100644 index 00000000..efede8a8 --- /dev/null +++ b/src/test/java/io/proximax/sdk/model/transaction/builder/AggregateTransactionBuilderTest.java @@ -0,0 +1,109 @@ +/* + * Copyright 2019 ProximaX Limited. All rights reserved. + * Use of this source code is governed by the Apache 2.0 + * license that can be found in the LICENSE file. + */ +package io.proximax.sdk.model.transaction.builder; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.math.BigInteger; +import java.time.temporal.ChronoUnit; +import java.util.Arrays; +import java.util.Optional; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import io.proximax.sdk.FeeCalculationStrategy; +import io.proximax.sdk.model.account.Address; +import io.proximax.sdk.model.account.PublicAccount; +import io.proximax.sdk.model.blockchain.NetworkType; +import io.proximax.sdk.model.transaction.AggregateTransaction; +import io.proximax.sdk.model.transaction.AggregateTransactionCosignature; +import io.proximax.sdk.model.transaction.Deadline; +import io.proximax.sdk.model.transaction.PlainMessage; +import io.proximax.sdk.model.transaction.Recipient; +import io.proximax.sdk.model.transaction.TransactionType; +import io.proximax.sdk.model.transaction.TransactionVersion; +import io.proximax.sdk.model.transaction.TransferTransaction; + +/** + * {@link AggregateTransactionBuilder} tests + */ +class AggregateTransactionBuilderTest { + + private static final NetworkType NETWORK_TYPE = NetworkType.MIJIN_TEST; + + private AggregateTransactionBuilder completeBuilder; + private AggregateTransactionBuilder bondedBuilder; + + @BeforeEach + void setUp() { + completeBuilder = initBuilder(AggregateTransactionBuilder.createComplete()); + bondedBuilder = initBuilder(AggregateTransactionBuilder.createBonded()); + + } + + private static AggregateTransactionBuilder initBuilder(AggregateTransactionBuilder builder) { + builder.networkType(NETWORK_TYPE); + builder.deadlineDuration(BigInteger.valueOf(60_000)); + builder.feeCalculationStrategy(FeeCalculationStrategy.MEDIUM); + return builder; + } + + @Test + void testCompleteNoCosig() { + TransferTransaction transferTx = new TransferTransaction(NetworkType.MIJIN_TEST, 3, + new Deadline(2, ChronoUnit.HOURS), BigInteger.valueOf(37750), Optional.empty(), Optional.empty(), + Optional.empty(), + Recipient.from(new Address("SDGLFW-DSHILT-IUHGIB-H5UGX2-VYF5VN-JEKCCD-BR26", NetworkType.MIJIN_TEST)), + Arrays.asList(), PlainMessage.Empty); + + AggregateTransaction agg = completeBuilder.innerTransactions(transferTx).build(); + + assertEquals(1, agg.getInnerTransactions().size()); + assertEquals(transferTx, agg.getInnerTransactions().get(0)); + assertEquals(TransactionType.AGGREGATE_COMPLETE, agg.getType()); + assertEquals(TransactionVersion.AGGREGATE_COMPLETE.getValue(), agg.getVersion()); + } + + @Test + void testBondedNoCosig() { + TransferTransaction transferTx = new TransferTransaction(NetworkType.MIJIN_TEST, 3, + new Deadline(2, ChronoUnit.HOURS), BigInteger.valueOf(37750), Optional.empty(), Optional.empty(), + Optional.empty(), + Recipient.from(new Address("SDGLFW-DSHILT-IUHGIB-H5UGX2-VYF5VN-JEKCCD-BR26", NetworkType.MIJIN_TEST)), + Arrays.asList(), PlainMessage.Empty); + + AggregateTransaction agg = bondedBuilder.innerTransactions(transferTx).build(); + + assertEquals(1, agg.getInnerTransactions().size()); + assertEquals(transferTx, agg.getInnerTransactions().get(0)); + assertEquals(TransactionType.AGGREGATE_BONDED, agg.getType()); + assertEquals(TransactionVersion.AGGREGATE_BONDED.getValue(), agg.getVersion()); + + } + + @Test + void testCompleteWithCosig() { + TransferTransaction transferTx = new TransferTransaction(NetworkType.MIJIN_TEST, 3, + new Deadline(2, ChronoUnit.HOURS), BigInteger.valueOf(37750), Optional.empty(), Optional.empty(), + Optional.empty(), + Recipient.from(new Address("SDGLFW-DSHILT-IUHGIB-H5UGX2-VYF5VN-JEKCCD-BR26", NetworkType.MIJIN_TEST)), + Arrays.asList(), PlainMessage.Empty); + + PublicAccount puba = new PublicAccount("9A49366406ACA952B88BADF5F1E9BE6CE4968141035A60BE503273EA65456B24", + NetworkType.MIJIN_TEST); + AggregateTransactionCosignature cosig = new AggregateTransactionCosignature("signature", + puba); + + AggregateTransaction agg = completeBuilder.innerTransactions(transferTx).cosignatures(cosig).build(); + + assertEquals(1, agg.getCosignatures().size()); + assertEquals("signature", agg.getCosignatures().get(0).getSignature()); + assertEquals(puba, agg.getCosignatures().get(0).getSigner()); + } + + +} diff --git a/src/test/java/io/proximax/sdk/model/transaction/builder/AliasTransactionBuilderTest.java b/src/test/java/io/proximax/sdk/model/transaction/builder/AliasTransactionBuilderTest.java new file mode 100644 index 00000000..48c2935f --- /dev/null +++ b/src/test/java/io/proximax/sdk/model/transaction/builder/AliasTransactionBuilderTest.java @@ -0,0 +1,101 @@ +/* + * Copyright 2019 ProximaX Limited. All rights reserved. + * Use of this source code is governed by the Apache 2.0 + * license that can be found in the LICENSE file. + */ +package io.proximax.sdk.model.transaction.builder; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +import java.math.BigInteger; +import java.util.Optional; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import io.proximax.sdk.FeeCalculationStrategy; +import io.proximax.sdk.model.account.Address; +import io.proximax.sdk.model.blockchain.NetworkType; +import io.proximax.sdk.model.mosaic.MosaicId; +import io.proximax.sdk.model.namespace.NamespaceId; +import io.proximax.sdk.model.transaction.AliasTransaction; + +/** + * {@link AliasTransactionBuilder} tests + */ +class AliasTransactionBuilderTest { + + private static final NetworkType NETWORK_TYPE = NetworkType.MIJIN_TEST; + + private AliasTransactionBuilder addressBuilder; + private AliasTransactionBuilder mosaicBuilder; + + @BeforeEach + void setUp() { + addressBuilder = init(AliasTransactionBuilder.createForAddress()); + mosaicBuilder = init(AliasTransactionBuilder.createForMosaic()); + + } + + private static AliasTransactionBuilder init(AliasTransactionBuilder builder) { + builder.networkType(NETWORK_TYPE); + builder.deadlineDuration(BigInteger.valueOf(60_000)); + builder.feeCalculationStrategy(FeeCalculationStrategy.MEDIUM); + return builder; + } + + @Test + void testLinkMosaic() { + MosaicId mosid = new MosaicId(BigInteger.valueOf(123456789)); + NamespaceId nsid = new NamespaceId("test.namespace"); + + AliasTransaction trans = mosaicBuilder.link(mosid).namespaceId(nsid).build(); + + assertEquals(Optional.of(mosid), trans.getMosaicId()); + assertEquals(nsid, trans.getNamespaceId()); + } + + @Test + void testLinkAddress() { + Address addr = new Address("SADD", NETWORK_TYPE); + NamespaceId nsid = new NamespaceId("test.namespace"); + + AliasTransaction trans = addressBuilder.link(addr).namespaceId(nsid).build(); + + assertEquals(Optional.of(addr), trans.getAddress()); + assertEquals(nsid, trans.getNamespaceId()); + } + + @Test + void testUnlinkMosaic() { + MosaicId mosid = new MosaicId(BigInteger.valueOf(123456789)); + NamespaceId nsid = new NamespaceId("test.namespace"); + + AliasTransaction trans = mosaicBuilder.unlink(mosid).namespaceId(nsid).build(); + + assertEquals(Optional.of(mosid), trans.getMosaicId()); + assertEquals(nsid, trans.getNamespaceId()); + } + + @Test + void testUnlinkAddress() { + Address addr = new Address("SADD", NETWORK_TYPE); + NamespaceId nsid = new NamespaceId("test.namespace"); + + AliasTransaction trans = addressBuilder.unlink(addr).namespaceId(nsid).build(); + + assertEquals(Optional.of(addr), trans.getAddress()); + assertEquals(nsid, trans.getNamespaceId()); + } + + @Test + void testTypeValidation() { + MosaicId mosid = new MosaicId(BigInteger.valueOf(123456789)); + Address addr = new Address("SADD", NETWORK_TYPE); + NamespaceId nsid = new NamespaceId("test.namespace"); + + assertThrows(IllegalArgumentException.class, () -> addressBuilder.mosaicId(mosid).namespaceId(nsid).build()); + assertThrows(IllegalArgumentException.class, () -> mosaicBuilder.address(addr).namespaceId(nsid).build()); + } +} diff --git a/src/test/java/io/proximax/sdk/model/transaction/builder/BlockchainConfigTransactionBuilderTest.java b/src/test/java/io/proximax/sdk/model/transaction/builder/BlockchainConfigTransactionBuilderTest.java new file mode 100644 index 00000000..45b5d8ac --- /dev/null +++ b/src/test/java/io/proximax/sdk/model/transaction/builder/BlockchainConfigTransactionBuilderTest.java @@ -0,0 +1,44 @@ +/* + * Copyright 2019 ProximaX Limited. All rights reserved. + * Use of this source code is governed by the Apache 2.0 + * license that can be found in the LICENSE file. + */ +package io.proximax.sdk.model.transaction.builder; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.math.BigInteger; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import io.proximax.sdk.FeeCalculationStrategy; +import io.proximax.sdk.model.blockchain.NetworkType; +import io.proximax.sdk.model.transaction.BlockchainConfigTransaction; + +/** + * {@link BlockchainConfigTransactionBuilder} tests + */ +class BlockchainConfigTransactionBuilderTest { + + private static final NetworkType NETWORK_TYPE = NetworkType.MIJIN_TEST; + + private BlockchainConfigTransactionBuilder builder; + + @BeforeEach + void setUp() { + builder = new BlockchainConfigTransactionBuilder(); + builder.networkType(NETWORK_TYPE); + builder.deadlineDuration(BigInteger.valueOf(60_000)); + builder.feeCalculationStrategy(FeeCalculationStrategy.MEDIUM); + } + @Test + void test() { + BlockchainConfigTransaction trans = builder.applyHeightDelta(BigInteger.ONE).blockchainConfig("config").supportedEntityVersions("entity versions").build(); + + assertEquals(BigInteger.ONE, trans.getApplyHeightDelta()); + assertEquals("config", trans.getBlockchainConfig()); + assertEquals("entity versions", trans.getSupportedEntityVersions()); + } + +} diff --git a/src/test/java/io/proximax/sdk/model/transaction/builder/BlockchainUpgradeTransactionBuilderTest.java b/src/test/java/io/proximax/sdk/model/transaction/builder/BlockchainUpgradeTransactionBuilderTest.java new file mode 100644 index 00000000..48e13ab2 --- /dev/null +++ b/src/test/java/io/proximax/sdk/model/transaction/builder/BlockchainUpgradeTransactionBuilderTest.java @@ -0,0 +1,45 @@ +/* + * Copyright 2019 ProximaX Limited. All rights reserved. + * Use of this source code is governed by the Apache 2.0 + * license that can be found in the LICENSE file. + */ +package io.proximax.sdk.model.transaction.builder; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.math.BigInteger; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import io.proximax.sdk.FeeCalculationStrategy; +import io.proximax.sdk.model.blockchain.BlockchainVersion; +import io.proximax.sdk.model.blockchain.NetworkType; +import io.proximax.sdk.model.transaction.BlockchainUpgradeTransaction; + +/** + * {@link BlockchainUpgradeTransactionBuilder} tests + */ +class BlockchainUpgradeTransactionBuilderTest { + + private static final NetworkType NETWORK_TYPE = NetworkType.MIJIN_TEST; + + private BlockchainUpgradeTransactionBuilder builder; + + @BeforeEach + void setUp() { + builder = new BlockchainUpgradeTransactionBuilder(); + builder.networkType(NETWORK_TYPE); + builder.deadlineDuration(BigInteger.valueOf(60_000)); + builder.feeCalculationStrategy(FeeCalculationStrategy.MEDIUM); + } + @Test + void test() { + BlockchainVersion version = new BlockchainVersion(1, 2, 3, 4); + BlockchainUpgradeTransaction trans = builder.newVersion(version).upgradePeriod(BigInteger.TEN).build(); + + assertEquals(version, trans.getNewVersion()); + assertEquals(BigInteger.TEN, trans.getUpgradePeriod()); + } + +} diff --git a/src/test/java/io/proximax/sdk/model/transaction/builder/LockFundsTransactionBuilderTest.java b/src/test/java/io/proximax/sdk/model/transaction/builder/LockFundsTransactionBuilderTest.java new file mode 100644 index 00000000..79c9cb14 --- /dev/null +++ b/src/test/java/io/proximax/sdk/model/transaction/builder/LockFundsTransactionBuilderTest.java @@ -0,0 +1,49 @@ +/* + * Copyright 2019 ProximaX Limited. All rights reserved. + * Use of this source code is governed by the Apache 2.0 + * license that can be found in the LICENSE file. + */ +package io.proximax.sdk.model.transaction.builder; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.math.BigInteger; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import io.proximax.sdk.FeeCalculationStrategy; +import io.proximax.sdk.model.blockchain.NetworkType; +import io.proximax.sdk.model.mosaic.NetworkCurrencyMosaic; +import io.proximax.sdk.model.transaction.LockFundsTransaction; +import io.proximax.sdk.model.transaction.SignedTransaction; +import io.proximax.sdk.model.transaction.TransactionType; + +/** + * {@link LockFundsTransactionBuilder} tests + */ +class LockFundsTransactionBuilderTest { + + private static final NetworkType NETWORK_TYPE = NetworkType.MIJIN_TEST; + + private LockFundsTransactionBuilder builder; + + @BeforeEach + void setUp() { + builder = new LockFundsTransactionBuilder(); + builder.networkType(NETWORK_TYPE); + builder.deadlineDuration(BigInteger.valueOf(60_000)); + builder.feeCalculationStrategy(FeeCalculationStrategy.MEDIUM); + } + @Test + void test() { + SignedTransaction signedTransaction = new SignedTransaction("payload", + "8498B38D89C1DC8A448EA5824938FF828926CD9F7747B1844B59B4B6807E878B", TransactionType.AGGREGATE_BONDED); + LockFundsTransaction trans = builder.aggregate(BigInteger.ONE).signedTransaction(signedTransaction).build(); + + assertEquals(BigInteger.ONE, trans.getDuration()); + assertEquals(NetworkCurrencyMosaic.TEN, trans.getMosaic()); + assertEquals(signedTransaction, trans.getSignedTransaction()); + } + +} diff --git a/src/test/java/io/proximax/sdk/model/transaction/builder/ModifyAccountPropertyAddressTransactionBuilderTest.java b/src/test/java/io/proximax/sdk/model/transaction/builder/ModifyAccountPropertyAddressTransactionBuilderTest.java new file mode 100644 index 00000000..57d34d95 --- /dev/null +++ b/src/test/java/io/proximax/sdk/model/transaction/builder/ModifyAccountPropertyAddressTransactionBuilderTest.java @@ -0,0 +1,53 @@ +/* + * Copyright 2019 ProximaX Limited. All rights reserved. + * Use of this source code is governed by the Apache 2.0 + * license that can be found in the LICENSE file. + */ +package io.proximax.sdk.model.transaction.builder; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.math.BigInteger; +import java.util.Arrays; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import io.proximax.core.crypto.KeyPair; +import io.proximax.sdk.FeeCalculationStrategy; +import io.proximax.sdk.model.account.Account; +import io.proximax.sdk.model.account.Address; +import io.proximax.sdk.model.account.props.AccountPropertyModification; +import io.proximax.sdk.model.account.props.AccountPropertyType; +import io.proximax.sdk.model.blockchain.NetworkType; +import io.proximax.sdk.model.transaction.ModifyAccountPropertyTransaction; + +/** + * {@link ModifyAccountPropertyAddressTransactionBuilder} tests + */ +class ModifyAccountPropertyAddressTransactionBuilderTest { + + private static final NetworkType NETWORK_TYPE = NetworkType.MIJIN_TEST; + + private ModifyAccountPropertyAddressTransactionBuilder builder; + + @BeforeEach + void setUp() { + builder = new ModifyAccountPropertyAddressTransactionBuilder(); + builder.networkType(NETWORK_TYPE); + builder.deadlineDuration(BigInteger.valueOf(60_000)); + builder.feeCalculationStrategy(FeeCalculationStrategy.MEDIUM); + } + + @Test + void test() { + Address addr = new Account(new KeyPair(), NETWORK_TYPE).getAddress(); + AccountPropertyModification
mod = AccountPropertyModification.add(addr); + ModifyAccountPropertyTransaction
trans = builder.propertyType(AccountPropertyType.ALLOW_ADDRESS).modifications(Arrays.asList(mod)).build(); + + assertEquals(AccountPropertyType.ALLOW_ADDRESS, trans.getPropertyType()); + assertEquals(1, trans.getPropertyModifications().size()); + assertEquals(mod, trans.getPropertyModifications().get(0)); + } + +} diff --git a/src/test/java/io/proximax/sdk/model/transaction/builder/ModifyAccountPropertyEntityTransactionBuilderTest.java b/src/test/java/io/proximax/sdk/model/transaction/builder/ModifyAccountPropertyEntityTransactionBuilderTest.java new file mode 100644 index 00000000..45c0ca18 --- /dev/null +++ b/src/test/java/io/proximax/sdk/model/transaction/builder/ModifyAccountPropertyEntityTransactionBuilderTest.java @@ -0,0 +1,50 @@ +/* + * Copyright 2019 ProximaX Limited. All rights reserved. + * Use of this source code is governed by the Apache 2.0 + * license that can be found in the LICENSE file. + */ +package io.proximax.sdk.model.transaction.builder; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.math.BigInteger; +import java.util.Arrays; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import io.proximax.sdk.FeeCalculationStrategy; +import io.proximax.sdk.model.account.props.AccountPropertyModification; +import io.proximax.sdk.model.account.props.AccountPropertyType; +import io.proximax.sdk.model.blockchain.NetworkType; +import io.proximax.sdk.model.transaction.ModifyAccountPropertyTransaction; +import io.proximax.sdk.model.transaction.TransactionType; + +/** + * {@link ModifyAccountPropertyEntityTransactionBuilder} tests + */ +class ModifyAccountPropertyEntityTransactionBuilderTest { + + private static final NetworkType NETWORK_TYPE = NetworkType.MIJIN_TEST; + + private ModifyAccountPropertyEntityTransactionBuilder builder; + + @BeforeEach + void setUp() { + builder = new ModifyAccountPropertyEntityTransactionBuilder(); + builder.networkType(NETWORK_TYPE); + builder.deadlineDuration(BigInteger.valueOf(60_000)); + builder.feeCalculationStrategy(FeeCalculationStrategy.MEDIUM); + } + + @Test + void test() { + AccountPropertyModification mod = AccountPropertyModification.add(TransactionType.MODIFY_CONTRACT); + ModifyAccountPropertyTransaction trans = builder.propertyType(AccountPropertyType.ALLOW_TRANSACTION).modifications(Arrays.asList(mod)).build(); + + assertEquals(AccountPropertyType.ALLOW_TRANSACTION, trans.getPropertyType()); + assertEquals(1, trans.getPropertyModifications().size()); + assertEquals(mod, trans.getPropertyModifications().get(0)); + } + +} diff --git a/src/test/java/io/proximax/sdk/model/transaction/builder/ModifyAccountPropertyMosaicTransactionBuilderTest.java b/src/test/java/io/proximax/sdk/model/transaction/builder/ModifyAccountPropertyMosaicTransactionBuilderTest.java new file mode 100644 index 00000000..6e950118 --- /dev/null +++ b/src/test/java/io/proximax/sdk/model/transaction/builder/ModifyAccountPropertyMosaicTransactionBuilderTest.java @@ -0,0 +1,52 @@ +/* + * Copyright 2019 ProximaX Limited. All rights reserved. + * Use of this source code is governed by the Apache 2.0 + * license that can be found in the LICENSE file. + */ +package io.proximax.sdk.model.transaction.builder; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.math.BigInteger; +import java.util.Arrays; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import io.proximax.sdk.FeeCalculationStrategy; +import io.proximax.sdk.model.account.props.AccountPropertyModification; +import io.proximax.sdk.model.account.props.AccountPropertyType; +import io.proximax.sdk.model.blockchain.NetworkType; +import io.proximax.sdk.model.mosaic.MosaicId; +import io.proximax.sdk.model.transaction.ModifyAccountPropertyTransaction; +import io.proximax.sdk.model.transaction.UInt64Id; + +/** + * {@link ModifyAccountPropertyMosaicTransactionBuilder} tests + */ +class ModifyAccountPropertyMosaicTransactionBuilderTest { + + private static final NetworkType NETWORK_TYPE = NetworkType.MIJIN_TEST; + + private ModifyAccountPropertyMosaicTransactionBuilder builder; + + @BeforeEach + void setUp() { + builder = new ModifyAccountPropertyMosaicTransactionBuilder(); + builder.networkType(NETWORK_TYPE); + builder.deadlineDuration(BigInteger.valueOf(60_000)); + builder.feeCalculationStrategy(FeeCalculationStrategy.MEDIUM); + } + + @Test + void test() { + MosaicId mosid = new MosaicId(BigInteger.ONE); + AccountPropertyModification mod = AccountPropertyModification.add(mosid); + ModifyAccountPropertyTransaction trans = builder.propertyType(AccountPropertyType.ALLOW_MOSAIC).modifications(Arrays.asList(mod)).build(); + + assertEquals(AccountPropertyType.ALLOW_MOSAIC, trans.getPropertyType()); + assertEquals(1, trans.getPropertyModifications().size()); + assertEquals(mod, trans.getPropertyModifications().get(0)); + } + +} diff --git a/src/test/java/io/proximax/sdk/model/transaction/builder/ModifyContractTransactionBuilderTest.java b/src/test/java/io/proximax/sdk/model/transaction/builder/ModifyContractTransactionBuilderTest.java new file mode 100644 index 00000000..64ea343e --- /dev/null +++ b/src/test/java/io/proximax/sdk/model/transaction/builder/ModifyContractTransactionBuilderTest.java @@ -0,0 +1,72 @@ +/* + * Copyright 2019 ProximaX Limited. All rights reserved. + * Use of this source code is governed by the Apache 2.0 + * license that can be found in the LICENSE file. + */ +package io.proximax.sdk.model.transaction.builder; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.math.BigInteger; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import io.proximax.core.crypto.KeyPair; +import io.proximax.sdk.FeeCalculationStrategy; +import io.proximax.sdk.model.account.Account; +import io.proximax.sdk.model.account.PublicAccount; +import io.proximax.sdk.model.blockchain.NetworkType; +import io.proximax.sdk.model.transaction.ModifyContractTransaction; +import io.proximax.sdk.model.transaction.MultisigCosignatoryModification; + +/** + * {@link ModifyContractTransactionBuilder} tests + */ +class ModifyContractTransactionBuilderTest { + + private static final NetworkType NETWORK_TYPE = NetworkType.MIJIN_TEST; + + private ModifyContractTransactionBuilder builder; + + @BeforeEach + void setUp() { + builder = new ModifyContractTransactionBuilder(); + builder.networkType(NETWORK_TYPE); + builder.deadlineDuration(BigInteger.valueOf(60_000)); + builder.feeCalculationStrategy(FeeCalculationStrategy.MEDIUM); + } + + @Test + void contractWithoutMods() { + ModifyContractTransaction trans = builder.durationDelta(BigInteger.TEN).contentHash("CAFE").build(); + + assertTrue(trans.getExecutorsModifications().isEmpty()); + assertTrue(trans.getCustomersModifications().isEmpty()); + assertTrue(trans.getVerifiersModifications().isEmpty()); + assertEquals("CAFE", trans.getContentHash()); + assertEquals(BigInteger.TEN, trans.getDurationDelta()); + } + + @Test + void contractWithMods() { + PublicAccount pa1 = new Account(new KeyPair(), NETWORK_TYPE).getPublicAccount(); + PublicAccount pa2 = new Account(new KeyPair(), NETWORK_TYPE).getPublicAccount(); + PublicAccount pa3 = new Account(new KeyPair(), NETWORK_TYPE).getPublicAccount(); + ModifyContractTransaction trans = builder.durationDelta(BigInteger.TEN).contentHash("CAFE") + .customersModifications(MultisigCosignatoryModification.add(pa1)) + .verifiersModifications(MultisigCosignatoryModification.add(pa2)) + .executorsModifications(MultisigCosignatoryModification.add(pa3)) + .build(); + + assertEquals(1, trans.getExecutorsModifications().size()); + assertEquals(pa3, trans.getExecutorsModifications().get(0).getCosignatoryPublicAccount()); + assertEquals(1, trans.getCustomersModifications().size()); + assertEquals(pa1, trans.getCustomersModifications().get(0).getCosignatoryPublicAccount()); + assertEquals(1, trans.getVerifiersModifications().size()); + assertEquals(pa2, trans.getVerifiersModifications().get(0).getCosignatoryPublicAccount()); + assertEquals("CAFE", trans.getContentHash()); + assertEquals(BigInteger.TEN, trans.getDurationDelta()); + } +} diff --git a/src/test/java/io/proximax/sdk/model/transaction/builder/ModifyMetadataTransactionBuilderTest.java b/src/test/java/io/proximax/sdk/model/transaction/builder/ModifyMetadataTransactionBuilderTest.java new file mode 100644 index 00000000..4e885be9 --- /dev/null +++ b/src/test/java/io/proximax/sdk/model/transaction/builder/ModifyMetadataTransactionBuilderTest.java @@ -0,0 +1,85 @@ +/* + * Copyright 2019 ProximaX Limited. All rights reserved. + * Use of this source code is governed by the Apache 2.0 + * license that can be found in the LICENSE file. + */ +package io.proximax.sdk.model.transaction.builder; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.math.BigInteger; +import java.util.Optional; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import io.proximax.sdk.FeeCalculationStrategy; +import io.proximax.sdk.model.account.Address; +import io.proximax.sdk.model.blockchain.NetworkType; +import io.proximax.sdk.model.metadata.MetadataModification; +import io.proximax.sdk.model.metadata.MetadataType; +import io.proximax.sdk.model.mosaic.MosaicId; +import io.proximax.sdk.model.namespace.NamespaceId; +import io.proximax.sdk.model.transaction.ModifyMetadataTransaction; +import io.proximax.sdk.model.transaction.TransactionType; + +/** + * {@link ModifyMetadataTransactionBuilder} tests + */ +class ModifyMetadataTransactionBuilderTest { + + private static final NetworkType NETWORK_TYPE = NetworkType.MIJIN_TEST; + + private ModifyMetadataTransactionBuilder builder; + + @BeforeEach + void setUp() { + builder = new ModifyMetadataTransactionBuilder(); + builder.networkType(NETWORK_TYPE); + builder.deadlineDuration(BigInteger.valueOf(60_000)); + builder.feeCalculationStrategy(FeeCalculationStrategy.MEDIUM); + } + + @Test + void testForAddress() { + Address addr = new Address("SADD", NETWORK_TYPE); + MetadataModification mod = MetadataModification.add("key", "value"); + + ModifyMetadataTransaction trans = builder.forAddress(addr).modifications(mod).build(); + + assertEquals(TransactionType.MODIFY_ADDRESS_METADATA, trans.getType()); + assertEquals(Optional.of(addr), trans.getAddress()); + assertEquals(1, trans.getModifications().size()); + assertEquals(mod, trans.getModifications().get(0)); + assertEquals(MetadataType.ADDRESS, trans.getMetadataType()); + } + + @Test + void testForMosaic() { + MosaicId mosid = new MosaicId(BigInteger.valueOf(123456789)); + NamespaceId nsid = new NamespaceId("test.namespace"); + MetadataModification mod = MetadataModification.add("key", "value"); + + ModifyMetadataTransaction trans = builder.forMosaic(mosid).modifications(mod).build(); + + assertEquals(TransactionType.MODIFY_MOSAIC_METADATA, trans.getType()); + assertEquals(Optional.of(mosid), trans.getMetadataId()); + assertEquals(1, trans.getModifications().size()); + assertEquals(mod, trans.getModifications().get(0)); + assertEquals(MetadataType.MOSAIC, trans.getMetadataType()); + } + + @Test + void testForNamespace() { + NamespaceId nsid = new NamespaceId("test.namespace"); + MetadataModification mod = MetadataModification.add("key", "value"); + + ModifyMetadataTransaction trans = builder.forNamespace(nsid).modifications(mod).build(); + + assertEquals(TransactionType.MODIFY_NAMESPACE_METADATA, trans.getType()); + assertEquals(Optional.of(nsid), trans.getMetadataId()); + assertEquals(1, trans.getModifications().size()); + assertEquals(mod, trans.getModifications().get(0)); + assertEquals(MetadataType.NAMESPACE, trans.getMetadataType()); + } +} diff --git a/src/test/java/io/proximax/sdk/model/transaction/builder/ModifyMultisigAccountTransactionBuilderTest.java b/src/test/java/io/proximax/sdk/model/transaction/builder/ModifyMultisigAccountTransactionBuilderTest.java new file mode 100644 index 00000000..408d0c68 --- /dev/null +++ b/src/test/java/io/proximax/sdk/model/transaction/builder/ModifyMultisigAccountTransactionBuilderTest.java @@ -0,0 +1,68 @@ +/* + * Copyright 2019 ProximaX Limited. All rights reserved. + * Use of this source code is governed by the Apache 2.0 + * license that can be found in the LICENSE file. + */ +package io.proximax.sdk.model.transaction.builder; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.math.BigInteger; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import io.proximax.core.crypto.KeyPair; +import io.proximax.sdk.FeeCalculationStrategy; +import io.proximax.sdk.model.account.Account; +import io.proximax.sdk.model.blockchain.NetworkType; +import io.proximax.sdk.model.transaction.ModifyMultisigAccountTransaction; +import io.proximax.sdk.model.transaction.MultisigCosignatoryModification; + +/** + * {@link ModifyMultisigAccountTransactionBuilder} tests + */ +class ModifyMultisigAccountTransactionBuilderTest { + + private static final NetworkType NETWORK_TYPE = NetworkType.MIJIN_TEST; + + private ModifyMultisigAccountTransactionBuilder builder; + + @BeforeEach + void setUp() { + builder = new ModifyMultisigAccountTransactionBuilder(); + builder.networkType(NETWORK_TYPE); + builder.deadlineDuration(BigInteger.valueOf(60_000)); + builder.feeCalculationStrategy(FeeCalculationStrategy.MEDIUM); + } + + @Test + void testEmpty() { + ModifyMultisigAccountTransaction trans = builder.build(); + + assertEquals(0, trans.getMinApprovalDelta()); + assertEquals(0, trans.getMinRemovalDelta()); + assertTrue(trans.getModifications().isEmpty()); + } + + @Test + void testMinAppRem() { + ModifyMultisigAccountTransaction trans = builder.minApprovalDelta(5).minRemovalDelta(8).build(); + + assertEquals(5, trans.getMinApprovalDelta()); + assertEquals(8, trans.getMinRemovalDelta()); + assertTrue(trans.getModifications().isEmpty()); + } + + @Test + void testMods() { + MultisigCosignatoryModification mod = MultisigCosignatoryModification.add(new Account(new KeyPair(), NETWORK_TYPE).getPublicAccount()); + ModifyMultisigAccountTransaction trans = builder.minApprovalDelta(5).minRemovalDelta(8).modifications(mod).build(); + + assertEquals(5, trans.getMinApprovalDelta()); + assertEquals(8, trans.getMinRemovalDelta()); + assertEquals(1, trans.getModifications().size()); + assertEquals(mod, trans.getModifications().get(0)); + } +} diff --git a/src/test/java/io/proximax/sdk/model/transaction/builder/MosaicDefinitionTransactionBuilderTest.java b/src/test/java/io/proximax/sdk/model/transaction/builder/MosaicDefinitionTransactionBuilderTest.java new file mode 100644 index 00000000..80c03efa --- /dev/null +++ b/src/test/java/io/proximax/sdk/model/transaction/builder/MosaicDefinitionTransactionBuilderTest.java @@ -0,0 +1,65 @@ +/* + * Copyright 2019 ProximaX Limited. All rights reserved. + * Use of this source code is governed by the Apache 2.0 + * license that can be found in the LICENSE file. + */ +package io.proximax.sdk.model.transaction.builder; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.math.BigInteger; +import java.util.Optional; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import io.proximax.sdk.FeeCalculationStrategy; +import io.proximax.sdk.model.blockchain.NetworkType; +import io.proximax.sdk.model.mosaic.MosaicId; +import io.proximax.sdk.model.mosaic.MosaicNonce; +import io.proximax.sdk.model.mosaic.MosaicProperties; +import io.proximax.sdk.model.transaction.MosaicDefinitionTransaction; + +/** + * {@link MosaicDefinitionTransactionBuilder} tests + */ +class MosaicDefinitionTransactionBuilderTest { + + private static final NetworkType NETWORK_TYPE = NetworkType.MIJIN_TEST; + + private MosaicDefinitionTransactionBuilder builder; + + @BeforeEach + void setUp() { + builder = new MosaicDefinitionTransactionBuilder(); + builder.networkType(NETWORK_TYPE); + builder.deadlineDuration(BigInteger.valueOf(60_000)); + builder.feeCalculationStrategy(FeeCalculationStrategy.MEDIUM); + } + + @Test + void testNoDuration() { + MosaicNonce nonce = MosaicNonce.createRandom(); + MosaicId mosid = new MosaicId("CAFECAFECAFECAFE"); + MosaicProperties props = new MosaicProperties(true, true, 5, Optional.empty()); + MosaicDefinitionTransaction trans = builder.nonce(nonce).mosaicId(mosid).mosaicProperties(props).build(); + + assertEquals(nonce, trans.getNonce()); + assertEquals(mosid, trans.getMosaicId()); + assertEquals(props, trans.getMosaicProperties()); + } + + @Test + void testDuration() { + MosaicNonce nonce = MosaicNonce.createRandom(); + MosaicId mosid = new MosaicId("CAFECAFECAFECAFE"); + MosaicProperties props = new MosaicProperties(true, true, 5, Optional.of(BigInteger.ONE)); + MosaicDefinitionTransaction trans = builder.nonce(nonce).mosaicId(mosid).mosaicProperties(props).build(); + + assertEquals(nonce, trans.getNonce()); + assertEquals(mosid, trans.getMosaicId()); + assertEquals(props, trans.getMosaicProperties()); + assertEquals(Optional.of(BigInteger.ONE), trans.getMosaicProperties().getDuration()); + } + +} diff --git a/src/test/java/io/proximax/sdk/model/transaction/builder/MosaicSupplyChangeTransactionBuilderTest.java b/src/test/java/io/proximax/sdk/model/transaction/builder/MosaicSupplyChangeTransactionBuilderTest.java new file mode 100644 index 00000000..c2404dfe --- /dev/null +++ b/src/test/java/io/proximax/sdk/model/transaction/builder/MosaicSupplyChangeTransactionBuilderTest.java @@ -0,0 +1,59 @@ +/* + * Copyright 2019 ProximaX Limited. All rights reserved. + * Use of this source code is governed by the Apache 2.0 + * license that can be found in the LICENSE file. + */ +package io.proximax.sdk.model.transaction.builder; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.math.BigInteger; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import io.proximax.sdk.FeeCalculationStrategy; +import io.proximax.sdk.model.blockchain.NetworkType; +import io.proximax.sdk.model.mosaic.MosaicId; +import io.proximax.sdk.model.mosaic.MosaicSupplyType; +import io.proximax.sdk.model.transaction.MosaicSupplyChangeTransaction; + +/** + * {@link MosaicSupplyChangeTransactionBuilder} tests + */ +class MosaicSupplyChangeTransactionBuilderTest { + + private static final NetworkType NETWORK_TYPE = NetworkType.MIJIN_TEST; + + private MosaicSupplyChangeTransactionBuilder builder; + + @BeforeEach + void setUp() { + builder = new MosaicSupplyChangeTransactionBuilder(); + builder.networkType(NETWORK_TYPE); + builder.deadlineDuration(BigInteger.valueOf(60_000)); + builder.feeCalculationStrategy(FeeCalculationStrategy.MEDIUM); + } + + @Test + void increase() { + MosaicId mosid = new MosaicId(BigInteger.valueOf(1234567890l)); + MosaicSupplyChangeTransaction trans = builder.increaseSupplyFor(mosid).delta(BigInteger.TEN).build(); + + assertEquals(mosid, trans.getMosaicId()); + assertEquals(MosaicSupplyType.INCREASE, trans.getMosaicSupplyType()); + assertEquals(BigInteger.TEN, trans.getDelta()); + } + + + @Test + void decrease() { + MosaicId mosid = new MosaicId(BigInteger.valueOf(1234567890l)); + MosaicSupplyChangeTransaction trans = builder.decreaseSupplyFor(mosid).delta(BigInteger.TEN).build(); + + assertEquals(mosid, trans.getMosaicId()); + assertEquals(MosaicSupplyType.DECREASE, trans.getMosaicSupplyType()); + assertEquals(BigInteger.TEN, trans.getDelta()); + } + +} diff --git a/src/test/java/io/proximax/sdk/model/transaction/builder/RegisterNamespaceTransactionBuilderTest.java b/src/test/java/io/proximax/sdk/model/transaction/builder/RegisterNamespaceTransactionBuilderTest.java new file mode 100644 index 00000000..8234ebc7 --- /dev/null +++ b/src/test/java/io/proximax/sdk/model/transaction/builder/RegisterNamespaceTransactionBuilderTest.java @@ -0,0 +1,62 @@ +/* + * Copyright 2019 ProximaX Limited. All rights reserved. + * Use of this source code is governed by the Apache 2.0 + * license that can be found in the LICENSE file. + */ +package io.proximax.sdk.model.transaction.builder; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.math.BigInteger; +import java.util.Optional; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import io.proximax.sdk.FeeCalculationStrategy; +import io.proximax.sdk.model.blockchain.NetworkType; +import io.proximax.sdk.model.namespace.NamespaceId; +import io.proximax.sdk.model.namespace.NamespaceType; +import io.proximax.sdk.model.transaction.RegisterNamespaceTransaction; + +/** + * {@link RegisterNamespaceTransactionBuilder} tests + */ +class RegisterNamespaceTransactionBuilderTest { + + private static final NetworkType NETWORK_TYPE = NetworkType.MIJIN_TEST; + + private RegisterNamespaceTransactionBuilder builder; + + @BeforeEach + void setUp() { + builder = new RegisterNamespaceTransactionBuilder(); + builder.networkType(NETWORK_TYPE); + builder.deadlineDuration(BigInteger.valueOf(60_000)); + builder.feeCalculationStrategy(FeeCalculationStrategy.MEDIUM); + } + + @Test + void rootNamespace() { + final String ID = "test.ns"; + RegisterNamespaceTransaction trans = builder.rootNamespace(ID).build(); + + assertEquals(NamespaceType.RootNamespace, trans.getNamespaceType()); + assertEquals(new NamespaceId(ID), trans.getNamespaceId()); + assertEquals(ID, trans.getNamespaceName()); + assertEquals(Optional.empty(), trans.getDuration()); + assertEquals(Optional.empty(), trans.getParentId()); + } + + @Test + void childNamespace() { + final String ID = "test.ns"; + RegisterNamespaceTransaction trans = builder.subNamespace(new NamespaceId(ID), "hello").duration(BigInteger.TEN).build(); + + assertEquals(NamespaceType.SubNamespace, trans.getNamespaceType()); + assertEquals(new NamespaceId(ID + ".hello"), trans.getNamespaceId()); + assertEquals("hello", trans.getNamespaceName()); + assertEquals(Optional.of(BigInteger.TEN), trans.getDuration()); + assertEquals(Optional.of(new NamespaceId(ID)), trans.getParentId()); + } +} diff --git a/src/test/java/io/proximax/sdk/model/transaction/builder/SecretLockTransactionBuilderTest.java b/src/test/java/io/proximax/sdk/model/transaction/builder/SecretLockTransactionBuilderTest.java new file mode 100644 index 00000000..e2db761b --- /dev/null +++ b/src/test/java/io/proximax/sdk/model/transaction/builder/SecretLockTransactionBuilderTest.java @@ -0,0 +1,68 @@ +/* + * Copyright 2019 ProximaX Limited. All rights reserved. + * Use of this source code is governed by the Apache 2.0 + * license that can be found in the LICENSE file. + */ +package io.proximax.sdk.model.transaction.builder; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.math.BigInteger; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import io.proximax.sdk.FeeCalculationStrategy; +import io.proximax.sdk.model.account.Address; +import io.proximax.sdk.model.blockchain.NetworkType; +import io.proximax.sdk.model.mosaic.NetworkCurrencyMosaic; +import io.proximax.sdk.model.transaction.HashType; +import io.proximax.sdk.model.transaction.SecretLockTransaction; + +/** + * {@link SecretLockTransactionBuilder} tests + */ +class SecretLockTransactionBuilderTest { + + private static final NetworkType NETWORK_TYPE = NetworkType.MIJIN_TEST; + + private SecretLockTransactionBuilder builder; + + @BeforeEach + void setUp() { + builder = new SecretLockTransactionBuilder(); + builder.networkType(NETWORK_TYPE); + builder.deadlineDuration(BigInteger.valueOf(60_000)); + builder.feeCalculationStrategy(FeeCalculationStrategy.MEDIUM); + } + + @Test + void test() { + Address recipient = new Address("SADD", NETWORK_TYPE); + String secret = "3fc8ba10229ab5778d05d9c4b7f56676a88bf9295c185acfc0f961db5408cafe"; + + SecretLockTransaction trans = builder.mosaic(NetworkCurrencyMosaic.TEN).recipient(recipient).duration(BigInteger.ONE).hashType(HashType.SHA3_256).secret(secret).build(); + + assertEquals(recipient, trans.getRecipient()); + assertEquals(secret, trans.getSecret()); + assertEquals(NetworkCurrencyMosaic.TEN, trans.getMosaic()); + assertEquals(BigInteger.ONE, trans.getDuration()); + assertEquals(HashType.SHA3_256, trans.getHashType()); + } + + + @Test + void testConvenienceSecret() { + Address recipient = new Address("SADD", NETWORK_TYPE); + String secret = "3fc8ba10229ab5778d05d9c4b7f56676a88bf9295c185acfc0f961db5408cafe"; + + SecretLockTransaction trans = builder.mosaic(NetworkCurrencyMosaic.TEN).recipient(recipient).duration(BigInteger.ONE).secret(HashType.SHA3_256, secret).build(); + + assertEquals(recipient, trans.getRecipient()); + assertEquals(secret, trans.getSecret()); + assertEquals(NetworkCurrencyMosaic.TEN, trans.getMosaic()); + assertEquals(BigInteger.ONE, trans.getDuration()); + assertEquals(HashType.SHA3_256, trans.getHashType()); + } + +} diff --git a/src/test/java/io/proximax/sdk/model/transaction/builder/SecretProofTransactionBuilderTest.java b/src/test/java/io/proximax/sdk/model/transaction/builder/SecretProofTransactionBuilderTest.java new file mode 100644 index 00000000..0d7c0cea --- /dev/null +++ b/src/test/java/io/proximax/sdk/model/transaction/builder/SecretProofTransactionBuilderTest.java @@ -0,0 +1,64 @@ +/* + * Copyright 2019 ProximaX Limited. All rights reserved. + * Use of this source code is governed by the Apache 2.0 + * license that can be found in the LICENSE file. + */ +package io.proximax.sdk.model.transaction.builder; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.math.BigInteger; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import io.proximax.sdk.FeeCalculationStrategy; +import io.proximax.sdk.model.account.Address; +import io.proximax.sdk.model.blockchain.NetworkType; +import io.proximax.sdk.model.transaction.HashType; +import io.proximax.sdk.model.transaction.Recipient; +import io.proximax.sdk.model.transaction.SecretProofTransaction; + +/** + * {@link SecretProofTransactionBuilder} tests + */ +class SecretProofTransactionBuilderTest { + + private static final NetworkType NETWORK_TYPE = NetworkType.MIJIN_TEST; + + private SecretProofTransactionBuilder builder; + + @BeforeEach + void setUp() { + builder = new SecretProofTransactionBuilder(); + builder.networkType(NETWORK_TYPE); + builder.deadlineDuration(BigInteger.valueOf(60_000)); + builder.feeCalculationStrategy(FeeCalculationStrategy.MEDIUM); + } + + @Test + void test() { + Recipient recipient = Recipient.from(new Address("SADD", NETWORK_TYPE)); + String secret = "3fc8ba10229ab5778d05d9c4b7f56676a88bf9295c185acfc0f961db5408cafe"; + + SecretProofTransaction trans = builder.recipient(recipient).proof("CAFE").hashType(HashType.SHA3_256).secret(secret).build(); + + assertEquals(recipient, trans.getRecipient()); + assertEquals(secret, trans.getSecret()); + assertEquals(HashType.SHA3_256, trans.getHashType()); + assertEquals("CAFE", trans.getProof()); + } + + @Test + void testConvenienceSecret() { + Recipient recipient = Recipient.from(new Address("SADD", NETWORK_TYPE)); + String secret = "3fc8ba10229ab5778d05d9c4b7f56676a88bf9295c185acfc0f961db5408cafe"; + + SecretProofTransaction trans = builder.recipient(recipient).proof("CAFE").secret(HashType.SHA3_256, secret).build(); + + assertEquals(recipient, trans.getRecipient()); + assertEquals(secret, trans.getSecret()); + assertEquals(HashType.SHA3_256, trans.getHashType()); + assertEquals("CAFE", trans.getProof()); + } +} diff --git a/src/test/java/io/proximax/sdk/model/transaction/builder/TransactionBuilderFactoryTest.java b/src/test/java/io/proximax/sdk/model/transaction/builder/TransactionBuilderFactoryTest.java new file mode 100644 index 00000000..ad23dd78 --- /dev/null +++ b/src/test/java/io/proximax/sdk/model/transaction/builder/TransactionBuilderFactoryTest.java @@ -0,0 +1,63 @@ +/* + * Copyright 2019 ProximaX Limited. All rights reserved. + * Use of this source code is governed by the Apache 2.0 + * license that can be found in the LICENSE file. + */ +package io.proximax.sdk.model.transaction.builder; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.math.BigInteger; +import java.util.Optional; + +import org.junit.jupiter.api.Test; + +import io.proximax.sdk.FeeCalculationStrategy; +import io.proximax.sdk.model.blockchain.NetworkType; +import io.proximax.sdk.model.transaction.DeadlineRaw; + +/** + * {@link TransactionBuilderFactory} tests + */ +class TransactionBuilderFactoryTest { + + private static final NetworkType NETWORK_TYPE = NetworkType.MIJIN_TEST; + private static final BigInteger DELAY = BigInteger.valueOf(60_000); + + @Test + void test() { + TransactionBuilderFactory fac = new TransactionBuilderFactory(); + fac.setNetworkType(NETWORK_TYPE); + fac.setDeadlineMillis(DELAY); + fac.setFeeCalculationStrategy(FeeCalculationStrategy.MEDIUM); + + testDefaults(fac.accountLink()); + testDefaults(fac.accountPropAddress()); + testDefaults(fac.accountPropEntityType()); + testDefaults(fac.accountPropMosaic()); + testDefaults(fac.aggregateBonded()); + testDefaults(fac.aggregateComplete()); + testDefaults(fac.aliasAddress()); + testDefaults(fac.aliasMosaic()); + testDefaults(fac.blockchainConfig()); + testDefaults(fac.blockchainUpgrade()); + testDefaults(fac.lockFunds()); + testDefaults(fac.modifyContract()); + testDefaults(fac.modifyMetadata()); + testDefaults(fac.mosaicDefinition()); + testDefaults(fac.mosaicSupplyChange()); + testDefaults(fac.multisigModification()); + testDefaults(fac.registerNamespace()); + testDefaults(fac.secretLock()); + testDefaults(fac.secretProof()); + testDefaults(fac.transfer()); + + } + + public void testDefaults(TransactionBuilder builder) { + assertEquals(NETWORK_TYPE, builder.getNetworkType()); + assertTrue(Math.abs(DeadlineRaw.startNow(DELAY).getInstant() - builder.getDeadline().getInstant()) < 500); + assertEquals(Optional.of(FeeCalculationStrategy.MEDIUM), builder.getFeeCalculationStrategy()); + } +} diff --git a/src/test/java/io/proximax/sdk/model/transaction/builder/TransactionBuilderTest.java b/src/test/java/io/proximax/sdk/model/transaction/builder/TransactionBuilderTest.java new file mode 100644 index 00000000..61fecaf7 --- /dev/null +++ b/src/test/java/io/proximax/sdk/model/transaction/builder/TransactionBuilderTest.java @@ -0,0 +1,80 @@ +/* + * Copyright 2019 ProximaX Limited. All rights reserved. + * Use of this source code is governed by the Apache 2.0 + * license that can be found in the LICENSE file. + */ +package io.proximax.sdk.model.transaction.builder; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.math.BigInteger; +import java.util.Optional; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import io.proximax.core.crypto.KeyPair; +import io.proximax.sdk.FeeCalculationStrategy; +import io.proximax.sdk.model.account.Account; +import io.proximax.sdk.model.blockchain.NetworkType; +import io.proximax.sdk.model.transaction.DeadlineRaw; +import io.proximax.sdk.model.transaction.Recipient; +import io.proximax.sdk.model.transaction.TransactionInfo; +import io.proximax.sdk.model.transaction.TransactionType; +import io.proximax.sdk.model.transaction.TransferTransaction; + +/** + * {@link TransactionBuilder} tests based on the {@link TransferTransactionBulder} + */ +class TransactionBuilderTest { + + private static final NetworkType NETWORK_TYPE = NetworkType.MIJIN_TEST; + + private TransferTransactionBuilder builder; + + @BeforeEach + void setUp() { + builder = new TransferTransactionBuilder(); + builder.networkType(NETWORK_TYPE); + builder.deadlineDuration(BigInteger.valueOf(60_000)); + builder.feeCalculationStrategy(FeeCalculationStrategy.MEDIUM); + } + @Test + void testEmptyTransferToRecipient() { + // prepare data + Account acc = new Account(new KeyPair(), NETWORK_TYPE); + TransactionInfo transInfo = TransactionInfo.create(BigInteger.ONE, 4, "hello", "CAFE", "CAFECAFE"); + Recipient recipient = Recipient.from(acc.getAddress()); + // create transaction + TransferTransaction trans = builder.to(recipient) + .version(7) + .type(TransactionType.ACCOUNT_LINK) + .maxFee(BigInteger.TEN) + .deadline(DeadlineRaw.startNow(BigInteger.valueOf(50000))) + .signature("CAFE") + .signer(acc.getPublicAccount()) + .transactionInfo(transInfo) + .build(); + // check transaction + assertEquals(NetworkType.MIJIN_TEST, trans.getNetworkType()); + // type of result will be different from the specified + assertEquals(TransactionType.TRANSFER, trans.getType()); + assertEquals(TransactionType.ACCOUNT_LINK, builder.getType()); + assertEquals(7, trans.getVersion()); + assertEquals(BigInteger.TEN, trans.getMaxFee()); + assertEquals(Optional.of(FeeCalculationStrategy.MEDIUM), builder.getFeeCalculationStrategy()); + assertTrue(Math.abs(DeadlineRaw.startNow(BigInteger.valueOf(50_000)).getInstant() - trans.getDeadline().getInstant())<500); + assertEquals(Optional.of("CAFE"), trans.getSignature()); + assertEquals(Optional.of(acc.getPublicAccount()), trans.getSigner()); + assertEquals(Optional.of(transInfo), trans.getTransactionInfo()); + } + + @Test + void testDeadline() { + TransactionBuilder bld = new TransferTransactionBuilder(); + + assertThrows(IllegalStateException.class, () -> bld.getDeadline()); + } +} diff --git a/src/test/java/io/proximax/sdk/model/transaction/builder/TransactionFactoryTest.java b/src/test/java/io/proximax/sdk/model/transaction/builder/TransactionFactoryTest.java new file mode 100644 index 00000000..b83140f4 --- /dev/null +++ b/src/test/java/io/proximax/sdk/model/transaction/builder/TransactionFactoryTest.java @@ -0,0 +1,35 @@ +/* + * Copyright 2019 ProximaX Limited. All rights reserved. + * Use of this source code is governed by the Apache 2.0 + * license that can be found in the LICENSE file. + */ +package io.proximax.sdk.model.transaction.builder; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.math.BigInteger; + +import org.junit.jupiter.api.Test; + +import io.proximax.sdk.FeeCalculationStrategy; +import io.proximax.sdk.model.blockchain.NetworkType; + +/** + * {@link TransactionBuilderFactory} tests + */ +class TransactionFactoryTest { + private static final NetworkType NETWORK_TYPE = NetworkType.MIJIN_TEST; + + @Test + void prepareFactory() { + TransactionBuilderFactory fac = new TransactionBuilderFactory(); + fac.setNetworkType(NETWORK_TYPE); + fac.setDeadlineMillis(BigInteger.valueOf(60_000)); + fac.setFeeCalculationStrategy(FeeCalculationStrategy.MEDIUM); + + assertEquals(NETWORK_TYPE, fac.getNetworkType()); + assertEquals(BigInteger.valueOf(60_000), fac.getDeadlineMillis()); + assertEquals(FeeCalculationStrategy.MEDIUM, fac.getFeeCalculationStrategy()); + } + +} diff --git a/src/test/java/io/proximax/sdk/model/transaction/builder/TransferTransactionBuilderTest.java b/src/test/java/io/proximax/sdk/model/transaction/builder/TransferTransactionBuilderTest.java new file mode 100644 index 00000000..515a0327 --- /dev/null +++ b/src/test/java/io/proximax/sdk/model/transaction/builder/TransferTransactionBuilderTest.java @@ -0,0 +1,95 @@ +/* + * Copyright 2019 ProximaX Limited. All rights reserved. + * Use of this source code is governed by the Apache 2.0 + * license that can be found in the LICENSE file. + */ +package io.proximax.sdk.model.transaction.builder; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.math.BigInteger; +import java.util.Arrays; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import io.proximax.core.crypto.KeyPair; +import io.proximax.sdk.FeeCalculationStrategy; +import io.proximax.sdk.model.account.Account; +import io.proximax.sdk.model.account.Address; +import io.proximax.sdk.model.blockchain.NetworkType; +import io.proximax.sdk.model.mosaic.NetworkCurrencyMosaic; +import io.proximax.sdk.model.namespace.NamespaceId; +import io.proximax.sdk.model.transaction.PlainMessage; +import io.proximax.sdk.model.transaction.Recipient; +import io.proximax.sdk.model.transaction.TransferTransaction; + +/** + * {@link TransferTransactionBuilder} tests + */ +class TransferTransactionBuilderTest { + + private static final NetworkType NETWORK_TYPE = NetworkType.MIJIN_TEST; + + private TransferTransactionBuilder builder; + + @BeforeEach + void setUp() { + builder = new TransferTransactionBuilder(); + builder.networkType(NETWORK_TYPE); + builder.deadlineDuration(BigInteger.valueOf(60_000)); + builder.feeCalculationStrategy(FeeCalculationStrategy.MEDIUM); + } + @Test + void testEmptyTransferToRecipient() { + // prepare data + Recipient recipient = Recipient.from(new Account(new KeyPair(), NETWORK_TYPE).getAddress()); + // create transaction + TransferTransaction trans = builder.to(recipient).build(); + // check transaction + assertEquals(NetworkType.MIJIN_TEST, trans.getNetworkType()); + assertTrue(trans.getMosaics().isEmpty()); + assertEquals(PlainMessage.Empty, trans.getMessage()); + assertEquals(recipient, trans.getRecipient()); + } + + @Test + void testEmptyTransferToAddress() { + // prepare data + Address recipient = new Account(new KeyPair(), NETWORK_TYPE).getAddress(); + // create transaction + TransferTransaction trans = builder.to(recipient).build(); + // check transaction + assertEquals(NetworkType.MIJIN_TEST, trans.getNetworkType()); + assertTrue(trans.getMosaics().isEmpty()); + assertEquals(PlainMessage.Empty, trans.getMessage()); + assertEquals(Recipient.from(recipient), trans.getRecipient()); + } + + @Test + void testEmptyTransferToNamespace() { + // prepare data + NamespaceId recipient = new NamespaceId("john.wick"); + // create transaction + TransferTransaction trans = builder.to(recipient).build(); + // check transaction + assertEquals(NetworkType.MIJIN_TEST, trans.getNetworkType()); + assertTrue(trans.getMosaics().isEmpty()); + assertEquals(PlainMessage.Empty, trans.getMessage()); + assertEquals(Recipient.from(recipient), trans.getRecipient()); + } + + @Test + void testMosaicTransferWithMessage() { + // prepare data + Recipient recipient = Recipient.from(new Account(new KeyPair(), NETWORK_TYPE).getAddress()); + // create transaction + TransferTransaction trans = builder.mosaics(NetworkCurrencyMosaic.TEN).to(recipient).message(PlainMessage.create("hello world")).build(); + // check transaction + assertEquals(NetworkType.MIJIN_TEST, trans.getNetworkType()); + assertEquals(Arrays.asList(NetworkCurrencyMosaic.TEN), trans.getMosaics()); + assertEquals("hello world", trans.getMessage().getPayload()); + assertEquals(recipient, trans.getRecipient()); + } +} diff --git a/src/test/resources/serialization/account_link.bytes b/src/test/resources/serialization/account_link.bytes index e57e408256c3a3d9ade380ce3149077ebe6a7d82..c9c35d5384e29fa4a5e869cf598b7667e85190b8 100644 GIT binary patch delta 11 ScmbQuIGb@o3M2c(R5Jh-RRduF delta 11 ScmbQuIGb@o3M13RR5Jh-K?7U> diff --git a/src/test/resources/serialization/link_address.bytes b/src/test/resources/serialization/link_address.bytes index 9d63aaa136e18f2f392777b4ed5babba51e5839a..3090a38c37139669188f0dbba4e0eb7732b125b9 100644 GIT binary patch delta 34 qcmZo;oWsaCXCh;>MA<5q2QyuM{hQhJh9hH2|B~i5N97K~p4|ZZCJ%D} delta 12 TcmbQk*v81%Hj%NJiOm8479Rrv diff --git a/src/test/resources/serialization/mosaic_definition.bytes b/src/test/resources/serialization/mosaic_definition.bytes index e3e31f81d613dee22710823430bbd43fba283839..987f4584d1250da9fbb6a9a19edd8c3bdc115249 100644 GIT binary patch delta 15 TcmbQlIEisW7sm@`1~32sBT@r2 delta 15 TcmbQlIEisW7l(j40~i1R9gYHk diff --git a/src/test/resources/serialization/secret_proof.bytes b/src/test/resources/serialization/secret_proof.bytes index a534a96833c1cd162821ebd9b639b0c4083c0ca0..1380748c0dbb1cc69cee58fbc96bb8b51e393161 100644 GIT binary patch delta 14 VcmZ3)xQKB=I?IkAC&r1{<^Ux71i}CS delta 14 VcmZ3)xQKB=I?IG0Cx(gH<^Ut#1epK;