示例#1
0
        public IBitGoApi GetByUser(string brokerId, string userId, string coinId, string newApiKey)
        {
            var bitGoUser = _bitgoUserReader.Get(
                BitGoUserNoSqlEntity.GeneratePartitionKey(brokerId),
                BitGoUserNoSqlEntity.GenerateRowKey(BitGoUserNoSqlEntity.TechSignerId,
                                                    coinId)) ??
                            _bitgoUserReader.Get(
                BitGoUserNoSqlEntity.GeneratePartitionKey(brokerId),
                BitGoUserNoSqlEntity.GenerateRowKey(BitGoUserNoSqlEntity.TechSignerId,
                                                    BitGoUserNoSqlEntity.DefaultCoin));

            var apiKeyEnc = bitGoUser?.User?.ApiKey;

            if (string.IsNullOrEmpty(apiKeyEnc) && string.IsNullOrEmpty(newApiKey))
            {
                _logger.LogError("Tech account is not configured, id = {techSignerName}",
                                 BitGoUserNoSqlEntity.TechSignerId);
                return(null);
            }

            lock (_clients)
            {
                if (!string.IsNullOrEmpty(apiKeyEnc) && _clients.TryGetValue(apiKeyEnc, out var api))
                {
                    return(api);
                }
            }

            var coin = _bitgoCointReader.Get(BitgoCoinEntity.GeneratePartitionKey(),
                                             BitgoCoinEntity.GenerateRowKey(coinId));

            if (coin == null)
            {
                _logger.LogError("Cannot fond bitgo coin id = {symbol}", coinId);
                return(null);
            }

            var apiKey = string.IsNullOrEmpty(apiKeyEnc) ? newApiKey : _encryptionService.Decrypt(apiKeyEnc);

            var client = new BitGoClient(
                apiKey, Program.Settings.BitgoExpressUrlMainNet,
                apiKey, Program.Settings.BitgoExpressUrlTestNet);

            lock (_clients)
            {
                _clients[apiKey] = coin.IsMainNet ? client.MainNet : client.TestNet;
                return(_clients[apiKey]);
            }
        }
        public async Task <SendTransactionResponse> SignAndSendTransactionAsync(SendTransactionRequest request)
        {
            _logger.LogInformation("Transfer Request: {jsonText}", JsonConvert.SerializeObject(request));

            try
            {
                var client = _bitGoClientService.GetByUser(request.BrokerId, BitGoUserNoSqlEntity.TechSignerId, request.BitgoCoin);
                if (client == null)
                {
                    throw new Exception($"Tech account is not configured, id = {BitGoUserNoSqlEntity.TechSignerId}, coin = {request.BitgoCoin}");
                }

                var wallet = _myNoSqlServerWalletDataReader.Get(
                    BitGoWalletNoSqlEntity.GeneratePartitionKey(request.BrokerId),
                    BitGoWalletNoSqlEntity.GenerateRowKey(request.BitgoWalletId));

                if (string.IsNullOrEmpty(wallet?.Wallet?.ApiKey))
                {
                    _logger.LogError("Cannot find pass phase for wallet {bitgoWalletIdText}", request.BitgoWalletId);
                    throw new Exception($"Cannot find pass phase for wallet {request.BitgoWalletId}");
                }

                var walletPass = _encryptionService.Decrypt(wallet.Wallet.ApiKey);

                var result = await client.SendCoinsAsync(request.BitgoCoin, request.BitgoWalletId,
                                                         walletPass, request.SequenceId,
                                                         request.Amount, request.Address);

                if (!result.Success)
                {
                    switch (result.Error.Code)
                    {
                    case "DuplicateSequenceIdError":
                    {
                        var transaction = await client.GetTransferBySequenceIdAsync(request.BitgoCoin,
                                                                                    request.BitgoWalletId, request.SequenceId);

                        if (!transaction.Success || transaction.Data == null)
                        {
                            _logger.LogError("Transfer is Duplicate, but cannot found transaction: {jsonText}",
                                             JsonConvert.SerializeObject(transaction.Error));

                            return(new SendTransactionResponse()
                                {
                                    Error = result.Error
                                });
                        }

                        _logger.LogInformation("Transfer is Duplicate, Result: {jsonText}",
                                               JsonConvert.SerializeObject(transaction.Data));

                        return(new SendTransactionResponse()
                            {
                                DuplicateTransaction = transaction.Data
                            });
                    }

                    case "needs unlock":
                        await _sessionPublisher.PublishAsync(new SignalBitGoSessionStateUpdate()
                        {
                            State = BitGoSessionState.Locked
                        });

                        return(new SendTransactionResponse()
                        {
                            Error =
                            {
                                Code         = "needs unlock",
                                ErrorMessage = "Session is locked"
                            }
                        });
                    }
                }

                if (!result.Success)
                {
                    _logger.LogError("Transfer Result: {jsonText}", JsonConvert.SerializeObject(result.Error));
                    return(new SendTransactionResponse()
                    {
                        Error = result.Error
                    });
                }

                await AddVolumeToApiKey(request.BrokerId, _encryptionService.GetSha256Hash(wallet.Wallet.ApiKey),
                                        request.BitgoCoin,
                                        _assetMapper.ConvertAmountFromBitgo(request.BitgoCoin, long.Parse(request.Amount)));

                _logger.LogInformation("Transfer Result: {jsonText}", JsonConvert.SerializeObject(result.Data));
                return(new SendTransactionResponse()
                {
                    Result = result.Data
                });
            }
            catch (Exception ex)
            {
                _logger.LogError(ex, "Transfer Request ERROR: {jsonText}. Error: {message}",
                                 JsonConvert.SerializeObject(request), ex.Message);
                throw;
            }
        }