public async Task <ExchangeResult> PreExchangeAsync(PreExchangeCommand cmd) { BlockchainType network = await _assetSettingsService.GetNetworkAsync(cmd.SourceAssetId); if (await _assetSettingsService.GetNetworkAsync(cmd.DestAssetId) != network) { throw new ExchangeOperationNotSupportedException("Assets are being served by different blockchains"); } string sourceWalletAddress = (await _merchantWalletService.GetDefaultAsync( cmd.MerchantId, cmd.SourceAssetId, PaymentDirection.Outgoing)).WalletAddress; await _walletBalanceValidator.ValidateTransfer(sourceWalletAddress, cmd.SourceAssetId, cmd.SourceAmount); string hotwallet = _bcnSettingsResolver.GetExchangeHotWallet(network); IAssetPairRate rate = await _assetRatesService.GetCurrentRateAsync(cmd.SourceAssetId, cmd.DestAssetId); decimal exchangeAmount = cmd.SourceAmount * rate.BidPrice; await _walletBalanceValidator.ValidateTransfer(hotwallet, cmd.DestAssetId, exchangeAmount); return(new ExchangeResult { SourceAssetId = cmd.SourceAssetId, SourceAmount = cmd.SourceAmount, DestAssetId = cmd.DestAssetId, DestAmount = exchangeAmount, Rate = rate.BidPrice }); }
public static WalletAllocationPolicy GetPolicy(this IList <BlockchainWalletAllocationPolicy> src, BlockchainType blockchainType) { BlockchainWalletAllocationPolicy policySetting = src.SingleOrDefault(x => x.Blockchain == blockchainType); return(policySetting?.WalletAllocationPolicy ?? WalletAllocationPolicy.New); }
public string GetCashoutHotWallet(BlockchainType blockchain) { string address; switch (blockchain) { case BlockchainType.Bitcoin: address = _blockchainSettings.Bitcoin.CashoutHotWalletAddress; break; case BlockchainType.Ethereum: case BlockchainType.EthereumIata: address = _blockchainSettings.Ethereum.CashoutHotWalletAddress; break; case BlockchainType.None: address = string.Empty; break; default: throw new Exception("Unexpected blockchain type"); } return(address); }
public Blockchain(string Group, string Name, BlockchainType Type, bool AcceptBodySignature) { this.Group = Group; this.Name = Name; this.Type = Type; this.AcceptBodySignature = AcceptBodySignature; }
public override async Task <bool> Execute(Source source, BlockchainType blockchain, BlockchainNetwork network) { ClientBase.ConnectionTimeout = new TimeSpan(0, 0, 5, 0); await using (var connection = new MySqlConnection(OTHubSettings.Instance.MariaDB.ConnectionString)) { int blockchainID = await GetBlockchainID(connection, blockchain, network); string currentHubAddress = await connection.ExecuteScalarAsync <string>("select HubAddress from blockchains where id = @id", new { id = blockchainID }); var allHubAddresses = new List <String>(); allHubAddresses.Add(currentHubAddress); var addresses = allHubAddresses.Distinct(); foreach (var address in addresses) { await PopulateSmartContracts(connection, address, address == currentHubAddress, blockchainID, blockchain, network); } } await SmartContractManager.Load(); return(true); }
public async Task <bool> Execute(string address, BlockchainType blockchain) { if (!SupportedNetworks.Contains(blockchain)) { throw new BlockchainTypeNotSupported(blockchain); } IBlockchainApiClient blockchainClient = _blockchainClientProvider.Get(blockchain); try { return(await blockchainClient.ValidateAddressAsync(address)); } catch (WalletAddressValidationException e) { _log.ErrorWithDetails(e, new { Blockchain = e.Blockchain.ToString(), e.Address }); throw; } catch (UnrecognizedApiResponse e) { _log.ErrorWithDetails(e, new { e.ResponseType }); throw; } }
public async Task <IList <IBcnWalletUsage> > GetVacantAsync(BlockchainType blockchain) { IList <BcnWalletUsageEntity> usages = await _tableStorage.GetDataAsync(x => x.Blockchain == blockchain && string.IsNullOrEmpty(x.OccupiedBy)); return(Mapper.Map <IList <IBcnWalletUsage> >(usages)); }
public async Task <IBcnWalletUsage> OccupyAsync(BlockchainType blockchain, string occupiedBy) { IEnumerable <IBcnWalletUsage> vacantWallets = await _walletUsageRepository.GetVacantAsync(blockchain); if (!vacantWallets.Any()) { throw new WalletAddressAllocationException(blockchain); } foreach (IBcnWalletUsage vacantWalletUsage in vacantWallets) { IBcnWalletUsage lockedUsage; try { lockedUsage = await OccupyAsync( vacantWalletUsage.WalletAddress, vacantWalletUsage.Blockchain, occupiedBy); } catch (WalletAddressInUseException) { continue; } return(lockedUsage); } throw new WalletAddressAllocationException(blockchain); }
public override async void BlockchainStartup(int blockchainId, BlockchainType blockchain, BlockchainNetwork network) { string websocketsUrl; string rpcUrl; await using (var connection = new MySqlConnection(OTHubSettings.Instance.MariaDB.ConnectionString)) { rpcUrl = await connection.ExecuteScalarAsync <string>(@"SELECT BlockchainNodeUrl FROM Blockchains where id = @id", new { id = blockchainId }); websocketsUrl = await connection.ExecuteScalarAsync <string>(@"SELECT BlockchainWebSocketsUrl FROM Blockchains where id = @id", new { id = blockchainId }); } Console.WriteLine(blockchain + " RPC: " + rpcUrl); Console.WriteLine(blockchain + " WS: " + websocketsUrl); if (string.IsNullOrWhiteSpace(websocketsUrl)) { return; } #pragma warning disable CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed Task.Run(async() => await WebSocketsManager.Start(blockchainId, websocketsUrl, rpcUrl, blockchain, network)); #pragma warning restore CS4014 // Because this call is not awaited, execution of the current method continues before the call is completed }
public async Task SetDefaultAssetsAsync( string merchantId, BlockchainType network, string walletAddress, IEnumerable <string> incomingPaymentDefaults = null, IEnumerable <string> outgoingPaymentDefaults = null) { try { await _merchantWalletRespository.UpdateAsync(new MerchantWallet { MerchantId = merchantId, Network = network, WalletAddress = walletAddress, IncomingPaymentDefaults = incomingPaymentDefaults?.ToList(), OutgoingPaymentDefaults = outgoingPaymentDefaults?.ToList(), }); } catch (KeyNotFoundException e) { _log.ErrorWithDetails(e, new { merchantId, network, walletAddress }); throw new MerchantWalletNotFoundException(merchantId, network, walletAddress); } }
public WalletAddressInUseException(string walletAddress, BlockchainType blockchain) : base( "Wallet address is already in use") { WalletAddress = walletAddress; Blockchain = blockchain; }
public async Task <bool> Execute(string address, BlockchainType blockchain) { IBlockchainApiClient blockchainClient = _blockchainClientProvider.Get(blockchain); try { return(await blockchainClient.ValidateAddressAsync(address)); } catch (WalletAddressValidationException validationEx) { await _log.WriteErrorAsync(nameof(BlockchainAddressValidator), nameof(Execute), new { Blockchain = validationEx.Blockchain.ToString(), validationEx.Address }.ToJson(), validationEx); throw; } catch (UnrecognizedApiResponse responseEx) { await _log.WriteErrorAsync(nameof(BlockchainAddressValidator), nameof(Execute), new { responseEx.ResponseType }.ToJson(), responseEx); throw; } }
public SwitcheoAuthenticationProvider(ApiCredentials credentials, BlockchainType keyType) : base(new ApiCredentials(new PrivateKey(EnsureHexFormat(credentials.PrivateKey.Key, credentials.PrivateKey?.Passphrase)))) { if (this.CanSign) { if (keyType == BlockchainType.Qtum || keyType == BlockchainType.Ethereum) { throw new NotImplementedException(); } try { this.KeyType = keyType; SecureString readablePrivateKey = credentials.PrivateKey.Key; // Decrypting private key if Nep2 format was provided if (WalletsHelper.IsNep2(credentials.PrivateKey.Key)) { readablePrivateKey = Nep2.Decrypt(credentials.PrivateKey.Key.GetString(), credentials.PrivateKey.Passphrase.GetString()).Result.ToHexString().ToSecureString(); } // Extracting wallet informations (public key, script hash, address and fixed address) this.WalletInformations = WalletsHelper.GetWalletInformations(readablePrivateKey, keyType); } catch (Exception) { throw privateKeyException; } } }
public string GetExplorerUrl(BlockchainType blockchain, string transactionHash) { Uri uri = null; switch (blockchain) { case BlockchainType.Bitcoin: uri = new Uri( new Uri( _blockchainSettings.Bitcoin.BlockchainExplorer.TransactionUrl .AddLastSymbolIfNotExists('/')), transactionHash); break; case BlockchainType.Ethereum: uri = new Uri( new Uri( _blockchainSettings.Ethereum.BlockchainExplorer.TransactionUrl .AddLastSymbolIfNotExists('/')), transactionHash); break; case BlockchainType.None: break; default: throw new Exception("Unexpected blockchain type"); } return(uri?.ToString() ?? string.Empty); }
public TransactionNotFoundException(BlockchainType blockchain, TransactionIdentityType identityType, string identity, string walletAddress) : base("Transaction not found") { Blockchain = blockchain; WalletAddress = walletAddress; IdentityType = identityType; Identity = identity; }
public async Task <IVirtualWallet> AddAssetAsync(string merchantId, string walletId, string assetId) { IVirtualWallet virtualWallet = await _virtualWalletService.GetAsync(merchantId, walletId); if (virtualWallet == null) { throw new WalletNotFoundException(walletId); } BlockchainType blockchainType = assetId.GetBlockchainType(); IBlockchainApiClient blockchainClient = _blockchainClientProvider.Get(blockchainType); WalletAllocationPolicy policy = _walletAllocationSettings.GetPolicy(blockchainType); IBcnWalletUsage walletUsage; switch (policy) { case WalletAllocationPolicy.New: string address = await blockchainClient.CreateAddressAsync(); walletUsage = await _bcnWalletUsageService.OccupyAsync(address, blockchainType, virtualWallet.Id); break; case WalletAllocationPolicy.Reuse: try { walletUsage = await _bcnWalletUsageService.OccupyAsync(blockchainType, virtualWallet.Id); } catch (WalletAddressAllocationException) { string newAddress = await blockchainClient.CreateAddressAsync(); walletUsage = await _bcnWalletUsageService.OccupyAsync(newAddress, blockchainType, virtualWallet.Id); } break; default: throw new UnknownWalletAllocationPolicyException(policy.ToString()); } IVirtualWallet updatedWallet = await _virtualWalletService.AddAddressAsync( virtualWallet.MerchantId, virtualWallet.Id, new BlockchainWallet { AssetId = assetId, Address = walletUsage.WalletAddress, Blockchain = walletUsage.Blockchain }); await _walletEventsPublisher.PublishAsync(walletUsage.WalletAddress, blockchainType, virtualWallet.DueDate); return(updatedWallet); }
public static async Task CreateMissingIdentities( MySqlConnection connection, Web3 cl, int blockchainId, BlockchainType blockchain, BlockchainNetwork network) { var eth = new EthApiService(cl.Client); var allIdentitiesCreated = connection .Query <OTContract_Profile_IdentityCreated>(@"select * from OTContract_Profile_IdentityCreated IC WHERE IC.NewIdentity not in (SELECT OTIdentity.Identity FROM OTIdentity WHERE BlockchainID = @BlockchainID) AND IC.BlockchainID = @blockchainID", new { blockchainId = blockchainId }) .ToArray(); foreach (var identity in allIdentitiesCreated) { var ercContract = new Contract(eth, AbiHelper.GetContractAbi(ContractTypeEnum.ERC725, blockchain, network), identity.NewIdentity); var otVersionFunction = ercContract.GetFunction("otVersion"); var value = await otVersionFunction.CallAsync <BigInteger>(); await OTIdentity.Insert(connection, new OTIdentity { TransactionHash = identity.TransactionHash, Identity = identity.NewIdentity, Version = (int)value, BlockchainID = blockchainId }); } //This only happens due to missing blockchain events (only happened in December 2018) var profilesCreatedWithoutIdentities = connection.Query( @"select TransactionHash, Profile from otcontract_profile_profilecreated WHERE Profile not in (select otidentity.Identity from otidentity WHERE BlockchainID = @blockchainID) AND BlockchainID = @blockchainID", new { blockchainId = blockchainId }).ToArray(); foreach (var profilesCreatedWithoutIdentity in profilesCreatedWithoutIdentities) { string hash = profilesCreatedWithoutIdentity.TransactionHash; string identity = profilesCreatedWithoutIdentity.Profile; var ercContract = new Contract(eth, AbiHelper.GetContractAbi(ContractTypeEnum.ERC725, blockchain, network), identity); var otVersionFunction = ercContract.GetFunction("otVersion"); var value = await otVersionFunction.CallAsync <BigInteger>(); await OTIdentity.Insert(connection, new OTIdentity { TransactionHash = hash, Identity = identity, Version = (int)value, BlockchainID = blockchainId }); } }
/// <summary> /// Checks if transaction update is supposed to be processed by current instance of service since /// there is a division between different networks /// </summary> /// <param name="walletAddress">Blockchain wallet address</param> /// <param name="blockchain">Blockchain type</param> /// <returns></returns> // todo: The division should be a matter of settings but not runtime processing private async Task ValidateWalletAddressHosterAsync(string walletAddress, BlockchainType blockchain) { string virtualAddress = await _bcnWalletUsageService.ResolveOccupierAsync(walletAddress, blockchain); if (string.IsNullOrEmpty(virtualAddress)) { throw new WalletAddressProcessingHostException(walletAddress, blockchain); } }
public string GetBlockchainTypeName(BlockchainType chainType) { if (chainType == NeuraliumBlockchainTypes.NeuraliumInstance.Neuralium) { return("Neuralium"); } return(""); }
public override ChainConfigurations GetChainConfiguration(BlockchainType chaintype) { if (chaintype.Value == NeuraliumBlockchainTypes.NeuraliumInstance.Neuralium.Value) { return(this.NeuraliumChainConfiguration); } return(null); }
public Blockchain(string Group, string Name, BlockchainType Type, BlockSynchronization HowTheBlocksAreLatched, bool AcceptBodySignature, int MaxBlockLenght = 2048, double DaysExpiredAfterInactivity = 30) { this.Group = Group; this.Name = Name; this.Type = Type; this.AcceptBodySignature = AcceptBodySignature; this.MaxBlockLenght = MaxBlockLenght; this.ExpiredAfterInactivity = TimeSpan.FromDays(DaysExpiredAfterInactivity); }
public IBlockchainApiClient Get(BlockchainType blockchainType) { if (!_blockchainClients.TryGetValue(blockchainType, out var client)) { throw new InvalidOperationException($"Blockchain client of type [{blockchainType.ToString()}] not found"); } return(client); }
public override async Task <bool> Execute(Source source, BlockchainType blockchain, BlockchainNetwork network) { await using (var connection = new MySqlConnection(OTHubSettings.Instance.MariaDB.ConnectionString)) { int blockchainID = await GetBlockchainID(connection, blockchain, network); return(await RunChildren(source, blockchain, network, blockchainID)); } }
public static async Task Start(int blockchainID, string webSocketsUrl, string rpcUrl, BlockchainType blockchainType, BlockchainNetwork blockchainNetwork) { bool failed = await Run(blockchainID, webSocketsUrl, rpcUrl, blockchainType, blockchainNetwork); if (failed) { _ = Task.Run(() => Start(blockchainID, webSocketsUrl, rpcUrl, blockchainType, blockchainNetwork)); } }
public async Task <IBcnWalletUsage> GetAsync(string walletAddress, BlockchainType blockchain) { string partitionKey = BcnWalletUsageEntity.ByWalletAddress.GeneratePartitionKey(walletAddress); string rowKey = BcnWalletUsageEntity.ByWalletAddress.GenerateRowKey(blockchain); BcnWalletUsageEntity entity = await _tableStorage.GetDataAsync(partitionKey, rowKey); return(Mapper.Map <BcnWalletUsage>(entity)); }
public async Task <ExchangeResult> ExecuteAsync(ExchangeCommand cmd) { BlockchainType network = await _assetSettingsService.GetNetworkAsync(cmd.SourceAssetId); if (await _assetSettingsService.GetNetworkAsync(cmd.DestAssetId) != network) { throw new ExchangeOperationNotSupportedException("Assets are being served by different blockchains"); } IAssetPairRate rate = await _assetRatesService.GetCurrentRateAsync(cmd.SourceAssetId, cmd.DestAssetId); if (cmd.ExpectedRate != null && rate.BidPrice != cmd.ExpectedRate) { throw new ExchangeRateChangedException(rate.BidPrice); } string hotwallet = _bcnSettingsResolver.GetExchangeHotWallet(network); string sourceAddress = await GetSourceAddressAsync(cmd); decimal exchangeAmount = cmd.SourceAmount * rate.BidPrice; await _walletBalanceValidator.ValidateTransfer(sourceAddress, cmd.SourceAssetId, cmd.SourceAmount); await _walletBalanceValidator.ValidateTransfer(hotwallet, cmd.DestAssetId, exchangeAmount); TransferResult toHotWallet = await _retryPolicy .ExecuteAsync(() => _transferService.ExchangeThrowFail( cmd.SourceAssetId, sourceAddress, hotwallet, cmd.SourceAmount)); await RegisterTransferTxsAsync(toHotWallet); string destAddress = await GetDestAddressAsync(cmd); TransferResult fromHotWallet = await _retryPolicy .ExecuteAsync(() => _transferService.ExchangeThrowFail( cmd.DestAssetId, hotwallet, destAddress, exchangeAmount)); await RegisterTransferTxsAsync(fromHotWallet, false); return(new ExchangeResult { SourceAssetId = cmd.SourceAssetId, SourceAmount = cmd.SourceAmount, DestAssetId = cmd.DestAssetId, DestAmount = exchangeAmount, Rate = rate.BidPrice }); }
public override async Task <bool> Execute(Source source, BlockchainType blockchain, BlockchainNetwork network) { ClientBase.ConnectionTimeout = new TimeSpan(0, 0, 5, 0); await using (var connection = new MySqlConnection(OTHubSettings.Instance.MariaDB.ConnectionString)) { int blockchainID = await GetBlockchainID(connection, blockchain, network); var cl = await GetWeb3(connection, blockchainID, blockchain); var eth = new EthApiService(cl.Client); foreach (var contract in await OTContract.GetByTypeAndBlockchain(connection, (int)ContractTypeEnum.Litigation, blockchainID)) { if (contract.IsArchived && contract.LastSyncedTimestamp.HasValue && (DateTime.Now - contract.LastSyncedTimestamp.Value).TotalDays <= 5) { #if DEBUG Logger.WriteLine(source, " Skipping contract: " + contract.Address); #endif continue; } Logger.WriteLine(source, " Using contract: " + contract.Address); var holdingContract = new Contract(eth, AbiHelper.GetContractAbi(ContractTypeEnum.Litigation, blockchain, network), contract.Address); var litigationInitiatedEvent = holdingContract.GetEvent("LitigationInitiated"); var litigationAnsweredEvent = holdingContract.GetEvent("LitigationAnswered"); var litigationTimedOutEvent = holdingContract.GetEvent("LitigationTimedOut"); var litigationCompletedEvent = holdingContract.GetEvent("LitigationCompleted"); var replacementStartedEvent = holdingContract.GetEvent("ReplacementStarted"); ulong size = (ulong)10000; BlockBatcher batcher = BlockBatcher.Start(contract.SyncBlockNumber, (ulong)LatestBlockNumber.Value, size, async delegate(ulong start, ulong end) { await Sync(connection, litigationInitiatedEvent, litigationAnsweredEvent, litigationTimedOutEvent, litigationCompletedEvent, replacementStartedEvent, contract, source, start, end, blockchainID, cl); }); await batcher.Execute(); } } return(true); }
public async Task <TransferResult> ExecuteAsync(TransferCommand transferCommand) { BlockchainType blockchainType = await _assetSettingsService.GetNetworkAsync(transferCommand.AssetId); IBlockchainApiClient blockchainClient = _blockchainClientProvider.Get(blockchainType); BlockchainTransferCommand cmd = new BlockchainTransferCommand(transferCommand.AssetId); string lykkeAssetId = transferCommand.AssetId.IsGuid() ? transferCommand.AssetId : await _lykkeAssetsResolver.GetLykkeId(transferCommand.AssetId); foreach (var transferCommandAmount in transferCommand.Amounts) { decimal balance = await blockchainClient.GetBalanceAsync(transferCommandAmount.Source, lykkeAssetId); if (transferCommandAmount.Amount == null) { if (balance > 0) { cmd.Amounts.Add(new TransferAmount { Amount = balance, Source = transferCommandAmount.Source, Destination = transferCommandAmount.Destination }); continue; } throw new InsufficientFundsException(transferCommandAmount.Source, transferCommand.AssetId); } if (transferCommandAmount.Amount > balance) { throw new InsufficientFundsException(transferCommandAmount.Source, transferCommand.AssetId); } cmd.Amounts.Add(transferCommandAmount); } BlockchainTransferResult blockchainTransferResult = await blockchainClient.TransferAsync(cmd); ITransfer transfer = await _transferRepository.AddAsync(new Transfer { AssetId = transferCommand.AssetId, Blockchain = blockchainTransferResult.Blockchain, CreatedOn = DateTime.UtcNow, Amounts = transferCommand.Amounts, Transactions = Mapper.Map <IEnumerable <TransferTransaction> >(blockchainTransferResult.Transactions) }); return(Mapper.Map <TransferResult>(transfer)); }
public override async Task <bool> Execute(Source source, BlockchainType blockchain, BlockchainNetwork network) { await using (var connection = new MySqlConnection(OTHubSettings.Instance.MariaDB.ConnectionString)) { int blockchainID = await GetBlockchainID(connection, blockchain, network); await OTOfferHolder.UpdateLitigationForAllOffers(connection, blockchainID); } return(true); }
public Blockchain(string @group, string name, BlockchainType type, BlockSynchronization synchronizationType, bool acceptBodySignature, int maxBlockLenght = 2048, double daysExpiredAfterInactivity = 30) { _network = NetworkInitializer.CurrentNetwork; Group = @group; Name = name; Type = type; SynchronizationType = synchronizationType; AcceptBodySignature = acceptBodySignature; MaxBlockLenght = maxBlockLenght; ExpiredAfterInactivity = TimeSpan.FromDays(daysExpiredAfterInactivity); }