mirror of
https://github.com/ACINQ/eclair.git
synced 2025-02-24 14:50:46 +01:00
[WIP] port to new service more 'calls'
This commit is contained in:
parent
134ceeb65b
commit
2635e1dd0a
3 changed files with 147 additions and 70 deletions
|
@ -285,7 +285,7 @@ class Setup(datadir: File,
|
|||
|
||||
// override val socketHandler = makeSocketHandler(system)(materializer)
|
||||
}
|
||||
val httpBound = Http().bindAndHandle(api.motherRoute, config.getString("api.binding-ip"), config.getInt("api.port")).recover {
|
||||
val httpBound = Http().bindAndHandle(api.route, config.getString("api.binding-ip"), config.getInt("api.port")).recover {
|
||||
case _: BindFailedException => throw TCPBindException(config.getInt("api.port"))
|
||||
}
|
||||
val httpTimeout = after(5 seconds, using = system.scheduler)(Future.failed(TCPBindException(config.getInt("api.port"))))
|
||||
|
|
|
@ -30,7 +30,7 @@ import fr.acinq.eclair.transactions.Transactions.{InputInfo, TransactionWithInpu
|
|||
import fr.acinq.eclair.wire._
|
||||
import fr.acinq.eclair.{ShortChannelId, UInt64}
|
||||
import org.json4s.JsonAST._
|
||||
import org.json4s.{CustomKeySerializer, CustomSerializer}
|
||||
import org.json4s.{CustomKeySerializer, CustomSerializer, jackson}
|
||||
|
||||
/**
|
||||
* JSON Serializers.
|
||||
|
@ -144,3 +144,34 @@ class PaymentRequestSerializer extends CustomSerializer[PaymentRequest](format =
|
|||
JField("minFinalCltvExpiry", if (p.minFinalCltvExpiry.isDefined) JLong(p.minFinalCltvExpiry.get) else JNull) ::
|
||||
Nil)
|
||||
}))
|
||||
|
||||
trait WithJsonSerializers {
|
||||
|
||||
implicit val serialization = jackson.Serialization
|
||||
|
||||
implicit val formats = org.json4s.DefaultFormats +
|
||||
new BinaryDataSerializer +
|
||||
new UInt64Serializer +
|
||||
new MilliSatoshiSerializer +
|
||||
new ShortChannelIdSerializer +
|
||||
new StateSerializer +
|
||||
new ShaChainSerializer +
|
||||
new PublicKeySerializer +
|
||||
new PrivateKeySerializer +
|
||||
new ScalarSerializer +
|
||||
new PointSerializer +
|
||||
new TransactionSerializer +
|
||||
new TransactionWithInputInfoSerializer +
|
||||
new InetSocketAddressSerializer +
|
||||
new OutPointSerializer +
|
||||
new OutPointKeySerializer +
|
||||
new InputInfoSerializer +
|
||||
new ColorSerializer +
|
||||
new RouteResponseSerializer +
|
||||
new ThrowableSerializer +
|
||||
new FailureMessageSerializer +
|
||||
new NodeAddressSerializer +
|
||||
new DirectionSerializer +
|
||||
new PaymentRequestSerializer
|
||||
|
||||
}
|
|
@ -8,101 +8,112 @@ import fr.acinq.bitcoin.Crypto.PublicKey
|
|||
import fr.acinq.bitcoin.{BinaryData, MilliSatoshi, Satoshi}
|
||||
import fr.acinq.eclair.{Kit, ShortChannelId}
|
||||
import fr.acinq.eclair.io.{NodeURI, Peer}
|
||||
import org.json4s.jackson
|
||||
import Marshallers._
|
||||
import de.heikoseeberger.akkahttpjson4s.Json4sSupport
|
||||
import fr.acinq.eclair.channel.{CMD_CLOSE, Register}
|
||||
import akka.actor.ActorRef
|
||||
import fr.acinq.eclair.channel._
|
||||
import fr.acinq.eclair.io.Peer.{GetPeerInfo, PeerInfo}
|
||||
import fr.acinq.eclair.wire.NodeAddress
|
||||
import scala.concurrent.{ExecutionContext, Future}
|
||||
import scala.concurrent.duration._
|
||||
|
||||
trait NewService {
|
||||
trait NewService extends WithJsonSerializers {
|
||||
|
||||
def appKit: Kit
|
||||
|
||||
def getInfoResponse: Future[GetInfoResponse]
|
||||
|
||||
implicit val ec = appKit.system.dispatcher
|
||||
|
||||
implicit val serialization = jackson.Serialization
|
||||
implicit val formats = org.json4s.DefaultFormats +
|
||||
new BinaryDataSerializer +
|
||||
new UInt64Serializer +
|
||||
new MilliSatoshiSerializer +
|
||||
new ShortChannelIdSerializer +
|
||||
new StateSerializer +
|
||||
new ShaChainSerializer +
|
||||
new PublicKeySerializer +
|
||||
new PrivateKeySerializer +
|
||||
new ScalarSerializer +
|
||||
new PointSerializer +
|
||||
new TransactionSerializer +
|
||||
new TransactionWithInputInfoSerializer +
|
||||
new InetSocketAddressSerializer +
|
||||
new OutPointSerializer +
|
||||
new OutPointKeySerializer +
|
||||
new InputInfoSerializer +
|
||||
new ColorSerializer +
|
||||
new RouteResponseSerializer +
|
||||
new ThrowableSerializer +
|
||||
new FailureMessageSerializer +
|
||||
new NodeAddressSerializer +
|
||||
new DirectionSerializer +
|
||||
new PaymentRequestSerializer
|
||||
|
||||
implicit val timeout = Timeout(60 seconds)
|
||||
implicit val shouldWritePretty: ShouldWritePretty = ShouldWritePretty.True
|
||||
import Json4sSupport.{marshaller, unmarshaller}
|
||||
|
||||
val connectRoute: Route = path("connect") {
|
||||
parameters("nodeId".as[PublicKey], "address".as[NodeAddress]) { (nodeId, addr) =>
|
||||
connect(s"$nodeId@$addr")
|
||||
} ~ parameters("uri") { uri =>
|
||||
connect(uri)
|
||||
}
|
||||
}
|
||||
val channelIdNamedParameter = "channelId".as[PublicKey]
|
||||
|
||||
val openRoute: Route = path("open") {
|
||||
parameters("nodeId".as[PublicKey], "fundingSatoshis".as[Long], "pushMsat".as[Long].?, "fundingFeerateSatByte".as[Long].?, "channelFlags".as[Int].?) {
|
||||
(nodeId, fundingSatoshis, pushMsat, fundingFeerateSatByte, channelFlags) =>
|
||||
open(nodeId, fundingSatoshis, pushMsat, fundingFeerateSatByte, channelFlags)
|
||||
}
|
||||
}
|
||||
|
||||
val closeRoute: Route = path("close") {
|
||||
parameters("channelId".as[BinaryData](sha256HashUnmarshaller), "scriptPubKey".as[BinaryData](binaryDataUnmarshaller).?) { (channelId: BinaryData, scriptPubKey_opt: Option[BinaryData]) =>
|
||||
close(channelId.toString(), scriptPubKey_opt)
|
||||
}
|
||||
}
|
||||
|
||||
val getInfoRoute: Route = path("getinfo") {
|
||||
complete(getInfoResponse)
|
||||
}
|
||||
|
||||
val motherRoute: Route = {
|
||||
val route: Route = {
|
||||
get {
|
||||
connectRoute ~
|
||||
openRoute ~
|
||||
closeRoute ~
|
||||
getInfoRoute
|
||||
path("getinfo") {
|
||||
complete(getInfoResponse)
|
||||
} ~
|
||||
path("help") {
|
||||
complete(help.mkString)
|
||||
}
|
||||
path("connect") {
|
||||
parameters("nodeId".as[PublicKey], "address".as[NodeAddress]) { (nodeId, addr) =>
|
||||
complete(connect(s"$nodeId@$addr"))
|
||||
} ~ parameters("uri") { uri =>
|
||||
complete(connect(uri))
|
||||
}
|
||||
} ~
|
||||
path("open") {
|
||||
parameters("nodeId".as[PublicKey], "fundingSatoshis".as[Long], "pushMsat".as[Long].?, "fundingFeerateSatByte".as[Long].?, "channelFlags".as[Int].?) {
|
||||
(nodeId, fundingSatoshis, pushMsat, fundingFeerateSatByte, channelFlags) =>
|
||||
complete(open(nodeId, fundingSatoshis, pushMsat, fundingFeerateSatByte, channelFlags))
|
||||
}
|
||||
} ~
|
||||
path("close") {
|
||||
parameters(channelIdNamedParameter, "scriptPubKey".as[BinaryData](binaryDataUnmarshaller).?) { (channelId, scriptPubKey_opt) =>
|
||||
complete(close(channelId.toString(), scriptPubKey_opt))
|
||||
}
|
||||
} ~
|
||||
path("forceclose") {
|
||||
parameters(channelIdNamedParameter) { channelId =>
|
||||
complete(forceClose(channelId.toString))
|
||||
}
|
||||
} ~
|
||||
path("updaterelayfee") {
|
||||
parameters(channelIdNamedParameter, "feeBaseMsat".as[Long], "feeProportionalMillionths".as[Long]) { (channelId, feeBase, feeProportional) =>
|
||||
complete(updateRelayFee(channelId.toString, feeBase, feeProportional))
|
||||
}
|
||||
} ~
|
||||
path("peers") {
|
||||
complete(peersInfo())
|
||||
} ~
|
||||
path("channels") {
|
||||
parameters(channelIdNamedParameter.?) { channelId_opt =>
|
||||
complete(channels(channelId_opt))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
def connect(uri: String) : Route = {
|
||||
complete((appKit.switchboard ? Peer.Connect(NodeURI.parse(uri))).mapTo[String])
|
||||
def connect(uri: String): Future[String] = {
|
||||
(appKit.switchboard ? Peer.Connect(NodeURI.parse(uri))).mapTo[String]
|
||||
}
|
||||
|
||||
def open(nodeId: PublicKey, fundingSatoshis: Long, pushMsat: Option[Long], fundingFeerateSatByte: Option[Long], flags: Option[Int]): Route = {
|
||||
complete((appKit.switchboard ? Peer.OpenChannel(
|
||||
def open(nodeId: PublicKey, fundingSatoshis: Long, pushMsat: Option[Long], fundingFeerateSatByte: Option[Long], flags: Option[Int]): Future[String] = {
|
||||
(appKit.switchboard ? Peer.OpenChannel(
|
||||
remoteNodeId = nodeId,
|
||||
fundingSatoshis = Satoshi(fundingSatoshis),
|
||||
pushMsat = pushMsat.map(MilliSatoshi).getOrElse(MilliSatoshi(0)),
|
||||
fundingTxFeeratePerKw_opt = fundingFeerateSatByte,
|
||||
channelFlags = flags.map(_.toByte))).mapTo[String])
|
||||
channelFlags = flags.map(_.toByte))).mapTo[String]
|
||||
}
|
||||
|
||||
def close(channelId: String, scriptPubKey: Option[BinaryData]) = {
|
||||
complete(sendToChannel(channelId, CMD_CLOSE(scriptPubKey)).mapTo[String])
|
||||
def close(channelId: String, scriptPubKey: Option[BinaryData]): Future[String] = {
|
||||
sendToChannel(channelId, CMD_CLOSE(scriptPubKey)).mapTo[String]
|
||||
}
|
||||
|
||||
def forceClose(channelId: String): Future[String] = {
|
||||
sendToChannel(channelId, CMD_FORCECLOSE).mapTo[String]
|
||||
}
|
||||
|
||||
def updateRelayFee(channelId: String, feeBaseMsat: Long, feeProportionalMillionths: Long): Future[String] = {
|
||||
sendToChannel(channelId, CMD_UPDATE_RELAY_FEE(feeBaseMsat, feeProportionalMillionths)).mapTo[String]
|
||||
}
|
||||
|
||||
def peersInfo(): Future[Iterable[PeerInfo]] = for {
|
||||
peers <- (appKit.switchboard ? 'peers).mapTo[Iterable[ActorRef]]
|
||||
peerinfos <- Future.sequence(peers.map(peer => (peer ? GetPeerInfo).mapTo[PeerInfo]))
|
||||
} yield peerinfos
|
||||
|
||||
def channels(channelIdFilter: Option[PublicKey]): Future[Iterable[RES_GETINFO]] = channelIdFilter match {
|
||||
case Some(pk) => for {
|
||||
channelsId <- (appKit.register ? 'channelsTo).mapTo[Map[BinaryData, PublicKey]].map(_.filter(_._2 == pk).keys)
|
||||
channels <- Future.sequence(channelsId.map(channelId => sendToChannel(channelId.toString(), CMD_GETINFO).mapTo[RES_GETINFO]))
|
||||
} yield channels
|
||||
case None => for {
|
||||
channels_id <- (appKit.register ? 'channels).mapTo[Map[BinaryData, ActorRef]].map(_.keys)
|
||||
channels <- Future.sequence(channels_id.map(channel_id => sendToChannel(channel_id.toString(), CMD_GETINFO).mapTo[RES_GETINFO]))
|
||||
} yield channels
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -120,4 +131,39 @@ trait NewService {
|
|||
res <- appKit.register ? fwdReq
|
||||
} yield res
|
||||
|
||||
def help = List(
|
||||
"connect (uri): open a secure connection to a lightning node",
|
||||
"connect (nodeId, host, port): open a secure connection to a lightning node",
|
||||
"open (nodeId, fundingSatoshis, pushMsat = 0, feerateSatPerByte = ?, channelFlags = 0x01): open a channel with another lightning node, by default push = 0, feerate for the funding tx targets 6 blocks, and channel is announced",
|
||||
"updaterelayfee (channelId, feeBaseMsat, feeProportionalMillionths): update relay fee for payments going through this channel",
|
||||
"peers: list existing local peers",
|
||||
"channels: list existing local channels",
|
||||
"channels (nodeId): list existing local channels to a particular nodeId",
|
||||
"channel (channelId): retrieve detailed information about a given channel",
|
||||
"channelstats: retrieves statistics about channel usage (fees, number and average amount of payments)",
|
||||
"allnodes: list all known nodes",
|
||||
"allchannels: list all known channels",
|
||||
"allupdates: list all channels updates",
|
||||
"allupdates (nodeId): list all channels updates for this nodeId",
|
||||
"receive (amountMsat, description): generate a payment request for a given amount",
|
||||
"receive (amountMsat, description, expirySeconds): generate a payment request for a given amount with a description and a number of seconds till it expires",
|
||||
"parseinvoice (paymentRequest): returns node, amount and payment hash in a payment request",
|
||||
"findroute (paymentRequest): returns nodes and channels of the route if there is any",
|
||||
"findroute (paymentRequest, amountMsat): returns nodes and channels of the route if there is any",
|
||||
"findroute (nodeId, amountMsat): returns nodes and channels of the route if there is any",
|
||||
"send (amountMsat, paymentHash, nodeId): send a payment to a lightning node",
|
||||
"send (paymentRequest): send a payment to a lightning node using a BOLT11 payment request",
|
||||
"send (paymentRequest, amountMsat): send a payment to a lightning node using a BOLT11 payment request and a custom amount",
|
||||
"close (channelId): close a channel",
|
||||
"close (channelId, scriptPubKey): close a channel and send the funds to the given scriptPubKey",
|
||||
"forceclose (channelId): force-close a channel by publishing the local commitment tx (careful: this is more expensive than a regular close and will incur a delay before funds are spendable)",
|
||||
"checkpayment (paymentHash): returns true if the payment has been received, false otherwise",
|
||||
"checkpayment (paymentRequest): returns true if the payment has been received, false otherwise",
|
||||
"audit: list all send/received/relayed payments",
|
||||
"audit (from, to): list send/received/relayed payments in that interval (from <= timestamp < to)",
|
||||
"networkfees: list all network fees paid to the miners, by transaction",
|
||||
"networkfees (from, to): list network fees paid to the miners, by transaction, in that interval (from <= timestamp < to)",
|
||||
"getinfo: returns info about the blockchain and this node",
|
||||
"help: display this message")
|
||||
|
||||
}
|
Loading…
Add table
Reference in a new issue