From dc0dcee030bb9a2791eaa64b8cc42518ddd6db69 Mon Sep 17 00:00:00 2001 From: Francois de la Rouviere Date: Tue, 12 Jan 2021 14:37:35 +0000 Subject: [PATCH] Move pending and completed withdrawal stats to CCTS (#360) * Move pending and completed withdrawal stats * Update WithdrawalModel.cs --- .../FederationWalletControllerTests.cs | 10 ++- .../CrossChainTestBase.cs | 2 +- .../Controllers/FederationWalletController.cs | 37 ++++------ .../FederatedPegFeature.cs | 52 ------------- .../Interfaces/ICrossChainTransferStore.cs | 9 ++- .../Models/WithdrawalModel.cs | 2 +- .../TargetChain/CrossChainTransferStore.cs | 73 ++++++++++++++++++- .../TargetChain/MempoolCleaner.cs | 2 +- .../TargetChain/WithdrawalHistoryProvider.cs | 35 +++------ 9 files changed, 111 insertions(+), 111 deletions(-) diff --git a/src/Stratis.Features.FederatedPeg.Tests/ControllersTests/FederationWalletControllerTests.cs b/src/Stratis.Features.FederatedPeg.Tests/ControllersTests/FederationWalletControllerTests.cs index 7a24249a61..e118ad686b 100644 --- a/src/Stratis.Features.FederatedPeg.Tests/ControllersTests/FederationWalletControllerTests.cs +++ b/src/Stratis.Features.FederatedPeg.Tests/ControllersTests/FederationWalletControllerTests.cs @@ -54,7 +54,7 @@ public FederationWalletControllerTests() this.withdrawalHistoryProvider = Substitute.For(); this.controller = new FederationWalletController(this.loggerFactory, this.walletManager, this.walletSyncManager, - this.connectionManager, this.network, this.chainIndexer, this.dateTimeProvider, this.withdrawalHistoryProvider); + this.connectionManager, this.network, this.chainIndexer, Substitute.For()); this.fedWallet = new FederationWallet { @@ -106,7 +106,7 @@ public void GetHistory() { var withdrawals = new List() { new WithdrawalModel(), new WithdrawalModel() }; - this.withdrawalHistoryProvider.GetHistory(0).ReturnsForAnyArgs(withdrawals); + this.withdrawalHistoryProvider.GetHistory(new[] { new CrossChainTransfer() }, 0).ReturnsForAnyArgs(withdrawals); IActionResult result = this.controller.GetHistory(5); List model = this.ActionResultToModel>(result); @@ -141,8 +141,10 @@ public void EnableFederation() [Fact] public void RemoveTransactions() { - var hashSet = new HashSet<(uint256, DateTimeOffset)>(); - hashSet.Add((uint256.One, DateTimeOffset.MinValue)); + var hashSet = new HashSet<(uint256, DateTimeOffset)> + { + (uint256.One, DateTimeOffset.MinValue) + }; this.walletManager.RemoveAllTransactions().Returns(info => hashSet); diff --git a/src/Stratis.Features.FederatedPeg.Tests/CrossChainTestBase.cs b/src/Stratis.Features.FederatedPeg.Tests/CrossChainTestBase.cs index 4306ed4fd4..7c6d6584b5 100644 --- a/src/Stratis.Features.FederatedPeg.Tests/CrossChainTestBase.cs +++ b/src/Stratis.Features.FederatedPeg.Tests/CrossChainTestBase.cs @@ -246,7 +246,7 @@ protected void Init(DataFolder dataFolder) protected ICrossChainTransferStore CreateStore() { return new CrossChainTransferStore(this.network, Substitute.For(), this.dataFolder, this.ChainIndexer, this.federatedPegSettings, this.dateTimeProvider, - this.loggerFactory, this.withdrawalExtractor, this.blockRepository, this.federationWalletManager, this.withdrawalTransactionBuilder, this.dBreezeSerializer, this.signals, this.stateRepositoryRoot); + this.loggerFactory, this.withdrawalExtractor, Substitute.For(), this.blockRepository, this.federationWalletManager, this.withdrawalTransactionBuilder, this.dBreezeSerializer, this.signals, this.stateRepositoryRoot); } /// diff --git a/src/Stratis.Features.FederatedPeg/Controllers/FederationWalletController.cs b/src/Stratis.Features.FederatedPeg/Controllers/FederationWalletController.cs index 4c643a63d7..09f5e674db 100644 --- a/src/Stratis.Features.FederatedPeg/Controllers/FederationWalletController.cs +++ b/src/Stratis.Features.FederatedPeg/Controllers/FederationWalletController.cs @@ -15,7 +15,6 @@ using Stratis.Bitcoin.Utilities.ModelStateErrors; using Stratis.Features.FederatedPeg.Interfaces; using Stratis.Features.FederatedPeg.Models; -using Stratis.Features.FederatedPeg.TargetChain; using Stratis.Features.FederatedPeg.Wallet; namespace Stratis.Features.FederatedPeg.Controllers @@ -37,18 +36,13 @@ public static class FederationWalletRouteEndPoint [Route("api/[controller]")] public class FederationWalletController : Controller { + private readonly ICrossChainTransferStore crossChainTransferStore; private readonly IFederationWalletManager federationWalletManager; - + private readonly Network network; private readonly IFederationWalletSyncManager walletSyncManager; - - private readonly CoinType coinType; - private readonly IConnectionManager connectionManager; - private readonly ChainIndexer chainIndexer; - private readonly IWithdrawalHistoryProvider withdrawalHistoryProvider; - /// Instance logger. private readonly ILogger logger; @@ -59,16 +53,15 @@ public class FederationWalletController : Controller IConnectionManager connectionManager, Network network, ChainIndexer chainIndexer, - IDateTimeProvider dateTimeProvider, - IWithdrawalHistoryProvider withdrawalHistoryProvider) + ICrossChainTransferStore crossChainTransferStore) { - this.federationWalletManager = walletManager; - this.walletSyncManager = walletSyncManager; this.connectionManager = connectionManager; - this.withdrawalHistoryProvider = withdrawalHistoryProvider; - this.coinType = (CoinType)network.Consensus.CoinType; + this.crossChainTransferStore = crossChainTransferStore; this.chainIndexer = chainIndexer; + this.federationWalletManager = walletManager; + this.network = network; this.logger = loggerFactory.CreateLogger(this.GetType().FullName); + this.walletSyncManager = walletSyncManager; } /// @@ -136,13 +129,13 @@ public IActionResult GetBalance() return this.NotFound("No federation wallet found."); } - (Money ConfirmedAmount, Money UnConfirmedAmount) result = this.federationWalletManager.GetSpendableAmount(); + (Money ConfirmedAmount, Money UnConfirmedAmount) = this.federationWalletManager.GetSpendableAmount(); var balance = new AccountBalanceModel { - CoinType = this.coinType, - AmountConfirmed = result.ConfirmedAmount, - AmountUnconfirmed = result.UnConfirmedAmount, + CoinType = (CoinType)this.network.Consensus.CoinType, + AmountConfirmed = ConfirmedAmount, + AmountUnconfirmed = UnConfirmedAmount, }; var model = new WalletBalanceModel(); @@ -175,11 +168,9 @@ public IActionResult GetHistory([FromQuery] int maxEntriesToReturn) { FederationWallet wallet = this.federationWalletManager.GetWallet(); if (wallet == null) - { return this.NotFound("No federation wallet found."); - } - List result = this.withdrawalHistoryProvider.GetHistory(maxEntriesToReturn); + List result = this.crossChainTransferStore.GetCompletedWithdrawals(maxEntriesToReturn); return this.Json(result); } @@ -235,7 +226,7 @@ public IActionResult Sync([FromBody] HashModel model) [ProducesResponseType((int)HttpStatusCode.BadRequest)] [ProducesResponseType((int)HttpStatusCode.NotFound)] [ProducesResponseType((int)HttpStatusCode.InternalServerError)] - public IActionResult EnableFederation([FromBody]EnableFederationRequest request) + public IActionResult EnableFederation([FromBody] EnableFederationRequest request) { Guard.NotNull(request, nameof(request)); @@ -282,7 +273,7 @@ public IActionResult EnableFederation([FromBody]EnableFederationRequest request) [ProducesResponseType((int)HttpStatusCode.OK)] [ProducesResponseType((int)HttpStatusCode.BadRequest)] [ProducesResponseType((int)HttpStatusCode.InternalServerError)] - public IActionResult RemoveTransactions([FromQuery]RemoveFederationTransactionsModel request) + public IActionResult RemoveTransactions([FromQuery] RemoveFederationTransactionsModel request) { Guard.NotNull(request, nameof(request)); diff --git a/src/Stratis.Features.FederatedPeg/FederatedPegFeature.cs b/src/Stratis.Features.FederatedPeg/FederatedPegFeature.cs index 406176c512..91f48a4ab4 100644 --- a/src/Stratis.Features.FederatedPeg/FederatedPegFeature.cs +++ b/src/Stratis.Features.FederatedPeg/FederatedPegFeature.cs @@ -25,7 +25,6 @@ using Stratis.Features.FederatedPeg.Distribution; using Stratis.Features.FederatedPeg.InputConsolidation; using Stratis.Features.FederatedPeg.Interfaces; -using Stratis.Features.FederatedPeg.Models; using Stratis.Features.FederatedPeg.Notifications; using Stratis.Features.FederatedPeg.Payloads; using Stratis.Features.FederatedPeg.SourceChain; @@ -40,16 +39,6 @@ namespace Stratis.Features.FederatedPeg { internal class FederatedPegFeature : FullNodeFeature { - /// - /// Given that we can have up to 10 UTXOs going at once. - /// - private const int TransfersToDisplay = 10; - - /// - /// The maximum number of pending transactions to display in the console logging. - /// - private const int PendingToDisplay = 25; - public const string FederationGatewayFeatureNamespace = "federationgateway"; private readonly IConnectionManager connectionManager; @@ -64,8 +53,6 @@ internal class FederatedPegFeature : FullNodeFeature private readonly IFederationWalletSyncManager walletSyncManager; - private readonly ChainIndexer chainIndexer; - private readonly Network network; private readonly ICrossChainTransferStore crossChainTransferStore; @@ -78,8 +65,6 @@ internal class FederatedPegFeature : FullNodeFeature private readonly IMaturedBlocksSyncManager maturedBlocksSyncManager; - private readonly IWithdrawalHistoryProvider withdrawalHistoryProvider; - private readonly IInputConsolidator inputConsolidator; private readonly ILogger logger; @@ -92,14 +77,12 @@ internal class FederatedPegFeature : FullNodeFeature IFederationWalletManager federationWalletManager, IFederationWalletSyncManager walletSyncManager, Network network, - ChainIndexer chainIndexer, INodeStats nodeStats, ICrossChainTransferStore crossChainTransferStore, IPartialTransactionRequester partialTransactionRequester, MempoolCleaner mempoolCleaner, ISignedMultisigTransactionBroadcaster signedBroadcaster, IMaturedBlocksSyncManager maturedBlocksSyncManager, - IWithdrawalHistoryProvider withdrawalHistoryProvider, IInputConsolidator inputConsolidator, ICollateralChecker collateralChecker = null) { @@ -107,7 +90,6 @@ internal class FederatedPegFeature : FullNodeFeature this.connectionManager = connectionManager; this.federatedPegSettings = federatedPegSettings; this.fullNode = fullNode; - this.chainIndexer = chainIndexer; this.federationWalletManager = federationWalletManager; this.walletSyncManager = walletSyncManager; this.network = network; @@ -115,7 +97,6 @@ internal class FederatedPegFeature : FullNodeFeature this.partialTransactionRequester = partialTransactionRequester; this.mempoolCleaner = mempoolCleaner; this.maturedBlocksSyncManager = maturedBlocksSyncManager; - this.withdrawalHistoryProvider = withdrawalHistoryProvider; this.signedBroadcaster = signedBroadcaster; this.inputConsolidator = inputConsolidator; @@ -258,39 +239,6 @@ private string CollectStats() benchLog.AppendLine(); } - try - { - List pendingWithdrawals = this.withdrawalHistoryProvider.GetPending(); - - if (pendingWithdrawals.Count > 0) - { - benchLog.AppendLine("--- Pending Withdrawals ---"); - foreach (WithdrawalModel withdrawal in pendingWithdrawals.Take(PendingToDisplay)) - benchLog.AppendLine(withdrawal.ToString()); - - if (pendingWithdrawals.Count > PendingToDisplay) - benchLog.AppendLine($"And {pendingWithdrawals.Count - PendingToDisplay} more..."); - - benchLog.AppendLine(); - } - } - catch (Exception exception) - { - benchLog.AppendLine("--- Pending Withdrawals ---"); - benchLog.AppendLine("Failed to retrieve data"); - this.logger.LogError("Exception occurred while getting pending withdrawals: '{0}'.", exception.ToString()); - } - - List completedWithdrawals = this.withdrawalHistoryProvider.GetHistory(TransfersToDisplay); - - if (completedWithdrawals.Count > 0) - { - benchLog.AppendLine("--- Recently Completed Withdrawals ---"); - foreach (WithdrawalModel withdrawal in completedWithdrawals) - benchLog.AppendLine(withdrawal.ToString()); - benchLog.AppendLine(); - } - return benchLog.ToString(); } } diff --git a/src/Stratis.Features.FederatedPeg/Interfaces/ICrossChainTransferStore.cs b/src/Stratis.Features.FederatedPeg/Interfaces/ICrossChainTransferStore.cs index 510aef5cb4..34db6b3cfd 100644 --- a/src/Stratis.Features.FederatedPeg/Interfaces/ICrossChainTransferStore.cs +++ b/src/Stratis.Features.FederatedPeg/Interfaces/ICrossChainTransferStore.cs @@ -96,6 +96,13 @@ public interface ICrossChainTransferStore : IDisposable /// /// The list of input transactions. /// The list of transactions that are completed (or unknown) wihdrawals. - List CompletedWithdrawals(IEnumerable transactionsToCheck); + List GetCompletedWithdrawalsForTransactions(IEnumerable transactionsToCheck); + + /// + /// Returns a list of completed withdrawals (those that are seen-in-block). + /// + /// The max items to display. + /// The completed withdrawals. + List GetCompletedWithdrawals(int transfersToDisplay); } } diff --git a/src/Stratis.Features.FederatedPeg/Models/WithdrawalModel.cs b/src/Stratis.Features.FederatedPeg/Models/WithdrawalModel.cs index 02e0501d07..cef104f5a3 100644 --- a/src/Stratis.Features.FederatedPeg/Models/WithdrawalModel.cs +++ b/src/Stratis.Features.FederatedPeg/Models/WithdrawalModel.cs @@ -50,7 +50,7 @@ public override string ToString() { var stringBuilder = new StringBuilder(); - stringBuilder.Append(string.Format("Block Height={0,8} Paying={1} Amount={2,12} Status={3}", + stringBuilder.Append(string.Format("Block Height={0,8} Paying={1} Amount={2,14} Status={3}", this.BlockHeight == 0 ? "Unconfirmed" : this.BlockHeight.ToString(), this.PayingTo, this.Amount.ToString(), diff --git a/src/Stratis.Features.FederatedPeg/TargetChain/CrossChainTransferStore.cs b/src/Stratis.Features.FederatedPeg/TargetChain/CrossChainTransferStore.cs index 75ecad42ad..fc6a64c57a 100644 --- a/src/Stratis.Features.FederatedPeg/TargetChain/CrossChainTransferStore.cs +++ b/src/Stratis.Features.FederatedPeg/TargetChain/CrossChainTransferStore.cs @@ -26,6 +26,11 @@ namespace Stratis.Features.FederatedPeg.TargetChain { public class CrossChainTransferStore : ICrossChainTransferStore { + /// + /// Given that we can have up to 10 UTXOs going at once. + /// + private const int TransfersToDisplay = 10; + /// /// Maximum number of partial transactions. /// @@ -78,13 +83,14 @@ public class CrossChainTransferStore : ICrossChainTransferStore private readonly ISignals signals; private readonly IStateRepositoryRoot stateRepositoryRoot; private readonly IWithdrawalExtractor withdrawalExtractor; + private readonly IWithdrawalHistoryProvider withdrawalHistoryProvider; private readonly IWithdrawalTransactionBuilder withdrawalTransactionBuilder; /// Provider of time functions. private readonly object lockObj; public CrossChainTransferStore(Network network, INodeStats nodeStats, DataFolder dataFolder, ChainIndexer chainIndexer, IFederatedPegSettings settings, IDateTimeProvider dateTimeProvider, - ILoggerFactory loggerFactory, IWithdrawalExtractor withdrawalExtractor, IBlockRepository blockRepository, IFederationWalletManager federationWalletManager, + ILoggerFactory loggerFactory, IWithdrawalExtractor withdrawalExtractor, IWithdrawalHistoryProvider withdrawalHistoryProvider, IBlockRepository blockRepository, IFederationWalletManager federationWalletManager, IWithdrawalTransactionBuilder withdrawalTransactionBuilder, DBreezeSerializer dBreezeSerializer, ISignals signals, IStateRepositoryRoot stateRepositoryRoot = null) { if (!settings.IsMainChain) @@ -108,8 +114,6 @@ public class CrossChainTransferStore : ICrossChainTransferStore this.chainIndexer = chainIndexer; this.blockRepository = blockRepository; this.federationWalletManager = federationWalletManager; - this.withdrawalTransactionBuilder = withdrawalTransactionBuilder; - this.withdrawalExtractor = withdrawalExtractor; this.dBreezeSerializer = dBreezeSerializer; this.lockObj = new object(); this.logger = loggerFactory.CreateLogger(this.GetType().FullName); @@ -119,6 +123,9 @@ public class CrossChainTransferStore : ICrossChainTransferStore this.settings = settings; this.signals = signals; this.stateRepositoryRoot = stateRepositoryRoot; + this.withdrawalExtractor = withdrawalExtractor; + this.withdrawalHistoryProvider = withdrawalHistoryProvider; + this.withdrawalTransactionBuilder = withdrawalTransactionBuilder; // Future-proof store name. string depositStoreName = "federatedTransfers" + settings.MultiSigAddress.ToString(); @@ -1385,7 +1392,7 @@ public bool ValidateTransaction(Transaction transaction, bool checkSignature = f } /// - public List CompletedWithdrawals(IEnumerable transactionsToCheck) + public List GetCompletedWithdrawalsForTransactions(IEnumerable transactionsToCheck) { var res = new List(); @@ -1440,6 +1447,64 @@ private void AddComponentStats(StringBuilder benchLog) benchLog.AppendLine("Partial Txs:".PadRight(20) + GetTransfersByStatusCount(CrossChainTransferStatus.Partial)); benchLog.AppendLine("Suspended Txs:".PadRight(20) + GetTransfersByStatusCount(CrossChainTransferStatus.Suspended)); benchLog.AppendLine(); + + var depositIds = new HashSet(); + ICrossChainTransfer[] transfers; + + try + { + foreach (CrossChainTransferStatus status in new[] { CrossChainTransferStatus.FullySigned, CrossChainTransferStatus.Partial }) + depositIds.UnionWith(this.depositsIdsByStatus[status]); + + transfers = this.Get(depositIds.ToArray()).Where(t => t != null).ToArray(); + + // When sorting, Suspended transactions will have null PartialTransactions. Always put them last in the order they're in. + IEnumerable inprogress = transfers.Where(x => x.Status != CrossChainTransferStatus.Suspended && x.Status != CrossChainTransferStatus.Rejected); + IEnumerable suspended = transfers.Where(x => x.Status == CrossChainTransferStatus.Suspended || x.Status == CrossChainTransferStatus.Rejected); + + List pendingWithdrawals = this.withdrawalHistoryProvider.GetPendingWithdrawals(inprogress.Concat(suspended)); + + if (pendingWithdrawals.Count > 0) + { + benchLog.AppendLine("--- Pending Withdrawals ---"); + foreach (WithdrawalModel withdrawal in pendingWithdrawals.Take(TransfersToDisplay)) + benchLog.AppendLine(withdrawal.ToString()); + + if (pendingWithdrawals.Count > TransfersToDisplay) + benchLog.AppendLine($"And {pendingWithdrawals.Count - TransfersToDisplay} more..."); + + benchLog.AppendLine(); + } + } + catch (Exception exception) + { + benchLog.AppendLine("--- Pending Withdrawals ---"); + benchLog.AppendLine("Failed to retrieve data"); + this.logger.LogError("Exception occurred while getting pending withdrawals: '{0}'.", exception.ToString()); + } + + List completedWithdrawals = GetCompletedWithdrawals(TransfersToDisplay); + if (completedWithdrawals.Count > 0) + { + benchLog.AppendLine("--- Recently Completed Withdrawals ---"); + + foreach (WithdrawalModel withdrawal in completedWithdrawals) + benchLog.AppendLine(withdrawal.ToString()); + + benchLog.AppendLine(); + } + } + + /// + public List GetCompletedWithdrawals(int transfersToDisplay) + { + var depositIds = new HashSet(); + foreach (CrossChainTransferStatus status in new[] { CrossChainTransferStatus.SeenInBlock }) + depositIds.UnionWith(this.depositsIdsByStatus[status]); + + ICrossChainTransfer[] transfers = this.Get(depositIds.ToArray()).Where(t => t != null).ToArray(); + + return this.withdrawalHistoryProvider.GetHistory(transfers, transfersToDisplay); } /// diff --git a/src/Stratis.Features.FederatedPeg/TargetChain/MempoolCleaner.cs b/src/Stratis.Features.FederatedPeg/TargetChain/MempoolCleaner.cs index 93825f8667..e4b97fd60e 100644 --- a/src/Stratis.Features.FederatedPeg/TargetChain/MempoolCleaner.cs +++ b/src/Stratis.Features.FederatedPeg/TargetChain/MempoolCleaner.cs @@ -120,7 +120,7 @@ private async Task CleanMempoolAsync() completedTransactions = this.CompletedTransactions(transactionsToCheck).ToList(); }); - List transactionsToRemove = this.store.CompletedWithdrawals(transactionsToCheck) + List transactionsToRemove = this.store.GetCompletedWithdrawalsForTransactions(transactionsToCheck) .Union(completedTransactions) .ToList(); diff --git a/src/Stratis.Features.FederatedPeg/TargetChain/WithdrawalHistoryProvider.cs b/src/Stratis.Features.FederatedPeg/TargetChain/WithdrawalHistoryProvider.cs index 982b2540fa..e6ce3cab39 100644 --- a/src/Stratis.Features.FederatedPeg/TargetChain/WithdrawalHistoryProvider.cs +++ b/src/Stratis.Features.FederatedPeg/TargetChain/WithdrawalHistoryProvider.cs @@ -11,56 +11,50 @@ namespace Stratis.Features.FederatedPeg.TargetChain { public interface IWithdrawalHistoryProvider { - List GetHistory(int maximumEntriesToReturn); - List GetPending(); + List GetHistory(IEnumerable crossChainTransfers, int maximumEntriesToReturn); + List GetPendingWithdrawals(IEnumerable crossChainTransfers); } public class WithdrawalHistoryProvider : IWithdrawalHistoryProvider { - private readonly Network network; private readonly IFederatedPegSettings federatedPegSettings; - private readonly ICrossChainTransferStore crossChainTransferStore; - private readonly IWithdrawalExtractor withdrawalExtractor; private readonly MempoolManager mempoolManager; + private readonly Network network; + private readonly IWithdrawalExtractor withdrawalExtractor; /// /// The constructor. /// /// Network we are running on. /// Federation settings providing access to number of signatures required. - /// Store which provides access to the statuses. /// Mempool which provides information about transactions in the mempool. /// Logger factory. /// Counter chain network. + /// public WithdrawalHistoryProvider( Network network, IFederatedPegSettings federatedPegSettings, - ICrossChainTransferStore crossChainTransferStore, MempoolManager mempoolManager, ILoggerFactory loggerFactory, CounterChainNetworkWrapper counterChainNetworkWrapper) { this.network = network; this.federatedPegSettings = federatedPegSettings; - this.crossChainTransferStore = crossChainTransferStore; this.withdrawalExtractor = new WithdrawalExtractor(federatedPegSettings, new OpReturnDataReader(loggerFactory, counterChainNetworkWrapper), network); this.mempoolManager = mempoolManager; } - // TODO: These can be more efficient, i.e. remove the wallet calls from GetHistory - // And use a different model for Withdrawals. It doesn't quite map to the Withdrawal class. - /// /// Get the history of successful withdrawals. /// + /// The list of transfers to report on. /// The maximum number of entries to return. /// A object containing a history of withdrawals. - public List GetHistory(int maximumEntriesToReturn) + public List GetHistory(IEnumerable crossChainTransfers, int maximumEntriesToReturn) { var result = new List(); - ICrossChainTransfer[] transfers = this.crossChainTransferStore.GetTransfersByStatus(new[] { CrossChainTransferStatus.SeenInBlock }); - foreach (ICrossChainTransfer transfer in transfers.OrderByDescending(t => t.BlockHeight)) + foreach (ICrossChainTransfer transfer in crossChainTransfers.OrderByDescending(t => t.BlockHeight)) { if (maximumEntriesToReturn-- <= 0) break; @@ -76,20 +70,13 @@ public List GetHistory(int maximumEntriesToReturn) /// /// Get pending withdrawals. /// + /// The list of transfers to report on. /// A object containing pending withdrawals and statuses. - public List GetPending() + public List GetPendingWithdrawals(IEnumerable crossChainTransfers) { var result = new List(); - // Get all Suspended, all Partial, and all FullySigned transfers. - ICrossChainTransfer[] inProgressTransfers = this.crossChainTransferStore.GetTransfersByStatus(new CrossChainTransferStatus[] - { - CrossChainTransferStatus.Suspended, - CrossChainTransferStatus.Partial, - CrossChainTransferStatus.FullySigned - }, true, false); - - foreach (ICrossChainTransfer transfer in inProgressTransfers) + foreach (ICrossChainTransfer transfer in crossChainTransfers) { var model = new WithdrawalModel(this.network, transfer); string status = transfer?.Status.ToString();