mirror of
https://github.com/bitcoinj/bitcoinj.git
synced 2024-11-20 02:09:29 +01:00
Coin: satoshi/long <-> btc/BigDecimal
* Add static utility methods: btcToSatoshi(), satoshiToBtc() * Add static factory method: ofBtc() * Add instance method: toBtc() * Add hamcrest-library to testImplementation for BigDecimal comparison
This commit is contained in:
parent
6d15df682a
commit
f6c8b0dbe3
@ -22,6 +22,7 @@ dependencies {
|
||||
testImplementation 'com.h2database:h2:1.3.167'
|
||||
testImplementation 'org.fusesource.leveldbjni:leveldbjni-all:1.8'
|
||||
testImplementation 'nl.jqno.equalsverifier:equalsverifier:2.5.2'
|
||||
testImplementation 'org.hamcrest:hamcrest-library:1.3'
|
||||
}
|
||||
|
||||
sourceCompatibility = 1.7
|
||||
|
@ -86,6 +86,12 @@ public final class Coin implements Monetary, Comparable<Coin>, Serializable {
|
||||
this.value = satoshis;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@code Coin} from a long integer number of satoshis.
|
||||
*
|
||||
* @param satoshis number of satoshis
|
||||
* @return {@code Coin} object containing value in satoshis
|
||||
*/
|
||||
public static Coin valueOf(final long satoshis) {
|
||||
return new Coin(satoshis);
|
||||
}
|
||||
@ -104,7 +110,7 @@ public final class Coin implements Monetary, Comparable<Coin>, Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an amount expressed in the way humans are used to into satoshis.
|
||||
* Create a {@code Coin} from an amount expressed in "the way humans are used to".
|
||||
*
|
||||
* @param coins Number of bitcoins
|
||||
* @param cents Number of bitcents (0.01 bitcoin)
|
||||
@ -119,7 +125,47 @@ public final class Coin implements Monetary, Comparable<Coin>, Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses an amount expressed in the way humans are used to.
|
||||
* Convert a decimal amount of BTC into satoshis.
|
||||
*
|
||||
* @param coins number of coins
|
||||
* @return number of satoshis
|
||||
*/
|
||||
public static long btcToSatoshi(BigDecimal coins) {
|
||||
return coins.movePointRight(SMALLEST_UNIT_EXPONENT).longValueExact();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert an amount in satoshis to an amount in BTC.
|
||||
*
|
||||
* @param satoshis number of satoshis
|
||||
* @return number of bitcoins (in BTC)
|
||||
*/
|
||||
public static BigDecimal satoshiToBtc(long satoshis) {
|
||||
return new BigDecimal(satoshis).movePointLeft(SMALLEST_UNIT_EXPONENT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@code Coin} from a decimal amount of BTC.
|
||||
*
|
||||
* @param coins number of coins (in BTC)
|
||||
* @return {@code Coin} object containing value in satoshis
|
||||
*/
|
||||
public static Coin ofBtc(BigDecimal coins) {
|
||||
return Coin.valueOf(btcToSatoshi(coins));
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@code Coin} from a long integer number of satoshis.
|
||||
*
|
||||
* @param satoshis number of satoshis
|
||||
* @return {@code Coin} object containing value in satoshis
|
||||
*/
|
||||
public static Coin ofSat(long satoshis) {
|
||||
return Coin.valueOf(satoshis);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@code Coin} by parsing a {@code String} amount expressed in "the way humans are used to".
|
||||
*
|
||||
* @param str string in a format understood by {@link BigDecimal#BigDecimal(String)}, for example "0", "1", "0.10",
|
||||
* * "1.23E3", "1234.5E-5".
|
||||
@ -129,7 +175,7 @@ public final class Coin implements Monetary, Comparable<Coin>, Serializable {
|
||||
*/
|
||||
public static Coin parseCoin(final String str) {
|
||||
try {
|
||||
long satoshis = new BigDecimal(str).movePointRight(SMALLEST_UNIT_EXPONENT).longValueExact();
|
||||
long satoshis = btcToSatoshi(new BigDecimal(str));
|
||||
return Coin.valueOf(satoshis);
|
||||
} catch (ArithmeticException e) {
|
||||
throw new IllegalArgumentException(e); // Repackage exception to honor method contract
|
||||
@ -137,7 +183,8 @@ public final class Coin implements Monetary, Comparable<Coin>, Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses an amount expressed in the way humans are used to. The amount is cut to satoshi precision.
|
||||
* Create a {@code Coin} by parsing a {@code String} amount expressed in "the way humans are used to".
|
||||
* The amount is cut to satoshi precision.
|
||||
*
|
||||
* @param str string in a format understood by {@link BigDecimal#BigDecimal(String)}, for example "0", "1", "0.10",
|
||||
* * "1.23E3", "1234.5E-5".
|
||||
@ -275,6 +322,24 @@ public final class Coin implements Monetary, Comparable<Coin>, Serializable {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert to number of satoshis
|
||||
*
|
||||
* @return decimal number of satoshis
|
||||
*/
|
||||
public long toSat() {
|
||||
return this.value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert to number of bitcoin (in BTC)
|
||||
*
|
||||
* @return decimal number of bitcoin (in BTC)
|
||||
*/
|
||||
public BigDecimal toBtc() {
|
||||
return satoshiToBtc(this.value);
|
||||
}
|
||||
|
||||
private static final MonetaryFormat FRIENDLY_FORMAT = MonetaryFormat.BTC.minDecimals(2).repeatOptionalDecimals(1, 6).postfixCode();
|
||||
|
||||
/**
|
||||
|
@ -19,13 +19,17 @@ package org.bitcoinj.core;
|
||||
import static org.bitcoinj.core.Coin.*;
|
||||
import static org.bitcoinj.core.NetworkParameters.MAX_MONEY;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import org.hamcrest.Matchers;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
public class CoinTest {
|
||||
|
||||
@Test
|
||||
@ -80,6 +84,54 @@ public class CoinTest {
|
||||
} catch (IllegalArgumentException e) {}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testBtcToSatoshi() {
|
||||
assertEquals(Long.MIN_VALUE, btcToSatoshi(new BigDecimal("-92233720368.54775808")));
|
||||
assertEquals(0L, btcToSatoshi(BigDecimal.ZERO));
|
||||
assertEquals(COIN.value, btcToSatoshi(BigDecimal.ONE));
|
||||
assertEquals(Long.MAX_VALUE, btcToSatoshi(new BigDecimal("92233720368.54775807")));
|
||||
}
|
||||
|
||||
@Test(expected = ArithmeticException.class)
|
||||
public void testBtcToSatoshi_tooSmall() {
|
||||
btcToSatoshi(new BigDecimal("-92233720368.54775809")); // .00000001 less than minimum value
|
||||
}
|
||||
|
||||
@Test(expected = ArithmeticException.class)
|
||||
public void testBtcToSatoshi_tooBig() {
|
||||
btcToSatoshi(new BigDecimal("92233720368.54775808")); // .00000001 more than maximum value
|
||||
}
|
||||
|
||||
@Test(expected = ArithmeticException.class)
|
||||
public void testBtcToSatoshi_tooPrecise1() {
|
||||
btcToSatoshi(new BigDecimal("0.000000001")); // More than SMALLEST_UNIT_EXPONENT precision
|
||||
}
|
||||
|
||||
@Test(expected = ArithmeticException.class)
|
||||
public void testBtcToSatoshi_tooPrecise2() {
|
||||
btcToSatoshi(new BigDecimal("92233720368.547758079")); // More than SMALLEST_UNIT_EXPONENT precision
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSatoshiToBtc() {
|
||||
assertThat(new BigDecimal("-92233720368.54775808"), Matchers.comparesEqualTo(satoshiToBtc(Long.MIN_VALUE)));
|
||||
assertThat(new BigDecimal("-0.00000001"), Matchers.comparesEqualTo(satoshiToBtc(NEGATIVE_SATOSHI.value)));
|
||||
assertThat(BigDecimal.ZERO, Matchers.comparesEqualTo(satoshiToBtc(0L)));
|
||||
assertThat(new BigDecimal("0.00000001"), Matchers.comparesEqualTo(satoshiToBtc(SATOSHI.value)));
|
||||
assertThat(BigDecimal.ONE, Matchers.comparesEqualTo(satoshiToBtc(COIN.value)));
|
||||
assertThat(new BigDecimal(50), Matchers.comparesEqualTo(satoshiToBtc(FIFTY_COINS.value)));
|
||||
assertThat(new BigDecimal("92233720368.54775807"), Matchers.comparesEqualTo(satoshiToBtc(Long.MAX_VALUE)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOfBtc() {
|
||||
assertEquals(Coin.valueOf(Long.MIN_VALUE), Coin.ofBtc(new BigDecimal("-92233720368.54775808")));
|
||||
assertEquals(ZERO, Coin.ofBtc(BigDecimal.ZERO));
|
||||
assertEquals(COIN, Coin.ofBtc(BigDecimal.ONE));
|
||||
assertEquals(Coin.valueOf(Long.MAX_VALUE), Coin.ofBtc(new BigDecimal("92233720368.54775807")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOperators() {
|
||||
assertTrue(SATOSHI.isPositive());
|
||||
@ -120,6 +172,17 @@ public class CoinTest {
|
||||
Coin.valueOf(Long.MIN_VALUE).subtract(Coin.SATOSHI);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToBtc() {
|
||||
assertThat(new BigDecimal("-92233720368.54775808"), Matchers.comparesEqualTo(Coin.valueOf(Long.MIN_VALUE).toBtc()));
|
||||
assertThat(new BigDecimal("-0.00000001"), Matchers.comparesEqualTo(NEGATIVE_SATOSHI.toBtc()));
|
||||
assertThat(BigDecimal.ZERO, Matchers.comparesEqualTo(ZERO.toBtc()));
|
||||
assertThat(new BigDecimal("0.00000001"), Matchers.comparesEqualTo(SATOSHI.toBtc()));
|
||||
assertThat(BigDecimal.ONE, Matchers.comparesEqualTo(COIN.toBtc()));
|
||||
assertThat(new BigDecimal(50), Matchers.comparesEqualTo(FIFTY_COINS.toBtc()));
|
||||
assertThat(new BigDecimal("92233720368.54775807"), Matchers.comparesEqualTo(Coin.valueOf(Long.MAX_VALUE).toBtc()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testToFriendlyString() {
|
||||
assertEquals("1.00 BTC", COIN.toFriendlyString());
|
||||
|
Loading…
Reference in New Issue
Block a user