@Test public void assertExchange() { String debitCurrency = "USD"; BigDecimal debitAmount = BigDecimal.valueOf(800d); String creditCurrency = "BTC"; BigDecimal askPrice = BigDecimal.valueOf(8222.21d); BigDecimal bidPrice = BigDecimal.valueOf(8219.04d); BigDecimal initialCreditCurrencyBalance = BigDecimal.valueOf(0.2d); BigDecimal expectedCreditAmount = debitAmount.divide(askPrice, 5, RoundingMode.HALF_UP); Mockito.when(balanceStore.get(ACCOUNT + "-" + creditCurrency)).thenReturn( new AccountCurrencyBalance(new AccountCurrency(ACCOUNT, creditCurrency), initialCreditCurrencyBalance)); Mockito.when(rateStore.get(debitCurrency + "-" + creditCurrency)).thenReturn(new ExchangeRate(debitCurrency, creditCurrency, askPrice, bidPrice, LocalDateTime.now().toEpochSecond(ZoneOffset.UTC))); Transaction transaction = new Transaction(UUID.randomUUID().toString(), ACCOUNT, Type.EXCHANGE, debitAmount, debitCurrency, null, creditCurrency); OperationResult operationResult = operationCreditTransformer.transform(transaction); Assertions.assertEquals(0, expectedCreditAmount.compareTo(operationResult.getTransaction().getCreditAmount())); Assertions.assertEquals(0, initialCreditCurrencyBalance.add(expectedCreditAmount) .compareTo(operationResult.getAccountCurrencyBalance().getBalance())); }
@Override public OperationResult transform(Transaction transaction) { String error = validateOperation(transaction); if (error != null) { return new OperationResult(false, transaction, null, error); } BigDecimal creditAmount = transaction.getCreditAmount(); if (Transaction.Type.EXCHANGE.equals(transaction.getType())) { Optional<ExchangeRate> exchangeRate = Optional .ofNullable(rateStore.get(transaction.getCreditCurrency() + "-" + transaction.getDebitCurrency())); Optional<ExchangeRate> invertedExchangeRate = Optional .ofNullable(rateStore.get(transaction.getDebitCurrency() + "-" + transaction.getCreditCurrency())); ExchangeRate rate = exchangeRate.orElse(invertedExchangeRate.orElse(null)); if (rate == null) { return new OperationResult(false, transaction, null, "Exchange rate could not be found for " + transaction.getCreditCurrency() + " and " + transaction.getDebitCurrency()); } if (rate.getBaseCurrency().equals(transaction.getCreditCurrency())) { creditAmount = transaction.getDebitAmount().multiply(rate.getBid()); } else { creditAmount = transaction.getDebitAmount().divide(rate.getAsk(), 5, RoundingMode.HALF_UP); } } String storeKey = transaction.getAccount() + "-" + transaction.getCreditCurrency(); AccountCurrencyBalance existingBalance = Optional.ofNullable(balanceStore.get(storeKey)) .orElseGet(() -> new AccountCurrencyBalance( new AccountCurrency(transaction.getAccount(), transaction.getCreditCurrency()), BigDecimal.ZERO)); AccountCurrencyBalance newBalance = new AccountCurrencyBalance(existingBalance.getAccountCurrency(), existingBalance.getBalance().add(creditAmount)); balanceStore.put(storeKey, newBalance); return new OperationResult(true, new Transaction(transaction.getGuid(), transaction.getAccount(), transaction.getType(), transaction.getDebitAmount(), transaction.getDebitCurrency(), creditAmount, transaction.getCreditCurrency()), newBalance, null); }
OperationCreditTransformer extends OperationTransformer { @Override public OperationResult transform(Transaction transaction) { String error = validateOperation(transaction); if (error != null) { return new OperationResult(false, transaction, null, error); } BigDecimal creditAmount = transaction.getCreditAmount(); if (Transaction.Type.EXCHANGE.equals(transaction.getType())) { Optional<ExchangeRate> exchangeRate = Optional .ofNullable(rateStore.get(transaction.getCreditCurrency() + "-" + transaction.getDebitCurrency())); Optional<ExchangeRate> invertedExchangeRate = Optional .ofNullable(rateStore.get(transaction.getDebitCurrency() + "-" + transaction.getCreditCurrency())); ExchangeRate rate = exchangeRate.orElse(invertedExchangeRate.orElse(null)); if (rate == null) { return new OperationResult(false, transaction, null, "Exchange rate could not be found for " + transaction.getCreditCurrency() + " and " + transaction.getDebitCurrency()); } if (rate.getBaseCurrency().equals(transaction.getCreditCurrency())) { creditAmount = transaction.getDebitAmount().multiply(rate.getBid()); } else { creditAmount = transaction.getDebitAmount().divide(rate.getAsk(), 5, RoundingMode.HALF_UP); } } String storeKey = transaction.getAccount() + "-" + transaction.getCreditCurrency(); AccountCurrencyBalance existingBalance = Optional.ofNullable(balanceStore.get(storeKey)) .orElseGet(() -> new AccountCurrencyBalance( new AccountCurrency(transaction.getAccount(), transaction.getCreditCurrency()), BigDecimal.ZERO)); AccountCurrencyBalance newBalance = new AccountCurrencyBalance(existingBalance.getAccountCurrency(), existingBalance.getBalance().add(creditAmount)); balanceStore.put(storeKey, newBalance); return new OperationResult(true, new Transaction(transaction.getGuid(), transaction.getAccount(), transaction.getType(), transaction.getDebitAmount(), transaction.getDebitCurrency(), creditAmount, transaction.getCreditCurrency()), newBalance, null); } }
OperationCreditTransformer extends OperationTransformer { @Override public OperationResult transform(Transaction transaction) { String error = validateOperation(transaction); if (error != null) { return new OperationResult(false, transaction, null, error); } BigDecimal creditAmount = transaction.getCreditAmount(); if (Transaction.Type.EXCHANGE.equals(transaction.getType())) { Optional<ExchangeRate> exchangeRate = Optional .ofNullable(rateStore.get(transaction.getCreditCurrency() + "-" + transaction.getDebitCurrency())); Optional<ExchangeRate> invertedExchangeRate = Optional .ofNullable(rateStore.get(transaction.getDebitCurrency() + "-" + transaction.getCreditCurrency())); ExchangeRate rate = exchangeRate.orElse(invertedExchangeRate.orElse(null)); if (rate == null) { return new OperationResult(false, transaction, null, "Exchange rate could not be found for " + transaction.getCreditCurrency() + " and " + transaction.getDebitCurrency()); } if (rate.getBaseCurrency().equals(transaction.getCreditCurrency())) { creditAmount = transaction.getDebitAmount().multiply(rate.getBid()); } else { creditAmount = transaction.getDebitAmount().divide(rate.getAsk(), 5, RoundingMode.HALF_UP); } } String storeKey = transaction.getAccount() + "-" + transaction.getCreditCurrency(); AccountCurrencyBalance existingBalance = Optional.ofNullable(balanceStore.get(storeKey)) .orElseGet(() -> new AccountCurrencyBalance( new AccountCurrency(transaction.getAccount(), transaction.getCreditCurrency()), BigDecimal.ZERO)); AccountCurrencyBalance newBalance = new AccountCurrencyBalance(existingBalance.getAccountCurrency(), existingBalance.getBalance().add(creditAmount)); balanceStore.put(storeKey, newBalance); return new OperationResult(true, new Transaction(transaction.getGuid(), transaction.getAccount(), transaction.getType(), transaction.getDebitAmount(), transaction.getDebitCurrency(), creditAmount, transaction.getCreditCurrency()), newBalance, null); } OperationCreditTransformer(String balanceStateStoreName, String rateStoreName); }
OperationCreditTransformer extends OperationTransformer { @Override public OperationResult transform(Transaction transaction) { String error = validateOperation(transaction); if (error != null) { return new OperationResult(false, transaction, null, error); } BigDecimal creditAmount = transaction.getCreditAmount(); if (Transaction.Type.EXCHANGE.equals(transaction.getType())) { Optional<ExchangeRate> exchangeRate = Optional .ofNullable(rateStore.get(transaction.getCreditCurrency() + "-" + transaction.getDebitCurrency())); Optional<ExchangeRate> invertedExchangeRate = Optional .ofNullable(rateStore.get(transaction.getDebitCurrency() + "-" + transaction.getCreditCurrency())); ExchangeRate rate = exchangeRate.orElse(invertedExchangeRate.orElse(null)); if (rate == null) { return new OperationResult(false, transaction, null, "Exchange rate could not be found for " + transaction.getCreditCurrency() + " and " + transaction.getDebitCurrency()); } if (rate.getBaseCurrency().equals(transaction.getCreditCurrency())) { creditAmount = transaction.getDebitAmount().multiply(rate.getBid()); } else { creditAmount = transaction.getDebitAmount().divide(rate.getAsk(), 5, RoundingMode.HALF_UP); } } String storeKey = transaction.getAccount() + "-" + transaction.getCreditCurrency(); AccountCurrencyBalance existingBalance = Optional.ofNullable(balanceStore.get(storeKey)) .orElseGet(() -> new AccountCurrencyBalance( new AccountCurrency(transaction.getAccount(), transaction.getCreditCurrency()), BigDecimal.ZERO)); AccountCurrencyBalance newBalance = new AccountCurrencyBalance(existingBalance.getAccountCurrency(), existingBalance.getBalance().add(creditAmount)); balanceStore.put(storeKey, newBalance); return new OperationResult(true, new Transaction(transaction.getGuid(), transaction.getAccount(), transaction.getType(), transaction.getDebitAmount(), transaction.getDebitCurrency(), creditAmount, transaction.getCreditCurrency()), newBalance, null); } OperationCreditTransformer(String balanceStateStoreName, String rateStoreName); @Override @SuppressWarnings("unchecked") void init(ProcessorContext context); @Override void close(); @Override OperationResult transform(Transaction transaction); }
OperationCreditTransformer extends OperationTransformer { @Override public OperationResult transform(Transaction transaction) { String error = validateOperation(transaction); if (error != null) { return new OperationResult(false, transaction, null, error); } BigDecimal creditAmount = transaction.getCreditAmount(); if (Transaction.Type.EXCHANGE.equals(transaction.getType())) { Optional<ExchangeRate> exchangeRate = Optional .ofNullable(rateStore.get(transaction.getCreditCurrency() + "-" + transaction.getDebitCurrency())); Optional<ExchangeRate> invertedExchangeRate = Optional .ofNullable(rateStore.get(transaction.getDebitCurrency() + "-" + transaction.getCreditCurrency())); ExchangeRate rate = exchangeRate.orElse(invertedExchangeRate.orElse(null)); if (rate == null) { return new OperationResult(false, transaction, null, "Exchange rate could not be found for " + transaction.getCreditCurrency() + " and " + transaction.getDebitCurrency()); } if (rate.getBaseCurrency().equals(transaction.getCreditCurrency())) { creditAmount = transaction.getDebitAmount().multiply(rate.getBid()); } else { creditAmount = transaction.getDebitAmount().divide(rate.getAsk(), 5, RoundingMode.HALF_UP); } } String storeKey = transaction.getAccount() + "-" + transaction.getCreditCurrency(); AccountCurrencyBalance existingBalance = Optional.ofNullable(balanceStore.get(storeKey)) .orElseGet(() -> new AccountCurrencyBalance( new AccountCurrency(transaction.getAccount(), transaction.getCreditCurrency()), BigDecimal.ZERO)); AccountCurrencyBalance newBalance = new AccountCurrencyBalance(existingBalance.getAccountCurrency(), existingBalance.getBalance().add(creditAmount)); balanceStore.put(storeKey, newBalance); return new OperationResult(true, new Transaction(transaction.getGuid(), transaction.getAccount(), transaction.getType(), transaction.getDebitAmount(), transaction.getDebitCurrency(), creditAmount, transaction.getCreditCurrency()), newBalance, null); } OperationCreditTransformer(String balanceStateStoreName, String rateStoreName); @Override @SuppressWarnings("unchecked") void init(ProcessorContext context); @Override void close(); @Override OperationResult transform(Transaction transaction);  }