Finishes serialization features for NIP-47
This commit is contained in:
+12
@@ -107,6 +107,18 @@ class KotlinSerializationMapper {
|
||||
json.encodeToString(BunkerMessageKSerializer, value)
|
||||
}
|
||||
|
||||
is Request -> {
|
||||
json.encodeToString(Nip47RequestKSerializer, value)
|
||||
}
|
||||
|
||||
is Response -> {
|
||||
json.encodeToString(Nip47ResponseKSerializer, value)
|
||||
}
|
||||
|
||||
is Notification -> {
|
||||
json.encodeToString(Nip47NotificationKSerializer, value)
|
||||
}
|
||||
|
||||
else -> {
|
||||
throw IllegalArgumentException("Unsupported type: ${value::class}")
|
||||
}
|
||||
|
||||
+1
-1
@@ -62,7 +62,7 @@ class NwcTransaction(
|
||||
var expires_at: Long? = null,
|
||||
var settled_at: Long? = null,
|
||||
var settle_deadline: Long? = null,
|
||||
var metadata: Any? = null,
|
||||
var metadata: Map<String, Any?>? = null,
|
||||
) {
|
||||
fun parsedMetadata(): NwcTransactionMetadata? = NwcTransactionMetadata.parse(metadata)
|
||||
}
|
||||
|
||||
@@ -31,7 +31,7 @@ abstract class Request(
|
||||
class PayInvoiceParams(
|
||||
var invoice: String? = null,
|
||||
var amount: Long? = null,
|
||||
var metadata: Any? = null,
|
||||
var metadata: Map<String, Any?>? = null,
|
||||
)
|
||||
|
||||
class PayInvoiceMethod(
|
||||
@@ -74,7 +74,7 @@ class MakeInvoiceParams(
|
||||
var description: String? = null,
|
||||
var description_hash: String? = null,
|
||||
var expiry: Long? = null,
|
||||
var metadata: Any? = null,
|
||||
var metadata: Map<String, Any?>? = null,
|
||||
)
|
||||
|
||||
class MakeInvoiceMethod(
|
||||
@@ -233,7 +233,7 @@ class CreateConnectionParams(
|
||||
var budget_renewal: String? = null,
|
||||
var expires_at: Long? = null,
|
||||
var isolated: Boolean? = null,
|
||||
var metadata: Any? = null,
|
||||
var metadata: Map<String, Any?>? = null,
|
||||
)
|
||||
|
||||
class CreateConnectionMethod(
|
||||
@@ -249,7 +249,7 @@ class CreateConnectionMethod(
|
||||
budgetRenewal: String? = null,
|
||||
expiresAt: Long? = null,
|
||||
isolated: Boolean? = null,
|
||||
metadata: Any? = null,
|
||||
metadata: Map<String, Any?>? = null,
|
||||
): CreateConnectionMethod =
|
||||
CreateConnectionMethod(
|
||||
CreateConnectionParams(pubkey, name, requestMethods, notificationTypes, maxAmount, budgetRenewal, expiresAt, isolated, metadata),
|
||||
|
||||
+1
-1
@@ -105,7 +105,7 @@ class GetInfoSuccessResponse(
|
||||
val block_hash: String? = null,
|
||||
val methods: List<String>? = null,
|
||||
val notifications: List<String>? = null,
|
||||
val metadata: Any? = null,
|
||||
val metadata: Map<String, Any?>? = null,
|
||||
val lud16: String? = null,
|
||||
)
|
||||
}
|
||||
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip47WalletConnect.kotlinSerialization
|
||||
|
||||
import kotlinx.serialization.json.JsonArray
|
||||
import kotlinx.serialization.json.JsonElement
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
import kotlinx.serialization.json.JsonPrimitive
|
||||
|
||||
// Helper function to convert JsonElement to standard Kotlin types recursively
|
||||
fun JsonElement.toAnyValue(): Any =
|
||||
when (this) {
|
||||
is JsonPrimitive -> {
|
||||
if (isString) {
|
||||
content
|
||||
} else {
|
||||
content.toBooleanStrictOrNull() ?: content.toDoubleOrNull() ?: content.toLongOrNull() ?: content
|
||||
}
|
||||
}
|
||||
|
||||
is JsonObject -> {
|
||||
toAnyMap()
|
||||
}
|
||||
|
||||
is JsonArray -> {
|
||||
map { it.toAnyValue() }
|
||||
}
|
||||
}
|
||||
|
||||
fun JsonObject.toAnyMap(): Map<String, Any?> = entries.associate { it.key to it.value.toAnyValue() }
|
||||
+41
-1
@@ -32,10 +32,13 @@ import kotlinx.serialization.descriptors.buildClassSerialDescriptor
|
||||
import kotlinx.serialization.encoding.Decoder
|
||||
import kotlinx.serialization.encoding.Encoder
|
||||
import kotlinx.serialization.json.JsonDecoder
|
||||
import kotlinx.serialization.json.JsonEncoder
|
||||
import kotlinx.serialization.json.JsonNull
|
||||
import kotlinx.serialization.json.buildJsonObject
|
||||
import kotlinx.serialization.json.jsonObject
|
||||
import kotlinx.serialization.json.jsonPrimitive
|
||||
import kotlinx.serialization.json.longOrNull
|
||||
import kotlinx.serialization.json.put
|
||||
|
||||
object Nip47NotificationKSerializer : KSerializer<Notification> {
|
||||
override val descriptor: SerialDescriptor =
|
||||
@@ -44,7 +47,44 @@ object Nip47NotificationKSerializer : KSerializer<Notification> {
|
||||
override fun serialize(
|
||||
encoder: Encoder,
|
||||
value: Notification,
|
||||
): Unit = throw UnsupportedOperationException("NIP-47 Notification serialization not supported")
|
||||
) {
|
||||
val jsonEncoder = encoder as JsonEncoder
|
||||
val jsonObject =
|
||||
buildJsonObject {
|
||||
put("notification_type", value.notification_type)
|
||||
when (value) {
|
||||
is PaymentReceivedNotification -> {
|
||||
Nip47ResponseKSerializer.serializeTransaction(value.notification)?.let {
|
||||
put("notification", it)
|
||||
}
|
||||
}
|
||||
|
||||
is PaymentSentNotification -> {
|
||||
Nip47ResponseKSerializer.serializeTransaction(value.notification)?.let {
|
||||
put("notification", it)
|
||||
}
|
||||
}
|
||||
|
||||
is HoldInvoiceAcceptedNotification -> {
|
||||
value.notification?.let { data ->
|
||||
put(
|
||||
"notification",
|
||||
buildJsonObject {
|
||||
data.type?.let { put("type", it) }
|
||||
data.invoice?.let { put("invoice", it) }
|
||||
data.payment_hash?.let { put("payment_hash", it) }
|
||||
data.amount?.let { put("amount", it) }
|
||||
data.created_at?.let { put("created_at", it) }
|
||||
data.expires_at?.let { put("expires_at", it) }
|
||||
data.settle_deadline?.let { put("settle_deadline", it) }
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
jsonEncoder.encodeJsonElement(jsonObject)
|
||||
}
|
||||
|
||||
override fun deserialize(decoder: Decoder): Notification {
|
||||
val jsonDecoder = decoder as JsonDecoder
|
||||
|
||||
+164
-1
@@ -51,15 +51,23 @@ import kotlinx.serialization.descriptors.SerialDescriptor
|
||||
import kotlinx.serialization.descriptors.buildClassSerialDescriptor
|
||||
import kotlinx.serialization.encoding.Decoder
|
||||
import kotlinx.serialization.encoding.Encoder
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.JsonDecoder
|
||||
import kotlinx.serialization.json.JsonEncoder
|
||||
import kotlinx.serialization.json.JsonNull
|
||||
import kotlinx.serialization.json.JsonNull.content
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
import kotlinx.serialization.json.add
|
||||
import kotlinx.serialization.json.booleanOrNull
|
||||
import kotlinx.serialization.json.buildJsonArray
|
||||
import kotlinx.serialization.json.buildJsonObject
|
||||
import kotlinx.serialization.json.encodeToJsonElement
|
||||
import kotlinx.serialization.json.intOrNull
|
||||
import kotlinx.serialization.json.jsonArray
|
||||
import kotlinx.serialization.json.jsonObject
|
||||
import kotlinx.serialization.json.jsonPrimitive
|
||||
import kotlinx.serialization.json.longOrNull
|
||||
import kotlinx.serialization.json.put
|
||||
|
||||
object Nip47RequestKSerializer : KSerializer<Request> {
|
||||
override val descriptor: SerialDescriptor =
|
||||
@@ -68,7 +76,159 @@ object Nip47RequestKSerializer : KSerializer<Request> {
|
||||
override fun serialize(
|
||||
encoder: Encoder,
|
||||
value: Request,
|
||||
): Unit = throw UnsupportedOperationException("NIP-47 Request serialization not supported")
|
||||
) {
|
||||
val jsonEncoder = encoder as JsonEncoder
|
||||
val jsonObject =
|
||||
buildJsonObject {
|
||||
put("method", value.method)
|
||||
when (value) {
|
||||
is PayInvoiceMethod -> {
|
||||
value.params?.let { put("params", serializePayInvoiceParams(it)) }
|
||||
}
|
||||
|
||||
is PayKeysendMethod -> {
|
||||
value.params?.let { put("params", serializePayKeysendParams(it)) }
|
||||
}
|
||||
|
||||
is MakeInvoiceMethod -> {
|
||||
value.params?.let { put("params", serializeMakeInvoiceParams(it)) }
|
||||
}
|
||||
|
||||
is LookupInvoiceMethod -> {
|
||||
value.params?.let { put("params", serializeLookupInvoiceParams(it)) }
|
||||
}
|
||||
|
||||
is ListTransactionsMethod -> {
|
||||
value.params?.let { put("params", serializeListTransactionsParams(it)) }
|
||||
}
|
||||
|
||||
is GetBalanceMethod -> {}
|
||||
|
||||
is GetInfoMethod -> {}
|
||||
|
||||
is GetBudgetMethod -> {}
|
||||
|
||||
is SignMessageMethod -> {
|
||||
value.params?.let { put("params", serializeSignMessageParams(it)) }
|
||||
}
|
||||
|
||||
is CreateConnectionMethod -> {
|
||||
value.params?.let { put("params", serializeCreateConnectionParams(it)) }
|
||||
}
|
||||
|
||||
is MakeHoldInvoiceMethod -> {
|
||||
value.params?.let { put("params", serializeMakeHoldInvoiceParams(it)) }
|
||||
}
|
||||
|
||||
is CancelHoldInvoiceMethod -> {
|
||||
value.params?.let { put("params", serializeCancelHoldInvoiceParams(it)) }
|
||||
}
|
||||
|
||||
is SettleHoldInvoiceMethod -> {
|
||||
value.params?.let { put("params", serializeSettleHoldInvoiceParams(it)) }
|
||||
}
|
||||
}
|
||||
}
|
||||
jsonEncoder.encodeJsonElement(jsonObject)
|
||||
}
|
||||
|
||||
private fun serializePayInvoiceParams(params: PayInvoiceParams): JsonObject =
|
||||
buildJsonObject {
|
||||
params.invoice?.let { put("invoice", it) }
|
||||
params.amount?.let { put("amount", it) }
|
||||
params.metadata?.let { put("metadata", Json.encodeToJsonElement(it)) }
|
||||
}
|
||||
|
||||
private fun serializePayKeysendParams(params: PayKeysendParams): JsonObject =
|
||||
buildJsonObject {
|
||||
params.amount?.let { put("amount", it) }
|
||||
params.pubkey?.let { put("pubkey", it) }
|
||||
params.preimage?.let { put("preimage", it) }
|
||||
params.tlv_records?.let { records ->
|
||||
put(
|
||||
"tlv_records",
|
||||
buildJsonArray {
|
||||
records.forEach { record ->
|
||||
add(
|
||||
buildJsonObject {
|
||||
record.type?.let { put("type", it) }
|
||||
record.value?.let { put("value", it) }
|
||||
},
|
||||
)
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun serializeMakeInvoiceParams(params: MakeInvoiceParams): JsonObject =
|
||||
buildJsonObject {
|
||||
params.amount?.let { put("amount", it) }
|
||||
params.description?.let { put("description", it) }
|
||||
params.description_hash?.let { put("description_hash", it) }
|
||||
params.expiry?.let { put("expiry", it) }
|
||||
params.metadata?.let { put("metadata", Json.encodeToJsonElement(it)) }
|
||||
}
|
||||
|
||||
private fun serializeLookupInvoiceParams(params: LookupInvoiceParams): JsonObject =
|
||||
buildJsonObject {
|
||||
params.payment_hash?.let { put("payment_hash", it) }
|
||||
params.invoice?.let { put("invoice", it) }
|
||||
}
|
||||
|
||||
private fun serializeListTransactionsParams(params: ListTransactionsParams): JsonObject =
|
||||
buildJsonObject {
|
||||
params.from?.let { put("from", it) }
|
||||
params.until?.let { put("until", it) }
|
||||
params.limit?.let { put("limit", it) }
|
||||
params.offset?.let { put("offset", it) }
|
||||
params.unpaid?.let { put("unpaid", it) }
|
||||
params.unpaid_outgoing?.let { put("unpaid_outgoing", it) }
|
||||
params.unpaid_incoming?.let { put("unpaid_incoming", it) }
|
||||
params.type?.let { put("type", it) }
|
||||
}
|
||||
|
||||
private fun serializeSignMessageParams(params: SignMessageParams): JsonObject =
|
||||
buildJsonObject {
|
||||
params.message?.let { put("message", it) }
|
||||
}
|
||||
|
||||
private fun serializeCreateConnectionParams(params: CreateConnectionParams): JsonObject =
|
||||
buildJsonObject {
|
||||
params.pubkey?.let { put("pubkey", it) }
|
||||
params.name?.let { put("name", it) }
|
||||
params.request_methods?.let { methods ->
|
||||
put("request_methods", buildJsonArray { methods.forEach { add(it) } })
|
||||
}
|
||||
params.notification_types?.let { types ->
|
||||
put("notification_types", buildJsonArray { types.forEach { add(it) } })
|
||||
}
|
||||
params.max_amount?.let { put("max_amount", it) }
|
||||
params.budget_renewal?.let { put("budget_renewal", it) }
|
||||
params.expires_at?.let { put("expires_at", it) }
|
||||
params.isolated?.let { put("isolated", it) }
|
||||
params.metadata?.let { put("metadata", Json.encodeToJsonElement(it)) }
|
||||
}
|
||||
|
||||
private fun serializeMakeHoldInvoiceParams(params: MakeHoldInvoiceParams): JsonObject =
|
||||
buildJsonObject {
|
||||
params.amount?.let { put("amount", it) }
|
||||
params.description?.let { put("description", it) }
|
||||
params.description_hash?.let { put("description_hash", it) }
|
||||
params.expiry?.let { put("expiry", it) }
|
||||
params.payment_hash?.let { put("payment_hash", it) }
|
||||
params.min_cltv_expiry_delta?.let { put("min_cltv_expiry_delta", it) }
|
||||
}
|
||||
|
||||
private fun serializeCancelHoldInvoiceParams(params: CancelHoldInvoiceParams): JsonObject =
|
||||
buildJsonObject {
|
||||
params.payment_hash?.let { put("payment_hash", it) }
|
||||
}
|
||||
|
||||
private fun serializeSettleHoldInvoiceParams(params: SettleHoldInvoiceParams): JsonObject =
|
||||
buildJsonObject {
|
||||
params.preimage?.let { put("preimage", it) }
|
||||
}
|
||||
|
||||
override fun deserialize(decoder: Decoder): Request {
|
||||
val jsonDecoder = decoder as JsonDecoder
|
||||
@@ -100,6 +260,7 @@ object Nip47RequestKSerializer : KSerializer<Request> {
|
||||
PayInvoiceParams(
|
||||
invoice = it["invoice"]?.jsonPrimitive?.content,
|
||||
amount = it["amount"]?.jsonPrimitive?.longOrNull,
|
||||
metadata = it["metadata"]?.jsonObject?.toAnyMap(),
|
||||
)
|
||||
},
|
||||
)
|
||||
@@ -135,6 +296,7 @@ object Nip47RequestKSerializer : KSerializer<Request> {
|
||||
description = it["description"]?.jsonPrimitive?.content,
|
||||
description_hash = it["description_hash"]?.jsonPrimitive?.content,
|
||||
expiry = it["expiry"]?.jsonPrimitive?.longOrNull,
|
||||
metadata = it["metadata"]?.jsonObject?.toAnyMap(),
|
||||
)
|
||||
},
|
||||
)
|
||||
@@ -194,6 +356,7 @@ object Nip47RequestKSerializer : KSerializer<Request> {
|
||||
budget_renewal = it["budget_renewal"]?.jsonPrimitive?.content,
|
||||
expires_at = it["expires_at"]?.jsonPrimitive?.longOrNull,
|
||||
isolated = it["isolated"]?.jsonPrimitive?.booleanOrNull,
|
||||
metadata = it["metadata"]?.jsonObject?.toAnyMap(),
|
||||
)
|
||||
},
|
||||
)
|
||||
|
||||
+177
-1
@@ -45,13 +45,20 @@ import kotlinx.serialization.descriptors.SerialDescriptor
|
||||
import kotlinx.serialization.descriptors.buildClassSerialDescriptor
|
||||
import kotlinx.serialization.encoding.Decoder
|
||||
import kotlinx.serialization.encoding.Encoder
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.JsonDecoder
|
||||
import kotlinx.serialization.json.JsonEncoder
|
||||
import kotlinx.serialization.json.JsonNull
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
import kotlinx.serialization.json.add
|
||||
import kotlinx.serialization.json.buildJsonArray
|
||||
import kotlinx.serialization.json.buildJsonObject
|
||||
import kotlinx.serialization.json.encodeToJsonElement
|
||||
import kotlinx.serialization.json.jsonArray
|
||||
import kotlinx.serialization.json.jsonObject
|
||||
import kotlinx.serialization.json.jsonPrimitive
|
||||
import kotlinx.serialization.json.longOrNull
|
||||
import kotlinx.serialization.json.put
|
||||
|
||||
object Nip47ResponseKSerializer : KSerializer<Response> {
|
||||
override val descriptor: SerialDescriptor =
|
||||
@@ -60,7 +67,154 @@ object Nip47ResponseKSerializer : KSerializer<Response> {
|
||||
override fun serialize(
|
||||
encoder: Encoder,
|
||||
value: Response,
|
||||
): Unit = throw UnsupportedOperationException("NIP-47 Response serialization not supported")
|
||||
) {
|
||||
val jsonEncoder = encoder as JsonEncoder
|
||||
val jsonObject =
|
||||
buildJsonObject {
|
||||
put("result_type", value.resultType)
|
||||
when (value) {
|
||||
is NwcErrorResponse -> {
|
||||
value.error?.let { put("error", serializeNwcError(it)) }
|
||||
}
|
||||
|
||||
is PayInvoiceSuccessResponse -> {
|
||||
value.result?.let { put("result", serializePayInvoiceResult(it)) }
|
||||
}
|
||||
|
||||
is PayInvoiceErrorResponse -> {
|
||||
value.error?.let { put("error", serializePayInvoiceErrorParams(it)) }
|
||||
}
|
||||
|
||||
is PayKeysendSuccessResponse -> {
|
||||
value.result?.let { put("result", serializePayKeysendResult(it)) }
|
||||
}
|
||||
|
||||
is MakeInvoiceSuccessResponse -> {
|
||||
serializeTransaction(value.result)?.let { put("result", it) }
|
||||
}
|
||||
|
||||
is LookupInvoiceSuccessResponse -> {
|
||||
serializeTransaction(value.result)?.let { put("result", it) }
|
||||
}
|
||||
|
||||
is ListTransactionsSuccessResponse -> {
|
||||
value.result?.let { put("result", serializeListTransactionsResult(it)) }
|
||||
}
|
||||
|
||||
is GetBalanceSuccessResponse -> {
|
||||
value.result?.let { put("result", serializeGetBalanceResult(it)) }
|
||||
}
|
||||
|
||||
is GetInfoSuccessResponse -> {
|
||||
value.result?.let { put("result", serializeGetInfoResult(it)) }
|
||||
}
|
||||
|
||||
is GetBudgetSuccessResponse -> {
|
||||
value.result?.let { put("result", serializeGetBudgetResult(it)) }
|
||||
}
|
||||
|
||||
is SignMessageSuccessResponse -> {
|
||||
value.result?.let { put("result", serializeSignMessageResult(it)) }
|
||||
}
|
||||
|
||||
is CreateConnectionSuccessResponse -> {
|
||||
value.result?.let { put("result", serializeCreateConnectionResult(it)) }
|
||||
}
|
||||
|
||||
is MakeHoldInvoiceSuccessResponse -> {
|
||||
serializeTransaction(value.result)?.let { put("result", it) }
|
||||
}
|
||||
|
||||
is CancelHoldInvoiceSuccessResponse -> {
|
||||
put("result", buildJsonObject {})
|
||||
}
|
||||
|
||||
is SettleHoldInvoiceSuccessResponse -> {
|
||||
put("result", buildJsonObject {})
|
||||
}
|
||||
}
|
||||
}
|
||||
jsonEncoder.encodeJsonElement(jsonObject)
|
||||
}
|
||||
|
||||
private fun serializeNwcError(error: NwcError): JsonObject =
|
||||
buildJsonObject {
|
||||
error.code?.let { put("code", it.name) }
|
||||
error.message?.let { put("message", it) }
|
||||
}
|
||||
|
||||
private fun serializePayInvoiceResult(result: PayInvoiceSuccessResponse.PayInvoiceResultParams): JsonObject =
|
||||
buildJsonObject {
|
||||
result.preimage?.let { put("preimage", it) }
|
||||
result.fees_paid?.let { put("fees_paid", it) }
|
||||
}
|
||||
|
||||
private fun serializePayInvoiceErrorParams(error: PayInvoiceErrorResponse.PayInvoiceErrorParams): JsonObject =
|
||||
buildJsonObject {
|
||||
error.code?.let { put("code", it.name) }
|
||||
error.message?.let { put("message", it) }
|
||||
}
|
||||
|
||||
private fun serializePayKeysendResult(result: PayKeysendSuccessResponse.PayKeysendResult): JsonObject =
|
||||
buildJsonObject {
|
||||
result.preimage?.let { put("preimage", it) }
|
||||
result.fees_paid?.let { put("fees_paid", it) }
|
||||
}
|
||||
|
||||
private fun serializeListTransactionsResult(result: ListTransactionsSuccessResponse.ListTransactionsResult): JsonObject =
|
||||
buildJsonObject {
|
||||
result.transactions?.let { transactions ->
|
||||
put(
|
||||
"transactions",
|
||||
buildJsonArray {
|
||||
transactions.forEach { serializeTransaction(it)?.let { t -> add(t) } }
|
||||
},
|
||||
)
|
||||
}
|
||||
result.total_count?.let { put("total_count", it) }
|
||||
}
|
||||
|
||||
private fun serializeGetBalanceResult(result: GetBalanceSuccessResponse.GetBalanceResult): JsonObject =
|
||||
buildJsonObject {
|
||||
result.balance?.let { put("balance", it) }
|
||||
}
|
||||
|
||||
private fun serializeGetInfoResult(result: GetInfoSuccessResponse.GetInfoResult): JsonObject =
|
||||
buildJsonObject {
|
||||
result.alias?.let { put("alias", it) }
|
||||
result.color?.let { put("color", it) }
|
||||
result.pubkey?.let { put("pubkey", it) }
|
||||
result.network?.let { put("network", it) }
|
||||
result.block_height?.let { put("block_height", it) }
|
||||
result.block_hash?.let { put("block_hash", it) }
|
||||
result.methods?.let { methods ->
|
||||
put("methods", buildJsonArray { methods.forEach { add(it) } })
|
||||
}
|
||||
result.notifications?.let { notifications ->
|
||||
put("notifications", buildJsonArray { notifications.forEach { add(it) } })
|
||||
}
|
||||
result.metadata?.let { put("metadata", Json.encodeToJsonElement(it)) }
|
||||
result.lud16?.let { put("lud16", it) }
|
||||
}
|
||||
|
||||
private fun serializeGetBudgetResult(result: GetBudgetSuccessResponse.GetBudgetResult): JsonObject =
|
||||
buildJsonObject {
|
||||
result.used_budget?.let { put("used_budget", it) }
|
||||
result.total_budget?.let { put("total_budget", it) }
|
||||
result.renews_at?.let { put("renews_at", it) }
|
||||
result.renewal_period?.let { put("renewal_period", it) }
|
||||
}
|
||||
|
||||
private fun serializeSignMessageResult(result: SignMessageSuccessResponse.SignMessageResult): JsonObject =
|
||||
buildJsonObject {
|
||||
result.message?.let { put("message", it) }
|
||||
result.signature?.let { put("signature", it) }
|
||||
}
|
||||
|
||||
private fun serializeCreateConnectionResult(result: CreateConnectionSuccessResponse.CreateConnectionResult): JsonObject =
|
||||
buildJsonObject {
|
||||
result.wallet_pubkey?.let { put("wallet_pubkey", it) }
|
||||
}
|
||||
|
||||
override fun deserialize(decoder: Decoder): Response {
|
||||
val jsonDecoder = decoder as JsonDecoder
|
||||
@@ -162,6 +316,26 @@ object Nip47ResponseKSerializer : KSerializer<Response> {
|
||||
return NwcError(code, obj["message"]?.jsonPrimitive?.content)
|
||||
}
|
||||
|
||||
fun serializeTransaction(transaction: NwcTransaction?): JsonObject? {
|
||||
if (transaction == null) return null
|
||||
return buildJsonObject {
|
||||
transaction.type?.let { put("type", it) }
|
||||
transaction.state?.let { put("state", it) }
|
||||
transaction.invoice?.let { put("invoice", it) }
|
||||
transaction.description?.let { put("description", it) }
|
||||
transaction.description_hash?.let { put("description_hash", it) }
|
||||
transaction.preimage?.let { put("preimage", it) }
|
||||
transaction.payment_hash?.let { put("payment_hash", it) }
|
||||
transaction.amount?.let { put("amount", it) }
|
||||
transaction.fees_paid?.let { put("fees_paid", it) }
|
||||
transaction.created_at?.let { put("created_at", it) }
|
||||
transaction.expires_at?.let { put("expires_at", it) }
|
||||
transaction.settled_at?.let { put("settled_at", it) }
|
||||
transaction.settle_deadline?.let { put("settle_deadline", it) }
|
||||
transaction.metadata?.let { put("metadata", Json.encodeToJsonElement(it)) }
|
||||
}
|
||||
}
|
||||
|
||||
fun parseTransaction(obj: JsonObject?): NwcTransaction? {
|
||||
if (obj == null) return null
|
||||
return NwcTransaction(
|
||||
@@ -178,6 +352,7 @@ object Nip47ResponseKSerializer : KSerializer<Response> {
|
||||
expires_at = obj["expires_at"]?.jsonPrimitive?.longOrNull,
|
||||
settled_at = obj["settled_at"]?.jsonPrimitive?.longOrNull,
|
||||
settle_deadline = obj["settle_deadline"]?.jsonPrimitive?.longOrNull,
|
||||
metadata = obj["metadata"]?.jsonObject?.toAnyMap(),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -260,6 +435,7 @@ object Nip47ResponseKSerializer : KSerializer<Response> {
|
||||
block_hash = it["block_hash"]?.jsonPrimitive?.content,
|
||||
methods = it["methods"]?.jsonArray?.map { m -> m.jsonPrimitive.content },
|
||||
notifications = it["notifications"]?.jsonArray?.map { n -> n.jsonPrimitive.content },
|
||||
metadata = it["metadata"]?.jsonObject?.toAnyMap(),
|
||||
lud16 = it["lud16"]?.jsonPrimitive?.content,
|
||||
)
|
||||
},
|
||||
|
||||
+6
@@ -56,8 +56,11 @@ import com.vitorpamplona.quartz.nip47WalletConnect.Notification
|
||||
import com.vitorpamplona.quartz.nip47WalletConnect.Request
|
||||
import com.vitorpamplona.quartz.nip47WalletConnect.Response
|
||||
import com.vitorpamplona.quartz.nip47WalletConnect.jackson.NotificationDeserializer
|
||||
import com.vitorpamplona.quartz.nip47WalletConnect.jackson.NotificationSerializer
|
||||
import com.vitorpamplona.quartz.nip47WalletConnect.jackson.RequestDeserializer
|
||||
import com.vitorpamplona.quartz.nip47WalletConnect.jackson.RequestSerializer
|
||||
import com.vitorpamplona.quartz.nip47WalletConnect.jackson.ResponseDeserializer
|
||||
import com.vitorpamplona.quartz.nip47WalletConnect.jackson.ResponseSerializer
|
||||
import com.vitorpamplona.quartz.nip59Giftwrap.rumors.Rumor
|
||||
import com.vitorpamplona.quartz.nip59Giftwrap.rumors.jackson.RumorDeserializer
|
||||
import com.vitorpamplona.quartz.nip59Giftwrap.rumors.jackson.RumorSerializer
|
||||
@@ -93,8 +96,11 @@ class JacksonMapper {
|
||||
.addSerializer(Rumor::class.java, RumorSerializer())
|
||||
.addDeserializer(Rumor::class.java, RumorDeserializer())
|
||||
// nip 47
|
||||
.addSerializer(Response::class.java, ResponseSerializer())
|
||||
.addDeserializer(Response::class.java, ResponseDeserializer())
|
||||
.addSerializer(Request::class.java, RequestSerializer())
|
||||
.addDeserializer(Request::class.java, RequestDeserializer())
|
||||
.addSerializer(Notification::class.java, NotificationSerializer())
|
||||
.addDeserializer(Notification::class.java, NotificationDeserializer())
|
||||
// nip 46
|
||||
.addDeserializer(BunkerMessage::class.java, BunkerMessageDeserializer())
|
||||
|
||||
+60
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip47WalletConnect.jackson
|
||||
|
||||
import com.fasterxml.jackson.core.JsonGenerator
|
||||
import com.fasterxml.jackson.databind.SerializerProvider
|
||||
import com.fasterxml.jackson.databind.ser.std.StdSerializer
|
||||
import com.vitorpamplona.quartz.nip47WalletConnect.HoldInvoiceAcceptedNotification
|
||||
import com.vitorpamplona.quartz.nip47WalletConnect.Notification
|
||||
import com.vitorpamplona.quartz.nip47WalletConnect.PaymentReceivedNotification
|
||||
import com.vitorpamplona.quartz.nip47WalletConnect.PaymentSentNotification
|
||||
|
||||
class NotificationSerializer : StdSerializer<Notification>(Notification::class.java) {
|
||||
override fun serialize(
|
||||
value: Notification,
|
||||
gen: JsonGenerator,
|
||||
provider: SerializerProvider,
|
||||
) {
|
||||
gen.writeStartObject()
|
||||
gen.writeStringField("notification_type", value.notification_type)
|
||||
when (value) {
|
||||
is PaymentReceivedNotification -> {
|
||||
if (value.notification != null) {
|
||||
gen.writeObjectField("notification", value.notification)
|
||||
}
|
||||
}
|
||||
|
||||
is PaymentSentNotification -> {
|
||||
if (value.notification != null) {
|
||||
gen.writeObjectField("notification", value.notification)
|
||||
}
|
||||
}
|
||||
|
||||
is HoldInvoiceAcceptedNotification -> {
|
||||
if (value.notification != null) {
|
||||
gen.writeObjectField("notification", value.notification)
|
||||
}
|
||||
}
|
||||
}
|
||||
gen.writeEndObject()
|
||||
}
|
||||
}
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip47WalletConnect.jackson
|
||||
|
||||
import com.fasterxml.jackson.core.JsonGenerator
|
||||
import com.fasterxml.jackson.databind.SerializerProvider
|
||||
import com.fasterxml.jackson.databind.ser.std.StdSerializer
|
||||
import com.vitorpamplona.quartz.nip47WalletConnect.CancelHoldInvoiceMethod
|
||||
import com.vitorpamplona.quartz.nip47WalletConnect.CreateConnectionMethod
|
||||
import com.vitorpamplona.quartz.nip47WalletConnect.ListTransactionsMethod
|
||||
import com.vitorpamplona.quartz.nip47WalletConnect.LookupInvoiceMethod
|
||||
import com.vitorpamplona.quartz.nip47WalletConnect.MakeHoldInvoiceMethod
|
||||
import com.vitorpamplona.quartz.nip47WalletConnect.MakeInvoiceMethod
|
||||
import com.vitorpamplona.quartz.nip47WalletConnect.PayInvoiceMethod
|
||||
import com.vitorpamplona.quartz.nip47WalletConnect.PayKeysendMethod
|
||||
import com.vitorpamplona.quartz.nip47WalletConnect.Request
|
||||
import com.vitorpamplona.quartz.nip47WalletConnect.SettleHoldInvoiceMethod
|
||||
import com.vitorpamplona.quartz.nip47WalletConnect.SignMessageMethod
|
||||
|
||||
class RequestSerializer : StdSerializer<Request>(Request::class.java) {
|
||||
override fun serialize(
|
||||
value: Request,
|
||||
gen: JsonGenerator,
|
||||
provider: SerializerProvider,
|
||||
) {
|
||||
gen.writeStartObject()
|
||||
if (value.method != null) {
|
||||
gen.writeStringField("method", value.method)
|
||||
}
|
||||
when (value) {
|
||||
is PayInvoiceMethod -> {
|
||||
if (value.params != null) {
|
||||
gen.writeObjectField("params", value.params)
|
||||
}
|
||||
}
|
||||
|
||||
is PayKeysendMethod -> {
|
||||
if (value.params != null) {
|
||||
gen.writeObjectField("params", value.params)
|
||||
}
|
||||
}
|
||||
|
||||
is MakeInvoiceMethod -> {
|
||||
if (value.params != null) {
|
||||
gen.writeObjectField("params", value.params)
|
||||
}
|
||||
}
|
||||
|
||||
is LookupInvoiceMethod -> {
|
||||
if (value.params != null) {
|
||||
gen.writeObjectField("params", value.params)
|
||||
}
|
||||
}
|
||||
|
||||
is ListTransactionsMethod -> {
|
||||
if (value.params != null) {
|
||||
gen.writeObjectField("params", value.params)
|
||||
}
|
||||
}
|
||||
|
||||
is MakeHoldInvoiceMethod -> {
|
||||
if (value.params != null) {
|
||||
gen.writeObjectField("params", value.params)
|
||||
}
|
||||
}
|
||||
|
||||
is CancelHoldInvoiceMethod -> {
|
||||
if (value.params != null) {
|
||||
gen.writeObjectField("params", value.params)
|
||||
}
|
||||
}
|
||||
|
||||
is SettleHoldInvoiceMethod -> {
|
||||
if (value.params != null) {
|
||||
gen.writeObjectField("params", value.params)
|
||||
}
|
||||
}
|
||||
|
||||
is SignMessageMethod -> {
|
||||
if (value.params != null) {
|
||||
gen.writeObjectField("params", value.params)
|
||||
}
|
||||
}
|
||||
|
||||
is CreateConnectionMethod -> {
|
||||
if (value.params != null) {
|
||||
gen.writeObjectField("params", value.params)
|
||||
}
|
||||
}
|
||||
}
|
||||
gen.writeEndObject()
|
||||
}
|
||||
}
|
||||
+146
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip47WalletConnect.jackson
|
||||
|
||||
import com.fasterxml.jackson.core.JsonGenerator
|
||||
import com.fasterxml.jackson.databind.SerializerProvider
|
||||
import com.fasterxml.jackson.databind.ser.std.StdSerializer
|
||||
import com.vitorpamplona.quartz.nip47WalletConnect.CancelHoldInvoiceSuccessResponse
|
||||
import com.vitorpamplona.quartz.nip47WalletConnect.CreateConnectionSuccessResponse
|
||||
import com.vitorpamplona.quartz.nip47WalletConnect.GetBalanceSuccessResponse
|
||||
import com.vitorpamplona.quartz.nip47WalletConnect.GetBudgetSuccessResponse
|
||||
import com.vitorpamplona.quartz.nip47WalletConnect.GetInfoSuccessResponse
|
||||
import com.vitorpamplona.quartz.nip47WalletConnect.ListTransactionsSuccessResponse
|
||||
import com.vitorpamplona.quartz.nip47WalletConnect.LookupInvoiceSuccessResponse
|
||||
import com.vitorpamplona.quartz.nip47WalletConnect.MakeHoldInvoiceSuccessResponse
|
||||
import com.vitorpamplona.quartz.nip47WalletConnect.MakeInvoiceSuccessResponse
|
||||
import com.vitorpamplona.quartz.nip47WalletConnect.NwcErrorResponse
|
||||
import com.vitorpamplona.quartz.nip47WalletConnect.PayInvoiceErrorResponse
|
||||
import com.vitorpamplona.quartz.nip47WalletConnect.PayInvoiceSuccessResponse
|
||||
import com.vitorpamplona.quartz.nip47WalletConnect.PayKeysendSuccessResponse
|
||||
import com.vitorpamplona.quartz.nip47WalletConnect.Response
|
||||
import com.vitorpamplona.quartz.nip47WalletConnect.SettleHoldInvoiceSuccessResponse
|
||||
import com.vitorpamplona.quartz.nip47WalletConnect.SignMessageSuccessResponse
|
||||
|
||||
class ResponseSerializer : StdSerializer<Response>(Response::class.java) {
|
||||
override fun serialize(
|
||||
value: Response,
|
||||
gen: JsonGenerator,
|
||||
provider: SerializerProvider,
|
||||
) {
|
||||
gen.writeStartObject()
|
||||
if (value.resultType.isNotEmpty()) {
|
||||
gen.writeStringField("result_type", value.resultType)
|
||||
}
|
||||
when (value) {
|
||||
is NwcErrorResponse -> {
|
||||
if (value.error != null) {
|
||||
gen.writeObjectField("error", value.error)
|
||||
}
|
||||
}
|
||||
|
||||
is PayInvoiceErrorResponse -> {
|
||||
if (value.error != null) {
|
||||
gen.writeObjectField("error", value.error)
|
||||
}
|
||||
}
|
||||
|
||||
is PayInvoiceSuccessResponse -> {
|
||||
if (value.result != null) {
|
||||
gen.writeObjectField("result", value.result)
|
||||
}
|
||||
}
|
||||
|
||||
is PayKeysendSuccessResponse -> {
|
||||
if (value.result != null) {
|
||||
gen.writeObjectField("result", value.result)
|
||||
}
|
||||
}
|
||||
|
||||
is MakeInvoiceSuccessResponse -> {
|
||||
if (value.result != null) {
|
||||
gen.writeObjectField("result", value.result)
|
||||
}
|
||||
}
|
||||
|
||||
is LookupInvoiceSuccessResponse -> {
|
||||
if (value.result != null) {
|
||||
gen.writeObjectField("result", value.result)
|
||||
}
|
||||
}
|
||||
|
||||
is ListTransactionsSuccessResponse -> {
|
||||
if (value.result != null) {
|
||||
gen.writeObjectField("result", value.result)
|
||||
}
|
||||
}
|
||||
|
||||
is GetBalanceSuccessResponse -> {
|
||||
if (value.result != null) {
|
||||
gen.writeObjectField("result", value.result)
|
||||
}
|
||||
}
|
||||
|
||||
is GetInfoSuccessResponse -> {
|
||||
if (value.result != null) {
|
||||
gen.writeObjectField("result", value.result)
|
||||
}
|
||||
}
|
||||
|
||||
is MakeHoldInvoiceSuccessResponse -> {
|
||||
if (value.result != null) {
|
||||
gen.writeObjectField("result", value.result)
|
||||
}
|
||||
}
|
||||
|
||||
is CancelHoldInvoiceSuccessResponse -> {
|
||||
if (value.result != null) {
|
||||
gen.writeObjectField("result", value.result)
|
||||
}
|
||||
}
|
||||
|
||||
is SettleHoldInvoiceSuccessResponse -> {
|
||||
if (value.result != null) {
|
||||
gen.writeObjectField("result", value.result)
|
||||
}
|
||||
}
|
||||
|
||||
is GetBudgetSuccessResponse -> {
|
||||
if (value.result != null) {
|
||||
gen.writeObjectField("result", value.result)
|
||||
}
|
||||
}
|
||||
|
||||
is SignMessageSuccessResponse -> {
|
||||
if (value.result != null) {
|
||||
gen.writeObjectField("result", value.result)
|
||||
}
|
||||
}
|
||||
|
||||
is CreateConnectionSuccessResponse -> {
|
||||
if (value.result != null) {
|
||||
gen.writeObjectField("result", value.result)
|
||||
}
|
||||
}
|
||||
}
|
||||
gen.writeEndObject()
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user