Example #1
0
        public TonClientRustAdapter(string configJson, ILogger <TonClientRustAdapter> logger)
        {
            _logger = logger;
            _logger.LogTrace("Creating context with options: {config}", configJson);
            using var optionsInteropJson = configJson.ToInteropStringDisposable();
            IntPtr resultPtr = RustInteropInterface.tc_create_context(optionsInteropJson);

            _logger.LogTrace("Reading context creation result");
            InteropString resultInterop = RustInteropInterface.tc_read_string(resultPtr);
            var           resultJson    = resultInterop.ToString();

            RustInteropInterface.tc_destroy_string(resultPtr);
            _logger.LogTrace("Got context creation result: {result}", resultJson);

            var createContextResult = JsonSerializer.Deserialize <CreateContextResponse>(resultJson, JsonOptionsProvider.JsonSerializerOptions);

            if (createContextResult?.ContextNumber == null)
            {
                throw new TonClientException($"Raw result: {resultJson}", new NullReferenceException("Result of context creation or context number is null"));
            }
            ClientError error = createContextResult.Error;

            if (error != null)
            {
                throw TonClientException.CreateExceptionWithCodeWithData(error.Code, error.Data?.ToObject <Dictionary <string, object> >(), error.Message);
            }

            _contextNumber = (uint)createContextResult.ContextNumber;
        }
 private static TonClientException CreateException(ClientError clientError, Exception innerException, Func <string> errorRawTextFunc)
 {
     return(clientError == null
         ? new TonClientException($"Raw result: {errorRawTextFunc()}",
                                  innerException ?? new NullReferenceException("Result of error response is null or not valid"))
         : TonClientException.CreateExceptionWithCodeWithData(clientError.Code, clientError.Data.ToObject <Dictionary <string, object> >(),
                                                              clientError.Message));
 }
        public void FromJson_Should_Use_Code_From_Json()
        {
            var json = JsonConvert.SerializeObject(new
            {
                code = 1001
            });

            var exception = TonClientException.FromJson(json);

            Assert.NotNull(exception);
            Assert.Equal(1001, exception.Code);
            Assert.NotEmpty(exception.Message);
            Assert.Empty(exception.Data);
        }
        public void FromJson_Should_Use_Data_From_Json()
        {
            var json = JsonConvert.SerializeObject(new
            {
                code    = 1001,
                message = "test message",
                data    = new
                {
                    version = "1.0.0"
                }
            });

            var exception = TonClientException.FromJson(json);

            Assert.NotNull(exception);
            Assert.Equal(1001, exception.Code);
            Assert.Equal("test message", exception.Message);
            Assert.True(exception.Data.Contains("version"));
            Assert.Equal("1.0.0", exception.Data["version"]);
        }
 public void FromJson_Should_Return_Exception_Even_If_Json_Is_Invalid(string json)
 {
     Assert.NotNull(TonClientException.FromJson(json));
 }
Example #6
0
        public async Task <string> RustRequest(string method, string requestJson, Action <string, uint> callback = null,
                                               CancellationToken cancellationToken = default)
        {
            _requestId = _requestId == uint.MaxValue ? 0 : _requestId + 1;

            var cts = new TaskCompletionSource <string>();

            var callbackDelegate = new CallbackDelegate((requestId, responseInteropString, responseType, finished) =>
            {
                var responseJson = responseInteropString.ToString();
                _logger.LogTrace("Got request response context:{context} request:{request} type:{responseType} finished:{finished} body:{body}",
                                 _contextNumber, requestId, ((ResponseType)responseType).ToString(), finished, responseJson);

                lock (_dictLock)
                {
                    if (!_delegatesDict.ContainsKey(requestId))
                    {
                        _logger.LogWarning("Request {request} was not found in this context {context}", requestId, _contextNumber);
                        return;
                    }

                    if (finished)
                    {
                        RemoveDelegateFromDict(requestId);
                    }
                }

                switch ((ResponseType)responseType)
                {
                case ResponseType.Success:
                    cts.SetResult(responseJson);
                    break;

                case ResponseType.Error:
                    TonClientException exception = TonExceptionSerializer.GetTonClientExceptionByResponse(responseJson);
                    cts.SetException(exception);
                    break;

                // do nothing
                case ResponseType.Nop:
                    break;

                // it is callback if responseType>=3
                default:
                    _logger.LogTrace("Sending callback context:{context} request:{request} body:{body}", _contextNumber, requestId, responseJson);
                    callback?.Invoke(responseJson, responseType);
                    break;
                }
            });

            lock (_dictLock)
            {
                _delegatesDict.Add(_requestId, callbackDelegate);
            }

            try
            {
                _logger.LogTrace("Sending request: context:{context} request:{request} method:{method} body:{body}", _contextNumber, _requestId, method,
                                 requestJson);
                using var methodInteropString     = method.ToInteropStringDisposable();
                using var paramsJsonInteropString = requestJson.ToInteropStringDisposable();
                RustInteropInterface.tc_request(_contextNumber, methodInteropString, paramsJsonInteropString, _requestId, callbackDelegate);
            }
            catch (Exception ex)
            {
                RemoveDelegateFromDict(_requestId);
                throw new TonClientException("Sending request error", ex);
            }

            Task executeOrTimeout = await Task.WhenAny(cts.Task, Task.Delay(_coreExecutionTimeOut, cancellationToken));

            if (cts.Task == executeOrTimeout)
            {
                return(await cts.Task);
            }

            // log error with ids and throw TonClientException
            _logger.LogError("Request execution timeout expired or cancellation requested. Context:{context} request:{request}", _contextNumber, _requestId);
            throw new TonClientException("Execution timeout expired or cancellation requested");
        }