mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2025-02-22 14:33:06 +01:00
Natural language syntax for currencies (#440)
* Convert CurrencyUnit and LnCurrencyUnit Scalacheck to Scalatest * Add Int and Long syntax to LnCurrencyUnit, MilliSatoshis and CurrencyUnit * Tweak toString methods
This commit is contained in:
parent
6944f948ab
commit
e34c4505d4
8 changed files with 484 additions and 19 deletions
|
@ -0,0 +1,167 @@
|
|||
package org.bitcoins.core.currency
|
||||
|
||||
import org.bitcoins.core.currency._
|
||||
|
||||
import org.bitcoins.testkit.util.BitcoinSUnitTest
|
||||
import org.bitcoins.testkit.core.gen.CurrencyUnitGenerator
|
||||
import scala.util.Try
|
||||
import org.bitcoins.core.number.Int64
|
||||
import scala.util.Success
|
||||
import scala.util.Failure
|
||||
import org.scalacheck.Gen
|
||||
import org.scalacheck.Shrink
|
||||
|
||||
class CurrencyUnitTest extends BitcoinSUnitTest {
|
||||
|
||||
behavior of "Satoshis"
|
||||
|
||||
it must "have symmetry serialization" in {
|
||||
forAll(CurrencyUnitGenerator.satoshis) { satoshis =>
|
||||
assert(Satoshis(satoshis.hex) == satoshis)
|
||||
}
|
||||
}
|
||||
|
||||
it must "have Int syntax" in {
|
||||
forAll(Gen.choose(0, Int.MaxValue)) { num =>
|
||||
assert(num.bitcoins == Bitcoins(num))
|
||||
assert(num.bitcoin == Bitcoins(num))
|
||||
assert(num.BTC == Bitcoins(num))
|
||||
|
||||
assert(num.satoshis == Satoshis(Int64(num)))
|
||||
assert(num.satoshi == Satoshis(Int64(num)))
|
||||
assert(num.sats == Satoshis(Int64(num)))
|
||||
assert(num.sat == Satoshis(Int64(num)))
|
||||
}
|
||||
}
|
||||
|
||||
it must "have Long syntax" in {
|
||||
forAll(Gen.choose(0, Satoshis.max.toLong / 100000000)) { num =>
|
||||
assert(num.bitcoins == Bitcoins(num))
|
||||
assert(num.bitcoin == Bitcoins(num))
|
||||
assert(num.BTC == Bitcoins(num))
|
||||
}
|
||||
|
||||
forAll(Gen.choose(0, Satoshis.max.toLong)) { num =>
|
||||
assert(num.satoshis == Satoshis(Int64(num)))
|
||||
assert(num.satoshi == Satoshis(Int64(num)))
|
||||
assert(num.sats == Satoshis(Int64(num)))
|
||||
assert(num.sat == Satoshis(Int64(num)))
|
||||
}
|
||||
}
|
||||
|
||||
it must "have additive identity" in {
|
||||
forAll(CurrencyUnitGenerator.satoshis) { satoshis =>
|
||||
assert(satoshis + CurrencyUnits.zero == satoshis)
|
||||
}
|
||||
}
|
||||
|
||||
it must "add satoshis" in {
|
||||
forAll(CurrencyUnitGenerator.satoshis, CurrencyUnitGenerator.satoshis) {
|
||||
(num1, num2) => (num1: Satoshis, num2: Satoshis) =>
|
||||
val result: Try[Int64] = Try(Int64(num1.toBigInt + num2.toBigInt))
|
||||
if (result.isSuccess && result.get >= Int64(Satoshis.min.toLong) &&
|
||||
result.get <= Int64(Satoshis.max.toLong))
|
||||
assert(num1 + num2 == Satoshis(result.get))
|
||||
else assert(Try(num1 + num2).isFailure)
|
||||
}
|
||||
}
|
||||
|
||||
it must "have subtractive identity for satoshis" in {
|
||||
forAll(CurrencyUnitGenerator.satoshis) { satoshis =>
|
||||
assert(satoshis - CurrencyUnits.zero == satoshis)
|
||||
}
|
||||
}
|
||||
|
||||
it must "subtract satoshis " in {
|
||||
forAll(CurrencyUnitGenerator.satoshis, CurrencyUnitGenerator.satoshis) {
|
||||
(num1: Satoshis, num2: Satoshis) =>
|
||||
val result: Try[Int64] = Try(Int64(num1.toBigInt - num2.toBigInt))
|
||||
if (result.isSuccess && result.get >= Int64(Satoshis.min.toLong) &&
|
||||
result.get <= Int64(Satoshis.max.toLong))
|
||||
assert(num1 - num2 == Satoshis(result.get))
|
||||
else assert(Try(num1 - num2).isFailure)
|
||||
}
|
||||
}
|
||||
|
||||
it must "multiply satoshis by zero" in {
|
||||
forAll(CurrencyUnitGenerator.satoshis) { satoshis =>
|
||||
assert(satoshis * CurrencyUnits.zero == CurrencyUnits.zero)
|
||||
}
|
||||
}
|
||||
|
||||
it must "have multiplicative identity" in {
|
||||
forAll(CurrencyUnitGenerator.satoshis) { satoshis =>
|
||||
assert(satoshis * Satoshis.one == satoshis)
|
||||
}
|
||||
}
|
||||
|
||||
it must "multiply satoshis" in {
|
||||
forAll(CurrencyUnitGenerator.satoshis, CurrencyUnitGenerator.satoshis) {
|
||||
(num1, num2) =>
|
||||
val result: Try[Int64] = Try(Int64(num1.toBigInt * num2.toBigInt))
|
||||
if (result.isSuccess && result.get >= Int64(Satoshis.min.toLong) &&
|
||||
result.get <= Int64(Satoshis.max.toLong))
|
||||
num1 * num2 == Satoshis(result.get)
|
||||
else Try(num1 * num2).isFailure
|
||||
}
|
||||
}
|
||||
|
||||
private val satoshiWithInt: Gen[(Satoshis, Int)] = for {
|
||||
sat <- CurrencyUnitGenerator.satoshis
|
||||
num <- Gen.choose(Int.MinValue, Int.MaxValue)
|
||||
} yield (sat, num)
|
||||
|
||||
it must "multiply a satoshi value with an int" in {
|
||||
forAll(satoshiWithInt) {
|
||||
case (sat, int) =>
|
||||
val safeProduct = sat.multiplySafe(int)
|
||||
val underlyingProduct = sat.toBigInt * int
|
||||
if (underlyingProduct < Satoshis.max.toBigInt && underlyingProduct > Satoshis.min.toBigInt) {
|
||||
assert(safeProduct.isSuccess)
|
||||
assert(safeProduct.get.satoshis.toBigInt == underlyingProduct)
|
||||
} else {
|
||||
assert(safeProduct.isFailure)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
it must "have '< & >=' property" in {
|
||||
forAll(CurrencyUnitGenerator.satoshis, CurrencyUnitGenerator.satoshis) {
|
||||
(num1, num2) =>
|
||||
assert((num1 < num2) || (num1 >= num2))
|
||||
}
|
||||
}
|
||||
|
||||
it must "have '<= & >' property" in {
|
||||
forAll(CurrencyUnitGenerator.satoshis, CurrencyUnitGenerator.satoshis) {
|
||||
(num1, num2) =>
|
||||
assert((num1 <= num2) || (num1 > num2))
|
||||
}
|
||||
}
|
||||
|
||||
it must "have '== & !=' property" in {
|
||||
forAll(CurrencyUnitGenerator.satoshis, CurrencyUnitGenerator.satoshis) {
|
||||
(num1, num2) =>
|
||||
assert((num1 == num2) || (num1 != num2))
|
||||
}
|
||||
}
|
||||
|
||||
it must "convert satoshis to bitcoin and then back to satoshis" in {
|
||||
forAll(CurrencyUnitGenerator.satoshis) { satoshis =>
|
||||
val b = Bitcoins(satoshis)
|
||||
assert(b.satoshis == satoshis)
|
||||
}
|
||||
}
|
||||
|
||||
it must "be able to add two unique currency unit types" in {
|
||||
forAll(CurrencyUnitGenerator.satoshis, CurrencyUnitGenerator.bitcoins) {
|
||||
(sats: Satoshis, btc: Bitcoins) =>
|
||||
val result =
|
||||
Try(Satoshis(Int64(sats.toBigInt + btc.satoshis.toBigInt)))
|
||||
val expected = result.map(Bitcoins(_))
|
||||
val actual: Try[CurrencyUnit] = Try(sats + btc)
|
||||
if (actual.isSuccess && expected.isSuccess) actual.get == expected.get
|
||||
else actual.isFailure && expected.isFailure
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,10 +1,166 @@
|
|||
package org.bitcoins.core.protocol.ln.currency
|
||||
|
||||
import org.bitcoins.core.protocol.ln.currency._
|
||||
import org.bitcoins.core.currency.Satoshis
|
||||
import org.bitcoins.core.protocol.ln.LnPolicy
|
||||
import org.scalatest.{FlatSpec, MustMatchers}
|
||||
import org.bitcoins.testkit.util.BitcoinSUnitTest
|
||||
import org.bitcoins.testkit.core.gen.ln.LnCurrencyUnitGen
|
||||
import scala.util.Success
|
||||
import scala.util.Failure
|
||||
import scala.util.Try
|
||||
import org.scalacheck.Gen
|
||||
import org.bitcoins.core.number.Int64
|
||||
|
||||
class LnCurrencyUnitTest extends BitcoinSUnitTest {
|
||||
|
||||
it must "have additive identity" in {
|
||||
forAll(LnCurrencyUnitGen.lnCurrencyUnit) { lnUnit =>
|
||||
assert(lnUnit + LnCurrencyUnits.zero == lnUnit)
|
||||
}
|
||||
}
|
||||
|
||||
it must "add to LnCurrencyUnits" in {
|
||||
forAll(LnCurrencyUnitGen.lnCurrencyUnit, LnCurrencyUnitGen.lnCurrencyUnit) {
|
||||
(num1, num2) =>
|
||||
val resultT: Try[LnCurrencyUnit] = Try(num1 + num2)
|
||||
resultT match {
|
||||
case Success(result) =>
|
||||
assert(PicoBitcoins.min <= result)
|
||||
assert(result <= PicoBitcoins.max)
|
||||
assert(num1 + num2 == result)
|
||||
case Failure(exc) => succeed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
it must "have subtractive identity for LnCurrencyUnits" in {
|
||||
forAll(LnCurrencyUnitGen.lnCurrencyUnit) { lnUnit =>
|
||||
assert(lnUnit - LnCurrencyUnits.zero == lnUnit)
|
||||
}
|
||||
}
|
||||
|
||||
it must "subtract two LnCurrencyUnit values" in {
|
||||
forAll(LnCurrencyUnitGen.lnCurrencyUnit, LnCurrencyUnitGen.lnCurrencyUnit) {
|
||||
(num1, num2) =>
|
||||
val resultT: Try[LnCurrencyUnit] = Try(num1 - num2)
|
||||
resultT match {
|
||||
case Success(result) =>
|
||||
assert(PicoBitcoins.min <= result)
|
||||
assert(result <= PicoBitcoins.max)
|
||||
assert(num1 - num2 == result)
|
||||
case Failure(exc) => succeed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
it must "multiply LnCurrencyUnit by zero" in {
|
||||
forAll(LnCurrencyUnitGen.lnCurrencyUnit) { lnUnit =>
|
||||
assert(lnUnit * LnCurrencyUnits.zero == LnCurrencyUnits.zero)
|
||||
}
|
||||
}
|
||||
|
||||
it must "have multiplicative identity for LnCurrencyUnits" in {
|
||||
forAll(LnCurrencyUnitGen.lnCurrencyUnit) { lnUnit =>
|
||||
assert(lnUnit * PicoBitcoins.one == lnUnit)
|
||||
}
|
||||
}
|
||||
|
||||
it must "multiply two LnCurrencyUnit values" in {
|
||||
forAll(LnCurrencyUnitGen.lnCurrencyUnit, LnCurrencyUnitGen.lnCurrencyUnit) {
|
||||
(num1, num2) =>
|
||||
val resultT: Try[LnCurrencyUnit] = Try(num1 * num2)
|
||||
resultT match {
|
||||
case Success(result) =>
|
||||
assert(result >= PicoBitcoins.min)
|
||||
assert(result <= PicoBitcoins.max)
|
||||
assert(num1 * num2 == result)
|
||||
case Failure(exc) => succeed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private val lnCurrWithInt: Gen[(LnCurrencyUnit, Int)] = for {
|
||||
ln <- LnCurrencyUnitGen.lnCurrencyUnit
|
||||
num <- Gen.choose(Int.MinValue, Int.MaxValue)
|
||||
} yield (ln, num)
|
||||
|
||||
it must "multiply a LnCurrencyUnit value with an int" in {
|
||||
forAll(lnCurrWithInt) {
|
||||
case (ln, int) =>
|
||||
val safeProduct = ln.multiplySafe(int)
|
||||
val underlyingProduct = ln.toBigInt * int
|
||||
if (underlyingProduct <= PicoBitcoins.min.toBigInt && underlyingProduct >= PicoBitcoins.max.toBigInt) {
|
||||
assert(safeProduct.isSuccess)
|
||||
safeProduct.get.toBigInt == underlyingProduct
|
||||
} else {
|
||||
safeProduct.isFailure
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
it must "have property '< & >=''" in {
|
||||
forAll(LnCurrencyUnitGen.lnCurrencyUnit, LnCurrencyUnitGen.lnCurrencyUnit) {
|
||||
(num1, num2) =>
|
||||
assert((num1 < num2) || (num1 >= num2))
|
||||
}
|
||||
}
|
||||
|
||||
it must "have property '<= & >'" in {
|
||||
forAll(LnCurrencyUnitGen.lnCurrencyUnit, LnCurrencyUnitGen.lnCurrencyUnit) {
|
||||
(num1, num2) =>
|
||||
assert((num1 <= num2) || (num1 > num2))
|
||||
}
|
||||
}
|
||||
|
||||
it must "have property '== & !='" in {
|
||||
forAll(LnCurrencyUnitGen.lnCurrencyUnit, LnCurrencyUnitGen.lnCurrencyUnit) {
|
||||
(num1, num2) =>
|
||||
assert((num1 == num2) || (num1 != num2))
|
||||
}
|
||||
}
|
||||
|
||||
it must "have Int syntax" in {
|
||||
forAll(Gen.choose(Int.MinValue, Int.MaxValue)) { num =>
|
||||
assert(num.millibitcoins == MilliBitcoins(num))
|
||||
assert(num.millibitcoin == MilliBitcoins(num))
|
||||
assert(num.mBTC == MilliBitcoins(num))
|
||||
|
||||
assert(num.microbitcoins == MicroBitcoins(num))
|
||||
assert(num.microbitcoin == MicroBitcoins(num))
|
||||
assert(num.uBTC == MicroBitcoins(num))
|
||||
|
||||
assert(num.nanobitcoins == NanoBitcoins(num))
|
||||
assert(num.nanobitcoin == NanoBitcoins(num))
|
||||
assert(num.nBTC == NanoBitcoins(num))
|
||||
|
||||
assert(num.picobitcoins == PicoBitcoins(num))
|
||||
assert(num.picobitcoin == PicoBitcoins(num))
|
||||
assert(num.pBTC == PicoBitcoins(num))
|
||||
}
|
||||
}
|
||||
|
||||
it must "have Long syntax" in {
|
||||
forAll(
|
||||
Gen.choose(LnPolicy.minMilliBitcoins.toLong,
|
||||
LnPolicy.maxMilliBitcoins.toLong)) { num =>
|
||||
assert(num.millibitcoins == MilliBitcoins(num))
|
||||
assert(num.millibitcoin == MilliBitcoins(num))
|
||||
assert(num.mBTC == MilliBitcoins(num))
|
||||
|
||||
assert(num.microbitcoins == MicroBitcoins(num))
|
||||
assert(num.microbitcoin == MicroBitcoins(num))
|
||||
assert(num.uBTC == MicroBitcoins(num))
|
||||
|
||||
assert(num.nanobitcoins == NanoBitcoins(num))
|
||||
assert(num.nanobitcoin == NanoBitcoins(num))
|
||||
assert(num.nBTC == NanoBitcoins(num))
|
||||
|
||||
assert(num.picobitcoins == PicoBitcoins(num))
|
||||
assert(num.picobitcoin == PicoBitcoins(num))
|
||||
assert(num.pBTC == PicoBitcoins(num))
|
||||
}
|
||||
}
|
||||
|
||||
class LnCurrencyUnitTest extends FlatSpec with MustMatchers {
|
||||
it must "serialize MilliBitcoins to string" in {
|
||||
val milliBitcoins = MilliBitcoins(1000)
|
||||
milliBitcoins.toEncodedString must be("1000m")
|
||||
|
|
|
@ -4,6 +4,7 @@ import org.bitcoins.testkit.core.gen.{CurrencyUnitGenerator, NumberGenerator}
|
|||
import org.bitcoins.testkit.core.gen.ln.LnCurrencyUnitGen
|
||||
import org.bitcoins.testkit.util.BitcoinSUnitTest
|
||||
import org.scalatest.prop.PropertyChecks
|
||||
import org.scalacheck.Gen
|
||||
|
||||
class MilliSatoshisTest extends BitcoinSUnitTest {
|
||||
behavior of "MilliSatoshis"
|
||||
|
@ -26,7 +27,7 @@ class MilliSatoshisTest extends BitcoinSUnitTest {
|
|||
}
|
||||
|
||||
it must "add millisatoshis" in {
|
||||
PropertyChecks.forAll(LnCurrencyUnitGen.milliSatoshisPair) {
|
||||
forAll(LnCurrencyUnitGen.milliSatoshisPair) {
|
||||
case (first, second) =>
|
||||
val bigInt = first.toBigInt + second.toBigInt
|
||||
assert((first + second).toBigInt == bigInt)
|
||||
|
@ -39,7 +40,7 @@ class MilliSatoshisTest extends BitcoinSUnitTest {
|
|||
} yield (msat, num)
|
||||
|
||||
it must "multiply millisatoshis with an int" in {
|
||||
PropertyChecks.forAll(msatWithNum) {
|
||||
forAll(msatWithNum) {
|
||||
case (msat, bigint) =>
|
||||
val underlyingCalc = msat.toBigInt * bigint
|
||||
assert((msat * bigint).toBigInt == underlyingCalc)
|
||||
|
@ -47,7 +48,7 @@ class MilliSatoshisTest extends BitcoinSUnitTest {
|
|||
}
|
||||
|
||||
it must "multiply millisatoshis with itself" in {
|
||||
PropertyChecks.forAll(LnCurrencyUnitGen.milliSatoshisPair) {
|
||||
forAll(LnCurrencyUnitGen.milliSatoshisPair) {
|
||||
case (first, second) =>
|
||||
val safe = first.multiplySafe(second)
|
||||
val unsafe = first * second
|
||||
|
@ -60,7 +61,7 @@ class MilliSatoshisTest extends BitcoinSUnitTest {
|
|||
}
|
||||
|
||||
it must "subtract msats after adding them" in {
|
||||
PropertyChecks.forAll(LnCurrencyUnitGen.milliSatoshisPair) {
|
||||
forAll(LnCurrencyUnitGen.milliSatoshisPair) {
|
||||
case (first, second) =>
|
||||
val added = first + second
|
||||
val subtracted = added - second
|
||||
|
@ -69,7 +70,7 @@ class MilliSatoshisTest extends BitcoinSUnitTest {
|
|||
}
|
||||
|
||||
it must "subtract msats" in {
|
||||
PropertyChecks.forAll(LnCurrencyUnitGen.milliSatoshisPair) {
|
||||
forAll(LnCurrencyUnitGen.milliSatoshisPair) {
|
||||
case (first, second) =>
|
||||
val subtracted = first subtractSafe second
|
||||
val isPositive = (first.toBigInt - second.toBigInt) >= 0
|
||||
|
@ -83,8 +84,7 @@ class MilliSatoshisTest extends BitcoinSUnitTest {
|
|||
}
|
||||
|
||||
it must "covert from a ln currency unit -> millisatoshis -> lnCurrencyUnit" in {
|
||||
|
||||
PropertyChecks.forAll(LnCurrencyUnitGen.positivePicoBitcoin) { pb =>
|
||||
forAll(LnCurrencyUnitGen.positivePicoBitcoin) { pb =>
|
||||
val underlying = pb.toBigInt
|
||||
//we lose the last digit of precision converting
|
||||
//PicoBitcoins -> MilliSatoshis
|
||||
|
@ -103,10 +103,28 @@ class MilliSatoshisTest extends BitcoinSUnitTest {
|
|||
}
|
||||
|
||||
it must "convert sat -> msat -> sat" in {
|
||||
PropertyChecks.forAll(CurrencyUnitGenerator.positiveRealistic) { sat =>
|
||||
forAll(CurrencyUnitGenerator.positiveRealistic) { sat =>
|
||||
val msat = MilliSatoshis(sat)
|
||||
assert(msat.toSatoshis == sat)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
it must "have Int syntax" in {
|
||||
forAll(Gen.choose(0, Int.MaxValue)) { num =>
|
||||
assert(num.millisatoshis == MilliSatoshis(num))
|
||||
assert(num.millisatoshi == MilliSatoshis(num))
|
||||
assert(num.msats == MilliSatoshis(num))
|
||||
assert(num.msat == MilliSatoshis(num))
|
||||
}
|
||||
}
|
||||
|
||||
it must "have Long syntax" in {
|
||||
forAll(Gen.choose(0L, Long.MaxValue)) { num =>
|
||||
assert(num.millisatoshis == MilliSatoshis(num))
|
||||
assert(num.millisatoshi == MilliSatoshis(num))
|
||||
assert(num.msats == MilliSatoshis(num))
|
||||
assert(num.msat == MilliSatoshis(num))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,7 +64,11 @@ sealed abstract class CurrencyUnit
|
|||
sealed abstract class Satoshis extends CurrencyUnit {
|
||||
override type A = Int64
|
||||
|
||||
override def toString: String = s"$toLong sat"
|
||||
override def toString: String = {
|
||||
val num = toLong
|
||||
val postFix = if (num == 1) "sat" else "sats"
|
||||
s"$num $postFix"
|
||||
}
|
||||
|
||||
override def bytes: ByteVector = RawSatoshisSerializer.write(this)
|
||||
|
||||
|
|
40
core/src/main/scala/org/bitcoins/core/currency/package.scala
Normal file
40
core/src/main/scala/org/bitcoins/core/currency/package.scala
Normal file
|
@ -0,0 +1,40 @@
|
|||
package org.bitcoins.core
|
||||
|
||||
import org.bitcoins.core.number.Int64
|
||||
|
||||
// We extend AnyVal to avoid runtime allocation of new
|
||||
// objects. See the Scala documentation on value classes
|
||||
// and universal traits for more:
|
||||
// https://docs.scala-lang.org/overviews/core/value-classes.html
|
||||
package object currency {
|
||||
|
||||
/** Provides natural language syntax for bitcoins */
|
||||
implicit class BitcoinsInt(private val i: Int) extends AnyVal {
|
||||
def bitcoins: Bitcoins = Bitcoins(i)
|
||||
def bitcoin: Bitcoins = bitcoins
|
||||
def BTC: Bitcoins = bitcoins
|
||||
}
|
||||
|
||||
/** Provides natural language syntax for bitcoins */
|
||||
implicit class BitcoinsLong(private val i: Long) extends AnyVal {
|
||||
def bitcoins: Bitcoins = Bitcoins(i)
|
||||
def bitcoin: Bitcoins = bitcoins
|
||||
def BTC: Bitcoins = bitcoins
|
||||
}
|
||||
|
||||
/** Provides natural language syntax for satoshis */
|
||||
implicit class SatoshisInt(private val i: Int) extends AnyVal {
|
||||
def satoshis: Satoshis = Satoshis(Int64(i))
|
||||
def satoshi: Satoshis = satoshis
|
||||
def sats: Satoshis = satoshis
|
||||
def sat: Satoshis = satoshis
|
||||
}
|
||||
|
||||
/** Provides natural language syntax for satoshis */
|
||||
implicit class SatoshisLong(private val i: Long) extends AnyVal {
|
||||
def satoshis: Satoshis = Satoshis(Int64(i))
|
||||
def satoshi: Satoshis = satoshis
|
||||
def sats: Satoshis = satoshis
|
||||
def sat: Satoshis = satoshis
|
||||
}
|
||||
}
|
|
@ -99,6 +99,8 @@ sealed abstract class LnCurrencyUnit
|
|||
def toEncodedString: String = {
|
||||
toBigInt + character.toString
|
||||
}
|
||||
|
||||
override def toString(): String = s"$underlying ${character}BTC"
|
||||
}
|
||||
|
||||
sealed abstract class MilliBitcoins extends LnCurrencyUnit {
|
||||
|
@ -128,8 +130,6 @@ object MilliBitcoins extends BaseNumbers[MilliBitcoins] {
|
|||
require(underlying <= LnPolicy.maxMilliBitcoins,
|
||||
"Number was too big for MilliBitcoins, got: " + underlying)
|
||||
|
||||
override def toString: String =
|
||||
s"${underlying / toPicoBitcoinMultiplier} mBTC"
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -160,8 +160,6 @@ object MicroBitcoins extends BaseNumbers[MicroBitcoins] {
|
|||
require(underlying <= LnPolicy.maxMicroBitcoins,
|
||||
"Number was too big for MicroBitcoins, got: " + underlying)
|
||||
|
||||
override def toString: String =
|
||||
s"${underlying / toPicoBitcoinMultiplier} uBTC"
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -191,8 +189,6 @@ object NanoBitcoins extends BaseNumbers[NanoBitcoins] {
|
|||
require(underlying <= LnPolicy.maxNanoBitcoins,
|
||||
"Number was too big for NanoBitcoins, got: " + underlying)
|
||||
|
||||
override def toString: String =
|
||||
s"${underlying / toPicoBitcoinMultiplier} nBTC"
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -220,7 +216,6 @@ object PicoBitcoins extends BaseNumbers[PicoBitcoins] {
|
|||
require(underlying <= LnPolicy.maxPicoBitcoins,
|
||||
"Number was too big for PicoBitcoins, got: " + underlying)
|
||||
|
||||
override def toString: String = s"$toBigInt pBTC"
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,11 @@ sealed abstract class MilliSatoshis
|
|||
* 10 msat
|
||||
* }}}
|
||||
*/
|
||||
override def toString: String = s"$toBigInt msat"
|
||||
override def toString: String = {
|
||||
val num = toBigInt
|
||||
val postFix = if (num == 1) "msat" else "msats"
|
||||
s"$num $postFix"
|
||||
}
|
||||
|
||||
def toBigInt: BigInt = underlying
|
||||
|
||||
|
|
|
@ -0,0 +1,81 @@
|
|||
package org.bitcoins.core.protocol.ln
|
||||
|
||||
// We extend AnyVal to avoid runtime allocation of new
|
||||
// objects. See the Scala documentation on value classes
|
||||
// and universal traits for more:
|
||||
// https://docs.scala-lang.org/overviews/core/value-classes.html
|
||||
package object currency {
|
||||
|
||||
/** Provides natural language syntax for millisatoshis */
|
||||
implicit class MilliSatoshisInt(private val i: Int) extends AnyVal {
|
||||
def millisatoshis: MilliSatoshis = MilliSatoshis(i)
|
||||
def millisatoshi: MilliSatoshis = millisatoshis
|
||||
def msats: MilliSatoshis = millisatoshis
|
||||
def msat: MilliSatoshis = millisatoshis
|
||||
}
|
||||
|
||||
/** Provides natural language syntax for millisatoshis */
|
||||
implicit class MilliSatoshisLong(private val i: Long) extends AnyVal {
|
||||
def millisatoshis: MilliSatoshis = MilliSatoshis(i)
|
||||
def millisatoshi: MilliSatoshis = millisatoshis
|
||||
def msats: MilliSatoshis = millisatoshis
|
||||
def msat: MilliSatoshis = millisatoshis
|
||||
}
|
||||
|
||||
/** Provides natural language syntax for millibitcoins */
|
||||
implicit class MilliBitcoinsInt(private val i: Int) extends AnyVal {
|
||||
def millibitcoins: MilliBitcoins = MilliBitcoins(i)
|
||||
def millibitcoin: MilliBitcoins = millibitcoins
|
||||
def mBTC: MilliBitcoins = millibitcoins
|
||||
}
|
||||
|
||||
/** Provides natural language syntax for millibitcoins */
|
||||
implicit class MilliBitcoinsLong(private val i: Long) extends AnyVal {
|
||||
def millibitcoins: MilliBitcoins = MilliBitcoins(i)
|
||||
def millibitcoin: MilliBitcoins = millibitcoins
|
||||
def mBTC: MilliBitcoins = millibitcoins
|
||||
}
|
||||
|
||||
/** Provides natural language syntax for microbitcoins */
|
||||
implicit class MicroBitcoinsInt(private val i: Int) extends AnyVal {
|
||||
def microbitcoins: MicroBitcoins = MicroBitcoins(i)
|
||||
def microbitcoin: MicroBitcoins = microbitcoins
|
||||
def uBTC: MicroBitcoins = microbitcoins
|
||||
}
|
||||
|
||||
/** Provides natural language syntax for microbitcoins */
|
||||
implicit class MicroBitcoinsLong(private val i: Long) extends AnyVal {
|
||||
def microbitcoins: MicroBitcoins = MicroBitcoins(i)
|
||||
def microbitcoin: MicroBitcoins = microbitcoins
|
||||
def uBTC: MicroBitcoins = microbitcoins
|
||||
}
|
||||
|
||||
/** Provides natural language syntax for nanobitcoins */
|
||||
implicit class NanoBitcoinsInt(private val i: Int) extends AnyVal {
|
||||
def nanobitcoins: NanoBitcoins = NanoBitcoins(i)
|
||||
def nanobitcoin: NanoBitcoins = nanobitcoins
|
||||
def nBTC: NanoBitcoins = nanobitcoins
|
||||
}
|
||||
|
||||
/** Provides natural language syntax for nanobitcoins */
|
||||
implicit class NanoBitcoinsLong(private val i: Long) extends AnyVal {
|
||||
def nanobitcoins: NanoBitcoins = NanoBitcoins(i)
|
||||
def nanobitcoin: NanoBitcoins = nanobitcoins
|
||||
def nBTC: NanoBitcoins = nanobitcoins
|
||||
}
|
||||
|
||||
/** Provides natural language syntax for picobitcoins */
|
||||
implicit class PicoitcoinsInt(private val i: Int) extends AnyVal {
|
||||
def picobitcoins: PicoBitcoins = PicoBitcoins(i)
|
||||
def picobitcoin: PicoBitcoins = picobitcoins
|
||||
def pBTC: PicoBitcoins = picobitcoins
|
||||
}
|
||||
|
||||
/** Provides natural language syntax for picobitcoins */
|
||||
implicit class PicoitcoinsLong(private val i: Long) extends AnyVal {
|
||||
def picobitcoins: PicoBitcoins = PicoBitcoins(i)
|
||||
def picobitcoin: PicoBitcoins = picobitcoins
|
||||
def pBTC: PicoBitcoins = picobitcoins
|
||||
}
|
||||
|
||||
}
|
Loading…
Add table
Reference in a new issue