From e66bd24dcec6f91c59520e1101435d91ab9b92d5 Mon Sep 17 00:00:00 2001 From: CC Date: Thu, 21 May 2026 11:15:41 +0200 Subject: [PATCH] fix: use generic NUT-17 subscription kinds --- src/model/types/jsonrpc.ts | 10 +++++++- src/wallet/WalletEvents.ts | 6 +++-- test/consts.ts | 2 +- test/transport/WSConnection.test.ts | 30 +++++++++++++++++++--- test/wallet/WalletEvents.test.ts | 40 ++++++++++++++--------------- test/wallet/wallet.node.test.ts | 14 +++++----- 6 files changed, 68 insertions(+), 34 deletions(-) diff --git a/src/model/types/jsonrpc.ts b/src/model/types/jsonrpc.ts index f45cdbc91..62dc25113 100644 --- a/src/model/types/jsonrpc.ts +++ b/src/model/types/jsonrpc.ts @@ -1,4 +1,12 @@ -export type RpcSubKinds = 'bolt11_mint_quote' | 'bolt11_melt_quote' | 'proof_state'; +export type RpcSubKinds = RpcSubKind | DeprecatedRpcSubKind; + +export type RpcSubKind = 'mint_quote' | 'melt_quote' | 'proof_state'; + +/** + * @deprecated NUT-17 subscription kinds are method-independent now. + * Remove these aliases once old bolt11-specific subscription kinds are no longer needed. + */ +export type DeprecatedRpcSubKind = 'bolt11_mint_quote' | 'bolt11_melt_quote'; export type RpcSubId = string | number | null; export type JsonRpcParams = { diff --git a/src/wallet/WalletEvents.ts b/src/wallet/WalletEvents.ts index 99021a56d..630363969 100644 --- a/src/wallet/WalletEvents.ts +++ b/src/wallet/WalletEvents.ts @@ -244,7 +244,8 @@ export class WalletEvents { if (!ws) throw new Error('Failed to establish WebSocket connection.'); const uniq = Array.from(new Set(ids)); - const subId = ws.createSubscription({ kind: 'bolt11_mint_quote', filters: uniq }, cb, err); + // TODO: Remove the deprecated bolt11_* aliases once old NUT-17 subscription kinds are gone. + const subId = ws.createSubscription({ kind: 'mint_quote', filters: uniq }, cb, err); const cancel = () => ws.cancelSubscription(subId, cb); return this.withAbort(opts?.signal, cancel); } @@ -292,7 +293,8 @@ export class WalletEvents { if (!ws) throw new Error('Failed to establish WebSocket connection.'); const uniq = Array.from(new Set(ids)); - const subId = ws.createSubscription({ kind: 'bolt11_melt_quote', filters: uniq }, cb, err); + // TODO: Remove the deprecated bolt11_* aliases once old NUT-17 subscription kinds are gone. + const subId = ws.createSubscription({ kind: 'melt_quote', filters: uniq }, cb, err); const cancel = () => ws.cancelSubscription(subId, cb); return this.withAbort(opts?.signal, cancel); } diff --git a/test/consts.ts b/test/consts.ts index 161900c9a..c3ff5c285 100644 --- a/test/consts.ts +++ b/test/consts.ts @@ -1,7 +1,7 @@ import { KeyChain, KeyChainCache, MintKeys, MintKeyset } from '../src'; export const MINTINFORESP = JSON.parse( - '{"name":"Testnut mint","pubkey":"0296d0aa13b6a31cf0cd974249f28c7b7176d7274712c95a41c7d8066d3f29d679","version":"Nutshell/0.16.3","description":"Mint for testing Cashu wallets","description_long":"This mint usually runs the latest main branch of the nutshell repository. It uses a FakeWallet, all your Lightning invoices will always be marked paid so that you can test minting and melting ecash via Lightning.","contact":[{"method":"email","info":"contact@me.com"},{"method":"twitter","info":"@me"},{"method":"nostr","info":"npub1337"}],"motd":"This is a message of the day field. You should display this field to your users if the content changes!","icon_url":"https://image.nostr.build/46ee47763c345d2cfa3317f042d332003f498ee281fb42808d47a7d3b9585911.png","time":1731684933,"nuts":{"4":{"methods":[{"method":"bolt11","unit":"sat","options":{"description":true}},{"method":"bolt11","unit":"usd","options":{"description":true}},{"method":"bolt11","unit":"eur","options":{"description":true}},{"method":"bolt12","unit":"sat","options":{"description":true}},{"method":"bolt12","unit":"usd","options":{"description":true}},{"method":"bolt12","unit":"eur","options":{"description":true}}],"disabled":false},"5":{"methods":[{"method":"bolt11","unit":"sat"},{"method":"bolt11","unit":"usd"},{"method":"bolt11","unit":"eur"},{"method":"bolt12","unit":"sat"},{"method":"bolt12","unit":"usd"},{"method":"bolt12","unit":"eur"}],"disabled":false},"7":{"supported":true},"8":{"supported":true},"9":{"supported":true},"10":{"supported":true},"11":{"supported":true},"12":{"supported":true},"14":{"supported":true},"17":{"supported":[{"method":"bolt11","unit":"sat","commands":["bolt11_melt_quote","proof_state","bolt11_mint_quote"]},{"method":"bolt11","unit":"usd","commands":["bolt11_melt_quote","proof_state","bolt11_mint_quote"]},{"method":"bolt11","unit":"eur","commands":["bolt11_melt_quote","proof_state","bolt11_mint_quote"]},{"method":"bolt12","unit":"sat","commands":["bolt12_melt_quote","proof_state","bolt12_mint_quote"]},{"method":"bolt12","unit":"usd","commands":["bolt12_melt_quote","proof_state","bolt12_mint_quote"]},{"method":"bolt12","unit":"eur","commands":["bolt12_melt_quote","proof_state","bolt12_mint_quote"]}]}}}', + '{"name":"Testnut mint","pubkey":"0296d0aa13b6a31cf0cd974249f28c7b7176d7274712c95a41c7d8066d3f29d679","version":"Nutshell/0.16.3","description":"Mint for testing Cashu wallets","description_long":"This mint usually runs the latest main branch of the nutshell repository. It uses a FakeWallet, all your Lightning invoices will always be marked paid so that you can test minting and melting ecash via Lightning.","contact":[{"method":"email","info":"contact@me.com"},{"method":"twitter","info":"@me"},{"method":"nostr","info":"npub1337"}],"motd":"This is a message of the day field. You should display this field to your users if the content changes!","icon_url":"https://image.nostr.build/46ee47763c345d2cfa3317f042d332003f498ee281fb42808d47a7d3b9585911.png","time":1731684933,"nuts":{"4":{"methods":[{"method":"bolt11","unit":"sat","options":{"description":true}},{"method":"bolt11","unit":"usd","options":{"description":true}},{"method":"bolt11","unit":"eur","options":{"description":true}},{"method":"bolt12","unit":"sat","options":{"description":true}},{"method":"bolt12","unit":"usd","options":{"description":true}},{"method":"bolt12","unit":"eur","options":{"description":true}}],"disabled":false},"5":{"methods":[{"method":"bolt11","unit":"sat"},{"method":"bolt11","unit":"usd"},{"method":"bolt11","unit":"eur"},{"method":"bolt12","unit":"sat"},{"method":"bolt12","unit":"usd"},{"method":"bolt12","unit":"eur"}],"disabled":false},"7":{"supported":true},"8":{"supported":true},"9":{"supported":true},"10":{"supported":true},"11":{"supported":true},"12":{"supported":true},"14":{"supported":true},"17":{"supported":[{"method":"bolt11","unit":"sat","commands":["melt_quote","proof_state","mint_quote"]},{"method":"bolt11","unit":"usd","commands":["melt_quote","proof_state","mint_quote"]},{"method":"bolt11","unit":"eur","commands":["melt_quote","proof_state","mint_quote"]},{"method":"bolt12","unit":"sat","commands":["melt_quote","proof_state","mint_quote"]},{"method":"bolt12","unit":"usd","commands":["melt_quote","proof_state","mint_quote"]},{"method":"bolt12","unit":"eur","commands":["melt_quote","proof_state","mint_quote"]}]}}}', ); /** diff --git a/test/transport/WSConnection.test.ts b/test/transport/WSConnection.test.ts index 231f4b11f..39616ba12 100644 --- a/test/transport/WSConnection.test.ts +++ b/test/transport/WSConnection.test.ts @@ -16,6 +16,30 @@ describe('testing WSConnection', () => { expect(connectionSpy).toHaveBeenCalled(); }); test('requesting subscription', async () => { + const message = (await new Promise(async (res) => { + server.on('connection', (socket) => { + socket.on('message', (m) => { + res(m.toString()); + }); + }); + const conn = new WSConnection(fakeUrl); + await conn.connect(); + + const callback = vi.fn(); + const errorCallback = vi.fn(); + conn.createSubscription( + { kind: 'mint_quote', filters: ['12345'] }, + callback, + errorCallback, + ); + })) as string; + expect(JSON.parse(message)).toMatchObject({ + jsonrpc: '2.0', + method: 'subscribe', + params: { kind: 'mint_quote', filters: ['12345'] }, + }); + }); + test('keeps deprecated bolt11 subscription kinds working', async () => { const message = (await new Promise(async (res) => { server.on('connection', (socket) => { socket.on('message', (m) => { @@ -45,7 +69,7 @@ describe('testing WSConnection', () => { const errorCallback = vi.fn(); expect(() => { conn.createSubscription( - { kind: 'bolt11_mint_quote', filters: ['123'] }, + { kind: 'mint_quote', filters: ['123'] }, callback, errorCallback, ); @@ -75,7 +99,7 @@ describe('testing WSConnection', () => { } }); subId = conn.createSubscription( - { kind: 'bolt11_mint_quote', filters: ['123'] }, + { kind: 'mint_quote', filters: ['123'] }, callback, errorCallback, ); @@ -117,7 +141,7 @@ describe('testing WSConnection', () => { }); const errorCallback = vi.fn(); conn.createSubscription( - { kind: 'bolt11_mint_quote', filters: ['123'] }, + { kind: 'mint_quote', filters: ['123'] }, callback, errorCallback, ); diff --git a/test/wallet/WalletEvents.test.ts b/test/wallet/WalletEvents.test.ts index 79acadc81..cf0e3a3da 100644 --- a/test/wallet/WalletEvents.test.ts +++ b/test/wallet/WalletEvents.test.ts @@ -34,7 +34,7 @@ class MockWS { * Deliver an update payload to matching subscribers for a kind. */ emit( - kind: 'bolt11_mint_quote' | 'bolt11_melt_quote', + kind: 'mint_quote' | 'melt_quote', payload: { quote: string; [k: string]: any }, ) { for (const { kind: k, filters, cb } of this.subs.values()) { @@ -128,7 +128,7 @@ describe('WalletEvents', () => { const canceller = await events.mintQuoteUpdates(['a', 'b'], cb, err); const ws = mock.mint.webSocketConnection!; - ws.emit('bolt11_mint_quote', { quote: 'a', state: 'PAID' }); + ws.emit('mint_quote', { quote: 'a', state: 'PAID' }); expect(cb).toHaveBeenCalledWith(expect.objectContaining({ quote: 'a' })); expect(typeof canceller).toBe('function'); @@ -140,10 +140,10 @@ describe('WalletEvents', () => { await events.mintQuotePaid('x', cb, err); const ws = mock.mint.webSocketConnection!; - ws.emit('bolt11_mint_quote', { quote: 'x', state: 'UNPAID' }); + ws.emit('mint_quote', { quote: 'x', state: 'UNPAID' }); expect(cb).not.toHaveBeenCalled(); - ws.emit('bolt11_mint_quote', { quote: 'x', state: 'PAID' }); + ws.emit('mint_quote', { quote: 'x', state: 'PAID' }); expect(cb).toHaveBeenCalledWith(expect.objectContaining({ quote: 'x' })); }); @@ -153,7 +153,7 @@ describe('WalletEvents', () => { await events.meltQuoteUpdates(['m1'], cb, err); const ws = mock.mint.webSocketConnection!; - ws.emit('bolt11_melt_quote', { quote: 'm1', state: 'PAID' }); + ws.emit('melt_quote', { quote: 'm1', state: 'PAID' }); expect(cb).toHaveBeenCalledWith(expect.objectContaining({ quote: 'm1' })); }); @@ -163,10 +163,10 @@ describe('WalletEvents', () => { await events.meltQuotePaid('m2', cb, err); const ws = mock.mint.webSocketConnection!; - ws.emit('bolt11_melt_quote', { quote: 'm2', state: 'UNPAID' }); + ws.emit('melt_quote', { quote: 'm2', state: 'UNPAID' }); expect(cb).not.toHaveBeenCalled(); - ws.emit('bolt11_melt_quote', { quote: 'm2', state: 'PAID' }); + ws.emit('melt_quote', { quote: 'm2', state: 'PAID' }); expect(cb).toHaveBeenCalledWith(expect.objectContaining({ quote: 'm2' })); }); @@ -189,7 +189,7 @@ describe('WalletEvents', () => { const p = events.onceMintPaid('q1'); await flushMicrotasks(); // wait for subscription to be created const ws = mock.mint.webSocketConnection!; - ws.emit('bolt11_mint_quote', { quote: 'q1', state: 'PAID', amount: 123 }); + ws.emit('mint_quote', { quote: 'q1', state: 'PAID', amount: 123 }); const res = await p; expect(res).toMatchObject({ quote: 'q1', amount: 123 }); await flushMicrotasks(); @@ -221,7 +221,7 @@ describe('WalletEvents', () => { const p = events.onceMintPaid('q4'); await flushMicrotasks(); // wait for subscription const ws = mock.mint.webSocketConnection!; - ws.fail('bolt11_mint_quote', new Error('boom')); + ws.fail('mint_quote', new Error('boom')); await expect(p).rejects.toThrow('boom'); await flushMicrotasks(); expect(ws.cancelSubscription).toHaveBeenCalled(); @@ -233,7 +233,7 @@ describe('WalletEvents', () => { const p = events.onceAnyMintPaid(['a', 'b', 'c']); await flushMicrotasks(); // subs ready const ws = mock.mint.webSocketConnection!; - ws.emit('bolt11_mint_quote', { quote: 'b', state: 'PAID', amount: 42 }); + ws.emit('mint_quote', { quote: 'b', state: 'PAID', amount: 42 }); const res = await p; expect(res).toMatchObject({ id: 'b', quote: expect.objectContaining({ amount: 42 }) }); await flushMicrotasks(); @@ -269,7 +269,7 @@ describe('WalletEvents', () => { const p = events.onceAnyMintPaid(['f1', 'f2', 'f3'], { failOnError: true }); await flushMicrotasks(); // subs ready const ws = mock.mint.webSocketConnection!; - ws.fail('bolt11_mint_quote', new Error('bad')); + ws.fail('mint_quote', new Error('bad')); await expect(p).rejects.toThrow(/bad/); await flushMicrotasks(); expect(ws.cancelSubscription.mock.calls.length).toBeGreaterThanOrEqual(3); @@ -279,8 +279,8 @@ describe('WalletEvents', () => { const p = events.onceAnyMintPaid(['dup', 'dup', 'other']); await flushMicrotasks(); // subs ready const ws = mock.mint.webSocketConnection!; - expect(ws.count('bolt11_mint_quote')).toBe(2); // dup + other - ws.emit('bolt11_mint_quote', { quote: 'dup', state: 'PAID' }); + expect(ws.count('mint_quote')).toBe(2); // dup + other + ws.emit('mint_quote', { quote: 'dup', state: 'PAID' }); const res = await p; expect(res.id).toBe('dup'); }); @@ -292,8 +292,8 @@ describe('WalletEvents', () => { const ws = mock.mint.webSocketConnection!; // Our WS mock broadcasts the same error to all subs per call; the first call // already empties the set. So assert we get *a* JSON-stringified object. - ws.fail('bolt11_mint_quote', { code: 1, msg: 'x' } as any); - ws.fail('bolt11_mint_quote', { code: 2, msg: 'y' } as any); + ws.fail('mint_quote', { code: 1, msg: 'x' } as any); + ws.fail('mint_quote', { code: 2, msg: 'y' } as any); await expect(p).rejects.toThrow(/"code":\s*\d/); }); @@ -302,7 +302,7 @@ describe('WalletEvents', () => { const p = events.onceMintPaid('bigobj'); await flushMicrotasks(); // sub ready const ws = mock.mint.webSocketConnection!; - ws.fail('bolt11_mint_quote', { n: 10n } as any); + ws.fail('mint_quote', { n: 10n } as any); await expect(p).rejects.toThrow(/\[object Object\]/); }); @@ -311,7 +311,7 @@ describe('WalletEvents', () => { await flushMicrotasks(); // sub ready const ws = mock.mint.webSocketConnection!; - ws.fail('bolt11_mint_quote', 10n); + ws.fail('mint_quote', 10n); // With current normalizeError/safeStringify, primitives fall back to // Object.prototype.toString => "[object BigInt]". @@ -324,7 +324,7 @@ describe('WalletEvents', () => { const p = events.onceMeltPaid('m1'); await flushMicrotasks(); // sub ready const ws = mock.mint.webSocketConnection!; - ws.emit('bolt11_melt_quote', { quote: 'm1', state: 'PAID', amount: 7 }); + ws.emit('melt_quote', { quote: 'm1', state: 'PAID', amount: 7 }); const res = await p; expect(res).toMatchObject({ quote: 'm1', amount: 7 }); await flushMicrotasks(); @@ -360,7 +360,7 @@ describe('WalletEvents', () => { const p = events.onceMeltPaid('m-error'); await flushMicrotasks(); // sub ready const ws = mock.mint.webSocketConnection!; - ws.fail('bolt11_melt_quote', new Error('melt-boom')); + ws.fail('melt_quote', new Error('melt-boom')); await expect(p).rejects.toThrow('melt-boom'); await flushMicrotasks(); expect(ws.cancelSubscription).toHaveBeenCalled(); @@ -372,7 +372,7 @@ describe('WalletEvents', () => { const p = events.onceMeltPaid('m-ok', { signal: ac.signal }); await flushMicrotasks(); // sub ready const ws = mock.mint.webSocketConnection!; - ws.emit('bolt11_melt_quote', { quote: 'm-ok', state: 'PAID', amount: 1 }); + ws.emit('melt_quote', { quote: 'm-ok', state: 'PAID', amount: 1 }); await expect(p).resolves.toMatchObject({ quote: 'm-ok' }); await flushMicrotasks(); expect(ws.cancelSubscription).toHaveBeenCalled(); diff --git a/test/wallet/wallet.node.test.ts b/test/wallet/wallet.node.test.ts index f47737bf6..e1982ffc0 100644 --- a/test/wallet/wallet.node.test.ts +++ b/test/wallet/wallet.node.test.ts @@ -37,7 +37,7 @@ import { MINTCACHE } from '../consts'; injectWebSocketImpl(WebSocket); const mintInfoResp = JSON.parse( - '{"name":"Testnut mint","pubkey":"0296d0aa13b6a31cf0cd974249f28c7b7176d7274712c95a41c7d8066d3f29d679","version":"Nutshell/0.16.3","description":"Mint for testing Cashu wallets","description_long":"This mint usually runs the latest main branch of the nutshell repository. It uses a FakeWallet, all your Lightning invoices will always be marked paid so that you can test minting and melting ecash via Lightning.","contact":[{"method":"email","info":"contact@me.com"},{"method":"twitter","info":"@me"},{"method":"nostr","info":"npub1337"}],"motd":"This is a message of the day field. You should display this field to your users if the content changes!","icon_url":"https://image.nostr.build/46ee47763c345d2cfa3317f042d332003f498ee281fb42808d47a7d3b9585911.png","time":1731684933,"nuts":{"4":{"methods":[{"method":"bolt11","unit":"sat","description":true},{"method":"bolt11","unit":"usd","description":true},{"method":"bolt11","unit":"eur","description":true}],"disabled":false},"5":{"methods":[{"method":"bolt11","unit":"sat"},{"method":"bolt11","unit":"usd"},{"method":"bolt11","unit":"eur"}],"disabled":false},"7":{"supported":true},"8":{"supported":true},"9":{"supported":true},"10":{"supported":true},"11":{"supported":true},"12":{"supported":true},"14":{"supported":true},"17":{"supported":[{"method":"bolt11","unit":"sat","commands":["bolt11_melt_quote","proof_state","bolt11_mint_quote"]},{"method":"bolt11","unit":"usd","commands":["bolt11_melt_quote","proof_state","bolt11_mint_quote"]},{"method":"bolt11","unit":"eur","commands":["bolt11_melt_quote","proof_state","bolt11_mint_quote"]}]}}}', + '{"name":"Testnut mint","pubkey":"0296d0aa13b6a31cf0cd974249f28c7b7176d7274712c95a41c7d8066d3f29d679","version":"Nutshell/0.16.3","description":"Mint for testing Cashu wallets","description_long":"This mint usually runs the latest main branch of the nutshell repository. It uses a FakeWallet, all your Lightning invoices will always be marked paid so that you can test minting and melting ecash via Lightning.","contact":[{"method":"email","info":"contact@me.com"},{"method":"twitter","info":"@me"},{"method":"nostr","info":"npub1337"}],"motd":"This is a message of the day field. You should display this field to your users if the content changes!","icon_url":"https://image.nostr.build/46ee47763c345d2cfa3317f042d332003f498ee281fb42808d47a7d3b9585911.png","time":1731684933,"nuts":{"4":{"methods":[{"method":"bolt11","unit":"sat","description":true},{"method":"bolt11","unit":"usd","description":true},{"method":"bolt11","unit":"eur","description":true}],"disabled":false},"5":{"methods":[{"method":"bolt11","unit":"sat"},{"method":"bolt11","unit":"usd"},{"method":"bolt11","unit":"eur"}],"disabled":false},"7":{"supported":true},"8":{"supported":true},"9":{"supported":true},"10":{"supported":true},"11":{"supported":true},"12":{"supported":true},"14":{"supported":true},"17":{"supported":[{"method":"bolt11","unit":"sat","commands":["melt_quote","proof_state","mint_quote"]},{"method":"bolt11","unit":"usd","commands":["melt_quote","proof_state","mint_quote"]},{"method":"bolt11","unit":"eur","commands":["melt_quote","proof_state","mint_quote"]}]}}}', ); const dummyKeysResp = { keysets: [ @@ -335,17 +335,17 @@ describe('test info', () => { { method: 'bolt11', unit: 'sat', - commands: ['bolt11_melt_quote', 'proof_state', 'bolt11_mint_quote'], + commands: ['melt_quote', 'proof_state', 'mint_quote'], }, { method: 'bolt11', unit: 'usd', - commands: ['bolt11_melt_quote', 'proof_state', 'bolt11_mint_quote'], + commands: ['melt_quote', 'proof_state', 'mint_quote'], }, { method: 'bolt11', unit: 'eur', - commands: ['bolt11_melt_quote', 'proof_state', 'bolt11_mint_quote'], + commands: ['melt_quote', 'proof_state', 'mint_quote'], }, ], }); @@ -367,7 +367,7 @@ describe('test info', () => { test('test info with deprecated contact field', async () => { // mintInfoRespDeprecated is the same as mintInfoResp but with the contact field in the old format const mintInfoRespDeprecated = JSON.parse( - '{"name":"Testnut mint","pubkey":"0296d0aa13b6a31cf0cd974249f28c7b7176d7274712c95a41c7d8066d3f29d679","version":"Nutshell/0.16.3","description":"Mint for testing Cashu wallets","description_long":"This mint usually runs the latest main branch of the nutshell repository. All your Lightning invoices will always be marked paid so that you can test minting and melting ecash via Lightning.","contact":[["email","contact@me.com"],["twitter","@me"],["nostr","npub1337"]],"motd":"This is a message of the day field. You should display this field to your users if the content changes!","nuts":{"4":{"methods":[{"method":"bolt11","unit":"sat"},{"method":"bolt11","unit":"usd"}],"disabled":false},"5":{"methods":[{"method":"bolt11","unit":"sat"},{"method":"bolt11","unit":"usd"}],"disabled":false},"7":{"supported":true},"8":{"supported":true},"9":{"supported":true},"10":{"supported":true},"11":{"supported":true},"12":{"supported":true},"17":[{"method":"bolt11","unit":"sat","commands":["bolt11_melt_quote","proof_state","bolt11_mint_quote"]},{"method":"bolt11","unit":"usd","commands":["bolt11_melt_quote","proof_state","bolt11_mint_quote"]}]}}', + '{"name":"Testnut mint","pubkey":"0296d0aa13b6a31cf0cd974249f28c7b7176d7274712c95a41c7d8066d3f29d679","version":"Nutshell/0.16.3","description":"Mint for testing Cashu wallets","description_long":"This mint usually runs the latest main branch of the nutshell repository. All your Lightning invoices will always be marked paid so that you can test minting and melting ecash via Lightning.","contact":[["email","contact@me.com"],["twitter","@me"],["nostr","npub1337"]],"motd":"This is a message of the day field. You should display this field to your users if the content changes!","nuts":{"4":{"methods":[{"method":"bolt11","unit":"sat"},{"method":"bolt11","unit":"usd"}],"disabled":false},"5":{"methods":[{"method":"bolt11","unit":"sat"},{"method":"bolt11","unit":"usd"}],"disabled":false},"7":{"supported":true},"8":{"supported":true},"9":{"supported":true},"10":{"supported":true},"11":{"supported":true},"12":{"supported":true},"17":[{"method":"bolt11","unit":"sat","commands":["melt_quote","proof_state","mint_quote"]},{"method":"bolt11","unit":"usd","commands":["melt_quote","proof_state","mint_quote"]}]}}', ); server.use( http.get(mintUrl + '/v1/info', () => { @@ -2226,7 +2226,7 @@ describe('WebSocket Updates', () => { }); describe('multi mint', async () => { const mintInfo = JSON.parse( - '{"name":"Cashu mint","pubkey":"023ef9a3cda9945d5e784e478d3bd0c8d39726bcb3ca11098fe685a95d3f889d28","version":"Nutshell/0.16.4","contact":[],"time":1737973290,"nuts":{"4":{"methods":[{"method":"bolt11","unit":"sat","description":true}],"disabled":false},"5":{"methods":[{"method":"bolt11","unit":"sat"}],"disabled":false},"7":{"supported":true},"8":{"supported":true},"9":{"supported":true},"10":{"supported":true},"11":{"supported":true},"12":{"supported":true},"14":{"supported":true},"20":{"supported":true},"15":{"methods":[{"method":"bolt11","unit":"sat"}]},"17":{"supported":[{"method":"bolt11","unit":"sat","commands":["bolt11_melt_quote","proof_state","bolt11_mint_quote"]}]}}}', + '{"name":"Cashu mint","pubkey":"023ef9a3cda9945d5e784e478d3bd0c8d39726bcb3ca11098fe685a95d3f889d28","version":"Nutshell/0.16.4","contact":[],"time":1737973290,"nuts":{"4":{"methods":[{"method":"bolt11","unit":"sat","description":true}],"disabled":false},"5":{"methods":[{"method":"bolt11","unit":"sat"}],"disabled":false},"7":{"supported":true},"8":{"supported":true},"9":{"supported":true},"10":{"supported":true},"11":{"supported":true},"12":{"supported":true},"14":{"supported":true},"20":{"supported":true},"15":{"methods":[{"method":"bolt11","unit":"sat"}]},"17":{"supported":[{"method":"bolt11","unit":"sat","commands":["melt_quote","proof_state","mint_quote"]}]}}}', ); test('multi path melt quotes', async () => { server.use( @@ -2601,7 +2601,7 @@ describe('restore', () => { describe('Blind Authentication', () => { test('Mint Info', async () => { const mintInfo = JSON.parse( - '{"name":"Testnut auth mint","pubkey":"020fbbac41bcbd8d9b5353ee137baf45e0b21ccf33c0721a09bc7cbec495b156a2","version":"Nutshell/0.16.4","description":"","description_long":"","contact":[{"method":"email","info":"contact@me.com"},{"method":"twitter","info":"@me"},{"method":"nostr","info":"npub1337"}],"motd":"","icon_url":"","time":1738594208,"nuts":{"4":{"methods":[{"method":"bolt11","unit":"sat","description":true},{"method":"bolt11","unit":"usd","description":true},{"method":"bolt11","unit":"eur","description":true}],"disabled":false},"5":{"methods":[{"method":"bolt11","unit":"sat"},{"method":"bolt11","unit":"usd"},{"method":"bolt11","unit":"eur"}],"disabled":false},"7":{"supported":true},"8":{"supported":true},"9":{"supported":true},"10":{"supported":true},"11":{"supported":true},"12":{"supported":true},"14":{"supported":true},"20":{"supported":true},"17":{"supported":[{"method":"bolt11","unit":"sat","commands":["bolt11_melt_quote","proof_state","bolt11_mint_quote"]},{"method":"bolt11","unit":"usd","commands":["bolt11_melt_quote","proof_state","bolt11_mint_quote"]},{"method":"bolt11","unit":"eur","commands":["bolt11_melt_quote","proof_state","bolt11_mint_quote"]}]},"21":{"openid_discovery":"https://oicd.8333.space/realms/nutshell/.well-known/openid-configuration","client_id":"cashu-client","protected_endpoints":[{"method":"POST","path":"/v1/auth/blind/mint"}]},"22":{"bat_max_mint":100,"protected_endpoints":[{"method":"POST","path":"/v1/swap"},{"method":"POST","path":"/v1/mint/quote/bolt11"},{"method":"POST","path":"/v1/mint/bolt11"},{"method":"POST","path":"/v1/melt/bolt11"}]}}}', + '{"name":"Testnut auth mint","pubkey":"020fbbac41bcbd8d9b5353ee137baf45e0b21ccf33c0721a09bc7cbec495b156a2","version":"Nutshell/0.16.4","description":"","description_long":"","contact":[{"method":"email","info":"contact@me.com"},{"method":"twitter","info":"@me"},{"method":"nostr","info":"npub1337"}],"motd":"","icon_url":"","time":1738594208,"nuts":{"4":{"methods":[{"method":"bolt11","unit":"sat","description":true},{"method":"bolt11","unit":"usd","description":true},{"method":"bolt11","unit":"eur","description":true}],"disabled":false},"5":{"methods":[{"method":"bolt11","unit":"sat"},{"method":"bolt11","unit":"usd"},{"method":"bolt11","unit":"eur"}],"disabled":false},"7":{"supported":true},"8":{"supported":true},"9":{"supported":true},"10":{"supported":true},"11":{"supported":true},"12":{"supported":true},"14":{"supported":true},"20":{"supported":true},"17":{"supported":[{"method":"bolt11","unit":"sat","commands":["melt_quote","proof_state","mint_quote"]},{"method":"bolt11","unit":"usd","commands":["melt_quote","proof_state","mint_quote"]},{"method":"bolt11","unit":"eur","commands":["melt_quote","proof_state","mint_quote"]}]},"21":{"openid_discovery":"https://oicd.8333.space/realms/nutshell/.well-known/openid-configuration","client_id":"cashu-client","protected_endpoints":[{"method":"POST","path":"/v1/auth/blind/mint"}]},"22":{"bat_max_mint":100,"protected_endpoints":[{"method":"POST","path":"/v1/swap"},{"method":"POST","path":"/v1/mint/quote/bolt11"},{"method":"POST","path":"/v1/mint/bolt11"},{"method":"POST","path":"/v1/melt/bolt11"}]}}}', ); server.use( http.get(mintUrl + '/v1/info', () => {