Perform sensible currency conversion (#1941)

It is kind of sad to see 1 GBP to be equal to 1 USD and also it looks misleading in the blotter.
This commit is contained in:
Viktor Kolomeyko 2017-10-25 19:25:19 +01:00 committed by GitHub
parent 44a7d872d8
commit dcca3179d9
2 changed files with 65 additions and 2 deletions

View File

@ -3,8 +3,12 @@ package net.corda.client.jfx.model
import javafx.beans.property.SimpleObjectProperty
import javafx.beans.value.ObservableValue
import net.corda.core.contracts.Amount
import net.corda.finance.CHF
import net.corda.finance.EUR
import net.corda.finance.GBP
import net.corda.finance.USD
import java.math.BigDecimal
import java.math.RoundingMode
import java.math.MathContext
import java.util.*
/**
@ -24,9 +28,24 @@ abstract class ExchangeRate {
/**
* Default implementation of an exchange rate model, which uses a fixed exchange rate.
*/
private val usdExchangeRates: Map<Currency, BigDecimal> = mapOf(
GBP to BigDecimal(1.31),
EUR to BigDecimal(1.18),
CHF to BigDecimal(1.01)
)
private fun safeFetchRate(currency: Currency) =
usdExchangeRates[currency] ?: throw IllegalArgumentException("No exchange rate for $currency")
// TODO hook up an actual oracle
class ExchangeRateModel {
val exchangeRate: ObservableValue<ExchangeRate> = SimpleObjectProperty<ExchangeRate>(object : ExchangeRate() {
override fun rate(from: Currency, to: Currency) = BigDecimal.ONE
override fun rate(from: Currency, to: Currency): BigDecimal =
when {
from == to -> BigDecimal.ONE
USD == to -> safeFetchRate(from)
USD == from -> BigDecimal.ONE.divide(safeFetchRate(to), MathContext.DECIMAL64)
else -> safeFetchRate(from).divide(safeFetchRate(to), MathContext.DECIMAL64)
}
})
}

View File

@ -0,0 +1,44 @@
package net.corda.client.jfx.model
import net.corda.core.contracts.Amount
import net.corda.finance.CHF
import net.corda.finance.GBP
import net.corda.finance.RUB
import net.corda.finance.USD
import org.assertj.core.api.Assertions
import org.junit.Test
import java.math.BigDecimal
import java.util.*
import kotlin.test.assertEquals
import kotlin.test.assertTrue
class ExchangeRateModelTest {
companion object {
private val instance = ExchangeRateModel().exchangeRate.value
private fun assertEquals(one: Amount<Currency>, another: Amount<Currency>) {
assertEquals(one.token, another.token)
assertTrue("$one != $another", {(one.toDecimal() - another.toDecimal()).abs() < BigDecimal(0.01) })
}
}
@Test
fun `perform fx testing`() {
val tenSwissies = Amount(10, BigDecimal.ONE, CHF)
assertEquals(instance.exchangeAmount(tenSwissies, CHF), tenSwissies)
val tenSwissiesInUsd = Amount(101, BigDecimal.ONE.divide(BigDecimal.TEN), USD)
assertEquals(instance.exchangeAmount(tenSwissies, USD), tenSwissiesInUsd)
assertEquals(instance.exchangeAmount(tenSwissiesInUsd, CHF), tenSwissies)
val tenQuidInSwissies = Amount(1297, BigDecimal.ONE.divide(BigDecimal(100)), CHF)
val tenQuid = Amount(10, BigDecimal.ONE, GBP)
assertEquals(instance.exchangeAmount(tenQuid, CHF), tenQuidInSwissies)
assertEquals(instance.exchangeAmount(tenQuidInSwissies, GBP), tenQuid)
Assertions.assertThatThrownBy { instance.exchangeAmount(tenQuid, RUB) }.isInstanceOf(IllegalArgumentException::class.java)
.hasMessage("No exchange rate for RUB")
}
}