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.property.SimpleObjectProperty
import javafx.beans.value.ObservableValue import javafx.beans.value.ObservableValue
import net.corda.core.contracts.Amount 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.BigDecimal
import java.math.RoundingMode import java.math.MathContext
import java.util.* import java.util.*
/** /**
@ -24,9 +28,24 @@ abstract class ExchangeRate {
/** /**
* Default implementation of an exchange rate model, which uses a fixed exchange rate. * 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 // TODO hook up an actual oracle
class ExchangeRateModel { class ExchangeRateModel {
val exchangeRate: ObservableValue<ExchangeRate> = SimpleObjectProperty<ExchangeRate>(object : ExchangeRate() { 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")
}
}