Move RPC server logic into separate project (#2440)

This commit is contained in:
benthecarman 2020-12-29 14:57:11 -06:00 committed by GitHub
parent b44aedacca
commit 214dba8a8f
19 changed files with 405 additions and 273 deletions

View File

@ -8,7 +8,7 @@ import org.bitcoins.core.protocol.tlv._
import org.bitcoins.dlc.oracle._
import org.bitcoins.dlc.oracle.config.DLCOracleAppConfig
import org.bitcoins.keymanager.WalletStorage
import org.bitcoins.server._
import org.bitcoins.server.routes.{Server, ServerCommand, ServerRoute}
import ujson._
import scala.util.{Failure, Success}

View File

@ -1,7 +1,7 @@
package org.bitcoins.oracle.server
import org.bitcoins.dlc.oracle.config.DLCOracleAppConfig
import org.bitcoins.server.{BitcoinSRunner, Server}
import org.bitcoins.server.routes.{BitcoinSRunner, Server}
import scala.concurrent.Future

View File

@ -0,0 +1,329 @@
package org.bitcoins.oracle.server
import org.bitcoins.commons.jsonmodels.bitcoind.RpcOpts.LockUnspentOutputParameter
import org.bitcoins.core.api.wallet.CoinSelectionAlgo
import org.bitcoins.core.protocol.BitcoinAddress
import org.bitcoins.core.protocol.tlv._
import org.bitcoins.core.protocol.transaction.{Transaction, TransactionOutPoint}
import org.bitcoins.core.psbt.PSBT
import org.bitcoins.crypto.AesPassword
import ujson._
import java.time.Instant
import scala.util.{Failure, Try}
case class CreateEvent(
label: String,
maturationTime: Instant,
outcomes: Vector[String])
object CreateEvent extends ServerJsonModels {
def fromJsArr(jsArr: ujson.Arr): Try[CreateEvent] = {
jsArr.arr.toList match {
case labelJs :: maturationTimeJs :: outcomesJs :: Nil =>
Try {
val label = labelJs.str
val maturationTime: Instant =
Instant.ofEpochSecond(maturationTimeJs.num.toLong)
val outcomes = outcomesJs.arr.map(_.str).toVector
CreateEvent(label, maturationTime, outcomes)
}
case Nil =>
Failure(
new IllegalArgumentException("Missing label and outcome arguments"))
case other =>
Failure(
new IllegalArgumentException(
s"Bad number of arguments: ${other.length}. Expected: 2"))
}
}
}
case class CreateRangedEvent(
eventName: String,
maturationTime: Instant,
start: Int,
stop: Int,
step: Int,
unit: String,
precision: Int)
object CreateRangedEvent extends ServerJsonModels {
def fromJsArr(jsArr: ujson.Arr): Try[CreateRangedEvent] = {
jsArr.arr.toList match {
case labelJs :: maturationTimeJs :: startJs :: stopJs :: stepJs :: unitJs :: precisionJs :: Nil =>
Try {
val label = labelJs.str
val maturationTime: Instant =
Instant.ofEpochSecond(maturationTimeJs.num.toLong)
val start = startJs.num.toInt
val stop = stopJs.num.toInt
val step = stepJs.num.toInt
val unit = unitJs.str
val precision = precisionJs.num.toInt
CreateRangedEvent(label,
maturationTime,
start,
stop,
step,
unit,
precision)
}
case Nil =>
Failure(
new IllegalArgumentException(
"Missing label, maturationTime, start, stop, and step arguments"))
case other =>
Failure(
new IllegalArgumentException(
s"Bad number of arguments: ${other.length}. Expected: 5"))
}
}
}
case class CreateDigitDecompEvent(
eventName: String,
maturationTime: Instant,
base: Int,
isSigned: Boolean,
numDigits: Int,
unit: String,
precision: Int)
object CreateDigitDecompEvent extends ServerJsonModels {
def fromJsArr(jsArr: ujson.Arr): Try[CreateDigitDecompEvent] = {
jsArr.arr.toList match {
case labelJs :: maturationTimeJs :: baseJs :: isSignedJs :: numDigitsJs :: unitJs :: precisionJs :: Nil =>
Try {
val label = labelJs.str
val maturationTime: Instant =
Instant.ofEpochSecond(maturationTimeJs.num.toLong)
val base = baseJs.num.toInt
val isSigned = isSignedJs.bool
val numDigits = numDigitsJs.num.toInt
val unit = unitJs.str
val precision = precisionJs.num.toInt
CreateDigitDecompEvent(label,
maturationTime,
base,
isSigned,
numDigits,
unit,
precision)
}
case Nil =>
Failure(new IllegalArgumentException(
"Missing label, maturationTime, base, isSigned, and numDigits arguments"))
case other =>
Failure(
new IllegalArgumentException(
s"Bad number of arguments: ${other.length}. Expected: 5"))
}
}
}
case class SignEvent(oracleEventTLV: OracleEventV0TLV, outcome: String)
object SignEvent extends ServerJsonModels {
def fromJsArr(jsArr: ujson.Arr): Try[SignEvent] = {
jsArr.arr.toList match {
case tlvJs :: outcomeJs :: Nil =>
Try {
val oracleEventTLV = OracleEventV0TLV(tlvJs.str)
val outcome = outcomeJs.str
SignEvent(oracleEventTLV, outcome)
}
case Nil =>
Failure(
new IllegalArgumentException(
"Missing oracle event tlv and outcome arguments"))
case other =>
Failure(
new IllegalArgumentException(
s"Bad number of arguments: ${other.length}. Expected: 2"))
}
}
}
case class SignForRange(oracleEventTLV: OracleEventV0TLV, num: Long)
object SignForRange extends ServerJsonModels {
def fromJsArr(jsArr: ujson.Arr): Try[SignForRange] = {
jsArr.arr.toList match {
case tlvJs :: numJs :: Nil =>
Try {
val oracleEventTLV = OracleEventV0TLV(tlvJs.str)
val num = numJs match {
case num: Num => num.value
case str: Str => str.value.toDouble
case _: Value =>
throw new IllegalArgumentException(
s"Unable to parse $numJs as a number")
}
SignForRange(oracleEventTLV, num.toLong)
}
case Nil =>
Failure(
new IllegalArgumentException(
"Missing oracle event tlv and num arguments"))
case other =>
Failure(
new IllegalArgumentException(
s"Bad number of arguments: ${other.length}. Expected: 2"))
}
}
}
case class SignDigits(oracleEventTLV: OracleEventV0TLV, num: Long)
object SignDigits extends ServerJsonModels {
def fromJsArr(jsArr: ujson.Arr): Try[SignDigits] = {
jsArr.arr.toList match {
case tlvJs :: numJs :: Nil =>
Try {
val oracleEventTLV = OracleEventV0TLV(tlvJs.str)
val num = numJs match {
case num: Num => num.value
case str: Str => str.value.toDouble
case _: Value =>
throw new IllegalArgumentException(
s"Unable to parse $numJs as a number")
}
SignDigits(oracleEventTLV, num.toLong)
}
case Nil =>
Failure(
new IllegalArgumentException(
"Missing oracle event tlv and num arguments"))
case other =>
Failure(
new IllegalArgumentException(
s"Bad number of arguments: ${other.length}. Expected: 2"))
}
}
}
case class GetEvent(oracleEventTLV: OracleEventV0TLV)
object GetEvent extends ServerJsonModels {
def fromJsArr(jsArr: ujson.Arr): Try[GetEvent] = {
require(jsArr.arr.size == 1,
s"Bad number of arguments: ${jsArr.arr.size}. Expected: 1")
Try {
val oracleEventTLV = OracleEventV0TLV(jsArr.arr.head.str)
GetEvent(oracleEventTLV)
}
}
}
case class KeyManagerPassphraseChange(
oldPassword: AesPassword,
newPassword: AesPassword)
object KeyManagerPassphraseChange extends ServerJsonModels {
def fromJsArr(jsArr: ujson.Arr): Try[KeyManagerPassphraseChange] = {
jsArr.arr.toList match {
case oldPassJs :: newPassJs :: Nil =>
Try {
val oldPass = AesPassword.fromString(oldPassJs.str)
val newPass = AesPassword.fromString(newPassJs.str)
KeyManagerPassphraseChange(oldPass, newPass)
}
case Nil =>
Failure(
new IllegalArgumentException(
"Missing old password and new password arguments"))
case other =>
Failure(
new IllegalArgumentException(
s"Bad number of arguments: ${other.length}. Expected: 2"))
}
}
}
case class KeyManagerPassphraseSet(password: AesPassword)
object KeyManagerPassphraseSet extends ServerJsonModels {
def fromJsArr(jsArr: ujson.Arr): Try[KeyManagerPassphraseSet] = {
jsArr.arr.toList match {
case passJs :: Nil =>
Try {
val pass = AesPassword.fromString(passJs.str)
KeyManagerPassphraseSet(pass)
}
case Nil =>
Failure(new IllegalArgumentException("Missing password argument"))
case other =>
Failure(
new IllegalArgumentException(
s"Bad number of arguments: ${other.length}. Expected: 1"))
}
}
}
trait ServerJsonModels {
def jsToBitcoinAddress(js: Value): BitcoinAddress = {
try {
BitcoinAddress.fromString(js.str)
} catch {
case _: IllegalArgumentException =>
throw Value.InvalidData(js, "Expected a valid address")
}
}
def jsToPSBTSeq(js: Value): Seq[PSBT] = {
js.arr.foldLeft(Seq.empty[PSBT])((seq, psbt) => seq :+ jsToPSBT(psbt))
}
def jsToPSBT(js: Value): PSBT = PSBT.fromString(js.str)
def jsToTransactionOutPointSeq(js: Value): Seq[TransactionOutPoint] = {
js.arr.foldLeft(Seq.empty[TransactionOutPoint])((seq, outPoint) =>
seq :+ jsToTransactionOutPoint(outPoint))
}
def jsToTransactionOutPoint(js: Value): TransactionOutPoint =
TransactionOutPoint(js.str)
def jsToLockUnspentOutputParameter(js: Value): LockUnspentOutputParameter =
LockUnspentOutputParameter.fromJson(js)
def jsToLockUnspentOutputParameters(
js: Value): Seq[LockUnspentOutputParameter] = {
js.arr.foldLeft(Seq.empty[LockUnspentOutputParameter])((seq, outPoint) =>
seq :+ jsToLockUnspentOutputParameter(outPoint))
}
def jsToCoinSelectionAlgo(js: Value): CoinSelectionAlgo =
CoinSelectionAlgo
.fromString(js.str)
def jsToTx(js: Value): Transaction = Transaction.fromHex(js.str)
def nullToOpt(value: Value): Option[Value] =
value match {
case Null => None
case Arr(arr) if arr.isEmpty => None
case Arr(arr) if arr.size == 1 => Some(arr.head)
case _: Value => Some(value)
}
}

View File

@ -1,4 +1,4 @@
package org.bitcoins.server
package org.bitcoins.server.routes
import akka.actor.ActorSystem
import com.typesafe.config.{Config, ConfigFactory}

View File

@ -1,4 +1,4 @@
package org.bitcoins.server
package org.bitcoins.server.routes
/** HTTP errors our server knows how to handle.
* These gets picked up by the exceptions handler

View File

@ -1,4 +1,4 @@
package org.bitcoins.server
package org.bitcoins.server.routes
import grizzled.slf4j.Logging

View File

@ -1,4 +1,4 @@
package org.bitcoins.server
package org.bitcoins.server.routes
import akka.actor.ActorSystem
import akka.event.Logging
@ -59,7 +59,7 @@ case class Server(
}
}
val route =
val route: Route =
// TODO implement better logging
DebuggingDirectives.logRequestResult("http-rpc-server", Logging.InfoLevel) {
withErrorHandling {

View File

@ -0,0 +1,26 @@
package org.bitcoins.server.routes
import ujson._
import upickle.default._
// TODO ID?
case class ServerCommand(method: String, params: ujson.Arr)
object ServerCommand {
implicit val rw: ReadWriter[ServerCommand] =
readwriter[ujson.Value].bimap[ServerCommand](
cmd => {
if (cmd.params.arr.isEmpty)
Obj("method" -> Str(cmd.method))
else Obj("method" -> Str(cmd.method), "params" -> cmd.params)
},
json => {
val obj = json.obj
val method = obj("method").str
if (obj.contains("params"))
ServerCommand(method, obj("params").arr)
else ServerCommand(method, Arr())
}
)
}

View File

@ -1,4 +1,4 @@
package org.bitcoins.server
package org.bitcoins.server.routes
import akka.http.scaladsl.server.StandardRoute

View File

@ -35,6 +35,7 @@ import org.bitcoins.crypto.{
}
import org.bitcoins.node.Node
import org.bitcoins.server.BitcoinSAppConfig.implicitToWalletConf
import org.bitcoins.server.routes.ServerCommand
import org.bitcoins.testkit.BitcoinSTestAppConfig
import org.bitcoins.wallet.MockWalletApi
import org.scalamock.scalatest.MockFactory

View File

@ -3,6 +3,7 @@ package org.bitcoins.server
import akka.actor.ActorSystem
import akka.dispatch.Dispatchers
import akka.http.scaladsl.Http
import grizzled.slf4j.Logging
import org.bitcoins.chain.blockchain.ChainHandler
import org.bitcoins.chain.config.ChainAppConfig
import org.bitcoins.chain.models._
@ -18,13 +19,15 @@ import org.bitcoins.feeprovider._
import org.bitcoins.node._
import org.bitcoins.node.config.NodeAppConfig
import org.bitcoins.node.models.Peer
import org.bitcoins.server.routes.{BitcoinSRunner, Server}
import org.bitcoins.wallet.Wallet
import org.bitcoins.wallet.config.WalletAppConfig
import scala.concurrent.{ExecutionContext, Future, Promise}
class BitcoinSServerMain(override val args: Array[String])
extends BitcoinSRunner {
extends BitcoinSRunner
with Logging {
override val actorSystemName = "bitcoin-s-server"
@ -288,26 +291,24 @@ class BitcoinSServerMain(override val args: Array[String])
val server = {
rpcPortOpt match {
case Some(rpcport) =>
Server.apply(conf = nodeConf,
handlers =
Seq(walletRoutes, nodeRoutes, chainRoutes, coreRoutes),
rpcbindOpt = rpcbindOpt,
rpcport = rpcport)
Server(conf = nodeConf,
handlers =
Seq(walletRoutes, nodeRoutes, chainRoutes, coreRoutes),
rpcbindOpt = rpcbindOpt,
rpcport = rpcport)
case None =>
conf.rpcPortOpt match {
case Some(rpcport) =>
Server.apply(
conf = nodeConf,
handlers =
Seq(walletRoutes, nodeRoutes, chainRoutes, coreRoutes),
rpcbindOpt = rpcbindOpt,
rpcport = rpcport)
Server(conf = nodeConf,
handlers =
Seq(walletRoutes, nodeRoutes, chainRoutes, coreRoutes),
rpcbindOpt = rpcbindOpt,
rpcport = rpcport)
case None =>
Server.apply(
conf = nodeConf,
handlers =
Seq(walletRoutes, nodeRoutes, chainRoutes, coreRoutes),
rpcbindOpt = rpcbindOpt)
Server(conf = nodeConf,
handlers =
Seq(walletRoutes, nodeRoutes, chainRoutes, coreRoutes),
rpcbindOpt = rpcbindOpt)
}
}
}

View File

@ -7,6 +7,7 @@ import org.bitcoins.commons.jsonmodels.BitcoinSServerInfo
import org.bitcoins.commons.serializers.Picklers._
import org.bitcoins.core.api.chain.ChainApi
import org.bitcoins.core.config.BitcoinNetwork
import org.bitcoins.server.routes.{Server, ServerCommand, ServerRoute}
import scodec.bits.ByteVector
import ujson._

View File

@ -5,6 +5,7 @@ import akka.http.scaladsl.server.Directives._
import akka.http.scaladsl.server._
import org.bitcoins.commons.jsonmodels.{SerializedPSBT, SerializedTransaction}
import org.bitcoins.core.api.core.CoreApi
import org.bitcoins.server.routes.{Server, ServerCommand, ServerRoute}
import ujson._
import scala.collection.mutable

View File

@ -7,6 +7,7 @@ import org.bitcoins.commons.serializers.Picklers._
import org.bitcoins.core.api.node.NodeApi
import org.bitcoins.node.Node
import org.bitcoins.rpc.client.common.BitcoindRpcClient
import org.bitcoins.server.routes.{Server, ServerCommand, ServerRoute}
import scala.concurrent.duration.DurationInt
import scala.util.{Failure, Success}

View File

@ -1,12 +1,10 @@
package org.bitcoins.server
import java.time.Instant
import org.bitcoins.commons.jsonmodels.bitcoind.RpcOpts.LockUnspentOutputParameter
import org.bitcoins.core.api.wallet.CoinSelectionAlgo
import org.bitcoins.core.crypto._
import org.bitcoins.core.currency.{Bitcoins, Satoshis}
import org.bitcoins.core.protocol.BlockStamp.BlockHeight
import org.bitcoins.core.protocol.tlv._
import org.bitcoins.core.protocol.transaction.{Transaction, TransactionOutPoint}
import org.bitcoins.core.protocol.{BitcoinAddress, BlockStamp}
import org.bitcoins.core.psbt.PSBT
@ -14,32 +12,9 @@ import org.bitcoins.core.wallet.fee.SatoshisPerVirtualByte
import org.bitcoins.core.wallet.utxo.AddressLabelTag
import org.bitcoins.crypto.{AesPassword, DoubleSha256DigestBE}
import ujson._
import upickle.default._
import scala.util.{Failure, Try}
// TODO ID?
case class ServerCommand(method: String, params: ujson.Arr)
object ServerCommand {
implicit val rw: ReadWriter[ServerCommand] =
readwriter[ujson.Value].bimap[ServerCommand](
cmd => {
if (cmd.params.arr.isEmpty)
Obj("method" -> Str(cmd.method))
else Obj("method" -> Str(cmd.method), "params" -> cmd.params)
},
json => {
val obj = json.obj
val method = obj("method").str
if (obj.contains("params"))
ServerCommand(method, obj("params").arr)
else ServerCommand(method, Arr())
}
)
}
case class GetNewAddress(labelOpt: Option[AddressLabelTag])
object GetNewAddress extends ServerJsonModels {
@ -741,226 +716,6 @@ object BumpFee extends ServerJsonModels {
}
}
// Oracle Models
case class CreateEvent(
label: String,
maturationTime: Instant,
outcomes: Vector[String])
object CreateEvent extends ServerJsonModels {
def fromJsArr(jsArr: ujson.Arr): Try[CreateEvent] = {
jsArr.arr.toList match {
case labelJs :: maturationTimeJs :: outcomesJs :: Nil =>
Try {
val label = labelJs.str
val maturationTime: Instant =
Instant.ofEpochSecond(maturationTimeJs.num.toLong)
val outcomes = outcomesJs.arr.map(_.str).toVector
CreateEvent(label, maturationTime, outcomes)
}
case Nil =>
Failure(
new IllegalArgumentException("Missing label and outcome arguments"))
case other =>
Failure(
new IllegalArgumentException(
s"Bad number of arguments: ${other.length}. Expected: 2"))
}
}
}
case class CreateRangedEvent(
eventName: String,
maturationTime: Instant,
start: Int,
stop: Int,
step: Int,
unit: String,
precision: Int)
object CreateRangedEvent extends ServerJsonModels {
def fromJsArr(jsArr: ujson.Arr): Try[CreateRangedEvent] = {
jsArr.arr.toList match {
case labelJs :: maturationTimeJs :: startJs :: stopJs :: stepJs :: unitJs :: precisionJs :: Nil =>
Try {
val label = labelJs.str
val maturationTime: Instant =
Instant.ofEpochSecond(maturationTimeJs.num.toLong)
val start = startJs.num.toInt
val stop = stopJs.num.toInt
val step = stepJs.num.toInt
val unit = unitJs.str
val precision = precisionJs.num.toInt
CreateRangedEvent(label,
maturationTime,
start,
stop,
step,
unit,
precision)
}
case Nil =>
Failure(
new IllegalArgumentException(
"Missing label, maturationTime, start, stop, and step arguments"))
case other =>
Failure(
new IllegalArgumentException(
s"Bad number of arguments: ${other.length}. Expected: 5"))
}
}
}
case class CreateDigitDecompEvent(
eventName: String,
maturationTime: Instant,
base: Int,
isSigned: Boolean,
numDigits: Int,
unit: String,
precision: Int)
object CreateDigitDecompEvent extends ServerJsonModels {
def fromJsArr(jsArr: ujson.Arr): Try[CreateDigitDecompEvent] = {
jsArr.arr.toList match {
case labelJs :: maturationTimeJs :: baseJs :: isSignedJs :: numDigitsJs :: unitJs :: precisionJs :: Nil =>
Try {
val label = labelJs.str
val maturationTime: Instant =
Instant.ofEpochSecond(maturationTimeJs.num.toLong)
val base = baseJs.num.toInt
val isSigned = isSignedJs.bool
val numDigits = numDigitsJs.num.toInt
val unit = unitJs.str
val precision = precisionJs.num.toInt
CreateDigitDecompEvent(label,
maturationTime,
base,
isSigned,
numDigits,
unit,
precision)
}
case Nil =>
Failure(new IllegalArgumentException(
"Missing label, maturationTime, base, isSigned, and numDigits arguments"))
case other =>
Failure(
new IllegalArgumentException(
s"Bad number of arguments: ${other.length}. Expected: 5"))
}
}
}
case class SignEvent(oracleEventTLV: OracleEventV0TLV, outcome: String)
object SignEvent extends ServerJsonModels {
def fromJsArr(jsArr: ujson.Arr): Try[SignEvent] = {
jsArr.arr.toList match {
case tlvJs :: outcomeJs :: Nil =>
Try {
val oracleEventTLV = OracleEventV0TLV(tlvJs.str)
val outcome = outcomeJs.str
SignEvent(oracleEventTLV, outcome)
}
case Nil =>
Failure(
new IllegalArgumentException(
"Missing oracle event tlv and outcome arguments"))
case other =>
Failure(
new IllegalArgumentException(
s"Bad number of arguments: ${other.length}. Expected: 2"))
}
}
}
case class SignForRange(oracleEventTLV: OracleEventV0TLV, num: Long)
object SignForRange extends ServerJsonModels {
def fromJsArr(jsArr: ujson.Arr): Try[SignForRange] = {
jsArr.arr.toList match {
case tlvJs :: numJs :: Nil =>
Try {
val oracleEventTLV = OracleEventV0TLV(tlvJs.str)
val num = numJs match {
case num: Num => num.value
case str: Str => str.value.toDouble
case _: Value =>
throw new IllegalArgumentException(
s"Unable to parse $numJs as a number")
}
SignForRange(oracleEventTLV, num.toLong)
}
case Nil =>
Failure(
new IllegalArgumentException(
"Missing oracle event tlv and num arguments"))
case other =>
Failure(
new IllegalArgumentException(
s"Bad number of arguments: ${other.length}. Expected: 2"))
}
}
}
case class SignDigits(oracleEventTLV: OracleEventV0TLV, num: Long)
object SignDigits extends ServerJsonModels {
def fromJsArr(jsArr: ujson.Arr): Try[SignDigits] = {
jsArr.arr.toList match {
case tlvJs :: numJs :: Nil =>
Try {
val oracleEventTLV = OracleEventV0TLV(tlvJs.str)
val num = numJs match {
case num: Num => num.value
case str: Str => str.value.toDouble
case _: Value =>
throw new IllegalArgumentException(
s"Unable to parse $numJs as a number")
}
SignDigits(oracleEventTLV, num.toLong)
}
case Nil =>
Failure(
new IllegalArgumentException(
"Missing oracle event tlv and num arguments"))
case other =>
Failure(
new IllegalArgumentException(
s"Bad number of arguments: ${other.length}. Expected: 2"))
}
}
}
case class GetEvent(oracleEventTLV: OracleEventV0TLV)
object GetEvent extends ServerJsonModels {
def fromJsArr(jsArr: ujson.Arr): Try[GetEvent] = {
require(jsArr.arr.size == 1,
s"Bad number of arguments: ${jsArr.arr.size}. Expected: 1")
Try {
val oracleEventTLV = OracleEventV0TLV(jsArr.arr.head.str)
GetEvent(oracleEventTLV)
}
}
}
trait ServerJsonModels {
def jsToBitcoinAddress(js: Value): BitcoinAddress = {

View File

@ -12,6 +12,7 @@ import org.bitcoins.core.wallet.utxo.{AddressLabelTagType, TxoState}
import org.bitcoins.crypto.NetworkElement
import org.bitcoins.keymanager._
import org.bitcoins.keymanager.config.KeyManagerAppConfig
import org.bitcoins.server.routes.{Server, ServerCommand, ServerRoute}
import org.bitcoins.wallet.config.WalletAppConfig
import ujson._

View File

@ -80,7 +80,8 @@ lazy val `bitcoin-s` = project
appCommonsTest,
testkit,
zmq,
oracleServer
oracleServer,
serverRoutes
)
.dependsOn(
secp256k1jni,
@ -117,7 +118,8 @@ lazy val `bitcoin-s` = project
appCommonsTest,
testkit,
zmq,
oracleServer
oracleServer,
serverRoutes
)
.settings(CommonSettings.settings: _*)
// unidoc aggregates Scaladocs for all subprojects into one big doc
@ -281,13 +283,20 @@ lazy val oracleServer = project
.settings(CommonSettings.prodSettings: _*)
.dependsOn(
dlcOracle,
appServer
serverRoutes
)
lazy val serverRoutes = project
.in(file("app/server-routes"))
.settings(CommonSettings.prodSettings: _*)
.settings(libraryDependencies ++= Deps.serverRoutes)
.dependsOn(appCommons, dbCommons)
lazy val appServer = project
.in(file("app/server"))
.settings(CommonSettings.prodSettings: _*)
.dependsOn(
serverRoutes,
appCommons,
node,
chain,

View File

@ -430,4 +430,11 @@ object Deps {
Compile.newMicroJson,
Compile.logback
)
val serverRoutes = List(
Compile.akkaHttp,
Compile.akkaActor,
Compile.akkaSlf4j,
Compile.akkaStream
)
}