Exemple #1
0
        public static TransactionEntity ToTransactionEntity(this ITransactionModel transactionModel)
        {
            return(new TransactionEntity
            {
                // Common
                Id = transactionModel.Id.ToGuid(),
                Version = transactionModel.Version,

                // Foreign
                AccountId = transactionModel.AccountId.ToGuid(),
                ProfileId = transactionModel.ProfileId,

                // Properties
                Amount = transactionModel.Amount,
                Info = transactionModel.Info,

                // Approvable
                Approved = transactionModel.Approved,
                Pending = transactionModel.Pending,
                Blocked = transactionModel.Blocked,

                // Concurrent
                SequentialNumber = transactionModel.SequentialNumber
            });
        }
        public async Task <AccountDto?> ProcessTransactionUpdatedEventAsync(ITransactionModel transactionModel)
        {
            if (!transactionModel.IsApproved())
            {
                return(null);
            }
            var transactionEntity = transactionModel.ToTransactionEntity();
            var mappedAccount     = await _accountsService.GetAccountByIdAsync(transactionEntity.AccountId);

            if (mappedAccount != null)
            {
                // Optimistic Concurrency Control: check version
                if (!mappedAccount.CheckConcurrentController(transactionEntity))
                {
                    return(null);
                }

                mappedAccount.SetBalance(transactionEntity);
                mappedAccount.IncrementConcurrentController();

                // Optimistic Concurrency Control: update incrementing the version
                var updatedAccount = await _accountsService.UpdateAccountAsync(mappedAccount);

                await _publishEndpoint.Publish(updatedAccount?.ToAccountEvent <AccountUpdatedEvent>());

                await _publishEndpoint.Publish(updatedAccount?.ToAccountEvent <AccountCheckCommand>());

                return(updatedAccount?.ToAccountModel <AccountDto>());
            }

            return(null);
        }
Exemple #3
0
    private void HandleReversions()
    {
        foreach (KeyValuePair <string, List <ITransactionModel> > currencyTransactionPair in _transactions)
        {
            List <ITransactionModel> transactionsToRemove  = new List <ITransactionModel>();
            List <ITransactionModel> reversionTransactions = currencyTransactionPair.Value.Where(t => t.TransactionType == TransactionType.Reversion).ToList();

            foreach (ITransactionModel reversionTransaction in reversionTransactions)
            {
                ITransactionModel revertedTransaction = currencyTransactionPair.Value.Where(t => t.CryptoCurrencyAmount == reversionTransaction.CryptoCurrencyAmount * -1 &&
                                                                                            t.TimeStamp < reversionTransaction.TimeStamp).OrderBy(t => Math.Abs((t.TimeStamp - reversionTransaction.TimeStamp).Ticks)).FirstOrDefault();

                if (revertedTransaction != null)
                {
                    reversionTransaction.CryptoCurrencyAmount = 0;
                    reversionTransaction.NativeAmount         = 0;
                    revertedTransaction.CryptoCurrencyAmount  = 0;
                    revertedTransaction.NativeAmount          = 0;

                    transactionsToRemove.Add(reversionTransaction);
                    transactionsToRemove.Add(revertedTransaction);
                }
            }

            foreach (ITransactionModel transactionToRemove in transactionsToRemove)
            {
                currencyTransactionPair.Value.Remove(transactionToRemove);
            }
        }
    }
Exemple #4
0
        public async Task <TransactionDto?> CreateNewTransactionAsync(ITransactionModel transactionModel)
        {
            if (
                string.IsNullOrEmpty(transactionModel.ProfileId) ||
                transactionModel.AccountId == Guid.Empty.ToString() ||
                !await _licenseManager.EvaluateNewEntityAsync(transactionModel)
                )
            {
                return(null);
            }

            // Optimistic Concurrency Control: set the sequential number
            var sequencedTransaction = await _concurrencyManager.SetNextSequentialNumber(transactionModel);

            var newTransaction = await _transactionsService.CreateTransactionAsync(
                sequencedTransaction.ToTransactionEntity()
                );

            if (newTransaction != null)
            {
                await _publishEndpoint.Publish(newTransaction.ToTransactionModel <TransactionCreatedEvent>());

                await _publishEndpoint.Publish(newTransaction.ToTransactionModel <TransactionCheckCommand>());

                return(newTransaction.ToTransactionModel <TransactionDto>());
            }

            return(null);
        }
Exemple #5
0
 public static TransactionEntity ToTransactionEntity(this ITransactionModel transactionModel)
 {
     return(new TransactionEntity
     {
         Id = transactionModel.Id.ToGuid(),
         Amount = transactionModel.Amount,
         AccountId = transactionModel.AccountId.ToGuid(),
         Approved = transactionModel.Approved,
         Pending = transactionModel.Pending,
         Version = transactionModel.Version,
         SequentialNumber = transactionModel.SequentialNumber
     });
 }
Exemple #6
0
        public async Task <ITransactionModel> SetNextSequentialNumber(ITransactionModel transactionModel)
        {
            var allTransactions = await _transactionsService.GetManyByParameterAsync(
                entity => entity !.ProfileId == transactionModel.ProfileId &&
                entity !.AccountId == transactionModel.AccountId.ToGuid()
                );

            var lastTransactionNumber = allTransactions.Max(t => t?.SequentialNumber);

            transactionModel.SequentialNumber = lastTransactionNumber.GetValueOrDefault(0) + 1;

            return(transactionModel);
        }
    public int CompareTo(ITransactionModel other)
    {
        int date = DateTime.Compare(TimeStamp, other.TimeStamp);

        if (date == 0)
        {
            if (TransactionType == TransactionType.Purchase)
            {
                return(-1);
            }

            return(1);
        }

        return(date);
    }
        public static TransactionResult MakeDeposit(ITransactionModel transaction)
        {
            try
            {
                if (transaction.RecieverAcct == null)
                {
                    return(TransactionResult.NoReciever);
                }

                transaction.RecieverAcct.Balance += ExchangeService.ConvertCurrency(transaction.TransactionAmt, transaction.Currency, transaction.RecieverAcct.Currency);
            }
            catch (Exception e)
            {
                throw (e);
            }

            return(TransactionResult.Success);
        }
Exemple #9
0
        public static BillingEntity ToBillingEntity(this ITransactionModel transactionModel)
        {
            return(new BillingEntity
            {
                Id = Guid.NewGuid(),

                ProfileId = transactionModel.ProfileId,
                AccountId = transactionModel.AccountId.ToGuid(),
                TransactionId = transactionModel.Id.ToGuid(),

                Amount = transactionModel.Amount,
                Approved = transactionModel.Approved,
                Pending = transactionModel.Pending,

                Created = DateTime.Now,
                Updated = DateTime.Now,
                Version = 0
            });
        }
        public ProfileDto?UpdateTransactionOnProfile(ITransactionModel transactionModel)
        {
            if (
                string.IsNullOrEmpty(transactionModel.ProfileId) ||
                string.IsNullOrEmpty(transactionModel.AccountId)
                )
            {
                return(null);
            }

            var updated = _profilesService.UpdateInArray(
                transactionModel.AccountId,
                transactionModel.ToTransactionSubEntity()
                );

            if (updated != null || !string.IsNullOrEmpty(updated?.Id))
            {
                return(updated.ToProfileDto());
            }
            return(null);
        }
Exemple #11
0
        public async Task <TransactionDto?> ProcessTransactionCheckedEventAsync(ITransactionModel transactionModel)
        {
            var transactionEntity = await _transactionsService.GetTransactionByIdAsync(transactionModel.Id.ToGuid());

            if (transactionEntity != null)
            {
                if (transactionModel.IsBlocked())
                {
                    transactionEntity.SetBlocked();
                }
                else
                {
                    if (transactionModel.IsApproved())
                    {
                        transactionEntity.SetApproval();
                    }
                    else
                    {
                        transactionEntity.SetDenial();
                    }
                }

                // Optimistic Concurrency Control: increment the version on update
                var updatedTransaction = await _transactionsService.UpdateTransactionAsync(transactionEntity);

                if (updatedTransaction != null)
                {
                    await _publishEndpoint.Publish(
                        updatedTransaction.ToTransactionModel <TransactionUpdatedEvent>()
                        );

                    await _publishEndpoint.Publish(updatedTransaction.ToNotificationEvent());

                    return(updatedTransaction.ToTransactionModel <TransactionDto>());
                }
            }

            return(null);
        }
        public static TransactionResult MakeWithdrawal(ITransactionModel transaction)
        {
            try
            {
                if (transaction.SenderAcct == null)
                {
                    return(TransactionResult.NoSender);
                }

                if (transaction.SenderAcct.Balance < ExchangeService.ConvertCurrency(transaction.TransactionAmt, transaction.Currency, transaction.SenderAcct.Currency))
                {
                    return(TransactionResult.InsufficientFunds);
                }

                transaction.SenderAcct.Balance -= ExchangeService.ConvertCurrency(transaction.TransactionAmt, transaction.Currency, transaction.SenderAcct.Currency);
            }
            catch (Exception e)
            {
                throw (e);
            }

            return(TransactionResult.Success);
        }
Exemple #13
0
        public async Task <ITransactionModel?> EvaluateTransactionAsync(ITransactionModel transactionCreatedEvent)
        {
            if (
                string.IsNullOrEmpty(transactionCreatedEvent.ProfileId) ||
                string.IsNullOrEmpty(transactionCreatedEvent.AccountId)
                )
            {
                return(null);
            }

            var isTransactionAllowed = await _licenseManager.EvaluateNewEntityAsync(transactionCreatedEvent);

            if (isTransactionAllowed)
            {
                transactionCreatedEvent.SetApproval();
            }
            else
            {
                transactionCreatedEvent.SetDenial();
            }

            var processedEntity = await _billingsService.CreateBillingAsync(
                transactionCreatedEvent.ToBillingEntity()
                );

            if (processedEntity != null)
            {
                var transactionProcessedEvent = processedEntity.ToTransactionModel <TransactionIsCheckedEvent>(
                    transactionCreatedEvent
                    );
                await _publishEndpoint.Publish(transactionProcessedEvent);

                return(transactionProcessedEvent);
            }

            return(null);
        }
        public static TModel ToTransactionModel <TModel>(
            this BillingEntity billingEntity,
            ITransactionModel transactionModel
            )
            where TModel : class, ITransactionModel, new()
        {
            return(new TModel
            {
                Id = transactionModel.Id,
                Version = transactionModel.Version,
                Timestamp = transactionModel.Timestamp,

                AccountId = transactionModel.AccountId,
                ProfileId = transactionModel.ProfileId,

                Amount = transactionModel.Amount,
                Info = transactionModel.Info,

                Approved = billingEntity.Approved,
                Pending = billingEntity.Pending,

                SequentialNumber = transactionModel.SequentialNumber
            });
        }
        public static TransactionResult MakeTransfer(ITransactionModel transaction)
        {
            try
            {
                TransactionResult result = MakeWithdrawal(transaction);
                if (result != TransactionResult.Success)
                {
                    return(result);
                }

                result = MakeDeposit(transaction);
                //desposit amount to reciever account, convert currency to currency of reciever account
                if (result != TransactionResult.Success)
                {
                    return(result);
                }
            }
            catch (Exception e)
            {
                throw (e);
            }

            return(TransactionResult.Success);
        }
Exemple #16
0
    //private static async Task<List<ITransactionModel>> InitFromBinanceApi(string address)
    //{
    //    using(CallRateLimiter explorerBinanceLimiter = new CallRateLimiter("BinanceExplorerApi", 10, TimeSpan.FromSeconds(1)))
    //    {
    //        HttpResponseMessage transactionsAmount = await explorerBinanceLimiter.GetDataAsync($"https://explorer.binance.org/api/v1/txs?page=1&rows=1&address={address}");


    //    }

    //    List<ITransactionModel> transactionModels = new List<ITransactionModel> { this };

    //    using (CallRateLimiter apiCallRateLimiter = new CallRateLimiter("BinanceApiCall", 10, TimeSpan.FromSeconds(1)))
    //    {
    //        HttpResponseMessage httpResponse = await apiCallRateLimiter.GetDataAsync($"https://dex.binance.org/api/v1/tx/{transactionId}?format=json");

    //        if (httpResponse.IsSuccessStatusCode)
    //        {
    //            BinanceChain.TransactionFromHash transactionFromHash = JsonConvert.DeserializeObject<BinanceChain.TransactionFromHash>(await httpResponse.Content.ReadAsStringAsync());

    //            if (transactionFromHash.Ok)
    //            {
    //                if (FULL_TAX.Contains(transactionFromHash.Tx.Value.Memo))
    //                {
    //                    IsFullyTaxed = true;
    //                }

    //                foreach (BinanceChain.TransactionInformationMessage transactionInformationMessage in transactionFromHash.Tx.Value.Msg)
    //                {
    //                    List<BinanceChain.TransactionAddressAndCoins> transactionInformationMessageValues = transactionInformationMessage.Value.Outputs.Where(b => b.Address == _address).ToList();

    //                    if (transactionInformationMessageValues.Count > 0)
    //                    {
    //                        for (int i = 1; i < transactionInformationMessageValues.Count; i++)
    //                        {
    //                            ITransactionModel blockChainTransactionModel = Clone();

    //                            foreach (BinanceChain.TransactionCoin coin in transactionInformationMessageValues[i].Coins)
    //                            {
    //                                blockChainTransactionModel.NativeAmount += ValueForOneCryptoTokenInNative * coin.Amount;
    //                                blockChainTransactionModel.CryptoCurrency += coin.Denom + "|";
    //                            }

    //                            blockChainTransactionModel.CryptoCurrency.Remove(blockChainTransactionModel.CryptoCurrency.Length - 1);
    //                            transactionModels.Add(blockChainTransactionModel);
    //                        }

    //                        BinanceChain.TransactionAddressAndCoins first = transactionInformationMessageValues[0];

    //                        NativeAmount = 0;

    //                        foreach (BinanceChain.TransactionCoin coin in first.Coins)
    //                        {
    //                            CryptoCurrency = coin.Denom;
    //                            CryptoCurrencyAmount += coin.Amount;
    //                            NativeAmount += ValueForOneCryptoTokenInNative * coin.Amount;
    //                        }
    //                    }
    //                }
    //            }
    //        }
    //        else
    //        {
    //            Debug.Log("Binance api call failed with code: " + httpResponse.StatusCode + " and message " + await httpResponse.Content.ReadAsStringAsync());
    //        }
    //    }

    //    return transactionModels;
    //}

    private async Task <List <ITransactionModel> > InitFromEthereumApi()
    {
        List <ITransactionModel> transactionModels = new List <ITransactionModel> {
            this
        };

        APIKeys keys;

        using (StreamReader streamReader = new StreamReader(API_KEYS_PATH))
        {
            string apiKeys = await streamReader.ReadToEndAsync();

            keys = JsonConvert.DeserializeObject <APIKeys>(apiKeys);
        }

        using (CallRateLimiter apiCallRateLimiter = new CallRateLimiter("EtherScan", 5, TimeSpan.FromSeconds(1)))
        {
            HttpResponseMessage etherTransactionsResponse = await apiCallRateLimiter.GetDataAsync($"https://api.etherscan.io/api?module=account&action=txlist&address={_address}&sort=asc&apikey={keys.EtherScanKey}");

            HttpResponseMessage erc20TransactionsResponse = await apiCallRateLimiter.GetDataAsync($"https://api.etherscan.io/api?module=account&action=tokentx&address={_address}&sort=asc&apikey={keys.EtherScanKey}");

            if (etherTransactionsResponse.IsSuccessStatusCode && erc20TransactionsResponse.IsSuccessStatusCode)
            {
                EthereumChain.EtherAddressTransactions etherAddressTransactions = JsonConvert.DeserializeObject <EthereumChain.EtherAddressTransactions>(await etherTransactionsResponse.Content.ReadAsStringAsync());
                EthereumChain.Erc20AddressTransactions erc20AddressTransactions = JsonConvert.DeserializeObject <EthereumChain.Erc20AddressTransactions>(await erc20TransactionsResponse.Content.ReadAsStringAsync());

                List <EthereumChain.IEtherScanTransaction> transactions = new List <EthereumChain.IEtherScanTransaction>();

                transactions.AddRange(erc20AddressTransactions.Result);

                foreach (var ethTransaction in etherAddressTransactions.Result)
                {
                    if (!transactions.Any(t => t.Hash == ethTransaction.Hash))
                    {
                        transactions.Add(ethTransaction);
                    }
                }

                if (transactions.Count > 0)
                {
                    for (int i = 1; i < transactions.Count; i++)
                    {
                        ITransactionModel blockChainTransactionModel = Clone();

                        NativeAmount         = transactions[i].Value * ValueForOneCryptoTokenInNative;
                        CryptoCurrency       = transactions[i].TokenSymbol;
                        CryptoCurrencyAmount = transactions[i].Value;
                    }

                    EthereumChain.IEtherScanTransaction first = transactions[0];
                    NativeAmount         = first.Value * ValueForOneCryptoTokenInNative;
                    CryptoCurrency       = first.TokenSymbol;
                    CryptoCurrencyAmount = first.Value;
                }
            }
            else
            {
                Debug.Log("Etherscan api call finished with code: " + etherTransactionsResponse.StatusCode + " and message " + await etherTransactionsResponse.Content.ReadAsStringAsync());
                Debug.Log("Etherscan api call finished with code: " + erc20TransactionsResponse.StatusCode + " and message " + await erc20TransactionsResponse.Content.ReadAsStringAsync());
            }
        }

        return(transactionModels);
    }
Exemple #17
0
 /// <summary>
 /// Specify the transactional model to be used.
 /// </summary>
 /// <param name="model"></param>
 /// <remarks>
 /// Typically you wouldn't need to do this at all.</remarks>
 public static void TransactionModel(ITransactionModel model)
 {
     Birch.Transactions.TransactionModel.Current = model ?? new Threaded();
 }
Exemple #18
0
 public bool Transferencia(ITransactionModel transaction, IAccount account)
 {
     throw new NotImplementedException();
 }
Exemple #19
0
 public bool Saque(ITransactionModel transaction)
 {
     throw new NotImplementedException();
 }
Exemple #20
0
    public void RunCalculations()
    {
        _gains.Clear();
        _losses.Clear();

        HandleReversions();

        WriteOverview();

        List <ITransactionModel> purchaseTransactions = new List <ITransactionModel>();

        foreach (KeyValuePair <string, List <ITransactionModel> > currencyTransaction in _transactions)
        {
            foreach (ITransactionModel transaction in currencyTransaction.Value)
            {
                ITransactionModel transactionClone = transaction.Clone();

                if (transactionClone.TransactionType == TransactionType.Purchase || transactionClone.TransactionType == TransactionType.Interest || transactionClone.TransactionType == TransactionType.Rebate)
                {
                    purchaseTransactions.Add(transactionClone);
                }
                else if (transactionClone.TransactionType == TransactionType.Sale)
                {
                    decimal cryptoCurrencyAmountFromTransactions = 0;

                    for (int i = 0; i < purchaseTransactions.Count; i++)
                    {
                        cryptoCurrencyAmountFromTransactions += purchaseTransactions[i].CryptoCurrencyAmount;

                        if (cryptoCurrencyAmountFromTransactions >= transactionClone.CryptoCurrencyAmount)
                        {
                            List <ITransactionModel> purchaseTransactionsNeededToCoverSale = purchaseTransactions.Take(i + 1).ToList();

                            CalculateSaleFromPurchases(purchaseTransactionsNeededToCoverSale, transactionClone);

                            if (purchaseTransactions[i].CryptoCurrencyAmount > 0)
                            {
                                purchaseTransactions.RemoveRange(0, i);
                            }
                            else
                            {
                                purchaseTransactions.RemoveRange(0, i + 1);
                            }

                            break;
                        }
                    }
                }
            }

            purchaseTransactions.Clear();
        }

        _gains.Sort((x, y) => x.CompareTo(y));
        _losses.Sort((x, y) => x.CompareTo(y));

        if (_gains.Count > 0)
        {
            _gains[0].TotalAmount = _gains[0].Amount;

            for (int i = 1; i < _gains.Count; i++)
            {
                _gains[i].TotalAmount = _gains[i].Amount + _gains[i - 1].TotalAmount;
            }
        }

        if (_losses.Count > 0)
        {
            _losses[0].TotalAmount = _losses[0].Amount;

            for (int i = 1; i < _losses.Count; i++)
            {
                _losses[i].TotalAmount = _losses[i].Amount + _losses[i - 1].TotalAmount;
            }
        }

        WriteTansactionGains();
        WriteTranactionLosses();
    }
Exemple #21
0
 public bool Deposito(ITransactionModel transaction)
 {
     throw new NotImplementedException();
 }
Exemple #22
0
    private void CalculateSaleFromPurchases(List <ITransactionModel> purchaseTransactionsNeededToCoverSale, ITransactionModel saleTransaction)
    {
        decimal originalSaleValueForeachToken = saleTransaction.ValueForOneCryptoTokenInNative;

        foreach (ITransactionModel purchaseTransaction in purchaseTransactionsNeededToCoverSale)
        {
            decimal cryptoCurrencySoldAmount = decimal.Zero;

            if (saleTransaction.CryptoCurrencyAmount > purchaseTransaction.CryptoCurrencyAmount)
            {
                saleTransaction.CryptoCurrencyAmount    -= purchaseTransaction.CryptoCurrencyAmount;
                cryptoCurrencySoldAmount                 = purchaseTransaction.CryptoCurrencyAmount;
                purchaseTransaction.CryptoCurrencyAmount = 0;
            }
            else
            {
                purchaseTransaction.CryptoCurrencyAmount -= saleTransaction.CryptoCurrencyAmount;
                cryptoCurrencySoldAmount             = saleTransaction.CryptoCurrencyAmount;
                saleTransaction.CryptoCurrencyAmount = 0;
            }

            decimal transactionProfit = decimal.Zero;

            if (purchaseTransaction.IsFullyTaxed)
            {
                transactionProfit = originalSaleValueForeachToken * cryptoCurrencySoldAmount;
            }
            else
            {
                transactionProfit = (saleTransaction.ValueForOneCryptoTokenInNative - purchaseTransaction.ValueForOneCryptoTokenInNative) * cryptoCurrencySoldAmount;
            }

            if (transactionProfit < 0)
            {
                _losses.Add(new TaxableEvent(purchaseTransaction.TransactionId, saleTransaction.TransactionId, saleTransaction.CryptoCurrency, purchaseTransaction.TimeStamp, saleTransaction.TimeStamp,
                                             transactionProfit * -1, MainComponent.Instance.TargetCurrency, saleTransaction.WalletName, cryptoCurrencySoldAmount));
            }
            else if (transactionProfit > 0)
            {
                _gains.Add(new TaxableEvent(purchaseTransaction.TransactionId, saleTransaction.TransactionId, saleTransaction.CryptoCurrency, purchaseTransaction.TimeStamp, saleTransaction.TimeStamp,
                                            transactionProfit, MainComponent.Instance.TargetCurrency, saleTransaction.WalletName, cryptoCurrencySoldAmount));
            }
        }
    }
Exemple #23
0
 public double Saldo(ITransactionModel transaction)
 {
     throw new NotImplementedException();
 }