public async Task <PaginatedList <Transaction> > GetHistoryAsync(DepositWallet depositWallet, string continuation) { if (!CanProvideHistoryFor(depositWallet)) { return(PaginatedList.From(Array.Empty <Transaction>())); } var continuationToken = continuation != null ? JsonConvert.DeserializeObject <ContinuationToken>(continuation) : new ContinuationToken { Page = 0 }; InsightApiTransactionsResponse response = null; try { response = await _insightApi.GetAddressTransactions(depositWallet.Address, continuationToken.Page); } catch (FlurlHttpException ex) when(ex.Call.HttpStatus == HttpStatusCode.BadRequest) { var responseMessage = await ex.GetResponseStringAsync(); if (responseMessage == "Invalid address. Code:-5") { _log.Warning ( "Insight API treated address as invalid. Skipping", context: new { Address = depositWallet.Address } ); } else { throw; } } if (response == null) { return(PaginatedList.From(Array.Empty <Transaction>())); } var depositOperations = response.Transactions.Where(tx => IsDeposit(tx, depositWallet.Address)); var depositTransactions = Map(depositOperations, depositWallet); var nextPage = continuationToken.Page + 1; var resultContinuation = nextPage < response.PagesTotal ? new ContinuationToken { Page = nextPage } : null; return(PaginatedList.From(resultContinuation, depositTransactions)); }
public async Task TestLtcDepositsHistory() { // Arrange var historyProvider = new LtcDepositsHistoryProvider ( _logFactory, new LtcSettings { Network = "ltc-main", InsightApiUrl = "https://insight.litecore.io/api" }, _blockchainProvider, _addressNormalizer ); var wallet = new DepositWallet ( Guid.NewGuid(), _addressNormalizer.NormalizeOrDefault("MJ1yiB1YLQFra7teEnsYhHbCXtg7Z5cXER", "LTC"), "LTC" ); // Act var transactions = await historyProvider.GetHistoryAsync(wallet, null); Assert.IsNull(transactions.Continuation, "Test should be modified to support continuation"); var inputTransaction1 = transactions.Items.SingleOrDefault(x => x.Hash == "0d7b0f981c5c2eec3f3894684ac376d09d35316a0e2b92613aa8447e43267782"); var inputTransaction2 = transactions.Items.SingleOrDefault(x => x.Hash == "185dd76bdddbedd755fa3f1f8964900cc58091fc59b55eadc9182964e8bca4d0"); var inputTransaction3 = transactions.Items.SingleOrDefault(x => x.Hash == "03e525835881d46dcd57afab4cf1a0bbf4393dbe5ffb9d5b71ad22585cfeb1d5"); var outputTransaction1 = transactions.Items.SingleOrDefault(x => x.Hash == "ea56e88b637fc3a3eb51c74d7009c5c2d123ec45a646bf4bc18da4000c968739"); var outputTransaction2 = transactions.Items.SingleOrDefault(x => x.Hash == "736182ece2301dbf6201a8990a8c22f2984bc1e8e83cb8fddb58b0f9ff278397"); var outputTransaction3 = transactions.Items.SingleOrDefault(x => x.Hash == "23414816382e805390263fabe3eeafd708d4321d8b2084419f26b81020ec8367"); // Assert Assert.IsNotNull(inputTransaction1); Assert.IsNotNull(inputTransaction2); Assert.IsNotNull(inputTransaction3); Assert.IsNull(outputTransaction1); Assert.IsNull(outputTransaction2); Assert.IsNull(outputTransaction3); Assert.AreEqual("LTC", inputTransaction1.CryptoCurrency); Assert.AreEqual(wallet.Address, inputTransaction1.OutputAddress); Assert.AreEqual(wallet.UserId, inputTransaction1.UserId); Assert.AreEqual(TransactionType.Deposit, inputTransaction1.Type); Assert.AreEqual("LTC", inputTransaction2.CryptoCurrency); Assert.AreEqual(wallet.Address, inputTransaction2.OutputAddress); Assert.AreEqual(wallet.UserId, inputTransaction2.UserId); Assert.AreEqual(TransactionType.Deposit, inputTransaction2.Type); Assert.AreEqual("LTC", inputTransaction3.CryptoCurrency); Assert.AreEqual(wallet.Address, inputTransaction3.OutputAddress); Assert.AreEqual(wallet.UserId, inputTransaction3.UserId); Assert.AreEqual(TransactionType.Deposit, inputTransaction3.Type); }
private List <Transaction> GetDeposits(IEnumerable <RippleTransaction> txs, DepositWallet wallet, string address, string tag) { return(txs // filter transaction by destination tag // to find deposits of specified user .Where(tx => tx.Validated && tx.Meta.TransactionResult == "tesSUCCESS" && tx.Tx.TransactionType == "Payment" && tx.Tx.Destination == address && (tag == null || tx.Tx.DestinationTag?.ToString("D") == tag)) .Select(tx => new Transaction(wallet.CryptoCurrency, tx.Tx.Hash, wallet.UserId, wallet.Address, TransactionType.Deposit)) .ToList()); }
public async Task <PaginatedList <Transaction> > GetHistoryAsync(DepositWallet depositWallet, string continuation) { if (!CanProvideHistoryFor(depositWallet)) { return(PaginatedList.From(Array.Empty <Transaction>())); } var response = await _client.GetBalance(depositWallet.Address, false, continuation); var depositOperations = response.Operations.Where(IsDeposit); var depositTransactions = Map(depositOperations, depositWallet.Address, depositWallet.UserId); return(PaginatedList.From(response.Continuation, depositTransactions.ToArray())); }
public async Task TestXrpDepositsHistoryWithoutTag() { // Arrange var historyProvider = new XrpDepositsHistoryProvider ( _blockchainProvider, new XrpSettings { RpcUrl = "http://s.altnet.rippletest.net:51234" } ); var wallet = new DepositWallet ( Guid.NewGuid(), "rBdTcycW4Q29RCojiQiQ3tAHNJiTsiqNu2", "XRP" ); // Act var transactions = await historyProvider.GetHistoryAsync(wallet, null); var inputTransaction1 = transactions.Items.SingleOrDefault(x => x.Hash == "2ECB3C49152C3E95CB11BCCE59FDEA96200696B9B529E13891DDC3F115EF55AB"); var inputTransaction2 = transactions.Items.SingleOrDefault(x => x.Hash == "8812C6CAFBE7C37C449D0C64673371BEAE26500276648FE6634BE87FCA9AFDF9"); var outputTransaction1 = transactions.Items.SingleOrDefault(x => x.Hash == "B5E4D68E8F0C9C440BF1C4040CB303546A0534EE173AB372B3F149ADCA59AB0D"); // Assert Assert.IsNotNull(inputTransaction1); Assert.IsNotNull(inputTransaction2); Assert.IsNull(outputTransaction1); Assert.AreEqual("XRP", inputTransaction1.CryptoCurrency); Assert.AreEqual(wallet.Address, inputTransaction1.OutputAddress); Assert.AreEqual(wallet.UserId, inputTransaction1.UserId); Assert.AreEqual(TransactionType.Deposit, inputTransaction1.Type); Assert.AreEqual("XRP", inputTransaction2.CryptoCurrency); Assert.AreEqual(wallet.Address, inputTransaction2.OutputAddress); Assert.AreEqual(wallet.UserId, inputTransaction2.UserId); Assert.AreEqual(TransactionType.Deposit, inputTransaction2.Type); }
public async Task TestBchDepositsHistory() { // Arrange var historyProvider = new BchDepositsHistoryProvider ( _logFactory, new BchSettings { Network = "main", InsightApiUrl = "https://blockdozer.com/insight-api" }, _blockchainProvider, _addressNormalizer ); var wallet = new DepositWallet ( Guid.NewGuid(), _addressNormalizer.NormalizeOrDefault("qrvvjf9an22vv4wumm2enzdee7xna659kggarhwzyl", "BCH"), "BCH" ); // Act var transactions = await historyProvider.GetHistoryAsync(wallet, null); Assert.IsNull(transactions.Continuation, "Test should be modified to support continuation"); var inputTransaction = transactions.Items.SingleOrDefault(x => x.Hash == "ca5119c2a07ef74e66fc25f5eb2501fede8eb04b1174c0e27b4e0093b705acfc"); var outputTransaction = transactions.Items.SingleOrDefault(x => x.Hash == "e9510d71e44749c9456fe2040c8ae5e276698dfd834c1c0c1329a85506cc87ac"); // Assert Assert.IsNotNull(inputTransaction); Assert.IsNull(outputTransaction); Assert.AreEqual("BCH", inputTransaction.CryptoCurrency); Assert.AreEqual(wallet.Address, inputTransaction.OutputAddress); Assert.AreEqual(wallet.UserId, inputTransaction.UserId); Assert.AreEqual(TransactionType.Deposit, inputTransaction.Type); }
public async Task <PaginatedList <Transaction> > GetHistoryAsync(DepositWallet depositWallet, string continuation) { if (!CanProvideHistoryFor(depositWallet)) { return(PaginatedList.From(Array.Empty <Transaction>())); } if (continuation != null) { throw new NotSupportedException("Continuation is not supported"); } var operations = await ReadTransactionsAsync(depositWallet); var internalOperations = await ReadInternalTransactionsAsync(depositWallet); var internalOperationHashes = internalOperations.Select(x => x.TransactionHash).ToHashSet(); var transactions = operations .Where(x => !internalOperationHashes.Contains(x.TransactionHash) && IsDeposit(depositWallet.Address, x.To)) .Select(x => new Transaction ( _ethereum.CryptoCurrency, x.TransactionHash.ToLower(), depositWallet.UserId, depositWallet.Address, TransactionType.Deposit )); var internalTransactions = internalOperations .Where(x => IsDeposit(depositWallet.Address, x.To)) .Select(x => new Transaction ( _ethereum.CryptoCurrency, x.TransactionHash.ToLower(), depositWallet.UserId, depositWallet.Address, TransactionType.Deposit )); var allTransactions = transactions.Concat(internalTransactions).ToArray(); return(PaginatedList.From(allTransactions)); }
public async Task TestEthDepositsHistoryForErc20() { // Arrange var historyProvider = new EthDepositsHistoryProvider ( _blockchainProvider, new EthSettings { SamuraiUrl = "http://144.76.25.187:8004" }, _addressNormalizer ); var wallet = new DepositWallet ( Guid.NewGuid(), _addressNormalizer.NormalizeOrDefault("0x27e017534031cf15f6b207c635362d720eef8908", "ETH"), "ETH" ); // Act var transactions = await historyProvider.GetHistoryAsync(wallet, null); Assert.IsNull(transactions.Continuation, "Test should be modified to support continuation"); var inputTransaction = transactions.Items.SingleOrDefault(x => x.Hash == "0x7b6d2c134d12d23c4bdd89cea50fd8693a119a42d0afcc3975725d830eeb01c8"); var outputTransaction = transactions.Items.SingleOrDefault(x => x.Hash == "0x7dbedaf6d657dffd3bfe6423d74e8e8b5821eaf519fee68fecc96884d0398d09"); // Assert Assert.IsNotNull(inputTransaction); Assert.IsNull(outputTransaction); Assert.AreEqual("ETH", inputTransaction.CryptoCurrency); Assert.AreEqual(wallet.Address, inputTransaction.OutputAddress); Assert.AreEqual(wallet.UserId, inputTransaction.UserId); Assert.AreEqual(TransactionType.Deposit, inputTransaction.Type); }
public async Task <PaginatedList <Transaction> > GetHistoryAsync(DepositWallet depositWallet, string continuation) { if (!CanProvideHistoryFor(depositWallet)) { return(PaginatedList.From(Array.Empty <Transaction>())); } if (continuation != null) { throw new NotSupportedException("Continuation is not supported"); } var addressParts = depositWallet.Address.Split('+', StringSplitOptions.RemoveEmptyEntries); var address = addressParts[0]; var tag = addressParts.Length > 1 ? addressParts[1] : null; List <RippleTransaction> txs; if (!_memoryCache.TryGetValue <List <RippleTransaction> >(address, out txs)) { lock (_mutex.GetOrAdd(address, new object())) { if (!_memoryCache.TryGetValue <List <RippleTransaction> >(address, out txs)) { txs = GetRippleTransactions(address).Result; _memoryCache.Set(address, txs, _settings.CacheExpirationPeriod); } } } return(PaginatedList.From( GetDeposits(txs, depositWallet, address, tag) )); }
public bool CanProvideHistoryFor(DepositWallet depositWallet) { return(depositWallet.CryptoCurrency == _liteCoin.CryptoCurrency); }
private IReadOnlyCollection <Transaction> Map(IEnumerable <InsightApiTransaction> insightApiTransactions, DepositWallet depositWallet) { return(insightApiTransactions .Select(tx => new Transaction ( _liteCoin.CryptoCurrency, tx.Id, depositWallet.UserId, depositWallet.Address, TransactionType.Deposit )) .ToArray()); }
public async Task TestBtcDepositsHistory() { // Arrange var historyProvider = new BtcDepositsHistoryProvider ( _blockchainProvider, new BtcSettings { Network = "main", NinjaUrl = "http://api.qbit.ninja" } ); var wallet = new DepositWallet ( Guid.NewGuid(), _addressNormalizer.NormalizeOrDefault("3N7cHrmKeEsjuFTx39WyGoZwAikAVSFoWX", "BTC"), "BTC" ); // Act var transactions = await historyProvider.GetHistoryAsync(wallet, null); Assert.IsNull(transactions.Continuation, "Test should be modified to support continuation"); var inputTransaction = transactions.Items.SingleOrDefault(x => x.Hash == "d8f1de74975ff7966c72944b75ac7ec307f58b42019e2206845c78b2f16326ba"); var coloredInputTransaction1 = transactions.Items.SingleOrDefault(x => x.Hash == "15f04a503a203a7a043d1126750028f3c805624fec38353280df23c85283df04"); var coloredInputTransaction2 = transactions.Items.SingleOrDefault(x => x.Hash == "c09d8d502d15ce54e61c14a97ef5a59a8ada20c269ac6ef2a065dd615f04247a"); var outputTransaction1 = transactions.Items.SingleOrDefault(x => x.Hash == "8c3f45a126a9558d393250aa58ca2b8b4b428c948b1ec837578ef1e13f81f6bf"); var outputTransaction2 = transactions.Items.SingleOrDefault(x => x.Hash == "cde67afceff4f7a4437b520c74f9200d4079f078754be617eafdcece835e9d9c"); var outputTransaction3 = transactions.Items.SingleOrDefault(x => x.Hash == "a4e793c395fc958cd87769a75411584da1517b6b6e48d7e160a6f19057ede853"); var outputTransaction4 = transactions.Items.SingleOrDefault(x => x.Hash == "1363846a07e44774ebd9c29f5033894492273b96dca873aab63065064fe00c06"); var outputTransaction5 = transactions.Items.SingleOrDefault(x => x.Hash == "12971723f3ebc31744693e7db4ba5fc9131c9b446c55a910ac7431b74bb91387"); var outputTransaction6 = transactions.Items.SingleOrDefault(x => x.Hash == "cdf73195df0b8ec119153c80b29d05944117711ce7570d70e5bcd681522c9521"); // Assert Assert.IsNotNull(inputTransaction); Assert.IsNotNull(coloredInputTransaction1); Assert.IsNotNull(coloredInputTransaction2); Assert.IsNull(outputTransaction1); Assert.IsNull(outputTransaction2); Assert.IsNull(outputTransaction3); Assert.IsNull(outputTransaction4); Assert.IsNull(outputTransaction5); Assert.IsNull(outputTransaction6); Assert.AreEqual("BTC", inputTransaction.CryptoCurrency); Assert.AreEqual(wallet.Address, inputTransaction.OutputAddress); Assert.AreEqual(wallet.UserId, inputTransaction.UserId); Assert.AreEqual(TransactionType.Deposit, inputTransaction.Type); Assert.AreEqual("BTC", coloredInputTransaction1.CryptoCurrency); Assert.AreEqual(wallet.Address, coloredInputTransaction1.OutputAddress); Assert.AreEqual(wallet.UserId, coloredInputTransaction1.UserId); Assert.AreEqual(TransactionType.Deposit, coloredInputTransaction1.Type); Assert.AreEqual("BTC", coloredInputTransaction2.CryptoCurrency); Assert.AreEqual(wallet.Address, coloredInputTransaction2.OutputAddress); Assert.AreEqual(wallet.UserId, coloredInputTransaction2.UserId); Assert.AreEqual(TransactionType.Deposit, coloredInputTransaction2.Type); }
public async Task TestEthDepositsHistoryForEther() { // Arrange var historyProvider = new EthDepositsHistoryProvider ( _blockchainProvider, new EthSettings { SamuraiUrl = "http://144.76.25.187:8004" }, _addressNormalizer ); var wallet = new DepositWallet ( Guid.NewGuid(), _addressNormalizer.NormalizeOrDefault("0xff9d0186e9bd8234cfefbae286c2f0321b0d760d", "ETH"), "ETH" ); // Act var transactions = await historyProvider.GetHistoryAsync(wallet, null); Assert.IsNull(transactions.Continuation, "Test should be modified to support continuation"); var inputTransaction1 = transactions.Items.SingleOrDefault(x => x.Hash == "0x605a3d3338fad48e8ca7597acad718afe56479776baf95568586c5c65674e5ae"); var inputTransaction2 = transactions.Items.SingleOrDefault(x => x.Hash == "0x7c36ca2cf156982000f4fb3e9df2cf20539367e92b16b909f7a98333f4f52843"); var inputTransaction3 = transactions.Items.SingleOrDefault(x => x.Hash == "0x20a52fbd3eefe39beb4576b2591430b28e43a3b906d324d99a501aff1cade8d8"); var inputTransaction4 = transactions.Items.SingleOrDefault(x => x.Hash == "0xad0ffe618b4ddb58f552361f32dc671f48c9a11a1095b66520ecb33f3ec7d7fe"); var inputTransaction5 = transactions.Items.SingleOrDefault(x => x.Hash == "0x302c023c77d7800cda7424a98adcd08e9c419c92d46ec00ed767bab02d212cc3"); var outputTransaction1 = transactions.Items.SingleOrDefault(x => x.Hash == "0x6ba8e3f37c412914bee3b6eb1fdad7097ebf167499941d6b36100ec84cd714ea"); var outputTransaction2 = transactions.Items.SingleOrDefault(x => x.Hash == "0x401a611b4324454814fd33fe3a2808068821eca67b275810c9d916fbc3237fb9"); var outputTransaction3 = transactions.Items.SingleOrDefault(x => x.Hash == "0xa312466e6ad6266f1c44c135684e8dba64380186966f14b838aa2c755262cb4b"); // Assert Assert.IsNotNull(inputTransaction1); Assert.IsNotNull(inputTransaction2); Assert.IsNotNull(inputTransaction3); Assert.IsNotNull(inputTransaction4); Assert.IsNotNull(inputTransaction5); Assert.IsNull(outputTransaction1); Assert.IsNull(outputTransaction2); Assert.IsNull(outputTransaction3); Assert.AreEqual("ETH", inputTransaction1.CryptoCurrency); Assert.AreEqual(wallet.Address, inputTransaction1.OutputAddress); Assert.AreEqual(wallet.UserId, inputTransaction1.UserId); Assert.AreEqual(TransactionType.Deposit, inputTransaction1.Type); Assert.AreEqual("ETH", inputTransaction2.CryptoCurrency); Assert.AreEqual(wallet.Address, inputTransaction2.OutputAddress); Assert.AreEqual(wallet.UserId, inputTransaction2.UserId); Assert.AreEqual(TransactionType.Deposit, inputTransaction2.Type); Assert.AreEqual("ETH", inputTransaction3.CryptoCurrency); Assert.AreEqual(wallet.Address, inputTransaction3.OutputAddress); Assert.AreEqual(wallet.UserId, inputTransaction3.UserId); Assert.AreEqual(TransactionType.Deposit, inputTransaction3.Type); Assert.AreEqual("ETH", inputTransaction4.CryptoCurrency); Assert.AreEqual(wallet.Address, inputTransaction4.OutputAddress); Assert.AreEqual(wallet.UserId, inputTransaction4.UserId); Assert.AreEqual(TransactionType.Deposit, inputTransaction4.Type); Assert.AreEqual("ETH", inputTransaction5.CryptoCurrency); Assert.AreEqual(wallet.Address, inputTransaction5.OutputAddress); Assert.AreEqual(wallet.UserId, inputTransaction5.UserId); Assert.AreEqual(TransactionType.Deposit, inputTransaction5.Type); }
private async Task <IReadOnlyCollection <SamuraiErc20Operation> > ReadInternalTransactionsAsync(DepositWallet depositWallet) { var operations = default(PaginatedList <SamuraiErc20Operation>); var allOperations = new List <SamuraiErc20Operation>(); do { operations = await _samuraiClient.GetErc20OperationsHistory(depositWallet.Address, operations?.Continuation); allOperations.AddRange(operations.Items); } while (operations.Continuation != null); return(allOperations); }
public bool CanProvideHistoryFor(DepositWallet depositWallet) { return(_ethereum.CryptoCurrency == depositWallet.CryptoCurrency); }
public bool CanProvideHistoryFor(DepositWallet depositWallet) { return(depositWallet.CryptoCurrency == _bitcoinCash.CryptoCurrency); }