feat(nwc): add pay/receive methods for BOLT12 (nostr-wallet-connect/nwc#2)

Adds the generalized `pay` (BIP321 payment instruction, incl. BOLT12 `lno=`)
and `receive` NIP-47 methods, plus the UNSUPPORTED_PAYMENT_INSTRUCTION /
UNSUPPORTED_NETWORK error codes. The `pay` result carries `payer_proof`
(lnp1…) — the proof a kind:9736 BOLT12 zap needs. Wired through both
serialization backends (kotlinx + Jackson) with round-trip tests.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SpgpWLKzgD7vS9Fs4CXTR3
This commit is contained in:
Claude
2026-07-24 21:38:32 +00:00
parent 802652dd4f
commit 7d3f7f7ca4
13 changed files with 371 additions and 1 deletions
@@ -40,6 +40,10 @@ import com.vitorpamplona.quartz.nip47WalletConnect.rpc.PayInvoiceMethod
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.PayInvoiceParams
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.PayKeysendMethod
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.PayKeysendParams
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.PayMethod
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.PayParams
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.ReceiveMethod
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.ReceiveParams
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.Request
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.SettleHoldInvoiceMethod
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.SettleHoldInvoiceParams
@@ -85,6 +89,14 @@ object Nip47RequestKSerializer : KSerializer<Request> {
value.params?.let { put("params", serializePayInvoiceParams(it)) }
}
is PayMethod -> {
value.params?.let { put("params", serializePayParams(it)) }
}
is ReceiveMethod -> {
value.params?.let { put("params", serializeReceiveParams(it)) }
}
is PayKeysendMethod -> {
value.params?.let { put("params", serializePayKeysendParams(it)) }
}
@@ -138,6 +150,21 @@ object Nip47RequestKSerializer : KSerializer<Request> {
params.metadata?.let { put("metadata", Json.encodeToJsonElement(it)) }
}
private fun serializePayParams(params: PayParams): JsonObject =
buildJsonObject {
params.payment?.let { put("payment", it) }
params.amount?.let { put("amount", it) }
params.payer_note?.let { put("payer_note", it) }
params.metadata?.let { put("metadata", Json.encodeToJsonElement(it)) }
}
private fun serializeReceiveParams(params: ReceiveParams): JsonObject =
buildJsonObject {
params.amount?.let { put("amount", it) }
params.description?.let { put("description", it) }
params.metadata?.let { put("metadata", Json.encodeToJsonElement(it)) }
}
private fun serializePayKeysendParams(params: PayKeysendParams): JsonObject =
buildJsonObject {
params.amount?.let { put("amount", it) }
@@ -236,6 +263,8 @@ object Nip47RequestKSerializer : KSerializer<Request> {
return when (method) {
NwcMethod.PAY_INVOICE -> parsePayInvoice(jsonObject)
NwcMethod.PAY -> parsePay(jsonObject)
NwcMethod.RECEIVE -> parseReceive(jsonObject)
NwcMethod.PAY_KEYSEND -> parsePayKeysend(jsonObject)
NwcMethod.MAKE_INVOICE -> parseMakeInvoice(jsonObject)
NwcMethod.LOOKUP_INVOICE -> parseLookupInvoice(jsonObject)
@@ -265,6 +294,33 @@ object Nip47RequestKSerializer : KSerializer<Request> {
)
}
private fun parsePay(json: JsonObject): PayMethod {
val params = json["params"]?.jsonObject
return PayMethod(
params?.let {
PayParams(
payment = it["payment"]?.jsonPrimitive?.content,
amount = it["amount"]?.jsonPrimitive?.longOrNull,
payer_note = it["payer_note"]?.jsonPrimitive?.content,
metadata = it["metadata"]?.jsonObject?.toAnyMap(),
)
},
)
}
private fun parseReceive(json: JsonObject): ReceiveMethod {
val params = json["params"]?.jsonObject
return ReceiveMethod(
params?.let {
ReceiveParams(
amount = it["amount"]?.jsonPrimitive?.longOrNull,
description = it["description"]?.jsonPrimitive?.content,
metadata = it["metadata"]?.jsonObject?.toAnyMap(),
)
},
)
}
private fun parsePayKeysend(json: JsonObject): PayKeysendMethod {
val params = json["params"]?.jsonObject
return PayKeysendMethod(
@@ -37,6 +37,8 @@ import com.vitorpamplona.quartz.nip47WalletConnect.rpc.NwcTransaction
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.PayInvoiceErrorResponse
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.PayInvoiceSuccessResponse
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.PayKeysendSuccessResponse
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.PaySuccessResponse
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.ReceiveSuccessResponse
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.Response
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.SettleHoldInvoiceSuccessResponse
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.SignMessageSuccessResponse
@@ -81,6 +83,14 @@ object Nip47ResponseKSerializer : KSerializer<Response> {
value.result?.let { put("result", serializePayInvoiceResult(it)) }
}
is PaySuccessResponse -> {
value.result?.let { put("result", serializePayResult(it)) }
}
is ReceiveSuccessResponse -> {
value.result?.let { put("result", serializeReceiveResult(it)) }
}
is PayInvoiceErrorResponse -> {
value.error?.let { put("error", serializePayInvoiceErrorParams(it)) }
}
@@ -155,6 +165,28 @@ object Nip47ResponseKSerializer : KSerializer<Response> {
error.message?.let { put("message", it) }
}
private fun serializePayResult(result: PaySuccessResponse.PayResult): JsonObject =
buildJsonObject {
result.transaction_id?.let { put("transaction_id", it) }
result.state?.let { put("state", it) }
result.instruction_type?.let { put("instruction_type", it) }
result.amount?.let { put("amount", it) }
result.fees_paid?.let { put("fees_paid", it) }
result.payment_hash?.let { put("payment_hash", it) }
result.preimage?.let { put("preimage", it) }
result.payer_proof?.let { put("payer_proof", it) }
result.txid?.let { put("txid", it) }
result.failure_reason?.let { put("failure_reason", it) }
result.created_at?.let { put("created_at", it) }
result.settled_at?.let { put("settled_at", it) }
}
private fun serializeReceiveResult(result: ReceiveSuccessResponse.ReceiveResult): JsonObject =
buildJsonObject {
result.bip321?.let { put("bip321", it) }
result.transaction_id?.let { put("transaction_id", it) }
}
private fun serializePayKeysendResult(result: PayKeysendSuccessResponse.PayKeysendResult): JsonObject =
buildJsonObject {
result.preimage?.let { put("preimage", it) }
@@ -242,6 +274,14 @@ object Nip47ResponseKSerializer : KSerializer<Response> {
parsePayInvoiceSuccess(jsonObject)
}
NwcMethod.PAY -> {
parsePaySuccess(jsonObject)
}
NwcMethod.RECEIVE -> {
parseReceiveSuccess(jsonObject)
}
NwcMethod.PAY_KEYSEND -> {
parsePayKeysendSuccess(jsonObject)
}
@@ -387,6 +427,40 @@ object Nip47ResponseKSerializer : KSerializer<Response> {
)
}
private fun parsePaySuccess(json: JsonObject): PaySuccessResponse {
val result = json["result"]?.jsonObject
return PaySuccessResponse(
result?.let {
PaySuccessResponse.PayResult(
transaction_id = it["transaction_id"]?.jsonPrimitive?.content,
state = it["state"]?.jsonPrimitive?.content,
instruction_type = it["instruction_type"]?.jsonPrimitive?.content,
amount = it["amount"]?.jsonPrimitive?.longOrNull,
fees_paid = it["fees_paid"]?.jsonPrimitive?.longOrNull,
payment_hash = it["payment_hash"]?.jsonPrimitive?.content,
preimage = it["preimage"]?.jsonPrimitive?.content,
payer_proof = it["payer_proof"]?.jsonPrimitive?.content,
txid = it["txid"]?.jsonPrimitive?.content,
failure_reason = it["failure_reason"]?.jsonPrimitive?.content,
created_at = it["created_at"]?.jsonPrimitive?.longOrNull,
settled_at = it["settled_at"]?.jsonPrimitive?.longOrNull,
)
},
)
}
private fun parseReceiveSuccess(json: JsonObject): ReceiveSuccessResponse {
val result = json["result"]?.jsonObject
return ReceiveSuccessResponse(
result?.let {
ReceiveSuccessResponse.ReceiveResult(
bip321 = it["bip321"]?.jsonPrimitive?.content,
transaction_id = it["transaction_id"]?.jsonPrimitive?.content,
)
},
)
}
private fun parsePayKeysendSuccess(json: JsonObject): PayKeysendSuccessResponse {
val result = json["result"]?.jsonObject
return PayKeysendSuccessResponse(
@@ -33,6 +33,10 @@ enum class NwcErrorCode {
BAD_REQUEST,
NOT_FOUND,
EXPIRED,
// nostr-wallet-connect/nwc#2 — pay/receive payment-instruction errors.
UNSUPPORTED_PAYMENT_INSTRUCTION,
UNSUPPORTED_NETWORK,
OTHER,
}
@@ -34,4 +34,8 @@ object NwcMethod {
const val MAKE_HOLD_INVOICE = "make_hold_invoice"
const val CANCEL_HOLD_INVOICE = "cancel_hold_invoice"
const val SETTLE_HOLD_INVOICE = "settle_hold_invoice"
// nostr-wallet-connect/nwc#2 — generalized payment instructions (BOLT12/BIP321).
const val PAY = "pay"
const val RECEIVE = "receive"
}
@@ -47,6 +47,48 @@ class PayInvoiceMethod(
}
}
// pay (nostr-wallet-connect/nwc#2) — settle any BIP321 payment instruction
// (bolt11 `lightning=`, BOLT12 `lno=`, or on-chain). `payment` is the BIP321 URI;
// `amount` (msats) is required only when the instruction has no amount; `payer_note`
// is delivered to the payee when the instruction supports payer messages (for a
// BOLT12 zap this carries `nostr:nipXX:<intent-id>`).
class PayParams(
var payment: String? = null,
var amount: Long? = null,
var payer_note: String? = null,
var metadata: Map<String, Any?>? = null,
)
class PayMethod(
var params: PayParams? = null,
) : Request(NwcMethod.PAY) {
companion object {
fun create(
payment: String,
amount: Long? = null,
payerNote: String? = null,
): PayMethod = PayMethod(PayParams(payment, amount, payerNote))
}
}
// receive (nostr-wallet-connect/nwc#2) — mint a payment instruction to be paid.
class ReceiveParams(
var amount: Long? = null,
var description: String? = null,
var metadata: Map<String, Any?>? = null,
)
class ReceiveMethod(
var params: ReceiveParams? = null,
) : Request(NwcMethod.RECEIVE) {
companion object {
fun create(
amount: Long? = null,
description: String? = null,
): ReceiveMethod = ReceiveMethod(ReceiveParams(amount, description))
}
}
// pay_keysend
class PayKeysendParams(
var amount: Long? = null,
@@ -68,6 +68,38 @@ class PayInvoiceErrorResponse(
override fun errorMessage() = error?.message
}
// pay success response (nostr-wallet-connect/nwc#2). For a settled BOLT12 payment
// `payer_proof` carries the `lnp1...` proof — the input a kind:9736 BOLT12 zap needs.
// It is best-effort ("optional if unavailable"), so callers must tolerate its absence.
class PaySuccessResponse(
val result: PayResult? = null,
) : Response(NwcMethod.PAY) {
class PayResult(
val transaction_id: String? = null,
val state: String? = null,
val instruction_type: String? = null,
val amount: Long? = null,
val fees_paid: Long? = null,
val payment_hash: String? = null,
val preimage: String? = null,
val payer_proof: String? = null,
val txid: String? = null,
val failure_reason: String? = null,
val created_at: Long? = null,
val settled_at: Long? = null,
)
}
// receive success response (nostr-wallet-connect/nwc#2).
class ReceiveSuccessResponse(
val result: ReceiveResult? = null,
) : Response(NwcMethod.RECEIVE) {
class ReceiveResult(
val bip321: String? = null,
val transaction_id: String? = null,
)
}
// pay_keysend success response
class PayKeysendSuccessResponse(
val result: PayKeysendResult? = null,
@@ -48,6 +48,8 @@ class NwcMethodTest {
assertEquals("make_hold_invoice", NwcMethod.MAKE_HOLD_INVOICE)
assertEquals("cancel_hold_invoice", NwcMethod.CANCEL_HOLD_INVOICE)
assertEquals("settle_hold_invoice", NwcMethod.SETTLE_HOLD_INVOICE)
assertEquals("pay", NwcMethod.PAY)
assertEquals("receive", NwcMethod.RECEIVE)
}
@Test
@@ -60,7 +62,7 @@ class NwcMethodTest {
@Test
fun testErrorCodeValues() {
val codes = NwcErrorCode.entries
assertEquals(13, codes.size)
assertEquals(15, codes.size)
assertEquals(NwcErrorCode.RATE_LIMITED, NwcErrorCode.valueOf("RATE_LIMITED"))
assertEquals(NwcErrorCode.NOT_IMPLEMENTED, NwcErrorCode.valueOf("NOT_IMPLEMENTED"))
assertEquals(NwcErrorCode.INSUFFICIENT_BALANCE, NwcErrorCode.valueOf("INSUFFICIENT_BALANCE"))
@@ -73,6 +75,8 @@ class NwcMethodTest {
assertEquals(NwcErrorCode.BAD_REQUEST, NwcErrorCode.valueOf("BAD_REQUEST"))
assertEquals(NwcErrorCode.NOT_FOUND, NwcErrorCode.valueOf("NOT_FOUND"))
assertEquals(NwcErrorCode.EXPIRED, NwcErrorCode.valueOf("EXPIRED"))
assertEquals(NwcErrorCode.UNSUPPORTED_PAYMENT_INSTRUCTION, NwcErrorCode.valueOf("UNSUPPORTED_PAYMENT_INSTRUCTION"))
assertEquals(NwcErrorCode.UNSUPPORTED_NETWORK, NwcErrorCode.valueOf("UNSUPPORTED_NETWORK"))
assertEquals(NwcErrorCode.OTHER, NwcErrorCode.valueOf("OTHER"))
}
@@ -33,6 +33,8 @@ import com.vitorpamplona.quartz.nip47WalletConnect.rpc.MakeInvoiceMethod
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.NwcMethod
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.PayInvoiceMethod
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.PayKeysendMethod
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.PayMethod
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.ReceiveMethod
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.Request
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.SettleHoldInvoiceMethod
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.SignMessageMethod
@@ -89,6 +91,67 @@ class RequestTest {
assertEquals(1000L, request.params?.amount)
}
// --- Pay (nwc#2 BOLT12/BIP321) ---
@Test
fun testPayCreateWithOfferAndPayerNote() {
val request = PayMethod.create("bitcoin:?lno=lno1abc", amount = 21_000L, payerNote = "nostr:nipXX:deadbeef")
assertEquals(NwcMethod.PAY, request.method)
assertEquals("bitcoin:?lno=lno1abc", request.params?.payment)
assertEquals(21_000L, request.params?.amount)
assertEquals("nostr:nipXX:deadbeef", request.params?.payer_note)
}
@Test
fun testPaySerialization() {
val request = PayMethod.create("bitcoin:?lno=lno1abc", amount = 21_000L, payerNote = "nostr:nipXX:deadbeef")
val json = OptimizedJsonMapper.toJson(request)
assertTrue(json.contains("\"method\":\"pay\""))
assertTrue(json.contains("\"payment\":\"bitcoin:?lno=lno1abc\""))
assertTrue(json.contains("\"amount\":21000"))
assertTrue(json.contains("\"payer_note\":\"nostr:nipXX:deadbeef\""))
}
@Test
fun testPayDeserialization() {
val json = """{"method":"pay","params":{"payment":"bitcoin:?lno=lno1abc","amount":21000,"payer_note":"nostr:nipXX:deadbeef"}}"""
val request = OptimizedJsonMapper.fromJsonTo<Request>(json)
assertIs<PayMethod>(request)
assertEquals("bitcoin:?lno=lno1abc", request.params?.payment)
assertEquals(21_000L, request.params?.amount)
assertEquals("nostr:nipXX:deadbeef", request.params?.payer_note)
}
@Test
fun testPayAmountlessDeserialization() {
val json = """{"method":"pay","params":{"payment":"bitcoin:?lno=lno1abc"}}"""
val request = OptimizedJsonMapper.fromJsonTo<Request>(json)
assertIs<PayMethod>(request)
assertEquals("bitcoin:?lno=lno1abc", request.params?.payment)
assertNull(request.params?.amount)
assertNull(request.params?.payer_note)
}
// --- Receive (nwc#2) ---
@Test
fun testReceiveSerialization() {
val request = ReceiveMethod.create(amount = 21_000L, description = "tip jar")
val json = OptimizedJsonMapper.toJson(request)
assertTrue(json.contains("\"method\":\"receive\""))
assertTrue(json.contains("\"amount\":21000"))
assertTrue(json.contains("\"description\":\"tip jar\""))
}
@Test
fun testReceiveDeserialization() {
val json = """{"method":"receive","params":{"amount":21000,"description":"tip jar"}}"""
val request = OptimizedJsonMapper.fromJsonTo<Request>(json)
assertIs<ReceiveMethod>(request)
assertEquals(21_000L, request.params?.amount)
assertEquals("tip jar", request.params?.description)
}
// --- PayKeysend ---
@Test
@@ -35,6 +35,8 @@ import com.vitorpamplona.quartz.nip47WalletConnect.rpc.NwcErrorResponse
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.PayInvoiceErrorResponse
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.PayInvoiceSuccessResponse
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.PayKeysendSuccessResponse
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.PaySuccessResponse
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.ReceiveSuccessResponse
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.Response
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.SettleHoldInvoiceSuccessResponse
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.SignMessageSuccessResponse
@@ -91,6 +93,53 @@ class ResponseTest {
assertEquals(NwcErrorCode.PAYMENT_FAILED, response.error?.code)
}
// --- Pay Success (nwc#2 BOLT12) ---
@Test
fun testPaySuccessWithPayerProofDeserialization() {
val json =
"""{"result_type":"pay","result":{"state":"settled","instruction_type":"bolt12","amount":21000,"fees_paid":100,"payment_hash":"abc","preimage":"def","payer_proof":"lnp1xyz","settled_at":1693876497}}"""
val response = OptimizedJsonMapper.fromJsonTo<Response>(json)
assertIs<PaySuccessResponse>(response)
assertEquals("settled", response.result?.state)
assertEquals("bolt12", response.result?.instruction_type)
assertEquals(21_000L, response.result?.amount)
assertEquals(100L, response.result?.fees_paid)
assertEquals("abc", response.result?.payment_hash)
assertEquals("def", response.result?.preimage)
assertEquals("lnp1xyz", response.result?.payer_proof)
assertEquals(1693876497L, response.result?.settled_at)
}
@Test
fun testPaySuccessWithoutPayerProof() {
// payer_proof is best-effort ("optional if unavailable") — absence must parse fine.
val json = """{"result_type":"pay","result":{"state":"settled","preimage":"def"}}"""
val response = OptimizedJsonMapper.fromJsonTo<Response>(json)
assertIs<PaySuccessResponse>(response)
assertEquals("def", response.result?.preimage)
assertNull(response.result?.payer_proof)
}
@Test
fun testPayErrorUnsupportedInstruction() {
val json = """{"result_type":"pay","error":{"code":"UNSUPPORTED_PAYMENT_INSTRUCTION","message":"no bolt12"}}"""
val response = OptimizedJsonMapper.fromJsonTo<Response>(json)
assertIs<NwcErrorResponse>(response)
assertEquals(NwcErrorCode.UNSUPPORTED_PAYMENT_INSTRUCTION, response.error?.code)
}
// --- Receive Success (nwc#2) ---
@Test
fun testReceiveSuccessDeserialization() {
val json = """{"result_type":"receive","result":{"bip321":"bitcoin:?lightning=lnbc1&lno=lno1","transaction_id":"tx1"}}"""
val response = OptimizedJsonMapper.fromJsonTo<Response>(json)
assertIs<ReceiveSuccessResponse>(response)
assertEquals("bitcoin:?lightning=lnbc1&lno=lno1", response.result?.bip321)
assertEquals("tx1", response.result?.transaction_id)
}
// --- PayKeysend Success ---
@Test
@@ -36,6 +36,8 @@ import com.vitorpamplona.quartz.nip47WalletConnect.rpc.MakeInvoiceMethod
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.NwcMethod
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.PayInvoiceMethod
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.PayKeysendMethod
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.PayMethod
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.ReceiveMethod
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.Request
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.SettleHoldInvoiceMethod
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.SignMessageMethod
@@ -51,6 +53,8 @@ class RequestDeserializer : StdDeserializer<Request>(Request::class.java) {
return when (method) {
NwcMethod.PAY_INVOICE -> jp.codec.treeToValue(jsonObject, PayInvoiceMethod::class.java)
NwcMethod.PAY -> jp.codec.treeToValue(jsonObject, PayMethod::class.java)
NwcMethod.RECEIVE -> jp.codec.treeToValue(jsonObject, ReceiveMethod::class.java)
NwcMethod.PAY_KEYSEND -> jp.codec.treeToValue(jsonObject, PayKeysendMethod::class.java)
NwcMethod.MAKE_INVOICE -> jp.codec.treeToValue(jsonObject, MakeInvoiceMethod::class.java)
NwcMethod.LOOKUP_INVOICE -> jp.codec.treeToValue(jsonObject, LookupInvoiceMethod::class.java)
@@ -31,6 +31,8 @@ import com.vitorpamplona.quartz.nip47WalletConnect.rpc.MakeHoldInvoiceMethod
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.MakeInvoiceMethod
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.PayInvoiceMethod
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.PayKeysendMethod
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.PayMethod
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.ReceiveMethod
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.Request
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.SettleHoldInvoiceMethod
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.SignMessageMethod
@@ -52,6 +54,18 @@ class RequestSerializer : StdSerializer<Request>(Request::class.java) {
}
}
is PayMethod -> {
if (value.params != null) {
gen.writeObjectField("params", value.params)
}
}
is ReceiveMethod -> {
if (value.params != null) {
gen.writeObjectField("params", value.params)
}
}
is PayKeysendMethod -> {
if (value.params != null) {
gen.writeObjectField("params", value.params)
@@ -39,6 +39,8 @@ import com.vitorpamplona.quartz.nip47WalletConnect.rpc.NwcMethod
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.PayInvoiceErrorResponse
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.PayInvoiceSuccessResponse
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.PayKeysendSuccessResponse
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.PaySuccessResponse
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.ReceiveSuccessResponse
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.Response
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.SettleHoldInvoiceSuccessResponse
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.SignMessageSuccessResponse
@@ -73,6 +75,14 @@ class ResponseDeserializer : StdDeserializer<Response>(Response::class.java) {
jp.codec.treeToValue(jsonObject, PayInvoiceSuccessResponse::class.java)
}
NwcMethod.PAY -> {
jp.codec.treeToValue(jsonObject, PaySuccessResponse::class.java)
}
NwcMethod.RECEIVE -> {
jp.codec.treeToValue(jsonObject, ReceiveSuccessResponse::class.java)
}
NwcMethod.PAY_KEYSEND -> {
jp.codec.treeToValue(jsonObject, PayKeysendSuccessResponse::class.java)
}
@@ -36,6 +36,8 @@ import com.vitorpamplona.quartz.nip47WalletConnect.rpc.NwcErrorResponse
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.PayInvoiceErrorResponse
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.PayInvoiceSuccessResponse
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.PayKeysendSuccessResponse
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.PaySuccessResponse
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.ReceiveSuccessResponse
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.Response
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.SettleHoldInvoiceSuccessResponse
import com.vitorpamplona.quartz.nip47WalletConnect.rpc.SignMessageSuccessResponse
@@ -69,6 +71,18 @@ class ResponseSerializer : StdSerializer<Response>(Response::class.java) {
}
}
is PaySuccessResponse -> {
if (value.result != null) {
gen.writeObjectField("result", value.result)
}
}
is ReceiveSuccessResponse -> {
if (value.result != null) {
gen.writeObjectField("result", value.result)
}
}
is PayKeysendSuccessResponse -> {
if (value.result != null) {
gen.writeObjectField("result", value.result)