public override Task StartWaitForRedeemBySomeoneAsync( Swap swap, CancellationToken cancellationToken = default) { Log.Debug("Wait redeem for swap {@swapId}", swap.Id); // start redeem control async _ = Fa12SwapRedeemedHelper.StartSwapRedeemedControlAsync( swap: swap, currency: Fa12Config, tezos: XtzConfig, refundTimeUtc: swap.TimeStamp.ToUniversalTime().AddSeconds(DefaultAcceptorLockTimeInSeconds), interval: TimeSpan.FromSeconds(30), cancelOnlyIfRefundTimeReached: true, redeemedHandler: RedeemBySomeoneCompletedEventHandler, canceledHandler: RedeemBySomeoneCanceledEventHandler, cancellationToken: cancellationToken); return(Task.CompletedTask); }
public override Task StartWaitForRedeemAsync( Swap swap, CancellationToken cancellationToken = default) { var lockTimeInSeconds = swap.IsInitiator ? DefaultInitiatorLockTimeInSeconds : DefaultAcceptorLockTimeInSeconds; // start redeem control async _ = Fa12SwapRedeemedHelper.StartSwapRedeemedControlAsync( swap: swap, currency: Fa12Config, tezos: XtzConfig, refundTimeUtc: swap.TimeStamp.ToUniversalTime().AddSeconds(lockTimeInSeconds), interval: TimeSpan.FromSeconds(30), cancelOnlyIfRefundTimeReached: true, redeemedHandler: RedeemCompletedEventHandler, canceledHandler: RedeemCanceledEventHandler, cancellationToken: cancellationToken); return(Task.CompletedTask); }
public override async Task RedeemAsync( Swap swap, CancellationToken cancellationToken = default) { var fa12 = Fa12Config; var secretResult = await Fa12SwapRedeemedHelper .IsRedeemedAsync( swap : swap, currency : fa12, tezos : XtzConfig, attempts : TezosSwap.MaxRedeemCheckAttempts, attemptIntervalInSec : TezosSwap.RedeemCheckAttemptIntervalInSec, cancellationToken : cancellationToken) .ConfigureAwait(false); if (!secretResult.HasError && secretResult.Value != null) { await RedeemConfirmedEventHandler(swap, null, cancellationToken) .ConfigureAwait(false); return; } if (swap.StateFlags.HasFlag(SwapStateFlags.IsRedeemBroadcast) && swap.RedeemTx != null && swap.RedeemTx.CreationTime != null && swap.RedeemTx.CreationTime.Value.ToUniversalTime() + TimeSpan.FromMinutes(5) > DateTime.UtcNow) { // redeem already broadcast _ = TrackTransactionConfirmationAsync( swap: swap, currency: fa12, dataRepository: Fa12Account.DataRepository, txId: swap.RedeemTx.Id, confirmationHandler: RedeemConfirmedEventHandler, cancellationToken: cancellationToken); return; } // check already refunded by initiator if (swap.IsAcceptor && swap.TimeStamp.ToUniversalTime().AddSeconds(DefaultInitiatorLockTimeInSeconds) < DateTime.UtcNow) { var isRefundedByParty = await Fa12SwapRefundedHelper .IsRefundedAsync(swap, fa12, XtzConfig, cancellationToken) .ConfigureAwait(false); if (isRefundedByParty != null && !isRefundedByParty.HasError && isRefundedByParty.Value) { swap.StateFlags |= SwapStateFlags.IsUnsettled; await UpdateSwapAsync(swap, SwapStateFlags.IsUnsettled, cancellationToken) .ConfigureAwait(false); return; } } if (swap.IsInitiator) { var redeemDeadline = swap.TimeStamp.ToUniversalTime().AddSeconds(DefaultAcceptorLockTimeInSeconds) - RedeemTimeReserve; if (DateTime.UtcNow > redeemDeadline) { Log.Error("Redeem dedline reached for swap {@swap}", swap.Id); return; } } Log.Debug("Create redeem for swap {@swapId}", swap.Id); var walletAddress = await TezosAccount .GetAddressAsync(swap.RedeemFromAddress, cancellationToken) .ConfigureAwait(false); if (walletAddress == null) { Log.Error("Can't get address {@address} for redeem from local db", swap.RedeemFromAddress); return; } if (walletAddress == null) { Log.Error("Insufficient funds for redeem"); return; } var feeAmountInMtz = fa12.RedeemFee + fa12.RevealFee; var storageLimitInMtz = fa12.RedeemStorageLimit * fa12.StorageFeeMultiplier; if (walletAddress.Balance.ToMicroTez() < feeAmountInMtz + storageLimitInMtz) { Log.Error("Insufficient funds for redeem"); return; } var redeemTx = new TezosTransaction { Currency = XtzConfig.Name, CreationTime = DateTime.UtcNow, From = walletAddress.Address, To = fa12.SwapContractAddress, Amount = 0, Fee = fa12.RedeemFee + fa12.RevealFee, GasLimit = fa12.RedeemGasLimit, StorageLimit = fa12.RedeemStorageLimit, Params = CreateRedeemParams(swap), Type = BlockchainTransactionType.Output | BlockchainTransactionType.SwapRedeem, UseRun = true, UseSafeStorageLimit = true, UseOfflineCounter = true }; try { await TezosAccount.AddressLocker .LockAsync(redeemTx.From, cancellationToken) .ConfigureAwait(false); using var securePublicKey = TezosAccount.Wallet .GetPublicKey(XtzConfig, walletAddress.KeyIndex, walletAddress.KeyType); // fill operation var(fillResult, isRunSuccess, hasReveal) = await redeemTx .FillOperationsAsync( securePublicKey : securePublicKey, tezosConfig : XtzConfig, headOffset : TezosConfig.HeadOffset, cancellationToken : cancellationToken) .ConfigureAwait(false); var signResult = await SignTransactionAsync(redeemTx, cancellationToken) .ConfigureAwait(false); if (!signResult) { Log.Error("Transaction signing error"); return; } swap.RedeemTx = redeemTx; swap.StateFlags |= SwapStateFlags.IsRedeemSigned; await UpdateSwapAsync(swap, SwapStateFlags.IsRedeemSigned, cancellationToken) .ConfigureAwait(false); await BroadcastTxAsync(swap, redeemTx, cancellationToken) .ConfigureAwait(false); } catch { throw; } finally { TezosAccount.AddressLocker.Unlock(redeemTx.From); } swap.RedeemTx = redeemTx; swap.StateFlags |= SwapStateFlags.IsRedeemBroadcast; await UpdateSwapAsync(swap, SwapStateFlags.IsRedeemBroadcast, cancellationToken) .ConfigureAwait(false); _ = TrackTransactionConfirmationAsync( swap: swap, currency: XtzConfig, dataRepository: Fa12Account.DataRepository, txId: redeemTx.Id, confirmationHandler: RedeemConfirmedEventHandler, cancellationToken: cancellationToken); }