mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2025-01-19 05:43:51 +01:00
offer-send
RPC (#4153)
* offer-send RPC * docs * change offet-send signature * change offer_send signature * add local address parameter * remove local address parameter * use temo contract id to send offers * respond to the PR comments
This commit is contained in:
parent
0bb0d9acdb
commit
56d0ae68ad
@ -104,5 +104,26 @@ case class DLCRoutes(dlcNode: DLCNodeApi)(implicit system: ActorSystem)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case ServerCommand("offer-send", arr) =>
|
||||||
|
withValidServerCommand(OfferSend.fromJsArr(arr)) {
|
||||||
|
case OfferSend(remoteAddress, message, offerE) =>
|
||||||
|
complete {
|
||||||
|
offerE match {
|
||||||
|
case Left(offerTLV) =>
|
||||||
|
dlcNode
|
||||||
|
.sendDLCOffer(remoteAddress, message, offerTLV)
|
||||||
|
.map { tempContractId =>
|
||||||
|
Server.httpSuccess(tempContractId.hex)
|
||||||
|
}
|
||||||
|
case Right(tempContractId) =>
|
||||||
|
dlcNode
|
||||||
|
.sendDLCOffer(remoteAddress, message, tempContractId)
|
||||||
|
.map { tempContractId =>
|
||||||
|
Server.httpSuccess(tempContractId.hex)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -15,6 +15,7 @@ import org.bitcoins.core.protocol.tlv._
|
|||||||
import org.bitcoins.core.protocol.transaction.{Transaction, TransactionOutPoint}
|
import org.bitcoins.core.protocol.transaction.{Transaction, TransactionOutPoint}
|
||||||
import org.bitcoins.core.protocol.{BitcoinAddress, BlockStamp}
|
import org.bitcoins.core.protocol.{BitcoinAddress, BlockStamp}
|
||||||
import org.bitcoins.core.psbt.PSBT
|
import org.bitcoins.core.psbt.PSBT
|
||||||
|
import org.bitcoins.core.util.NetworkUtil
|
||||||
import org.bitcoins.core.wallet.fee.SatoshisPerVirtualByte
|
import org.bitcoins.core.wallet.fee.SatoshisPerVirtualByte
|
||||||
import org.bitcoins.core.wallet.utxo.AddressLabelTag
|
import org.bitcoins.core.wallet.utxo.AddressLabelTag
|
||||||
import org.bitcoins.crypto._
|
import org.bitcoins.crypto._
|
||||||
@ -1384,7 +1385,7 @@ object OfferAdd {
|
|||||||
}
|
}
|
||||||
case other =>
|
case other =>
|
||||||
val exn = new IllegalArgumentException(
|
val exn = new IllegalArgumentException(
|
||||||
s"Bad number or arguments to registerincomingoffer, got=${other.length} expected=3")
|
s"Bad number or arguments to offer-add, got=${other.length} expected=3")
|
||||||
Failure(exn)
|
Failure(exn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1403,7 +1404,37 @@ object OfferRemove {
|
|||||||
}
|
}
|
||||||
case other =>
|
case other =>
|
||||||
val exn = new IllegalArgumentException(
|
val exn = new IllegalArgumentException(
|
||||||
s"Bad number or arguments to rejectincomingoffer, got=${other.length} expected=1")
|
s"Bad number or arguments to offer-remove, got=${other.length} expected=1")
|
||||||
|
Failure(exn)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
case class OfferSend(
|
||||||
|
remoteAddress: InetSocketAddress,
|
||||||
|
message: String,
|
||||||
|
offerE: Either[DLCOfferTLV, Sha256Digest])
|
||||||
|
|
||||||
|
object OfferSend {
|
||||||
|
|
||||||
|
def fromJsArr(arr: ujson.Arr): Try[OfferSend] = {
|
||||||
|
arr.arr.toList match {
|
||||||
|
case offerJs :: peerAddressJs :: messageJs :: Nil =>
|
||||||
|
Try {
|
||||||
|
val peerAddress =
|
||||||
|
NetworkUtil.parseInetSocketAddress(peerAddressJs.str, 2862)
|
||||||
|
val message = messageJs.str
|
||||||
|
val offerE =
|
||||||
|
Try(LnMessageFactory(DLCOfferTLV).fromHex(offerJs.str).tlv)
|
||||||
|
.orElse(Try(DLCOfferTLV.fromHex(offerJs.str))) match {
|
||||||
|
case Success(o) => Left(o)
|
||||||
|
case Failure(_) => Right(Sha256Digest.fromHex(offerJs.str))
|
||||||
|
}
|
||||||
|
OfferSend(peerAddress, message, offerE)
|
||||||
|
}
|
||||||
|
case other =>
|
||||||
|
val exn = new IllegalArgumentException(
|
||||||
|
s"Bad number or arguments to offer-send, got=${other.length} expected=3")
|
||||||
Failure(exn)
|
Failure(exn)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import org.bitcoins.core.protocol.BitcoinAddress
|
|||||||
import org.bitcoins.core.protocol.dlc.models.DLCMessage
|
import org.bitcoins.core.protocol.dlc.models.DLCMessage
|
||||||
import org.bitcoins.core.protocol.tlv._
|
import org.bitcoins.core.protocol.tlv._
|
||||||
import org.bitcoins.core.util.StartStopAsync
|
import org.bitcoins.core.util.StartStopAsync
|
||||||
|
import org.bitcoins.crypto.Sha256Digest
|
||||||
|
|
||||||
import java.net.InetSocketAddress
|
import java.net.InetSocketAddress
|
||||||
import scala.concurrent.Future
|
import scala.concurrent.Future
|
||||||
@ -20,5 +21,15 @@ trait DLCNodeApi extends StartStopAsync[Unit] {
|
|||||||
externalChangeAddress: Option[BitcoinAddress]): Future[
|
externalChangeAddress: Option[BitcoinAddress]): Future[
|
||||||
DLCMessage.DLCAccept]
|
DLCMessage.DLCAccept]
|
||||||
|
|
||||||
|
def sendDLCOffer(
|
||||||
|
peerAddress: InetSocketAddress,
|
||||||
|
message: String,
|
||||||
|
offerTLV: DLCOfferTLV): Future[Sha256Digest]
|
||||||
|
|
||||||
|
def sendDLCOffer(
|
||||||
|
peerAddress: InetSocketAddress,
|
||||||
|
message: String,
|
||||||
|
tempContractId: Sha256Digest): Future[Sha256Digest]
|
||||||
|
|
||||||
def getHostAddress: Future[InetSocketAddress]
|
def getHostAddress: Future[InetSocketAddress]
|
||||||
}
|
}
|
||||||
|
@ -112,8 +112,13 @@ trait DLCWalletApi { self: WalletApi =>
|
|||||||
|
|
||||||
def findDLC(dlcId: Sha256Digest): Future[Option[DLCStatus]]
|
def findDLC(dlcId: Sha256Digest): Future[Option[DLCStatus]]
|
||||||
|
|
||||||
|
def findDLCByTemporaryContractId(
|
||||||
|
tempContractId: Sha256Digest): Future[Option[DLCStatus]]
|
||||||
|
|
||||||
def cancelDLC(dlcId: Sha256Digest): Future[Unit]
|
def cancelDLC(dlcId: Sha256Digest): Future[Unit]
|
||||||
|
|
||||||
|
def getDLCOffer(dlcId: Sha256Digest): Future[Option[DLCOffer]]
|
||||||
|
|
||||||
/** Retrieves accounting and financial metrics for the entire dlc wallet */
|
/** Retrieves accounting and financial metrics for the entire dlc wallet */
|
||||||
def getWalletAccounting(): Future[DLCWalletAccounting]
|
def getWalletAccounting(): Future[DLCWalletAccounting]
|
||||||
|
|
||||||
@ -125,6 +130,9 @@ trait DLCWalletApi { self: WalletApi =>
|
|||||||
def listIncomingDLCOffers(): Future[Vector[IncomingDLCOfferDb]]
|
def listIncomingDLCOffers(): Future[Vector[IncomingDLCOfferDb]]
|
||||||
|
|
||||||
def rejectIncomingDLCOffer(offerHash: Sha256Digest): Future[Unit]
|
def rejectIncomingDLCOffer(offerHash: Sha256Digest): Future[Unit]
|
||||||
|
|
||||||
|
def findIncomingDLCOffer(
|
||||||
|
offerHash: Sha256Digest): Future[Option[IncomingDLCOfferDb]]
|
||||||
}
|
}
|
||||||
|
|
||||||
/** An HDWallet that supports DLCs and both Neutrino and SPV methods of syncing */
|
/** An HDWallet that supports DLCs and both Neutrino and SPV methods of syncing */
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
package org.bitcoins.core.api.dlc.wallet.db
|
package org.bitcoins.core.api.dlc.wallet.db
|
||||||
|
|
||||||
import org.bitcoins.core.protocol.tlv.DLCOfferTLV
|
import org.bitcoins.core.protocol.tlv.{DLCOfferTLV, LnMessage, SendOfferTLV}
|
||||||
import org.bitcoins.crypto.Sha256Digest
|
import org.bitcoins.crypto.Sha256Digest
|
||||||
|
|
||||||
import java.time.Instant
|
import java.time.Instant
|
||||||
@ -15,4 +15,15 @@ case class IncomingDLCOfferDb(
|
|||||||
"peer length must not exceed 1024 characters")
|
"peer length must not exceed 1024 characters")
|
||||||
require(message.forall(_.length <= 1024),
|
require(message.forall(_.length <= 1024),
|
||||||
"message length must not exceed 1024 characters")
|
"message length must not exceed 1024 characters")
|
||||||
|
|
||||||
|
def toTLV: SendOfferTLV = {
|
||||||
|
require(peer.nonEmpty)
|
||||||
|
require(message.nonEmpty)
|
||||||
|
SendOfferTLV(offer = offerTLV, message = message.get, peer = peer.get)
|
||||||
|
}
|
||||||
|
|
||||||
|
def toMessage: LnMessage[SendOfferTLV] = {
|
||||||
|
LnMessage(this.toTLV)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -174,7 +174,8 @@ object TLV extends TLVParentFactory[TLV] {
|
|||||||
FundingSignaturesV0TLV,
|
FundingSignaturesV0TLV,
|
||||||
DLCOfferTLV,
|
DLCOfferTLV,
|
||||||
DLCAcceptTLV,
|
DLCAcceptTLV,
|
||||||
DLCSignTLV
|
DLCSignTLV,
|
||||||
|
SendOfferTLV
|
||||||
) ++ EventDescriptorTLV.allFactories ++
|
) ++ EventDescriptorTLV.allFactories ++
|
||||||
PayoutCurvePieceTLV.allFactories ++
|
PayoutCurvePieceTLV.allFactories ++
|
||||||
ContractDescriptorTLV.allFactories ++
|
ContractDescriptorTLV.allFactories ++
|
||||||
@ -1687,6 +1688,38 @@ object FundingSignaturesV0TLV extends TLVFactory[FundingSignaturesV0TLV] {
|
|||||||
|
|
||||||
sealed trait DLCSetupTLV extends TLV
|
sealed trait DLCSetupTLV extends TLV
|
||||||
|
|
||||||
|
case class SendOfferTLV(
|
||||||
|
peer: NormalizedString,
|
||||||
|
message: NormalizedString,
|
||||||
|
offer: DLCOfferTLV)
|
||||||
|
extends DLCSetupTLV {
|
||||||
|
|
||||||
|
require(peer.length <= 1024, "peer length must not exceed 1024 characters")
|
||||||
|
require(message.length <= 1024,
|
||||||
|
"message length must not exceed 1024 characters")
|
||||||
|
|
||||||
|
override val tpe: BigSizeUInt = SendOfferTLV.tpe
|
||||||
|
|
||||||
|
override val value: ByteVector = {
|
||||||
|
strBytes(peer) ++ strBytes(message) ++ offer.bytes
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object SendOfferTLV extends TLVFactory[SendOfferTLV] {
|
||||||
|
|
||||||
|
override val tpe: BigSizeUInt = BigSizeUInt(65534)
|
||||||
|
|
||||||
|
override val typeName: String = "SendOfferTLV"
|
||||||
|
|
||||||
|
override def fromTLVValue(value: ByteVector): SendOfferTLV = {
|
||||||
|
val iter = ValueIterator(value)
|
||||||
|
val peer = iter.takeString()
|
||||||
|
val message = iter.takeString()
|
||||||
|
val offer = iter.take(DLCOfferTLV)
|
||||||
|
SendOfferTLV(peer, message, offer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
case class DLCOfferTLV(
|
case class DLCOfferTLV(
|
||||||
protocolVersionOpt: Option[Int],
|
protocolVersionOpt: Option[Int],
|
||||||
contractFlags: Byte,
|
contractFlags: Byte,
|
||||||
|
@ -3,6 +3,7 @@ package org.bitcoins.dlc.node
|
|||||||
import akka.actor.ActorRef
|
import akka.actor.ActorRef
|
||||||
import org.bitcoins.core.number.UInt32
|
import org.bitcoins.core.number.UInt32
|
||||||
import org.bitcoins.core.protocol.dlc.models.DLCState
|
import org.bitcoins.core.protocol.dlc.models.DLCState
|
||||||
|
import org.bitcoins.core.protocol.tlv.{LnMessage, SendOfferTLV}
|
||||||
import org.bitcoins.core.wallet.fee.SatoshisPerVirtualByte
|
import org.bitcoins.core.wallet.fee.SatoshisPerVirtualByte
|
||||||
import org.bitcoins.dlc.node.peer.Peer
|
import org.bitcoins.dlc.node.peer.Peer
|
||||||
import org.bitcoins.rpc.util.RpcUtil
|
import org.bitcoins.rpc.util.RpcUtil
|
||||||
@ -33,17 +34,13 @@ class DLCNegotiationTest extends BitcoinSDualWalletTest {
|
|||||||
val connectAddress =
|
val connectAddress =
|
||||||
InetSocketAddress.createUnresolved("127.0.0.1", port)
|
InetSocketAddress.createUnresolved("127.0.0.1", port)
|
||||||
|
|
||||||
val serverF = DLCServer.bind(walletA, bindAddress, None)
|
|
||||||
|
|
||||||
val handlerP = Promise[ActorRef]()
|
val handlerP = Promise[ActorRef]()
|
||||||
val clientF =
|
|
||||||
DLCClient.connect(Peer(connectAddress, socks5ProxyParams = None),
|
|
||||||
walletB,
|
|
||||||
Some(handlerP))
|
|
||||||
|
|
||||||
for {
|
for {
|
||||||
_ <- serverF
|
_ <- DLCServer.bind(walletA, bindAddress, None)
|
||||||
_ <- clientF
|
_ <- DLCClient.connect(Peer(connectAddress, socks5ProxyParams = None),
|
||||||
|
walletB,
|
||||||
|
Some(handlerP))
|
||||||
|
|
||||||
handler <- handlerP.future
|
handler <- handlerP.future
|
||||||
|
|
||||||
@ -79,4 +76,55 @@ class DLCNegotiationTest extends BitcoinSDualWalletTest {
|
|||||||
)
|
)
|
||||||
} yield succeed
|
} yield succeed
|
||||||
}
|
}
|
||||||
|
|
||||||
|
it must "receive an offer over" in {
|
||||||
|
fundedDLCWallets: (FundedDLCWallet, FundedDLCWallet) =>
|
||||||
|
val walletA = fundedDLCWallets._1.wallet
|
||||||
|
val walletB = fundedDLCWallets._2.wallet
|
||||||
|
val port = RpcUtil.randomPort
|
||||||
|
val bindAddress =
|
||||||
|
new InetSocketAddress("0.0.0.0", port)
|
||||||
|
val connectAddress =
|
||||||
|
InetSocketAddress.createUnresolved("127.0.0.1", port)
|
||||||
|
|
||||||
|
val handlerP = Promise[ActorRef]()
|
||||||
|
|
||||||
|
for {
|
||||||
|
_ <- DLCServer.bind(walletA, bindAddress, None)
|
||||||
|
_ <- DLCClient.connect(Peer(connectAddress, socks5ProxyParams = None),
|
||||||
|
walletB,
|
||||||
|
Some(handlerP))
|
||||||
|
|
||||||
|
handler <- handlerP.future
|
||||||
|
|
||||||
|
preA <- walletA.listIncomingDLCOffers()
|
||||||
|
preB <- walletA.listIncomingDLCOffers()
|
||||||
|
_ = assert(preA.isEmpty)
|
||||||
|
_ = assert(preB.isEmpty)
|
||||||
|
|
||||||
|
offer <- walletB.createDLCOffer(sampleContractInfo,
|
||||||
|
half,
|
||||||
|
Some(SatoshisPerVirtualByte.one),
|
||||||
|
UInt32.zero,
|
||||||
|
UInt32.one,
|
||||||
|
None,
|
||||||
|
None)
|
||||||
|
tlv = SendOfferTLV(peer = "peer", message = "msg", offer = offer.toTLV)
|
||||||
|
|
||||||
|
_ = handler ! DLCDataHandler.Send(LnMessage(tlv))
|
||||||
|
|
||||||
|
_ <- TestAsyncUtil.awaitConditionF { () =>
|
||||||
|
walletA.listIncomingDLCOffers().map(_.nonEmpty)
|
||||||
|
}
|
||||||
|
postA <- walletA.listIncomingDLCOffers()
|
||||||
|
postB <- walletB.listIncomingDLCOffers()
|
||||||
|
|
||||||
|
} yield {
|
||||||
|
assert(postA.nonEmpty)
|
||||||
|
assert(postB.isEmpty)
|
||||||
|
assert(postA.head.peer.get == "peer")
|
||||||
|
assert(postA.head.message.get == "msg")
|
||||||
|
assert(postA.head.offerTLV == offer.toTLV)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,6 +51,13 @@ class DLCDataHandler(dlcWalletApi: DLCWalletApi, connectionHandler: ActorRef)
|
|||||||
for {
|
for {
|
||||||
_ <- dlcWalletApi.registerIncomingDLCOffer(dlcOffer, None, None)
|
_ <- dlcWalletApi.registerIncomingDLCOffer(dlcOffer, None, None)
|
||||||
} yield ()
|
} yield ()
|
||||||
|
case dlcOfferMessage: SendOfferTLV =>
|
||||||
|
for {
|
||||||
|
_ <- dlcWalletApi.registerIncomingDLCOffer(
|
||||||
|
offerTLV = dlcOfferMessage.offer,
|
||||||
|
peer = Some(dlcOfferMessage.peer),
|
||||||
|
message = Some(dlcOfferMessage.message))
|
||||||
|
} yield ()
|
||||||
case dlcAccept: DLCAcceptTLV =>
|
case dlcAccept: DLCAcceptTLV =>
|
||||||
val f = for {
|
val f = for {
|
||||||
sign <- dlcWalletApi.signDLC(dlcAccept)
|
sign <- dlcWalletApi.signDLC(dlcAccept)
|
||||||
|
@ -7,6 +7,7 @@ import org.bitcoins.core.api.dlc.wallet.DLCWalletApi
|
|||||||
import org.bitcoins.core.protocol.BitcoinAddress
|
import org.bitcoins.core.protocol.BitcoinAddress
|
||||||
import org.bitcoins.core.protocol.dlc.models.DLCMessage
|
import org.bitcoins.core.protocol.dlc.models.DLCMessage
|
||||||
import org.bitcoins.core.protocol.tlv._
|
import org.bitcoins.core.protocol.tlv._
|
||||||
|
import org.bitcoins.crypto.Sha256Digest
|
||||||
import org.bitcoins.dlc.node.config._
|
import org.bitcoins.dlc.node.config._
|
||||||
import org.bitcoins.dlc.node.peer.Peer
|
import org.bitcoins.dlc.node.peer.Peer
|
||||||
|
|
||||||
@ -56,21 +57,14 @@ case class DLCNode(wallet: DLCWalletApi)(implicit
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
def acceptDLCOffer(
|
override def acceptDLCOffer(
|
||||||
peerAddress: InetSocketAddress,
|
peerAddress: InetSocketAddress,
|
||||||
dlcOffer: LnMessage[DLCOfferTLV],
|
dlcOffer: LnMessage[DLCOfferTLV],
|
||||||
externalPayoutAddress: Option[BitcoinAddress],
|
externalPayoutAddress: Option[BitcoinAddress],
|
||||||
externalChangeAddress: Option[BitcoinAddress]): Future[
|
externalChangeAddress: Option[BitcoinAddress]): Future[
|
||||||
DLCMessage.DLCAccept] = {
|
DLCMessage.DLCAccept] = {
|
||||||
|
|
||||||
val peer =
|
|
||||||
Peer(socket = peerAddress, socks5ProxyParams = config.socks5ProxyParams)
|
|
||||||
|
|
||||||
val handlerP = Promise[ActorRef]()
|
|
||||||
|
|
||||||
for {
|
for {
|
||||||
_ <- DLCClient.connect(peer, wallet, Some(handlerP))
|
handler <- connectToPeer(peerAddress)
|
||||||
handler <- handlerP.future
|
|
||||||
accept <- wallet.acceptDLCOffer(dlcOffer.tlv,
|
accept <- wallet.acceptDLCOffer(dlcOffer.tlv,
|
||||||
externalPayoutAddress,
|
externalPayoutAddress,
|
||||||
externalChangeAddress)
|
externalChangeAddress)
|
||||||
@ -79,4 +73,51 @@ case class DLCNode(wallet: DLCWalletApi)(implicit
|
|||||||
accept
|
accept
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override def sendDLCOffer(
|
||||||
|
peerAddress: InetSocketAddress,
|
||||||
|
message: String,
|
||||||
|
offerTLV: DLCOfferTLV): Future[Sha256Digest] = {
|
||||||
|
for {
|
||||||
|
handler <- connectToPeer(peerAddress)
|
||||||
|
localAddress <- getHostAddress
|
||||||
|
} yield {
|
||||||
|
val peer = NormalizedString(
|
||||||
|
localAddress.getHostString + ":" + peerAddress.getPort)
|
||||||
|
val msg = NormalizedString(message)
|
||||||
|
val lnMessage = LnMessage(
|
||||||
|
SendOfferTLV(peer = peer, message = msg, offer = offerTLV))
|
||||||
|
handler ! DLCDataHandler.Send(lnMessage)
|
||||||
|
offerTLV.tempContractId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override def sendDLCOffer(
|
||||||
|
peerAddress: InetSocketAddress,
|
||||||
|
message: String,
|
||||||
|
temporaryContractId: Sha256Digest): Future[Sha256Digest] = {
|
||||||
|
for {
|
||||||
|
dlcOpt <- wallet.findDLCByTemporaryContractId(temporaryContractId)
|
||||||
|
dlc = dlcOpt.getOrElse(
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
s"Cannot find a DLC with temp contact ID $temporaryContractId"))
|
||||||
|
offerOpt <- wallet.getDLCOffer(dlc.dlcId)
|
||||||
|
offer = offerOpt.getOrElse(
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
s"Cannot find an offer with for DLC ID ${dlc.dlcId}"))
|
||||||
|
res <- sendDLCOffer(peerAddress, message, offer.toTLV)
|
||||||
|
} yield res
|
||||||
|
}
|
||||||
|
|
||||||
|
private def connectToPeer(
|
||||||
|
peerAddress: InetSocketAddress): Future[ActorRef] = {
|
||||||
|
val peer =
|
||||||
|
Peer(socket = peerAddress, socks5ProxyParams = config.socks5ProxyParams)
|
||||||
|
|
||||||
|
val handlerP = Promise[ActorRef]()
|
||||||
|
for {
|
||||||
|
_ <- DLCClient.connect(peer, wallet, Some(handlerP))
|
||||||
|
handler <- handlerP.future
|
||||||
|
} yield handler
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -550,7 +550,8 @@ object DLCParsingTestVector extends TestVectorParser[DLCParsingTestVector] {
|
|||||||
)
|
)
|
||||||
|
|
||||||
DLCMessageTestVector(LnMessage(tlv), "oracle_attestment_v0", fields)
|
DLCMessageTestVector(LnMessage(tlv), "oracle_attestment_v0", fields)
|
||||||
case _: UnknownTLV | _: ErrorTLV | _: PingTLV | _: PongTLV | _: InitTLV =>
|
case _: UnknownTLV | _: ErrorTLV | _: PingTLV | _: PongTLV | _: InitTLV |
|
||||||
|
_: SendOfferTLV =>
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
s"DLCParsingTestVector is only defined for DLC messages and TLVs, got $tlv")
|
s"DLCParsingTestVector is only defined for DLC messages and TLVs, got $tlv")
|
||||||
}
|
}
|
||||||
|
@ -1598,44 +1598,69 @@ abstract class DLCWallet
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override def getDLCOffer(dlcId: Sha256Digest): Future[Option[DLCOffer]] =
|
||||||
|
dlcDataManagement.getOffer(dlcId, transactionDAO)
|
||||||
|
|
||||||
|
override def findDLCByTemporaryContractId(
|
||||||
|
tempContractId: Sha256Digest): Future[Option[DLCStatus]] = {
|
||||||
|
val start = System.currentTimeMillis()
|
||||||
|
|
||||||
|
val dlcOptF = for {
|
||||||
|
dlcDbOpt <- dlcDAO.findByTempContractId(tempContractId)
|
||||||
|
dlcStatusOpt <- dlcDbOpt match {
|
||||||
|
case None => Future.successful(None)
|
||||||
|
case Some(dlcDb) => findDLCStatus(dlcDb)
|
||||||
|
}
|
||||||
|
} yield dlcStatusOpt
|
||||||
|
|
||||||
|
dlcOptF.foreach(_ =>
|
||||||
|
logger.debug(
|
||||||
|
s"Done finding tempContractId=$tempContractId, it took=${System
|
||||||
|
.currentTimeMillis() - start}ms"))
|
||||||
|
dlcOptF
|
||||||
|
}
|
||||||
|
|
||||||
override def findDLC(dlcId: Sha256Digest): Future[Option[DLCStatus]] = {
|
override def findDLC(dlcId: Sha256Digest): Future[Option[DLCStatus]] = {
|
||||||
val start = System.currentTimeMillis()
|
val start = System.currentTimeMillis()
|
||||||
val dlcDbOptF = dlcDAO.read(dlcId)
|
|
||||||
|
val dlcOptF = for {
|
||||||
|
dlcDbOpt <- dlcDAO.read(dlcId)
|
||||||
|
dlcStatusOpt <- dlcDbOpt match {
|
||||||
|
case None => Future.successful(None)
|
||||||
|
case Some(dlcDb) => findDLCStatus(dlcDb)
|
||||||
|
}
|
||||||
|
} yield dlcStatusOpt
|
||||||
|
|
||||||
|
dlcOptF.foreach(_ =>
|
||||||
|
logger.debug(
|
||||||
|
s"Done finding dlc=$dlcId, it took=${System.currentTimeMillis() - start}ms"))
|
||||||
|
dlcOptF
|
||||||
|
}
|
||||||
|
|
||||||
|
private def findDLCStatus(dlcDb: DLCDb) = {
|
||||||
|
val dlcId = dlcDb.dlcId
|
||||||
val contractDataOptF = contractDataDAO.read(dlcId)
|
val contractDataOptF = contractDataDAO.read(dlcId)
|
||||||
val offerDbOptF = dlcOfferDAO.read(dlcId)
|
val offerDbOptF = dlcOfferDAO.read(dlcId)
|
||||||
val acceptDbOptF = dlcAcceptDAO.read(dlcId)
|
val acceptDbOptF = dlcAcceptDAO.read(dlcId)
|
||||||
val closingTxOptF: Future[Option[TransactionDb]] = for {
|
val closingTxOptF: Future[Option[TransactionDb]] = getClosingTxOpt(dlcDb)
|
||||||
dlcDbOpt <- dlcDbOptF
|
|
||||||
closingTxFOpt <- {
|
|
||||||
dlcDbOpt.map(dlcDb => getClosingTxOpt(dlcDb)) match {
|
|
||||||
case None => Future.successful(None)
|
|
||||||
case Some(closingTxIdOpt) => closingTxIdOpt
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} yield closingTxFOpt
|
|
||||||
|
|
||||||
val dlcOptF: Future[Option[DLCStatus]] = for {
|
val dlcOptF: Future[Option[DLCStatus]] = for {
|
||||||
dlcDbOpt <- dlcDbOptF
|
|
||||||
contractDataOpt <- contractDataOptF
|
contractDataOpt <- contractDataOptF
|
||||||
offerDbOpt <- offerDbOptF
|
offerDbOpt <- offerDbOptF
|
||||||
acceptDbOpt <- acceptDbOptF
|
acceptDbOpt <- acceptDbOptF
|
||||||
closingTxOpt <- closingTxOptF
|
closingTxOpt <- closingTxOptF
|
||||||
result <- {
|
result <- {
|
||||||
(dlcDbOpt, contractDataOpt, offerDbOpt) match {
|
(contractDataOpt, offerDbOpt) match {
|
||||||
case (Some(dlcDb), Some(contractData), Some(offerDb)) =>
|
case (Some(contractData), Some(offerDb)) =>
|
||||||
buildDLCStatus(dlcDb,
|
buildDLCStatus(dlcDb,
|
||||||
contractData,
|
contractData,
|
||||||
offerDb,
|
offerDb,
|
||||||
acceptDbOpt,
|
acceptDbOpt,
|
||||||
closingTxOpt)
|
closingTxOpt)
|
||||||
case (_, _, _) => Future.successful(None)
|
case (_, _) => Future.successful(None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} yield result
|
} yield result
|
||||||
|
|
||||||
dlcOptF.foreach(_ =>
|
|
||||||
logger.debug(
|
|
||||||
s"Done finding dlc=$dlcId, it took=${System.currentTimeMillis() - start}ms"))
|
|
||||||
dlcOptF
|
dlcOptF
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,6 +48,13 @@ case class DLCDataManagement(dlcWalletDAOs: DLCWalletDAOs)(implicit
|
|||||||
}
|
}
|
||||||
private val safeDatabase: SafeDatabase = dlcDAO.safeDatabase
|
private val safeDatabase: SafeDatabase = dlcDAO.safeDatabase
|
||||||
|
|
||||||
|
private[wallet] def getOffer(
|
||||||
|
dlcId: Sha256Digest,
|
||||||
|
txDAO: TransactionDAO): Future[Option[DLCOffer]] = {
|
||||||
|
val dataF = getDLCFundingData(dlcId, txDAO)
|
||||||
|
dataF.map(data => data.map(_.offer))
|
||||||
|
}
|
||||||
|
|
||||||
private[wallet] def getDLCAnnouncementDbs(dlcId: Sha256Digest): Future[(
|
private[wallet] def getDLCAnnouncementDbs(dlcId: Sha256Digest): Future[(
|
||||||
Vector[DLCAnnouncementDb],
|
Vector[DLCAnnouncementDb],
|
||||||
Vector[OracleAnnouncementDataDb],
|
Vector[OracleAnnouncementDataDb],
|
||||||
@ -203,7 +210,7 @@ case class DLCDataManagement(dlcWalletDAOs: DLCWalletDAOs)(implicit
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private def getDLCOfferData(
|
private[wallet] def getDLCOfferData(
|
||||||
dlcId: Sha256Digest,
|
dlcId: Sha256Digest,
|
||||||
transactionDAO: TransactionDAO): Future[Option[OfferedDbState]] = {
|
transactionDAO: TransactionDAO): Future[Option[OfferedDbState]] = {
|
||||||
|
|
||||||
|
@ -33,4 +33,9 @@ trait IncomingDLCOffersHandling { self: DLCWallet =>
|
|||||||
def listIncomingDLCOffers(): Future[Vector[IncomingDLCOfferDb]] = {
|
def listIncomingDLCOffers(): Future[Vector[IncomingDLCOfferDb]] = {
|
||||||
dlcWalletDAOs.incomingDLCOfferDAO.findAll()
|
dlcWalletDAOs.incomingDLCOfferDAO.findAll()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def findIncomingDLCOffer(
|
||||||
|
offerHash: Sha256Digest): Future[Option[IncomingDLCOfferDb]] = {
|
||||||
|
dlcWalletDAOs.incomingDLCOfferDAO.find(offerHash)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,6 +48,11 @@ case class IncomingDLCOfferDAO()(implicit
|
|||||||
safeDatabase.run(query.delete)
|
safeDatabase.run(query.delete)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def find(pk: Sha256Digest): Future[Option[IncomingDLCOfferDb]] = {
|
||||||
|
val query = table.filter(_.hash === pk)
|
||||||
|
safeDatabase.run(query.result).map(_.headOption)
|
||||||
|
}
|
||||||
|
|
||||||
class IncomingDLCOfferTable(tag: Tag)
|
class IncomingDLCOfferTable(tag: Tag)
|
||||||
extends Table[IncomingDLCOfferDb](tag, schemaName, "incoming_offers") {
|
extends Table[IncomingDLCOfferDb](tag, schemaName, "incoming_offers") {
|
||||||
|
|
||||||
|
@ -300,13 +300,14 @@ the `-p 9999:9999` port mapping on the docker container to adjust for this.
|
|||||||
- `getdlcs` - Returns all dlcs in the wallet
|
- `getdlcs` - Returns all dlcs in the wallet
|
||||||
- `getdlc` `dlcId` - Gets a specific dlc in the wallet
|
- `getdlc` `dlcId` - Gets a specific dlc in the wallet
|
||||||
- `dlcId` - Internal id of the DLC
|
- `dlcId` - Internal id of the DLC
|
||||||
- `offer-add` `offerTLV` `peer` `message` - Puts an incoming offer into the inbox
|
- `offer-add` `offerTLV` `peerAddress` `message` - Puts an incoming offer into the inbox
|
||||||
- `offerTLV` - Offer TLV
|
- `offerTLV` - Offer TLV
|
||||||
- `peer` - Peer URI (optional)
|
- `peer` - Peer URI (optional)
|
||||||
- `message` - Peer's message or note (optional)
|
- `message` - Peer's message or note (optional)
|
||||||
- `"offer-remove` `hash` - remove an incoming offer from inbox
|
- `"offer-remove` `hash` - Remove an incoming offer from inbox
|
||||||
- `hash` - Hash of the offer TLV
|
- `hash` - Hash of the offer TLV
|
||||||
- `offers-list` - List all incoming offers from the inbox
|
- `offer-send` `offerOrTempContractId` `peerAddress` `message` - Sends an offer to a peer. `offerOrTempContractId` is either an offer TLV or a temporary contract ID.
|
||||||
|
- `offers-list` - List all incoming offers from the inbox
|
||||||
|
|
||||||
### Network
|
### Network
|
||||||
- `getpeers` - List the connected peers
|
- `getpeers` - List the connected peers
|
||||||
|
Loading…
Reference in New Issue
Block a user