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)); }
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"); }