diff --git a/csharp/src/Workflow.Abstractions/Workflows/ISwapWorkflow.cs b/csharp/src/Workflow.Abstractions/Workflows/ISwapWorkflow.cs index 7a63eac3..40cbbeb2 100644 --- a/csharp/src/Workflow.Abstractions/Workflows/ISwapWorkflow.cs +++ b/csharp/src/Workflow.Abstractions/Workflows/ISwapWorkflow.cs @@ -3,7 +3,6 @@ namespace Train.Solver.Workflow.Abstractions.Workflows; -[Workflow] public interface ISwapWorkflow { [WorkflowSignal] diff --git a/csharp/src/Workflow.Swap/Extensions/TrainSolverBuilderExtensions.cs b/csharp/src/Workflow.Swap/Extensions/TrainSolverBuilderExtensions.cs index acf38b60..9a182937 100644 --- a/csharp/src/Workflow.Swap/Extensions/TrainSolverBuilderExtensions.cs +++ b/csharp/src/Workflow.Swap/Extensions/TrainSolverBuilderExtensions.cs @@ -5,15 +5,16 @@ using Train.Solver.Workflow.Common.Helpers; using Train.Solver.Workflow.Swap.Activities; using Train.Solver.Workflow.Swap.Workflows; +using Train.Solver.Workflow.Swap.Workflows.RedeemWorkflows; namespace Train.Solver.Workflow.Swap.Extensions; public static class TrainSolverBuilderExtensions { public static TrainSolverBuilder WithCoreWorkflows( - this TrainSolverBuilder builder) + this TrainSolverBuilder builder) { - var temporalBuilder = builder.Services + builder.Services .AddHostedTemporalWorker(Constants.CoreTaskQueue) .AddTransientActivities() .AddTransientActivities() diff --git a/csharp/src/Workflow.Swap/Workflows/BaseWorkflow.cs b/csharp/src/Workflow.Swap/Workflows/BaseWorkflow.cs new file mode 100644 index 00000000..001500f7 --- /dev/null +++ b/csharp/src/Workflow.Swap/Workflows/BaseWorkflow.cs @@ -0,0 +1,42 @@ +using Temporalio.Workflows; +using Train.Solver.Workflow.Abstractions.Activities; +using Train.Solver.Workflow.Abstractions.Models; +using static Train.Solver.Workflow.Common.Helpers.TemporalHelper; +using static Temporalio.Workflows.Workflow; +using Train.Solver.Workflow.Common; + +namespace Train.Solver.Workflow.Swap.Workflows; + +public abstract class BaseWorkflow +{ + public virtual async Task ExecuteTransactionAsync(TransactionRequest transactionRequest) + { + var confirmedTransaction = await ExecuteChildTransactionProcessorWorkflowAsync( + transactionRequest.Network.Type, + x => x.RunAsync(transactionRequest, new TransactionExecutionContext()), + new ChildWorkflowOptions + { + Id = BuildProcessorId( + transactionRequest.Network.Name, + transactionRequest.Type, + NewGuid()), + TaskQueue = transactionRequest.Network.Type.ToString(), + }); + + await ExecuteActivityAsync( + (ISwapActivities x) => + x.CreateSwapTransactionAsync(transactionRequest.SwapId, transactionRequest.Type, confirmedTransaction), + DefaultActivityOptions(Constants.CoreTaskQueue)); + + await ExecuteActivityAsync( + (ISwapActivities x) => x.UpdateExpensesAsync( + confirmedTransaction.NetworkName, + confirmedTransaction.FeeAsset, + confirmedTransaction.FeeAmount.ToString(), + confirmedTransaction.Asset, + transactionRequest.Type), + DefaultActivityOptions(Constants.CoreTaskQueue)); + + return confirmedTransaction; + } +} diff --git a/csharp/src/Workflow.Swap/Workflows/EventListenerWorkflow.cs b/csharp/src/Workflow.Swap/Workflows/EventListenerWorkflow.cs index 3d374341..1ce2c075 100644 --- a/csharp/src/Workflow.Swap/Workflows/EventListenerWorkflow.cs +++ b/csharp/src/Workflow.Swap/Workflows/EventListenerWorkflow.cs @@ -45,17 +45,17 @@ public async Task RunAsync( var solverWallets = await ExecuteActivityAsync( (ISwapActivities x) => x.GetRouteSourceWalletsAsync( network.Type), - new() - { - TaskQueue = Constants.CoreTaskQueue, - StartToCloseTimeout = TimeSpan.FromSeconds(20), - ScheduleToCloseTimeout = TimeSpan.FromMinutes(20), - RetryPolicy = new() - { - InitialInterval = TimeSpan.FromSeconds(5), - BackoffCoefficient = 1f, - } - }); + new() + { + TaskQueue = Constants.CoreTaskQueue, + StartToCloseTimeout = TimeSpan.FromSeconds(20), + ScheduleToCloseTimeout = TimeSpan.FromMinutes(20), + RetryPolicy = new() + { + InitialInterval = TimeSpan.FromSeconds(5), + BackoffCoefficient = 1f, + } + }); while (!Temporalio.Workflows.Workflow.CancellationToken.IsCancellationRequested) { diff --git a/csharp/src/Workflow.Swap/Workflows/RedeemWorkflows/AztecRedeemWorkflow.cs b/csharp/src/Workflow.Swap/Workflows/RedeemWorkflows/AztecRedeemWorkflow.cs new file mode 100644 index 00000000..c4703fb3 --- /dev/null +++ b/csharp/src/Workflow.Swap/Workflows/RedeemWorkflows/AztecRedeemWorkflow.cs @@ -0,0 +1,12 @@ +using Train.Solver.Workflow.Abstractions.Models; + +namespace Train.Solver.Workflow.Swap.Workflows.RedeemWorkflows; + +public class AztecRedeemWorkflow : BaseWorkflow +{ + public async Task RedeemAsync(TransactionRequest destinationRedeemRequest) + { + // Redeem LP funds + await ExecuteTransactionAsync(destinationRedeemRequest); + } +} diff --git a/csharp/src/Workflow.Swap/Workflows/RedeemWorkflows/SourceDestinationRedeemWorkflow.cs b/csharp/src/Workflow.Swap/Workflows/RedeemWorkflows/SourceDestinationRedeemWorkflow.cs new file mode 100644 index 00000000..c1136918 --- /dev/null +++ b/csharp/src/Workflow.Swap/Workflows/RedeemWorkflows/SourceDestinationRedeemWorkflow.cs @@ -0,0 +1,21 @@ +using Train.Solver.Workflow.Abstractions.Models; + +namespace Train.Solver.Workflow.Swap.Workflows.RedeemWorkflows; + +public class SourceDestinationRedeemWorkflow : BaseWorkflow +{ + public async Task RedeemAsync( + TransactionRequest sourceRedeemRequest, + TransactionRequest destinationRedeemRequest) + { + // Redeem user funds + var redeemInDestinationTask = ExecuteTransactionAsync(destinationRedeemRequest); + + // Redeem LP funds + var redeemInSourceTask = ExecuteTransactionAsync(sourceRedeemRequest); + + await Task.WhenAll( + redeemInDestinationTask, + redeemInSourceTask); + } +} \ No newline at end of file diff --git a/csharp/src/Workflow.Swap/Workflows/SwapWorkflow.cs b/csharp/src/Workflow.Swap/Workflows/SwapWorkflow.cs index ff5d89b5..2e0cd562 100644 --- a/csharp/src/Workflow.Swap/Workflows/SwapWorkflow.cs +++ b/csharp/src/Workflow.Swap/Workflows/SwapWorkflow.cs @@ -11,11 +11,12 @@ using Train.Solver.Workflow.Abstractions.Workflows; using Train.Solver.Workflow.Common; using Train.Solver.Common.Extensions; +using Train.Solver.Workflow.Swap.Workflows.RedeemWorkflows; namespace Train.Solver.Workflow.Swap.Workflows; [Workflow] -public class SwapWorkflow : ISwapWorkflow +public class SwapWorkflow : BaseWorkflow, ISwapWorkflow { private static readonly TimeSpan _maxAcceptableCommitTimelockPeriod = TimeSpan.FromMinutes(45); private static readonly TimeSpan _minAcceptableTimelockPeriod = TimeSpan.FromMinutes(15); @@ -225,46 +226,49 @@ await ExecuteTransactionAsync(new TransactionRequest() return; } - // Redeem user funds - var redeemInDestinationTask = ExecuteTransactionAsync(new TransactionRequest() + var sourceRedeemRequest = new TransactionRequest() { PrepareArgs = new HTLCRedeemTransactionPrepareRequest { CommitId = _htlcCommitMessage!.CommitId, - Asset = _htlcCommitMessage.DestinationAsset, + Asset = _htlcCommitMessage.SourceAsset, Secret = hashlock.Secret, - DestinationAddress = _htlcCommitMessage.DestinationAddress, - SenderAddress = _destinationWalletAddress + DestinationAddress = _sourceWalletAddress, + SenderAddress = _htlcCommitMessage.SenderAddress }.ToJson(), Type = TransactionType.HTLCRedeem, - Network = _destinationNetwork, - FromAddress = _destinationWalletAddress!, + Network = _sourceNetwork, + FromAddress = _sourceWalletAddress!, SignerAgentUrl = _sourceWalletAgentUrl!, SwapId = _swapId - }); + }; - // Redeem LP funds - var redeemInSourceTask = ExecuteTransactionAsync(new TransactionRequest() + var destinationRedeemRequest = new TransactionRequest() { PrepareArgs = new HTLCRedeemTransactionPrepareRequest { CommitId = _htlcCommitMessage!.CommitId, - Asset = _htlcCommitMessage.SourceAsset, + Asset = _htlcCommitMessage.DestinationAsset, Secret = hashlock.Secret, - DestinationAddress = _sourceWalletAddress, - SenderAddress = _htlcCommitMessage.SenderAddress + DestinationAddress = _htlcCommitMessage.DestinationAddress, + SenderAddress = _destinationWalletAddress }.ToJson(), Type = TransactionType.HTLCRedeem, - Network = _sourceNetwork, - FromAddress = _sourceWalletAddress!, + Network = _destinationNetwork, + FromAddress = _destinationWalletAddress!, SignerAgentUrl = _sourceWalletAgentUrl!, SwapId = _swapId - }); - - await Task.WhenAll( - redeemInDestinationTask, - redeemInSourceTask); + }; + switch (_sourceNetwork.Type) + { + case NetworkType.Aztec: + await new AztecRedeemWorkflow().RedeemAsync(destinationRedeemRequest); + break; + default: + await new SourceDestinationRedeemWorkflow().RedeemAsync(sourceRedeemRequest, destinationRedeemRequest); + break; + } } catch (Exception e) when (TemporalException.IsCanceledException(e)) { @@ -338,35 +342,4 @@ public Task LockCommitedAsync(HTLCLockEventMessage message) return Task.CompletedTask; } - - private async Task ExecuteTransactionAsync(TransactionRequest transactionRequest) - { - var confirmedTransaction = await ExecuteChildTransactionProcessorWorkflowAsync( - transactionRequest.Network.Type, - x => x.RunAsync(transactionRequest, new TransactionExecutionContext()), - new ChildWorkflowOptions - { - Id = BuildProcessorId( - transactionRequest.Network.Name, - transactionRequest.Type, - NewGuid()), - TaskQueue = transactionRequest.Network.Type.ToString(), - }); - - await ExecuteActivityAsync( - (ISwapActivities x) => - x.CreateSwapTransactionAsync(transactionRequest.SwapId, transactionRequest.Type, confirmedTransaction), - DefaultActivityOptions(Constants.CoreTaskQueue)); - - await ExecuteActivityAsync( - (ISwapActivities x) => x.UpdateExpensesAsync( - confirmedTransaction.NetworkName, - confirmedTransaction.FeeAsset, - confirmedTransaction.FeeAmount.ToString(), - confirmedTransaction.Asset, - transactionRequest.Type), - DefaultActivityOptions(Constants.CoreTaskQueue)); - - return confirmedTransaction; - } }