예제 #1
0
        public async Task <(string, string, Error)> GenerateOrGetAddressIdAsync(string bitgoCoin, string bitgoWalletId,
                                                                                string label)
        {
            var coin = await GetCoin(bitgoCoin);

            var addresses = await _bitgoClient.Get(coin.IsMainNet).GetAddressesAsync(bitgoCoin, bitgoWalletId, label, 50);

            if (addresses.Data.TotalAddressCount > 0)
            {
                return(addresses.Data.Addresses.Last().AddressId, addresses.Data.Addresses.Last().Label, null);
            }

            var newAddress = await _bitgoClient.Get(coin.IsMainNet).CreateAddressAsync(bitgoCoin, bitgoWalletId, label);

            return(newAddress.Data?.AddressId, newAddress.Data?.Label, newAddress.Error);
        }
        public async Task HandledDepositAsync(SignalBitGoTransfer transferId)
        {
            transferId.AddToActivityAsJsonTag("bitgo signal");

            _logger.LogInformation("Request to handle transfer from BitGo: {transferJson}",
                                   JsonConvert.SerializeObject(transferId));

            var(brokerId, assetSymbol) = _assetMapper.BitgoCoinToAsset(transferId.Coin, transferId.WalletId);

            if (string.IsNullOrEmpty(brokerId) || string.IsNullOrEmpty(assetSymbol))
            {
                _logger.LogWarning("Cannot handle BitGo deposit, asset do not found {transferJson}",
                                   JsonConvert.SerializeObject(transferId));
                return;
            }

            var coin = _bitgoCoinReader.Get(BitgoCoinEntity.GeneratePartitionKey(),
                                            BitgoCoinEntity.GenerateRowKey(transferId.Coin));

            var transferResp =
                await _bitgoClient.Get(coin.IsMainNet)
                .GetTransferAsync(transferId.Coin, transferId.WalletId, transferId.TransferId);

            var transfer = transferResp.Data;

            if (transfer == null)
            {
                _logger.LogWarning("Cannot handle BitGo deposit, transfer do not found {transferJson}",
                                   JsonConvert.SerializeObject(transferId));
                Activity.Current?.SetStatus(Status.Error);
                return;
            }

            transfer.AddToActivityAsJsonTag("bitgo-transfer");

            _logger.LogInformation("Transfer from BitGo: {transferJson}", JsonConvert.SerializeObject(transfer));

            var requirement = _assetMapper.GetRequiredConfirmations(transfer.Coin);

            if (transfer.Confirmations < requirement)
            {
                _logger.LogError(
                    $"Transaction do not has enough conformations. Transaction has: {transfer.Confirmations}, requirement: {requirement}");
                Activity.Current?.SetStatus(Status.Error);
                throw new Exception(
                          $"Transaction do not has enough conformations. Transaction has: {transfer.Confirmations}, requirement: {requirement}");
            }

            if (!_assetMapper.IsWalletEnabled(transfer.Coin, transfer.WalletId))
            {
                _logger.LogError(
                    "Transfer {transferIdString} from BitGo is skipped, Wallet do not include in enabled wallet list",
                    transfer.TransferId);
                Activity.Current?.SetStatus(Status.Error);
                return;
            }

            foreach (var entryGroup in transfer.Entries
                     .Where(e => e.Value > 0 && !string.IsNullOrEmpty(e.Label) && e.WalletId == transferId.WalletId &&
                            (e.Token == null || e.Token == transferId.Coin))
                     .GroupBy(e => e.Label))
            {
                var label  = entryGroup.Key;
                var wallet = _walletMapper.BitgoLabelToWallet(label);
                if (wallet == null)
                {
                    _logger.LogWarning("Cannot found wallet for transfer entry with label={label} address={address}",
                                       label, entryGroup.First().Address);
                    continue;
                }

                wallet.WalletId.AddToActivityAsTag("walletId");
                wallet.ClientId.AddToActivityAsTag("clientId");

                var bitgoAmount = entryGroup.Sum(e => e.Value);
                var meAmount    = _assetMapper.ConvertAmountFromBitgo(transferId.Coin, bitgoAmount);

                var accuracy = _assetsDictionary.GetAssetById(new AssetIdentity()
                {
                    Symbol   = assetSymbol,
                    BrokerId = wallet.BrokerId
                }).Accuracy;

                var roundedAmount = Math.Round(meAmount, accuracy, MidpointRounding.ToNegativeInfinity);

                try
                {
                    await using var ctx = DatabaseContext.Create(_dbContextOptionsBuilder);
                    await ctx.InsertAsync(new DepositEntity
                    {
                        BrokerId      = wallet.BrokerId,
                        WalletId      = wallet.WalletId,
                        ClientId      = wallet.ClientId,
                        TransactionId = $"{transfer.TransferId}:{wallet.WalletId}",
                        Amount        = (decimal)roundedAmount,
                        AssetSymbol   = assetSymbol,
                        Comment       =
                            $"Bitgo transfer [{transferId.Coin}:{transferId.WalletId}] entry label='{label}', count entry={entryGroup.Count()}",
                        Integration    = "BitGo",
                        Txid           = transfer.TxId,
                        Status         = DepositStatus.New,
                        EventDate      = DateTime.UtcNow,
                        UpdateDate     = DateTime.UtcNow,
                        FeeAmount      = 0,
                        FeeAssetSymbol = assetSymbol,
                        CardLast4      = string.Empty
                    });
                }
                catch (Exception e)
                {
                    Console.WriteLine(e);
                    throw;
                }
            }

            _logger.LogInformation("Deposit request from BitGo {transferIdString} is handled", transfer.TransferId);
        }