feat: add NIP-47 get_budget, sign_message, create_connection methods and Alby Hub interop

- Add get_budget, sign_message, create_connection request/response types
- Add NwcTransactionType (incoming/outgoing) and NwcTransactionState
  (PENDING/SETTLED/FAILED/ACCEPTED) constants
- Add missing error codes: BAD_REQUEST, NOT_FOUND, EXPIRED
- Add settle_deadline field to NwcTransaction
- Add total_count to ListTransactionsResult
- Add metadata and lud16 to GetInfoResult
- Add unpaid_outgoing and unpaid_incoming to ListTransactionsParams
- Update Jackson deserializers for new method types
- Add AlbyInteropTest with 25+ tests verifying compatibility with
  Alby Hub's JSON formats for all request/response types
- Update existing tests for new constants and error codes

https://claude.ai/code/session_01JFogiwyR4CPVP8cRznqahJ
This commit is contained in:
Claude
2026-03-14 02:58:40 +00:00
parent 8c73dd8f14
commit 9e4cb446ef
11 changed files with 669 additions and 1 deletions
@@ -25,7 +25,9 @@ import com.fasterxml.jackson.databind.DeserializationContext
import com.fasterxml.jackson.databind.JsonNode
import com.fasterxml.jackson.databind.deser.std.StdDeserializer
import com.vitorpamplona.quartz.nip47WalletConnect.CancelHoldInvoiceMethod
import com.vitorpamplona.quartz.nip47WalletConnect.CreateConnectionMethod
import com.vitorpamplona.quartz.nip47WalletConnect.GetBalanceMethod
import com.vitorpamplona.quartz.nip47WalletConnect.GetBudgetMethod
import com.vitorpamplona.quartz.nip47WalletConnect.GetInfoMethod
import com.vitorpamplona.quartz.nip47WalletConnect.ListTransactionsMethod
import com.vitorpamplona.quartz.nip47WalletConnect.LookupInvoiceMethod
@@ -36,6 +38,7 @@ 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
import com.vitorpamplona.quartz.utils.asTextOrNull
class RequestDeserializer : StdDeserializer<Request>(Request::class.java) {
@@ -54,6 +57,9 @@ class RequestDeserializer : StdDeserializer<Request>(Request::class.java) {
NwcMethod.LIST_TRANSACTIONS -> jp.codec.treeToValue(jsonObject, ListTransactionsMethod::class.java)
NwcMethod.GET_BALANCE -> jp.codec.treeToValue(jsonObject, GetBalanceMethod::class.java)
NwcMethod.GET_INFO -> jp.codec.treeToValue(jsonObject, GetInfoMethod::class.java)
NwcMethod.GET_BUDGET -> jp.codec.treeToValue(jsonObject, GetBudgetMethod::class.java)
NwcMethod.SIGN_MESSAGE -> jp.codec.treeToValue(jsonObject, SignMessageMethod::class.java)
NwcMethod.CREATE_CONNECTION -> jp.codec.treeToValue(jsonObject, CreateConnectionMethod::class.java)
NwcMethod.MAKE_HOLD_INVOICE -> jp.codec.treeToValue(jsonObject, MakeHoldInvoiceMethod::class.java)
NwcMethod.CANCEL_HOLD_INVOICE -> jp.codec.treeToValue(jsonObject, CancelHoldInvoiceMethod::class.java)
NwcMethod.SETTLE_HOLD_INVOICE -> jp.codec.treeToValue(jsonObject, SettleHoldInvoiceMethod::class.java)
@@ -25,7 +25,9 @@ import com.fasterxml.jackson.databind.DeserializationContext
import com.fasterxml.jackson.databind.JsonNode
import com.fasterxml.jackson.databind.deser.std.StdDeserializer
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
@@ -39,6 +41,7 @@ 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
import com.vitorpamplona.quartz.utils.asTextOrNull
class ResponseDeserializer : StdDeserializer<Response>(Response::class.java) {
@@ -70,6 +73,9 @@ class ResponseDeserializer : StdDeserializer<Response>(Response::class.java) {
NwcMethod.LIST_TRANSACTIONS -> jp.codec.treeToValue(jsonObject, ListTransactionsSuccessResponse::class.java)
NwcMethod.GET_BALANCE -> jp.codec.treeToValue(jsonObject, GetBalanceSuccessResponse::class.java)
NwcMethod.GET_INFO -> jp.codec.treeToValue(jsonObject, GetInfoSuccessResponse::class.java)
NwcMethod.GET_BUDGET -> jp.codec.treeToValue(jsonObject, GetBudgetSuccessResponse::class.java)
NwcMethod.SIGN_MESSAGE -> jp.codec.treeToValue(jsonObject, SignMessageSuccessResponse::class.java)
NwcMethod.CREATE_CONNECTION -> jp.codec.treeToValue(jsonObject, CreateConnectionSuccessResponse::class.java)
NwcMethod.MAKE_HOLD_INVOICE -> jp.codec.treeToValue(jsonObject, MakeHoldInvoiceSuccessResponse::class.java)
NwcMethod.CANCEL_HOLD_INVOICE -> jp.codec.treeToValue(jsonObject, CancelHoldInvoiceSuccessResponse::class.java)
NwcMethod.SETTLE_HOLD_INVOICE -> jp.codec.treeToValue(jsonObject, SettleHoldInvoiceSuccessResponse::class.java)