public static Task CallSubstrate(this BackgroundService service, ILogger logger, PublicKey contractKey, string nodeEndpoint, Address from, byte[] privateKey, Func <IApplication, IExtrinsicCall> callGenerator) { var completionSource = new TaskCompletionSource(); Task.Run(async() => { SafeApplication application = SafeApplication.CreateApplication( ex => { logger.LogError(ex, "{ServiceName} substrate api failed", service.GetType().FullName); Interlocked.Exchange <TaskCompletionSource?>(ref completionSource, null)?.SetException(ex); }, logger, contractKey); try { application.Application.Connect(nodeEndpoint); var call = callGenerator(application.Application !); application.HealthCheck(TimeSpan.FromMinutes(10), () => { Interlocked.Exchange <TaskCompletionSource?>(ref completionSource, null)?.SetException(new TimeoutException()); application.Dispose(); }); var result = await application.Application.SignWaitRetryOnLowPriority(from, privateKey, call); application.CancelHealthCheck(); result.Switch(_ => { Interlocked.Exchange <TaskCompletionSource?>(ref completionSource, null)?.SetResult(); }, fail => { var error = fail.ErrorMessage(application.Application); logger.LogError("Failed to call substrate, {ErrorText}", error); Interlocked.Exchange <TaskCompletionSource?>(ref completionSource, null)?.SetException(new ApplicationException(error)); }); } catch (Exception ex) { Interlocked.Exchange <TaskCompletionSource?>(ref completionSource, null)?.SetException(ex); } finally { application.Dispose(); } }); return(completionSource.Task); }