├── .gitignore ├── .travis.yml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── build.gradle ├── ci-build.sh ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradlew ├── gradlew.bat ├── lombok.config ├── settings.gradle └── src ├── main ├── java │ └── io │ │ └── ezalabs │ │ └── multiversxspringbootstarterreactive │ │ ├── MxClientAutoConfiguration.java │ │ ├── MxInteractorAutoConfiguration.java │ │ ├── MxNetworkAutoConfiguration.java │ │ ├── api │ │ ├── ApiResourceURI.java │ │ ├── ApiResponse.java │ │ └── model │ │ │ ├── AccountBalance.java │ │ │ ├── AccountESDTRoles.java │ │ │ ├── AccountNonce.java │ │ │ ├── AccountOnNetwork.java │ │ │ ├── AccountStorageValue.java │ │ │ ├── ContractQueryResult.java │ │ │ ├── ContractQueryResultHex.java │ │ │ ├── ContractQueryResultInt.java │ │ │ ├── ContractQueryResultString.java │ │ │ ├── ESDTToken.java │ │ │ ├── Hyperblock.java │ │ │ ├── NFTData.java │ │ │ ├── NetworkConfig.java │ │ │ ├── NodeHeartbeatStatus.java │ │ │ ├── Receipt.java │ │ │ ├── ShardBlock.java │ │ │ ├── ShardFromHyperblock.java │ │ │ ├── ShardFromSimulatedTransaction.java │ │ │ ├── ShardStatus.java │ │ │ ├── SimulationResults.java │ │ │ ├── SmartContractResult.java │ │ │ ├── TokenList.java │ │ │ ├── TransactionCostEstimation.java │ │ │ ├── TransactionForAddress.java │ │ │ ├── TransactionHash.java │ │ │ ├── TransactionOnNetwork.java │ │ │ ├── TransactionStatus.java │ │ │ └── TransactionsSentResult.java │ │ ├── client │ │ ├── MxProxyClient.java │ │ └── MxProxyClientImpl.java │ │ ├── config │ │ ├── JsonMapper.java │ │ ├── MxClientConfig.java │ │ ├── MxNetworkConfigSupplier.java │ │ └── constants │ │ │ ├── AddressConstants.java │ │ │ ├── CurrencyConstants.java │ │ │ ├── ESDTConstants.java │ │ │ ├── TransactionConstants.java │ │ │ └── WalletConstants.java │ │ ├── domain │ │ ├── ApiModelToDomainConvertible.java │ │ ├── account │ │ │ ├── Account.java │ │ │ └── Address.java │ │ ├── common │ │ │ ├── Balance.java │ │ │ └── Nonce.java │ │ ├── esdt │ │ │ ├── ESDTGlobalOp.java │ │ │ ├── ESDTIssuance.java │ │ │ ├── ESDTLocalOp.java │ │ │ ├── ESDTNFTMultiTransfer.java │ │ │ ├── ESDTOwnershipTransfer.java │ │ │ ├── ESDTQueryType.java │ │ │ ├── ESDTRoleAssignment.java │ │ │ ├── ESDTTransaction.java │ │ │ ├── ESDTTransfer.java │ │ │ ├── ESDTUpgrade.java │ │ │ ├── NFTAddURI.java │ │ │ ├── NFTAttributesUpdate.java │ │ │ ├── NFTCreation.java │ │ │ ├── NFTCreationRoleTransfer.java │ │ │ ├── NFTSFTGlobalOp.java │ │ │ ├── NFTSFTLocalOp.java │ │ │ ├── NFTStopCreation.java │ │ │ └── common │ │ │ │ ├── ESDTSpecialRole.java │ │ │ │ ├── ESDTUri.java │ │ │ │ ├── TokenAttributes.java │ │ │ │ ├── TokenDecimals.java │ │ │ │ ├── TokenIdentifier.java │ │ │ │ ├── TokenInitialSupply.java │ │ │ │ ├── TokenName.java │ │ │ │ ├── TokenProperty.java │ │ │ │ ├── TokenPropertyName.java │ │ │ │ ├── TokenRoyalties.java │ │ │ │ ├── TokenTicker.java │ │ │ │ └── TransferToken.java │ │ ├── smartcontract │ │ │ ├── ContractFunction.java │ │ │ ├── ContractQuery.java │ │ │ ├── FunctionArg.java │ │ │ └── FunctionName.java │ │ ├── transaction │ │ │ ├── ChainID.java │ │ │ ├── GasLimit.java │ │ │ ├── GasPrice.java │ │ │ ├── Hash.java │ │ │ ├── PayloadData.java │ │ │ ├── Signable.java │ │ │ ├── Signature.java │ │ │ ├── Transaction.java │ │ │ ├── TransactionStatus.java │ │ │ └── TransactionVersion.java │ │ └── wallet │ │ │ └── Wallet.java │ │ ├── error │ │ ├── ErrorMessage.java │ │ └── exception │ │ │ ├── CannotConvertBitsException.java │ │ │ ├── CannotCreateAddressException.java │ │ │ ├── CannotCreateSignatureException.java │ │ │ ├── CannotDecodeBech32AddressException.java │ │ │ ├── CannotDeriveKeysException.java │ │ │ ├── CannotGenerateMnemonicException.java │ │ │ ├── CannotSignTransactionException.java │ │ │ ├── DeserializationException.java │ │ │ ├── EmptyPayloadException.java │ │ │ ├── GatewayException.java │ │ │ ├── InvalidBalanceException.java │ │ │ ├── InvalidChainIdException.java │ │ │ ├── InvalidHexValueException.java │ │ │ ├── InvalidNonceException.java │ │ │ ├── InvalidPemFileException.java │ │ │ ├── InvalidProxyUrlException.java │ │ │ ├── InvalidSentTransactionsException.java │ │ │ ├── InvalidTransactionStatusException.java │ │ │ ├── InvalidTransactionVersionException.java │ │ │ ├── MissingTransactionRequestException.java │ │ │ ├── NegativeGasException.java │ │ │ ├── PrivateKeyHexSizeException.java │ │ │ ├── ProxyRequestException.java │ │ │ ├── ResponseException.java │ │ │ ├── SignatureEmptyException.java │ │ │ └── WrongNetworkAddressException.java │ │ ├── interactor │ │ ├── WrappedResponses.java │ │ ├── account │ │ │ ├── MxAccountInteractor.java │ │ │ └── MxAccountInteractorImpl.java │ │ ├── block │ │ │ ├── MxBlockInteractor.java │ │ │ └── MxBlockInteractorImpl.java │ │ ├── esdt │ │ │ ├── MxESDTInteractor.java │ │ │ └── MxESDTInteractorImpl.java │ │ ├── network │ │ │ ├── MxNetworkInteractor.java │ │ │ └── MxNetworkInteractorImpl.java │ │ ├── smartcontract │ │ │ ├── MxSmartContractInteractor.java │ │ │ └── MxSmartContractInteractorImpl.java │ │ └── transaction │ │ │ ├── MxTransactionInteractor.java │ │ │ ├── MxTransactionInteractorImpl.java │ │ │ └── TransactionRequest.java │ │ ├── properties │ │ └── MxClientProperties.java │ │ └── util │ │ ├── BitsConverter.java │ │ ├── GasUtils.java │ │ ├── HexValidator.java │ │ ├── MnemonicsUtils.java │ │ └── PemUtils.java └── resources │ └── META-INF │ └── spring.factories └── test ├── java └── io │ └── ezalabs │ └── multiversxspringbootstarterreactive │ ├── api │ └── ApiResponseTest.java │ ├── client │ └── MxProxyClientTest.java │ ├── domain │ ├── account │ │ └── AddressTest.java │ ├── common │ │ ├── BalanceTest.java │ │ └── NonceTest.java │ ├── esdt │ │ ├── ESDTIssuanceTest.java │ │ ├── ESDTRoleAssignmentTest.java │ │ ├── ESDTSpecialRoleTest.java │ │ ├── ESDTUpgradeTest.java │ │ ├── NFTAddURITest.java │ │ ├── NFTAttributesUpdateTest.java │ │ ├── NFTStopCreationTest.java │ │ ├── TokenInitialSupplyTest.java │ │ ├── TokenNameTest.java │ │ ├── TokenPropertyNameTest.java │ │ ├── TokenTickerTest.java │ │ ├── issuance │ │ │ ├── ESDTUriTest.java │ │ │ ├── NFTCreationTest.java │ │ │ ├── TokenAttributesTest.java │ │ │ ├── TokenDecimalsTest.java │ │ │ ├── TokenIdentifierTest.java │ │ │ └── TokenRoyaltiesTest.java │ │ ├── operations │ │ │ ├── ESDTGlobalOpTest.java │ │ │ ├── NFTSFTGlobalOpTest.java │ │ │ └── NFTSFTLocalOpTest.java │ │ ├── role │ │ │ ├── ESDTOwnershipTransferTest.java │ │ │ └── NFTCreationRoleTransferTest.java │ │ └── transfer │ │ │ ├── ESDTLocalOpTest.java │ │ │ ├── ESDTNFTMultiTransferTest.java │ │ │ └── ESDTTransferTest.java │ ├── smartcontract │ │ ├── ContractFunctionTest.java │ │ ├── ContractQueryResultTest.java │ │ ├── FunctionArgTest.java │ │ └── FunctionNameTest.java │ ├── transaction │ │ ├── ChainIDTest.java │ │ ├── GasTest.java │ │ ├── HashTest.java │ │ ├── PayloadDataTest.java │ │ ├── SignatureTest.java │ │ ├── TransactionStatusTest.java │ │ ├── TransactionTest.java │ │ └── TransactionVersionTest.java │ └── wallet │ │ └── WalletTest.java │ ├── interactor │ ├── Helper.java │ ├── account │ │ └── MxAccountInteractorTest.java │ ├── block │ │ └── MxBlockInteractorTest.java │ ├── esdt │ │ └── MxESDTInteractorTest.java │ ├── network │ │ └── MxNetworkInteractorTest.java │ ├── smartcontract │ │ └── MxSmartContractInteractorTest.java │ └── transaction │ │ └── MxTransactionInteractorTest.java │ ├── properties │ └── MxClientPropertiesTest.java │ └── util │ ├── GasUtilsTest.java │ ├── HexValidatorTest.java │ └── PemUtilsTest.java └── resources ├── devnetAccount1.pem ├── invalid.pem └── validPemButNotValidPrivateKey.pem /.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | .gradle 3 | build/ 4 | !gradle/wrapper/gradle-wrapper.jar 5 | !**/src/main/**/build/ 6 | !**/src/test/**/build/ 7 | 8 | ### STS ### 9 | .apt_generated 10 | .classpath 11 | .factorypath 12 | .project 13 | .settings 14 | .springBeans 15 | .sts4-cache 16 | bin/ 17 | !**/src/main/**/bin/ 18 | !**/src/test/**/bin/ 19 | 20 | ### IntelliJ IDEA ### 21 | .idea 22 | *.iws 23 | *.iml 24 | *.ipr 25 | out/ 26 | !**/src/main/**/out/ 27 | !**/src/test/**/out/ 28 | 29 | ### NetBeans ### 30 | /nbproject/private/ 31 | /nbbuild/ 32 | /dist/ 33 | /nbdist/ 34 | /.nb-gradle/ 35 | 36 | ### VS Code ### 37 | .vscode/ 38 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | install: skip 3 | 4 | jdk: openjdk11 5 | 6 | branches: 7 | only: 8 | - main 9 | 10 | before_cache: 11 | - rm -f $HOME/.gradle/caches/modules-2/modules-2.lock 12 | - rm -fr $HOME/.gradle/caches/*/plugin-resolution/ 13 | 14 | cache: 15 | directories: 16 | - $HOME/.gradle/caches/ 17 | - $HOME/.gradle/wrapper/ 18 | 19 | script: 20 | - ./ci-build.sh -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | 3 | ## [1.0.0] - 04-Oct-2021 4 | 5 | First version, containing: 6 | 7 | - API request & response models 8 | - Reactive ErdProxyClient 9 | - Custom JSON Mapper for API responses 10 | - Configuration (static & dynamic) 11 | - Domain & value objects (account, wallet, transaction, signature etc) 12 | - Specific exceptions runtime exceptions 13 | - Utilities (gas, hex, mnemonics, pem) 14 | - Interactors (interfaces & implementations) for account, block, network, transaction 15 | - Javadoc 16 | - Lombok 17 | - unit tests with Jacoco code coverage 18 | - gradle build tool 19 | 20 | ## [1.0.1] - 11-Oct-2021 21 | 22 | Fixed spring.factories for ErdSimpleTransactionSender. 23 | 24 | ## [1.0.2] - 15-Nov-2021 25 | 26 | - Changed Sendable as part of Transaction class. 27 | - Refactoring in ErdSimpleTransactionSender. 28 | - Updated dependencies. 29 | - Small tweaks. 30 | 31 | ## [1.0.3] - 06-Jan-2022 32 | 33 | - Added the SmartContractInteractor interface & implementation 34 | - Added SC API & domain objects 35 | - Removed ErdSimpleTransactionSender and moved methods as overloaded to TransactionInteractor 36 | - Refactored gateway selection properties mechanism 37 | - Upgraded Log4J version to v2.17.1 to prevent vulnerability 38 | - Minor bug fixes 39 | 40 | ## [1.0.4] - 07-Jan-2022 41 | 42 | - Updated Spring Boot version 43 | 44 | ## [1.0.5] - 11-Jan-2022 45 | 46 | - Removed WalletCreator 47 | - Added creation from PEM & mnemonics to Wallet main class 48 | - Added support for PEM creation through reactive FilePart 49 | 50 | ## [1.0.6] - 25-Jan-2022 51 | 52 | - Fixed custom GasLimit set From ScFunction in the SmartContractInteractor 53 | 54 | ## [1.1.0] - 21-Feb-2022 55 | 56 | - Added the ESDTInteractor interface & implementation 57 | - Added ESDT API & domain objects 58 | - Some refactoring in the SmartContractInteractor 59 | - New method in HexValidator 60 | - Other improvements 61 | 62 | ## [1.1.1] - 24-Feb-2022 63 | 64 | - Refactor FunctionArgs 65 | - Added fromString and fromNumber for the function argument as the hex encoding output is different 66 | 67 | ## [1.1.2] - 04-Mar-2022 68 | 69 | - Fixed string value in FunctionArg to only trim the value, not eliminate all whitespaces 70 | 71 | ## [1.2.0] - 30-May-2023 72 | 73 | - upgraded to Java 17 and Spring Boot 3 74 | - refactored framework to match the rebranding into MultiversX 75 | - added option to use a custom proxy URL 76 | 77 | ## [1.2.1] - 04-Oct-2023 78 | 79 | - changed the project domain -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 ezalabs.io 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /ci-build.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ./gradlew build publishToSonatype -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ezalabs/multiversx-spring-boot-starter-reactive/9f78d8b0ac0a1faa8ad865857286e724e20442a5/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /lombok.config: -------------------------------------------------------------------------------- 1 | config.stopBubbling = true 2 | lombok.addLombokGeneratedAnnotation = true -------------------------------------------------------------------------------- /settings.gradle: -------------------------------------------------------------------------------- 1 | rootProject.name = 'multiversx-spring-boot-starter-reactive' 2 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/MxClientAutoConfiguration.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive; 2 | 3 | import io.ezalabs.multiversxspringbootstarterreactive.client.MxProxyClient; 4 | import io.ezalabs.multiversxspringbootstarterreactive.client.MxProxyClientImpl; 5 | import io.ezalabs.multiversxspringbootstarterreactive.config.MxClientConfig; 6 | import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; 7 | import org.springframework.boot.context.properties.EnableConfigurationProperties; 8 | import org.springframework.context.annotation.Bean; 9 | import org.springframework.context.annotation.Configuration; 10 | import io.ezalabs.multiversxspringbootstarterreactive.properties.MxClientProperties; 11 | 12 | @Configuration 13 | @EnableConfigurationProperties(MxClientProperties.class) 14 | public class MxClientAutoConfiguration { 15 | 16 | @Bean 17 | public MxClientConfig clientConfig(MxClientProperties props) { 18 | return new MxClientConfig(props); 19 | } 20 | 21 | @Bean 22 | @ConditionalOnBean(MxClientConfig.class) 23 | public MxProxyClient proxyClient(MxClientConfig config) { 24 | return new MxProxyClientImpl(config); 25 | } 26 | 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/MxNetworkAutoConfiguration.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive; 2 | 3 | import io.ezalabs.multiversxspringbootstarterreactive.config.MxNetworkConfigSupplier; 4 | import org.springframework.beans.factory.annotation.Autowired; 5 | import org.springframework.boot.autoconfigure.AutoConfigureAfter; 6 | import org.springframework.context.annotation.Bean; 7 | import org.springframework.context.annotation.Configuration; 8 | import io.ezalabs.multiversxspringbootstarterreactive.interactor.network.MxNetworkInteractor; 9 | 10 | @Configuration 11 | @AutoConfigureAfter(MxInteractorAutoConfiguration.class) 12 | public class MxNetworkAutoConfiguration { 13 | 14 | @Autowired 15 | private MxNetworkInteractor networkInteractor; 16 | 17 | @Bean 18 | public MxNetworkConfigSupplier proxyNetworkConfig() { 19 | return new MxNetworkConfigSupplier(networkInteractor); 20 | } 21 | 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/api/ApiResourceURI.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.api; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.Getter; 5 | 6 | /** 7 | * Enum containing URI for accessing resources on the network 8 | * 9 | * @author carlo_stanciu 10 | */ 11 | @AllArgsConstructor 12 | @Getter 13 | public enum ApiResourceURI { 14 | 15 | NETWORK_CONFIG("network/config"), 16 | SHARD_STATUS("network/status/%s"), 17 | ACCOUNT_ON_NETWORK("address/%s"), 18 | ACCOUNT_BALANCE("address/%s/balance"), 19 | ACCOUNT_NONCE("address/%s/nonce"), 20 | ACCOUNT_STORAGE_VALUE("address/%s/key/%s"), 21 | ACCOUNT_STORAGE("address/%s/keys"), 22 | ADDRESS_TRANSACTIONS("address/%s/transactions"), 23 | TRANSACTION_ON_NETWORK("transaction/%s?withResults=%s"), 24 | SEND_TRANSACTION("transaction/send"), 25 | SEND_MULTIPLE_TRANSACTIONS("transaction/send-multiple"), 26 | SIMULATE_TRANSACTION("transaction/simulate"), 27 | ESTIMATE_TRANSACTION_COST("transaction/cost"), 28 | TRANSACTION_STATUS("transaction/%s/status"), 29 | NODE_HEARTBEAT_STATUS("node/heartbeatstatus"), 30 | HYPERBLOCK_BY_NONCE("hyperblock/by-nonce/%s"), 31 | HYPERBLOCK_BY_HASH("hyperblock/by-hash/%s"), 32 | BLOCK_BY_NONCE_FROM_SHARD("block/%s/by-nonce/%s"), 33 | BLOCK_BY_HASH_FROM_SHARD("block/%s/by-hash/%s"), 34 | QUERY_SMART_CONTRACT("vm-values/query"), 35 | QUERY_SMART_CONTRACT_HEX("vm-values/hex"), 36 | QUERY_SMART_CONTRACT_STRING("vm-values/string"), 37 | QUERY_SMART_CONTRACT_INT("vm-values/int"), 38 | ESDT_TOKENS_FOR_ADDRESS("address/%s/esdt"), 39 | ESDT_BALANCE_FOR_ADDRESS("address/%s/esdt/%s"), 40 | ESDT_ROLES_FOR_ADDRESS("address/%s/esdts/roles"), 41 | ESDT_ALL_ISSUED_TOKENS("network/esdts"), 42 | ESDT_ALL_ISSUED_FUNGIBLE_TOKENS("network/esdt/fungible-tokens"), 43 | ESDT_ALL_ISSUED_SEMIFUNGIBLE_TOKENS("network/esdt/semi-fungible-tokens"), 44 | ESDT_ALL_ISSUED_NONFUNGIBLE_TOKENS("network/esdt/non-fungible-tokens"), 45 | NFT_DATA_FOR_ADDRESS("address/%s/nft/%s/nonce/%s"), 46 | NFT_SFT_REGISTERED_FOR_ADDRESS("address/%s/registered-nfts"), 47 | ESDT_TOKENS_WITH_ROLE("address/%s/esdts-with-role/%s"); 48 | 49 | private final String URI; 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/api/ApiResponse.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.api; 2 | 3 | import static io.netty.util.internal.StringUtil.isNullOrEmpty; 4 | 5 | import io.ezalabs.multiversxspringbootstarterreactive.error.exception.ResponseException; 6 | import lombok.Data; 7 | 8 | /** 9 | * Base API response received from the MultiversX proxy with generic based on response type 10 | * 11 | * @author carlo_stanciu 12 | */ 13 | @Data 14 | public class ApiResponse { 15 | 16 | private String error; 17 | private String code; 18 | private T data; 19 | 20 | /** 21 | * Method throws exception if the api response code is other than successful 22 | */ 23 | public void throwIfError() { 24 | if (!isNullOrEmpty(error)) { 25 | throw new ResponseException(error); 26 | } 27 | 28 | if (!code.equals("successful")) { 29 | throw new ResponseException(); 30 | } 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/api/model/AccountBalance.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.api.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import java.math.BigInteger; 6 | import lombok.Builder; 7 | import lombok.Value; 8 | import lombok.extern.jackson.Jacksonized; 9 | 10 | /** 11 | * API response when querying for address balance 12 | * 13 | * @author carlo_stanciu 14 | */ 15 | @Value 16 | @Jacksonized 17 | @Builder 18 | @JsonInclude(JsonInclude.Include.NON_EMPTY) 19 | public class AccountBalance { 20 | 21 | @JsonProperty("balance") 22 | BigInteger balance; 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/api/model/AccountESDTRoles.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.api.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import java.util.Map; 6 | import java.util.Set; 7 | import lombok.Builder; 8 | import lombok.Value; 9 | import lombok.extern.jackson.Jacksonized; 10 | 11 | /** 12 | * part of API response used in ESDT role queries 13 | * 14 | * @author carlo_stanciu 15 | */ 16 | @Value 17 | @Jacksonized 18 | @Builder 19 | @JsonInclude(JsonInclude.Include.NON_EMPTY) 20 | public class AccountESDTRoles { 21 | 22 | @JsonProperty("roles") 23 | Map> roles; 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/api/model/AccountNonce.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.api.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.Builder; 6 | import lombok.Value; 7 | import lombok.extern.jackson.Jacksonized; 8 | 9 | /** 10 | * API response when querying for address nonce 11 | * 12 | * @author carlo_stanciu 13 | */ 14 | @Value 15 | @Jacksonized 16 | @Builder 17 | @JsonInclude(JsonInclude.Include.NON_EMPTY) 18 | public class AccountNonce { 19 | 20 | @JsonProperty("nonce") 21 | Long nonce; 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/api/model/AccountOnNetwork.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.api.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import java.math.BigInteger; 6 | import lombok.Builder; 7 | import lombok.Value; 8 | import lombok.extern.jackson.Jacksonized; 9 | import io.ezalabs.multiversxspringbootstarterreactive.domain.ApiModelToDomainConvertible; 10 | import io.ezalabs.multiversxspringbootstarterreactive.domain.account.Account; 11 | import io.ezalabs.multiversxspringbootstarterreactive.domain.account.Address; 12 | import io.ezalabs.multiversxspringbootstarterreactive.domain.common.Balance; 13 | import io.ezalabs.multiversxspringbootstarterreactive.domain.common.Nonce; 14 | 15 | /** 16 | * API response when querying for account info 17 | * 18 | * @author carlo_stanciu 19 | */ 20 | @Value 21 | @Jacksonized 22 | @Builder 23 | @JsonInclude(JsonInclude.Include.NON_EMPTY) 24 | public class AccountOnNetwork implements ApiModelToDomainConvertible { 25 | 26 | @JsonProperty("address") 27 | String address; 28 | @JsonProperty("balance") 29 | BigInteger balance; 30 | @JsonProperty("developerReward") 31 | BigInteger developerReward; 32 | @JsonProperty("nonce") 33 | Long nonce; 34 | @JsonProperty("username") 35 | String username; 36 | @JsonProperty("code") 37 | String code; 38 | @JsonProperty("codeHash") 39 | String codeHash; 40 | @JsonProperty("codeMetadata") 41 | String codeMetadata; 42 | @JsonProperty("ownerAddress") 43 | String ownerAddress; 44 | @JsonProperty("rootHash") 45 | String rootHash; 46 | 47 | @Override 48 | public Account toDomainObject() { 49 | var account = new Account(); 50 | account.setAddress(Address.fromBech32(this.getAddress())); 51 | account.setNonce(Nonce.fromLong(this.getNonce())); 52 | account.setBalance(Balance.fromNumber(this.getBalance())); 53 | account.setCode(this.getCode()); 54 | account.setUsername(this.getUsername()); 55 | return account; 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/api/model/AccountStorageValue.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.api.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.Builder; 6 | import lombok.Value; 7 | import lombok.extern.jackson.Jacksonized; 8 | 9 | /** 10 | * API response when querying for address storage value 11 | * 12 | * @author carlo_stanciu 13 | */ 14 | @Value 15 | @Jacksonized 16 | @Builder 17 | @JsonInclude(JsonInclude.Include.NON_EMPTY) 18 | public class AccountStorageValue { 19 | 20 | @JsonProperty("value") 21 | String value; 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/api/model/ContractQueryResult.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.api.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import java.util.List; 6 | import lombok.Builder; 7 | import lombok.Value; 8 | import lombok.extern.jackson.Jacksonized; 9 | 10 | /** 11 | * part of API response used in smart contract query results 12 | * 13 | * @author carlo_stanciu 14 | */ 15 | @Value 16 | @Jacksonized 17 | @Builder 18 | @JsonInclude(JsonInclude.Include.NON_EMPTY) 19 | public class ContractQueryResult { 20 | 21 | @JsonProperty("returnData") 22 | List data; 23 | @JsonProperty("returnCode") 24 | String code; 25 | @JsonProperty("returnMessage") 26 | String message; 27 | 28 | } 29 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/api/model/ContractQueryResultHex.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.api.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.Builder; 6 | import lombok.Value; 7 | import lombok.extern.jackson.Jacksonized; 8 | 9 | /** 10 | * API response when querying smart contract for hex value 11 | * 12 | * @author carlo_stanciu 13 | */ 14 | @Value 15 | @Jacksonized 16 | @Builder 17 | @JsonInclude(JsonInclude.Include.NON_EMPTY) 18 | public class ContractQueryResultHex { 19 | 20 | @JsonProperty("data") 21 | String value; 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/api/model/ContractQueryResultInt.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.api.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import java.math.BigInteger; 6 | import lombok.Builder; 7 | import lombok.Value; 8 | import lombok.extern.jackson.Jacksonized; 9 | 10 | /** 11 | * API response when querying smart contract for integer value 12 | * 13 | * @author carlo_stanciu 14 | */ 15 | @Value 16 | @Jacksonized 17 | @Builder 18 | @JsonInclude(JsonInclude.Include.NON_EMPTY) 19 | public class ContractQueryResultInt { 20 | 21 | @JsonProperty("data") 22 | BigInteger value; 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/api/model/ContractQueryResultString.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.api.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.Builder; 6 | import lombok.Value; 7 | import lombok.extern.jackson.Jacksonized; 8 | 9 | /** 10 | * API response when querying smart contract for string value 11 | * 12 | * @author carlo_stanciu 13 | */ 14 | @Value 15 | @Jacksonized 16 | @Builder 17 | @JsonInclude(JsonInclude.Include.NON_EMPTY) 18 | public class ContractQueryResultString { 19 | 20 | @JsonProperty("data") 21 | String value; 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/api/model/ESDTToken.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.api.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.Builder; 6 | import lombok.Value; 7 | import lombok.extern.jackson.Jacksonized; 8 | 9 | /** 10 | * part of API response used in ESDT queries 11 | * 12 | * @author carlo_stanciu 13 | */ 14 | @Value 15 | @Jacksonized 16 | @Builder 17 | @JsonInclude(JsonInclude.Include.NON_EMPTY) 18 | public class ESDTToken { 19 | 20 | @JsonProperty("tokenIdentifier") 21 | String identifier; 22 | @JsonProperty("balance") 23 | String balance; 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/api/model/Hyperblock.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.api.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import java.math.BigInteger; 6 | import java.util.List; 7 | import lombok.Builder; 8 | import lombok.Value; 9 | import lombok.extern.jackson.Jacksonized; 10 | 11 | /** 12 | * API response when querying for hyperblock data 13 | * 14 | * @author carlo_stanciu 15 | */ 16 | @Value 17 | @Jacksonized 18 | @Builder 19 | @JsonInclude(JsonInclude.Include.NON_EMPTY) 20 | public class Hyperblock { 21 | 22 | @JsonProperty("nonce") 23 | Long nonce; 24 | @JsonProperty("round") 25 | Long round; 26 | @JsonProperty("hash") 27 | String hash; 28 | @JsonProperty("prevBlockHash") 29 | String previousBlockHash; 30 | @JsonProperty("epoch") 31 | Long epoch; 32 | @JsonProperty("shardBlocks") 33 | List shardBlocks; 34 | @JsonProperty("accumulatedFees") 35 | BigInteger accumulatedFees; 36 | @JsonProperty("developerFees") 37 | BigInteger developerFees; 38 | @JsonProperty("accumulatedFeesInEpoch") 39 | BigInteger accumulatedFeesInEpoch; 40 | @JsonProperty("developerFeesInEpoch") 41 | BigInteger developerFeesInEpoch; 42 | @JsonProperty("status") 43 | String status; 44 | 45 | } -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/api/model/NFTData.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.api.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import java.math.BigInteger; 6 | import java.util.List; 7 | import lombok.Builder; 8 | import lombok.Value; 9 | import lombok.extern.jackson.Jacksonized; 10 | 11 | /** 12 | * API response when querying for NFT data 13 | * 14 | * @author carlo_stanciu 15 | */ 16 | @Value 17 | @Jacksonized 18 | @Builder 19 | @JsonInclude(JsonInclude.Include.NON_EMPTY) 20 | public class NFTData { 21 | 22 | @JsonProperty("attributes") 23 | String attributes; 24 | @JsonProperty("balance") 25 | BigInteger balance; 26 | @JsonProperty("creator") 27 | String creatorAddress; 28 | @JsonProperty("hash") 29 | String hash; 30 | @JsonProperty("name") 31 | String name; 32 | @JsonProperty("nonce") 33 | Long nonce; 34 | @JsonProperty("properties") 35 | String properties; 36 | @JsonProperty("royalties") 37 | String royalties; 38 | @JsonProperty("tokenIdentifier") 39 | String tokenIdentifier; 40 | @JsonProperty("uris") 41 | List uris; 42 | 43 | } -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/api/model/NetworkConfig.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.api.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import java.math.BigInteger; 6 | import lombok.Builder; 7 | import lombok.Value; 8 | import lombok.extern.jackson.Jacksonized; 9 | 10 | /** 11 | * API response when querying for network configuration 12 | * 13 | * @author carlo_stanciu 14 | */ 15 | @Value 16 | @Jacksonized 17 | @Builder 18 | @JsonInclude(JsonInclude.Include.NON_EMPTY) 19 | public class NetworkConfig { 20 | 21 | @JsonProperty("erd_chain_id") 22 | String chainId; 23 | @JsonProperty("erd_denomination") 24 | Long denomination; 25 | @JsonProperty("erd_gas_per_data_byte") 26 | Long gasPerDataByte; 27 | @JsonProperty("erd_gas_price_modifier") 28 | Double gasPriceModifier; 29 | @JsonProperty("erd_latest_tag_software_version") 30 | String latestTagSoftwareVersion; 31 | @JsonProperty("erd_meta_consensus_group_size") 32 | Integer metaConsensusGroupSize; 33 | @JsonProperty("erd_min_gas_limit") 34 | BigInteger minGasLimit; 35 | @JsonProperty("erd_min_gas_price") 36 | BigInteger minGasPrice; 37 | @JsonProperty("erd_min_transaction_version") 38 | Integer minTransactionVersion; 39 | @JsonProperty("erd_num_metachain_nodes") 40 | Integer numMetachainNodes; 41 | @JsonProperty("erd_num_nodes_in_shard") 42 | Integer numNodesInShard; 43 | @JsonProperty("erd_num_shards_without_meta") 44 | Integer numShardsWithoutMeta; 45 | @JsonProperty("erd_rewards_top_up_gradient_poInteger") 46 | BigInteger rewardsTopUpGradientPoInteger; 47 | @JsonProperty("erd_round_duration") 48 | Long roundDuration; 49 | @JsonProperty("erd_rounds_per_epoch") 50 | Long roundPerEpoch; 51 | @JsonProperty("erd_shard_consensus_group_size") 52 | Integer shardConsensusGroupSize; 53 | @JsonProperty("erd_start_time") 54 | Long startTime; 55 | @JsonProperty("erd_top_up_factor") 56 | Double topUpFactor; 57 | 58 | } -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/api/model/NodeHeartbeatStatus.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.api.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import java.time.Instant; 6 | import lombok.Builder; 7 | import lombok.Value; 8 | import lombok.extern.jackson.Jacksonized; 9 | 10 | /** 11 | * API response when querying for node status 12 | * 13 | * @author carlo_stanciu 14 | */ 15 | @Value 16 | @Jacksonized 17 | @Builder 18 | @JsonInclude(JsonInclude.Include.NON_EMPTY) 19 | public class NodeHeartbeatStatus { 20 | 21 | @JsonProperty("timeStamp") 22 | Instant timestamp; 23 | @JsonProperty("publicKey") 24 | String publicKey; 25 | @JsonProperty("versionNumber") 26 | String versionNumber; 27 | @JsonProperty("nodeDisplayName") 28 | String nodeDisplayName; 29 | @JsonProperty("identity") 30 | String identity; 31 | @JsonProperty("totalUpTimeSec") 32 | Long totalUpTimeSeconds; 33 | @JsonProperty("totalDownTimeSec") 34 | Long totalDownTimeSeconds; 35 | @JsonProperty("maxInactiveTime") 36 | String maxInactiveTime; 37 | @JsonProperty("receivedShardID") 38 | Long receivedShardId; 39 | @JsonProperty("computedShardID") 40 | Long computedShardId; 41 | @JsonProperty("peerType") 42 | String peerType; 43 | @JsonProperty("isActive") 44 | Boolean isActive; 45 | @JsonProperty("nonce") 46 | Long nonce; 47 | @JsonProperty("numInstances") 48 | Long numOfInstances; 49 | 50 | } -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/api/model/Receipt.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.api.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import java.math.BigInteger; 6 | import lombok.Builder; 7 | import lombok.Value; 8 | import lombok.extern.jackson.Jacksonized; 9 | 10 | /** 11 | * part of API response used in transactions and simulation results 12 | * 13 | * @author carlo_stanciu 14 | */ 15 | @Value 16 | @Jacksonized 17 | @Builder 18 | @JsonInclude(JsonInclude.Include.NON_EMPTY) 19 | public class Receipt { 20 | 21 | @JsonProperty("hash") 22 | String hash; 23 | @JsonProperty("nonce") 24 | Long nonce; 25 | @JsonProperty("value") 26 | BigInteger value; 27 | @JsonProperty("receiver") 28 | String receiver; 29 | @JsonProperty("sender") 30 | String sender; 31 | 32 | } -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/api/model/ShardBlock.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.api.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import java.math.BigInteger; 6 | import lombok.Builder; 7 | import lombok.Value; 8 | import lombok.extern.jackson.Jacksonized; 9 | 10 | /** 11 | * API response when querying for block shard data 12 | * 13 | * @author carlo_stanciu 14 | */ 15 | @Value 16 | @Jacksonized 17 | @Builder 18 | @JsonInclude(JsonInclude.Include.NON_EMPTY) 19 | public class ShardBlock { 20 | 21 | @JsonProperty("nonce") 22 | Long nonce; 23 | @JsonProperty("round") 24 | Long round; 25 | @JsonProperty("hash") 26 | String hash; 27 | @JsonProperty("prevBlockHash") 28 | String previousBlockHash; 29 | @JsonProperty("epoch") 30 | Long epoch; 31 | @JsonProperty("shard") 32 | Integer shard; 33 | @JsonProperty("accumulatedFees") 34 | BigInteger accumulatedFees; 35 | @JsonProperty("developerFees") 36 | BigInteger developerFees; 37 | @JsonProperty("status") 38 | String status; 39 | 40 | } -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/api/model/ShardFromHyperblock.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.api.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.Builder; 6 | import lombok.Value; 7 | import lombok.extern.jackson.Jacksonized; 8 | 9 | /** 10 | * API response when querying for hyperblock shard data 11 | * 12 | * @author carlo_stanciu 13 | */ 14 | @Value 15 | @Jacksonized 16 | @Builder 17 | @JsonInclude(JsonInclude.Include.NON_EMPTY) 18 | public class ShardFromHyperblock { 19 | 20 | @JsonProperty("hash") 21 | String hash; 22 | @JsonProperty("nonce") 23 | Long nonce; 24 | @JsonProperty("round") 25 | Long round; 26 | @JsonProperty("shard") 27 | Integer shard; 28 | 29 | } -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/api/model/ShardFromSimulatedTransaction.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.api.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.Builder; 6 | import lombok.Value; 7 | import lombok.extern.jackson.Jacksonized; 8 | 9 | /** 10 | * part of API response when simulating transaction execution 11 | * 12 | * @author carlo_stanciu 13 | */ 14 | @Value 15 | @Jacksonized 16 | @Builder 17 | @JsonInclude(JsonInclude.Include.NON_EMPTY) 18 | public class ShardFromSimulatedTransaction { 19 | 20 | @JsonProperty("status") 21 | String status; 22 | @JsonProperty("failReason") 23 | String failReason; 24 | @JsonProperty("hash") 25 | String hash; 26 | 27 | } -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/api/model/ShardStatus.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.api.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.Builder; 6 | import lombok.Value; 7 | import lombok.extern.jackson.Jacksonized; 8 | 9 | /** 10 | * API response when querying for shard status 11 | * 12 | * @author carlo_stanciu 13 | */ 14 | @Value 15 | @Jacksonized 16 | @Builder 17 | @JsonInclude(JsonInclude.Include.NON_EMPTY) 18 | public class ShardStatus { 19 | 20 | @JsonProperty("erd_current_round") 21 | long currentRound; 22 | @JsonProperty("erd_epoch_number") 23 | long epochNumber; 24 | @JsonProperty("erd_highest_final_nonce") 25 | long highestFinalNonce; 26 | @JsonProperty("erd_nonce") 27 | long nonce; 28 | @JsonProperty("erd_nonce_at_epoch_start") 29 | long nonceAtEpochStart; 30 | @JsonProperty("erd_nonces_passed_in_current_epoch") 31 | long noncesPassedInCurrentEpoch; 32 | @JsonProperty("erd_round_at_epoch_start") 33 | long roundAtEpochStart; 34 | @JsonProperty("erd_rounds_passed_in_current_epoch") 35 | long roundsPassedInCurrentEpoch; 36 | @JsonProperty("erd_rounds_per_epoch") 37 | long roundsPerEpoch; 38 | 39 | } -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/api/model/SimulationResults.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.api.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import java.util.List; 6 | import lombok.Builder; 7 | import lombok.Value; 8 | import lombok.extern.jackson.Jacksonized; 9 | 10 | /** 11 | * API response when simulating transaction execution 12 | * 13 | * @author carlo_stanciu 14 | */ 15 | @Value 16 | @Jacksonized 17 | @Builder 18 | @JsonInclude(JsonInclude.Include.NON_EMPTY) 19 | public class SimulationResults { 20 | 21 | @JsonProperty("receiverShard") 22 | ShardFromSimulatedTransaction receiverShard; 23 | @JsonProperty("senderShard") 24 | ShardFromSimulatedTransaction senderShard; 25 | @JsonProperty("scResults") 26 | List smartContractResults; 27 | @JsonProperty("receipts") 28 | List receipts; 29 | 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/api/model/SmartContractResult.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.api.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import java.math.BigInteger; 6 | import lombok.Builder; 7 | import lombok.Value; 8 | import lombok.extern.jackson.Jacksonized; 9 | 10 | /** 11 | * part of API response when querying for transaction status 12 | * 13 | * @author carlo_stanciu 14 | */ 15 | @Value 16 | @Jacksonized 17 | @Builder 18 | @JsonInclude(JsonInclude.Include.NON_EMPTY) 19 | public class SmartContractResult { 20 | 21 | @JsonProperty("hash") 22 | String hash; 23 | @JsonProperty("nonce") 24 | Long nonce; 25 | @JsonProperty("value") 26 | BigInteger value; 27 | @JsonProperty("receiver") 28 | String receiver; 29 | @JsonProperty("sender") 30 | String sender; 31 | @JsonProperty("data") 32 | String data; 33 | @JsonProperty("prevTxHash") 34 | String previousTransactionHash; 35 | @JsonProperty("originalTxHash") 36 | String originalTransactionHash; 37 | @JsonProperty("gasLimit") 38 | BigInteger gasLimit; 39 | @JsonProperty("gasPrice") 40 | BigInteger gasPrice; 41 | @JsonProperty("callType") 42 | Integer callType; 43 | 44 | } -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/api/model/TokenList.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.api.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import java.util.Set; 6 | import lombok.Builder; 7 | import lombok.Value; 8 | import lombok.extern.jackson.Jacksonized; 9 | 10 | /** 11 | * part of API response used in ESDT queries 12 | * 13 | * @author carlo_stanciu 14 | */ 15 | @Value 16 | @Jacksonized 17 | @Builder 18 | @JsonInclude(JsonInclude.Include.NON_EMPTY) 19 | public class TokenList { 20 | 21 | @JsonProperty("tokens") 22 | Set tokens; 23 | 24 | } 25 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/api/model/TransactionCostEstimation.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.api.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.Builder; 6 | import lombok.Value; 7 | import lombok.extern.jackson.Jacksonized; 8 | 9 | /** 10 | * API response when estimating transaction execution 11 | * 12 | * @author carlo_stanciu 13 | */ 14 | @Value 15 | @Jacksonized 16 | @Builder 17 | @JsonInclude(JsonInclude.Include.NON_EMPTY) 18 | public class TransactionCostEstimation { 19 | 20 | @JsonProperty("txGasUnits") 21 | String transactionGasUnits; 22 | 23 | @JsonProperty("returnMessage") 24 | String returnMessage; 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/api/model/TransactionHash.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.api.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.Builder; 6 | import lombok.Value; 7 | import lombok.extern.jackson.Jacksonized; 8 | 9 | /** 10 | * API response when sending a transaction for execution 11 | * 12 | * @author carlo_stanciu 13 | */ 14 | @Value 15 | @Jacksonized 16 | @Builder 17 | @JsonInclude(JsonInclude.Include.NON_EMPTY) 18 | public class TransactionHash { 19 | 20 | @JsonProperty("txHash") 21 | String hash; 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/api/model/TransactionStatus.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.api.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import lombok.Builder; 6 | import lombok.Value; 7 | import lombok.extern.jackson.Jacksonized; 8 | 9 | /** 10 | * API response when querying for transactions status 11 | * 12 | * @author carlo_stanciu 13 | */ 14 | @Value 15 | @Jacksonized 16 | @Builder 17 | @JsonInclude(JsonInclude.Include.NON_EMPTY) 18 | public class TransactionStatus { 19 | 20 | @JsonProperty("status") 21 | String status; 22 | 23 | } 24 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/api/model/TransactionsSentResult.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.api.model; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import com.fasterxml.jackson.annotation.JsonProperty; 5 | import java.util.Map; 6 | import lombok.Builder; 7 | import lombok.Value; 8 | import lombok.extern.jackson.Jacksonized; 9 | 10 | /** 11 | * API response sending multiple transactions for execution 12 | * 13 | * @author carlo_stanciu 14 | */ 15 | @Value 16 | @Jacksonized 17 | @Builder 18 | @JsonInclude(JsonInclude.Include.NON_EMPTY) 19 | public class TransactionsSentResult { 20 | 21 | @JsonProperty("numOfSentTxs") 22 | Integer numberOfSentTransactions; 23 | @JsonProperty("txsHashes") 24 | Map transactionsHashes; 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/client/MxProxyClient.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.client; 2 | 3 | import reactor.core.publisher.Mono; 4 | 5 | /** 6 | * Proxy client used for interaction with MultiversX Gateway 7 | * 8 | * @author carlo_stanciu 9 | */ 10 | public interface MxProxyClient { 11 | 12 | /** 13 | * Used for GET HTTP method 14 | * 15 | * @param uri - resource URI 16 | * @param responseType - response class type object type for deserialization 17 | * @param - response object 18 | * @return - instance of response object T 19 | */ 20 | Mono get(String uri, Class responseType); 21 | 22 | /** 23 | * Used for POST HTTP method 24 | * 25 | * @param uri - resource URI 26 | * @param payload - request body 27 | * @param responseType - response class type object type for deserialization 28 | * @param - response object 29 | * @param

- payload object 30 | * @return - instance of response object T 31 | */ 32 | Mono post(String uri, P payload, Class responseType); 33 | 34 | } 35 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/client/MxProxyClientImpl.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.client; 2 | 3 | import static java.util.Objects.nonNull; 4 | 5 | import io.ezalabs.multiversxspringbootstarterreactive.config.JsonMapper; 6 | import io.ezalabs.multiversxspringbootstarterreactive.config.MxClientConfig; 7 | import lombok.extern.slf4j.Slf4j; 8 | import org.springframework.http.HttpMethod; 9 | import org.springframework.http.MediaType; 10 | import org.springframework.web.reactive.function.client.WebClient; 11 | import reactor.core.publisher.Mono; 12 | import io.ezalabs.multiversxspringbootstarterreactive.api.ApiResponse; 13 | import io.ezalabs.multiversxspringbootstarterreactive.error.exception.EmptyPayloadException; 14 | import io.ezalabs.multiversxspringbootstarterreactive.error.exception.ProxyRequestException; 15 | 16 | @Slf4j 17 | public class MxProxyClientImpl implements MxProxyClient { 18 | 19 | private final WebClient mxClient; 20 | 21 | public MxProxyClientImpl(MxClientConfig config) { 22 | this.mxClient = config.getMxClientBuilder().build(); 23 | } 24 | 25 | public Mono get(String uri, Class responseType) { 26 | log.debug("[ProxyClient] executing GET {}", uri); 27 | return processRequest(uri, null, responseType, HttpMethod.GET); 28 | } 29 | 30 | public Mono post(String uri, P payload, Class responseType) { 31 | log.debug("[ProxyClient] executing POST {}", uri); 32 | return processRequest(uri, payload, responseType, HttpMethod.POST); 33 | } 34 | 35 | private Mono processRequest(String uri, P payload, Class responseType, HttpMethod method) { 36 | var requestBuilder = mxClient 37 | .method(method) 38 | .uri(uri); 39 | 40 | if (method == HttpMethod.POST) { 41 | if (nonNull(payload)) { 42 | requestBuilder 43 | .contentType(MediaType.APPLICATION_JSON) 44 | .bodyValue(payload); 45 | } else { 46 | throw new EmptyPayloadException(); 47 | } 48 | } 49 | 50 | return requestBuilder.exchangeToMono(r -> r.bodyToMono(String.class)) 51 | .map(r -> JsonMapper.deserializeApiResponse(r, responseType)) 52 | .doOnSuccess(this::onSuccess) 53 | .doOnError(this::onError) 54 | .map(ApiResponse::getData); 55 | } 56 | 57 | private void onSuccess(ApiResponse response) { 58 | response.throwIfError(); 59 | } 60 | 61 | private void onError(Throwable t) { 62 | var errorMessage = t.getMessage(); 63 | throw new ProxyRequestException(errorMessage); 64 | } 65 | 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/config/JsonMapper.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.config; 2 | 3 | import com.fasterxml.jackson.annotation.JsonInclude; 4 | import com.fasterxml.jackson.core.JsonProcessingException; 5 | import com.fasterxml.jackson.databind.ObjectMapper; 6 | import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; 7 | import io.ezalabs.multiversxspringbootstarterreactive.api.ApiResponse; 8 | import io.ezalabs.multiversxspringbootstarterreactive.error.exception.DeserializationException; 9 | 10 | /** 11 | * Component used to serialisation / deserialization based on JacksonMapper 12 | * 13 | * @author carlo_stanciu 14 | */ 15 | public class JsonMapper { 16 | 17 | private static final ObjectMapper mapper; 18 | 19 | private JsonMapper() { 20 | } 21 | 22 | static { 23 | mapper = new Jackson2ObjectMapperBuilder() 24 | .build() 25 | .setDefaultPropertyInclusion(JsonInclude.Include.NON_EMPTY); 26 | } 27 | 28 | /** 29 | * Deserializes responses received from the gateway 30 | * 31 | * @param response - JSON response as String 32 | * @param responseType - response class type object type for deserialization 33 | * @param - response object 34 | * @return - ApiResponse containing the parametrized data value 35 | */ 36 | public static ApiResponse deserializeApiResponse(String response, Class responseType) { 37 | try { 38 | var type = mapper.getTypeFactory().constructParametricType(ApiResponse.class, responseType); 39 | return mapper.readValue(response, type); 40 | } catch (JsonProcessingException e) { 41 | throw new DeserializationException(e.getMessage()); 42 | } 43 | } 44 | 45 | /** 46 | * Serializes an Object the buffer of its JSON String 47 | * 48 | * @param object - target object 49 | * @return - buffer of the JSON String 50 | * @throws - JsonProcessingException 51 | */ 52 | public static byte[] serializeToJsonBuffer(Object object) throws JsonProcessingException { 53 | return mapper.writeValueAsString(object).getBytes(); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/config/MxClientConfig.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.config; 2 | 3 | import io.netty.handler.timeout.ReadTimeoutHandler; 4 | import io.netty.handler.timeout.WriteTimeoutHandler; 5 | import java.net.MalformedURLException; 6 | import java.net.URL; 7 | import java.util.concurrent.TimeUnit; 8 | import lombok.Getter; 9 | import lombok.extern.slf4j.Slf4j; 10 | import org.springframework.http.client.reactive.ReactorClientHttpConnector; 11 | import org.springframework.web.reactive.function.client.WebClient; 12 | import reactor.netty.http.client.HttpClient; 13 | import io.ezalabs.multiversxspringbootstarterreactive.error.exception.InvalidProxyUrlException; 14 | import io.ezalabs.multiversxspringbootstarterreactive.properties.MxClientProperties; 15 | 16 | /** 17 | * Class used for the configuration of MxClient 18 | * 19 | * @author carlo_stanciu 20 | */ 21 | @Slf4j 22 | @Getter 23 | public class MxClientConfig { 24 | 25 | private final String proxyUrl; 26 | private final WebClient.Builder mxClientBuilder; 27 | 28 | /** 29 | * Constructor for creating an MxClientConfig instance using properties 30 | * 31 | * @param clientProperties - injected properties required for webclient configuration 32 | */ 33 | public MxClientConfig(MxClientProperties clientProperties) { 34 | this.proxyUrl = clientProperties.getProxyUrl(); 35 | var httpClient = HttpClient.create() 36 | .doOnConnected(conn -> conn 37 | .addHandlerFirst(new ReadTimeoutHandler(clientProperties.getReadTimeoutMillis(), TimeUnit.MILLISECONDS)) 38 | .addHandlerFirst(new WriteTimeoutHandler(clientProperties.getWriteTimeoutMillis(), TimeUnit.MILLISECONDS))); 39 | 40 | validateUrl(proxyUrl); 41 | 42 | log.info("Configuring client with proxy URl %s.".formatted(proxyUrl)); 43 | this.mxClientBuilder = WebClient 44 | .builder() 45 | .baseUrl(proxyUrl) 46 | .clientConnector(new ReactorClientHttpConnector(httpClient)); 47 | } 48 | 49 | private void validateUrl(String url) { 50 | try { 51 | new URL(url); 52 | } catch (MalformedURLException e) { 53 | throw new InvalidProxyUrlException(url); 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/config/MxNetworkConfigSupplier.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.config; 2 | 3 | import jakarta.annotation.PostConstruct; 4 | import java.math.BigInteger; 5 | import lombok.extern.slf4j.Slf4j; 6 | import io.ezalabs.multiversxspringbootstarterreactive.api.model.NetworkConfig; 7 | import io.ezalabs.multiversxspringbootstarterreactive.interactor.network.MxNetworkInteractor; 8 | 9 | /** 10 | * Network configuration provider class which synchronises at startup with the MultiversX Gateway 11 | *

12 | * Source for network configuration values Uses default static values from D chain in case synchronising doesn't succeed 13 | * 14 | * @author carlo_stanciu 15 | */ 16 | @Slf4j 17 | public class MxNetworkConfigSupplier { 18 | 19 | private final MxNetworkInteractor networkInteractor; 20 | public static NetworkConfig config; 21 | 22 | public static final Integer DEFAULT_VERSION = 1; 23 | 24 | /** 25 | * Main constructor used for dependency injection 26 | * 27 | * @param networkInteractor - component used to extract configuration from the network 28 | */ 29 | public MxNetworkConfigSupplier(MxNetworkInteractor networkInteractor) { 30 | this.networkInteractor = networkInteractor; 31 | } 32 | 33 | static { 34 | config = NetworkConfig 35 | .builder() 36 | .chainId("D") 37 | .gasPerDataByte(1500L) 38 | .minGasLimit(BigInteger.valueOf(70_000L)) 39 | .minGasPrice(BigInteger.valueOf(1_000_000_000L)) 40 | .minTransactionVersion(DEFAULT_VERSION) 41 | .build(); 42 | } 43 | 44 | /** 45 | * Method called at startup which is using the NetworkInteractor to synchronise the configuration from the network 46 | */ 47 | @PostConstruct 48 | public void sync() { 49 | networkInteractor.getNetworkConfig() 50 | .doOnSuccess(r -> { 51 | config = r; 52 | log.info("MultiversX network configuration synced. Chain ID: {}", r.getChainId()); 53 | }) 54 | .doOnError(e -> 55 | log.error("Could not sync MultiversX network configuration at startup. Using default configs for chain ID {}.", 56 | config.getChainId())) 57 | .subscribe(); 58 | } 59 | 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/config/constants/AddressConstants.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.config.constants; 2 | 3 | /** 4 | * Class containing static config values used in Address construction and validation 5 | * 6 | * @author carlo_stanciu 7 | */ 8 | public class AddressConstants { 9 | 10 | public static final String HRP = "erd"; 11 | public static final int PUBKEY_LENGTH = 32; 12 | public static final int PUBKEY_HEX_LENGTH = PUBKEY_LENGTH * 2; 13 | public static final int BECH32_LENGTH = 62; 14 | public static final String ZERO_PUBKEY_STRING = "0000000000000000000000000000000000000000000000000000000000000000"; 15 | 16 | } 17 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/config/constants/CurrencyConstants.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.config.constants; 2 | 3 | import java.math.BigInteger; 4 | 5 | /** 6 | * Class containing static config values used in Balance construction and validation 7 | * 8 | * @author carlo_stanciu 9 | */ 10 | public class CurrencyConstants { 11 | 12 | public static final Integer BASE10 = 10; 13 | public static final Integer DENOMINATION = 18; 14 | public static final String ONE_EGLD_STRING = BigInteger.ONE.multiply(BigInteger.TEN.pow(DENOMINATION)).toString(); 15 | public static final String EGLD_TICKER = "EGLD"; 16 | 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/config/constants/TransactionConstants.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.config.constants; 2 | 3 | import java.math.BigInteger; 4 | 5 | /** 6 | * Class containing static config values used in Transaction construction and validation 7 | * 8 | * @author carlo_stanciu 9 | */ 10 | public class TransactionConstants { 11 | 12 | public static final Integer TRANSACTION_VERSION_DEFAULT = 1; 13 | public static final Integer TRANSACTION_VERSION_TX_HASH_SIGN = 2; 14 | public static final Integer SIGNATURE_LENGTH = 64; 15 | public static final Integer SIGNATURE_LENGTH_HEX = SIGNATURE_LENGTH * 2; 16 | public static final BigInteger SC_CALL_GAS_LIMIT = BigInteger.valueOf(20_000_000L); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/config/constants/WalletConstants.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.config.constants; 2 | 3 | /** 4 | * Class containing static config values used in Wallet construction and validation 5 | * 6 | * @author carlo_stanciu 7 | */ 8 | public class WalletConstants { 9 | 10 | public static final int DEFAULT_ENTROPY_BITS = 256; 11 | public static final int PRIVATE_KEY_LENGTH = 64; 12 | public static final String BIP39_SALT_MODIFIER = "mnemonic"; 13 | public static final int BIP39_PBKDF2_ROUNDS = 2048; 14 | public static final String BIP32_SEED_MODIFIER = "ed25519 seed"; 15 | public static final long[] MX_DERIVATION_PATH = {44, 508, 0, 0, 0}; 16 | public static final long HARDENED_OFFSET = 0x80000000; 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/domain/ApiModelToDomainConvertible.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain; 2 | 3 | /** 4 | * An Interface describing the behaviour of a API object model converting into a domain object 5 | * 6 | * @param - domain object type 7 | * @author carlo_stanciu 8 | */ 9 | public interface ApiModelToDomainConvertible { 10 | 11 | /** 12 | * Method used to map API object model to a domain object 13 | * 14 | * @return - T domain object 15 | */ 16 | T toDomainObject(); 17 | 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/domain/account/Account.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.account; 2 | 3 | import lombok.Data; 4 | import io.ezalabs.multiversxspringbootstarterreactive.domain.common.Balance; 5 | import io.ezalabs.multiversxspringbootstarterreactive.domain.common.Nonce; 6 | 7 | /** 8 | * Domain object for Account representation 9 | * 10 | * @author carlo_stanciu 11 | */ 12 | @Data 13 | public class Account { 14 | 15 | private Address address = Address.zero(); 16 | private Nonce nonce = Nonce.zero(); 17 | private Balance balance = Balance.zero(); 18 | private String code; 19 | private String username; 20 | 21 | } 22 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/domain/common/Nonce.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.common; 2 | 3 | import io.ezalabs.multiversxspringbootstarterreactive.error.exception.InvalidNonceException; 4 | import io.ezalabs.multiversxspringbootstarterreactive.util.HexValidator; 5 | import lombok.Value; 6 | 7 | /** 8 | * Value object for Nonce 9 | * 10 | * @author carlo_stanciu 11 | */ 12 | @Value 13 | public class Nonce { 14 | 15 | Long value; 16 | 17 | private Nonce(Long value) { 18 | if (value < 0) { 19 | throw new InvalidNonceException(value); 20 | } 21 | 22 | this.value = value; 23 | } 24 | 25 | /** 26 | * Creates Nonce from Long 27 | * 28 | * @param value - Long value for nonce 29 | * @return - an instance of Nonce 30 | */ 31 | public static Nonce fromLong(Long value) { 32 | return new Nonce(value); 33 | } 34 | 35 | /** 36 | * Creates a Nonce object with value 0 37 | * 38 | * @return - an instance of Nonce 39 | */ 40 | public static Nonce zero() { 41 | return new Nonce(0L); 42 | } 43 | 44 | /** 45 | * Getter 46 | * 47 | * @return - hex value of the nonce 48 | */ 49 | public String getHex() { 50 | return HexValidator.processNumberHexArgument(Long.toString(value, 16)); 51 | } 52 | 53 | @Override 54 | public String toString() { 55 | return value.toString(); 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/domain/esdt/ESDTLocalOp.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.esdt; 2 | 3 | import static java.lang.String.format; 4 | 5 | import io.ezalabs.multiversxspringbootstarterreactive.config.constants.ESDTConstants; 6 | import io.ezalabs.multiversxspringbootstarterreactive.domain.common.Balance; 7 | import io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.common.TokenIdentifier; 8 | import io.ezalabs.multiversxspringbootstarterreactive.domain.transaction.GasLimit; 9 | import io.ezalabs.multiversxspringbootstarterreactive.domain.transaction.PayloadData; 10 | import io.ezalabs.multiversxspringbootstarterreactive.domain.wallet.Wallet; 11 | import io.ezalabs.multiversxspringbootstarterreactive.interactor.transaction.TransactionRequest; 12 | import lombok.Builder; 13 | import lombok.NonNull; 14 | import lombok.Value; 15 | 16 | /** 17 | * Value object for ESDT Local operations minting 18 | * 19 | * @author carlo_stanciu 20 | */ 21 | @Builder 22 | @Value 23 | public class ESDTLocalOp implements ESDTTransaction { 24 | 25 | @NonNull 26 | Type type; 27 | @NonNull 28 | TokenIdentifier tokenIdentifier; 29 | @NonNull 30 | Balance amount; 31 | @NonNull 32 | @Builder.Default 33 | GasLimit gasLimit = GasLimit.defaultEsdtLocalOp(); 34 | 35 | private PayloadData processPayloadData() { 36 | return PayloadData.fromString(format("%s@%s@%s", 37 | processType(), 38 | tokenIdentifier.getHex(), 39 | amount.getHex())); 40 | } 41 | 42 | @Override 43 | public TransactionRequest toTransactionRequest(Wallet wallet) { 44 | return TransactionRequest.builder() 45 | .receiverAddress(wallet.getAddress()) 46 | .data(processPayloadData()) 47 | .value(Balance.zero()) 48 | .gasLimit(gasLimit) 49 | .build(); 50 | } 51 | 52 | private String processType() { 53 | return type.equals(Type.MINT) ? ESDTConstants.ESDT_MINT_CALL : ESDTConstants.ESDT_BURN_CALL; 54 | } 55 | 56 | public enum Type {MINT, BURN} 57 | } 58 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/domain/esdt/ESDTNFTMultiTransfer.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.esdt; 2 | 3 | import static java.lang.String.format; 4 | 5 | import io.ezalabs.multiversxspringbootstarterreactive.config.constants.ESDTConstants; 6 | import io.ezalabs.multiversxspringbootstarterreactive.domain.account.Address; 7 | import io.ezalabs.multiversxspringbootstarterreactive.domain.common.Balance; 8 | import io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.common.TransferToken; 9 | import io.ezalabs.multiversxspringbootstarterreactive.domain.transaction.GasLimit; 10 | import io.ezalabs.multiversxspringbootstarterreactive.domain.transaction.PayloadData; 11 | import io.ezalabs.multiversxspringbootstarterreactive.domain.wallet.Wallet; 12 | import io.ezalabs.multiversxspringbootstarterreactive.interactor.transaction.TransactionRequest; 13 | import io.ezalabs.multiversxspringbootstarterreactive.util.HexValidator; 14 | import java.util.List; 15 | import java.util.stream.Collectors; 16 | import lombok.Builder; 17 | import lombok.NonNull; 18 | import lombok.Value; 19 | 20 | /** 21 | * Value object for multi ESDT transfer 22 | * 23 | * @author carlo_stanciu 24 | */ 25 | @Builder 26 | @Value 27 | public class ESDTNFTMultiTransfer implements ESDTTransaction { 28 | 29 | @NonNull 30 | Address receiverAddress; 31 | @NonNull 32 | List tokenList; 33 | 34 | private PayloadData processPayloadData() { 35 | return PayloadData.fromString(String.format("%s@%s@%s@%s", 36 | ESDTConstants.ESDT_MULTI_TRANSFER_CALL, 37 | receiverAddress.getHex(), 38 | HexValidator.processNumberHexArgument(Integer.toString(tokenList.size(), 16)), 39 | processTokenList())); 40 | } 41 | 42 | @Override 43 | public TransactionRequest toTransactionRequest(Wallet wallet) { 44 | return TransactionRequest.builder() 45 | .receiverAddress(wallet.getAddress()) 46 | .data(processPayloadData()) 47 | .value(Balance.zero()) 48 | .gasLimit(GasLimit.multiEsdtTransfer(tokenList.size())) 49 | .build(); 50 | } 51 | 52 | private String processTokenList() { 53 | return tokenList.stream() 54 | .map(t -> t.getIdentifier().getHex() 55 | + "@" + t.getNonce().getHex() 56 | + "@" + t.getAmount().getHex()) 57 | .collect(Collectors.joining("@")); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/domain/esdt/ESDTOwnershipTransfer.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.esdt; 2 | 3 | import static java.lang.String.format; 4 | 5 | import io.ezalabs.multiversxspringbootstarterreactive.config.constants.ESDTConstants; 6 | import io.ezalabs.multiversxspringbootstarterreactive.domain.account.Address; 7 | import io.ezalabs.multiversxspringbootstarterreactive.domain.common.Balance; 8 | import io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.common.TokenIdentifier; 9 | import io.ezalabs.multiversxspringbootstarterreactive.domain.transaction.GasLimit; 10 | import io.ezalabs.multiversxspringbootstarterreactive.domain.transaction.PayloadData; 11 | import io.ezalabs.multiversxspringbootstarterreactive.domain.wallet.Wallet; 12 | import io.ezalabs.multiversxspringbootstarterreactive.interactor.transaction.TransactionRequest; 13 | import lombok.Builder; 14 | import lombok.NonNull; 15 | import lombok.Value; 16 | 17 | /** 18 | * Value object for ESDT ownership transfer 19 | * 20 | * @author carlo_stanciu 21 | */ 22 | @Builder 23 | @Value 24 | public class ESDTOwnershipTransfer implements ESDTTransaction { 25 | 26 | @NonNull 27 | TokenIdentifier tokenIdentifier; 28 | @NonNull 29 | Address targetAddress; 30 | @NonNull 31 | @Builder.Default 32 | GasLimit gasLimit = GasLimit.defaultEsdtIssuance(); 33 | 34 | private PayloadData processPayloadData() { 35 | return PayloadData.fromString(String.format("%s@%s@%s", 36 | ESDTConstants.ESDT_TRANSFER_OWNERSHIP_CALL, 37 | tokenIdentifier.getHex(), 38 | targetAddress.getHex())); 39 | } 40 | 41 | @Override 42 | public TransactionRequest toTransactionRequest(Wallet wallet) { 43 | return TransactionRequest.builder() 44 | .receiverAddress(Address.fromBech32(ESDTConstants.ESDT_ISSUER_BECH32_ADDRESS)) 45 | .data(processPayloadData()) 46 | .value(Balance.zero()) 47 | .gasLimit(gasLimit) 48 | .build(); 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/domain/esdt/ESDTQueryType.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.esdt; 2 | 3 | public enum ESDTQueryType { 4 | 5 | ALL, FUNGIBLE, NON_FUNGIBLE, SEMI_FUNGIBLE 6 | 7 | } 8 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/domain/esdt/ESDTRoleAssignment.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.esdt; 2 | 3 | import static java.lang.String.format; 4 | 5 | import io.ezalabs.multiversxspringbootstarterreactive.config.constants.ESDTConstants; 6 | import io.ezalabs.multiversxspringbootstarterreactive.domain.account.Address; 7 | import io.ezalabs.multiversxspringbootstarterreactive.domain.common.Balance; 8 | import io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.common.ESDTSpecialRole; 9 | import io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.common.TokenIdentifier; 10 | import io.ezalabs.multiversxspringbootstarterreactive.domain.transaction.GasLimit; 11 | import io.ezalabs.multiversxspringbootstarterreactive.domain.transaction.PayloadData; 12 | import io.ezalabs.multiversxspringbootstarterreactive.domain.wallet.Wallet; 13 | import io.ezalabs.multiversxspringbootstarterreactive.error.ErrorMessage; 14 | import io.ezalabs.multiversxspringbootstarterreactive.interactor.transaction.TransactionRequest; 15 | import java.util.Set; 16 | import java.util.stream.Collectors; 17 | import lombok.Builder; 18 | import lombok.NonNull; 19 | import lombok.Value; 20 | 21 | /** 22 | * Value object for ESDT role assignment 23 | * 24 | * @author carlo_stanciu 25 | */ 26 | @Builder 27 | @Value 28 | public class ESDTRoleAssignment implements ESDTTransaction { 29 | 30 | @NonNull 31 | Type type; 32 | @NonNull 33 | TokenIdentifier tokenIdentifier; 34 | @NonNull 35 | Address address; 36 | @NonNull 37 | Set roles; 38 | @NonNull 39 | @Builder.Default 40 | GasLimit gasLimit = GasLimit.defaultEsdtIssuance(); 41 | 42 | private PayloadData processPayloadData() { 43 | if (roles.isEmpty()) { 44 | throw new IllegalArgumentException(ErrorMessage.TOKEN_ROLE.getValue()); 45 | } 46 | 47 | return PayloadData.fromString(format("%s@%s@%s@%s", 48 | processType(), 49 | tokenIdentifier.getHex(), 50 | address.getHex(), 51 | roles.stream() 52 | .map(ESDTSpecialRole::getHex) 53 | .collect(Collectors.joining("@")))); 54 | } 55 | 56 | @Override 57 | public TransactionRequest toTransactionRequest(Wallet wallet) { 58 | return TransactionRequest.builder() 59 | .receiverAddress(Address.fromBech32(ESDTConstants.ESDT_ISSUER_BECH32_ADDRESS)) 60 | .data(processPayloadData()) 61 | .value(Balance.zero()) 62 | .gasLimit(gasLimit) 63 | .build(); 64 | } 65 | 66 | private String processType() { 67 | return type.equals(Type.SET) ? ESDTConstants.ESDT_SET_ROLE_CALL : ESDTConstants.ESDT_UNSET_ROLE_CALL; 68 | } 69 | 70 | public enum Type {SET, UNSET} 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/domain/esdt/ESDTTransaction.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.esdt; 2 | 3 | import io.ezalabs.multiversxspringbootstarterreactive.domain.wallet.Wallet; 4 | import io.ezalabs.multiversxspringbootstarterreactive.interactor.transaction.TransactionRequest; 5 | 6 | public interface ESDTTransaction { 7 | 8 | TransactionRequest toTransactionRequest(Wallet wallet); 9 | 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/domain/esdt/ESDTUpgrade.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.esdt; 2 | 3 | import static java.lang.String.format; 4 | 5 | import io.ezalabs.multiversxspringbootstarterreactive.config.constants.ESDTConstants; 6 | import io.ezalabs.multiversxspringbootstarterreactive.domain.account.Address; 7 | import io.ezalabs.multiversxspringbootstarterreactive.domain.common.Balance; 8 | import io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.common.TokenIdentifier; 9 | import io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.common.TokenProperty; 10 | import io.ezalabs.multiversxspringbootstarterreactive.domain.transaction.GasLimit; 11 | import io.ezalabs.multiversxspringbootstarterreactive.domain.transaction.PayloadData; 12 | import io.ezalabs.multiversxspringbootstarterreactive.domain.wallet.Wallet; 13 | import io.ezalabs.multiversxspringbootstarterreactive.error.ErrorMessage; 14 | import io.ezalabs.multiversxspringbootstarterreactive.interactor.transaction.TransactionRequest; 15 | import java.util.HashSet; 16 | import java.util.Set; 17 | import java.util.stream.Collectors; 18 | import lombok.Builder; 19 | import lombok.NonNull; 20 | import lombok.Value; 21 | 22 | /** 23 | * Value object for ESDT upgrading 24 | * 25 | * @author carlo_stanciu 26 | */ 27 | @Builder 28 | @Value 29 | public class ESDTUpgrade implements ESDTTransaction { 30 | 31 | @NonNull 32 | TokenIdentifier tokenIdentifier; 33 | @Builder.Default 34 | GasLimit gasLimit = GasLimit.defaultEsdtIssuance(); 35 | @Builder.Default 36 | Set properties = new HashSet<>(); 37 | 38 | private PayloadData processPayloadData() { 39 | if (properties.isEmpty()) { 40 | throw new IllegalArgumentException(ErrorMessage.TOKEN_PROPERTY.getValue()); 41 | } 42 | 43 | return PayloadData.fromString(String.format("%s@%s%s", 44 | ESDTConstants.ESDT_UPGRADE_CALL, 45 | tokenIdentifier.getHex(), 46 | properties.stream() 47 | .map(p -> "@" + p.getNameHex() + "@" + p.getValueHex()) 48 | .collect(Collectors.joining()))); 49 | } 50 | 51 | @Override 52 | public TransactionRequest toTransactionRequest(Wallet wallet) { 53 | return TransactionRequest.builder() 54 | .receiverAddress(Address.fromBech32(ESDTConstants.ESDT_ISSUER_BECH32_ADDRESS)) 55 | .data(processPayloadData()) 56 | .value(Balance.zero()) 57 | .gasLimit(gasLimit) 58 | .build(); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/domain/esdt/NFTAddURI.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.esdt; 2 | 3 | import static java.lang.String.format; 4 | 5 | import io.ezalabs.multiversxspringbootstarterreactive.config.constants.ESDTConstants; 6 | import io.ezalabs.multiversxspringbootstarterreactive.domain.common.Balance; 7 | import io.ezalabs.multiversxspringbootstarterreactive.domain.common.Nonce; 8 | import io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.common.ESDTUri; 9 | import io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.common.TokenIdentifier; 10 | import io.ezalabs.multiversxspringbootstarterreactive.domain.transaction.GasLimit; 11 | import io.ezalabs.multiversxspringbootstarterreactive.domain.transaction.PayloadData; 12 | import io.ezalabs.multiversxspringbootstarterreactive.domain.wallet.Wallet; 13 | import io.ezalabs.multiversxspringbootstarterreactive.interactor.transaction.TransactionRequest; 14 | import java.util.Set; 15 | import java.util.stream.Collectors; 16 | import lombok.Builder; 17 | import lombok.NonNull; 18 | import lombok.Value; 19 | 20 | /** 21 | * Value object for NFT URI adding 22 | * 23 | * @author carlo_stanciu 24 | */ 25 | @Builder 26 | @Value 27 | public class NFTAddURI implements ESDTTransaction { 28 | 29 | @NonNull 30 | TokenIdentifier tokenIdentifier; 31 | @NonNull 32 | Nonce nonce; 33 | @NonNull 34 | Set uris; 35 | @NonNull 36 | @Builder.Default 37 | GasLimit gasLimit = GasLimit.defaultNftCreate(); 38 | 39 | private PayloadData processPayloadData() { 40 | return PayloadData.fromString(String.format("%s@%s@%s@%s", 41 | ESDTConstants.ESDT_NFT_ADD_URI_CALL, 42 | tokenIdentifier.getHex(), 43 | nonce.getHex(), 44 | processUris())); 45 | } 46 | 47 | private String processUris() { 48 | if (uris.isEmpty()) { 49 | throw new IllegalArgumentException("List of URIs cannot be empty"); 50 | } 51 | 52 | return uris.stream() 53 | .map(ESDTUri::getHex) 54 | .collect(Collectors.joining("@")); 55 | } 56 | 57 | @Override 58 | public TransactionRequest toTransactionRequest(Wallet wallet) { 59 | return TransactionRequest.builder() 60 | .receiverAddress(wallet.getAddress()) 61 | .data(processPayloadData()) 62 | .value(Balance.zero()) 63 | .gasLimit(gasLimit) 64 | .build(); 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/domain/esdt/NFTAttributesUpdate.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.esdt; 2 | 3 | import static java.lang.String.format; 4 | 5 | import io.ezalabs.multiversxspringbootstarterreactive.config.constants.ESDTConstants; 6 | import io.ezalabs.multiversxspringbootstarterreactive.domain.common.Balance; 7 | import io.ezalabs.multiversxspringbootstarterreactive.domain.common.Nonce; 8 | import io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.common.TokenAttributes; 9 | import io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.common.TokenIdentifier; 10 | import io.ezalabs.multiversxspringbootstarterreactive.domain.transaction.GasLimit; 11 | import io.ezalabs.multiversxspringbootstarterreactive.domain.transaction.PayloadData; 12 | import io.ezalabs.multiversxspringbootstarterreactive.domain.wallet.Wallet; 13 | import io.ezalabs.multiversxspringbootstarterreactive.interactor.transaction.TransactionRequest; 14 | import lombok.Builder; 15 | import lombok.NonNull; 16 | import lombok.Value; 17 | 18 | /** 19 | * Value object for NFT attributes update 20 | * 21 | * @author carlo_stanciu 22 | */ 23 | @Builder 24 | @Value 25 | public class NFTAttributesUpdate implements ESDTTransaction { 26 | 27 | @NonNull 28 | TokenIdentifier tokenIdentifier; 29 | @NonNull 30 | Nonce nonce; 31 | @NonNull 32 | TokenAttributes tokenAttributes; 33 | @NonNull 34 | @Builder.Default 35 | GasLimit gasLimit = GasLimit.defaultNftCreate(); 36 | 37 | private PayloadData processPayloadData() { 38 | return PayloadData.fromString(String.format("%s@%s@%s@%s", 39 | ESDTConstants.ESDT_NFT_UPDATE_ATTRIBUTES_CALL, 40 | tokenIdentifier.getHex(), 41 | nonce.getHex(), 42 | tokenAttributes.getHex())); 43 | } 44 | 45 | @Override 46 | public TransactionRequest toTransactionRequest(Wallet wallet) { 47 | return TransactionRequest.builder() 48 | .receiverAddress(wallet.getAddress()) 49 | .data(processPayloadData()) 50 | .value(Balance.zero()) 51 | .gasLimit(gasLimit) 52 | .build(); 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/domain/esdt/NFTCreationRoleTransfer.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.esdt; 2 | 3 | import static java.lang.String.format; 4 | 5 | import io.ezalabs.multiversxspringbootstarterreactive.config.constants.ESDTConstants; 6 | import io.ezalabs.multiversxspringbootstarterreactive.domain.account.Address; 7 | import io.ezalabs.multiversxspringbootstarterreactive.domain.common.Balance; 8 | import io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.common.TokenIdentifier; 9 | import io.ezalabs.multiversxspringbootstarterreactive.domain.transaction.GasLimit; 10 | import io.ezalabs.multiversxspringbootstarterreactive.domain.transaction.PayloadData; 11 | import io.ezalabs.multiversxspringbootstarterreactive.domain.wallet.Wallet; 12 | import io.ezalabs.multiversxspringbootstarterreactive.interactor.transaction.TransactionRequest; 13 | import lombok.Builder; 14 | import lombok.NonNull; 15 | import lombok.Value; 16 | 17 | /** 18 | * Value object for NFT create role transfer 19 | * 20 | * @author carlo_stanciu 21 | */ 22 | @Builder 23 | @Value 24 | public class NFTCreationRoleTransfer implements ESDTTransaction { 25 | 26 | @NonNull 27 | TokenIdentifier tokenIdentifier; 28 | @NonNull 29 | Address fromAddress; 30 | @NonNull 31 | Address toAddress; 32 | @NonNull 33 | @Builder.Default 34 | GasLimit gasLimit = GasLimit.defaultEsdtIssuance(); 35 | 36 | private PayloadData processPayloadData() { 37 | return PayloadData.fromString(String.format("%s@%s@%s@%s", 38 | ESDTConstants.ESDT_NFT_CREATE_ROLE_TRANSFER_CALL, 39 | tokenIdentifier.getHex(), 40 | fromAddress.getHex(), 41 | toAddress.getHex())); 42 | } 43 | 44 | @Override 45 | public TransactionRequest toTransactionRequest(Wallet wallet) { 46 | return TransactionRequest.builder() 47 | .receiverAddress(Address.fromBech32(ESDTConstants.ESDT_ISSUER_BECH32_ADDRESS)) 48 | .data(processPayloadData()) 49 | .value(Balance.zero()) 50 | .gasLimit(gasLimit) 51 | .build(); 52 | } 53 | 54 | } 55 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/domain/esdt/NFTSFTGlobalOp.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.esdt; 2 | 3 | import static java.lang.String.format; 4 | 5 | import io.ezalabs.multiversxspringbootstarterreactive.config.constants.ESDTConstants; 6 | import io.ezalabs.multiversxspringbootstarterreactive.domain.account.Address; 7 | import io.ezalabs.multiversxspringbootstarterreactive.domain.common.Balance; 8 | import io.ezalabs.multiversxspringbootstarterreactive.domain.common.Nonce; 9 | import io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.common.TokenIdentifier; 10 | import io.ezalabs.multiversxspringbootstarterreactive.domain.transaction.GasLimit; 11 | import io.ezalabs.multiversxspringbootstarterreactive.domain.transaction.PayloadData; 12 | import io.ezalabs.multiversxspringbootstarterreactive.domain.wallet.Wallet; 13 | import io.ezalabs.multiversxspringbootstarterreactive.interactor.transaction.TransactionRequest; 14 | import lombok.Builder; 15 | import lombok.NonNull; 16 | import lombok.Value; 17 | 18 | /** 19 | * Value object for NFT \ SFT global operations 20 | * 21 | * @author carlo_stanciu 22 | */ 23 | @Builder 24 | @Value 25 | public class NFTSFTGlobalOp implements ESDTTransaction { 26 | 27 | @NonNull 28 | Type type; 29 | @NonNull 30 | TokenIdentifier tokenIdentifier; 31 | @NonNull 32 | Nonce nonce; 33 | @NonNull 34 | Address address; 35 | @NonNull 36 | @Builder.Default 37 | GasLimit gasLimit = GasLimit.defaultEsdtGlobalOp(); 38 | 39 | private PayloadData processPayloadData() { 40 | return PayloadData.fromString(format("%s@%s@%s@%s", 41 | processType(), 42 | tokenIdentifier.getHex(), 43 | nonce.getHex(), 44 | address.getHex())); 45 | } 46 | 47 | @Override 48 | public TransactionRequest toTransactionRequest(Wallet wallet) { 49 | return TransactionRequest.builder() 50 | .receiverAddress(Address.fromBech32(ESDTConstants.ESDT_ISSUER_BECH32_ADDRESS)) 51 | .data(processPayloadData()) 52 | .value(Balance.zero()) 53 | .gasLimit(gasLimit) 54 | .build(); 55 | } 56 | 57 | private String processType() { 58 | switch (type) { 59 | case FREEZE: 60 | return ESDTConstants.ESDT_NFT_FREEZE_CALL; 61 | case UNFREEZE: 62 | return ESDTConstants.ESDT_NFT_UNFREEZE_CALL; 63 | case WIPE: 64 | return ESDTConstants.ESDT_NFT_WIPE_CALL; 65 | default: 66 | throw new IllegalArgumentException(); 67 | } 68 | } 69 | 70 | public enum Type {FREEZE, UNFREEZE, WIPE} 71 | } 72 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/domain/esdt/NFTSFTLocalOp.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.esdt; 2 | 3 | import static java.lang.String.format; 4 | 5 | import io.ezalabs.multiversxspringbootstarterreactive.config.constants.ESDTConstants; 6 | import io.ezalabs.multiversxspringbootstarterreactive.domain.common.Balance; 7 | import io.ezalabs.multiversxspringbootstarterreactive.domain.common.Nonce; 8 | import io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.common.TokenIdentifier; 9 | import io.ezalabs.multiversxspringbootstarterreactive.domain.transaction.GasLimit; 10 | import io.ezalabs.multiversxspringbootstarterreactive.domain.transaction.PayloadData; 11 | import io.ezalabs.multiversxspringbootstarterreactive.domain.wallet.Wallet; 12 | import io.ezalabs.multiversxspringbootstarterreactive.interactor.transaction.TransactionRequest; 13 | import lombok.Builder; 14 | import lombok.NonNull; 15 | import lombok.Value; 16 | 17 | /** 18 | * Value object for NFT \ SFT local operations (add/burn quantity) 19 | *

20 | * !!! add quantity will only work for SFT token 21 | * 22 | * @author carlo_stanciu 23 | */ 24 | @Builder 25 | @Value 26 | public class NFTSFTLocalOp implements ESDTTransaction { 27 | 28 | @NonNull 29 | Type type; 30 | @NonNull 31 | TokenIdentifier tokenIdentifier; 32 | @NonNull 33 | Nonce nonce; 34 | @NonNull 35 | Balance amount; 36 | @NonNull 37 | @Builder.Default 38 | GasLimit gasLimit = GasLimit.defaultNftCreate(); 39 | 40 | private PayloadData processPayloadData() { 41 | return PayloadData.fromString(format("%s@%s@%s@%s", 42 | processType(), 43 | tokenIdentifier.getHex(), 44 | nonce.getHex(), 45 | amount.getHex())); 46 | } 47 | 48 | @Override 49 | public TransactionRequest toTransactionRequest(Wallet wallet) { 50 | return TransactionRequest.builder() 51 | .receiverAddress(wallet.getAddress()) 52 | .data(processPayloadData()) 53 | .value(Balance.zero()) 54 | .gasLimit(gasLimit) 55 | .build(); 56 | } 57 | 58 | private String processType() { 59 | return type.equals(Type.ADD) ? ESDTConstants.ESDT_NFTSFT_ADD_CALL : ESDTConstants.ESDT_NFTSFT_BURN_CALL; 60 | } 61 | 62 | public enum Type {ADD, BURN} 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/domain/esdt/NFTStopCreation.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.esdt; 2 | 3 | import static java.lang.String.format; 4 | 5 | import io.ezalabs.multiversxspringbootstarterreactive.config.constants.ESDTConstants; 6 | import io.ezalabs.multiversxspringbootstarterreactive.domain.account.Address; 7 | import io.ezalabs.multiversxspringbootstarterreactive.domain.common.Balance; 8 | import io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.common.TokenIdentifier; 9 | import io.ezalabs.multiversxspringbootstarterreactive.domain.transaction.GasLimit; 10 | import io.ezalabs.multiversxspringbootstarterreactive.domain.transaction.PayloadData; 11 | import io.ezalabs.multiversxspringbootstarterreactive.domain.wallet.Wallet; 12 | import io.ezalabs.multiversxspringbootstarterreactive.interactor.transaction.TransactionRequest; 13 | import lombok.Builder; 14 | import lombok.NonNull; 15 | import lombok.Value; 16 | 17 | /** 18 | * Value object for NFT stop creation transfer 19 | * 20 | * @author carlo_stanciu 21 | */ 22 | @Builder 23 | @Value 24 | public class NFTStopCreation implements ESDTTransaction { 25 | 26 | @NonNull 27 | TokenIdentifier tokenIdentifier; 28 | @NonNull 29 | @Builder.Default 30 | GasLimit gasLimit = GasLimit.defaultEsdtIssuance(); 31 | 32 | private PayloadData processPayloadData() { 33 | return PayloadData.fromString(String.format("%s@%s", 34 | ESDTConstants.ESDT_NFT_STOP_CREATION_CALL, 35 | tokenIdentifier.getHex())); 36 | } 37 | 38 | @Override 39 | public TransactionRequest toTransactionRequest(Wallet wallet) { 40 | return TransactionRequest.builder() 41 | .receiverAddress(Address.fromBech32(ESDTConstants.ESDT_ISSUER_BECH32_ADDRESS)) 42 | .data(processPayloadData()) 43 | .value(Balance.zero()) 44 | .gasLimit(gasLimit) 45 | .build(); 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/domain/esdt/common/ESDTSpecialRole.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.common; 2 | 3 | import io.ezalabs.multiversxspringbootstarterreactive.config.constants.ESDTConstants; 4 | import io.ezalabs.multiversxspringbootstarterreactive.error.ErrorMessage; 5 | import java.util.HashMap; 6 | import java.util.Map; 7 | import java.util.Optional; 8 | import lombok.Getter; 9 | import org.bouncycastle.util.encoders.Hex; 10 | 11 | @Getter 12 | public enum ESDTSpecialRole { 13 | 14 | ESDT_LOCAL_BURN(ESDTConstants.ESDT_BURN_ROLE), 15 | ESDT_LOCAL_MINT(ESDTConstants.ESDT_MINT_ROLE), 16 | 17 | ESDT_TRANSFER(ESDTConstants.ESDT_TRANSFER), 18 | 19 | ESDT_NFT_CREATE(ESDTConstants.ESDT_NFT_CREATE_ROLE), 20 | ESDT_NFT_BURN(ESDTConstants.ESDT_NFT_BURN_ROLE), 21 | ESDT_NFT_ADD_QUANTITY(ESDTConstants.ESDT_NFT_ADD_QUANTITY_ROLE), 22 | ESDT_NFT_UPDATE_ATTRIBUTES(ESDTConstants.ESDT_NFT_UPDATE_ATTRIBUTES), 23 | ESDT_NFT_ADD_URI(ESDTConstants.ESDT_NFT_ADD_URI); 24 | 25 | private static final Map BY_VALUE = new HashMap<>(); 26 | 27 | static { 28 | for (ESDTSpecialRole e : values()) { 29 | BY_VALUE.put(e.value, e); 30 | } 31 | } 32 | 33 | private final String hex; 34 | private final String value; 35 | 36 | ESDTSpecialRole(String value) { 37 | this.value = value; 38 | this.hex = Hex.toHexString(value.getBytes()); 39 | } 40 | 41 | public static ESDTSpecialRole getByValue(String value) { 42 | return Optional.ofNullable(BY_VALUE.get(value)) 43 | .orElseThrow(() -> new IllegalArgumentException(ErrorMessage.TOKEN_ROLE.getValue())); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/domain/esdt/common/TokenAttributes.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.common; 2 | 3 | import static io.netty.util.internal.StringUtil.isNullOrEmpty; 4 | 5 | import io.ezalabs.multiversxspringbootstarterreactive.error.ErrorMessage; 6 | import java.util.Arrays; 7 | import java.util.Set; 8 | import java.util.stream.Collectors; 9 | import lombok.Value; 10 | import org.bouncycastle.util.encoders.Hex; 11 | 12 | /** 13 | * Value object for ESDT token attributes 14 | * 15 | * @author carlo_stanciu 16 | */ 17 | @Value 18 | public class TokenAttributes { 19 | 20 | ESDTUri metadataUri; 21 | Set tags; 22 | 23 | private TokenAttributes(ESDTUri metadataUri, Set tags) { 24 | this.metadataUri = metadataUri; 25 | this.tags = tags; 26 | } 27 | 28 | /** 29 | * Creates a TokenName object from String inputs 30 | * 31 | * @return - an instance of TokenAttributes 32 | */ 33 | public static TokenAttributes fromString(String metadata, String[] tags) { 34 | verifyNullEmpty(tags); 35 | var tagsW = Arrays.stream(tags).map(TokenAttributes::removeWhitespace) 36 | .collect(Collectors.toSet()); 37 | 38 | return new TokenAttributes(ESDTUri.fromString(metadata, ESDTUri.Type.METADATA), tagsW); 39 | } 40 | 41 | /** 42 | * Getter 43 | * 44 | * @return - hex value of the Token Attributes 45 | */ 46 | public String getHex() { 47 | return Hex.toHexString(toString().getBytes()); 48 | } 49 | 50 | /** 51 | * Returns the value 52 | * 53 | * @return - value in String format 54 | */ 55 | @Override 56 | public String toString() { 57 | return "metadata:" + metadataUri.getValue() + ";tags:" + String.join(",", tags); 58 | } 59 | 60 | private static String removeWhitespace(String value) { 61 | return value.replaceAll("\\s+", ""); 62 | } 63 | 64 | private static void verifyNullEmpty(String... value) { 65 | if (value == null || value.length == 0) { 66 | throw new IllegalArgumentException(ErrorMessage.TOKEN_ATTRIBUTES.getValue()); 67 | } 68 | 69 | Arrays.stream(value).forEach(v -> { 70 | if (isNullOrEmpty(v)) { 71 | throw new IllegalArgumentException(ErrorMessage.TOKEN_ATTRIBUTES.getValue()); 72 | } 73 | }); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/domain/esdt/common/TokenDecimals.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.common; 2 | 3 | import io.ezalabs.multiversxspringbootstarterreactive.error.ErrorMessage; 4 | import io.ezalabs.multiversxspringbootstarterreactive.util.HexValidator; 5 | import lombok.Value; 6 | 7 | /** 8 | * Value object for ESDT token decimals 9 | * 10 | * @author carlo_stanciu 11 | */ 12 | @Value 13 | public class TokenDecimals { 14 | 15 | Integer decimals; 16 | 17 | private TokenDecimals(Integer decimals) { 18 | this.decimals = decimals; 19 | } 20 | 21 | /** 22 | * Creates an TokenDecimals object from number input 23 | * 24 | * @return - an instance of TokenDecimals 25 | */ 26 | public static TokenDecimals fromNumber(Integer decimals) { 27 | verifyDecimals(decimals); 28 | 29 | return new TokenDecimals(decimals); 30 | } 31 | 32 | /** 33 | * Creates an TokenDecimals object from String inputs 34 | * 35 | * @return - an instance of TokenDecimals 36 | */ 37 | public static TokenDecimals fromString(String decimals) { 38 | var decimalsNumber = Integer.parseInt(decimals.strip()); 39 | verifyDecimals(decimalsNumber); 40 | 41 | return fromNumber(decimalsNumber); 42 | } 43 | 44 | /** 45 | * Getter 46 | * 47 | * @return - hex value of the decimals 48 | */ 49 | public String getHex() { 50 | return HexValidator.processNumberHexArgument(Integer.toString(decimals, 16)); 51 | } 52 | 53 | /** 54 | * Returns the value 55 | * 56 | * @return - value in String format 57 | */ 58 | @Override 59 | public String toString() { 60 | return decimals.toString(); 61 | } 62 | 63 | private static void verifyDecimals(Integer decimals) { 64 | if (!(decimals >= 0 && decimals <= 18 && decimals % 2 == 0)) { 65 | throw new IllegalArgumentException(ErrorMessage.TOKEN_DECIMALS.getValue()); 66 | } 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/domain/esdt/common/TokenIdentifier.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.common; 2 | 3 | import static io.netty.util.internal.StringUtil.isNullOrEmpty; 4 | import static java.lang.String.format; 5 | 6 | import io.ezalabs.multiversxspringbootstarterreactive.error.ErrorMessage; 7 | import lombok.Value; 8 | import org.bouncycastle.util.encoders.Hex; 9 | 10 | /** 11 | * Value object for ESDT token identifier 12 | * 13 | * @author carlo_stanciu 14 | */ 15 | @Value 16 | public class TokenIdentifier { 17 | 18 | String value; 19 | 20 | private TokenIdentifier(String name) { 21 | this.value = name; 22 | } 23 | 24 | /** 25 | * ¬ Creates a TokenIdentifier object from String input 26 | * 27 | * @return - an instance of TokenIdentifier 28 | */ 29 | public static TokenIdentifier fromString(String name) { 30 | if (isNullOrEmpty(name)) { 31 | throw new IllegalArgumentException(ErrorMessage.TOKEN_IDENTIFIER.getValue()); 32 | } 33 | 34 | var value = name.replaceAll("\\s+", "").toLowerCase(); 35 | verifyFormat(value); 36 | 37 | return new TokenIdentifier(format("%s-%s", 38 | value.split("-")[0].toUpperCase(), 39 | value.split("-")[1].toLowerCase())); 40 | } 41 | 42 | /** 43 | * Getter 44 | * 45 | * @return - hex value of the TokenIdentifier 46 | */ 47 | public String getHex() { 48 | return Hex.toHexString(value.getBytes()); 49 | } 50 | 51 | /** 52 | * Returns the value 53 | * 54 | * @return - value in String format 55 | */ 56 | @Override 57 | public String toString() { 58 | return value; 59 | } 60 | 61 | private static void verifyFormat(String value) { 62 | if (!(value.matches("^[a-zA-Z0-9]{3,10}+-[a-zA-Z0-9]{6}+$"))) { 63 | throw new IllegalArgumentException(ErrorMessage.TOKEN_IDENTIFIER.getValue()); 64 | } 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/domain/esdt/common/TokenInitialSupply.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.common; 2 | 3 | import io.ezalabs.multiversxspringbootstarterreactive.error.ErrorMessage; 4 | import io.ezalabs.multiversxspringbootstarterreactive.util.HexValidator; 5 | import java.math.BigInteger; 6 | import lombok.Value; 7 | 8 | /** 9 | * Value object for ESDT token initial supply 10 | * 11 | * @author carlo_stanciu 12 | */ 13 | @Value 14 | public class TokenInitialSupply { 15 | 16 | BigInteger supply; 17 | 18 | private TokenInitialSupply(BigInteger supply) { 19 | this.supply = supply; 20 | } 21 | 22 | /** 23 | * Creates an InitialSupply object from number inputs 24 | * 25 | * @return - an instance of InitialSupply 26 | */ 27 | public static TokenInitialSupply fromNumber(BigInteger supply) { 28 | verifySupply(supply); 29 | 30 | return new TokenInitialSupply(supply); 31 | } 32 | 33 | /** 34 | * Creates an InitialSupply object from String inputs 35 | * 36 | * @return - an instance of InitialSupply 37 | */ 38 | public static TokenInitialSupply fromString(String supply) { 39 | var supplyNumber = new BigInteger(supply.strip()); 40 | verifySupply(supplyNumber); 41 | 42 | return fromNumber(supplyNumber); 43 | } 44 | 45 | /** 46 | * Getter 47 | * 48 | * @return - hex value of the initial supply 49 | */ 50 | public String getHex() { 51 | return HexValidator.processNumberHexArgument(supply.toString(16)); 52 | } 53 | 54 | /** 55 | * Returns the value 56 | * 57 | * @return - value in String format 58 | */ 59 | @Override 60 | public String toString() { 61 | return supply.toString(); 62 | } 63 | 64 | private static void verifySupply(BigInteger supply) { 65 | if (supply.signum() == -1 || supply.signum() == 0) { 66 | throw new IllegalArgumentException(ErrorMessage.INITIAL_SUPPLY.getValue()); 67 | } 68 | } 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/domain/esdt/common/TokenName.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.common; 2 | 3 | import static io.netty.util.internal.StringUtil.isNullOrEmpty; 4 | 5 | import io.ezalabs.multiversxspringbootstarterreactive.error.ErrorMessage; 6 | import lombok.Value; 7 | import org.bouncycastle.util.encoders.Hex; 8 | 9 | /** 10 | * Value object for ESDT token name 11 | * 12 | * @author carlo_stanciu 13 | */ 14 | @Value 15 | public class TokenName { 16 | 17 | String value; 18 | 19 | private TokenName(String name) { 20 | this.value = name; 21 | } 22 | 23 | /** 24 | * Creates a TokenName object from String input 25 | * 26 | * @return - an instance of TokenName 27 | */ 28 | public static TokenName fromString(String name) { 29 | if (isNullOrEmpty(name)) { 30 | throw new IllegalArgumentException(ErrorMessage.TOKEN_NAME.getValue()); 31 | } 32 | 33 | var value = name.replaceAll("\\s+", ""); 34 | verifyFormat(value); 35 | 36 | return new TokenName(value); 37 | } 38 | 39 | /** 40 | * Getter 41 | * 42 | * @return - hex value of the Token Name 43 | */ 44 | public String getHex() { 45 | return Hex.toHexString(value.getBytes()); 46 | } 47 | 48 | /** 49 | * Returns the value 50 | * 51 | * @return - value in String format 52 | */ 53 | @Override 54 | public String toString() { 55 | return value; 56 | } 57 | 58 | private static void verifyFormat(String value) { 59 | if (!value.matches("^[a-zA-Z0-9]{3,20}+$")) { 60 | throw new IllegalArgumentException(ErrorMessage.TOKEN_NAME.getValue()); 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/domain/esdt/common/TokenProperty.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.common; 2 | 3 | import lombok.AllArgsConstructor; 4 | import lombok.EqualsAndHashCode; 5 | import lombok.Value; 6 | import org.bouncycastle.util.encoders.Hex; 7 | 8 | /** 9 | * Value object for ESDT token property name 10 | * 11 | * @author carlo_stanciu 12 | */ 13 | @Value 14 | @AllArgsConstructor 15 | @EqualsAndHashCode(doNotUseGetters = true) 16 | public class TokenProperty { 17 | 18 | TokenPropertyName name; 19 | 20 | @EqualsAndHashCode.Exclude 21 | Boolean value; 22 | 23 | /** 24 | * Getter 25 | * 26 | * @return - hex value of the property name 27 | */ 28 | public String getNameHex() { 29 | return name.getHex(); 30 | } 31 | 32 | /** 33 | * Getter 34 | * 35 | * @return - hex value of the property name 36 | */ 37 | public String getValueHex() { 38 | return Hex.toHexString(value.toString().getBytes()); 39 | } 40 | 41 | 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/domain/esdt/common/TokenPropertyName.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.common; 2 | 3 | import io.ezalabs.multiversxspringbootstarterreactive.error.ErrorMessage; 4 | import java.util.HashMap; 5 | import java.util.Map; 6 | import java.util.Optional; 7 | import lombok.Getter; 8 | import org.bouncycastle.util.encoders.Hex; 9 | 10 | @Getter 11 | public enum TokenPropertyName { 12 | 13 | CAN_FREEZE("canFreeze"), 14 | CAN_WIPE("canWipe"), 15 | CAN_PAUSE("canPause"), 16 | CAN_CHANGE_OWNER("canChangeOwner"), 17 | CAN_UPGRADE("canUpgrade"), 18 | CAN_ADD_SPECIAL_ROLES("canAddSpecialRoles"), 19 | CAN_TRANSFER_NFT_CREATE_ROLE("canTransferNFTCreateRole"); 20 | 21 | private static final Map BY_VALUE = new HashMap<>(); 22 | 23 | static { 24 | for (TokenPropertyName e : values()) { 25 | BY_VALUE.put(e.value, e); 26 | } 27 | } 28 | 29 | private final String hex; 30 | private final String value; 31 | 32 | TokenPropertyName(String value) { 33 | this.value = value; 34 | this.hex = Hex.toHexString(value.getBytes()); 35 | } 36 | 37 | public static TokenPropertyName getByValue(String value) { 38 | return Optional.ofNullable(BY_VALUE.get(value)) 39 | .orElseThrow(() -> new IllegalArgumentException(ErrorMessage.TOKEN_PROPERTY.getValue())); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/domain/esdt/common/TokenRoyalties.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.common; 2 | 3 | import static java.util.Objects.nonNull; 4 | 5 | import io.ezalabs.multiversxspringbootstarterreactive.error.ErrorMessage; 6 | import io.ezalabs.multiversxspringbootstarterreactive.util.HexValidator; 7 | import lombok.Value; 8 | 9 | /** 10 | * Value object for ESDT NFT royalties 11 | * 12 | * @author carlo_stanciu 13 | */ 14 | @Value 15 | public class TokenRoyalties { 16 | 17 | Integer value; 18 | 19 | private TokenRoyalties(Integer number) { 20 | this.value = number; 21 | } 22 | 23 | /** 24 | * Creates an TokenRoyalties object from number input 25 | * 26 | * @return - an instance of TokenRoyalties 27 | */ 28 | public static TokenRoyalties fromNumber(Integer value) { 29 | if (!(nonNull(value) && value >= 0 && value <= 10000)) { 30 | throw new IllegalArgumentException(ErrorMessage.TOKEN_ROYALTIES.getValue()); 31 | } 32 | 33 | return new TokenRoyalties(value); 34 | } 35 | 36 | /** 37 | * Getter 38 | * 39 | * @return - hex value of the Token Royalties 40 | */ 41 | public String getHex() { 42 | return HexValidator.processNumberHexArgument(Integer.toString(value, 16)); 43 | } 44 | 45 | /** 46 | * Returns the value 47 | * 48 | * @return - value in String format 49 | */ 50 | @Override 51 | public String toString() { 52 | return value.toString(); 53 | } 54 | 55 | } 56 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/domain/esdt/common/TokenTicker.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.common; 2 | 3 | import static io.netty.util.internal.StringUtil.isNullOrEmpty; 4 | 5 | import io.ezalabs.multiversxspringbootstarterreactive.error.ErrorMessage; 6 | import lombok.Value; 7 | import org.bouncycastle.util.encoders.Hex; 8 | 9 | /** 10 | * Value object for ESDT token ticker 11 | * 12 | * @author carlo_stanciu 13 | */ 14 | @Value 15 | public class TokenTicker { 16 | 17 | String value; 18 | 19 | private TokenTicker(String name) { 20 | this.value = name; 21 | } 22 | 23 | /** 24 | * ¬ Creates a TokenTicker object from String input 25 | * 26 | * @return - an instance of TokenTicker 27 | */ 28 | public static TokenTicker fromString(String name) { 29 | if (isNullOrEmpty(name)) { 30 | throw new IllegalArgumentException(ErrorMessage.TOKEN_NAME.getValue()); 31 | } 32 | 33 | var value = name.replaceAll("\\s+", "").toUpperCase(); 34 | verifyFormat(value); 35 | 36 | return new TokenTicker(value); 37 | } 38 | 39 | /** 40 | * Getter 41 | * 42 | * @return - hex value of the Token Ticker 43 | */ 44 | public String getHex() { 45 | return Hex.toHexString(value.getBytes()); 46 | } 47 | 48 | /** 49 | * Returns the value 50 | * 51 | * @return - value in String format 52 | */ 53 | @Override 54 | public String toString() { 55 | return value; 56 | } 57 | 58 | private static void verifyFormat(String value) { 59 | if (!value.matches("^[a-zA-Z0-9]{3,10}+$")) { 60 | throw new IllegalArgumentException(ErrorMessage.TOKEN_TICKER.getValue()); 61 | } 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/domain/esdt/common/TransferToken.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.common; 2 | 3 | import lombok.Builder; 4 | import lombok.NonNull; 5 | import lombok.Value; 6 | import io.ezalabs.multiversxspringbootstarterreactive.domain.common.Balance; 7 | import io.ezalabs.multiversxspringbootstarterreactive.domain.common.Nonce; 8 | 9 | /** 10 | * Value object for ESDT token data for transfer 11 | * 12 | * @author carlo_stanciu 13 | */ 14 | @Value 15 | @Builder 16 | public class TransferToken { 17 | 18 | @NonNull 19 | TokenIdentifier identifier; 20 | @NonNull 21 | @Builder.Default 22 | Nonce nonce = Nonce.fromLong(0L); 23 | @NonNull 24 | Balance amount; 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/domain/smartcontract/ContractFunction.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.smartcontract; 2 | 3 | import java.util.Collections; 4 | import java.util.List; 5 | import java.util.stream.Collectors; 6 | import lombok.Builder; 7 | import lombok.NonNull; 8 | import lombok.Value; 9 | import io.ezalabs.multiversxspringbootstarterreactive.domain.account.Address; 10 | import io.ezalabs.multiversxspringbootstarterreactive.domain.common.Balance; 11 | import io.ezalabs.multiversxspringbootstarterreactive.domain.transaction.GasLimit; 12 | import io.ezalabs.multiversxspringbootstarterreactive.domain.transaction.PayloadData; 13 | 14 | /** 15 | * Value object for Smart Contract function 16 | * 17 | * @author carlo_stanciu 18 | */ 19 | @Builder(toBuilder = true) 20 | @Value 21 | public class ContractFunction { 22 | 23 | @NonNull 24 | Address smartContractAddress; 25 | @NonNull 26 | FunctionName functionName; 27 | @NonNull 28 | @Builder.Default 29 | List args = Collections.emptyList(); 30 | @NonNull 31 | @Builder.Default 32 | Balance value = Balance.zero(); 33 | @NonNull 34 | @Builder.Default 35 | GasLimit gasLimit = GasLimit.defaultSmartContractCall(); 36 | 37 | /** 38 | * Retrieves an instance of Contract Function containing the function name and arguments in the required format 39 | * 40 | * @return - an instance of PayloadData 41 | */ 42 | public PayloadData getPayloadData() { 43 | return PayloadData.fromString(String.format("%s%s", 44 | functionName.getValue(), 45 | args.stream() 46 | .map(p -> "@" + p.getHex()) 47 | .collect(Collectors.joining()))); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/domain/smartcontract/ContractQuery.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.smartcontract; 2 | 3 | import com.fasterxml.jackson.annotation.JsonProperty; 4 | import java.util.Collections; 5 | import java.util.List; 6 | import java.util.stream.Collectors; 7 | import lombok.AccessLevel; 8 | import lombok.Builder; 9 | import lombok.NonNull; 10 | import lombok.Value; 11 | import io.ezalabs.multiversxspringbootstarterreactive.domain.account.Address; 12 | import io.ezalabs.multiversxspringbootstarterreactive.domain.common.Balance; 13 | 14 | /** 15 | * Value object for Smart Contract query 16 | * 17 | * @author carlo_stanciu 18 | */ 19 | @Builder 20 | @Value 21 | public class ContractQuery { 22 | 23 | @NonNull 24 | Address smartContractAddress; 25 | @NonNull 26 | FunctionName functionName; 27 | @NonNull 28 | @Builder.Default 29 | List args = Collections.emptyList(); 30 | @Builder.Default 31 | Address callerAddress = Address.zero(); 32 | @Builder.Default 33 | Balance value = Balance.zero(); 34 | 35 | /** 36 | * Method used to create a Sendable representation of the query used for submitting to the ContractInteractor 37 | * 38 | * @return - instance of SendableTransaction 39 | */ 40 | public Sendable toSendable() { 41 | return Sendable.builder() 42 | .smartContractAddress(smartContractAddress.getBech32()) 43 | .functionName(functionName.getValue()) 44 | .args(args.stream().map(FunctionArg::getHex).collect(Collectors.toList()).toArray(String[]::new)) 45 | .callerAddress(callerAddress.isZero() ? null : callerAddress.getBech32()) 46 | .value(value.isZero() ? null : value.toString()) 47 | .build(); 48 | } 49 | 50 | @Value 51 | @Builder(access = AccessLevel.PRIVATE) 52 | public static class Sendable { 53 | 54 | @JsonProperty("scAddress") 55 | String smartContractAddress; 56 | @JsonProperty("funcName") 57 | String functionName; 58 | @JsonProperty("args") 59 | String[] args; 60 | @JsonProperty("caller") 61 | String callerAddress; 62 | @JsonProperty("value") 63 | String value; 64 | 65 | } 66 | 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/domain/smartcontract/FunctionArg.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.smartcontract; 2 | 3 | import static io.netty.util.internal.StringUtil.isNullOrEmpty; 4 | import static java.util.Objects.nonNull; 5 | 6 | import io.ezalabs.multiversxspringbootstarterreactive.error.ErrorMessage; 7 | import io.ezalabs.multiversxspringbootstarterreactive.util.HexValidator; 8 | import java.math.BigInteger; 9 | import lombok.Value; 10 | import org.bouncycastle.util.encoders.Hex; 11 | 12 | /** 13 | * Value object for smart contract function argument 14 | * 15 | * @author carlo_stanciu 16 | */ 17 | @Value 18 | public class FunctionArg { 19 | 20 | String sVal; 21 | BigInteger nVal; 22 | 23 | private FunctionArg(String sVal, BigInteger nVal) { 24 | this.sVal = sVal; 25 | this.nVal = nVal; 26 | } 27 | 28 | /** 29 | * Creates a FunctionArg object from String input 30 | * 31 | * @param arg - string arg 32 | * @return - an instance of FunctionArg 33 | */ 34 | public static FunctionArg fromString(String arg) { 35 | if (isNullOrEmpty(arg)) { 36 | throw new IllegalArgumentException(ErrorMessage.FUNCTION_ARG_NULL.getValue()); 37 | } 38 | return new FunctionArg(arg.trim(), null); 39 | } 40 | 41 | /** 42 | * Creates a FunctionArgs object from BigInteger input 43 | * 44 | * @param arg - number arg 45 | * @return - an instance of FunctionArg 46 | */ 47 | public static FunctionArg fromNumber(BigInteger arg) { 48 | if ((!nonNull(arg)) || arg.signum() == -1) { 49 | throw new IllegalArgumentException(ErrorMessage.FUNCTION_ARG_NULL.getValue()); 50 | } 51 | return new FunctionArg(null, arg); 52 | } 53 | 54 | /** 55 | * Getter 56 | * 57 | * @return - hex value 58 | */ 59 | public String getHex() { 60 | return nonNull(sVal) ? 61 | Hex.toHexString(sVal.getBytes()) 62 | : 63 | HexValidator.processNumberHexArgument(nVal.toString(16)); 64 | } 65 | 66 | /** 67 | * returns the arg in String format 68 | * 69 | * @return - value string 70 | */ 71 | @Override 72 | public String toString() { 73 | return nonNull(sVal) ? sVal : nVal.toString(); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/domain/smartcontract/FunctionName.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.smartcontract; 2 | 3 | import static io.netty.util.internal.StringUtil.isNullOrEmpty; 4 | 5 | import io.ezalabs.multiversxspringbootstarterreactive.error.ErrorMessage; 6 | import lombok.Value; 7 | import org.apache.logging.log4j.util.Strings; 8 | import org.bouncycastle.util.encoders.Hex; 9 | 10 | /** 11 | * Value object for smart contract function name 12 | * 13 | * @author carlo_stanciu 14 | */ 15 | @Value 16 | public class FunctionName { 17 | 18 | String value; 19 | 20 | private FunctionName(String name) { 21 | this.value = name; 22 | } 23 | 24 | /** 25 | * Creates a FunctionName object with empty array of args 26 | * 27 | * @return - an instance of FunctionName 28 | */ 29 | public static FunctionName fromString(String name) { 30 | if (isNullOrEmpty(name)) { 31 | throw new IllegalArgumentException(ErrorMessage.FUNCTION_NAME.getValue()); 32 | } 33 | 34 | return new FunctionName(name.replaceAll("\\s+", "")); 35 | } 36 | 37 | /** 38 | * Creates a FunctionName object with empty array of args 39 | * 40 | * @return - an instance of FunctionName 41 | */ 42 | public static FunctionName empty() { 43 | return new FunctionName(Strings.EMPTY); 44 | } 45 | 46 | /** 47 | * Checks if function name is empty 48 | * 49 | * @return boolean 50 | */ 51 | public boolean isEmpty() { 52 | return value.isEmpty(); 53 | } 54 | 55 | /** 56 | * Getter 57 | * 58 | * @return - hex value of the Function Name 59 | */ 60 | public String getHex() { 61 | return Hex.toHexString(value.getBytes()); 62 | } 63 | 64 | /** 65 | * Returns the value 66 | * 67 | * @return - value in String format 68 | */ 69 | @Override 70 | public String toString() { 71 | return value; 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/domain/transaction/ChainID.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.transaction; 2 | 3 | import io.ezalabs.multiversxspringbootstarterreactive.error.exception.InvalidChainIdException; 4 | import java.util.Locale; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Getter; 7 | 8 | /** 9 | * Enum representing Chain ID values 10 | * 11 | * @author carlo_stanciu 12 | */ 13 | @AllArgsConstructor 14 | @Getter 15 | public enum ChainID { 16 | 17 | MAINNET("1"), 18 | DEVNET("D"), 19 | TESTNET("T"); 20 | 21 | private final String value; 22 | 23 | /** 24 | * Creates enum instance from String input 25 | * 26 | * @param id - String value of chainID 27 | * @return - ChainID instance 28 | */ 29 | public static ChainID fromString(String id) { 30 | var value = id.toUpperCase(Locale.ROOT); 31 | 32 | switch (value) { 33 | case "1": 34 | return ChainID.MAINNET; 35 | case "D": 36 | return ChainID.DEVNET; 37 | case "T": 38 | return ChainID.TESTNET; 39 | default: 40 | throw new InvalidChainIdException(id); 41 | } 42 | } 43 | 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/domain/transaction/GasPrice.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.transaction; 2 | 3 | import io.ezalabs.multiversxspringbootstarterreactive.config.constants.CurrencyConstants; 4 | import io.ezalabs.multiversxspringbootstarterreactive.error.exception.NegativeGasException; 5 | import java.math.BigInteger; 6 | import lombok.Value; 7 | 8 | /** 9 | * Value object for GasPrice 10 | * 11 | * @author carlo_stanciu 12 | */ 13 | @Value 14 | public class GasPrice { 15 | 16 | BigInteger value; 17 | 18 | private GasPrice(BigInteger value) { 19 | if (value.signum() == -1) { 20 | throw new NegativeGasException(value); 21 | } 22 | 23 | this.value = value; 24 | } 25 | 26 | /** 27 | * Creates an GasPrice object from a number value 28 | * 29 | * @param value - value in BigInteger format 30 | * @return an instance of GasPrice 31 | */ 32 | public static GasPrice fromNumber(BigInteger value) { 33 | return new GasPrice(value); 34 | } 35 | 36 | /** 37 | * Creates an GasPrice object from a String value 38 | * 39 | * @param value - value in String format 40 | * @return an instance of GasPrice 41 | */ 42 | public static GasPrice fromString(String value) { 43 | return fromNumber(new BigInteger(value)); 44 | } 45 | 46 | @Override 47 | public String toString() { 48 | return value.toString(CurrencyConstants.BASE10); 49 | } 50 | 51 | } 52 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/domain/transaction/Hash.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.transaction; 2 | 3 | import lombok.Value; 4 | import org.bouncycastle.util.encoders.Hex; 5 | 6 | /** 7 | * Value object for Hash 8 | * 9 | * @author carlo_stanciu 10 | */ 11 | @Value 12 | public class Hash { 13 | 14 | byte[] value; 15 | 16 | private Hash(byte[] value) { 17 | this.value = value; 18 | } 19 | 20 | /** 21 | * Creates a Hash object from a String value 22 | * 23 | * @param hash - value in String format 24 | * @return - an instance of Hash 25 | */ 26 | public static Hash fromString(String hash) { 27 | return new Hash(Hex.decode(hash)); 28 | } 29 | 30 | /** 31 | * Creates an Hash object from a buffer 32 | * 33 | * @param buffer - value in buffer format 34 | * @return - an instance of Hash 35 | */ 36 | public static Hash fromBuffer(byte[] buffer) { 37 | return new Hash(buffer); 38 | } 39 | 40 | /** 41 | * Creates an empty Hash 42 | * 43 | * @return - an instance of Hash 44 | */ 45 | public static Hash empty() { 46 | return new Hash(new byte[]{}); 47 | } 48 | 49 | /** 50 | * Checks if Hash is empty 51 | * 52 | * @return - boolean 53 | */ 54 | public boolean isEmpty() { 55 | return value.length == 0; 56 | } 57 | 58 | /** 59 | * Getter 60 | * 61 | * @return - byte[] 62 | */ 63 | public byte[] getValue() { 64 | return value; 65 | } 66 | 67 | @Override 68 | public String toString() { 69 | return Hex.toHexString(value); 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/domain/transaction/PayloadData.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.transaction; 2 | 3 | import static io.netty.util.internal.StringUtil.isNullOrEmpty; 4 | 5 | import lombok.Value; 6 | import org.bouncycastle.util.encoders.Base64; 7 | 8 | /** 9 | * Value object for transaction PayloadData 10 | * 11 | * @author carlo_stanciu 12 | */ 13 | @Value 14 | public class PayloadData { 15 | 16 | byte[] buffer; 17 | 18 | private PayloadData(byte[] buffer) { 19 | this.buffer = buffer; 20 | } 21 | 22 | /** 23 | * Creates an PayloadData object from a data String 24 | * 25 | * @param value - data String value 26 | * @return - an instance of PayloadData 27 | */ 28 | public static PayloadData fromString(String value) { 29 | return new PayloadData(value.getBytes()); 30 | } 31 | 32 | /** 33 | * Creates an PayloadData object from a data encoded String 34 | * 35 | * @param encoded - data Base64 encoded String value 36 | * @return - an instance of PayloadData 37 | */ 38 | public static PayloadData fromBase64Encoded(String encoded) { 39 | return isNullOrEmpty(encoded) ? PayloadData.empty() : new PayloadData(Base64.decode(encoded)); 40 | } 41 | 42 | /** 43 | * Creates an empty PayloadData 44 | * 45 | * @return - an instance of PayloadData 46 | */ 47 | public static PayloadData empty() { 48 | return new PayloadData(new byte[]{}); 49 | } 50 | 51 | /** 52 | * Checks if PayloadData is empty 53 | * 54 | * @return - boolean 55 | */ 56 | public boolean isEmpty() { 57 | return length() == 0; 58 | } 59 | 60 | /** 61 | * Retrieves the length of the data 62 | * 63 | * @return - length of data buffer 64 | */ 65 | public int length() { 66 | return buffer.length; 67 | } 68 | 69 | /** 70 | * Retrieves the Base64 encoded data 71 | * 72 | * @return - data String Base64 encoded 73 | */ 74 | public String encoded() { 75 | return new String(Base64.encode(buffer)); 76 | } 77 | 78 | @Override 79 | public String toString() { 80 | return new String(buffer); 81 | } 82 | 83 | } 84 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/domain/transaction/Signable.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.transaction; 2 | 3 | import com.fasterxml.jackson.core.JsonProcessingException; 4 | 5 | /** 6 | * An Interface describing the behaviour of a signable component by an wallet 7 | */ 8 | public interface Signable { 9 | 10 | /** 11 | * Method used for serializing the object in a JSON buffer to be ready for signing by a wallet 12 | * 13 | * @return - JSON buffer 14 | * @throws - JsonProcessingException 15 | */ 16 | byte[] serializeForSigning() throws JsonProcessingException; 17 | 18 | /** 19 | * Method used for applying signature to Signable object 20 | * 21 | * @param signature - input for applying 22 | */ 23 | void applySignature(Signature signature); 24 | 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/domain/transaction/Signature.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.transaction; 2 | 3 | import io.ezalabs.multiversxspringbootstarterreactive.config.constants.TransactionConstants; 4 | import io.ezalabs.multiversxspringbootstarterreactive.error.exception.CannotCreateSignatureException; 5 | import io.ezalabs.multiversxspringbootstarterreactive.error.exception.SignatureEmptyException; 6 | import io.ezalabs.multiversxspringbootstarterreactive.util.HexValidator; 7 | import java.util.Arrays; 8 | import lombok.Value; 9 | import org.bouncycastle.util.encoders.Hex; 10 | 11 | /** 12 | * Value object for Signature 13 | * 14 | * @author carlo_stanciu 15 | */ 16 | @Value 17 | public class Signature { 18 | 19 | String hex; 20 | 21 | private Signature(String hex) { 22 | this.hex = hex; 23 | } 24 | 25 | /** 26 | * used for creating an Signature using a hex representation of an Signable object 27 | * 28 | * @param hexValue - hex value of Signable object buffer 29 | * @return - an instance of Signature 30 | */ 31 | public static Signature fromHex(String hexValue) { 32 | if (!HexValidator.isHexValid(hexValue, TransactionConstants.SIGNATURE_LENGTH_HEX)) { 33 | throw new CannotCreateSignatureException(hexValue); 34 | } 35 | 36 | return new Signature(hexValue); 37 | } 38 | 39 | /** 40 | * used for creating an Signature using a buffer representation of an Signable object 41 | * 42 | * @param buffer - buffer of Signable object buffer 43 | * @return - an instance of Signature 44 | */ 45 | public static Signature fromBuffer(byte[] buffer) { 46 | if (buffer.length != TransactionConstants.SIGNATURE_LENGTH) { 47 | throw new CannotCreateSignatureException(Arrays.toString(buffer)); 48 | } 49 | 50 | return new Signature(Hex.toHexString(buffer)); 51 | } 52 | 53 | /** 54 | * Creates an empty Signature 55 | * 56 | * @return - an instance of Signature 57 | */ 58 | public static Signature empty() { 59 | return new Signature(""); 60 | } 61 | 62 | /** 63 | * Getter Throws exception if empty 64 | * 65 | * @return - hex value of the Signature 66 | */ 67 | public String getHex() { 68 | if (isEmpty()) { 69 | throw new SignatureEmptyException(); 70 | } 71 | 72 | return hex; 73 | } 74 | 75 | /** 76 | * Checks if Signature is empty 77 | * 78 | * @return - boolean 79 | */ 80 | public boolean isEmpty() { 81 | return hex.isEmpty(); 82 | } 83 | 84 | 85 | } 86 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/domain/transaction/TransactionStatus.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.transaction; 2 | 3 | import io.ezalabs.multiversxspringbootstarterreactive.error.exception.InvalidTransactionStatusException; 4 | import java.util.Locale; 5 | import lombok.AllArgsConstructor; 6 | import lombok.Getter; 7 | 8 | /** 9 | * Enum representing Transaction status values 10 | * 11 | * @author carlo_stanciu 12 | */ 13 | @AllArgsConstructor 14 | @Getter 15 | public enum TransactionStatus { 16 | 17 | PENDING("pending"), 18 | SUCCESS("success"), 19 | FAIL("fail"), 20 | INVALID("invalid"), 21 | UNKNOWN("unknown"); 22 | 23 | private final String value; 24 | 25 | /** 26 | * Creates enum instance from String input 27 | * 28 | * @param value - String value of the status 29 | * @return - TransactionStatus instance 30 | */ 31 | public static TransactionStatus fromString(String value) { 32 | var status = value.toLowerCase(Locale.ROOT); 33 | 34 | switch (status) { 35 | case "pending": 36 | return TransactionStatus.PENDING; 37 | case "success": 38 | return TransactionStatus.SUCCESS; 39 | case "fail": 40 | return TransactionStatus.FAIL; 41 | case "invalid": 42 | return TransactionStatus.INVALID; 43 | default: 44 | throw new InvalidTransactionStatusException(status); 45 | } 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/domain/transaction/TransactionVersion.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.transaction; 2 | 3 | import io.ezalabs.multiversxspringbootstarterreactive.config.constants.TransactionConstants; 4 | import io.ezalabs.multiversxspringbootstarterreactive.error.exception.InvalidTransactionVersionException; 5 | import lombok.Value; 6 | 7 | /** 8 | * Value object for TransactionVersion 9 | * 10 | * @author carlo_stanciu 11 | */ 12 | @Value 13 | public class TransactionVersion { 14 | 15 | Integer value; 16 | 17 | private TransactionVersion(Integer value) { 18 | if (Integer.signum(value) == -1) { 19 | throw new InvalidTransactionVersionException(value); 20 | } 21 | 22 | this.value = value; 23 | } 24 | 25 | /** 26 | * Creates an TransactionVersion object from a number value 27 | * 28 | * @param value - value in Integer format 29 | * @return an instance of TransactionVersion 30 | */ 31 | public static TransactionVersion fromInteger(Integer value) { 32 | return new TransactionVersion(value); 33 | } 34 | 35 | /** 36 | * Create an TransactionVersion object with default version 37 | * 38 | * @return an instance of TransactionVersion 39 | */ 40 | public static TransactionVersion withDefaultVersion() { 41 | return new TransactionVersion(TransactionConstants.TRANSACTION_VERSION_DEFAULT); 42 | } 43 | 44 | /** 45 | * Create an TransactionVersion object with transaction hash sign version 46 | * 47 | * @return an instance of TransactionVersion 48 | */ 49 | public static TransactionVersion withTransactionHashSignVersion() { 50 | return new TransactionVersion(TransactionConstants.TRANSACTION_VERSION_TX_HASH_SIGN); 51 | } 52 | 53 | @Override 54 | public String toString() { 55 | return value.toString(); 56 | } 57 | 58 | } 59 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/error/exception/CannotConvertBitsException.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.error.exception; 2 | 3 | import io.ezalabs.multiversxspringbootstarterreactive.error.ErrorMessage; 4 | 5 | public class CannotConvertBitsException extends RuntimeException { 6 | 7 | public CannotConvertBitsException() { 8 | super(ErrorMessage.CANNOT_CONVERT_BITS.getValue()); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/error/exception/CannotCreateAddressException.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.error.exception; 2 | 3 | import io.ezalabs.multiversxspringbootstarterreactive.error.ErrorMessage; 4 | 5 | public class CannotCreateAddressException extends RuntimeException { 6 | 7 | public CannotCreateAddressException(byte[] value) { 8 | super(String.format(ErrorMessage.CANNOT_CREATE_ADDRESS.getValue(), value)); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/error/exception/CannotCreateSignatureException.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.error.exception; 2 | 3 | import io.ezalabs.multiversxspringbootstarterreactive.error.ErrorMessage; 4 | 5 | public class CannotCreateSignatureException extends RuntimeException { 6 | 7 | public CannotCreateSignatureException(String value) { 8 | super(String.format(ErrorMessage.CANNOT_CREATE_SIGNATURE.getValue(), value)); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/error/exception/CannotDecodeBech32AddressException.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.error.exception; 2 | 3 | import io.ezalabs.multiversxspringbootstarterreactive.error.ErrorMessage; 4 | 5 | public class CannotDecodeBech32AddressException extends RuntimeException { 6 | 7 | public CannotDecodeBech32AddressException() { 8 | super(ErrorMessage.CANNOT_DECODE_BECH32_ADDRESS.getValue()); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/error/exception/CannotDeriveKeysException.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.error.exception; 2 | 3 | import io.ezalabs.multiversxspringbootstarterreactive.error.ErrorMessage; 4 | 5 | public class CannotDeriveKeysException extends RuntimeException { 6 | 7 | public CannotDeriveKeysException() { 8 | super(ErrorMessage.CANNOT_DERIVE_KEYS.getValue()); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/error/exception/CannotGenerateMnemonicException.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.error.exception; 2 | 3 | import io.ezalabs.multiversxspringbootstarterreactive.error.ErrorMessage; 4 | 5 | public class CannotGenerateMnemonicException extends RuntimeException { 6 | 7 | public CannotGenerateMnemonicException() { 8 | super(ErrorMessage.CANNOT_GENERATE_MNEMONIC.getValue()); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/error/exception/CannotSignTransactionException.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.error.exception; 2 | 3 | import io.ezalabs.multiversxspringbootstarterreactive.error.ErrorMessage; 4 | 5 | public class CannotSignTransactionException extends RuntimeException { 6 | 7 | public CannotSignTransactionException(Throwable e) { 8 | super(String.format(ErrorMessage.CANNOT_SIGN_TRANSACTION.getValue(), e.getMessage())); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/error/exception/DeserializationException.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.error.exception; 2 | 3 | public class DeserializationException extends RuntimeException { 4 | 5 | public DeserializationException(String message) { 6 | super(message); 7 | } 8 | 9 | } 10 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/error/exception/EmptyPayloadException.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.error.exception; 2 | 3 | import io.ezalabs.multiversxspringbootstarterreactive.error.ErrorMessage; 4 | 5 | public class EmptyPayloadException extends RuntimeException { 6 | 7 | public EmptyPayloadException() { 8 | super(ErrorMessage.PAYLOAD.getValue()); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/error/exception/GatewayException.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.error.exception; 2 | 3 | import io.ezalabs.multiversxspringbootstarterreactive.error.ErrorMessage; 4 | 5 | public class GatewayException extends RuntimeException { 6 | 7 | public GatewayException() { 8 | super(ErrorMessage.INVALID_GATEWAY.getValue()); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/error/exception/InvalidBalanceException.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.error.exception; 2 | 3 | import java.math.BigInteger; 4 | import io.ezalabs.multiversxspringbootstarterreactive.error.ErrorMessage; 5 | 6 | public class InvalidBalanceException extends RuntimeException { 7 | 8 | public InvalidBalanceException(BigInteger balance) { 9 | super(String.format(ErrorMessage.INVALID_BALANCE.getValue(), balance)); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/error/exception/InvalidChainIdException.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.error.exception; 2 | 3 | import io.ezalabs.multiversxspringbootstarterreactive.error.ErrorMessage; 4 | 5 | public class InvalidChainIdException extends RuntimeException { 6 | 7 | public InvalidChainIdException(String chainId) { 8 | super(String.format(ErrorMessage.INVALID_CHAIN_ID.getValue(), chainId)); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/error/exception/InvalidHexValueException.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.error.exception; 2 | 3 | import io.ezalabs.multiversxspringbootstarterreactive.error.ErrorMessage; 4 | 5 | public class InvalidHexValueException extends RuntimeException { 6 | 7 | public InvalidHexValueException(String value) { 8 | super(String.format(ErrorMessage.INVALID_HEX_VALUE.getValue(), value)); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/error/exception/InvalidNonceException.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.error.exception; 2 | 3 | import io.ezalabs.multiversxspringbootstarterreactive.error.ErrorMessage; 4 | 5 | public class InvalidNonceException extends RuntimeException { 6 | 7 | public InvalidNonceException(long nonce) { 8 | super(String.format(ErrorMessage.INVALID_NONCE.getValue(), nonce)); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/error/exception/InvalidPemFileException.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.error.exception; 2 | 3 | import static java.lang.String.format; 4 | 5 | import io.ezalabs.multiversxspringbootstarterreactive.error.ErrorMessage; 6 | 7 | public class InvalidPemFileException extends RuntimeException { 8 | 9 | public InvalidPemFileException(Throwable t) { 10 | super(format(ErrorMessage.INVALID_PEM_FILE.getValue(), t.getMessage())); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/error/exception/InvalidProxyUrlException.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.error.exception; 2 | 3 | import io.ezalabs.multiversxspringbootstarterreactive.error.ErrorMessage; 4 | 5 | public class InvalidProxyUrlException extends RuntimeException { 6 | 7 | public InvalidProxyUrlException(String url) { 8 | super(ErrorMessage.INVALID_PROXY_URL.getValue().formatted(url)); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/error/exception/InvalidSentTransactionsException.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.error.exception; 2 | 3 | import io.ezalabs.multiversxspringbootstarterreactive.error.ErrorMessage; 4 | 5 | public class InvalidSentTransactionsException extends RuntimeException { 6 | 7 | public InvalidSentTransactionsException() { 8 | super(ErrorMessage.INVALID_SENT_TRANSACTIONS.getValue()); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/error/exception/InvalidTransactionStatusException.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.error.exception; 2 | 3 | import io.ezalabs.multiversxspringbootstarterreactive.error.ErrorMessage; 4 | 5 | public class InvalidTransactionStatusException extends RuntimeException { 6 | 7 | public InvalidTransactionStatusException(String status) { 8 | super(String.format(ErrorMessage.INVALID_BALANCE.getValue(), status)); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/error/exception/InvalidTransactionVersionException.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.error.exception; 2 | 3 | import io.ezalabs.multiversxspringbootstarterreactive.error.ErrorMessage; 4 | 5 | public class InvalidTransactionVersionException extends RuntimeException { 6 | 7 | public InvalidTransactionVersionException(int transactionId) { 8 | super(String.format(ErrorMessage.INVALID_TRANSACTION_VERSION.getValue(), transactionId)); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/error/exception/MissingTransactionRequestException.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.error.exception; 2 | 3 | import io.ezalabs.multiversxspringbootstarterreactive.error.ErrorMessage; 4 | 5 | public class MissingTransactionRequestException extends RuntimeException { 6 | 7 | public MissingTransactionRequestException() { 8 | super(ErrorMessage.MISSING_TRANSACTIONS_REQUESTS.getValue()); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/error/exception/NegativeGasException.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.error.exception; 2 | 3 | import java.math.BigInteger; 4 | import io.ezalabs.multiversxspringbootstarterreactive.error.ErrorMessage; 5 | 6 | public class NegativeGasException extends RuntimeException { 7 | 8 | public NegativeGasException(BigInteger gasLimit) { 9 | super(String.format(ErrorMessage.NEGATIVE_GAS.getValue(), gasLimit)); 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/error/exception/PrivateKeyHexSizeException.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.error.exception; 2 | 3 | import io.ezalabs.multiversxspringbootstarterreactive.error.ErrorMessage; 4 | 5 | public class PrivateKeyHexSizeException extends RuntimeException { 6 | 7 | public PrivateKeyHexSizeException(int size) { 8 | super(String.format(ErrorMessage.PRIVATE_KEY_LENGTH.getValue(), size)); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/error/exception/ProxyRequestException.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.error.exception; 2 | 3 | public class ProxyRequestException extends RuntimeException { 4 | 5 | public ProxyRequestException(String errorMessage) { 6 | super(errorMessage); 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/error/exception/ResponseException.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.error.exception; 2 | 3 | import io.ezalabs.multiversxspringbootstarterreactive.error.ErrorMessage; 4 | 5 | public class ResponseException extends RuntimeException { 6 | 7 | public ResponseException(String error) { 8 | super(error); 9 | } 10 | 11 | public ResponseException() { 12 | super(ErrorMessage.RESPONSE_NOT_SUCCESSFUL.getValue()); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/error/exception/SignatureEmptyException.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.error.exception; 2 | 3 | import io.ezalabs.multiversxspringbootstarterreactive.error.ErrorMessage; 4 | 5 | public class SignatureEmptyException extends RuntimeException { 6 | 7 | public SignatureEmptyException() { 8 | super(ErrorMessage.SIGNATURE_EMPTY.getValue()); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/error/exception/WrongNetworkAddressException.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.error.exception; 2 | 3 | import io.ezalabs.multiversxspringbootstarterreactive.error.ErrorMessage; 4 | 5 | public class WrongNetworkAddressException extends RuntimeException { 6 | 7 | public WrongNetworkAddressException(String hrp) { 8 | super(String.format(ErrorMessage.WRONG_NETWORK_ADDRESS.getValue(), hrp)); 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/interactor/account/MxAccountInteractor.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.interactor.account; 2 | 3 | import io.ezalabs.multiversxspringbootstarterreactive.api.model.AccountBalance; 4 | import io.ezalabs.multiversxspringbootstarterreactive.api.model.AccountNonce; 5 | import io.ezalabs.multiversxspringbootstarterreactive.api.model.AccountOnNetwork; 6 | import io.ezalabs.multiversxspringbootstarterreactive.api.model.AccountStorageValue; 7 | import io.ezalabs.multiversxspringbootstarterreactive.api.model.TransactionForAddress; 8 | import java.util.List; 9 | import java.util.Map; 10 | import reactor.core.publisher.Mono; 11 | import io.ezalabs.multiversxspringbootstarterreactive.domain.account.Address; 12 | 13 | /** 14 | * Interface used for interaction with Account on the network 15 | * 16 | * @author carlo_stanciu 17 | */ 18 | public interface MxAccountInteractor { 19 | 20 | /** 21 | * Method used to query an Account's information 22 | * 23 | * @param address - Address input 24 | * @return - AccountOnNetwork API response 25 | */ 26 | Mono getAccountInfo(Address address); 27 | 28 | /** 29 | * Method used to query the balance of an Account 30 | * 31 | * @param address - Address input 32 | * @return - AddressBalance API response 33 | */ 34 | Mono getBalance(Address address); 35 | 36 | /** 37 | * Method used to query the nonce of an Account 38 | * 39 | * @param address - Address input 40 | * @return - AddressNonce API response 41 | */ 42 | Mono getNonce(Address address); 43 | 44 | /** 45 | * Method used to query the list of transactions for an Account 46 | * 47 | * @param address - Address input 48 | * @return - TransactionForAddress API response 49 | */ 50 | Mono> getTransactions(Address address); 51 | 52 | /** 53 | * Method used to query a storage value of an Account 54 | * 55 | * @param address - Address input 56 | * @param key - String key of the value 57 | * @return - AddressStorageValue API Response 58 | */ 59 | Mono getStorageValue(Address address, String key); 60 | 61 | /** 62 | * Method used to query all the storage of an Account 63 | * 64 | * @param address - Address input 65 | * @return - storage as a Map of String keys and String values 66 | */ 67 | Mono> getStorage(Address address); 68 | 69 | 70 | } 71 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/interactor/block/MxBlockInteractor.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.interactor.block; 2 | 3 | import io.ezalabs.multiversxspringbootstarterreactive.api.model.Hyperblock; 4 | import io.ezalabs.multiversxspringbootstarterreactive.api.model.ShardBlock; 5 | import reactor.core.publisher.Mono; 6 | 7 | /** 8 | * Interface used for interaction with hyperblocks / shard blocks on the network 9 | * 10 | * @author carlo_stanciu 11 | */ 12 | public interface MxBlockInteractor { 13 | 14 | /** 15 | * Method used to query Hyperblock information by nonce 16 | * 17 | * @param nonce - value used as query parameter 18 | * @return - Hyperblock API response 19 | */ 20 | Mono queryHyperblockByNonce(Long nonce); 21 | 22 | /** 23 | * Method used to query Hyperblock information by hash 24 | * 25 | * @param hash - value used as query parameter 26 | * @return - Hyperblock API response 27 | */ 28 | Mono queryHyperblockByHash(String hash); 29 | 30 | /** 31 | * Method used to query ShardBlock information by shard and nonce 32 | * 33 | * @param shard - value used as query parameter 34 | * @param nonce - value used as query parameter 35 | * @return - ShardBlock API response 36 | */ 37 | Mono queryShardBlockByNonceFromShard(Integer shard, Long nonce); 38 | 39 | /** 40 | * Method used to query ShardBlock information by shard and hash 41 | * 42 | * @param shard - value used as query parameter 43 | * @param hash - value used as query parameter 44 | * @return - ShardBlock API response 45 | */ 46 | Mono queryShardBlockByHashFromShard(Integer shard, String hash); 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/interactor/block/MxBlockInteractorImpl.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.interactor.block; 2 | 3 | import static java.lang.String.format; 4 | 5 | import io.ezalabs.multiversxspringbootstarterreactive.api.ApiResourceURI; 6 | import io.ezalabs.multiversxspringbootstarterreactive.api.model.Hyperblock; 7 | import io.ezalabs.multiversxspringbootstarterreactive.api.model.ShardBlock; 8 | import io.ezalabs.multiversxspringbootstarterreactive.client.MxProxyClient; 9 | import lombok.AllArgsConstructor; 10 | import reactor.core.publisher.Mono; 11 | import io.ezalabs.multiversxspringbootstarterreactive.interactor.WrappedResponses; 12 | 13 | @AllArgsConstructor 14 | public class MxBlockInteractorImpl implements MxBlockInteractor { 15 | 16 | private final MxProxyClient client; 17 | 18 | @Override 19 | public Mono queryHyperblockByNonce(Long nonce) { 20 | return client 21 | .get(String.format(ApiResourceURI.HYPERBLOCK_BY_NONCE.getURI(), nonce), 22 | WrappedResponses.QueryHyperblock.class) 23 | .map(WrappedResponses.QueryHyperblock::getHyperblock); 24 | } 25 | 26 | @Override 27 | public Mono queryHyperblockByHash(String hash) { 28 | return client 29 | .get(format(ApiResourceURI.HYPERBLOCK_BY_HASH.getURI(), hash), 30 | WrappedResponses.QueryHyperblock.class) 31 | .map(WrappedResponses.QueryHyperblock::getHyperblock); 32 | } 33 | 34 | @Override 35 | public Mono queryShardBlockByNonceFromShard(Integer shard, Long nonce) { 36 | return client 37 | .get(format(ApiResourceURI.BLOCK_BY_NONCE_FROM_SHARD.getURI(), shard, nonce), 38 | WrappedResponses.QueryBlock.class) 39 | .map(WrappedResponses.QueryBlock::getBlock); 40 | } 41 | 42 | @Override 43 | public Mono queryShardBlockByHashFromShard(Integer shard, String hash) { 44 | return client 45 | .get(format(ApiResourceURI.BLOCK_BY_HASH_FROM_SHARD.getURI(), shard, hash), 46 | WrappedResponses.QueryBlock.class) 47 | .map(WrappedResponses.QueryBlock::getBlock); 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/interactor/network/MxNetworkInteractor.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.interactor.network; 2 | 3 | import io.ezalabs.multiversxspringbootstarterreactive.api.model.NetworkConfig; 4 | import io.ezalabs.multiversxspringbootstarterreactive.api.model.NodeHeartbeatStatus; 5 | import io.ezalabs.multiversxspringbootstarterreactive.api.model.ShardStatus; 6 | import java.util.List; 7 | import reactor.core.publisher.Mono; 8 | 9 | /** 10 | * Interface used for interaction with network configuration 11 | * 12 | * @author carlo_stanciu 13 | */ 14 | public interface MxNetworkInteractor { 15 | 16 | /** 17 | * Method used to query network configuration 18 | * 19 | * @return - NetworkConfig API response 20 | */ 21 | Mono getNetworkConfig(); 22 | 23 | /** 24 | * Method used to query a shard's status based on id 25 | * 26 | * @param shardId - value used as search id 27 | * @return - ShardStatus API response 28 | */ 29 | Mono getShardStatus(String shardId); 30 | 31 | /** 32 | * Method used to query a node's heartbeat status 33 | * 34 | * @return - list of NodeHeartbeatStatus API response 35 | */ 36 | Mono> getNodeHeartbeatStatus(); 37 | 38 | } 39 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/interactor/network/MxNetworkInteractorImpl.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.interactor.network; 2 | 3 | import static java.lang.String.format; 4 | 5 | import io.ezalabs.multiversxspringbootstarterreactive.api.ApiResourceURI; 6 | import io.ezalabs.multiversxspringbootstarterreactive.api.model.NetworkConfig; 7 | import io.ezalabs.multiversxspringbootstarterreactive.api.model.NodeHeartbeatStatus; 8 | import io.ezalabs.multiversxspringbootstarterreactive.api.model.ShardStatus; 9 | import io.ezalabs.multiversxspringbootstarterreactive.client.MxProxyClient; 10 | import java.util.List; 11 | import lombok.AllArgsConstructor; 12 | import lombok.extern.slf4j.Slf4j; 13 | import reactor.core.publisher.Mono; 14 | import io.ezalabs.multiversxspringbootstarterreactive.interactor.WrappedResponses; 15 | 16 | @AllArgsConstructor 17 | @Slf4j 18 | public class MxNetworkInteractorImpl implements MxNetworkInteractor { 19 | 20 | private final MxProxyClient client; 21 | 22 | @Override 23 | public Mono getNetworkConfig() { 24 | return client 25 | .get(ApiResourceURI.NETWORK_CONFIG.getURI(), 26 | WrappedResponses.GetNetworkConfigResponse.class) 27 | .map(WrappedResponses.GetNetworkConfigResponse::getNetworkConfig); 28 | } 29 | 30 | @Override 31 | public Mono getShardStatus(String shardId) { 32 | return client 33 | .get(format(ApiResourceURI.SHARD_STATUS.getURI(), shardId), 34 | WrappedResponses.GetShardStatusResponse.class) 35 | .map(WrappedResponses.GetShardStatusResponse::getShardStatus); 36 | } 37 | 38 | @Override 39 | public Mono> getNodeHeartbeatStatus() { 40 | return client 41 | .get(ApiResourceURI.NODE_HEARTBEAT_STATUS.getURI(), 42 | WrappedResponses.GetNodeHeartbeatStatusResponse.class) 43 | .map(WrappedResponses.GetNodeHeartbeatStatusResponse::getHeartbeatstatus); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/interactor/smartcontract/MxSmartContractInteractor.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.interactor.smartcontract; 2 | 3 | import io.ezalabs.multiversxspringbootstarterreactive.api.model.ContractQueryResult; 4 | import io.ezalabs.multiversxspringbootstarterreactive.api.model.ContractQueryResultHex; 5 | import io.ezalabs.multiversxspringbootstarterreactive.api.model.ContractQueryResultInt; 6 | import io.ezalabs.multiversxspringbootstarterreactive.api.model.ContractQueryResultString; 7 | import io.ezalabs.multiversxspringbootstarterreactive.api.model.TransactionHash; 8 | import reactor.core.publisher.Mono; 9 | import io.ezalabs.multiversxspringbootstarterreactive.domain.smartcontract.ContractFunction; 10 | import io.ezalabs.multiversxspringbootstarterreactive.domain.smartcontract.ContractQuery; 11 | import io.ezalabs.multiversxspringbootstarterreactive.domain.wallet.Wallet; 12 | 13 | /** 14 | * Interface used for interaction with smart contracts on the network 15 | * 16 | * @author carlo_stanciu 17 | */ 18 | public interface MxSmartContractInteractor { 19 | 20 | /** 21 | * Method used to call a smart contract function 22 | * 23 | * @param wallet - transaction caller's Wallet instance 24 | * @param function - smart contract function object 25 | * @return - TransactionHash API response 26 | */ 27 | Mono callFunction(Wallet wallet, ContractFunction function); 28 | 29 | /** 30 | * Method used to query smart contract 31 | * 32 | * @param query - smart contract query function object 33 | * @return - ScQueryResult API response 34 | */ 35 | Mono query(ContractQuery query); 36 | 37 | /** 38 | * Method used to query smart contract for hex value 39 | * 40 | * @param query - smart contract query function object 41 | * @return - ScQueryResultHex API response 42 | */ 43 | Mono queryHex(ContractQuery query); 44 | 45 | /** 46 | * Method used to query smart contract for String value 47 | * 48 | * @param query - smart contract query function object 49 | * @return - ScQueryResultString API response 50 | */ 51 | Mono queryString(ContractQuery query); 52 | 53 | /** 54 | * Method used to query smart contract for integer value 55 | * 56 | * @param query - smart contract query function object 57 | * @return - ScQueryResultInt API response 58 | */ 59 | Mono queryInt(ContractQuery query); 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/interactor/transaction/TransactionRequest.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.interactor.transaction; 2 | 3 | import lombok.Builder; 4 | import lombok.NonNull; 5 | import lombok.Value; 6 | import io.ezalabs.multiversxspringbootstarterreactive.domain.account.Address; 7 | import io.ezalabs.multiversxspringbootstarterreactive.domain.common.Balance; 8 | import io.ezalabs.multiversxspringbootstarterreactive.domain.transaction.GasLimit; 9 | import io.ezalabs.multiversxspringbootstarterreactive.domain.transaction.PayloadData; 10 | 11 | /** 12 | * Object used as a payload in the TransactionSender's methods 13 | * 14 | * @author carlo_stanciu 15 | */ 16 | @Builder 17 | @Value 18 | public class TransactionRequest { 19 | 20 | @NonNull 21 | Address receiverAddress; 22 | @NonNull 23 | Balance value; 24 | @NonNull 25 | PayloadData data; 26 | @NonNull 27 | @Builder.Default 28 | GasLimit gasLimit = GasLimit.zero(); 29 | 30 | } 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/properties/MxClientProperties.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.properties; 2 | 3 | import io.ezalabs.multiversxspringbootstarterreactive.error.exception.GatewayException; 4 | import java.util.Locale; 5 | import lombok.Data; 6 | import org.springframework.boot.context.properties.ConfigurationProperties; 7 | 8 | /** 9 | * Configuration class for spring properties mapping 10 | * 11 | * @author carlo_stanciu 12 | */ 13 | @Data 14 | @ConfigurationProperties(prefix = "spring.multiversx.client") 15 | public class MxClientProperties { 16 | 17 | private String proxyUrl; 18 | private long readTimeoutMillis = 10_000L; 19 | private long writeTimeoutMillis = 10_000L; 20 | 21 | { 22 | setGateway("devnet"); 23 | } 24 | 25 | public void setGateway(String gateway) { 26 | var gatewayValue = switch (gateway.toLowerCase(Locale.ROOT).strip()) { 27 | case "devnet" -> "devnet-gateway"; 28 | case "testnet" -> "testnet-gateway"; 29 | case "mainnet" -> "gateway"; 30 | default -> throw new GatewayException(); 31 | }; 32 | 33 | this.proxyUrl = "https://%s.multiversx.com".formatted(gatewayValue); 34 | } 35 | 36 | public void setCustomProxyUrl(String customProxyUrl) { 37 | this.proxyUrl = customProxyUrl; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/util/BitsConverter.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.util; 2 | 3 | import io.ezalabs.multiversxspringbootstarterreactive.error.exception.CannotConvertBitsException; 4 | import java.io.ByteArrayOutputStream; 5 | 6 | /** 7 | * author MultiversX Network - mx-sdk-erdjava 8 | */ 9 | public class BitsConverter { 10 | 11 | public static byte[] convertBits(byte[] data, int fromBits, int toBits, boolean pad) { 12 | int acc = 0; 13 | int bits = 0; 14 | var ret = new ByteArrayOutputStream(); 15 | int maxv = (1 << toBits) - 1; 16 | int maxAcc = (1 << (fromBits + toBits - 1)) - 1; 17 | 18 | for (byte value : data) { 19 | var valueAsInt = value & 0xff; 20 | 21 | if (valueAsInt >>> fromBits != 0) { 22 | throw new CannotConvertBitsException(); 23 | } 24 | 25 | acc = ((acc << fromBits) | valueAsInt) & maxAcc; 26 | bits += fromBits; 27 | 28 | while (bits >= toBits) { 29 | bits -= toBits; 30 | ret.write((acc >>> bits) & maxv); 31 | } 32 | } 33 | 34 | if (pad) { 35 | if (bits > 0) { 36 | ret.write((acc << (toBits - bits)) & maxv); 37 | } 38 | } else if (bits >= fromBits || ((acc << (toBits - bits)) & maxv) != 0) { 39 | throw new CannotConvertBitsException(); 40 | } 41 | 42 | return ret.toByteArray(); 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/util/GasUtils.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.util; 2 | 3 | import io.ezalabs.multiversxspringbootstarterreactive.config.MxNetworkConfigSupplier; 4 | import java.math.BigInteger; 5 | import io.ezalabs.multiversxspringbootstarterreactive.domain.transaction.PayloadData; 6 | 7 | /** 8 | * Utility class for Gas 9 | * 10 | * @author carlo_stanciu 11 | */ 12 | public class GasUtils { 13 | 14 | /** 15 | * Method used for computing gas cost of a Transaction based on payload data 16 | * 17 | * @param data - data to process 18 | * @return - gas cost in BigInteger format 19 | */ 20 | public static BigInteger computeGasCost(PayloadData data) { 21 | return MxNetworkConfigSupplier.config.getMinGasLimit() 22 | .add(BigInteger.valueOf(data.length()) 23 | .multiply(BigInteger.valueOf(MxNetworkConfigSupplier.config.getGasPerDataByte()))); 24 | } 25 | 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/util/HexValidator.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.util; 2 | 3 | import org.bouncycastle.util.encoders.Hex; 4 | 5 | /** 6 | * Utility class for HEX validation 7 | * 8 | * @author carlo_stanciu 9 | */ 10 | public class HexValidator { 11 | 12 | /** 13 | * Method used for verifying if a HEX String is valid 14 | * 15 | * @param hexValue - HEX value in String format 16 | * @param requiredLength - length condition 17 | * @return - true if valid, false if not 18 | */ 19 | public static boolean isHexValid(String hexValue, Integer requiredLength) { 20 | try { 21 | Hex.decode(hexValue); 22 | return hexValue.length() == requiredLength; 23 | } catch (Exception e) { 24 | return false; 25 | } 26 | } 27 | 28 | /** 29 | * Method used for processing hex number arguments for transactions 30 | * 31 | * @param hex - HEX value in String format 32 | * @return - HEX value with even nr of chars 33 | */ 34 | public static String processNumberHexArgument(String hex) { 35 | if (!(hex.length() % 2 == 0)) { 36 | return "0" + hex; 37 | } 38 | 39 | return hex; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/main/java/io/ezalabs/multiversxspringbootstarterreactive/util/PemUtils.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.util; 2 | 3 | import io.ezalabs.multiversxspringbootstarterreactive.error.exception.InvalidPemFileException; 4 | import java.io.File; 5 | import java.io.FileReader; 6 | import java.io.InputStreamReader; 7 | import java.io.Reader; 8 | import java.util.Base64; 9 | import org.bouncycastle.util.io.pem.PemObject; 10 | import org.bouncycastle.util.io.pem.PemReader; 11 | import org.springframework.core.io.buffer.DataBuffer; 12 | import org.springframework.http.codec.multipart.FilePart; 13 | import reactor.core.publisher.Mono; 14 | 15 | /** 16 | * Utility class used for processing PEM files 17 | * 18 | * @author carlo_stanciu 19 | */ 20 | public class PemUtils { 21 | 22 | /** 23 | * Method used for extracting the private key in hex format from a PEM file 24 | * 25 | * @param pem - target PEM file (in File format) 26 | * @return - private key hex in String format 27 | */ 28 | public static String extractKeyHex(File pem) { 29 | try { 30 | return processPem(new FileReader(pem)); 31 | } catch (Exception e) { 32 | throw new InvalidPemFileException(e); 33 | } 34 | } 35 | 36 | /** 37 | * Method used for extracting the private key in hex format from a PEM file Used in reactive steam input 38 | * 39 | * @param pem - target PEM file (in FilePart format) 40 | * @return - private key hex in String format 41 | */ 42 | public static Mono extractKeyHex(FilePart pem) { 43 | return pem.content() 44 | .map(DataBuffer::asInputStream) 45 | .next() 46 | .map(is -> processPem(new InputStreamReader(is))); 47 | } 48 | 49 | private static String processPem(Reader reader) { 50 | PemObject pemObject; 51 | try { 52 | pemObject = new PemReader(reader).readPemObject(); 53 | var keyBase64 = Base64.getEncoder().encodeToString(pemObject.getContent()); 54 | var privateKeyBase64 = keyBase64.substring(0, keyBase64.length() / 2); 55 | 56 | return new String(Base64.getDecoder().decode(privateKeyBase64)); 57 | } catch (Exception e) { 58 | throw new InvalidPemFileException(e); 59 | } 60 | } 61 | 62 | 63 | } 64 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/spring.factories: -------------------------------------------------------------------------------- 1 | org.springframework.boot.autoconfigure.EnableAutoConfiguration=\ 2 | io.ezalabs.multiversxspringbootstarterreactive.MxClientAutoConfiguration,\ 3 | io.ezalabs.multiversxspringbootstarterreactive.config.MxNetworkConfigSupplier,\ 4 | io.ezalabs.multiversxspringbootstarterreactive.MxInteractorAutoConfiguration -------------------------------------------------------------------------------- /src/test/java/io/ezalabs/multiversxspringbootstarterreactive/api/ApiResponseTest.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.api; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | import static org.junit.jupiter.api.Assertions.assertThrows; 5 | 6 | import io.ezalabs.multiversxspringbootstarterreactive.error.ErrorMessage; 7 | import io.ezalabs.multiversxspringbootstarterreactive.error.exception.ResponseException; 8 | import org.junit.jupiter.api.Assertions; 9 | import org.junit.jupiter.api.Test; 10 | 11 | class ApiResponseTest { 12 | 13 | @Test 14 | void throwIfError() { 15 | var apiResponse = new ApiResponse<>(); 16 | var expectedErrMsg = "failed for some reason"; 17 | apiResponse.setError(expectedErrMsg); 18 | 19 | var ex = assertThrows(ResponseException.class, apiResponse::throwIfError); 20 | assertEquals(expectedErrMsg, ex.getMessage()); 21 | 22 | apiResponse.setError(""); 23 | apiResponse.setCode("notSuccessful"); 24 | 25 | var ex2 = assertThrows(ResponseException.class, apiResponse::throwIfError); 26 | Assertions.assertEquals(ErrorMessage.RESPONSE_NOT_SUCCESSFUL.getValue(), ex2.getMessage()); 27 | } 28 | } -------------------------------------------------------------------------------- /src/test/java/io/ezalabs/multiversxspringbootstarterreactive/domain/account/AddressTest.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.account; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertArrayEquals; 4 | import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; 5 | import static org.junit.jupiter.api.Assertions.assertEquals; 6 | import static org.junit.jupiter.api.Assertions.assertThrows; 7 | 8 | import io.ezalabs.multiversxspringbootstarterreactive.config.constants.AddressConstants; 9 | import io.ezalabs.multiversxspringbootstarterreactive.error.exception.CannotDecodeBech32AddressException; 10 | import io.ezalabs.multiversxspringbootstarterreactive.error.exception.InvalidHexValueException; 11 | import org.bouncycastle.util.encoders.Hex; 12 | import org.junit.jupiter.api.Assertions; 13 | import org.junit.jupiter.api.Test; 14 | 15 | class AddressTest { 16 | 17 | String hexPublicKey = "bf86ad970aa3c93c2382889c0a4fba4728b5b851634d57ccd65dcddeda8c8bb0"; 18 | String bech32 = "erd1h7r2m9c250yncguz3zwq5na6gu5ttwz3vdx40nxkthxaak5v3wcqtpkvkj"; 19 | 20 | @Test 21 | void fromHex() { 22 | Assertions.assertDoesNotThrow(() -> Address.fromHex(hexPublicKey)); 23 | assertThrows(InvalidHexValueException.class, () -> Address.fromHex(hexPublicKey.concat("1234"))); 24 | } 25 | 26 | @Test 27 | void fromBech32() { 28 | Assertions.assertDoesNotThrow(() -> Address.fromBech32(bech32)); 29 | assertThrows(CannotDecodeBech32AddressException.class, () -> Address.fromBech32(bech32.concat("123"))); 30 | } 31 | 32 | @Test 33 | void hex() { 34 | var address = Address.fromBech32(bech32); 35 | assertEquals(hexPublicKey, address.getHex()); 36 | } 37 | 38 | @Test 39 | void publicKey() { 40 | var address = Address.fromBech32(bech32); 41 | assertArrayEquals(Hex.decode(hexPublicKey), address.getPublicKey()); 42 | } 43 | 44 | @Test 45 | void bech32() { 46 | var address = Address.fromHex(hexPublicKey); 47 | assertEquals(bech32, address.getBech32()); 48 | } 49 | 50 | @Test 51 | void zero() { 52 | assertEquals(AddressConstants.ZERO_PUBKEY_STRING, Address.zero().getHex()); 53 | } 54 | } -------------------------------------------------------------------------------- /src/test/java/io/ezalabs/multiversxspringbootstarterreactive/domain/common/BalanceTest.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.common; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; 4 | import static org.junit.jupiter.api.Assertions.assertEquals; 5 | import static org.junit.jupiter.api.Assertions.assertFalse; 6 | import static org.junit.jupiter.api.Assertions.assertThrows; 7 | import static org.junit.jupiter.api.Assertions.assertTrue; 8 | 9 | import io.ezalabs.multiversxspringbootstarterreactive.config.constants.CurrencyConstants; 10 | import io.ezalabs.multiversxspringbootstarterreactive.error.exception.InvalidBalanceException; 11 | import java.math.BigInteger; 12 | import org.junit.jupiter.api.Assertions; 13 | import org.junit.jupiter.api.Test; 14 | 15 | class BalanceTest { 16 | 17 | String oneEgldString = CurrencyConstants.ONE_EGLD_STRING; 18 | 19 | @Test 20 | void fromEgld() { 21 | var expected = oneEgldString; 22 | var balance = Balance.fromEgld(1.00); 23 | 24 | assertEquals(new BigInteger(expected), balance.getValue()); 25 | assertEquals(expected, balance.toString()); 26 | 27 | var expectedWithDecimal = "1120500000000000000"; 28 | var balanceWithDecimal = Balance.fromEgld(1.1205); 29 | 30 | assertEquals(new BigInteger(expectedWithDecimal), balanceWithDecimal.getValue()); 31 | assertEquals(expectedWithDecimal, balanceWithDecimal.toString()); 32 | } 33 | 34 | @Test 35 | void fromString_positive() { 36 | Assertions.assertDoesNotThrow(() -> Balance.fromString((oneEgldString))); 37 | } 38 | 39 | @Test 40 | void fromString_negative() { 41 | assertThrows(InvalidBalanceException.class, () -> Balance.fromString(("-".concat(oneEgldString)))); 42 | } 43 | 44 | @Test 45 | void fromNumber() { 46 | Assertions.assertDoesNotThrow(() -> Balance.fromNumber(new BigInteger(oneEgldString))); 47 | } 48 | 49 | @Test 50 | void zero() { 51 | assertEquals(BigInteger.ZERO, Balance.zero().getValue()); 52 | } 53 | 54 | @Test 55 | void isZero() { 56 | assertTrue(Balance.zero().isZero()); 57 | assertFalse(Balance.fromString(oneEgldString).isZero()); 58 | } 59 | 60 | @Test 61 | void isSet() { 62 | assertFalse(Balance.zero().isSet()); 63 | assertTrue(Balance.fromString(oneEgldString).isSet()); 64 | } 65 | 66 | @Test 67 | void toCurrencyString() { 68 | var balance1 = Balance.fromString("5100000000000000000"); 69 | assertEquals("5.10EGLD", balance1.toCurrencyString()); 70 | 71 | var balance2 = Balance.fromEgld(51.7689); 72 | assertEquals("51.76EGLD", balance2.toCurrencyString()); 73 | } 74 | 75 | } -------------------------------------------------------------------------------- /src/test/java/io/ezalabs/multiversxspringbootstarterreactive/domain/common/NonceTest.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.common; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertDoesNotThrow; 4 | import static org.junit.jupiter.api.Assertions.assertEquals; 5 | import static org.junit.jupiter.api.Assertions.assertThrows; 6 | 7 | import io.ezalabs.multiversxspringbootstarterreactive.error.exception.InvalidNonceException; 8 | import org.junit.jupiter.api.Assertions; 9 | import org.junit.jupiter.api.Test; 10 | 11 | class NonceTest { 12 | 13 | @Test 14 | void fromLong() { 15 | Assertions.assertDoesNotThrow(() -> Nonce.fromLong(1L)); 16 | assertThrows(InvalidNonceException.class, () -> Nonce.fromLong(-1L)); 17 | } 18 | 19 | @Test 20 | void zero() { 21 | assertEquals(0, Nonce.zero().getValue()); 22 | } 23 | 24 | } -------------------------------------------------------------------------------- /src/test/java/io/ezalabs/multiversxspringbootstarterreactive/domain/esdt/ESDTSpecialRoleTest.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.esdt; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | import static org.junit.jupiter.api.Assertions.assertThrows; 5 | import static io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.common.ESDTSpecialRole.ESDT_LOCAL_BURN; 6 | import static io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.common.ESDTSpecialRole.ESDT_LOCAL_MINT; 7 | 8 | import io.ezalabs.multiversxspringbootstarterreactive.config.constants.ESDTConstants; 9 | import org.bouncycastle.util.encoders.Hex; 10 | import org.junit.jupiter.api.Test; 11 | import io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.common.ESDTSpecialRole; 12 | 13 | class ESDTSpecialRoleTest { 14 | 15 | @Test 16 | void testHexAndValue() { 17 | var pName = ESDT_LOCAL_MINT; 18 | 19 | assertEquals(Hex.toHexString(ESDTConstants.ESDT_MINT_ROLE.getBytes()), pName.getHex()); 20 | assertEquals(ESDTConstants.ESDT_MINT_ROLE, pName.getValue()); 21 | } 22 | 23 | @Test 24 | void testGetByValue() { 25 | assertEquals(ESDT_LOCAL_BURN, ESDTSpecialRole.getByValue(ESDTConstants.ESDT_BURN_ROLE)); 26 | assertThrows(IllegalArgumentException.class, () -> ESDTSpecialRole.getByValue("mintRole")); 27 | } 28 | 29 | } -------------------------------------------------------------------------------- /src/test/java/io/ezalabs/multiversxspringbootstarterreactive/domain/esdt/ESDTUpgradeTest.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.esdt; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | 5 | import io.ezalabs.multiversxspringbootstarterreactive.config.constants.ESDTConstants; 6 | import java.util.LinkedHashSet; 7 | import java.util.List; 8 | import org.junit.jupiter.api.Test; 9 | import io.ezalabs.multiversxspringbootstarterreactive.domain.account.Address; 10 | import io.ezalabs.multiversxspringbootstarterreactive.domain.common.Balance; 11 | import io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.common.TokenIdentifier; 12 | import io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.common.TokenProperty; 13 | import io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.common.TokenPropertyName; 14 | import io.ezalabs.multiversxspringbootstarterreactive.domain.wallet.Wallet; 15 | 16 | class ESDTUpgradeTest { 17 | 18 | private static final Wallet wallet = Wallet.fromPrivateKeyHex( 19 | "8442d0bcadbae1b75eff1165f1e3a61f120bddbb440393d8ba3c366342ee4f62"); 20 | 21 | @Test 22 | void upgrade() { 23 | var tokenIdentifier = TokenIdentifier.fromString("YMY-8888aa"); 24 | 25 | var freezeProp = new TokenProperty(TokenPropertyName.CAN_FREEZE, true); 26 | var wipeProp = new TokenProperty(TokenPropertyName.CAN_WIPE, false); 27 | var pauseProp = new TokenProperty(TokenPropertyName.CAN_PAUSE, true); 28 | var changeProp = new TokenProperty(TokenPropertyName.CAN_CHANGE_OWNER, true); 29 | var upgradeProp = new TokenProperty(TokenPropertyName.CAN_UPGRADE, true); 30 | var specialRoleProp = new TokenProperty(TokenPropertyName.CAN_ADD_SPECIAL_ROLES, true); 31 | 32 | var props = new LinkedHashSet<>(List.of(freezeProp, wipeProp, pauseProp, changeProp, 33 | upgradeProp, specialRoleProp)); 34 | 35 | var upgrade = ESDTUpgrade.builder() 36 | .tokenIdentifier(tokenIdentifier) 37 | .properties(props) 38 | .build(); 39 | 40 | var req = upgrade.toTransactionRequest(wallet); 41 | 42 | assertEquals(Address.fromBech32(ESDTConstants.ESDT_ISSUER_BECH32_ADDRESS).getBech32(), 43 | req.getReceiverAddress().getBech32()); 44 | assertEquals(Balance.zero().getValue(), req.getValue().getValue()); 45 | 46 | var dataArgs = req.getData().toString().split("@"); 47 | assertEquals(ESDTConstants.ESDT_UPGRADE_CALL, dataArgs[0]); 48 | assertEquals(tokenIdentifier.getHex(), dataArgs[1]); 49 | 50 | int index = 2; 51 | for (TokenProperty prop : props) { 52 | assertEquals(prop.getNameHex(), dataArgs[index++]); 53 | assertEquals(prop.getValueHex(), dataArgs[index++]); 54 | } 55 | } 56 | 57 | } -------------------------------------------------------------------------------- /src/test/java/io/ezalabs/multiversxspringbootstarterreactive/domain/esdt/NFTAddURITest.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.esdt; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | 5 | import io.ezalabs.multiversxspringbootstarterreactive.config.constants.ESDTConstants; 6 | import java.util.LinkedHashSet; 7 | import java.util.List; 8 | import java.util.Set; 9 | import org.junit.jupiter.api.Test; 10 | import io.ezalabs.multiversxspringbootstarterreactive.domain.common.Balance; 11 | import io.ezalabs.multiversxspringbootstarterreactive.domain.common.Nonce; 12 | import io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.common.ESDTUri; 13 | import io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.common.TokenIdentifier; 14 | import io.ezalabs.multiversxspringbootstarterreactive.domain.transaction.GasLimit; 15 | import io.ezalabs.multiversxspringbootstarterreactive.domain.wallet.Wallet; 16 | 17 | class NFTAddURITest { 18 | 19 | final Wallet wallet = Wallet.fromPrivateKeyHex("8442d0bcadbae1b75eff1165f1e3a61f120bddbb440393d8ba3c366342ee4f62"); 20 | 21 | @Test 22 | void create() { 23 | final var identifier = TokenIdentifier.fromString("YMY-19jf9a"); 24 | final var nonce = Nonce.fromLong(2L); 25 | 26 | final var uri1 = ESDTUri.fromString("ipfsCID/img.jpeg", ESDTUri.Type.MEDIA); 27 | final var uri2 = ESDTUri.fromString("ipfsCID/img2.jpeg", ESDTUri.Type.MEDIA); 28 | final Set uris = new LinkedHashSet<>(List.of(uri1, uri2)); 29 | 30 | var nft = NFTAddURI.builder() 31 | .tokenIdentifier(identifier) 32 | .nonce(nonce) 33 | .uris(uris) 34 | .build(); 35 | 36 | var req = nft.toTransactionRequest(wallet); 37 | 38 | assertEquals(wallet.getAddress().getBech32(), req.getReceiverAddress().getBech32()); 39 | assertEquals(Balance.zero().getValue(), req.getValue().getValue()); 40 | assertEquals(GasLimit.defaultNftCreate().getValue(), req.getGasLimit().getValue()); 41 | 42 | var dataArgs = req.getData().toString().split("@"); 43 | assertEquals(ESDTConstants.ESDT_NFT_ADD_URI_CALL, dataArgs[0]); 44 | assertEquals(identifier.getHex(), dataArgs[1]); 45 | assertEquals(nonce.getHex(), dataArgs[2]); 46 | assertEquals(uri1.getHex(), dataArgs[3]); 47 | assertEquals(uri2.getHex(), dataArgs[4]); 48 | } 49 | 50 | } -------------------------------------------------------------------------------- /src/test/java/io/ezalabs/multiversxspringbootstarterreactive/domain/esdt/NFTAttributesUpdateTest.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.esdt; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | 5 | import io.ezalabs.multiversxspringbootstarterreactive.config.constants.ESDTConstants; 6 | import org.junit.jupiter.api.Test; 7 | import io.ezalabs.multiversxspringbootstarterreactive.domain.common.Balance; 8 | import io.ezalabs.multiversxspringbootstarterreactive.domain.common.Nonce; 9 | import io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.common.TokenAttributes; 10 | import io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.common.TokenIdentifier; 11 | import io.ezalabs.multiversxspringbootstarterreactive.domain.transaction.GasLimit; 12 | import io.ezalabs.multiversxspringbootstarterreactive.domain.wallet.Wallet; 13 | 14 | class NFTAttributesUpdateTest { 15 | 16 | final Wallet wallet = Wallet.fromPrivateKeyHex("8442d0bcadbae1b75eff1165f1e3a61f120bddbb440393d8ba3c366342ee4f62"); 17 | 18 | @Test 19 | void create() { 20 | final var identifier = TokenIdentifier.fromString("YMY-19jf9a"); 21 | final var nonce = Nonce.fromLong(2L); 22 | final var attributes = TokenAttributes.fromString("ipfsCID/fileName.json", new String[]{"one", "two"}); 23 | 24 | var nft = NFTAttributesUpdate.builder() 25 | .tokenIdentifier(identifier) 26 | .nonce(nonce) 27 | .tokenAttributes(attributes) 28 | .build(); 29 | 30 | var req = nft.toTransactionRequest(wallet); 31 | 32 | assertEquals(wallet.getAddress().getBech32(), req.getReceiverAddress().getBech32()); 33 | assertEquals(Balance.zero().getValue(), req.getValue().getValue()); 34 | assertEquals(GasLimit.defaultNftCreate().getValue(), req.getGasLimit().getValue()); 35 | 36 | var dataArgs = req.getData().toString().split("@"); 37 | assertEquals(ESDTConstants.ESDT_NFT_UPDATE_ATTRIBUTES_CALL, dataArgs[0]); 38 | assertEquals(identifier.getHex(), dataArgs[1]); 39 | assertEquals(nonce.getHex(), dataArgs[2]); 40 | assertEquals(attributes.getHex(), dataArgs[3]); 41 | } 42 | 43 | } -------------------------------------------------------------------------------- /src/test/java/io/ezalabs/multiversxspringbootstarterreactive/domain/esdt/NFTStopCreationTest.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.esdt; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | import static org.junit.jupiter.api.Assertions.assertTrue; 5 | 6 | import io.ezalabs.multiversxspringbootstarterreactive.config.constants.ESDTConstants; 7 | import org.junit.jupiter.api.Test; 8 | import io.ezalabs.multiversxspringbootstarterreactive.domain.account.Address; 9 | import io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.common.TokenIdentifier; 10 | import io.ezalabs.multiversxspringbootstarterreactive.domain.transaction.GasLimit; 11 | import io.ezalabs.multiversxspringbootstarterreactive.domain.wallet.Wallet; 12 | 13 | class NFTStopCreationTest { 14 | 15 | private static final Wallet wallet = Wallet.fromPrivateKeyHex( 16 | "8442d0bcadbae1b75eff1165f1e3a61f120bddbb440393d8ba3c366342ee4f62"); 17 | 18 | @Test 19 | void transferRole() { 20 | final var identifier = TokenIdentifier.fromString("YMY-8888aa"); 21 | 22 | var stopCreation = NFTStopCreation.builder() 23 | .tokenIdentifier(identifier) 24 | .build(); 25 | 26 | var req = stopCreation.toTransactionRequest(wallet); 27 | 28 | assertEquals(Address.fromBech32(ESDTConstants.ESDT_ISSUER_BECH32_ADDRESS).getBech32(), 29 | req.getReceiverAddress().getBech32()); 30 | assertEquals(GasLimit.defaultEsdtIssuance().getValue(), req.getGasLimit().getValue()); 31 | assertTrue(req.getValue().isZero()); 32 | 33 | var dataArgs = req.getData().toString().split("@"); 34 | assertEquals(ESDTConstants.ESDT_NFT_STOP_CREATION_CALL, dataArgs[0]); 35 | assertEquals(identifier.getHex(), dataArgs[1]); 36 | } 37 | 38 | } -------------------------------------------------------------------------------- /src/test/java/io/ezalabs/multiversxspringbootstarterreactive/domain/esdt/TokenInitialSupplyTest.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.esdt; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | import static org.junit.jupiter.api.Assertions.assertThrows; 5 | 6 | import io.ezalabs.multiversxspringbootstarterreactive.error.ErrorMessage; 7 | import java.math.BigInteger; 8 | import org.junit.jupiter.api.Assertions; 9 | import org.junit.jupiter.api.Test; 10 | import io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.common.TokenInitialSupply; 11 | 12 | class TokenInitialSupplyTest { 13 | 14 | @Test 15 | void fromNumber() { 16 | var s1 = TokenInitialSupply 17 | .fromNumber(BigInteger.valueOf(31_000_000L)); 18 | 19 | assertEquals("01d905c0", s1.getHex()); 20 | 21 | Assertions.assertEquals(ErrorMessage.INITIAL_SUPPLY.getValue(), 22 | assertThrows(IllegalArgumentException.class, 23 | () -> TokenInitialSupply.fromNumber(BigInteger.valueOf(-500L))).getMessage()); 24 | } 25 | 26 | @Test 27 | void fromString() { 28 | var s1 = TokenInitialSupply.fromString("32000000"); 29 | 30 | assertEquals(BigInteger.valueOf(32_000_000L), s1.getSupply()); 31 | assertEquals("01e84800", s1.getHex()); 32 | 33 | assertThrows(NumberFormatException.class, () -> TokenInitialSupply.fromString("120ks")); 34 | } 35 | } -------------------------------------------------------------------------------- /src/test/java/io/ezalabs/multiversxspringbootstarterreactive/domain/esdt/TokenNameTest.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.esdt; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | import static org.junit.jupiter.api.Assertions.assertThrows; 5 | 6 | import org.bouncycastle.util.encoders.Hex; 7 | import org.junit.jupiter.api.Test; 8 | import io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.common.TokenName; 9 | 10 | class TokenNameTest { 11 | 12 | @Test 13 | void fromString() { 14 | 15 | var t1 = TokenName.fromString(" UsT "); 16 | 17 | assertEquals("UsT", t1.getValue()); 18 | assertEquals("UsT", new String(Hex.decode(t1.getHex()))); 19 | 20 | assertThrows(IllegalArgumentException.class, () -> TokenName.fromString(null)); 21 | assertThrows(IllegalArgumentException.class, () -> TokenName.fromString(" ")); 22 | assertThrows(IllegalArgumentException.class, () -> TokenName.fromString("TOKKEN--")); 23 | assertThrows(IllegalArgumentException.class, () -> TokenName.fromString(" aa ")); 24 | assertThrows(IllegalArgumentException.class, () -> TokenName.fromString("aaaaaaaaaaaaaaaaaaaaa")); 25 | } 26 | } -------------------------------------------------------------------------------- /src/test/java/io/ezalabs/multiversxspringbootstarterreactive/domain/esdt/TokenPropertyNameTest.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.esdt; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | import static org.junit.jupiter.api.Assertions.assertThrows; 5 | 6 | import org.junit.jupiter.api.Test; 7 | import io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.common.TokenPropertyName; 8 | 9 | class TokenPropertyNameTest { 10 | 11 | @Test 12 | void testHexAndValue() { 13 | var pName = TokenPropertyName.CAN_ADD_SPECIAL_ROLES; 14 | 15 | assertEquals("63616e4164645370656369616c526f6c6573", pName.getHex()); 16 | assertEquals("canAddSpecialRoles", pName.getValue()); 17 | } 18 | 19 | @Test 20 | void testGetByValue() { 21 | assertEquals(TokenPropertyName.CAN_FREEZE, TokenPropertyName.getByValue("canFreeze")); 22 | assertThrows(IllegalArgumentException.class, () -> TokenPropertyName.getByValue("cannotFreeze")); 23 | } 24 | } -------------------------------------------------------------------------------- /src/test/java/io/ezalabs/multiversxspringbootstarterreactive/domain/esdt/TokenTickerTest.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.esdt; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | import static org.junit.jupiter.api.Assertions.assertThrows; 5 | 6 | import org.bouncycastle.util.encoders.Hex; 7 | import org.junit.jupiter.api.Test; 8 | import io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.common.TokenTicker; 9 | 10 | class TokenTickerTest { 11 | 12 | @Test 13 | void fromString() { 14 | var t1 = TokenTicker.fromString(" UsT "); 15 | 16 | assertEquals("UST", t1.getValue()); 17 | assertEquals("UST", new String(Hex.decode(t1.getHex()))); 18 | 19 | assertThrows(IllegalArgumentException.class, () -> TokenTicker.fromString(null)); 20 | assertThrows(IllegalArgumentException.class, () -> TokenTicker.fromString(" ")); 21 | assertThrows(IllegalArgumentException.class, () -> TokenTicker.fromString("tkn--")); 22 | assertThrows(IllegalArgumentException.class, () -> TokenTicker.fromString(" tk ")); 23 | assertThrows(IllegalArgumentException.class, () -> TokenTicker.fromString("aaaaaaaaaaa")); 24 | } 25 | 26 | } -------------------------------------------------------------------------------- /src/test/java/io/ezalabs/multiversxspringbootstarterreactive/domain/esdt/issuance/ESDTUriTest.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.issuance; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | import static org.junit.jupiter.api.Assertions.assertThrows; 5 | 6 | import org.junit.jupiter.api.Test; 7 | import io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.common.ESDTUri; 8 | 9 | class ESDTUriTest { 10 | 11 | @Test 12 | void invalidURI() { 13 | assertThrows(IllegalArgumentException.class, () -> ESDTUri.fromString("f3/f -9fa92", ESDTUri.Type.MEDIA)); 14 | } 15 | 16 | @Test 17 | void fromStringMeta() { 18 | var uri = ESDTUri.fromString("https://host/storage/metadata.json", ESDTUri.Type.METADATA); 19 | assertEquals("68747470733a2f2f686f73742f73746f726167652f6d657461646174612e6a736f6e", 20 | uri.getHex()); 21 | } 22 | 23 | @Test 24 | void fromStringMedia() { 25 | var uri = ESDTUri.fromString("https://host/storage/image.jpeg", ESDTUri.Type.MEDIA); 26 | assertEquals("68747470733a2f2f686f73742f73746f726167652f696d6167652e6a706567", 27 | uri.getHex()); 28 | } 29 | 30 | @Test 31 | void fromStringMeta_notJson() { 32 | assertThrows(IllegalArgumentException.class, 33 | () -> ESDTUri.fromString("https://host/storage/metadata.notJson", ESDTUri.Type.METADATA)); 34 | } 35 | 36 | @Test 37 | void fromStringMedia_notSupported() { 38 | assertThrows(IllegalArgumentException.class, 39 | () -> ESDTUri.fromString("https://host/storage/image.another", ESDTUri.Type.MEDIA)); 40 | } 41 | } -------------------------------------------------------------------------------- /src/test/java/io/ezalabs/multiversxspringbootstarterreactive/domain/esdt/issuance/TokenAttributesTest.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.issuance; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | import static org.junit.jupiter.api.Assertions.assertThrows; 5 | 6 | import org.junit.jupiter.api.Test; 7 | import io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.common.TokenAttributes; 8 | 9 | class TokenAttributesTest { 10 | 11 | @Test 12 | void fromString() { 13 | var tag1 = " first"; 14 | var tag2 = " second "; 15 | var tags = new String[]{tag1, tag2}; 16 | 17 | var attr = TokenAttributes.fromString("ipfs/CID/fileName.json", tags); 18 | 19 | assertEquals("metadata:ipfs/CID/fileName.json;tags:first,second", attr.toString()); 20 | assertEquals("6d657461646174613a697066732f4349442f66696c654e616d652e6a736f6e3b746167733a66697273742c7365636f6e64", 21 | attr.getHex()); 22 | } 23 | 24 | @Test 25 | void fromStringErr() { 26 | assertThrows(IllegalArgumentException.class, () -> TokenAttributes 27 | .fromString(null, null)); 28 | assertThrows(IllegalArgumentException.class, () -> TokenAttributes 29 | .fromString("", new String[]{})); 30 | assertThrows(IllegalArgumentException.class, () -> TokenAttributes 31 | .fromString("ipfs/CID/fileName.json", new String[]{})); 32 | assertThrows(IllegalArgumentException.class, () -> TokenAttributes 33 | .fromString("ipfs/CID/fileName.txt", new String[]{"one"})); 34 | } 35 | 36 | } -------------------------------------------------------------------------------- /src/test/java/io/ezalabs/multiversxspringbootstarterreactive/domain/esdt/issuance/TokenDecimalsTest.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.issuance; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | import static org.junit.jupiter.api.Assertions.assertThrows; 5 | 6 | import io.ezalabs.multiversxspringbootstarterreactive.error.ErrorMessage; 7 | import org.junit.jupiter.api.Assertions; 8 | import org.junit.jupiter.api.Test; 9 | import io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.common.TokenDecimals; 10 | 11 | class TokenDecimalsTest { 12 | 13 | @Test 14 | void fromNumber() { 15 | var s1 = TokenDecimals.fromNumber(2); 16 | 17 | assertEquals("02", s1.getHex()); 18 | 19 | Assertions.assertEquals(ErrorMessage.TOKEN_DECIMALS.getValue(), 20 | assertThrows(IllegalArgumentException.class, 21 | () -> TokenDecimals.fromNumber(-1)).getMessage()); 22 | assertEquals(ErrorMessage.TOKEN_DECIMALS.getValue(), 23 | assertThrows(IllegalArgumentException.class, 24 | () -> TokenDecimals.fromNumber(19)).getMessage()); 25 | assertEquals(ErrorMessage.TOKEN_DECIMALS.getValue(), 26 | assertThrows(IllegalArgumentException.class, 27 | () -> TokenDecimals.fromNumber(7)).getMessage()); 28 | } 29 | 30 | @Test 31 | void fromString() { 32 | var s1 = TokenDecimals.fromString("6"); 33 | assertEquals("06", s1.getHex()); 34 | 35 | assertThrows(NumberFormatException.class, () -> TokenDecimals.fromString("2x")); 36 | 37 | } 38 | 39 | } -------------------------------------------------------------------------------- /src/test/java/io/ezalabs/multiversxspringbootstarterreactive/domain/esdt/issuance/TokenIdentifierTest.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.issuance; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | import static org.junit.jupiter.api.Assertions.assertThrows; 5 | 6 | import org.bouncycastle.util.encoders.Hex; 7 | import org.junit.jupiter.api.Test; 8 | import io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.common.TokenIdentifier; 9 | 10 | class TokenIdentifierTest { 11 | 12 | @Test 13 | void fromString() { 14 | var t1 = TokenIdentifier.fromString("MoJi-J29900"); 15 | 16 | assertEquals("MOJI-j29900", t1.getValue()); 17 | assertEquals(Hex.toHexString("MOJI-j29900".getBytes()), t1.getHex()); 18 | 19 | assertThrows(IllegalArgumentException.class, () -> TokenIdentifier.fromString(null)); 20 | assertThrows(IllegalArgumentException.class, () -> TokenIdentifier.fromString(" ")); 21 | assertThrows(IllegalArgumentException.class, () -> TokenIdentifier.fromString("tkn--")); 22 | assertThrows(IllegalArgumentException.class, () -> TokenIdentifier.fromString("AS-90fa9 ")); 23 | } 24 | } -------------------------------------------------------------------------------- /src/test/java/io/ezalabs/multiversxspringbootstarterreactive/domain/esdt/issuance/TokenRoyaltiesTest.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.issuance; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | import static org.junit.jupiter.api.Assertions.assertThrows; 5 | 6 | import org.junit.jupiter.api.Test; 7 | import io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.common.TokenRoyalties; 8 | 9 | class TokenRoyaltiesTest { 10 | 11 | @Test 12 | void create() { 13 | var roy = TokenRoyalties.fromNumber(5); 14 | 15 | assertEquals("05", roy.getHex()); 16 | 17 | assertThrows(IllegalArgumentException.class, () -> TokenRoyalties.fromNumber(null)); 18 | assertThrows(IllegalArgumentException.class, () -> TokenRoyalties.fromNumber(-1)); 19 | assertThrows(IllegalArgumentException.class, () -> TokenRoyalties.fromNumber(10001)); 20 | } 21 | 22 | } -------------------------------------------------------------------------------- /src/test/java/io/ezalabs/multiversxspringbootstarterreactive/domain/esdt/operations/NFTSFTLocalOpTest.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.operations; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | import static org.junit.jupiter.api.Assertions.assertTrue; 5 | 6 | import io.ezalabs.multiversxspringbootstarterreactive.config.constants.ESDTConstants; 7 | import java.math.BigInteger; 8 | import org.junit.jupiter.api.Test; 9 | import io.ezalabs.multiversxspringbootstarterreactive.domain.common.Balance; 10 | import io.ezalabs.multiversxspringbootstarterreactive.domain.common.Nonce; 11 | import io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.NFTSFTLocalOp; 12 | import io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.common.TokenIdentifier; 13 | import io.ezalabs.multiversxspringbootstarterreactive.domain.transaction.GasLimit; 14 | import io.ezalabs.multiversxspringbootstarterreactive.domain.wallet.Wallet; 15 | 16 | class NFTSFTLocalOpTest { 17 | 18 | private static final Wallet wallet = Wallet.fromPrivateKeyHex( 19 | "8442d0bcadbae1b75eff1165f1e3a61f120bddbb440393d8ba3c366342ee4f62"); 20 | private final TokenIdentifier identifier = TokenIdentifier.fromString("YMY-8888aa"); 21 | private final Balance amount = Balance.fromNumber(BigInteger.valueOf(500)); 22 | private final Nonce nonce = Nonce.fromLong(2L); 23 | 24 | @Test 25 | void mint() { 26 | var minting = builder() 27 | .type(NFTSFTLocalOp.Type.ADD) 28 | .build(); 29 | 30 | var request = minting.toTransactionRequest(wallet); 31 | 32 | assertEquals(wallet.getAddress().getBech32(), request.getReceiverAddress().getBech32()); 33 | assertEquals(GasLimit.defaultNftCreate().getValue(), request.getGasLimit().getValue()); 34 | assertTrue(request.getValue().isZero()); 35 | 36 | var dataArgs = request.getData().toString().split("@"); 37 | assertEquals(ESDTConstants.ESDT_NFTSFT_ADD_CALL, dataArgs[0]); 38 | assertEquals(identifier.getHex(), dataArgs[1]); 39 | assertEquals(nonce.getHex(), dataArgs[2]); 40 | assertEquals(amount.getHex(), dataArgs[3]); 41 | } 42 | 43 | @Test 44 | void burn() { 45 | var burning = builder() 46 | .type(NFTSFTLocalOp.Type.BURN) 47 | .build(); 48 | 49 | var request = burning.toTransactionRequest(wallet); 50 | 51 | var dataArgs = request.getData().toString().split("@"); 52 | assertEquals(ESDTConstants.ESDT_NFTSFT_BURN_CALL, dataArgs[0]); 53 | } 54 | 55 | private NFTSFTLocalOp.NFTSFTLocalOpBuilder builder() { 56 | return NFTSFTLocalOp.builder() 57 | .amount(amount) 58 | .nonce(nonce) 59 | .tokenIdentifier(identifier); 60 | } 61 | 62 | } -------------------------------------------------------------------------------- /src/test/java/io/ezalabs/multiversxspringbootstarterreactive/domain/esdt/role/ESDTOwnershipTransferTest.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.role; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | import static org.junit.jupiter.api.Assertions.assertTrue; 5 | 6 | import io.ezalabs.multiversxspringbootstarterreactive.config.constants.ESDTConstants; 7 | import org.junit.jupiter.api.Test; 8 | import io.ezalabs.multiversxspringbootstarterreactive.domain.account.Address; 9 | import io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.ESDTOwnershipTransfer; 10 | import io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.common.TokenIdentifier; 11 | import io.ezalabs.multiversxspringbootstarterreactive.domain.transaction.GasLimit; 12 | import io.ezalabs.multiversxspringbootstarterreactive.domain.wallet.Wallet; 13 | 14 | class ESDTOwnershipTransferTest { 15 | 16 | private static final Wallet wallet = Wallet.fromPrivateKeyHex( 17 | "8442d0bcadbae1b75eff1165f1e3a61f120bddbb440393d8ba3c366342ee4f62"); 18 | private static final Address targetAddress = Address.fromBech32( 19 | "erd1gklqdv77my5y8n75hszv737gq54q9xk0tmzdh8v5vkfstd64aw7ser9nfr"); 20 | private final TokenIdentifier identifier = TokenIdentifier.fromString("YMY-8888aa"); 21 | 22 | @Test 23 | void transferOwnership() { 24 | var transfer = ESDTOwnershipTransfer.builder() 25 | .tokenIdentifier(identifier) 26 | .targetAddress(targetAddress) 27 | .build(); 28 | 29 | var req = transfer.toTransactionRequest(wallet); 30 | 31 | assertEquals(Address.fromBech32(ESDTConstants.ESDT_ISSUER_BECH32_ADDRESS).getBech32(), 32 | req.getReceiverAddress().getBech32()); 33 | assertEquals(GasLimit.defaultEsdtIssuance().getValue(), req.getGasLimit().getValue()); 34 | assertTrue(req.getValue().isZero()); 35 | 36 | var dataArgs = req.getData().toString().split("@"); 37 | assertEquals(ESDTConstants.ESDT_TRANSFER_OWNERSHIP_CALL, dataArgs[0]); 38 | assertEquals(identifier.getHex(), dataArgs[1]); 39 | assertEquals(targetAddress.getHex(), dataArgs[2]); 40 | assertEquals(3, dataArgs.length); 41 | } 42 | 43 | } -------------------------------------------------------------------------------- /src/test/java/io/ezalabs/multiversxspringbootstarterreactive/domain/esdt/role/NFTCreationRoleTransferTest.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.role; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | import static org.junit.jupiter.api.Assertions.assertTrue; 5 | 6 | import io.ezalabs.multiversxspringbootstarterreactive.config.constants.ESDTConstants; 7 | import org.junit.jupiter.api.Test; 8 | import io.ezalabs.multiversxspringbootstarterreactive.domain.account.Address; 9 | import io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.NFTCreationRoleTransfer; 10 | import io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.common.TokenIdentifier; 11 | import io.ezalabs.multiversxspringbootstarterreactive.domain.transaction.GasLimit; 12 | import io.ezalabs.multiversxspringbootstarterreactive.domain.wallet.Wallet; 13 | 14 | class NFTCreationRoleTransferTest { 15 | 16 | private static final Wallet wallet = Wallet.fromPrivateKeyHex( 17 | "8442d0bcadbae1b75eff1165f1e3a61f120bddbb440393d8ba3c366342ee4f62"); 18 | private static final Address toAddress = Address.fromBech32( 19 | "erd1gklqdv77my5y8n75hszv737gq54q9xk0tmzdh8v5vkfstd64aw7ser9nfr"); 20 | 21 | @Test 22 | void transferRole() { 23 | final var identifier = TokenIdentifier.fromString("YMY-8888aa"); 24 | 25 | var transfer = NFTCreationRoleTransfer.builder() 26 | .tokenIdentifier(identifier) 27 | .fromAddress(wallet.getAddress()) 28 | .toAddress(toAddress) 29 | .build(); 30 | 31 | var req = transfer.toTransactionRequest(wallet); 32 | 33 | assertEquals(Address.fromBech32(ESDTConstants.ESDT_ISSUER_BECH32_ADDRESS).getBech32(), 34 | req.getReceiverAddress().getBech32()); 35 | assertEquals(GasLimit.defaultEsdtIssuance().getValue(), req.getGasLimit().getValue()); 36 | assertTrue(req.getValue().isZero()); 37 | 38 | var dataArgs = req.getData().toString().split("@"); 39 | assertEquals(ESDTConstants.ESDT_NFT_CREATE_ROLE_TRANSFER_CALL, dataArgs[0]); 40 | assertEquals(identifier.getHex(), dataArgs[1]); 41 | assertEquals(wallet.getAddress().getHex(), dataArgs[2]); 42 | assertEquals(toAddress.getHex(), dataArgs[3]); 43 | } 44 | 45 | } -------------------------------------------------------------------------------- /src/test/java/io/ezalabs/multiversxspringbootstarterreactive/domain/esdt/transfer/ESDTLocalOpTest.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.transfer; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | import static org.junit.jupiter.api.Assertions.assertTrue; 5 | 6 | import io.ezalabs.multiversxspringbootstarterreactive.config.constants.ESDTConstants; 7 | import java.math.BigInteger; 8 | import org.junit.jupiter.api.Test; 9 | import io.ezalabs.multiversxspringbootstarterreactive.domain.common.Balance; 10 | import io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.ESDTLocalOp; 11 | import io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.common.TokenIdentifier; 12 | import io.ezalabs.multiversxspringbootstarterreactive.domain.transaction.GasLimit; 13 | import io.ezalabs.multiversxspringbootstarterreactive.domain.wallet.Wallet; 14 | 15 | class ESDTLocalOpTest { 16 | 17 | private static final Wallet wallet = Wallet.fromPrivateKeyHex( 18 | "8442d0bcadbae1b75eff1165f1e3a61f120bddbb440393d8ba3c366342ee4f62"); 19 | private final TokenIdentifier identifier = TokenIdentifier.fromString("YMY-8888aa"); 20 | private final Balance amount = Balance.fromNumber(BigInteger.valueOf(500)); 21 | 22 | @Test 23 | void mint() { 24 | var minting = builder() 25 | .type(ESDTLocalOp.Type.MINT) 26 | .build(); 27 | 28 | var request = minting.toTransactionRequest(wallet); 29 | 30 | assertEquals(wallet.getAddress().getBech32(), request.getReceiverAddress().getBech32()); 31 | assertEquals(GasLimit.defaultEsdtLocalOp().getValue(), request.getGasLimit().getValue()); 32 | assertTrue(request.getValue().isZero()); 33 | 34 | var dataArgs = request.getData().toString().split("@"); 35 | assertEquals(ESDTConstants.ESDT_MINT_CALL, dataArgs[0]); 36 | assertEquals(identifier.getHex(), dataArgs[1]); 37 | assertEquals(amount.getHex(), dataArgs[2]); 38 | } 39 | 40 | @Test 41 | void burn() { 42 | var burning = builder() 43 | .type(ESDTLocalOp.Type.BURN) 44 | .build(); 45 | 46 | var request = burning.toTransactionRequest(wallet); 47 | 48 | var dataArgs = request.getData().toString().split("@"); 49 | assertEquals(ESDTConstants.ESDT_BURN_CALL, dataArgs[0]); 50 | } 51 | 52 | private ESDTLocalOp.ESDTLocalOpBuilder builder() { 53 | return ESDTLocalOp.builder() 54 | .amount(amount) 55 | .tokenIdentifier(identifier); 56 | } 57 | 58 | } -------------------------------------------------------------------------------- /src/test/java/io/ezalabs/multiversxspringbootstarterreactive/domain/esdt/transfer/ESDTTransferTest.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.transfer; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | 5 | import java.math.BigInteger; 6 | import java.util.List; 7 | import org.junit.jupiter.api.Test; 8 | import io.ezalabs.multiversxspringbootstarterreactive.domain.account.Address; 9 | import io.ezalabs.multiversxspringbootstarterreactive.domain.common.Balance; 10 | import io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.ESDTTransfer; 11 | import io.ezalabs.multiversxspringbootstarterreactive.domain.esdt.common.TokenIdentifier; 12 | import io.ezalabs.multiversxspringbootstarterreactive.domain.smartcontract.FunctionArg; 13 | import io.ezalabs.multiversxspringbootstarterreactive.domain.smartcontract.FunctionName; 14 | import io.ezalabs.multiversxspringbootstarterreactive.domain.wallet.Wallet; 15 | 16 | class ESDTTransferTest { 17 | 18 | private static final Wallet wallet = Wallet.fromPrivateKeyHex( 19 | "8442d0bcadbae1b75eff1165f1e3a61f120bddbb440393d8ba3c366342ee4f62"); 20 | 21 | @Test 22 | void transferWithoutScCall() { 23 | var transferWithoutScCall = transferBuilder().build(); 24 | var req1 = transferWithoutScCall.toTransactionRequest(wallet); 25 | 26 | assertEquals("ESDTTransfer@4d4f4a4f2d6a3239393030@0a", req1.getData().toString()); 27 | } 28 | 29 | @Test 30 | void transferWithFunction() { 31 | var transferWithFunction = transferBuilder() 32 | .functionName(FunctionName.fromString("call")) 33 | .build(); 34 | var req2 = transferWithFunction.toTransactionRequest(wallet); 35 | 36 | assertEquals("ESDTTransfer@4d4f4a4f2d6a3239393030@0a@63616c6c", req2.getData().toString()); 37 | } 38 | 39 | @Test 40 | void transferWithFunctionAndArgs() { 41 | var transferWithFunctionAndArgs = transferBuilder() 42 | .functionName(FunctionName.fromString("call")) 43 | .args(List.of(FunctionArg.fromString("baby"))) 44 | .build(); 45 | var req3 = transferWithFunctionAndArgs.toTransactionRequest(wallet); 46 | 47 | assertEquals("ESDTTransfer@4d4f4a4f2d6a3239393030@0a@63616c6c@62616279", req3.getData().toString()); 48 | } 49 | 50 | private ESDTTransfer.ESDTTransferBuilder transferBuilder() { 51 | return ESDTTransfer.builder() 52 | .receiverAddress(Address.fromBech32("erd1gklqdv77my5y8n75hszv737gq54q9xk0tmzdh8v5vkfstd64aw7ser9nfr")) 53 | .tokenIdentifier(TokenIdentifier.fromString("MOJO-J29900")) 54 | .amount(Balance.fromNumber(BigInteger.TEN)); 55 | } 56 | } -------------------------------------------------------------------------------- /src/test/java/io/ezalabs/multiversxspringbootstarterreactive/domain/smartcontract/ContractFunctionTest.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.smartcontract; 2 | 3 | import static java.lang.String.format; 4 | import static org.junit.jupiter.api.Assertions.assertEquals; 5 | 6 | import java.math.BigInteger; 7 | import java.util.List; 8 | import org.junit.jupiter.api.Test; 9 | import io.ezalabs.multiversxspringbootstarterreactive.domain.account.Address; 10 | 11 | class ContractFunctionTest { 12 | 13 | @Test 14 | void getPayloadData() { 15 | var arg1 = FunctionArg.fromString("argument"); 16 | var arg2 = FunctionArg.fromNumber(BigInteger.TWO); 17 | 18 | var scFunction = ContractFunction.builder() 19 | .functionName(FunctionName.fromString("deposit")) 20 | .args(List.of(arg1, arg2)) 21 | .smartContractAddress(Address.zero()) 22 | .build(); 23 | 24 | assertEquals(format("deposit@%s@%s", arg1.getHex(), arg2.getHex()), scFunction.getPayloadData().toString()); 25 | } 26 | } -------------------------------------------------------------------------------- /src/test/java/io/ezalabs/multiversxspringbootstarterreactive/domain/smartcontract/ContractQueryResultTest.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.smartcontract; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | 5 | import io.ezalabs.multiversxspringbootstarterreactive.api.model.ContractQueryResult; 6 | import java.util.Arrays; 7 | import java.util.List; 8 | import org.junit.jupiter.api.Test; 9 | 10 | class ContractQueryResultTest { 11 | 12 | List encodedData = Arrays.asList("ZWxyb25k", "Y3JsZGV2"); 13 | 14 | @Test 15 | void getData() { 16 | var result = ContractQueryResult.builder() 17 | .data(encodedData) 18 | .code("ok") 19 | .message("success") 20 | .build(); 21 | 22 | assertEquals(encodedData, result.getData()); 23 | } 24 | } -------------------------------------------------------------------------------- /src/test/java/io/ezalabs/multiversxspringbootstarterreactive/domain/smartcontract/FunctionArgTest.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.smartcontract; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | import static org.junit.jupiter.api.Assertions.assertThrows; 5 | 6 | import java.math.BigInteger; 7 | import org.junit.jupiter.api.Test; 8 | 9 | class FunctionArgTest { 10 | 11 | @Test 12 | void fromString() { 13 | assertEquals("argument list", FunctionArg.fromString(" argument list ").toString()); 14 | assertEquals("617267756d656e74206c697374", FunctionArg.fromString("argument list ").getHex()); 15 | 16 | assertThrows(IllegalArgumentException.class, () -> FunctionArg.fromString("")); 17 | assertThrows(IllegalArgumentException.class, () -> FunctionArg.fromString(null)); 18 | } 19 | 20 | @Test 21 | void fromNumber() { 22 | assertEquals("2", FunctionArg.fromNumber(BigInteger.TWO).toString()); 23 | assertEquals("02", FunctionArg.fromNumber(BigInteger.TWO).getHex()); 24 | 25 | assertThrows(IllegalArgumentException.class, () -> FunctionArg.fromNumber(null)); 26 | assertThrows(IllegalArgumentException.class, () -> FunctionArg.fromNumber(BigInteger.valueOf(-1L))); 27 | } 28 | 29 | } -------------------------------------------------------------------------------- /src/test/java/io/ezalabs/multiversxspringbootstarterreactive/domain/smartcontract/FunctionNameTest.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.smartcontract; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | import static org.junit.jupiter.api.Assertions.assertThrows; 5 | 6 | import org.apache.logging.log4j.util.Strings; 7 | import org.junit.jupiter.api.Test; 8 | 9 | class FunctionNameTest { 10 | 11 | @Test 12 | void fromString() { 13 | assertThrows(IllegalArgumentException.class, () -> FunctionName.fromString(null)); 14 | assertThrows(IllegalArgumentException.class, () -> FunctionName.fromString("")); 15 | 16 | assertEquals("saveToken", FunctionName.fromString(" saveToken ").getValue()); 17 | assertEquals("73617665546f6b656e", FunctionName.fromString(" saveToken ").getHex()); 18 | assertEquals(Strings.EMPTY, FunctionName.empty().getValue()); 19 | } 20 | } -------------------------------------------------------------------------------- /src/test/java/io/ezalabs/multiversxspringbootstarterreactive/domain/transaction/ChainIDTest.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.transaction; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | import static org.junit.jupiter.api.Assertions.assertThrows; 5 | 6 | import io.ezalabs.multiversxspringbootstarterreactive.error.exception.InvalidChainIdException; 7 | import org.junit.jupiter.api.Test; 8 | 9 | class ChainIDTest { 10 | 11 | @Test 12 | void creation() { 13 | assertEquals(ChainID.DEVNET, ChainID.fromString("D")); 14 | assertEquals(ChainID.MAINNET, ChainID.fromString("1")); 15 | assertEquals(ChainID.TESTNET, ChainID.fromString("T")); 16 | } 17 | 18 | @Test 19 | void error() { 20 | assertThrows(InvalidChainIdException.class, () -> ChainID.fromString("unrecognized")); 21 | } 22 | } -------------------------------------------------------------------------------- /src/test/java/io/ezalabs/multiversxspringbootstarterreactive/domain/transaction/GasTest.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.transaction; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | import static org.junit.jupiter.api.Assertions.assertThrows; 5 | 6 | import io.ezalabs.multiversxspringbootstarterreactive.error.exception.NegativeGasException; 7 | import java.math.BigInteger; 8 | import org.junit.jupiter.api.Test; 9 | 10 | class GasTest { 11 | 12 | @Test 13 | void gasLimitAndPrice_fromNumber() { 14 | var expected = BigInteger.TEN; 15 | 16 | assertEquals(expected, GasLimit.fromNumber(BigInteger.TEN).getValue()); 17 | assertEquals(expected, GasPrice.fromNumber(BigInteger.TEN).getValue()); 18 | 19 | assertThrows(NegativeGasException.class, () -> GasLimit.fromNumber(new BigInteger("-5000"))); 20 | assertThrows(NegativeGasException.class, () -> GasPrice.fromNumber(new BigInteger("-5000"))); 21 | } 22 | 23 | @Test 24 | void gasLimitAndPrice_fromString() { 25 | var expected = "10000"; 26 | 27 | assertEquals(expected, GasLimit.fromString(expected).toString()); 28 | assertEquals(expected, GasPrice.fromString(expected).toString()); 29 | } 30 | } -------------------------------------------------------------------------------- /src/test/java/io/ezalabs/multiversxspringbootstarterreactive/domain/transaction/HashTest.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.transaction; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertArrayEquals; 4 | 5 | import org.bouncycastle.util.encoders.Hex; 6 | import org.junit.jupiter.api.Test; 7 | 8 | class HashTest { 9 | 10 | byte[] hashAsBuffer = "092309uf230j9j03f29".getBytes(); 11 | 12 | @Test 13 | void fromString() { 14 | var hashAsString = new String(Hex.encode(hashAsBuffer)); 15 | var expected = Hex.decode(hashAsString); 16 | 17 | assertArrayEquals(expected, Hash.fromString(hashAsString).getValue()); 18 | } 19 | 20 | @Test 21 | void fromBuffer() { 22 | assertArrayEquals(hashAsBuffer, Hash.fromBuffer(hashAsBuffer).getValue()); 23 | } 24 | 25 | } -------------------------------------------------------------------------------- /src/test/java/io/ezalabs/multiversxspringbootstarterreactive/domain/transaction/PayloadDataTest.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.transaction; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertArrayEquals; 4 | import static org.junit.jupiter.api.Assertions.assertEquals; 5 | import static org.junit.jupiter.api.Assertions.assertTrue; 6 | 7 | import java.util.Base64; 8 | import org.apache.logging.log4j.util.Strings; 9 | import org.junit.jupiter.api.Test; 10 | 11 | class PayloadDataTest { 12 | 13 | String dataString = "crldev x multiversX"; 14 | byte[] dataAsBuffer = dataString.getBytes(); 15 | String encoded = Base64.getEncoder().encodeToString(dataAsBuffer); 16 | 17 | @Test 18 | void fromString() { 19 | assertArrayEquals(dataAsBuffer, PayloadData.fromString(dataString).getBuffer()); 20 | } 21 | 22 | @Test 23 | void fromEncoded() { 24 | var emptyEncoded = Strings.EMPTY; 25 | 26 | assertArrayEquals(dataAsBuffer, PayloadData.fromBase64Encoded(encoded).getBuffer()); 27 | assertTrue(PayloadData.fromBase64Encoded(emptyEncoded).isEmpty()); 28 | } 29 | 30 | @Test 31 | void length() { 32 | assertEquals(dataString.length(), PayloadData.fromBase64Encoded(encoded).length()); 33 | } 34 | 35 | @Test 36 | void encoded() { 37 | assertEquals(encoded, PayloadData.fromString(dataString).encoded()); 38 | } 39 | } -------------------------------------------------------------------------------- /src/test/java/io/ezalabs/multiversxspringbootstarterreactive/domain/transaction/SignatureTest.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.transaction; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | import static org.junit.jupiter.api.Assertions.assertThrows; 5 | 6 | import io.ezalabs.multiversxspringbootstarterreactive.error.exception.CannotCreateSignatureException; 7 | import io.ezalabs.multiversxspringbootstarterreactive.error.exception.SignatureEmptyException; 8 | import org.bouncycastle.util.encoders.Hex; 9 | import org.junit.jupiter.api.Test; 10 | 11 | class SignatureTest { 12 | 13 | String signatureHex = "0b80e9e08732fa0dd84bf3f39d84447cbf1ac84f1417938c73ef0c1ea652a19eef13479143d19260324965676941fc7126a9e4638db766110a4f3d3d57422309"; 14 | String invalidSignatureHex = "696e76616c69642d7369676e6174757265"; 15 | 16 | @Test 17 | void fromHex() { 18 | assertEquals(signatureHex, Signature.fromHex(signatureHex).getHex()); 19 | assertThrows(CannotCreateSignatureException.class, () -> Signature.fromHex(invalidSignatureHex)); 20 | } 21 | 22 | @Test 23 | void fromBuffer() { 24 | var signatureBuffer = Hex.decode(signatureHex); 25 | var invalidSignatureBuffer = Hex.decode(invalidSignatureHex); 26 | 27 | assertEquals(signatureHex, Signature.fromBuffer(signatureBuffer).getHex()); 28 | assertThrows(CannotCreateSignatureException.class, () -> Signature.fromBuffer(invalidSignatureBuffer)); 29 | } 30 | 31 | @Test 32 | void empty() { 33 | assertThrows(SignatureEmptyException.class, () -> Signature.empty().getHex()); 34 | } 35 | 36 | } -------------------------------------------------------------------------------- /src/test/java/io/ezalabs/multiversxspringbootstarterreactive/domain/transaction/TransactionStatusTest.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.transaction; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | import static org.junit.jupiter.api.Assertions.assertThrows; 5 | 6 | import io.ezalabs.multiversxspringbootstarterreactive.error.exception.InvalidTransactionStatusException; 7 | import org.junit.jupiter.api.Test; 8 | 9 | class TransactionStatusTest { 10 | 11 | @Test 12 | void create() { 13 | assertEquals(TransactionStatus.FAIL, TransactionStatus.fromString("FaiL")); 14 | assertEquals(TransactionStatus.SUCCESS, TransactionStatus.fromString("suCCESS")); 15 | assertEquals(TransactionStatus.INVALID, TransactionStatus.fromString("INVAlid")); 16 | assertEquals(TransactionStatus.PENDING, TransactionStatus.fromString("pending")); 17 | } 18 | 19 | @Test 20 | void error() { 21 | assertThrows(InvalidTransactionStatusException.class, () -> TransactionStatus.fromString("unrecognized")); 22 | } 23 | } -------------------------------------------------------------------------------- /src/test/java/io/ezalabs/multiversxspringbootstarterreactive/domain/transaction/TransactionVersionTest.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.domain.transaction; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | import static org.junit.jupiter.api.Assertions.assertThrows; 5 | 6 | import io.ezalabs.multiversxspringbootstarterreactive.config.constants.TransactionConstants; 7 | import io.ezalabs.multiversxspringbootstarterreactive.error.exception.InvalidTransactionVersionException; 8 | import org.junit.jupiter.api.Test; 9 | 10 | class TransactionVersionTest { 11 | 12 | @Test 13 | void create() { 14 | assertEquals(2, TransactionVersion.fromInteger(2).getValue()); 15 | assertThrows(InvalidTransactionVersionException.class, () -> TransactionVersion.fromInteger(-1)); 16 | } 17 | 18 | @Test 19 | void withDefaultVersion() { 20 | assertEquals(TransactionConstants.TRANSACTION_VERSION_DEFAULT, TransactionVersion.withDefaultVersion().getValue()); 21 | } 22 | 23 | @Test 24 | void withTxHashSignVersion() { 25 | assertEquals(TransactionConstants.TRANSACTION_VERSION_TX_HASH_SIGN, TransactionVersion.withTransactionHashSignVersion().getValue()); 26 | } 27 | } -------------------------------------------------------------------------------- /src/test/java/io/ezalabs/multiversxspringbootstarterreactive/interactor/Helper.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.interactor; 2 | 3 | import static org.mockito.ArgumentMatchers.any; 4 | import static org.mockito.ArgumentMatchers.anyString; 5 | import static org.mockito.Mockito.when; 6 | 7 | import io.ezalabs.multiversxspringbootstarterreactive.client.MxProxyClient; 8 | import java.util.function.Consumer; 9 | import java.util.function.Supplier; 10 | import org.reactivestreams.Publisher; 11 | import org.springframework.http.HttpMethod; 12 | import reactor.core.publisher.Mono; 13 | import reactor.test.StepVerifier; 14 | 15 | public class Helper { 16 | 17 | public static void verifyInteractionOk(MxProxyClient client, 18 | Object apiResponse, 19 | Supplier> action, 20 | Consumer assertion, HttpMethod method) { 21 | 22 | mockClientMethod(client, apiResponse, method); 23 | 24 | StepVerifier.create(action.get()) 25 | .assertNext(assertion) 26 | .verifyComplete(); 27 | } 28 | 29 | public static void verifyInteractionException(MxProxyClient client, 30 | Object apiResponse, 31 | Supplier> action, 32 | Class exception, HttpMethod method) { 33 | 34 | mockClientMethod(client, apiResponse, method); 35 | 36 | StepVerifier.create(action.get()) 37 | .verifyError(exception); 38 | } 39 | 40 | private static void mockClientMethod(MxProxyClient client, Object apiResponse, HttpMethod method) { 41 | if (method == HttpMethod.GET) { 42 | when((client.get(anyString(), any()))).thenReturn(Mono.just(apiResponse)); 43 | } else { 44 | when((client.post(anyString(), any(), any()))).thenReturn(Mono.just(apiResponse)); 45 | } 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/test/java/io/ezalabs/multiversxspringbootstarterreactive/properties/MxClientPropertiesTest.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.properties; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | import static org.junit.jupiter.api.Assertions.assertThrows; 5 | 6 | import io.ezalabs.multiversxspringbootstarterreactive.error.exception.GatewayException; 7 | import org.junit.jupiter.api.Test; 8 | 9 | class MxClientPropertiesTest { 10 | 11 | @Test 12 | void setGateway() { 13 | var props = new MxClientProperties(); 14 | 15 | assertEquals("https://devnet-gateway.multiversx.com", props.getProxyUrl()); 16 | 17 | props.setGateway("devnet"); 18 | assertEquals("https://devnet-gateway.multiversx.com", props.getProxyUrl()); 19 | 20 | props.setGateway("testnet"); 21 | assertEquals("https://testnet-gateway.multiversx.com", props.getProxyUrl()); 22 | 23 | props.setGateway("mainnet"); 24 | assertEquals("https://gateway.multiversx.com", props.getProxyUrl()); 25 | 26 | props.setCustomProxyUrl("https://custom-api.com"); 27 | assertEquals("https://custom-api.com", props.getProxyUrl()); 28 | 29 | assertThrows(GatewayException.class, () -> props.setGateway("invalid")); 30 | } 31 | } -------------------------------------------------------------------------------- /src/test/java/io/ezalabs/multiversxspringbootstarterreactive/util/GasUtilsTest.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.util; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | 5 | import java.math.BigInteger; 6 | import org.junit.jupiter.api.Test; 7 | import io.ezalabs.multiversxspringbootstarterreactive.domain.transaction.PayloadData; 8 | 9 | class GasUtilsTest { 10 | 11 | @Test 12 | void computeGasCost() { 13 | var expectedCost = BigInteger.valueOf(92500); 14 | assertEquals(expectedCost, GasUtils.computeGasCost(PayloadData.fromString("crldev x elrond"))); 15 | 16 | var expectedCostEmpty = BigInteger.valueOf(70000); 17 | assertEquals(expectedCostEmpty, GasUtils.computeGasCost(PayloadData.empty())); 18 | } 19 | 20 | } -------------------------------------------------------------------------------- /src/test/java/io/ezalabs/multiversxspringbootstarterreactive/util/HexValidatorTest.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.util; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | import static org.junit.jupiter.api.Assertions.assertFalse; 5 | import static org.junit.jupiter.api.Assertions.assertTrue; 6 | 7 | import io.ezalabs.multiversxspringbootstarterreactive.config.constants.AddressConstants; 8 | import org.junit.jupiter.api.Test; 9 | 10 | class HexValidatorTest { 11 | 12 | @Test 13 | void hexValid() { 14 | assertTrue( 15 | HexValidator.isHexValid("bf86ad970aa3c93c2382889c0a4fba4728b5b851634d57ccd65dcddeda8c8bb0", AddressConstants.PUBKEY_HEX_LENGTH)); 16 | } 17 | 18 | @Test 19 | void hexInvalid() { 20 | assertFalse(HexValidator.isHexValid("bf86ad970aa3c93c2382889c0a4fba4728b5b851634d57ccd65dcddeda8b0", AddressConstants.PUBKEY_HEX_LENGTH)); 21 | } 22 | 23 | @Test 24 | void processNumberHexARg() { 25 | assertEquals("034851", HexValidator.processNumberHexArgument("34851")); 26 | assertEquals("5408", HexValidator.processNumberHexArgument("5408")); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /src/test/java/io/ezalabs/multiversxspringbootstarterreactive/util/PemUtilsTest.java: -------------------------------------------------------------------------------- 1 | package io.ezalabs.multiversxspringbootstarterreactive.util; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | import static org.junit.jupiter.api.Assertions.assertThrows; 5 | import static org.mockito.Mockito.when; 6 | 7 | import io.ezalabs.multiversxspringbootstarterreactive.error.exception.InvalidPemFileException; 8 | import java.io.FileInputStream; 9 | import java.io.IOException; 10 | import org.junit.jupiter.api.Test; 11 | import org.mockito.Mockito; 12 | import org.springframework.core.io.buffer.DataBuffer; 13 | import org.springframework.http.codec.multipart.FilePart; 14 | import org.springframework.util.ResourceUtils; 15 | import reactor.core.publisher.Flux; 16 | import reactor.test.StepVerifier; 17 | 18 | class PemUtilsTest { 19 | 20 | @Test 21 | void extractKeyHex_fromFile() throws IOException { 22 | var pemFile = ResourceUtils.getFile("classpath:devnetAccount1.pem"); 23 | var expected = "8442d0bcadbae1b75eff1165f1e3a61f120bddbb440393d8ba3c366342ee4f62"; 24 | 25 | assertEquals(expected, PemUtils.extractKeyHex(pemFile)); 26 | } 27 | 28 | @Test 29 | void extractKeyHex_invalidFile() throws IOException { 30 | var pemFile = ResourceUtils.getFile("classpath:invalid.pem"); 31 | 32 | assertThrows(InvalidPemFileException.class, () -> PemUtils.extractKeyHex(pemFile)); 33 | } 34 | 35 | @Test 36 | void extractKeyHex_fromFilePart() throws IOException { 37 | var pemFile = ResourceUtils.getFile("classpath:devnetAccount1.pem"); 38 | 39 | var pemFilePart = Mockito.mock(FilePart.class); 40 | var dataBuffer = Mockito.mock(DataBuffer.class); 41 | 42 | when(dataBuffer.asInputStream()).thenReturn(new FileInputStream(pemFile)); 43 | when(pemFilePart.content()).thenReturn(Flux.just(dataBuffer)); 44 | 45 | var expected = "8442d0bcadbae1b75eff1165f1e3a61f120bddbb440393d8ba3c366342ee4f62"; 46 | 47 | StepVerifier.create(PemUtils.extractKeyHex(pemFilePart)) 48 | .assertNext(key -> assertEquals(expected, key)) 49 | .verifyComplete(); 50 | } 51 | 52 | } -------------------------------------------------------------------------------- /src/test/resources/devnetAccount1.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY for erd1h7r2m9c250yncguz3zwq5na6gu5ttwz3vdx40nxkthxaak5v3wcqtpkvkj----- 2 | ODQ0MmQwYmNhZGJhZTFiNzVlZmYxMTY1ZjFlM2E2MWYxMjBiZGRiYjQ0MDM5M2Q4 3 | YmEzYzM2NjM0MmVlNGY2MmJmODZhZDk3MGFhM2M5M2MyMzgyODg5YzBhNGZiYTQ3 4 | MjhiNWI4NTE2MzRkNTdjY2Q2NWRjZGRlZGE4YzhiYjA= 5 | -----END PRIVATE KEY for erd1h7r2m9c250yncguz3zwq5na6gu5ttwz3vdx40nxkthxaak5v3wcqtpkvkj----- -------------------------------------------------------------------------------- /src/test/resources/invalid.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY for erd1h7r2m9c250yncguz3zwq5na6gu5ttwz3vdx40nxkthxaak5v3wcqtpkvkj----- 2 | ODQ0MmQwYmNhZGJhZTFiNzVlZmYxMTY1ZjFlM2E2MWYxMjBiZGRiYjQ0MDM5M2Q4 3 | YmEzYzM2NjM0MmV--------INVALID-----------MyMzgyODg5YzBhNGZiYTQ3 4 | MjhiNWI4NTE2MzRkNTdjY2Q2NWRjZGRlZGE4YzhiYjA= 5 | -----END PRIVATE KEY for erd1h7r2m9c250yncguz3zwq5na6gu5ttwz3vdx40nxkthxaak5v3wcqtpkvkj----- -------------------------------------------------------------------------------- /src/test/resources/validPemButNotValidPrivateKey.pem: -------------------------------------------------------------------------------- 1 | -----BEGIN PRIVATE KEY for rd1h7r2m9c250yncguz3zwq5na6gu5ttwz3vdx40nxkthxaak5v3wcqtpkvkj----- 2 | ODQ0MmQwYmNhZGJhZTFiNzVlZmYxMTY1ZjFlM2E2MWYxMjBiZGRiYjQ0MDM5M2Q4 3 | YmEzYzM2NjM0MmVlNGY2MmJmODZhZDk3MGFhM2M5M2MyMzgyODg5YzBhNGZiYTQ3 4 | MjhiNWI4NTE2MzRkNTdjY2Q2NWRjZGRlZGE4YzhiYjA= 5 | -----END PRIVATE KEY for erd1h7r2m9c250yncguz3zwq5na6gu5ttwz3vdx40nxkthxaak5v3wcqtpkvkj----- --------------------------------------------------------------------------------