private async Task <IEnumerable <EthereumTransaction> > CreatePaymentTxsAsync(
            ClientSwap swap,
            int lockTimeInSeconds,
            CancellationToken cancellationToken = default(CancellationToken))
        {
            Log.Debug("Create payment transactions for swap {@swapId}", swap.Id);

            var requiredAmountInEth     = AmountHelper.QtyToAmount(swap.Side, swap.Qty, swap.Price);
            var refundTimeStampUtcInSec = new DateTimeOffset(swap.TimeStamp.ToUniversalTime().AddSeconds(lockTimeInSeconds)).ToUnixTimeSeconds();
            var isInitTx             = true;
            var rewardForRedeemInEth = swap.PartyRewardForRedeem;

            var unspentAddresses = (await Account
                                    .GetUnspentAddressesAsync(Eth, cancellationToken)
                                    .ConfigureAwait(false))
                                   .ToList()
                                   .SortList((a, b) => a.AvailableBalance().CompareTo(b.AvailableBalance()));

            var transactions = new List <EthereumTransaction>();

            foreach (var walletAddress in unspentAddresses)
            {
                Log.Debug("Create swap payment tx from address {@address} for swap {@swapId}", walletAddress.Address, swap.Id);

                var balanceInEth = (await Account
                                    .GetAddressBalanceAsync(
                                        currency: Eth,
                                        address: walletAddress.Address,
                                        cancellationToken: cancellationToken)
                                    .ConfigureAwait(false))
                                   .Available;

                Log.Debug("Available balance: {@balance}", balanceInEth);

                var feeAmountInEth = isInitTx
                    ? (rewardForRedeemInEth == 0
                        ? Eth.InitiateFeeAmount
                        : Eth.InitiateWithRewardFeeAmount)
                    : Eth.AddFeeAmount;

                var amountInEth = Math.Min(balanceInEth - feeAmountInEth, requiredAmountInEth);

                if (amountInEth <= 0)
                {
                    Log.Warning(
                        "Insufficient funds at {@address}. Balance: {@balance}, feeAmount: {@feeAmount}, result: {@result}.",
                        walletAddress.Address,
                        balanceInEth,
                        feeAmountInEth,
                        amountInEth);

                    continue;
                }

                requiredAmountInEth -= amountInEth;

                var nonce = await EthereumNonceManager.Instance
                            .GetNonce(Eth, walletAddress.Address)
                            .ConfigureAwait(false);

                TransactionInput txInput;

                if (isInitTx)
                {
                    var message = new InitiateFunctionMessage
                    {
                        HashedSecret    = swap.SecretHash,
                        Participant     = swap.PartyAddress,
                        RefundTimestamp = refundTimeStampUtcInSec,
                        AmountToSend    = Atomix.Ethereum.EthToWei(amountInEth),
                        FromAddress     = walletAddress.Address,
                        GasPrice        = Atomix.Ethereum.GweiToWei(Eth.GasPriceInGwei),
                        Nonce           = nonce,
                        RedeemFee       = Atomix.Ethereum.EthToWei(rewardForRedeemInEth)
                    };

                    var initiateGasLimit = rewardForRedeemInEth == 0
                        ? Eth.InitiateGasLimit
                        : Eth.InitiateWithRewardGasLimit;

                    message.Gas = await EstimateGasAsync(message, new BigInteger(initiateGasLimit))
                                  .ConfigureAwait(false);

                    txInput = message.CreateTransactionInput(Eth.SwapContractAddress);
                }
                else
                {
                    var message = new AddFunctionMessage
                    {
                        HashedSecret = swap.SecretHash,
                        AmountToSend = Atomix.Ethereum.EthToWei(amountInEth),
                        FromAddress  = walletAddress.Address,
                        GasPrice     = Atomix.Ethereum.GweiToWei(Eth.GasPriceInGwei),
                        Nonce        = nonce,
                    };

                    message.Gas = await EstimateGasAsync(message, new BigInteger(Eth.AddGasLimit))
                                  .ConfigureAwait(false);

                    txInput = message.CreateTransactionInput(Eth.SwapContractAddress);
                }

                transactions.Add(new EthereumTransaction(Eth, txInput)
                {
                    Type = EthereumTransaction.OutputTransaction
                });

                if (isInitTx)
                {
                    isInitTx = false;
                }

                if (requiredAmountInEth == 0)
                {
                    break;
                }
            }

            if (requiredAmountInEth > 0)
            {
                Log.Warning("Insufficient funds (left {@requredAmount}).", requiredAmountInEth);
                return(Enumerable.Empty <EthereumTransaction>());
            }

            return(transactions);
        }
        protected virtual async Task <IEnumerable <EthereumTransaction> > CreatePaymentTxsAsync(
            Swap swap,
            int lockTimeInSeconds,
            CancellationToken cancellationToken = default)
        {
            var eth = Eth;

            Log.Debug("Create payment transactions for swap {@swapId}", swap.Id);

            var requiredAmountInEth     = AmountHelper.QtyToAmount(swap.Side, swap.Qty, swap.Price, eth.DigitsMultiplier);
            var refundTimeStampUtcInSec = new DateTimeOffset(swap.TimeStamp.ToUniversalTime().AddSeconds(lockTimeInSeconds)).ToUnixTimeSeconds();
            var isInitTx             = true;
            var rewardForRedeemInEth = swap.PartyRewardForRedeem;

            var unspentAddresses = (await _account
                                    .GetUnspentAddressesAsync(cancellationToken)
                                    .ConfigureAwait(false))
                                   .ToList()
                                   .SortList(new AvailableBalanceAscending());

            var transactions = new List <EthereumTransaction>();

            foreach (var walletAddress in unspentAddresses)
            {
                Log.Debug("Create swap payment tx from address {@address} for swap {@swapId}", walletAddress.Address, swap.Id);

                var balanceInEth = (await _account
                                    .GetAddressBalanceAsync(
                                        address: walletAddress.Address,
                                        cancellationToken: cancellationToken)
                                    .ConfigureAwait(false))
                                   .Available;

                Log.Debug("Available balance: {@balance}", balanceInEth);

                var feeAmountInEth = isInitTx
                    ? rewardForRedeemInEth == 0
                        ? eth.InitiateFeeAmount
                        : eth.InitiateWithRewardFeeAmount
                    : eth.AddFeeAmount;

                var amountInEth = Math.Min(balanceInEth - feeAmountInEth, requiredAmountInEth);

                if (amountInEth <= 0)
                {
                    Log.Warning(
                        "Insufficient funds at {@address}. Balance: {@balance}, feeAmount: {@feeAmount}, result: {@result}.",
                        walletAddress.Address,
                        balanceInEth,
                        feeAmountInEth,
                        amountInEth);

                    continue;
                }

                requiredAmountInEth -= amountInEth;

                var nonceResult = await EthereumNonceManager.Instance
                                  .GetNonceAsync(eth, walletAddress.Address)
                                  .ConfigureAwait(false);

                if (nonceResult.HasError)
                {
                    Log.Error("Nonce getting error with code {@code} and description {@description}",
                              nonceResult.Error.Code,
                              nonceResult.Error.Description);

                    return(null);
                }

                TransactionInput txInput;

                if (isInitTx)
                {
                    var message = new InitiateFunctionMessage
                    {
                        HashedSecret    = swap.SecretHash,
                        Participant     = swap.PartyAddress,
                        RefundTimestamp = refundTimeStampUtcInSec,
                        AmountToSend    = Atomex.Ethereum.EthToWei(amountInEth),
                        FromAddress     = walletAddress.Address,
                        GasPrice        = Atomex.Ethereum.GweiToWei(eth.GasPriceInGwei),
                        Nonce           = nonceResult.Value,
                        RedeemFee       = Atomex.Ethereum.EthToWei(rewardForRedeemInEth)
                    };

                    var initiateGasLimit = rewardForRedeemInEth == 0
                        ? eth.InitiateGasLimit
                        : eth.InitiateWithRewardGasLimit;

                    message.Gas = await EstimateGasAsync(message, new BigInteger(initiateGasLimit))
                                  .ConfigureAwait(false);

                    txInput = message.CreateTransactionInput(eth.SwapContractAddress);
                }
                else
                {
                    var message = new AddFunctionMessage
                    {
                        HashedSecret = swap.SecretHash,
                        AmountToSend = Atomex.Ethereum.EthToWei(amountInEth),
                        FromAddress  = walletAddress.Address,
                        GasPrice     = Atomex.Ethereum.GweiToWei(Eth.GasPriceInGwei),
                        Nonce        = nonceResult.Value,
                    };

                    message.Gas = await EstimateGasAsync(message, new BigInteger(eth.AddGasLimit))
                                  .ConfigureAwait(false);

                    txInput = message.CreateTransactionInput(eth.SwapContractAddress);
                }

                transactions.Add(new EthereumTransaction(eth, txInput)
                {
                    Type = BlockchainTransactionType.Output | BlockchainTransactionType.SwapPayment
                });

                if (isInitTx)
                {
                    isInitTx = false;
                }

                if (requiredAmountInEth == 0)
                {
                    break;
                }
            }

            if (requiredAmountInEth > 0)
            {
                Log.Warning("Insufficient funds (left {@requiredAmount}).", requiredAmountInEth);
                return(Enumerable.Empty <EthereumTransaction>());
            }

            return(transactions);
        }