diff --git a/src/CashuWallet.ts b/src/CashuWallet.ts index 890e4e7c..8953ab8d 100644 --- a/src/CashuWallet.ts +++ b/src/CashuWallet.ts @@ -16,6 +16,7 @@ import { SerializedBlindedMessage, SerializedBlindedSignature, SplitPayload, + Token, TokenEntry } from './model/types/index.js'; import { @@ -163,22 +164,27 @@ class CashuWallet { return this.payLnInvoice(invoice, proofs, undefined, counter); } /** - * Receive an encoded Cashu token - * @param encodedToken Cashu token + * Receive an encoded or raw Cashu token + * @param {(string|Token)} token - Cashu token * @param preference optional preference for splitting proofs into specific amounts * @param counter? optionally set counter to derive secret deterministically. CashuWallet class must be initialized with seed phrase to take effect * @returns New token with newly created proofs, token entries that had errors, and newKeys if they have changed */ async receive( - encodedToken: string, + token: string | Token, preference?: Array, counter?: number ): Promise { - const { token } = cleanToken(getDecodedToken(encodedToken)); + let decodedToken: Array; + if (typeof token === 'string') { + decodedToken = cleanToken(getDecodedToken(token)).token; + } else { + decodedToken = token.token; + } const tokenEntries: Array = []; const tokenEntriesWithError: Array = []; let newKeys: MintKeys | undefined; - for (const tokenEntry of token) { + for (const tokenEntry of decodedToken) { if (!tokenEntry?.proofs?.length) { continue; } diff --git a/src/index.ts b/src/index.ts index afe3b8a7..a321c040 100644 --- a/src/index.ts +++ b/src/index.ts @@ -3,7 +3,7 @@ import { CashuWallet } from './CashuWallet.js'; import { setGlobalRequestOptions } from './request.js'; import { generateNewMnemonic, deriveSeedFromMnemonic } from './secrets.js'; import { getEncodedToken, getDecodedToken, deriveKeysetId, decodeInvoice } from './utils.js'; -import { decode} from '@gandlaf21/bolt11-decode'; +import { decode } from '@gandlaf21/bolt11-decode'; export * from './model/types/index.js'; diff --git a/test/wallet.test.ts b/test/wallet.test.ts index 6bd0873d..7f0d0599 100644 --- a/test/wallet.test.ts +++ b/test/wallet.test.ts @@ -2,6 +2,7 @@ import { decode } from '@gandlaf21/bolt11-decode'; import nock from 'nock'; import { CashuMint } from '../src/CashuMint.js'; import { CashuWallet } from '../src/CashuWallet.js'; +import { cleanToken, getDecodedToken } from '../src/utils.js'; const dummyKeysResp = { 1: '02f970b6ee058705c0dddc4313721cffb7efd3d142d96ea8e01d31c2b2ff09f181' }; const mintUrl = 'https://legend.lnbits.com/cashu/api/v1/4gr9Xcmz3XEkUNwiBiQGoC'; @@ -35,7 +36,7 @@ describe('test fees', () => { describe('receive', () => { const tokenInput = 'eyJwcm9vZnMiOlt7ImlkIjoiL3VZQi82d1duWWtVIiwiYW1vdW50IjoxLCJzZWNyZXQiOiJBZmtRYlJYQUc1UU1tT3ArbG9vRzQ2OXBZWTdiaStqbEcxRXRDT2tIa2hZPSIsIkMiOiIwMmY4NWRkODRiMGY4NDE4NDM2NmNiNjkxNDYxMDZhZjdjMGYyNmYyZWUwYWQyODdhM2U1ZmE4NTI1MjhiYjI5ZGYifV0sIm1pbnRzIjpbeyJ1cmwiOiJodHRwczovL2xlZ2VuZC5sbmJpdHMuY29tL2Nhc2h1L2FwaS92MS80Z3I5WGNtejNYRWtVTndpQmlRR29DIiwiaWRzIjpbIi91WUIvNndXbllrVSJdfV19'; - test('test receive', async () => { + test('test receive encoded token', async () => { nock(mintUrl) .post('/split') .reply(200, { @@ -61,6 +62,35 @@ describe('receive', () => { expect(/[A-Za-z0-9+/]{43}=/.test(t.token[0].proofs[0].secret)).toBe(true); expect(tokensWithErrors).toBe(undefined); }); + + test('test receive raw token', async () => { + const decodedInput = cleanToken(getDecodedToken(tokenInput)); + + nock(mintUrl) + .post('/split') + .reply(200, { + promises: [ + { + id: 'z32vUtKgNCm1', + amount: 1, + C_: '021179b095a67380ab3285424b563b7aab9818bd38068e1930641b3dceb364d422' + } + ] + }); + const wallet = new CashuWallet(mint); + + const { token: t, tokensWithErrors } = await wallet.receive(decodedInput); + + expect(t.token).toHaveLength(1); + expect(t.token[0].proofs).toHaveLength(1); + expect(t.token[0]).toMatchObject({ + proofs: [{ amount: 1, id: 'z32vUtKgNCm1' }], + mint: 'https://legend.lnbits.com/cashu/api/v1/4gr9Xcmz3XEkUNwiBiQGoC' + }); + expect(/[0-9a-f]{64}/.test(t.token[0].proofs[0].C)).toBe(true); + expect(/[A-Za-z0-9+/]{43}=/.test(t.token[0].proofs[0].secret)).toBe(true); + expect(tokensWithErrors).toBe(undefined); + }); test('test receive custom split', async () => { nock(mintUrl) .post('/split')