diff --git a/ndk-wallet/package.json b/ndk-wallet/package.json index dc6c926e..16c2c376 100644 --- a/ndk-wallet/package.json +++ b/ndk-wallet/package.json @@ -38,7 +38,7 @@ }, "homepage": "https://github.com/nostr-dev-kit/ndk", "dependencies": { - "@cashu/cashu-ts": "1.0.0-rc.9", + "@cashu/cashu-ts": "1.1.0", "@getalby/sdk": "^3.6.1", "@nostr-dev-kit/ndk": "workspace:*", "debug": "^4.3.4", diff --git a/ndk-wallet/src/cashu/deposit.ts b/ndk-wallet/src/cashu/deposit.ts index 03c16030..1bd4b936 100644 --- a/ndk-wallet/src/cashu/deposit.ts +++ b/ndk-wallet/src/cashu/deposit.ts @@ -39,7 +39,7 @@ export class NDKCashuDeposit extends EventEmitter<{ } async start() { - const quote = await this._wallet.mintQuote(this.amount); + const quote = await this._wallet.createMintQuote(this.amount); d("created quote %s for %d %s", quote.quote, this.amount, this.mint); this.quoteId = quote.quote; diff --git a/ndk-wallet/src/cashu/history.ts b/ndk-wallet/src/cashu/history.ts index 887b5562..e6d82fad 100644 --- a/ndk-wallet/src/cashu/history.ts +++ b/ndk-wallet/src/cashu/history.ts @@ -11,6 +11,9 @@ const MARKERS = { DESTROYED: "destroyed", }; +/** + * This class represents a balance change in the wallet, whether money being added or removed. + */ export class NDKWalletChange extends NDKEvent { static MARKERS = MARKERS; diff --git a/ndk-wallet/src/cashu/pay/ln.ts b/ndk-wallet/src/cashu/pay/ln.ts index b9af24ca..8cab8b21 100644 --- a/ndk-wallet/src/cashu/pay/ln.ts +++ b/ndk-wallet/src/cashu/pay/ln.ts @@ -4,102 +4,165 @@ import type { NDKCashuPay } from "../pay"; import type { TokenSelection} from "../proofs"; import { rollOverProofs, chooseProofsForPr } from "../proofs"; import type { MintUrl } from "../mint/utils"; +import { NDKCashuWallet } from "../wallet"; -/** - * - * @param useMint Forces the payment to use a specific mint - * @returns - */ export async function payLn(this: NDKCashuPay, useMint?: MintUrl): Promise { const mintBalances = this.wallet.mintBalances; - const selections: TokenSelection[] = []; - let amount = this.getAmount(); + const amount = this.getAmount() / 1000; // convert msat to sat const data = this.info as LnPaymentInfo; if (!data.pr) throw new Error("missing pr"); - amount /= 1000; // convert msat to sat - - let paid = false; - let processingSelections = false; - const processSelections = async (resolve: (value: string) => void, reject: (err: string) => void) => { - processingSelections = true; - for (const selection of selections) { - const _wallet = new CashuWallet(new CashuMint(selection.mint)); - this.debug( - "paying LN invoice for %d sats (%d in fees) with proofs %o, %s", - selection.quote!.amount, - selection.quote!.fee_reserve, - selection.usedProofs, - data.pr - ); - try { - const result = await _wallet.payLnInvoice( - data.pr, - selection.usedProofs, - selection.quote - ); - this.debug("payment result: %o", result); - - if (result.isPaid && result.preimage) { - this.debug("payment successful"); - rollOverProofs(selection, result.change, selection.mint, this.wallet); - paid = true; - resolve(result.preimage); - } - } catch (e) { - this.debug("failed to pay with mint %s", e.message); - if (e?.message.match(/already spent/i)) { - this.debug("proofs already spent, rolling over"); - rollOverProofs(selection, [], selection.mint, this.wallet); - } - } - } - - if (!paid) { - reject("failed to pay with any mint"); - } - - processingSelections = false; - }; - return new Promise((resolve, reject) => { - let foundMint = false; + const eligibleMints = getEligibleMints(mintBalances, amount, useMint, this.debug); + + if (eligibleMints.length === 0) { + handleInsufficientBalance(amount, data.pr, this.wallet, this.debug, reject); + return; + } - for (const [mint, balance] of Object.entries(mintBalances)) { - if (useMint && mint !== useMint) continue; + attemptPaymentWithEligibleMints(eligibleMints, data.pr, amount, this.wallet, this.debug, resolve, reject); + }); +} +function getEligibleMints( + mintBalances: Record, + amount: number, + useMint: MintUrl | undefined, + debug: NDKCashuPay['debug'] +): string[] { + return Object.entries(mintBalances) + .filter(([mint, balance]) => { + if (useMint && mint !== useMint) return false; if (balance < amount) { - this.debug("mint %s has insufficient balance %d", mint, balance, amount); - - if (useMint) { - reject(`insufficient balance in mint ${mint} (${balance} < ${amount})`); - return; - } - - continue; + debug("mint %s has insufficient balance %d", mint, balance, amount); + return false; } + return true; + }) + .map(([mint]) => mint); +} - foundMint = true; +function handleInsufficientBalance( + amount: number, + pr: string, + wallet: NDKCashuPay['wallet'], + debug: NDKCashuPay['debug'], + reject: (reason: string) => void +): void { + wallet.emit("insufficient_balance", {amount, pr}); + debug("no mint with sufficient balance found"); + reject("no mint with sufficient balance found"); +} - chooseProofsForPr(data.pr, mint, this.wallet).then(async (result) => { +async function attemptPaymentWithEligibleMints( + eligibleMints: string[], + pr: string, + amount: number, + wallet: NDKCashuPay['wallet'], + debug: NDKCashuPay['debug'], + resolve: (value: string) => void, + reject: (reason: string) => void +): Promise { + const TIMEOUT = 10000; // 10 seconds timeout + const selections: TokenSelection[] = []; + + const selectionPromises = eligibleMints.map(mint => + chooseProofsForPr(pr, mint, wallet) + .then(result => { if (result) { - this.debug("successfully chose proofs for mint %s", mint); + debug("Successfully chose proofs for mint %s", mint); selections.push(result); - if (!processingSelections) { - this.debug("processing selections"); - await processSelections(resolve, reject); - } } - }); + return result; + }) + .catch(error => { + debug("Error choosing proofs for mint %s: %s", mint, error); + return null; + }) + ); + + try { + await Promise.race([ + Promise.all(selectionPromises), + new Promise((_, timeoutReject) => setTimeout(() => timeoutReject(new Error("Timeout")), TIMEOUT)) + ]); + } catch (error) { + debug("Timed out while choosing proofs: %s", error); + } + + if (selections.length === 0) { + reject("Failed to choose proofs for any mint"); + return; + } + + // Sort selections by fee reserve (lower is better) + selections.sort((a, b) => (a.quote?.fee_reserve ?? 0) - (b.quote?.fee_reserve ?? 0)); + + for (const selection of selections) { + try { + const result = await executePayment(selection, pr, wallet, debug); + if (result) { + resolve(result); + return; + } + } catch (error) { + debug("Failed to execute payment for mint %s: %s", selection.mint, error); } + } - this.debug({foundMint}) + reject("Failed to pay with any mint"); +} + +/** + * Attempts to pay using a selected set of Cashu tokens. + * + * @param selection - The TokenSelection object containing the chosen proofs and quote for the payment. + * @param pr - The Lightning Network payment request (invoice) to pay. + * @param wallet - The NDKCashuPay wallet instance. + * @param debug - The debug function for logging. + * @returns A Promise that resolves to the payment preimage as a string if successful, or null if the payment fails. + * + * @throws Will throw an error if the payment fails due to network issues or other problems. + * + * This function performs the following steps: + * 1. Creates a new CashuWallet instance for the specific mint. + * 2. Attempts to pay the Lightning invoice using the selected proofs. + * 3. If successful, it rolls over any change proofs. + * 4. If the proofs are already spent, it rolls over the selection without change. + * 5. Logs the process and any errors for debugging purposes. + */ +async function executePayment( + selection: TokenSelection, + pr: string, + wallet: NDKCashuWallet, + debug: NDKCashuPay['debug'] +): Promise { + const _wallet = new CashuWallet(new CashuMint(selection.mint)); + debug( + "Attempting LN payment for %d sats (%d in fees) with proofs %o, %s", + selection.quote!.amount, + selection.quote!.fee_reserve, + selection.usedProofs, + pr + ); - if (!foundMint) { - this.wallet.emit("insufficient_balance", {amount, pr: data.pr}); - - this.debug("no mint with sufficient balance found"); - reject("no mint with sufficient balance found"); + try { + const result = await _wallet.payLnInvoice(pr, selection.usedProofs, selection.quote); + debug("Payment result: %o", result); + + if (result.isPaid && result.preimage) { + debug("Payment successful"); + rollOverProofs(selection, result.change, selection.mint, wallet); + return result.preimage; } - }); + } catch (e) { + debug("Failed to pay with mint %s", e.message); + if (e?.message.match(/already spent/i)) { + debug("Proofs already spent, rolling over"); + rollOverProofs(selection, [], selection.mint, wallet); + } + throw e; + } + + return null; } diff --git a/ndk-wallet/src/cashu/pay/nut.ts b/ndk-wallet/src/cashu/pay/nut.ts index 9f906f06..19b16b35 100644 --- a/ndk-wallet/src/cashu/pay/nut.ts +++ b/ndk-wallet/src/cashu/pay/nut.ts @@ -52,7 +52,7 @@ async function payNutWithMintTransfer( // get quotes from the mints the recipient has const quotesPromises = mints.map(async (mint) => { const wallet = new CashuWallet(new CashuMint(mint), { unit: pay.unit }); - const quote = await wallet.mintQuote(amount); + const quote = await wallet.createMintQuote(amount); return { quote, mint }; }); diff --git a/ndk-wallet/src/cashu/proofs.ts b/ndk-wallet/src/cashu/proofs.ts index b7ab73f6..b96cb2d1 100644 --- a/ndk-wallet/src/cashu/proofs.ts +++ b/ndk-wallet/src/cashu/proofs.ts @@ -28,7 +28,7 @@ export async function chooseProofsForPr( wallet: NDKCashuWallet ): Promise { const _wallet = new CashuWallet(new CashuMint(mint)); - const quote = await _wallet.meltQuote(pr); + const quote = await _wallet.createMeltQuote(pr); return chooseProofsForQuote(quote, wallet, mint); } @@ -135,7 +135,7 @@ export async function rollOverProofs( d( "adding to delete a token that was seen on relay %s %o", token.relay?.url, - token.onRelays + token.onRelays.map((r) => r.url) ); deleteEvent.tag(["e", token.id]); if (token.relay) relaySet?.addRelay(token.relay); diff --git a/ndk-wallet/src/cashu/token.ts b/ndk-wallet/src/cashu/token.ts index 0faaed22..5a7c647c 100644 --- a/ndk-wallet/src/cashu/token.ts +++ b/ndk-wallet/src/cashu/token.ts @@ -8,7 +8,6 @@ import { decrypt } from "./decrypt"; export function proofsTotalBalance(proofs: Proof[]): number { for (const proof of proofs) { - console.log("proof", proof.secret); if (proof.amount < 0) { throw new Error("proof amount is negative"); } diff --git a/ndk-wallet/src/cashu/wallet.ts b/ndk-wallet/src/cashu/wallet.ts index 9e6d202e..56a1cd47 100644 --- a/ndk-wallet/src/cashu/wallet.ts +++ b/ndk-wallet/src/cashu/wallet.ts @@ -176,7 +176,7 @@ export class NDKCashuWallet extends EventEmitter implements NDK } get name(): string | undefined { - return this.getPrivateTag("name"); + return this.getPrivateTag("name") ?? this.event.tagValue("name"); } get unit(): string { @@ -386,7 +386,6 @@ export class NDKCashuWallet extends EventEmitter implements NDK } public addToken(token: NDKCashuToken) { - console.trace("adding token", token.id, token.rawEvent()); if (!this.knownTokens.has(token.id)) { this.knownTokens.add(token.id); this.tokens.push(token); diff --git a/ndk-wallet/src/service/lifecycle/index.ts b/ndk-wallet/src/service/lifecycle/index.ts index 38aacc2c..b1b8a239 100644 --- a/ndk-wallet/src/service/lifecycle/index.ts +++ b/ndk-wallet/src/service/lifecycle/index.ts @@ -120,17 +120,8 @@ class NDKWalletLifecycle extends EventEmitter<{ } private eoseHandler() { - this.debug("Loaded wallets", { - defaultWallet: this.defaultWallet?.event?.rawEvent(), - wallets: Array.from(this.wallets.values()).map((w) => w.event?.rawEvent()), - }); this.eosed = true; - if (this.tokensSub) { - this.debug("WE ALREADY HAVE TOKENS SUB!!!"); - return; - } - // if we don't have a default wallet, choose the first one if there is one const firstWallet = Array.from(this.wallets.values())[0]; if (!this.defaultWallet && firstWallet) { @@ -152,14 +143,11 @@ class NDKWalletLifecycle extends EventEmitter<{ for (const wallet of this.wallets.values()) { if (!oldestWalletTimestamp || wallet.event.created_at! > oldestWalletTimestamp) { oldestWalletTimestamp = wallet.event.created_at!; - this.debug("oldest wallet timestamp", oldestWalletTimestamp); } this.emit("wallet", wallet); } - this.debug("oldest wallet timestamp", oldestWalletTimestamp, this.wallets.values()); - this.tokensSub = this.ndk.subscribe( [ { kinds: [NDKKind.CashuToken], authors: [this.user!.pubkey] }, diff --git a/ndk-wallet/src/service/lifecycle/token.ts b/ndk-wallet/src/service/lifecycle/token.ts index eb91476c..783ff7f8 100644 --- a/ndk-wallet/src/service/lifecycle/token.ts +++ b/ndk-wallet/src/service/lifecycle/token.ts @@ -4,8 +4,6 @@ import type NDKWalletLifecycle from "."; import type { NDKCashuWallet } from "../../cashu/wallet"; async function handleToken(this: NDKWalletLifecycle, event: NDKEvent, relay?: NDKRelay) { - this.debug("Received token event %s from %s", event.id, relay?.url); - if (this.knownTokens.has(event.id)) return; this.knownTokens.add(event.id); @@ -21,7 +19,6 @@ async function handleToken(this: NDKWalletLifecycle, event: NDKEvent, relay?: ND this.debug("no wallet found for token %s", token.id); this.orphanedTokens.set(token.id, token); } else { - this.debug("adding token %s to wallet %s", token.id, wallet.name); wallet.addToken(token); } } diff --git a/ndk/src/relay/pool/index.ts b/ndk/src/relay/pool/index.ts index cfe73462..2a8d1cc7 100644 --- a/ndk/src/relay/pool/index.ts +++ b/ndk/src/relay/pool/index.ts @@ -42,7 +42,7 @@ export class NDKPool extends EventEmitter<{ "relay:authed": (relay: NDKRelay) => void; }> { // TODO: This should probably be an LRU cache - public relays = new Map(); + private _relays = new Map(); public autoConnectRelays = new Set(); public blacklistRelayUrls: Set; private debug: debug.Debugger; @@ -61,13 +61,21 @@ export class NDKPool extends EventEmitter<{ super(); this.debug = debug ?? ndk.debug.extend("pool"); this.ndk = ndk; + this.relayUrls = relayUrls; - for (const relayUrl of relayUrls) { + this.blacklistRelayUrls = new Set(blacklistedRelayUrls); + } + + get relays() { + return this._relays; + } + + set relayUrls(urls: WebSocket["url"][]) { + this._relays.clear(); + for (const relayUrl of urls) { const relay = new NDKRelay(relayUrl, undefined, this.ndk); this.addRelay(relay, false); } - - this.blacklistRelayUrls = new Set(blacklistedRelayUrls); } set name(name: string) { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5cf97358..28119f83 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -353,8 +353,8 @@ importers: specifier: workspace:* version: link:../ndk svelte: - specifier: 5.0.0-next.260 - version: 5.0.0-next.260 + specifier: ^4.2.1 + version: 4.2.19 devDependencies: '@nostr-dev-kit/eslint-config-custom': specifier: workspace:* @@ -532,8 +532,8 @@ importers: ndk-wallet: dependencies: '@cashu/cashu-ts': - specifier: 1.0.0-rc.9 - version: 1.0.0-rc.9 + specifier: 1.1.0 + version: 1.1.0 '@getalby/sdk': specifier: ^3.6.1 version: 3.7.1(typescript@5.5.3) @@ -1470,8 +1470,8 @@ packages: '@braintree/sanitize-url@7.1.0': resolution: {integrity: sha512-o+UlMLt49RvtCASlOMW0AkHnabN9wR9rwCCherxO0yG4Npy34GkvrAqdXQvrhNs+jh+gkK8gB8Lf05qL/O7KWg==} - '@cashu/cashu-ts@1.0.0-rc.9': - resolution: {integrity: sha512-8tWKGi+0syV1Aqhz+UB5vQMhflMw+9zeb6LbeI3Q3ZsKs7u2SSZp5x+DVV9XLGFDCwFJ2pCnumYNMn8bY2iCVw==} + '@cashu/cashu-ts@1.1.0': + resolution: {integrity: sha512-zdMKOHx3l+gzCRbK2R+dPaui78Kq3f4C1pz+ya7polbpzqPGU+NlT3Y3V9uKjwLJUp1G0lumKKU0lj4/Ywczpg==} '@cashu/crypto@0.2.7': resolution: {integrity: sha512-1aaDfUjiHNXoJqg8nW+341TLWV9W28DsVNXJUKcHL0yAmwLs5+56SSnb8LLDJzPamLVoYL0U0bda91klAzptig==} @@ -2489,9 +2489,6 @@ packages: '@noble/curves@1.2.0': resolution: {integrity: sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==} - '@noble/curves@1.4.2': - resolution: {integrity: sha512-TavHr8qycMChk8UwMld0ZDRvatedkzWfH8IiaeGCfymOP5i0hSCozz9vHOL0nkwk7HRMlFnAiKpS2jrUmSybcw==} - '@noble/curves@1.6.0': resolution: {integrity: sha512-TlaHRXDehJuRNR9TfZDNQ45mMEd5dwUwmicsafcIX4SsNiqnCHKjE/1alYPd/lDRVhxdhUAlv8uEhMCI5zjIJQ==} engines: {node: ^14.21.3 || >=16} @@ -2504,10 +2501,6 @@ packages: resolution: {integrity: sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==} engines: {node: '>= 16'} - '@noble/hashes@1.4.0': - resolution: {integrity: sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==} - engines: {node: '>= 16'} - '@noble/hashes@1.5.0': resolution: {integrity: sha512-1j6kQFb7QRru7eKN3ZDvRcP13rugwdxZqCjbiAVZfIJwgj2A65UmT4TgARXGlXgnRkORLTDTrO19ZErt7+QXgA==} engines: {node: ^14.21.3 || >=16} @@ -3017,14 +3010,14 @@ packages: '@scure/bip32@1.3.1': resolution: {integrity: sha512-osvveYtyzdEVbt3OfwwXFr4P2iVBL5u1Q3q4ONBfDY/UpOuXmOlbgwc1xECEboY8wIays8Yt6onaWMUdUbfl0A==} - '@scure/bip32@1.4.0': - resolution: {integrity: sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg==} + '@scure/bip32@1.5.0': + resolution: {integrity: sha512-8EnFYkqEQdnkuGBVpCzKxyIwDCBLDVj3oiX0EKUFre/tOjL/Hqba1D6n/8RcmaQy4f95qQFrO2A8Sr6ybh4NRw==} '@scure/bip39@1.2.1': resolution: {integrity: sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg==} - '@scure/bip39@1.3.0': - resolution: {integrity: sha512-disdg7gHuTDZtY+ZdkmLpPCk7fxZSu3gBiEGuoC1XYxv9cGx3Z6cpTggCgW6odSOOIXCiDjuGejW+aJKCY/pIQ==} + '@scure/bip39@1.4.0': + resolution: {integrity: sha512-BEEm6p8IueV/ZTfQLp/0vhw4NPnT9oWf5+28nvmeUICjP99f4vr2d+qc7AVGDDtwRep6ifR43Yed9ERVmiITzw==} '@shikijs/core@1.10.0': resolution: {integrity: sha512-BZcr6FCmPfP6TXaekvujZcnkFmJHZ/Yglu97r/9VjzVndQA56/F4WjUKtJRQUnK59Wi7p/UTAOekMfCJv7jnYg==} @@ -3796,11 +3789,6 @@ packages: peerDependencies: acorn: ^6.0.0 || ^7.0.0 || ^8.0.0 - acorn-typescript@1.4.13: - resolution: {integrity: sha512-xsc9Xv0xlVfwp2o7sQ+GCQ1PgbkdcpWdTzrwXxO3xDMTAywVS3oXVOcOHuRjAPkS4P9b+yc/qNF15460v+jp4Q==} - peerDependencies: - acorn: '>=8.9.0' - acorn-walk@8.2.0: resolution: {integrity: sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==} engines: {node: '>=0.4.0'} @@ -3906,10 +3894,6 @@ packages: aria-query@5.3.0: resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==} - aria-query@5.3.2: - resolution: {integrity: sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==} - engines: {node: '>= 0.4'} - array-buffer-byte-length@1.0.0: resolution: {integrity: sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==} @@ -3962,10 +3946,6 @@ packages: axobject-query@4.0.0: resolution: {integrity: sha512-+60uv1hiVFhHZeO+Lz0RYzsVHy5Wr1ayX0mwda9KPDVLNJgZ1T9Ny7VmFbLDzxsH0D87I86vgj3gFrjTJUYznw==} - axobject-query@4.1.0: - resolution: {integrity: sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==} - engines: {node: '>= 0.4'} - babel-core@7.0.0-bridge.0: resolution: {integrity: sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg==} peerDependencies: @@ -5067,9 +5047,6 @@ packages: resolution: {integrity: sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==} engines: {node: '>=0.10'} - esrap@1.2.2: - resolution: {integrity: sha512-F2pSJklxx1BlQIQgooczXCPHmcWpn6EsP5oo73LQfonG9fIlIENQ8vMmfGXeojP9MrkzUNAfyU5vdFlR9shHAw==} - esrecurse@4.3.0: resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} engines: {node: '>=4.0'} @@ -7797,10 +7774,6 @@ packages: resolution: {integrity: sha512-IY1rnGr6izd10B0A8LqsBfmlT5OILVuZ7XsI0vdGPEvuonFV7NYEUK4dAkm9Zg2q0Um92kYjTpS1CAP3Nh/KWw==} engines: {node: '>=16'} - svelte@5.0.0-next.260: - resolution: {integrity: sha512-TGcvG71DUklf5P4UmJxOQiVxWYLPp4c6o+NUjmVMsAXKsCMXOTXw+QpnmEWw5D95Sj7SrmAGeIT+p/uvHAUZXg==} - engines: {node: '>=18'} - sveltedoc-parser@4.2.1: resolution: {integrity: sha512-sWJRa4qOfRdSORSVw9GhfDEwsbsYsegnDzBevUCF6k/Eis/QqCu9lJ6I0+d/E2wOWCjOhlcJ3+jl/Iur+5mmCw==} engines: {node: '>=10.0.0'} @@ -8780,9 +8753,6 @@ packages: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} - zimmerframe@1.1.2: - resolution: {integrity: sha512-rAbqEGa8ovJy4pyBxZM70hg4pE6gDgaQ0Sl9M3enG3I0d6H4XSAM3GeNGLKnsBpuijUow064sf7ww1nutC5/3w==} - zwitch@2.0.4: resolution: {integrity: sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==} @@ -9893,21 +9863,21 @@ snapshots: '@braintree/sanitize-url@7.1.0': {} - '@cashu/cashu-ts@1.0.0-rc.9': + '@cashu/cashu-ts@1.1.0': dependencies: '@cashu/crypto': 0.2.7 '@noble/curves': 1.6.0 '@noble/hashes': 1.5.0 - '@scure/bip32': 1.4.0 - '@scure/bip39': 1.3.0 + '@scure/bip32': 1.5.0 + '@scure/bip39': 1.4.0 buffer: 6.0.3 '@cashu/crypto@0.2.7': dependencies: '@noble/curves': 1.6.0 '@noble/hashes': 1.5.0 - '@scure/bip32': 1.4.0 - '@scure/bip39': 1.3.0 + '@scure/bip32': 1.5.0 + '@scure/bip39': 1.4.0 buffer: 6.0.3 '@changesets/apply-release-plan@6.1.4': @@ -11012,10 +10982,6 @@ snapshots: dependencies: '@noble/hashes': 1.3.2 - '@noble/curves@1.4.2': - dependencies: - '@noble/hashes': 1.4.0 - '@noble/curves@1.6.0': dependencies: '@noble/hashes': 1.5.0 @@ -11024,8 +10990,6 @@ snapshots: '@noble/hashes@1.3.2': {} - '@noble/hashes@1.4.0': {} - '@noble/hashes@1.5.0': {} '@noble/secp256k1@2.0.0': {} @@ -11452,10 +11416,10 @@ snapshots: '@noble/hashes': 1.3.1 '@scure/base': 1.1.9 - '@scure/bip32@1.4.0': + '@scure/bip32@1.5.0': dependencies: - '@noble/curves': 1.4.2 - '@noble/hashes': 1.4.0 + '@noble/curves': 1.6.0 + '@noble/hashes': 1.5.0 '@scure/base': 1.1.9 '@scure/bip39@1.2.1': @@ -11463,9 +11427,9 @@ snapshots: '@noble/hashes': 1.3.1 '@scure/base': 1.1.9 - '@scure/bip39@1.3.0': + '@scure/bip39@1.4.0': dependencies: - '@noble/hashes': 1.4.0 + '@noble/hashes': 1.5.0 '@scure/base': 1.1.9 '@shikijs/core@1.10.0': {} @@ -12823,10 +12787,6 @@ snapshots: dependencies: acorn: 8.12.1 - acorn-typescript@1.4.13(acorn@8.12.1): - dependencies: - acorn: 8.12.1 - acorn-walk@8.2.0: {} acorn@8.10.0: {} @@ -12928,8 +12888,6 @@ snapshots: dependencies: dequal: 2.0.3 - aria-query@5.3.2: {} - array-buffer-byte-length@1.0.0: dependencies: call-bind: 1.0.2 @@ -12992,8 +12950,6 @@ snapshots: dependencies: dequal: 2.0.3 - axobject-query@4.1.0: {} - babel-core@7.0.0-bridge.0(@babel/core@7.25.2): dependencies: '@babel/core': 7.25.2 @@ -14516,11 +14472,6 @@ snapshots: dependencies: estraverse: 5.3.0 - esrap@1.2.2: - dependencies: - '@jridgewell/sourcemap-codec': 1.5.0 - '@types/estree': 1.0.6 - esrecurse@4.3.0: dependencies: estraverse: 5.3.0 @@ -18271,22 +18222,6 @@ snapshots: magic-string: 0.30.10 periscopic: 3.1.0 - svelte@5.0.0-next.260: - dependencies: - '@ampproject/remapping': 2.3.0 - '@jridgewell/sourcemap-codec': 1.5.0 - '@types/estree': 1.0.6 - acorn: 8.12.1 - acorn-typescript: 1.4.13(acorn@8.12.1) - aria-query: 5.3.2 - axobject-query: 4.1.0 - esm-env: 1.0.0 - esrap: 1.2.2 - is-reference: 3.0.2 - locate-character: 3.0.0 - magic-string: 0.30.11 - zimmerframe: 1.1.2 - sveltedoc-parser@4.2.1: dependencies: eslint: 8.4.1 @@ -19589,6 +19524,4 @@ snapshots: yocto-queue@0.1.0: {} - zimmerframe@1.1.2: {} - zwitch@2.0.4: {}