public async Task <RefundClaimStatus> TryClaimRefundAsync(DepositDetails deposit, Address refundTo)
        {
            ulong now = _timestamper.EpochSeconds;

            if (!deposit.CanClaimRefund(now))
            {
                return(RefundClaimStatus.Empty);
            }

            Block?latestBlock = await _blockchainBridge.GetLatestBlockAsync();

            if (latestBlock == null)
            {
                return(RefundClaimStatus.Empty);
            }

            now = (ulong)latestBlock.Timestamp;
            if (!deposit.CanClaimRefund(now))
            {
                return(RefundClaimStatus.Empty);
            }

            Keccak depositId       = deposit.Deposit.Id;
            Keccak?transactionHash = deposit.ClaimedRefundTransaction?.Hash;

            if (transactionHash is null)
            {
                Address     provider    = deposit.DataAsset.Provider.Address;
                RefundClaim refundClaim = new RefundClaim(depositId, deposit.DataAsset.Id, deposit.Deposit.Units,
                                                          deposit.Deposit.Value, deposit.Deposit.ExpiryTime, deposit.Pepper, provider, refundTo);
                UInt256 gasPrice = await _gasPriceService.GetCurrentAsync();

                transactionHash = await _refundService.ClaimRefundAsync(refundTo, refundClaim, gasPrice);

                if (transactionHash is null)
                {
                    if (_logger.IsError)
                    {
                        _logger.Error("There was an error when trying to claim refund (no transaction hash returned).");
                    }
                    return(RefundClaimStatus.Empty);
                }

                deposit.AddClaimedRefundTransaction(TransactionInfo.Default(transactionHash, 0, gasPrice,
                                                                            _refundService.GasLimit, _timestamper.EpochSeconds));
                await _depositRepository.UpdateAsync(deposit);

                if (_logger.IsInfo)
                {
                    _logger.Info($"Claimed a refund for deposit: '{depositId}', gas price: {gasPrice} wei, transaction hash: '{transactionHash}' (awaits a confirmation).");
                }
            }

            bool confirmed = await TryConfirmClaimAsync(deposit, string.Empty);

            return(confirmed
                ? RefundClaimStatus.Confirmed(transactionHash)
                : RefundClaimStatus.Unconfirmed(transactionHash));
        }
 public void Setup()
 {
     Prepare();
     _claimedRefundTransactionHash = TestItem.KeccakA;
     _refundService = Substitute.For <IRefundService>();
     _refundService.ClaimRefundAsync(Arg.Any <Address>(), Arg.Any <RefundClaim>())
     .Returns(_claimedRefundTransactionHash);
     _refundService.ClaimEarlyRefundAsync(Arg.Any <Address>(), Arg.Any <EarlyRefundClaim>())
     .Returns(_claimedRefundTransactionHash);
     _depositRepository   = Substitute.For <IDepositDetailsRepository>();
     _transactionVerifier = Substitute.For <ITransactionVerifier>();
     _transactionVerifier.VerifyAsync(Arg.Any <NdmTransaction>()).Returns(new TransactionVerifierResult(true, 1, 1));
     _timestamper    = new Timestamper();
     _refundClaimant = new RefundClaimant(_refundService, _ndmBridge, _depositRepository,
                                          _transactionVerifier, _timestamper, LimboLogs.Instance);
 }
        public async Task TryClaimRefundAsync(DepositDetails deposit, Address refundTo)
        {
            var now = _timestamper.EpochSeconds;

            if (!deposit.CanClaimRefund(now))
            {
                return;
            }

            var latestBlock = await _blockchainBridge.GetLatestBlockAsync();

            now = (ulong)latestBlock.Timestamp;
            if (!deposit.CanClaimRefund(now))
            {
                return;
            }

            var depositId       = deposit.Deposit.Id;
            var transactionHash = deposit.ClaimedRefundTransactionHash;

            if (transactionHash is null)
            {
                var provider    = deposit.DataAsset.Provider.Address;
                var refundClaim = new RefundClaim(depositId, deposit.DataAsset.Id, deposit.Deposit.Units,
                                                  deposit.Deposit.Value, deposit.Deposit.ExpiryTime, deposit.Pepper, provider, refundTo);
                transactionHash = await _refundService.ClaimRefundAsync(refundTo, refundClaim);

                deposit.SetClaimedRefundTransactionHash(transactionHash);
                await _depositRepository.UpdateAsync(deposit);

                if (_logger.IsInfo)
                {
                    _logger.Info($"Claimed a refund for deposit: '{depositId}', transaction hash: '{transactionHash}' (awaits a confirmation).");
                }
            }

            await TryConfirmClaimAsync(deposit, string.Empty);
        }