private static void ValidateAssetIsNotNull(BlockchainAsset asset)
 {
     if (asset == null)
     {
         throw new ArgumentNullException("Asset is required", nameof(asset));
     }
 }
Exemple #2
0
        public async Task AddBalanceAsync(
            DateTime at,
            string blockchainType,
            string addressName,
            string address,
            BlockchainAsset asset,
            decimal balance,
            string explorerUrl)
        {
            if (_flushed)
            {
                throw new InvalidOperationException("Report already flushed");
            }

            var item = new ReportItem
            {
                At             = at,
                BlockchainType = blockchainType,
                AddressName    = addressName,
                Address        = address,
                Asset          = asset,
                Balance        = balance,
                ExplorerUrl    = explorerUrl
            };

            var tasks = _reportRepositories.Select(x => x.AddBalanceAsync(item));

            await Task.WhenAll(tasks);
        }
Exemple #3
0
        public async Task CanCalculateBalanceAtPointOfTime()
        {
            var balanceProvider = new NeoBalanceProvider("https://neoscan.io/api/main_net/v1/");

            var neoAsset  = new BlockchainAsset("NEO", "c56f33fc6ecfcd0c225c4ab356fee59390af8560be0e930faebe74a6daff7c9b", "ac2e579f-187b-4429-8d60-bea6e4f65f76");
            var gasAsset  = new BlockchainAsset("GAS", "602c79718b16e442de58778e148d0b1084e3b2dffd5de6b7b16cee7969282de7", "f1ccf1dd-9008-4999-adc8-2cb587717083");
            var seasAsset = new BlockchainAsset("SEAS", "de7be47c4c93f1483a0a3fff556a885a68413d97", null);

            var expectations = new List <(string address, DateTime dateTime, IReadOnlyDictionary <BlockchainAsset, decimal> result)>
            {
                ("AYCFkFWhpxXgGzFjnMofYcJMUJ9Z8eneV3", DateTime.Parse("2019-07-01T19:00:00+0000"), new Dictionary <BlockchainAsset, decimal>
                {
                    { neoAsset, 1289 },
                    { gasAsset, 4.30532041m },
                    { seasAsset, 12 }
                }),
                ("AYCFkFWhpxXgGzFjnMofYcJMUJ9Z8eneV3", DateTime.Parse("2019-07-01T12:23:50+0000"), new Dictionary <BlockchainAsset, decimal>
                {
                    { neoAsset, 1259 },
                    { gasAsset, 0 },
                    { seasAsset, 12 }
                }),
            };

            foreach (var assert in expectations)
            {
                var result = await balanceProvider.GetBalancesAsync(assert.address, assert.dateTime);

                Assert.Equal(result, assert.result);
            }
        }
        public async Task CanCalculateBalanceAtPointOfTime()
        {
            var logFactory      = LogFactory.Create().AddUnbufferedConsole();
            var balanceProvider = new DecredBalanceProvider
                                  (
                logFactory,
                "https://explorer.dcrdata.org/insight/api/"
                                  );

            var decredAsset  = new BlockchainAsset("DCR", "DCR", "02154b48-7ed9-4211-b614-e87679fd4f5a");
            var expectations = new List <(string address, DateTime dateTime, IReadOnlyDictionary <BlockchainAsset, decimal> result)>
            {
                ("DscTMvxiYJvUsC9VFFTLTFj9MPWo2Togc33", DateTime.Parse("2019-07-01T19:00:00+0000"), new Dictionary <BlockchainAsset, decimal>
                {
                    { decredAsset, 100.51172068m }
                }),
            };

            foreach (var assert in expectations)
            {
                var result = await balanceProvider.GetBalancesAsync(assert.address, assert.dateTime);

                Assert.Equal(result, assert.result);
            }
        }
Exemple #5
0
        public string Format(string address, BlockchainAsset asset)
        {
            if (asset.BlockchainId != "ETH")
            {
                return($"https://etherscan.io/token/{asset.BlockchainId}?a={address}");
            }

            return($"https://etherscan.io/address/{address}");
        }
        public SamuraiBalanceProvider(
            string url,
            BlockchainAsset nativeAsset,
            IAssetsServiceWithCache assetsServiceClient)
        {
            _nativeAsset = nativeAsset;
            _client      = new SamuraiClient(url);
            _tokensCache = new Dictionary <string, SamuraiErc20TokenResponse>();

            AsyncInitialization = InitializeAsync(assetsServiceClient);
        }
Exemple #7
0
 public Coin(CoinId id,
             BlockchainAsset asset,
             decimal value,
             string address,
             string redeem)
 {
     Id      = id;
     Asset   = asset;
     Value   = value;
     Address = address;
     Redeem  = redeem;
 }
Exemple #8
0
        public NeoBalanceProvider(string baseUrl)
        {
            _baseUrl = baseUrl;

            _neoAsset = BuildAsset(NeoBlockchainAssetId);
            _gasAsset = BuildAsset(GasBlockchainAssetId);

            _assetNames = new Dictionary <string, string>
            {
                { "de7be47c4c93f1483a0a3fff556a885a68413d97", "SEAS" }
            };
        }
Exemple #9
0
        public async Task CanCalculateBalanceAtPointOfTime()
        {
            var balanceProvider = new SteemBalanceProvider("https://api.steemit.com/");

            var asset = new BlockchainAsset("STEEM", "STEEM", "72da9464-49d0-4f95-983d-635c04e39f3c");

            var expectations = new List <(string address, DateTime dateTime, IReadOnlyDictionary <BlockchainAsset, decimal> result)>
            {
                ("lykke-exchange", DateTime.Parse("2019-07-10T19:00:00+0000"), new Dictionary <BlockchainAsset, decimal>
                {
                    { asset, 2751.324m }
                })
            };

            foreach (var assert in expectations)
            {
                var result = await balanceProvider.GetBalancesAsync(assert.address, assert.dateTime);

                Assert.Equal(assert.result[asset], result[asset]);
            }
        }
Exemple #10
0
        public async Task CanCalculateBalanceAtPointOfTime()
        {
            var balanceProvider = new BitsharesBalanceProvider("https://explorer.bitshares-kibana.info/");

            var bitshresAsset = new BlockchainAsset("BTS", "1.3.0", "20ce0468-917e-4097-abba-edf7c8600cfb");

            var expectations = new List <(string address, DateTime dateTime, IReadOnlyDictionary <BlockchainAsset, decimal> result)>
            {
                ("1.2.1038643", DateTime.Parse("2019-07-03T19:00:00+0000"), new Dictionary <BlockchainAsset, decimal>
                {
                    { bitshresAsset, 35441.40289m }
                })
            };

            foreach (var assert in expectations)
            {
                var result = await balanceProvider.GetBalancesAsync(assert.address, assert.dateTime);

                Assert.Equal(assert.result[bitshresAsset], result[bitshresAsset]);
            }
        }
        public async Task CanCalculateBalanceAtPointOfTime()
        {
            var balanceProvider = new SolarCoinBalanceProvider("https://chainz.cryptoid.info");

            var baseAsset = new BlockchainAsset("SLR", "SLR", "SLR");

            var expectations = new List <(string address, DateTime dateTime, IReadOnlyDictionary <BlockchainAsset, decimal> result)>
            {
                ("8cSBrj3d9Hc2KZ6dfNCMHG4BqLwjMjNULP", DateTime.Parse("2019-07-14T22:00+0000"), new Dictionary <BlockchainAsset, decimal>
                {
                    { baseAsset, 7741781.94727671m }
                })
            };

            foreach (var assert in expectations)
            {
                var result = await balanceProvider.GetBalancesAsync(assert.address, assert.dateTime);

                Assert.Equal(assert.result[baseAsset], result[baseAsset]);
            }
        }
        public async Task CanCalculateBalanceAtPointOfTime()
        {
            var balanceProvider = new NemBalanceProvider("http://explorer.nemtool.com/");

            var nemAsset = new BlockchainAsset("XEM", "XEM", "903eafbd-cc29-4d60-8d7d-907695d9caae");

            var expectations = new List <(string address, DateTime dateTime, IReadOnlyDictionary <BlockchainAsset, decimal> result)>
            {
                ("NAFSSJLNTIEI5ISMWKEY2BJFH5LAUSHP7JVQLWGT", DateTime.Parse("2019-07-04T19:00:00+0000"), new Dictionary <BlockchainAsset, decimal>
                {
                    { nemAsset, 4868.073614m }
                })
            };

            foreach (var assert in expectations)
            {
                var result = await balanceProvider.GetBalancesAsync(assert.address, assert.dateTime);

                Assert.Equal(assert.result[nemAsset], result[nemAsset]);
            }
        }
 public string Format(string address, BlockchainAsset asset)
 {
     return($"https://blockchair.com/bitcoin-cash/address/{address}");
 }
Exemple #14
0
 public string Format(string address, BlockchainAsset asset)
 {
     return($"https://chainz.cryptoid.info/slr/address.dws?{address}.htm");
 }
Exemple #15
0
        public SolarCoinBalanceProvider(string baseUrl)
        {
            _baseUrl = baseUrl;

            _baseAsset = new BlockchainAsset("SLR", "SLR", "SLR");
        }
 public string Format(string address, BlockchainAsset asset)
 {
     return($"https://bitshares-explorer.io/#/accounts/{address}");
 }
Exemple #17
0
 public string Format(string address, BlockchainAsset asset)
 {
     return($"https://steemblockexplorer.com/@{address}");
 }
        /// <inheritdoc />
        public async Task <TransactionBuildingResult> BuildTransactionAsync(Guid operationId, string fromAddress, string toAddress, BlockchainAsset asset, decimal amount, bool includeFee)
        {
            ValidateOperationIdIsNotEmpty(operationId);
            ValidateFromAddresIsNotEmpty(fromAddress);
            ValidateToAddressIsNotEmpty(toAddress);
            ValidateAssetIsNotNull(asset);
            ValidateAmountRange(amount);

            BuildTransactionResponse apiResponse;

            try
            {
                apiResponse = await _runner.RunWithRetriesAsync(() => _api.BuildTransactionAsync(
                                                                    new BuildTransactionRequest
                {
                    OperationId = operationId,
                    FromAddress = fromAddress,
                    ToAddress   = toAddress,
                    AssetId     = asset.AssetId,
                    Amount      = Conversions.CoinsToContract(amount, asset.Accuracy),
                    IncludeFee  = includeFee
                }));
            }
            catch (ErrorResponseException ex) when(ex.StatusCode == HttpStatusCode.NotAcceptable)
            {
                throw new NonAcceptableAmountException($"Transaction amount {amount} is non acceptable", ex);
            }

            return(new TransactionBuildingResult(apiResponse));
        }
Exemple #19
0
        public async Task InvalidDepositAmounEnrolledToMeTest()
        {
            var blockchainType                = "Stellar";
            var hotWallet                     = "hot-wallet";
            var depositWallet                 = "deposit-wallet";
            var operationId                   = Guid.NewGuid();
            Mock <ILogFactory> logFactory     = new Mock <ILogFactory>();
            var hotWalletProviderMock         = new Mock <IHotWalletsProvider>();
            var blockchainApiClientMock       = new Mock <IBlockchainApiClient>();
            var cqrsEngineMock                = new Mock <ICqrsEngine>();
            var enrolledBalanceRepositoryMock = new Mock <IEnrolledBalanceRepository>();
            var cashinRepositoryMock          = new Mock <ICashinRepository>();
            var depositWalletLockRepository   = new Mock <IDepositWalletLockRepository>();
            var chaosKittyMock                = new Mock <IChaosKitty>();
            var xlmBlockchainAsset            = new BlockchainAsset
                                                (
                new AssetContract
            {
                AssetId  = "XLM",
                Accuracy = 7,
                Name     = "Stellar XLM"
            }
                                                );
            var blockchainAssets = new Dictionary <string, BlockchainAsset>
            {
                { xlmBlockchainAsset.AssetId, xlmBlockchainAsset }
            };
            var xlmAsset = new Asset
            {
                Id = "XLM-asset",
                BlockchainIntegrationLayerAssetId = xlmBlockchainAsset.AssetId,
                BlockchainIntegrationLayerId      = blockchainType,
                CashinMinimalAmount = 1
            };
            var assets = new Dictionary <string, Asset>
            {
                { xlmAsset.BlockchainIntegrationLayerAssetId, xlmAsset }
            };

            hotWalletProviderMock
            .Setup(x => x.GetHotWalletAddress(It.Is <string>(b => b == blockchainType)))
            .Returns(hotWallet);

            cashinRepositoryMock
            .Setup(x => x.GetOrAddAsync
                   (
                       It.Is <string>(b => b == blockchainType),
                       It.Is <string>(d => d == depositWallet),
                       It.Is <string>(a => a == xlmBlockchainAsset.AssetId),
                       It.Is <Guid>(o => o == operationId),
                       It.IsAny <Func <CashinAggregate> >()
                   ))
            .ReturnsAsync(() => CashinAggregate.StartWaitingForActualBalance
                          (
                              operationId,
                              xlmAsset.Id,
                              xlmBlockchainAsset.Accuracy,
                              xlmBlockchainAsset.Accuracy,
                              xlmBlockchainAsset.AssetId,
                              blockchainType,
                              (decimal)xlmAsset.CashinMinimalAmount,
                              depositWallet,
                              hotWallet
                          ));

            var balanceProcessor = new BalanceProcessor(
                blockchainType,
                EmptyLogFactory.Instance,
                hotWalletProviderMock.Object,
                blockchainApiClientMock.Object,
                cqrsEngineMock.Object,
                enrolledBalanceRepositoryMock.Object,
                assets,
                blockchainAssets);

            // 1. Deposit 100 is detected on DW at block 5000
            // 2. Balance processor has detected this balance, published EnrollToMatchingEngineCommand with balance 100,
            //     but failed to save aggregate state due to Azure Storage unavailability here -
            //     https://github.com/LykkeCity/Lykke.Job.BlockchainCashinDetector/blob/895c9d879e59af5c1312ef5f09f8e76a97607679/src/Lykke.Job.BlockchainCashinDetector/Workflow/PeriodicalHandlers/BalanceProcessor.cs#L173
            // In current implementation this turns to the publicshing LockDepositWalletCommand

            // Arrange

            depositWalletLockRepository
            .Setup(x => x.LockAsync
                   (
                       It.Is <DepositWalletKey>(k =>
                                                k.DepositWalletAddress == depositWallet &&
                                                k.BlockchainType == blockchainType &&
                                                k.BlockchainAssetId == xlmBlockchainAsset.AssetId),
                       It.Is <decimal>(b => b == 100),
                       It.Is <long>(d => d == 5000),
                       It.IsAny <Func <Guid> >()
                   ))
            .ReturnsAsync <DepositWalletKey, decimal, long, Func <Guid>, IDepositWalletLockRepository, DepositWalletLock>
            (
                (key, balance, block, newOperationIdFactory) =>
                DepositWalletLock.Create
                (
                    key,
                    operationId,
                    100,
                    5000
                )
            );

            blockchainApiClientMock
            .Setup(x => x.EnumerateWalletBalanceBatchesAsync
                   (
                       It.IsAny <int>(),
                       It.IsAny <Func <string, int> >(),
                       It.IsAny <Func <IReadOnlyList <WalletBalance>, Task <bool> > >()
                   ))
            .ReturnsAsync <int, Func <string, int>, Func <IReadOnlyList <WalletBalance>, Task <bool> >, IBlockchainApiClient, EnumerationStatistics>
            (
                (batchSize, accuracyProvider, enumerationCallback) =>
            {
                enumerationCallback(new List <WalletBalance>
                {
                    new WalletBalance
                    (
                        new WalletBalanceContract
                    {
                        Address = depositWallet,
                        AssetId = xlmBlockchainAsset.AssetId,
                        Balance = Conversions.CoinsToContract(100, xlmBlockchainAsset.Accuracy),
                        Block   = 5000
                    },
                        assetAccuracy: xlmBlockchainAsset.Accuracy
                    )
                }).GetAwaiter().GetResult();

                return(new EnumerationStatistics(1, 1, TimeSpan.FromMilliseconds(1)));
            }
            );

            cashinRepositoryMock
            .Setup(x => x.SaveAsync(It.IsAny <CashinAggregate>()))
            .Throws <CashinAggregatePersistingFailureTestException>();

            // Act / Assert

            await Assert.ThrowsAsync <CashinAggregatePersistingFailureTestException>(async() =>
            {
                await balanceProcessor.ProcessAsync(100);
            });

            depositWalletLockRepository.Verify(x => x.LockAsync
                                               (
                                                   It.Is <DepositWalletKey>(k =>
                                                                            k.DepositWalletAddress == depositWallet &&
                                                                            k.BlockchainType == blockchainType &&
                                                                            k.BlockchainAssetId == xlmBlockchainAsset.AssetId),
                                                   It.Is <decimal>(b => b == 100),
                                                   It.Is <long>(d => d == 5000),
                                                   It.IsAny <Func <Guid> >()
                                               ));

            cqrsEngineMock.Verify(
                x => x.SendCommand
                (
                    It.Is <EnrollToMatchingEngineCommand>(c =>
                                                          c.DepositWalletAddress == depositWallet &&
                                                          c.AssetId == xlmAsset.Id &&
                                                          c.BlockchainType == blockchainType &&
                                                          c.BlockchainAssetId == xlmBlockchainAsset.AssetId &&
                                                          c.OperationId == operationId &&
                                                          // ReSharper disable once CompareOfFloatsByEqualityOperator
                                                          c.MatchingEngineOperationAmount == 100.0d),
                    It.Is <string>(c => c == BlockchainCashinDetectorBoundedContext.Name),
                    It.Is <string>(c => c == BlockchainCashinDetectorBoundedContext.Name),
                    It.IsAny <uint>()
                ),
                Times.Once);

            // The bug is:
            // 3. One more deposit has detected and DW balance is changed to 300 at block 5001
            // 4. Balance processor has detected balance 300, publish EnrollToMatchingEngineCommand with balance 300 and saved aggregate.
            // 5. First enrollement command is processed and 100 is enrolled to ME
            // 6. Second enrollement command with amount = 300 is processed but it's deduplicated by ME
            // 7. Finally aggregate contains ME amount = 300, but actually only 100 is enrolled
            // Should be:
            // There should be the same balance 100 at block 5000 as in first iteration

            // Arrange

            depositWalletLockRepository
            .Setup(x => x.LockAsync
                   (
                       It.Is <DepositWalletKey>(k =>
                                                k.DepositWalletAddress == depositWallet &&
                                                k.BlockchainType == blockchainType &&
                                                k.BlockchainAssetId == xlmBlockchainAsset.AssetId),
                       It.Is <decimal>(b => b == 300),
                       It.Is <long>(d => d == 5001),
                       It.IsAny <Func <Guid> >()
                   ))
            .ReturnsAsync <DepositWalletKey, decimal, long, Func <Guid>, IDepositWalletLockRepository, DepositWalletLock>
            (
                (key, balance, block, newOperationIdFactory) =>
                DepositWalletLock.Create
                (
                    key,
                    operationId,
                    100,
                    5000
                )
            );

            blockchainApiClientMock
            .Setup(x => x.EnumerateWalletBalanceBatchesAsync
                   (
                       It.IsAny <int>(),
                       It.IsAny <Func <string, int> >(),
                       It.IsAny <Func <IReadOnlyList <WalletBalance>, Task <bool> > >()
                   ))
            .ReturnsAsync <int, Func <string, int>, Func <IReadOnlyList <WalletBalance>, Task <bool> >, IBlockchainApiClient, EnumerationStatistics>
            (
                (batchSize, accuracyProvider, enumerationCallback) =>
            {
                enumerationCallback(new List <WalletBalance>
                {
                    new WalletBalance
                    (
                        new WalletBalanceContract
                    {
                        Address = depositWallet,
                        AssetId = xlmBlockchainAsset.AssetId,
                        Balance = Conversions.CoinsToContract(300, xlmBlockchainAsset.Accuracy),
                        Block   = 5001
                    },
                        assetAccuracy: xlmBlockchainAsset.Accuracy
                    )
                }).GetAwaiter().GetResult();

                return(new EnumerationStatistics(1, 1, TimeSpan.FromMilliseconds(1)));
            }
            );

            cashinRepositoryMock
            .Setup(x => x.SaveAsync(It.IsAny <CashinAggregate>()))
            .Returns(Task.CompletedTask);

            depositWalletLockRepository.Invocations.Clear();
            cqrsEngineMock.Invocations.Clear();
            cashinRepositoryMock.Invocations.Clear();

            // Act

            await balanceProcessor.ProcessAsync(100);

            // Verify

            depositWalletLockRepository.Verify(
                x => x.LockAsync
                (
                    It.Is <DepositWalletKey>(k =>
                                             k.DepositWalletAddress == depositWallet &&
                                             k.BlockchainType == blockchainType &&
                                             k.BlockchainAssetId == xlmBlockchainAsset.AssetId),
                    It.Is <decimal>(b => b == 300),
                    It.Is <long>(d => d == 5001),
                    It.IsAny <Func <Guid> >()
                ),
                Times.Once);

            cqrsEngineMock.Verify(
                x => x.SendCommand
                (
                    It.Is <EnrollToMatchingEngineCommand>(c =>
                                                          c.DepositWalletAddress == depositWallet &&
                                                          c.AssetId == xlmAsset.Id &&
                                                          c.BlockchainType == blockchainType &&
                                                          c.BlockchainAssetId == xlmBlockchainAsset.AssetId &&
                                                          c.OperationId == operationId &&
                                                          // ReSharper disable once CompareOfFloatsByEqualityOperator
                                                          c.MatchingEngineOperationAmount == 100.0d),
                    It.Is <string>(c => c == BlockchainCashinDetectorBoundedContext.Name),
                    It.Is <string>(c => c == BlockchainCashinDetectorBoundedContext.Name),
                    It.IsAny <uint>()
                ),
                Times.Once);


            cashinRepositoryMock.Verify(x => x.SaveAsync
                                        (
                                            It.Is <CashinAggregate>(a =>
                                                                    a.OperationAmount == 100 &&
                                                                    a.MeAmount == 100 &&
                                                                    a.BalanceAmount == 100 &&
                                                                    a.BalanceBlock == 5000 &&
                                                                    a.DepositWalletAddress == depositWallet &&
                                                                    a.HotWalletAddress == hotWallet &&
                                                                    a.OperationId == operationId &&
                                                                    a.AssetAccuracy == xlmBlockchainAsset.Accuracy &&
                                                                    a.AssetId == xlmAsset.Id &&
                                                                    a.BlockchainAssetId == xlmBlockchainAsset.AssetId &&
                                                                    a.BlockchainType == blockchainType &&
                                                                    a.CashinMinimalAmount == (decimal)xlmAsset.CashinMinimalAmount &&
                                                                    a.State == CashinState.Started
                                                                    )
                                        ));
        }
        public async Task <BroadcastedTransaction> GetBroadcastedTransactionAsync(Guid operationId, BlockchainAsset asset)
        {
            ValidateOperationIdIsNotEmpty(operationId);
            ValidateAssetIsNotNull(asset);

            var apiResponse = await _runner.RunWithRetriesAsync(() => _api.GetBroadcastedTransactionAsync(operationId));

            return(new BroadcastedTransaction(apiResponse, asset.Accuracy));
        }
Exemple #21
0
        /// <inheritdoc />
        public async Task <BroadcastedTransactionWithManyOutputs> GetBroadcastedTransactionWithManyOutputsAsync(Guid operationId, BlockchainAsset asset)
        {
            var result = await TryGetBroadcastedTransactionWithManyOutputsAsync(operationId, asset);

            if (result == null)
            {
                throw new ResultValidationException("Transaction is not found");
            }

            return(result);
        }
Exemple #22
0
        /// <inheritdoc />
        public async Task <TransactionBuildingResult> BuildTransactionWithManyOutputsAsync(Guid operationId, string fromAddress, string fromAddressContext, IEnumerable <BuildingTransactionOutput> outputs, BlockchainAsset asset)
        {
            ValidateOperationIdIsNotEmpty(operationId);
            ValidateToAddressIsNotEmpty(fromAddress);
            // ReSharper disable once PossibleMultipleEnumeration
            ValidateOutputsNotNull(outputs);
            ValidateAssetIsNotNull(asset);

            try
            {
                var apiResponse = await _runner.RunWithRetriesAsync(() => _api.BuildTransactionWithManyOutputsAsync(
                                                                        new BuildTransactionWithManyOutputsRequest
                {
                    OperationId        = operationId,
                    FromAddress        = fromAddress,
                    FromAddressContext = fromAddressContext,
                    // ReSharper disable once PossibleMultipleEnumeration
                    Outputs = outputs
                              .Select(o => o.ToContract(asset.Accuracy))
                              .ToArray(),
                    AssetId = asset.AssetId
                }));

                return(new TransactionBuildingResult(apiResponse));
            }
            catch (ErrorResponseException ex) when(ex.StatusCode == HttpStatusCode.NotImplemented)
            {
                throw new NotSupportedException("Operation is not supported by the blockchain. See GetCapabilitiesAsync", ex);
            }
            catch (ErrorResponseException ex) when(ex.StatusCode == HttpStatusCode.Conflict)
            {
                throw new TransactionAlreadyBroadcastedException(ex);
            }
        }
Exemple #23
0
        /// <inheritdoc />
        public async Task <TransactionBuildingResult> BuildSingleTransactionAsync(Guid operationId, string fromAddress, string fromAddressContext, string toAddress, BlockchainAsset asset, decimal amount, bool includeFee)
        {
            ValidateOperationIdIsNotEmpty(operationId);
            ValidateFromAddresIsNotEmpty(fromAddress);
            ValidateToAddressIsNotEmpty(toAddress);
            ValidateAssetIsNotNull(asset);
            ValidateAmountRange(amount);

            try
            {
                var apiResponse = await _runner.RunWithRetriesAsync(() => _api.BuildSingleTransactionAsync(
                                                                        new BuildSingleTransactionRequest
                {
                    OperationId        = operationId,
                    FromAddress        = fromAddress,
                    FromAddressContext = fromAddressContext,
                    ToAddress          = toAddress,
                    AssetId            = asset.AssetId,
                    Amount             = Conversions.CoinsToContract(amount, asset.Accuracy),
                    IncludeFee         = includeFee
                }));

                return(new TransactionBuildingResult(apiResponse));
            }
            catch (ErrorResponseException ex) when(ex.StatusCode == HttpStatusCode.Conflict)
            {
                throw new TransactionAlreadyBroadcastedException(ex);
            }
        }
Exemple #24
0
        public NemBalanceProvider(string baseUrl)
        {
            _baseUrl = baseUrl;

            _nemAsset = new BlockchainAsset("XEM", "XEM", "903eafbd-cc29-4d60-8d7d-907695d9caae");
        }
 public string Format(string address, BlockchainAsset asset)
 {
     return($"https://gastracker.io/addr/{address}");
 }
 public string Format(string address, BlockchainAsset asset)
 {
     return($"https://explorer.dcrdata.org/address/{address}");
 }
 /// <inheritdoc />
 public async Task <BroadcastedTransaction> TryGetBroadcastedTransactionAsync(Guid operationId, BlockchainAsset asset)
 {
     try
     {
         return(await GetBroadcastedTransactionAsync(operationId, asset));
     }
     catch (ErrorResponseException ex) when(ex.StatusCode == HttpStatusCode.NoContent)
     {
         return(null);
     }
 }
        public SteemBalanceProvider(string baseUrl)
        {
            _baseUrl = baseUrl;

            _steemAsset = new BlockchainAsset("STEEM", "STEEM", "72da9464-49d0-4f95-983d-635c04e39f3c");
        }
Exemple #29
0
 public string Format(string address, BlockchainAsset asset)
 {
     return($"https://explorer.bitcoingold.org/insight/address/{address}");
 }
 public string Format(string address, BlockchainAsset asset)
 {
     return($"http://explorer.nemchina.com/#/s_account?account={address}");
 }