示例#1
0
        public async Task Handle(CashoutTransactionStateSavedEvent evt)
        {
            var message           = evt.Message;
            var walletCredentials = await _walletCredentialsRepository.GetAsync(message.ClientId);

            var amount        = message.Amount.ParseAnyDouble();
            var transactionId = evt.Command.TransactionId.ToString();
            var context       = await _transactionService.GetTransactionContext <CashOutContextData>(transactionId);

            var isForwardWithdawal = context.AddData?.ForwardWithdrawal != null;

            var operation = new CashInOutOperation
            {
                Id             = context.CashOperationId,
                ClientId       = message.ClientId,
                Multisig       = walletCredentials?.MultiSig,
                AssetId        = message.AssetId,
                Amount         = -Math.Abs(amount),
                DateTime       = DateTime.UtcNow,
                AddressFrom    = walletCredentials?.MultiSig,
                AddressTo      = context.Address,
                TransactionId  = transactionId,
                Type           = isForwardWithdawal ? CashOperationType.ForwardCashOut : CashOperationType.None,
                BlockChainHash = string.Empty,
                State          = TransactionStates.SettledOffchain
            };

            operation.AddFeeDataToOperation(message);

            await RegisterOperation(operation);
        }
示例#2
0
        public async Task Handle(ForwardWithdawalLinkedEvent evt)
        {
            var message           = evt.Message;
            var walletCredentials = await _walletCredentialsRepository.GetAsync(message.ClientId);

            var amount        = message.Amount.ParseAnyDouble();
            var transactionId = message.Id;
            var context       = await _transactionService.GetTransactionContext <CashOutContextData>(transactionId);

            var asset = await _assetsServiceWithCache.TryGetAssetAsync(message.AssetId);

            var baseAsset = await _assetsServiceWithCache.TryGetAssetAsync(asset.ForwardBaseAsset);

            var operation = new CashInOutOperation
            {
                Id            = context.AddData.ForwardWithdrawal.Id,
                ClientId      = message.ClientId,
                Multisig      = walletCredentials?.MultiSig,
                AssetId       = baseAsset.Id,
                Amount        = Math.Abs(amount),
                DateTime      = DateTime.UtcNow.AddDays(asset.ForwardFrozenDays),
                AddressFrom   = walletCredentials?.MultiSig,
                AddressTo     = context.Address,
                TransactionId = transactionId,
                Type          = CashOperationType.ForwardCashIn,
                State         = TransactionStates.InProcessOffchain
            };

            operation.AddFeeDataToOperation(message);

            await RegisterOperation(operation);
        }
示例#3
0
        public async Task Handle(ManualTransactionStateSavedEvent evt)
        {
            var message           = evt.Message;
            var walletCredentials = await _walletCredentialsRepository.GetAsync(message.ClientId);

            var transactionId = message.Id;
            var context       = await _transactionService.GetTransactionContext <CashOutContextData>(transactionId);

            var operation = new CashInOutOperation
            {
                Id             = transactionId,
                ClientId       = message.ClientId,
                Multisig       = walletCredentials?.MultiSig,
                AssetId        = message.AssetId,
                Amount         = message.Amount.ParseAnyDouble(),
                DateTime       = DateTime.UtcNow,
                AddressFrom    = walletCredentials?.MultiSig,
                AddressTo      = context.Address,
                TransactionId  = transactionId,
                Type           = CashOperationType.None,
                BlockChainHash = string.Empty,
                State          = TransactionStates.SettledOffchain
            };

            operation.AddFeeDataToOperation(message);

            await RegisterOperation(operation);
        }
示例#4
0
        public async Task Handle(IssueTransactionStateSavedEvent evt)
        {
            var message       = evt.Message;
            var multisig      = evt.Command.Multisig;
            var amount        = evt.Command.Amount;
            var transactionId = evt.Command.TransactionId.ToString();
            var context       = await _transactionService.GetTransactionContext <IssueContextData>(transactionId);

            var operation = new CashInOutOperation
            {
                Id            = context.CashOperationId,
                ClientId      = message.ClientId,
                Multisig      = multisig,
                AssetId       = message.AssetId,
                Amount        = (double)Math.Abs(amount),
                DateTime      = DateTime.UtcNow,
                AddressTo     = multisig,
                TransactionId = transactionId,
                State         = TransactionStates.SettledOffchain
            };

            operation.AddFeeDataToOperation(message);

            await RegisterOperation(operation);
        }
        public override Task <CashInOutOperationResponse> CashInOut(CashInOutOperation request,
                                                                    ServerCallContext context)
        {
            var isWithdrawal = double.Parse(request.Volume) < 0;

            using var activity = MyTelemetry.StartActivity(isWithdrawal ? "Withdrawal" : "Deposit");

            activity?.AddTag("operationId", request.Id)
            .AddTag("brokerId", request.BrokerId)
            .AddTag("accountId", request.AccountId)
            .AddTag("walletId", request.WalletId)
            .AddTag("assetId", request.AssetId)
            .AddTag("volume", request.Volume);

            if (isWithdrawal && request.Fees.Count == 0)
            {
                var fees = _assetFeesClient.GetAssetFees(request.BrokerId, request.AssetId,
                                                         OperationType.Withdrawal);
                if (fees != null)
                {
                    request.Fees.Add(FeesConverter.ConvertAssetFee(fees));
                }
            }

            return(_cashServiceClient.CashInOutAsync(request, cancellationToken: context.CancellationToken)
                   .ResponseAsync);
        }
示例#6
0
        public async Task <OperationResponse> CashOutAsync(string brokerId, CashInOutModel model)
        {
            var wallet = await _accountsClient.Wallet.GetAsync((long)model.WalletId, brokerId);

            if (wallet == null)
            {
                throw new ArgumentException($"Wallet '{model.WalletId}' does not exist.");
            }

            var volume = model.Volume >= 0 ? -model.Volume : model.Volume;

            var request = new CashInOutOperation
            {
                Id          = Guid.NewGuid().ToString(),
                BrokerId    = brokerId,
                AccountId   = model.AccountId,
                WalletId    = model.WalletId,
                AssetId     = model.Asset,
                Volume      = volume.ToString(CultureInfo.InvariantCulture),
                Description = model.Description
            };

            var fee = await GetFeeAsync(brokerId, model.Asset, RequestType.CashOut);

            request.Fees.Add(fee);

            var result = await _matchingEngineClient.CashOperations.CashInOutAsync(request);

            return(new OperationResponse(result));
        }
 private void AssertCashInOutOperation(CashInOutOperation cashInOutOperation, decimal volume)
 {
     Assert.NotNull(cashInOutOperation);
     Assert.NotEmpty(cashInOutOperation.Id);
     Assert.Equal(cashInOutOperation.BrokerId, BrokerId);
     Assert.Equal(cashInOutOperation.AccountId, AccountId);
     Assert.Equal(cashInOutOperation.WalletId, WalletId);
     Assert.Equal(cashInOutOperation.AssetId, Btc);
     Assert.Equal(cashInOutOperation.Volume, volume.ToString(CultureInfo.InvariantCulture));
     Assert.Equal(cashInOutOperation.Description, Description);
 }
示例#8
0
        private async Task RegisterOperation(CashInOutOperation operation)
        {
            var operationId = await _cashOperationsRepositoryClient.RegisterAsync(operation);

            if (operationId != operation.Id)
            {
                _log.Warning($"Unexpected response from Operations Service: {operationId}",
                             context: operation.ToJson());
            }

            ChaosKitty.Meow();
        }
        private async Task <bool> ProcessManualOperation(IBitcoinTransaction transaction, CashInOutQueueMessage msg)
        {
            var asset = await _assetsService.TryGetAssetAsync(msg.AssetId);

            var walletCredentials = await _walletCredentialsRepository.GetAsync(msg.ClientId);

            var context          = transaction.GetContextData <CashOutContextData>();
            var isOffchainClient = await _clientSettingsRepository.IsOffchainClient(msg.ClientId);

            var isBtcOffchainClient = isOffchainClient && asset.Blockchain == Blockchain.Bitcoin;

            var operation = new CashInOutOperation
            {
                Id             = Guid.NewGuid().ToString(),
                ClientId       = msg.ClientId,
                Multisig       = walletCredentials.MultiSig,
                AssetId        = msg.AssetId,
                Amount         = msg.Amount.ParseAnyDouble(),
                DateTime       = DateTime.UtcNow,
                AddressFrom    = walletCredentials.MultiSig,
                AddressTo      = context.Address,
                TransactionId  = msg.Id,
                Type           = CashOperationType.None,
                BlockChainHash = asset.IssueAllowed && isBtcOffchainClient ? string.Empty : transaction.BlockchainHash,
                State          = GetState(transaction, isBtcOffchainClient)
            };

            var newHistoryEntry = new HistoryEntry
            {
                ClientId   = operation.ClientId,
                Amount     = operation.Amount,
                Currency   = asset.Name,
                DateTime   = msg.Date,
                OpType     = "CashInOut",
                CustomData = JsonConvert.SerializeObject(operation)
            };

            try
            {
                await _cashOperationsRepository.RegisterAsync(operation)
                .ContinueWith(t => _historyWriter.Push(newHistoryEntry));
            }
            catch (Exception e)
            {
                await _log.WriteErrorAsync(nameof(CashInOutQueue), nameof(ProcessManualOperation), null, e);

                return(false);
            }

            return(true);
        }
        public async Task ChangeBalance(ClientWalletEntity wallet,
                                        Asset asset,
                                        decimal amount,
                                        string comment)
        {
            var operationId = Guid.NewGuid().ToString("N");

            var request = new CashInOutOperation
            {
                BrokerId    = wallet.Client.TenantId,
                AccountId   = (ulong)wallet.Client.ClientId,
                WalletId    = (ulong)wallet.WalletId,
                AssetId     = asset.Symbol,
                Description = comment,
                Volume      = amount.ToString(CultureInfo.InvariantCulture),
                Id          = operationId
            };

            _logger.LogInformation($"CashInRequest: {request.ToJson()}");

            var response = await _matchingEngineClient.CashOperations.CashInOutAsync(request);

            _logger.LogInformation(
                "ME operations {MeOperation}, Id: {OperationId}. Status: {MeStatus}, Reason: {MeReason}; BrokerId: {TenantId}; AccountId: {AccountId}; WalletId: {WalletId}; Asset: {AssetSymbol}; Volume: {Volume}",
                "CashInOut",
                operationId,
                response.Status.ToString(),
                response.StatusReason,
                wallet.Client.TenantId,
                (ulong)wallet.Client.ClientId,
                (ulong)wallet.WalletId,
                asset.Symbol,
                amount);

            if (response.Status != Status.Ok)
            {
                throw new MatchingEngineException(response.Status.ToString(),
                                                  response.StatusReason,
                                                  "CashInOutAsync",
                                                  "CashOperations",
                                                  request,
                                                  response);
            }
        }
示例#11
0
        public async Task <OperationResponse> CashInAsync(string brokerId, CashInOutModel model)
        {
            var wallet = await _accountsClient.Wallet.GetAsync((long)model.WalletId, brokerId);

            if (wallet == null)
            {
                throw new ArgumentException($"Wallet '{model.WalletId}' does not exist.");
            }

            if (!wallet.IsEnabled)
            {
                throw new ArgumentException($"Wallet '{model.WalletId}' is disabled.");
            }

            if (wallet.Type != WalletType.Main)
            {
                throw new ArgumentException($"Wallet type must have type '{WalletType.Main}' for deposit / withdrawal operations.");
            }

            var request = new CashInOutOperation
            {
                Id          = Guid.NewGuid().ToString(),
                BrokerId    = brokerId,
                AccountId   = model.AccountId,
                WalletId    = model.WalletId,
                AssetId     = model.Asset,
                Volume      = model.Volume.ToString(CultureInfo.InvariantCulture),
                Description = model.Description
            };

            var fee = await GetFeeAsync(brokerId, model.Asset, RequestType.CashIn);

            request.Fees.Add(fee);

            var result = await _matchingEngineClient.CashOperations.CashInOutAsync(request);

            return(new OperationResponse(result));
        }
示例#12
0
 async Task <CashInOutOperationResponse> ICashServiceClient.CashInOutAsync(CashInOutOperation request, CancellationToken cancellationToken)
 {
     return(await CashInOutAsync(request, cancellationToken : cancellationToken));
 }
示例#13
0
 CashInOutOperationResponse ICashServiceClient.CashInOut(CashInOutOperation request, CancellationToken cancellationToken)
 {
     return(CashInOut(request, cancellationToken: cancellationToken));
 }
示例#14
0
 public async Task <Response> CashInOutAsync(CashInOutOperation request, CancellationToken cancellationToken = default)
 {
     return(await _client.CashInOutAsync(request, cancellationToken : cancellationToken));
 }
示例#15
0
 public static void AddFeeDataToOperation(this CashInOutOperation operation, CashInOutQueueMessage message)
 {
     operation.FeeSize = (double)(message?.Fees?.FirstOrDefault()?.Transfer?.Volume ?? 0);
     operation.FeeType = FeeType.Absolute;
 }
示例#16
0
 public CashInOutOperationResponse CashInOut(CashInOutOperation request,
                                             CancellationToken cancellationToken = new CancellationToken())
 {
     throw new System.NotImplementedException();
 }