コード例 #1
0
        public async Task <List <TxHistory> > GetHistory(TxDirectionType direction, string address, int take, string afterHash)
        {
            var observation = await _observationRepository.GetAsync(address);

            if (observation == null)
            {
                return(new List <TxHistory>());
            }

            List <TxHistory> result;
            string           afterPagingToken = null;

            if (!string.IsNullOrEmpty(afterHash))
            {
                var tx = await _horizonService.GetTransactionDetails(afterHash);

                if (tx == null || !afterHash.Equals(tx.Hash, StringComparison.OrdinalIgnoreCase))
                {
                    throw new BusinessException($"No transaction found. hash={afterHash}");
                }
                afterPagingToken = tx.PagingToken;
            }

            if (_balanceService.IsDepositBaseAddress(address))
            {
                result = await GetDepositBaseHistory(direction, address, take, afterPagingToken);
            }
            else
            {
                result = await GetBaseAddressHistory(direction, address, take, afterPagingToken);
            }

            return(result);
        }
コード例 #2
0
        private async Task ProcessBroadcastInProgress(Guid operationId)
        {
            try
            {
                var broadcast = await _broadcastRepository.GetAsync(operationId);

                if (broadcast == null)
                {
                    throw new BusinessException($"Broadcast for observed operation not found. operationId={operationId})");
                }

                var tx = await _horizonService.GetTransactionDetails(broadcast.Hash);

                if (tx == null)
                {
                    // transaction still in progress
                    return;
                }

                var paymentOp = _horizonService.GetFirstPaymentFromTransaction(tx);
                broadcast.State     = TxBroadcastState.Completed;
                broadcast.Amount    = paymentOp.Amount.InnerValue;
                broadcast.Fee       = tx.FeePaid;
                broadcast.CreatedAt = tx.CreatedAt;
                broadcast.Ledger    = tx.Ledger;
                await _broadcastRepository.MergeAsync(broadcast);

                await _observationRepository.DeleteIfExistAsync(operationId.ToString());
            }
            catch (Exception ex)
            {
                var broadcast = new TxBroadcast
                {
                    State     = TxBroadcastState.Failed,
                    Error     = ex.Message,
                    ErrorCode = TxExecutionError.Unknown
                };
                await _broadcastRepository.MergeAsync(broadcast);

                await _observationRepository.DeleteIfExistAsync(operationId.ToString());

                await _log.WriteErrorAsync(nameof(TransactionService), nameof(ProcessBroadcastInProgress),
                                           $"Failed to process in progress broadcast. operationId={operationId})", ex);
            }
        }
コード例 #3
0
        private async Task <int> QueryAndProcessPayments(string address, PaymentContext context)
        {
            int count    = 0;
            var payments = await _horizonService.GetPayments(address, StellarSdkConstants.OrderAsc, context.Cursor);

            if (payments == null)
            {
                await _log.WriteWarningAsync(nameof(TransactionHistoryService), nameof(QueryAndProcessPayments),
                                             $"Address not found: {address}");

                context.Cursor = null;
                return(count);
            }

            context.Cursor = null;
            foreach (var payment in payments.Embedded.Records)
            {
                try
                {
                    context.Cursor = payment.PagingToken;
                    count++;

                    // create_account, payment or account_merge
                    if (payment.TypeI == (int)OperationType.OperationTypeEnum.CREATE_ACCOUNT ||
                        payment.TypeI == (int)OperationType.OperationTypeEnum.PAYMENT && Core.Domain.Asset.Stellar.TypeName.Equals(payment.AssetType, StringComparison.OrdinalIgnoreCase) ||
                        payment.TypeI == (int)OperationType.OperationTypeEnum.ACCOUNT_MERGE)
                    {
                        if (context.Transaction == null || !context.Transaction.Hash.Equals(payment.TransactionHash, StringComparison.OrdinalIgnoreCase))
                        {
                            var tx = await _horizonService.GetTransactionDetails(payment.TransactionHash);

                            context.Transaction  = tx ?? throw new BusinessException($"Transaction not found. hash={payment.TransactionHash}");
                            context.AccountMerge = 0;
                        }

                        var history = new TxHistory
                        {
                            AssetId   = Core.Domain.Asset.Stellar.Id,
                            Hash      = payment.TransactionHash,
                            PaymentId = payment.Id,
                            CreatedAt = payment.CreatedAt,
                            Memo      = GetMemo(context.Transaction)
                        };

                        // create_account
                        if (payment.TypeI == (int)OperationType.OperationTypeEnum.CREATE_ACCOUNT)
                        {
                            history.FromAddress = payment.Funder;
                            history.ToAddress   = payment.Account;
                            history.PaymentType = PaymentType.CreateAccount;

                            decimal amount = Decimal.Parse(payment.StartingBalance);
                            history.Amount = Convert.ToInt64(amount * One.Value);
                        }
                        // payment
                        else if (payment.TypeI == (int)OperationType.OperationTypeEnum.PAYMENT)
                        {
                            history.FromAddress = payment.From;
                            history.ToAddress   = payment.To;
                            history.PaymentType = PaymentType.Payment;

                            decimal amount = Decimal.Parse(payment.Amount);
                            history.Amount = Convert.ToInt64(amount * One.Value);
                        }
                        // account_merge
                        else if (payment.TypeI == (int)OperationType.OperationTypeEnum.ACCOUNT_MERGE)
                        {
                            history.FromAddress = payment.Account;
                            history.ToAddress   = payment.Into;
                            history.PaymentType = PaymentType.AccountMerge;

                            var resultXdrBase64 = context.Transaction.ResultXdr;
                            history.Amount = _horizonService.GetAccountMergeAmount(resultXdrBase64, context.AccountMerge);
                            context.AccountMerge++;
                        }
                        else
                        {
                            throw new BusinessException($"Invalid payment type. type=${payment.TypeI}");
                        }

                        history.OperationId = await _txBroadcastRepository.GetOperationId(payment.TransactionHash);

                        if (address.Equals(history.ToAddress, StringComparison.OrdinalIgnoreCase))
                        {
                            await _txHistoryRepository.InsertOrReplaceAsync(context.TableId, TxDirectionType.Incoming, history);

                            context.Sequence++;
                        }
                        if (address.Equals(history.FromAddress, StringComparison.OrdinalIgnoreCase))
                        {
                            await _txHistoryRepository.InsertOrReplaceAsync(context.TableId, TxDirectionType.Outgoing, history);

                            context.Sequence++;
                        }
                    }
                }
                catch (Exception ex)
                {
                    throw new BusinessException($"Failed to process payment of transaction. payment={payment?.Id}, hash={context?.Transaction?.Hash}", ex);
                }
            }
            return(count);
        }
コード例 #4
0
        private async Task ProcessBroadcastInProgress(Guid operationId)
        {
            TxBroadcast broadcast = null;

            try
            {
                broadcast = await _broadcastRepository.GetAsync(operationId);

                if (broadcast == null)
                {
                    await _observationRepository.DeleteIfExistAsync(operationId.ToString());

                    throw new BusinessException($"Broadcast for observed operation not found. operationId={operationId}");
                }

                var tx = await _horizonService.GetTransactionDetails(broadcast.Hash);

                if (tx == null)
                {
                    // transaction still in progress
                    return;
                }
                if (!broadcast.Hash.Equals(tx.Hash, StringComparison.OrdinalIgnoreCase))
                {
                    throw new BusinessException($"Transaction hash mismatch. actual={tx.Hash}, expected={broadcast.Hash}");
                }

                var operation     = _horizonService.GetFirstOperationFromTxEnvelopeXdr(tx.EnvelopeXdr);
                var operationType = operation.Discriminant.InnerValue;

                // ReSharper disable once SwitchStatementMissingSomeCases
                switch (operationType)
                {
                case OperationType.OperationTypeEnum.CREATE_ACCOUNT:
                {
                    broadcast.Amount = operation.CreateAccountOp.StartingBalance.InnerValue;
                    break;
                }

                case OperationType.OperationTypeEnum.PAYMENT:
                {
                    broadcast.Amount = operation.PaymentOp.Amount.InnerValue;
                    break;
                }

                case OperationType.OperationTypeEnum.ACCOUNT_MERGE:
                {
                    broadcast.Amount = _horizonService.GetAccountMergeAmount(tx.ResultXdr, 0);
                    break;
                }

                default:
                    throw new BusinessException($"Unsupported operation type. type={operationType}");
                }

                DateTime.TryParse(tx.CreatedAt, out var createdAt);
                broadcast.State     = TxBroadcastState.Completed;
                broadcast.Fee       = tx.FeeCharged;
                broadcast.CreatedAt = createdAt;
                broadcast.Ledger    = tx.Ledger * 10;

                await _broadcastRepository.MergeAsync(broadcast);

                await _observationRepository.DeleteIfExistAsync(operationId.ToString());
            }
            catch (Exception ex)
            {
                if (broadcast != null)
                {
                    broadcast.State     = TxBroadcastState.Failed;
                    broadcast.Error     = ex.Message;
                    broadcast.ErrorCode = TxExecutionError.Unknown;

                    await _broadcastRepository.MergeAsync(broadcast);

                    await _observationRepository.DeleteIfExistAsync(operationId.ToString());
                }

                throw new BusinessException($"Failed to process in progress broadcast. operationId={operationId}", ex);
            }
        }