All Downloads are FREE. Search and download functionalities are using the official Maven repository.

tech.deplant.java4ever.binding.EverSdk Maven / Gradle / Ivy

package tech.deplant.java4ever.binding;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import tech.deplant.java4ever.binding.ffi.EverSdkContext;
import tech.deplant.java4ever.binding.ffi.NativeMethods;
import tech.deplant.java4ever.binding.loader.DefaultLoader;
import tech.deplant.java4ever.binding.loader.DefaultLoaderContext;
import tech.deplant.java4ever.binding.loader.LibraryLoader;

import java.util.Arrays;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.*;
import java.util.function.Consumer;
import java.util.stream.Collectors;

/**
 * The type Ever sdk.
 */
public class EverSdk {
	/**
	 * The constant LOG_FORMAT.
	 */
	public final static String LOG_FORMAT = "CTX:%d REQ:%d FUNC:%s %s:%s";
	private final static System.Logger logger = System.getLogger(EverSdk.class.getName());
	private final static Map contexts = new ConcurrentHashMap<>();
	/**
	 * Timeout for the waiting of async operations.
	 */
	public static long timeout = 600_000L;

	/**
	 * Context config client . client config.
	 *
	 * @param contextId the context id
	 * @return the client . client config
	 */
	public static Client.ClientConfig contextConfig(int contextId) {
		return contexts.get(contextId).config();
	}

	/**
	 * Gets default workchain id.
	 *
	 * @param contextId the context id
	 * @return the default workchain id
	 */
	public static long getDefaultWorkchainId(int contextId) {
		return switch (contextConfig(contextId).abi()) {
			case Client.AbiConfig abiConfig -> Objects.requireNonNullElse(abiConfig.workchain(), 0L);
			case null -> 0L;
		};
	}

	/**
	 * Load.
	 */
	public static void load() {
		load(DefaultLoaderContext.SINGLETON(ClassLoader.getSystemClassLoader()));
	}

	/**
	 * Load.
	 *
	 * @param loader the loader
	 */
	public static void load(LibraryLoader loader) {
		loader.load();
	}

	/**
	 * Async method to call EVER-SDK that do not return responses. It will response as soon as call is sent.
	 *
	 * @param 

function params type parameter * @param contextId config context id * @param functionName EVER-SDK function name * @param functionInputs EVER-SDK function inputs * @return the completable future with generic result type * @throws EverSdkException the ever sdk exception */ public static

CompletableFuture asyncVoid(final int contextId, final String functionName, final P functionInputs) throws EverSdkException { return contexts.get(contextId).callAsync(functionName, functionInputs, Void.class, null, null); } /** * Async method to get future result from EVER-SDK * * @param result type parameter * @param

function params type parameter * @param contextId config context id * @param functionName EVER-SDK function name * @param functionInputs EVER-SDK function inputs * @param outputClass EVER-SDK output class * @return the completable future with generic result type * @throws EverSdkException the ever sdk exception */ public static CompletableFuture async(final int contextId, final String functionName, final P functionInputs, final Class outputClass) throws EverSdkException { return contexts.get(contextId).callAsync(functionName, functionInputs, outputClass, null, null); } /** * Async method to get future result from EVER-SDK with additional parameter to receive recurring events from EVER-SDK * * @param result type parameter * @param

function params type parameter * @param contextId config context id * @param functionName EVER-SDK function name * @param functionInputs EVER-SDK function inputs * @param outputClass EVER-SDK output class * @param eventConsumer Java Consumer (lambda-function) that accepts JsonNode object returned by EVER-SDK * @return the completable future with generic result type * @throws EverSdkException the ever sdk exception */ public static CompletableFuture asyncCallback(final int contextId, final String functionName, final P functionInputs, final Class outputClass, Consumer eventConsumer) throws EverSdkException { return contexts.get(contextId).callAsync(functionName, functionInputs, outputClass, eventConsumer, null); } /** * Async method to get future result from EVER-SDK with additional parameter to receive AppObject callbacks. * * @param result type parameter * @param

function params type parameter * @param contextId config context id * @param functionName EVER-SDK function name * @param functionInputs EVER-SDK function inputs * @param outputClass EVER-SDK output class * @param appObject Pointer to AppObject implementation * @return the completable future with generic result type * @throws EverSdkException the ever sdk exception */ public static CompletableFuture asyncAppObject(final int contextId, final String functionName, final P functionInputs, final Class outputClass, AppObject appObject) throws EverSdkException { return contexts.get(contextId).callAsync(functionName, functionInputs, outputClass, null, appObject); } /** * Destroy. * * @param contextId the context id */ public static void destroy(int contextId) { NativeMethods.tcDestroyContext(contextId); } /** * Create default int. * * @return the int * @throws EverSdkException the ever sdk exception */ public static int createDefault() throws EverSdkException { return createWithJson("{}"); } /** * Creates a builder object that is used to precisely configure EVER-SDK before creating new context. * After specifying all needed configs in builder style, call build() to finish and create context_id * with EVER-SDK. * * @return the builder */ public static Builder builder() { return new Builder(); } /** * Helper method to create new context with only one setting - endpoint of the blockchain. * * @param endpoint the endpoint of the blockchain. * @return context_id for future usage * @throws EverSdkException the ever sdk exception */ public static int createWithEndpoint(String endpoint) throws EverSdkException { return createWithJson("{ \"network\":{ \"endpoints\": [\"%s\"] } }".formatted(endpoint)); } /** * Helper method to create new context from existing config object * * @param config config object * @return context_id for future usage * @throws EverSdkException the ever sdk exception */ public static int createWithConfig(Client.ClientConfig config) throws EverSdkException { var mergedConfig = new Client.ClientConfig(new Client.BindingConfig(DefaultLoader.BINDING_LIBRARY_NAME, DefaultLoader.BINDING_LIBRARY_VERSION), config.network(), config.crypto(), config.abi(), config.boc(), config.proofs(), config.localStoragePath()); String resultString = ""; ResultOfCreateContext createContextResponse; try { String mergedJson = JsonContext.SDK_JSON_MAPPER().writeValueAsString(mergedConfig); try { resultString = NativeMethods.tcCreateContext(mergedJson); createContextResponse = JsonContext.SDK_JSON_MAPPER() .readValue(resultString, ResultOfCreateContext.class); Optional contextId = Optional.ofNullable(createContextResponse.result()); if (contextId.isEmpty() || contextId.get() < 1) { logger.log(System.Logger.Level.ERROR, () -> "FUNC:sdk.tc_create_context result is empty!"); throw new EverSdkException(new EverSdkException.ErrorResult(-502, "FUNC:sdk.tc_create_context result is empty!")); } int ctxId = contextId.get(); contexts.put(ctxId, new EverSdkContext(ctxId, mergedConfig)); logger.log(System.Logger.Level.TRACE, () -> "FUNC:sdk.tc_create_context CTX:%d JSON:%s".formatted(ctxId, mergedJson)); return ctxId; } catch (JsonProcessingException e) { final String finalResultString = resultString; logger.log(System.Logger.Level.ERROR, () -> "FUNC:sdk.tc_create_context request deserialization failed! Exception: %s Result: %s".formatted( e, finalResultString)); throw new EverSdkException(new EverSdkException.ErrorResult(-501, "FUNC:sdk.tc_create_context request deserialization failed! " + e.getMessage() + finalResultString), e.getCause()); } } catch (JsonProcessingException e) { logger.log(System.Logger.Level.ERROR, () -> "EVER-SDK tc_create_context request serialization failed! Exception: %s Config: %s".formatted( e, mergedConfig)); throw new EverSdkException(new EverSdkException.ErrorResult(-502, "EVER-SDK tc_create_context request serialization failed!"), e.getCause()); } } /** * Helper method to create new context from existing JSON config * * @param configJson json text that contains config parameters * @return context_id for future usage * @throws EverSdkException the ever sdk exception */ public static int createWithJson(String configJson) throws EverSdkException { try { return createWithConfig(JsonContext.SDK_JSON_MAPPER().readValue(configJson, Client.ClientConfig.class)); } catch (JsonProcessingException e) { logger.log(System.Logger.Level.ERROR, () -> "EVER-SDK tc_create_context request serialization failed! Exception: %s Config: %s".formatted( e, configJson)); throw new EverSdkException(new EverSdkException.ErrorResult(-502, "EVER-SDK tc_create_context request serialization failed!"), e.getCause()); } } public static Processing.ResultOfProcessMessage sendExternalMessage(int contextId, String dstAddress, Abi.ABI abi, String stateInit, String messageBody, String optionalSrcAddress) throws EverSdkException { var message = EverSdk.await(Boc.encodeExternalInMessage(contextId, optionalSrcAddress, dstAddress, stateInit, messageBody, null)).message(); var request = EverSdk.await(Processing.sendMessage(contextId, message, abi, false, null)); return EverSdk.await(Processing.waitForTransaction(contextId, abi, message, request.shardBlockId(), false, request.sendingEndpoints(), null)); } /** * Helper method that awaits for completable future for timeout that * you can specify by issuing EverSdk.timeout = 60_000L. * All Java Futures possible errors are wrapped in EverSdkException. If you want to catch these errors, * catch errors -400, -408, -500 * * @param result type parameter * @param functionOutputs future result to wait for * @return returns result of the given type * @throws EverSdkException the ever sdk exception */ public static T await(CompletableFuture functionOutputs) throws EverSdkException { try { return functionOutputs.get(timeout, TimeUnit.MILLISECONDS); } catch (InterruptedException ex3) { logger.log(System.Logger.Level.ERROR, () -> "EVER-SDK Call interrupted! %s".formatted(ex3.toString())); throw new EverSdkException(new EverSdkException.ErrorResult(-400, "EVER-SDK call interrupted!"), ex3.getCause()); } catch (TimeoutException ex4) { logger.log(System.Logger.Level.ERROR, () -> "EVER-SDK Call expired on Timeout! %s".formatted(ex4.toString())); throw new EverSdkException(new EverSdkException.ErrorResult(-408, "EVER-SDK call expired on Timeout!"), ex4.getCause()); } catch (ExecutionException e) { if (e.getCause() instanceof EverSdkException everEx) { throw new EverSdkException(everEx.errorResponse()); } else { logger.log(System.Logger.Level.ERROR, () -> "EVER-SDK Call unknown execution exception! %s".formatted(e.toString())); throw new EverSdkException(new EverSdkException.ErrorResult(-500, "EVER-SDK call expired on Timeout!"), e.getCause()); } } } /** * The type Result of create context. */ public record ResultOfCreateContext(Integer result, String error) { } /** * The type Builder. */ public static class Builder { private Boolean cacheInLocalStorage = null; // true private String localStoragePath = null; // "~/.tonclient" //Context.NetworkConfig private String[] endpoints = null; // "https://localhost"; @Deprecated private String serverAddress; // deprecated, use endpoints private Integer networkRetriesCount = null; // 5; private Integer messageRetriesCount = null; // 5; private Long messageProcessingTimeout = null; // 40000L; private Long waitForTimeout = null; // 40000L; private Long outOfSyncThreshold = null; // 15000L; private Long reconnectTimeout = null; // 12000L; private String accessKey = null; // //Context.CryptoConfig private Crypto.MnemonicDictionary mnemonicDictionary = null; // Crypto.MnemonicDictionary.English; private Integer mnemonicWordCount = null; // 12; private String hdkeyDerivationPath = null; // "m/44'/396'/0'/0/0"; //Context.AbiConfig; private Long workchain = null; // 0L; private Long messageExpirationTimeout = null; // 40000L; private Long messageExpirationTimeoutGrowFactor = null; // null; private Long cacheMaxSize = null; // 10240L; private Long maxReconnectTimeout = null; // 120000L; private Integer sendingEndpointCount = null; // 1; private Long latencyDetectionInterval = null; // 60000L; private Long maxLatency = null; // 60000L; private Long queryTimeout = null; // 60000L; private Client.NetworkQueriesProtocol queriesProtocol = null; // Client.NetworkQueriesProtocol.HTTP; private Long firstRempStatusTimeout = null; // 1000L; private Long nextRempStatusTimeout = null; // 5000L; private Long signatureId = null; /** * Instantiates a new Builder. */ public Builder() { } /** * Local storage path builder. * * @param localStoragePath the local storage path * @return the builder */ public Builder localStoragePath(String localStoragePath) { this.localStoragePath = localStoragePath; return this; } /** * Proofs cache in local storage builder. * * @param cacheInLocalStorage the cache in local storage * @return the builder */ public Builder proofsCacheInLocalStorage(boolean cacheInLocalStorage) { this.cacheInLocalStorage = cacheInLocalStorage; return this; } /** * Network max reconnect timeout builder. * * @param maxReconnectTimeout the max reconnect timeout * @return the builder */ public Builder networkMaxReconnectTimeout(Long maxReconnectTimeout) { this.maxReconnectTimeout = maxReconnectTimeout; return this; } /** * Network sending endpoint count builder. * * @param sendingEndpointCount the sending endpoint count * @return the builder */ public Builder networkSendingEndpointCount(Integer sendingEndpointCount) { this.sendingEndpointCount = sendingEndpointCount; return this; } /** * Network latency detection interval builder. * * @param latencyDetectionInterval the latency detection interval * @return the builder */ public Builder networkLatencyDetectionInterval(Long latencyDetectionInterval) { this.latencyDetectionInterval = latencyDetectionInterval; return this; } /** * Network max latency builder. * * @param maxLatency the max latency * @return the builder */ public Builder networkMaxLatency(Long maxLatency) { this.maxLatency = maxLatency; return this; } /** * Network query timeout builder. * * @param queryTimeout the query timeout * @return the builder */ public Builder networkQueryTimeout(Long queryTimeout) { this.queryTimeout = queryTimeout; return this; } /** * Network queries protocol builder. * * @param queriesProtocol the queries protocol * @return the builder */ public Builder networkQueriesProtocol(Client.NetworkQueriesProtocol queriesProtocol) { this.queriesProtocol = queriesProtocol; return this; } /** * Network first remp status timeout builder. * * @param firstRempStatusTimeout the first remp status timeout * @return the builder */ public Builder networkFirstRempStatusTimeout(Long firstRempStatusTimeout) { this.firstRempStatusTimeout = firstRempStatusTimeout; return this; } /** * Network next remp status timeout builder. * * @param nextRempStatusTimeout the next remp status timeout * @return the builder */ public Builder networkNextRempStatusTimeout(Long nextRempStatusTimeout) { this.nextRempStatusTimeout = nextRempStatusTimeout; return this; } /** * Network endpoints builder. * * @param endpoints the endpoints * @return the builder */ public Builder networkEndpoints(String... endpoints) { this.endpoints = endpoints; return this; } /** * Network server address builder. * * @param server_address the server address * @return the builder */ public Builder networkServerAddress(String server_address) { this.serverAddress = server_address; return this; } /** * Network retries count builder. * * @param network_retries_count the network retries count * @return the builder */ public Builder networkRetriesCount(Integer network_retries_count) { this.networkRetriesCount = network_retries_count; return this; } /** * Network message retries count builder. * * @param message_retries_count the message retries count * @return the builder */ public Builder networkMessageRetriesCount(Integer message_retries_count) { this.messageRetriesCount = message_retries_count; return this; } /** * Network message processing timeout builder. * * @param message_processing_timeout the message processing timeout * @return the builder */ public Builder networkMessageProcessingTimeout(Long message_processing_timeout) { this.messageProcessingTimeout = message_processing_timeout; return this; } /** * Network wait for timeout builder. * * @param wait_for_timeout the wait for timeout * @return the builder */ public Builder networkWaitForTimeout(Long wait_for_timeout) { this.waitForTimeout = wait_for_timeout; return this; } /** * Network out of sync threshold builder. * * @param out_of_sync_threshold the out of sync threshold * @return the builder */ public Builder networkOutOfSyncThreshold(Long out_of_sync_threshold) { this.outOfSyncThreshold = out_of_sync_threshold; return this; } /** * Network reconnect timeout builder. * * @param reconnect_timeout the reconnect timeout * @return the builder */ public Builder networkReconnectTimeout(Long reconnect_timeout) { this.reconnectTimeout = reconnect_timeout; return this; } /** * Network signature id builder. * * @param signatureId the signature id * @return the builder */ public Builder networkSignatureId(Long signatureId) { this.signatureId = signatureId; return this; } /** * Network access key builder. * * @param access_key the access key * @return the builder */ public Builder networkAccessKey(String access_key) { this.accessKey = access_key; return this; } /** * Crypto mnemonic dictionary builder. * * @param mnemonic_dictionary the mnemonic dictionary * @return the builder */ //cripto public Builder cryptoMnemonicDictionary(Crypto.MnemonicDictionary mnemonic_dictionary) { this.mnemonicDictionary = mnemonic_dictionary; return this; } /** * Crypto mnemonic word count builder. * * @param mnemonic_word_count the mnemonic word count * @return the builder */ public Builder cryptoMnemonicWordCount(Integer mnemonic_word_count) { this.mnemonicWordCount = mnemonic_word_count; return this; } /** * Crypto hdkey derivation path builder. * * @param hdkey_derivation_path the hdkey derivation path * @return the builder */ public Builder cryptoHdkeyDerivationPath(String hdkey_derivation_path) { this.hdkeyDerivationPath = hdkey_derivation_path; return this; } /** * Abi workchain builder. * * @param workchain the workchain * @return the builder */ //abi public Builder abiWorkchain(Long workchain) { this.workchain = workchain; return this; } /** * Abi message expiration timeout builder. * * @param message_expiration_timeout the message expiration timeout * @return the builder */ public Builder abiMessageExpirationTimeout(Long message_expiration_timeout) { this.messageExpirationTimeout = message_expiration_timeout; return this; } /** * Abi message expiration timeout grow factor builder. * * @param message_expiration_timeout_grow_factor the message expiration timeout grow factor * @return the builder */ public Builder abiMessageExpirationTimeoutGrowFactor(Long message_expiration_timeout_grow_factor) { this.messageExpirationTimeoutGrowFactor = message_expiration_timeout_grow_factor; return this; } /** * Boc cache max size builder. * * @param cacheMaxSize the cache max size * @return the builder */ public Builder bocCacheMaxSize(Long cacheMaxSize) { this.cacheMaxSize = cacheMaxSize; return this; } private Client.NetworkConfig buildNetworkConfig() { if (this.serverAddress == null && this.endpoints == null && this.networkRetriesCount == null && this.maxReconnectTimeout == null && this.reconnectTimeout == null && this.messageRetriesCount == null && this.messageProcessingTimeout == null && this.waitForTimeout == null && this.outOfSyncThreshold == null && this.sendingEndpointCount == null && this.latencyDetectionInterval == null && this.maxLatency == null && this.queryTimeout == null && this.queriesProtocol == null && this.firstRempStatusTimeout == null && this.nextRempStatusTimeout == null && this.signatureId == null && this.accessKey == null) { return null; } else { return new Client.NetworkConfig(this.serverAddress, this.endpoints, this.networkRetriesCount, this.maxReconnectTimeout, this.reconnectTimeout, this.messageRetriesCount, this.messageProcessingTimeout, this.waitForTimeout, this.outOfSyncThreshold, this.sendingEndpointCount, this.latencyDetectionInterval, this.maxLatency, this.queryTimeout, this.queriesProtocol, this.firstRempStatusTimeout, this.nextRempStatusTimeout, this.signatureId, this.accessKey); } } private Client.CryptoConfig buildCryptoConfig() { if (this.mnemonicDictionary == null && this.mnemonicWordCount == null && this.hdkeyDerivationPath == null) { return null; } else { return new Client.CryptoConfig(this.mnemonicDictionary, this.mnemonicWordCount, this.hdkeyDerivationPath); } } private Client.AbiConfig buildAbiConfig() { if (this.workchain == null && this.messageExpirationTimeout == null && this.messageExpirationTimeoutGrowFactor == null) { return null; } else { return new Client.AbiConfig(this.workchain, this.messageExpirationTimeout, this.messageExpirationTimeoutGrowFactor); } } private Client.BocConfig buildBocConfig() { if (this.cacheMaxSize == null) { return null; } else { return new Client.BocConfig(this.cacheMaxSize); } } private Client.ProofsConfig buildProofsConfig() { if (this.cacheInLocalStorage == null) { return null; } else { return new Client.ProofsConfig(this.cacheInLocalStorage); } } /** * Build int. * * @return the int * @throws EverSdkException the ever sdk exception */ public int build() throws EverSdkException { var config = new Client.ClientConfig(new Client.BindingConfig("java4ever", "3.0.0"), buildNetworkConfig(), buildCryptoConfig(), buildAbiConfig(), buildBocConfig(), buildProofsConfig(), this.localStoragePath); return createWithConfig(config); } } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy