Exemple #1
0
        private void RegisterRepo(ContainerBuilder builder)
        {
            builder.Register(x => new AssetRepository())
            .As <IAssetRepository>()
            .SingleInstance();

            var connectionString = _settings.Nested(p => p.Bitcoin.Db.DataConnString);

            builder.Register(x => OperationMetaRepository.Create(connectionString, x.Resolve <ILogFactory>()))
            .As <IOperationMetaRepository>()
            .SingleInstance();

            builder.Register(x => OperationEventRepository.Create(connectionString, x.Resolve <ILogFactory>()))
            .As <IOperationEventRepository>()
            .SingleInstance();

            builder.Register(x => UnconfirmedTransactionRepository.Create(connectionString, x.Resolve <ILogFactory>()))
            .As <IUnconfirmedTransactionRepository>()
            .SingleInstance();


            builder.Register(x => ObservableOperationRepository.Create(connectionString, x.Resolve <ILogFactory>()))
            .As <IObservableOperationRepository>()
            .SingleInstance();

            builder.Register(x => ObservableWalletRepository.Create(connectionString, x.Resolve <ILogFactory>()))
            .As <IObservableWalletRepository>()
            .SingleInstance();

            builder.Register(x => WalletBalanceRepository.Create(connectionString, x.Resolve <ILogFactory>()))
            .As <IWalletBalanceRepository>()
            .SingleInstance();

            builder.Register(x => LastProcessedBlockRepository.Create(connectionString, x.Resolve <ILogFactory>()))
            .As <ILastProcessedBlockRepository>()
            .SingleInstance();

            builder.Register(x => SpentOutputRepository.Create(connectionString, x.Resolve <ILogFactory>()))
            .As <ISpentOutputRepository>()
            .SingleInstance();

            builder.Register(x => FeeRateRepository.Create(connectionString, x.Resolve <ILogFactory>()))
            .As <IFeeRateRepository>()
            .SingleInstance();
        }
Exemple #2
0
        private static async Task Execute(string bitcoinCashDataConnString,
                                          string settingsUrl,
                                          string bitcoinCashNetwork,
                                          string blockchainType)
        {
            BCash.Instance.EnsureRegistered();
            var network      = Network.GetNetwork(bitcoinCashNetwork);
            var bcashNetwork = network == Network.Main ? BCash.Instance.Mainnet : BCash.Instance.Regtest;

            var logConsole = LogFactory.Create().AddConsole();
            var settings   = new SettingsServiceReloadingManager <AppSettings>(settingsUrl, p => {});

            var walletRepo = BlockchainWalletsRepository.Create(settings.Nested(p => p.BlockchainWalletsService.Db.DataConnString),
                                                                logConsole);

            var firstGenerationBlockchainWalletRepository = FirstGenerationBlockchainWalletRepository.Create(settings.Nested(x => x.BlockchainWalletsService.Db.ClientPersonalInfoConnString), logConsole);

            var observableWalletsRepo = ObservableWalletRepository.Create(new ReloadingManagerAdapter <string>(bitcoinCashDataConnString),
                                                                          logConsole);

            var addressValidator = new AddressValidator(network, bcashNetwork);

            Console.WriteLine("Retrieving observable wallets");

            var observableWallets = (await observableWalletsRepo.GetAll()).ToList();

            Console.WriteLine("Processing items");

            var counter = 0;

            foreach (var observableWallet in observableWallets)
            {
                counter++;

                var address = addressValidator.GetBitcoinAddress(observableWallet.Address);

                if (address == null)
                {
                    throw new ArgumentException($"Unrecognized address {observableWallet.Address}",
                                                nameof(observableWallet.Address));
                }

                var oldAdrr = address.ScriptPubKey.GetDestinationAddress(network).ToString();
                var newAddr = address.ScriptPubKey.GetDestinationAddress(bcashNetwork).ToString();

                Console.WriteLine($"Processing {observableWallet.Address}:{oldAdrr}:{newAddr} -- {counter} of {observableWallets.Count}");

                var wallet = await walletRepo.TryGetAsync(blockchainType, oldAdrr);

                if (wallet == null)
                {
                    var prevColor = Console.ForegroundColor;
                    Console.ForegroundColor = ConsoleColor.Yellow;
                    Console.WriteLine($"Wallet not found {observableWallet.Address} -{blockchainType}. Queued by {oldAdrr}");
                    Console.ForegroundColor = prevColor;

                    continue;
                }

                var oldCredsRecord = new BcnCredentialsRecord
                {
                    Address      = string.Empty,
                    AssetAddress = oldAdrr,
                    ClientId     = wallet.ClientId.ToString(),
                    EncodedKey   = string.Empty,
                    PublicKey    = string.Empty,
                    AssetId      = $"{blockchainType} ({wallet.AssetId})"
                };

                var newCredsRecord = new BcnCredentialsRecord
                {
                    Address      = string.Empty,
                    AssetAddress = newAddr,
                    ClientId     = wallet.ClientId.ToString(),
                    EncodedKey   = string.Empty,
                    PublicKey    = string.Empty,
                    AssetId      = $"{blockchainType} ({wallet.AssetId})"
                };

                await firstGenerationBlockchainWalletRepository.DeleteIfExistAsync(oldCredsRecord);

                await firstGenerationBlockchainWalletRepository.InsertOrReplaceAsync(newCredsRecord);

                await walletRepo.DeleteIfExistsAsync(wallet.BlockchainType, wallet.ClientId, oldAdrr);

                await walletRepo.AddAsync(wallet.BlockchainType, wallet.ClientId, newAddr, wallet.CreatorType);
            }

            Console.WriteLine("All done");
        }
        private static async Task Execute(string settingsUrl)
        {
            if (!Uri.TryCreate(settingsUrl, UriKind.Absolute, out _))
            {
                Console.WriteLine($"{SettingsUrl}: {settingsUrl} should be a valid uri");

                return;
            }

            var logFactory = LogFactory.Create().AddConsole();

            var settings = new SettingsServiceReloadingManager <AppSettings>(settingsUrl).Nested(x => x.BitcoinCashApi);

            BCash.Instance.EnsureRegistered();
            var network      = Network.GetNetwork(settings.CurrentValue.Network);
            var bcashNetwork = network == Network.Main ? BCash.Instance.Mainnet : BCash.Instance.Regtest;

            var addressValidator = new AddressValidator(network, bcashNetwork);

            var observableWalletRepository = new ObservableWalletRepository(AzureTableStorage <ObservableWalletEntity> .Create(
                                                                                settings.Nested(p => p.Db.DataConnString),
                                                                                "ObservableWallets", logFactory));

            var observableWalletV2Repository = new ObservableWalletRepository(AzureTableStorage <ObservableWalletEntity> .Create(
                                                                                  settings.Nested(p => p.Db.DataConnString),
                                                                                  "ObservableWalletsV2", logFactory));

            var walletBalanceV2Repo = new WalletBalanceRepository(
                AzureTableStorage <WalletBalanceEntity> .Create(settings.Nested(p => p.Db.DataConnString),
                                                                "WalletBalancesV2", logFactory));

            var bcProvider = new RpcBlockchainProvider(new RPCClient(
                                                           new NetworkCredential(settings.CurrentValue.Rpc.UserName, settings.CurrentValue.Rpc.Password),
                                                           new Uri(settings.CurrentValue.Rpc.Host),
                                                           bcashNetwork), addressValidator, logFactory.CreateLog("temp"));

            var walletBalanceService = new WalletBalanceService(walletBalanceV2Repo,
                                                                observableWalletV2Repository,
                                                                bcProvider,
                                                                new OperationsConfirmationsSettings
            {
                MinConfirmationsToDetectOperation = settings.CurrentValue.MinConfirmationsToDetectOperation
            });

            Console.WriteLine("Retrieving observable wallets");

            var observableWallets = (await observableWalletRepository.GetAll()).ToList();

            var obserwabletWalletsTransformation = observableWallets.ToDictionary(observableWallet => observableWallet.Address, observableWallet =>
            {
                var addr = addressValidator.GetBitcoinAddress(observableWallet.Address);

                if (addr == null)
                {
                    throw new ArgumentException($"Unable to recognize address {observableWallet.Address}", nameof(observableWallet.Address));
                }

                var oldAdrr = addr.ScriptPubKey.GetDestinationAddress(network).ToString();
                var newAddr = addr.ScriptPubKey.GetDestinationAddress(bcashNetwork).ToString();

                if (!string.Equals(observableWallet.Address, oldAdrr, StringComparison.InvariantCultureIgnoreCase))
                {
                    var prevColor           = Console.ForegroundColor;
                    Console.ForegroundColor = ConsoleColor.Yellow;
                    Console.WriteLine($"{observableWallet.Address} not in obsolete format. Old format: {oldAdrr} | New Format {newAddr}");
                    Console.ForegroundColor = prevColor;
                }

                return(newAddr);
            });

            var refillingProgress = 0;

            Console.WriteLine("Filling table ObservableWalletsV2");
            await observableWallets.ForEachAsyncSemaphore(8, async observableWallet =>
            {
                var progress   = Interlocked.Increment(ref refillingProgress);
                var newAddress = obserwabletWalletsTransformation[observableWallet.Address];

                Console.WriteLine($"Inserting obserwablewallet record {observableWallet.Address} => {newAddress} " +
                                  $"-- {progress} of {observableWallets.Count}");

                await observableWalletV2Repository.Insert(ObservableWallet.Create(newAddress));
            });

            var updatingBalanceProgress = 0;

            Console.WriteLine("Filling table WalletBalancesV2");
            await observableWallets.ForEachAsyncSemaphore(8, async observableWallet =>
            {
                var progress = Interlocked.Increment(ref updatingBalanceProgress);

                var newAddress = obserwabletWalletsTransformation[observableWallet.Address];

                Console.WriteLine($"Updating balance record {observableWallet.Address} => {newAddress} " +
                                  $"-- {progress} of {observableWallets.Count}");

                await walletBalanceService.UpdateBalance(newAddress);
            });

            Console.WriteLine("All done!");
        }
        private static async Task Import(string settingsUrl, string hotwallet, string timestamp, string batchSize)
        {
            if (!Uri.TryCreate(settingsUrl, UriKind.Absolute, out _))
            {
                Console.WriteLine($"{SettingsUrl}: {settingsUrl} should be a valid uri");

                return;
            }

            DateTime timeStampTyped;

            if (!DateTime.TryParse(timestamp, out timeStampTyped))
            {
                Console.WriteLine($"{Timestamp}: {timestamp} should be Date time ");

                return;
            }

            if (!DateTime.TryParse(timestamp, out timeStampTyped))
            {
                Console.WriteLine($"{Timestamp}: {timestamp} should be a valid Date time ");

                return;
            }

            if (!int.TryParse(batchSize, out var batchSizeTyped))
            {
                Console.WriteLine($"{BatchSize}: {batchSize} should be a valid integer ");

                return;
            }

            var logFactory = LogFactory.Create().AddConsole();

            var settings = new SettingsServiceReloadingManager <AppSettings>(settingsUrl).Nested(x => x.BitcoinCashApi);

            var network          = Network.GetNetwork(settings.CurrentValue.Network);
            var bcashNetwork     = network == Network.Main ? BCash.Instance.Mainnet : BCash.Instance.Regtest;
            var addressValidator = new AddressValidator(network, bcashNetwork);
            var hotwalletTyped   = addressValidator.GetBitcoinAddress(hotwallet);

            if (hotwalletTyped == null)
            {
                Console.WriteLine($"{HotWallet}: {hotwallet} should be a valid bitcoin address");

                return;
            }

            var authTokenBytes = Encoding.ASCII.GetBytes($"{settings.CurrentValue.Rpc.UserName}:{settings.CurrentValue.Rpc.Password}");
            var authToken      = Convert.ToBase64String(authTokenBytes);
            var httpClient     = new HttpClient
            {
                BaseAddress           = new Uri(settings.CurrentValue.Rpc.Host),
                Timeout               = TimeSpan.FromMinutes(30),
                DefaultRequestHeaders =
                {
                    Authorization = new AuthenticationHeaderValue("Basic", authToken)
                }
            };

            var observableWalletRepository = new ObservableWalletRepository(AzureTableStorage <ObservableWalletEntity> .Create(
                                                                                settings.Nested(p => p.Db.DataConnString),
                                                                                "ObservableWalletsV2", logFactory));

            Console.WriteLine("Retrieving observable wallets");

            var observableWallets = await observableWalletRepository.GetAll();

            var walletsToImport = observableWallets
                                  .Select(p => addressValidator.GetBitcoinAddress(p.Address))
                                  .Concat(new[] { hotwalletTyped })
                                  .ToList();

            Console.WriteLine($"Importing {walletsToImport.Count} addresses in node started at {DateTime.UtcNow}. Timestamp {timeStampTyped}. Batch size {batchSize}");

            var batchNum = 1;

            foreach (var batch in walletsToImport.Batch(batchSizeTyped))
            {
                Console.WriteLine($"{DateTime.UtcNow} Importing batch {batchNum++}...");

                var payload = new
                {
                    jsonrpc = "1.0",
                    id      = Guid.NewGuid().ToString(),
                    method  = "importmulti",
                    @params = new object[]
                    {
                        batch.Select(address => new
                        {
                            scriptPubKey = new ImportMultiAddress.ScriptPubKeyObject(address),
                            timestamp    = Utils.DateTimeToUnixTime(new DateTimeOffset(timeStampTyped))
                        }),
                        new
                        {
                            rescan = true
                        }
                    }
                };

                await Policy
                .Handle <Exception>()
                .RetryAsync(5, (e, i) =>
                {
                    Console.WriteLine($"Retrying ({i})...");
                })
                .ExecuteAsync(async() =>
                {
                    using (var content = new StringContent(JsonConvert.SerializeObject(payload), Encoding.UTF8, "application/json"))
                    {
                        using (var response = await httpClient.PostAsync("", content))
                        {
                            if (response.StatusCode != HttpStatusCode.OK)
                            {
                                Console.WriteLine($"Failed to execute RPC call. Response: {response.StatusCode}");
                                throw new InvalidOperationException($"Failed to execute RPC call. Response: {response.StatusCode}, {await response.Content.ReadAsStringAsync()}");
                            }
                        }
                    }
                });

                Console.WriteLine($"{DateTime.UtcNow} Batch imported");
            }

            Console.WriteLine($"Import completed at {DateTime.UtcNow}");
        }