Allow getbalance to return in sats

This commit is contained in:
Ben Carman 2020-02-27 14:18:38 -06:00
parent 6a5700ffef
commit 77674a3ca8
5 changed files with 62 additions and 15 deletions

View file

@ -91,8 +91,18 @@ object ConsoleCli {
), ),
cmd("getbalance") cmd("getbalance")
.hidden() .hidden()
.action((_, conf) => conf.copy(command = GetBalance)) .action((_, conf) => conf.copy(command = GetBalance(false)))
.text("Get the wallet balance"), .text("Get the wallet balance")
.children(
opt[Unit]("sats")
.required()
.action((_, conf) =>
conf.copy(command = conf.command match {
case getBalance: GetBalance =>
getBalance.copy(isSats = true)
case other => other
}))
),
cmd("getnewaddress") cmd("getnewaddress")
.hidden() .hidden()
.action((_, conf) => conf.copy(command = GetNewAddress)) .action((_, conf) => conf.copy(command = GetNewAddress))
@ -230,8 +240,8 @@ object ConsoleCli {
} }
val requestParam: RequestParam = config.command match { val requestParam: RequestParam = config.command match {
case GetBalance => case GetBalance(isSats) =>
RequestParam("getbalance") RequestParam("getbalance", Seq(up.writeJs(isSats)))
case GetNewAddress => case GetNewAddress =>
RequestParam("getnewaddress") RequestParam("getnewaddress")
case Rescan(addressBatchSize, startBlock, endBlock, force) => case Rescan(addressBatchSize, startBlock, endBlock, force) =>
@ -358,7 +368,7 @@ object CliCommand {
case class SendToAddress(destination: BitcoinAddress, amount: Bitcoins) case class SendToAddress(destination: BitcoinAddress, amount: Bitcoins)
extends CliCommand extends CliCommand
case object GetNewAddress extends CliCommand case object GetNewAddress extends CliCommand
case object GetBalance extends CliCommand case class GetBalance(isSats: Boolean) extends CliCommand
// Node // Node
case object GetPeers extends CliCommand case object GetPeers extends CliCommand

View file

@ -1,7 +1,7 @@
package org.bitcoins package org.bitcoins
import org.bitcoins.core.protocol.{BitcoinAddress, BlockStamp} import org.bitcoins.core.protocol.{BitcoinAddress, BlockStamp}
import org.bitcoins.core.currency.Bitcoins import org.bitcoins.core.currency.{Bitcoins, Satoshis}
import org.bitcoins.core.protocol.transaction.Transaction import org.bitcoins.core.protocol.transaction.Transaction
import org.bitcoins.core.psbt.PSBT import org.bitcoins.core.psbt.PSBT
import upickle.default._ import upickle.default._

View file

@ -198,11 +198,26 @@ class RoutesSpec
.returning(Future.successful(Bitcoins(50))) .returning(Future.successful(Bitcoins(50)))
val route = val route =
walletRoutes.handleCommand(ServerCommand("getbalance", Arr())) walletRoutes.handleCommand(
ServerCommand("getbalance", Arr(Bool(false))))
Get() ~> route ~> check { Get() ~> route ~> check {
contentType shouldEqual `application/json` contentType shouldEqual `application/json`
responseAs[String] shouldEqual """{"result":50,"error":null}""" responseAs[String] shouldEqual """{"result":"50.00000000 BTC","error":null}"""
}
}
"return the wallet's balance in sats" in {
(mockWalletApi.getBalance: () => Future[CurrencyUnit])
.expects()
.returning(Future.successful(Bitcoins(50)))
val route =
walletRoutes.handleCommand(ServerCommand("getbalance", Arr(Bool(true))))
Get() ~> route ~> check {
contentType shouldEqual `application/json`
responseAs[String] shouldEqual """{"result":"5000000000 sats","error":null}"""
} }
} }

View file

@ -17,6 +17,18 @@ object ServerCommand {
implicit val rw: ReadWriter[ServerCommand] = macroRW implicit val rw: ReadWriter[ServerCommand] = macroRW
} }
case class GetBalance(isSats: Boolean)
object GetBalance extends ServerJsonModels {
def fromJsArr(jsArr: ujson.Arr): Try[GetBalance] = {
require(jsArr.arr.size == 1,
s"Bad number of arguments: ${jsArr.arr.size}. Expected: 1")
Try(GetBalance(jsArr.arr.head.bool))
}
}
case class CombinePSBTs(psbts: Seq[PSBT]) case class CombinePSBTs(psbts: Seq[PSBT])
object CombinePSBTs extends ServerJsonModels { object CombinePSBTs extends ServerJsonModels {

View file

@ -20,14 +20,24 @@ case class WalletRoutes(wallet: UnlockedWalletApi, node: Node)(
implicit val materializer = ActorMaterializer() implicit val materializer = ActorMaterializer()
def handleCommand: PartialFunction[ServerCommand, StandardRoute] = { def handleCommand: PartialFunction[ServerCommand, StandardRoute] = {
case ServerCommand("getbalance", _) => case ServerCommand("getbalance", arr) =>
GetBalance.fromJsArr(arr) match {
case Failure(exception) =>
reject(ValidationRejection("failure", Some(exception)))
case Success(GetBalance(isSats)) =>
complete { complete {
wallet.getBalance().map { balance => wallet.getBalance().map { balance =>
Server.httpSuccess( Server.httpSuccess(
Bitcoins(balance.satoshis) if (isSats) {
balance.satoshis.toString
} else {
Bitcoins(balance.satoshis).toString
}
) )
} }
} }
}
case ServerCommand("getnewaddress", _) => case ServerCommand("getnewaddress", _) =>
complete { complete {
wallet.getNewAddress().map { address => wallet.getNewAddress().map { address =>