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(); }
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}"); }