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.{BitcoinAddress, BlockStamp}
|
||||
import org.bitcoins.core.psbt.PSBT
|
||||
import org.bitcoins.core.util.NetworkUtil
|
||||
import org.bitcoins.core.wallet.fee.SatoshisPerVirtualByte
|
||||
import org.bitcoins.core.wallet.utxo.AddressLabelTag
|
||||
import org.bitcoins.crypto._
|
||||
@ -1384,7 +1385,7 @@ object OfferAdd {
|
||||
}
|
||||
case other =>
|
||||
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)
|
||||
}
|
||||
}
|
||||
@ -1403,7 +1404,37 @@ object OfferRemove {
|
||||
}
|
||||
case other =>
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import org.bitcoins.core.protocol.BitcoinAddress
|
||||
import org.bitcoins.core.protocol.dlc.models.DLCMessage
|
||||
import org.bitcoins.core.protocol.tlv._
|
||||
import org.bitcoins.core.util.StartStopAsync
|
||||
import org.bitcoins.crypto.Sha256Digest
|
||||
|
||||
import java.net.InetSocketAddress
|
||||
import scala.concurrent.Future
|
||||
@ -20,5 +21,15 @@ trait DLCNodeApi extends StartStopAsync[Unit] {
|
||||
externalChangeAddress: Option[BitcoinAddress]): Future[
|
||||
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]
|
||||
}
|
||||
|
@ -112,8 +112,13 @@ trait DLCWalletApi { self: WalletApi =>
|
||||
|
||||
def findDLC(dlcId: Sha256Digest): Future[Option[DLCStatus]]
|
||||
|
||||
def findDLCByTemporaryContractId(
|
||||
tempContractId: Sha256Digest): Future[Option[DLCStatus]]
|
||||
|
||||
def cancelDLC(dlcId: Sha256Digest): Future[Unit]
|
||||
|
||||
def getDLCOffer(dlcId: Sha256Digest): Future[Option[DLCOffer]]
|
||||
|
||||
/** Retrieves accounting and financial metrics for the entire dlc wallet */
|
||||
def getWalletAccounting(): Future[DLCWalletAccounting]
|
||||
|
||||
@ -125,6 +130,9 @@ trait DLCWalletApi { self: WalletApi =>
|
||||
def listIncomingDLCOffers(): Future[Vector[IncomingDLCOfferDb]]
|
||||
|
||||
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 */
|
||||
|
@ -1,6 +1,6 @@
|
||||
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 java.time.Instant
|
||||
@ -15,4 +15,15 @@ case class IncomingDLCOfferDb(
|
||||
"peer length must not exceed 1024 characters")
|
||||
require(message.forall(_.length <= 1024),
|
||||
"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,
|
||||
DLCOfferTLV,
|
||||
DLCAcceptTLV,
|
||||
DLCSignTLV
|
||||
DLCSignTLV,
|
||||
SendOfferTLV
|
||||
) ++ EventDescriptorTLV.allFactories ++
|
||||
PayoutCurvePieceTLV.allFactories ++
|
||||
ContractDescriptorTLV.allFactories ++
|
||||
@ -1687,6 +1688,38 @@ object FundingSignaturesV0TLV extends TLVFactory[FundingSignaturesV0TLV] {
|
||||
|
||||
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(
|
||||
protocolVersionOpt: Option[Int],
|
||||
contractFlags: Byte,
|
||||
|
@ -3,6 +3,7 @@ package org.bitcoins.dlc.node
|
||||
import akka.actor.ActorRef
|
||||
import org.bitcoins.core.number.UInt32
|
||||
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.dlc.node.peer.Peer
|
||||
import org.bitcoins.rpc.util.RpcUtil
|
||||
@ -33,17 +34,13 @@ class DLCNegotiationTest extends BitcoinSDualWalletTest {
|
||||
val connectAddress =
|
||||
InetSocketAddress.createUnresolved("127.0.0.1", port)
|
||||
|
||||
val serverF = DLCServer.bind(walletA, bindAddress, None)
|
||||
|
||||
val handlerP = Promise[ActorRef]()
|
||||
val clientF =
|
||||
DLCClient.connect(Peer(connectAddress, socks5ProxyParams = None),
|
||||
walletB,
|
||||
Some(handlerP))
|
||||
|
||||
for {
|
||||
_ <- serverF
|
||||
_ <- clientF
|
||||
_ <- DLCServer.bind(walletA, bindAddress, None)
|
||||
_ <- DLCClient.connect(Peer(connectAddress, socks5ProxyParams = None),
|
||||
walletB,
|
||||
Some(handlerP))
|
||||
|
||||
handler <- handlerP.future
|
||||
|
||||
@ -79,4 +76,55 @@ class DLCNegotiationTest extends BitcoinSDualWalletTest {
|
||||
)
|
||||
} 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 {
|
||||
_ <- dlcWalletApi.registerIncomingDLCOffer(dlcOffer, None, None)
|
||||
} yield ()
|
||||
case dlcOfferMessage: SendOfferTLV =>
|
||||
for {
|
||||
_ <- dlcWalletApi.registerIncomingDLCOffer(
|
||||
offerTLV = dlcOfferMessage.offer,
|
||||
peer = Some(dlcOfferMessage.peer),
|
||||
message = Some(dlcOfferMessage.message))
|
||||
} yield ()
|
||||
case dlcAccept: DLCAcceptTLV =>
|
||||
val f = for {
|
||||
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.dlc.models.DLCMessage
|
||||
import org.bitcoins.core.protocol.tlv._
|
||||
import org.bitcoins.crypto.Sha256Digest
|
||||
import org.bitcoins.dlc.node.config._
|
||||
import org.bitcoins.dlc.node.peer.Peer
|
||||
|
||||
@ -56,21 +57,14 @@ case class DLCNode(wallet: DLCWalletApi)(implicit
|
||||
}
|
||||
}
|
||||
|
||||
def acceptDLCOffer(
|
||||
override def acceptDLCOffer(
|
||||
peerAddress: InetSocketAddress,
|
||||
dlcOffer: LnMessage[DLCOfferTLV],
|
||||
externalPayoutAddress: Option[BitcoinAddress],
|
||||
externalChangeAddress: Option[BitcoinAddress]): Future[
|
||||
DLCMessage.DLCAccept] = {
|
||||
|
||||
val peer =
|
||||
Peer(socket = peerAddress, socks5ProxyParams = config.socks5ProxyParams)
|
||||
|
||||
val handlerP = Promise[ActorRef]()
|
||||
|
||||
for {
|
||||
_ <- DLCClient.connect(peer, wallet, Some(handlerP))
|
||||
handler <- handlerP.future
|
||||
handler <- connectToPeer(peerAddress)
|
||||
accept <- wallet.acceptDLCOffer(dlcOffer.tlv,
|
||||
externalPayoutAddress,
|
||||
externalChangeAddress)
|
||||
@ -79,4 +73,51 @@ case class DLCNode(wallet: DLCWalletApi)(implicit
|
||||
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)
|
||||
case _: UnknownTLV | _: ErrorTLV | _: PingTLV | _: PongTLV | _: InitTLV =>
|
||||
case _: UnknownTLV | _: ErrorTLV | _: PingTLV | _: PongTLV | _: InitTLV |
|
||||
_: SendOfferTLV =>
|
||||
throw new IllegalArgumentException(
|
||||
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]] = {
|
||||
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 offerDbOptF = dlcOfferDAO.read(dlcId)
|
||||
val acceptDbOptF = dlcAcceptDAO.read(dlcId)
|
||||
val closingTxOptF: Future[Option[TransactionDb]] = for {
|
||||
dlcDbOpt <- dlcDbOptF
|
||||
closingTxFOpt <- {
|
||||
dlcDbOpt.map(dlcDb => getClosingTxOpt(dlcDb)) match {
|
||||
case None => Future.successful(None)
|
||||
case Some(closingTxIdOpt) => closingTxIdOpt
|
||||
}
|
||||
}
|
||||
} yield closingTxFOpt
|
||||
val closingTxOptF: Future[Option[TransactionDb]] = getClosingTxOpt(dlcDb)
|
||||
|
||||
val dlcOptF: Future[Option[DLCStatus]] = for {
|
||||
dlcDbOpt <- dlcDbOptF
|
||||
contractDataOpt <- contractDataOptF
|
||||
offerDbOpt <- offerDbOptF
|
||||
acceptDbOpt <- acceptDbOptF
|
||||
closingTxOpt <- closingTxOptF
|
||||
result <- {
|
||||
(dlcDbOpt, contractDataOpt, offerDbOpt) match {
|
||||
case (Some(dlcDb), Some(contractData), Some(offerDb)) =>
|
||||
(contractDataOpt, offerDbOpt) match {
|
||||
case (Some(contractData), Some(offerDb)) =>
|
||||
buildDLCStatus(dlcDb,
|
||||
contractData,
|
||||
offerDb,
|
||||
acceptDbOpt,
|
||||
closingTxOpt)
|
||||
case (_, _, _) => Future.successful(None)
|
||||
case (_, _) => Future.successful(None)
|
||||
}
|
||||
}
|
||||
} yield result
|
||||
|
||||
dlcOptF.foreach(_ =>
|
||||
logger.debug(
|
||||
s"Done finding dlc=$dlcId, it took=${System.currentTimeMillis() - start}ms"))
|
||||
dlcOptF
|
||||
}
|
||||
|
||||
|
@ -48,6 +48,13 @@ case class DLCDataManagement(dlcWalletDAOs: DLCWalletDAOs)(implicit
|
||||
}
|
||||
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[(
|
||||
Vector[DLCAnnouncementDb],
|
||||
Vector[OracleAnnouncementDataDb],
|
||||
@ -203,7 +210,7 @@ case class DLCDataManagement(dlcWalletDAOs: DLCWalletDAOs)(implicit
|
||||
}
|
||||
}
|
||||
|
||||
private def getDLCOfferData(
|
||||
private[wallet] def getDLCOfferData(
|
||||
dlcId: Sha256Digest,
|
||||
transactionDAO: TransactionDAO): Future[Option[OfferedDbState]] = {
|
||||
|
||||
|
@ -33,4 +33,9 @@ trait IncomingDLCOffersHandling { self: DLCWallet =>
|
||||
def listIncomingDLCOffers(): Future[Vector[IncomingDLCOfferDb]] = {
|
||||
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)
|
||||
}
|
||||
|
||||
def find(pk: Sha256Digest): Future[Option[IncomingDLCOfferDb]] = {
|
||||
val query = table.filter(_.hash === pk)
|
||||
safeDatabase.run(query.result).map(_.headOption)
|
||||
}
|
||||
|
||||
class IncomingDLCOfferTable(tag: Tag)
|
||||
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
|
||||
- `getdlc` `dlcId` - Gets a specific dlc in the wallet
|
||||
- `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
|
||||
- `peer` - Peer URI (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
|
||||
- `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
|
||||
- `getpeers` - List the connected peers
|
||||
|
Loading…
Reference in New Issue
Block a user