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