diff --git a/package.json b/package.json index 64a74d7..d8564b4 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "dependencies": { "@getalby/lightning-tools": "^8.1.1", "@getalby/sdk": "^8.0.1", + "@lendasat/lendaswap-sdk-pure": "^0.2.36", "@noble/hashes": "^2.0.1", "commander": "^14.0.3", "nostr-tools": "^2.23.3" diff --git a/src/commands/pay-crypto.ts b/src/commands/pay-crypto.ts new file mode 100644 index 0000000..f930391 --- /dev/null +++ b/src/commands/pay-crypto.ts @@ -0,0 +1,68 @@ +import { Command } from "commander"; +import { payInvoice } from "../tools/nwc/pay_invoice.js"; +import { getClient, handleError, output } from "../utils.js"; +import { + isPlausibleEvmAddress, + payCrypto, + findSupportedPair, +} from "../lendaswap/swap.js"; + +export function registerPayCryptoCommand(program: Command) { + program + .command("pay-crypto") + .description( + "Pay any supported crypto or stablecoin address from your Lightning wallet using an atomic swap (powered by Lendaswap).\n\n" + + "Supported currencies and networks are sourced live from the Lendaswap API; if a pair is not available you'll get an error listing what is.", + ) + .argument("
", "Recipient address on the target network") + .requiredOption( + "-a, --amount ", + "Amount to send in target-currency units (e.g. 10 = 10 USDC)", + Number, + ) + .option("--currency ", "Target currency", "USDC") + .option("--network ", "Target network (chain name or id, e.g. arbitrum / 42161)", "arbitrum") + .addHelpText( + "after", + "\nExample:\n" + + " $ npx @getalby/cli pay-crypto 0xabc... --amount 10 --currency USDC --network arbitrum\n", + ) + .action(async (address: string, options) => { + await handleError(async () => { + if (!Number.isFinite(options.amount) || options.amount <= 0) { + throw new Error(`Invalid --amount: ${options.amount}`); + } + if (!isPlausibleEvmAddress(address)) { + throw new Error( + `Recipient address does not look valid (expected 0x + 40 hex chars): ${address}`, + ); + } + + // Validate the pair against the live Lendaswap catalog before + // asking the user for their wallet — fast feedback on typos. + const pair = await findSupportedPair(options.currency, options.network); + + const nwc = await getClient(program); + + const { swapId } = await payCrypto({ + pair, + amount: options.amount, + targetAddress: address, + payInvoice: async (bolt11Invoice) => { + await payInvoice(nwc, { invoice: bolt11Invoice }); + }, + }); + + output({ + swap_id: swapId, + status: "completed", + target: { + address, + currency: pair.symbol, + network: pair.network, + amount: options.amount, + }, + }); + }); + }); +} diff --git a/src/index.ts b/src/index.ts index 17aca0f..fa7d1c0 100644 --- a/src/index.ts +++ b/src/index.ts @@ -21,6 +21,7 @@ import { registerParseInvoiceCommand } from "./commands/parse-invoice.js"; import { registerVerifyPreimageCommand } from "./commands/verify-preimage.js"; import { registerRequestInvoiceFromLightningAddressCommand } from "./commands/request-invoice-from-lightning-address.js"; import { registerFetch402Command } from "./commands/fetch.js"; +import { registerPayCryptoCommand } from "./commands/pay-crypto.js"; import { registerConnectCommand } from "./commands/connect.js"; import { registerAuthCommand } from "./commands/auth.js"; import { registerListWalletsCommand } from "./commands/list-wallets.js"; @@ -99,6 +100,10 @@ registerRequestInvoiceFromLightningAddressCommand(program); program.commandsGroup("HTTP 402 Payments (requires wallet connection):"); registerFetch402Command(program); +// Register cross-currency payments (Lightning → EVM via atomic swap) +program.commandsGroup("Cross-Currency Payments (requires wallet connection):"); +registerPayCryptoCommand(program); + // Register service discovery program.commandsGroup("Service Discovery:"); registerDiscoverCommand(program); diff --git a/src/lendaswap/swap.ts b/src/lendaswap/swap.ts new file mode 100644 index 0000000..a9dc16c --- /dev/null +++ b/src/lendaswap/swap.ts @@ -0,0 +1,263 @@ +import { + Asset, + Client, + InMemorySwapStorage, + InMemoryWalletStorage, + type LightningToEvmSwapResponse, + type SwapStatus, + type SwapStatusHandler, + toChain, + toChainName, +} from "@lendasat/lendaswap-sdk-pure"; + +// Allow tests (or local dev against staging) to override the API endpoint. +const API_BASE_URL = process.env.LENDASWAP_API_URL || "https://api.satora.io"; + +// Terminal statuses where the swap is irrecoverably done. Mirrors the same +// constants used by the bitcoin-card-topup reference frontend. +const SUCCESS_STATUSES: SwapStatus[] = ["clientredeemed", "serverredeemed"]; +const FAILURE_STATUSES: SwapStatus[] = [ + "expired", + "clientrefunded", + "clientrefundedserverrefunded", + "clientrefundedserverfunded", + "clientinvalidfunded", + "clientfundedtoolate", + "serverwontfund", +]; + +let clientPromise: Promise | null = null; + +function getClient(): Promise { + if (!clientPromise) { + // In-memory storage: a single CLI invocation waits synchronously for a + // terminal swap status, so there's nothing to recover across runs. If the + // process is killed mid-swap, the HTLC refund timer is the safety net. + clientPromise = Client.builder() + .withBaseUrl(API_BASE_URL) + .withSignerStorage(new InMemoryWalletStorage()) + .withSwapStorage(new InMemorySwapStorage()) + .build(); + } + return clientPromise; +} + +export interface SupportedPair { + /** Token symbol as reported by the API (e.g. "USDC"). */ + symbol: string; + /** Human-friendly chain name (e.g. "Arbitrum"). */ + network: string; + decimals: number; + /** Canonical chain identifier from the SDK (e.g. "42161"). */ + chain: string; + /** Token ID — ERC-20 contract address for EVM tokens. */ + tokenId: string; +} + +let supportedPairsPromise: Promise | null = null; + +/** + * Fetch all (currency, network) pairs that can be the target of a + * Lightning → EVM swap. The list comes straight from the Lendaswap API: + * `getTokens()` for the token universe, intersected with `getSwapPairs()` + * filtered to source = Lightning. + */ +export function getSupportedPairs(): Promise { + if (!supportedPairsPromise) { + supportedPairsPromise = (async () => { + const client = await getClient(); + const [tokens, swapPairs] = await Promise.all([ + client.getTokens(), + client.getSwapPairs(), + ]); + const lightningTargetChains = new Set( + swapPairs.pairs + .filter((p) => p.source === "Lightning") + .map((p) => p.target), + ); + return tokens.evm_tokens + .filter((t) => lightningTargetChains.has(t.chain)) + .map((t) => ({ + symbol: t.symbol, + network: toChainName(t.chain), + decimals: t.decimals, + chain: t.chain, + tokenId: t.token_id, + })); + })(); + } + return supportedPairsPromise; +} + +function formatPairsList(pairs: SupportedPair[]): string { + return pairs.map((p) => ` - ${p.symbol} on ${p.network}`).join("\n"); +} + +/** + * Resolve a (currency, network) pair against the live API list, or throw + * with a human-readable error listing every supported pair. Network can be + * a chain name ("arbitrum") or chain id ("42161"); matching is case-insensitive. + */ +export async function findSupportedPair( + currency: string, + network: string, +): Promise { + const pairs = await getSupportedPairs(); + const symbol = currency.toUpperCase(); + // toChain normalizes "arbitrum"/"42161"/"Arbitrum" to the canonical chain id. + const chain = toChain(network); + const pair = pairs.find( + (p) => p.symbol.toUpperCase() === symbol && p.chain === chain, + ); + if (!pair) { + throw new Error( + `Unsupported currency/network combination: ${currency} on ${network}.\n` + + `Supported:\n${formatPairsList(pairs)}`, + ); + } + return pair; +} + +/** + * EVM address shape check: every chain reachable from Lightning is EVM, so + * the universal `0x` + 40-hex format applies. Lendaswap does the + * authoritative validation when it builds the swap; this is just a sanity + * pre-check so an obvious typo fails fast before we lock funds. + */ +export function isPlausibleEvmAddress(address: string): boolean { + return /^0x[0-9a-fA-F]{40}$/.test(address); +} + +function toSmallestUnit(amount: number, decimals: number): number { + return Math.round(amount * 10 ** decimals); +} + +async function createPaymentSwap(params: { + pair: SupportedPair; + amount: number; + targetAddress: string; +}): Promise { + const client = await getClient(); + const targetAmount = toSmallestUnit(params.amount, params.pair.decimals); + + const targetAsset: Asset = { + chain: params.pair.chain, + tokenId: params.pair.tokenId, + }; + + const result = await client.createSwap({ + source: Asset.BTC_LIGHTNING, + target: targetAsset, + targetAmount, + targetAddress: params.targetAddress, + gasless: true, + referralCode: "lnds_2c07e38f10a28d47", + }); + // Source is BTC_LIGHTNING and target is an EVM token, so the SDK routes + // through its Lightning→EVM path. + return result.response as LightningToEvmSwapResponse; +} + +async function subscribeToSwap( + swapId: string, + onUpdate: SwapStatusHandler, +): Promise<() => void> { + const client = await getClient(); + return client.subscribeToSwaps([swapId], onUpdate); +} + +async function claimSwap(swapId: string) { + const client = await getClient(); + return client.claim(swapId); +} + +export interface PayCryptoParams { + /** Currency/network pair the recipient will be paid in — use {@link findSupportedPair} to obtain. */ + pair: SupportedPair; + /** Amount of the target currency the recipient should receive (e.g. 10 for 10 USDC). */ + amount: number; + /** Recipient address on the target network. */ + targetAddress: string; + /** + * Pay the swap's bolt11 invoice. The caller owns the Lightning wallet; this + * keeps lendaswap independent of any specific wallet/NWC implementation. + */ + payInvoice: (bolt11Invoice: string) => Promise; +} + +export interface PayCryptoResult { + swapId: string; +} + +/** + * Run a Lightning → on-chain crypto payment swap and block until it reaches a + * terminal status. Throws on any failure status. All swap-provider specifics + * (Lendaswap SDK calls, status handling, claim-on-serverfunded) live here so + * that swapping out the provider is a self-contained change. + */ +export async function payCrypto( + params: PayCryptoParams, +): Promise { + const swap = await createPaymentSwap({ + pair: params.pair, + amount: params.amount, + targetAddress: params.targetAddress, + }); + + // Subscribe BEFORE paying so we don't miss the `serverfunded` event + // that triggers our claim. Unsubscribe in `finally` no matter what. + let unsubscribe: (() => void) | undefined; + try { + await new Promise((resolve, reject) => { + let settled = false; + const settle = (fn: () => void) => { + if (settled) return; + settled = true; + fn(); + }; + + let claimStarted = false; + subscribeToSwap(swap.id, (_id, status) => { + if (status === "serverfunded" && !claimStarted) { + claimStarted = true; + claimSwap(swap.id).catch((err) => + settle(() => + reject(err instanceof Error ? err : new Error(String(err))), + ), + ); + } + if (SUCCESS_STATUSES.includes(status)) { + settle(resolve); + } else if (FAILURE_STATUSES.includes(status)) { + settle(() => reject(new Error(`Swap ${status}`))); + } + }) + .then((unsub) => { + unsubscribe = unsub; + // If the swap already terminated before subscribe resolved, + // tear down immediately. + if (settled) unsub(); + }) + .catch((err) => + settle(() => + reject(err instanceof Error ? err : new Error(String(err))), + ), + ); + + // Pay the Lightning invoice. Failure here propagates as the + // overall swap failure; success doesn't resolve us — only a + // terminal swap status does. + params + .payInvoice(swap.bolt11_invoice) + .catch((err) => + settle(() => + reject(err instanceof Error ? err : new Error(String(err))), + ), + ); + }); + } finally { + unsubscribe?.(); + } + + return { swapId: swap.id }; +} diff --git a/src/test/pay-crypto.test.ts b/src/test/pay-crypto.test.ts new file mode 100644 index 0000000..19b0821 --- /dev/null +++ b/src/test/pay-crypto.test.ts @@ -0,0 +1,205 @@ +import { describe, test, expect, beforeAll, afterAll } from "vitest"; +import { spawn } from "child_process"; +import { createServer, type Server } from "http"; +import { type AddressInfo } from "net"; + +// Stand up a local HTTP mock for the Lendaswap API endpoints the CLI hits +// during validation. The CLI spawns a fresh subprocess per test, so the +// `LENDASWAP_API_URL` env var (consumed in src/lendaswap/swap.ts) points it +// at this mock instead of api.satora.io. We only need `/tokens` and +// `/swap-pairs` — pair validation runs before wallet load, so tests never +// reach the swap-creation endpoints. +// +// IMPORTANT: we use async `spawn`, not the shared `execSync`-based runCli +// helper. `execSync` blocks the event loop, which would prevent this +// in-process mock from accepting the subprocess's TCP connection — fetch +// would just time out. + +let server: Server; +let mockUrl = ""; + +const MOCK_TOKENS = { + btc_tokens: [], + evm_tokens: [ + { + chain: "42161", + decimals: 6, + name: "USD Coin", + symbol: "USDC", + token_id: "0xaf88d065e77c8cc2239327c5edb3a432268e5831", + }, + { + chain: "42161", + decimals: 6, + name: "Tether USD", + symbol: "USDT", + token_id: "0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9", + }, + ], +}; + +// Only the Lightning → 42161 (Arbitrum) pair is enabled in the mock. So +// USDC/USDT on Arbitrum resolve; the same symbols on any other chain are +// rejected as unsupported. +const MOCK_SWAP_PAIRS = { + pairs: [ + { + fee_percentage: 0.0025, + max_sats: 100_000_000, + min_sats: 1000, + source: "Lightning", + target: "42161", + }, + ], +}; + +beforeAll(async () => { + server = createServer((req, res) => { + res.setHeader("Content-Type", "application/json"); + if (req.url === "/tokens") { + res.end(JSON.stringify(MOCK_TOKENS)); + } else if (req.url === "/swap-pairs") { + res.end(JSON.stringify(MOCK_SWAP_PAIRS)); + } else { + res.statusCode = 404; + res.end(JSON.stringify({ error: "not found" })); + } + }); + await new Promise((resolve) => + server.listen(0, "127.0.0.1", () => resolve()), + ); + const addr = server.address() as AddressInfo; + mockUrl = `http://127.0.0.1:${addr.port}`; +}); + +afterAll( + () => new Promise((resolve) => server.close(() => resolve())), +); + +interface ErrorOutput { + error: string; +} + +interface CliResult { + success: boolean; + output: T; +} + +function runCliAsync(args: string): Promise> { + return new Promise((resolve) => { + const child = spawn("node", ["build/index.js", ...args.split(" ")], { + env: { + ...process.env, + // Wallet load always fails — exposes the validation gates as the + // only thing that can succeed or fail before that point. + HOME: "/tmp/nonexistent-alby-cli-test-home", + NWC_URL: "", + LENDASWAP_API_URL: mockUrl, + }, + }); + let stdout = ""; + let stderr = ""; + child.stdout.on("data", (d) => (stdout += d.toString())); + child.stderr.on("data", (d) => (stderr += d.toString())); + child.on("close", (code) => { + const raw = code === 0 ? stdout : stderr || stdout || "{}"; + try { + resolve({ success: code === 0, output: JSON.parse(raw) }); + } catch { + resolve({ success: code === 0, output: { error: raw } as T }); + } + }); + }); +} + +describe("pay-crypto validation", () => { + describe("unsupported currency/network combination", () => { + test("unknown currency is rejected and lists supported pairs", async () => { + const result = await runCliAsync( + "pay-crypto 0x000000000000000000000000000000000000dead --amount 10 --currency XYZ --network arbitrum", + ); + expect(result.success).toBe(false); + expect(result.output.error).toContain( + "Unsupported currency/network combination", + ); + expect(result.output.error).toContain("USDC on Arbitrum"); + }); + + test("USDC on ethereum is rejected (chain not in swap-pairs)", async () => { + const result = await runCliAsync( + "pay-crypto 0x000000000000000000000000000000000000dead --amount 10 --currency USDC --network ethereum", + ); + expect(result.success).toBe(false); + expect(result.output.error).toContain( + "Unsupported currency/network combination", + ); + expect(result.output.error).toContain("USDC on Arbitrum"); + }); + }); + + describe("malformed EVM address", () => { + test("completely non-hex string is rejected", async () => { + const result = await runCliAsync( + "pay-crypto notanaddress --amount 10", + ); + expect(result.success).toBe(false); + expect(result.output.error).toContain("address does not look valid"); + }); + + test("too-short hex with 0x prefix is rejected", async () => { + const result = await runCliAsync( + "pay-crypto 0xabc --amount 10", + ); + expect(result.success).toBe(false); + expect(result.output.error).toContain("address does not look valid"); + }); + + test("40-char hex without 0x prefix is rejected", async () => { + const result = await runCliAsync( + "pay-crypto 000000000000000000000000000000000000dead --amount 10", + ); + expect(result.success).toBe(false); + expect(result.output.error).toContain("address does not look valid"); + }); + }); + + describe("invalid amount", () => { + test("--amount 0 is rejected", async () => { + const result = await runCliAsync( + "pay-crypto 0x000000000000000000000000000000000000dead --amount 0", + ); + expect(result.success).toBe(false); + expect(result.output.error).toContain("Invalid --amount"); + }); + + test("--amount -1 is rejected", async () => { + const result = await runCliAsync( + "pay-crypto 0x000000000000000000000000000000000000dead --amount -1", + ); + expect(result.success).toBe(false); + expect(result.output.error).toContain("Invalid --amount"); + }); + + test("--amount abc (NaN) is rejected", async () => { + const result = await runCliAsync( + "pay-crypto 0x000000000000000000000000000000000000dead --amount abc", + ); + expect(result.success).toBe(false); + expect(result.output.error).toContain("Invalid --amount"); + }); + }); + + describe("happy-path validation", () => { + test("valid USDC/arbitrum inputs get past validation and fail only at wallet load", async () => { + // The mocked supported list includes USDC on 42161 (Arbitrum), so + // findSupportedPair succeeds. With the wallet env disabled, the only + // error left is "No wallet connection found" from getClient() — + // proof that amount, address, and pair gates all accepted the input. + const result = await runCliAsync( + "pay-crypto 0x000000000000000000000000000000000000dead --amount 10 --currency USDC --network arbitrum", + ); + expect(result.success).toBe(false); + expect(result.output.error).toContain("No wallet connection found"); + }); + }); +}); diff --git a/yarn.lock b/yarn.lock index e575a5d..cb6c087 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,6 +2,55 @@ # yarn lockfile v1 +"@adraffy/ens-normalize@^1.11.0": + version "1.11.1" + resolved "https://registry.yarnpkg.com/@adraffy/ens-normalize/-/ens-normalize-1.11.1.tgz#6c2d657d4b2dfb37f8ea811dcb3e60843d4ac24a" + integrity sha512-nhCBV3quEgesuf7c7KYfperqSS14T8bYuvJ8PcLJp6znkZpFc0AuW4qBtr8eKVyPPe/8RSr7sglCWPU5eaxwKQ== + +"@arkade-os/sdk@^0.4.6": + version "0.4.30" + resolved "https://registry.yarnpkg.com/@arkade-os/sdk/-/sdk-0.4.30.tgz#2c50ea3c3070b9778954cdfa5bb250908e97132b" + integrity sha512-I/XWJ+EkZMBuBhy0vqahMQ8HVn8QlCcW5xHSA9jREs2IsR1PAO1r+yOxOhq9F4lMT+biHz0kcYU4K3t/ewtj7Q== + dependencies: + "@bitcoinerlab/descriptors-scure" "3.1.7" + "@marcbachmann/cel-js" "7.3.1" + "@noble/curves" "2.0.1" + "@noble/secp256k1" "3.0.0" + "@scure/base" "2.0.0" + "@scure/bip39" "2.0.1" + "@scure/btc-signer" "2.0.1" + bip68 "1.0.4" + ws-electrumx-client "1.0.5" + +"@bitcoinerlab/descriptors-core@3.1.7": + version "3.1.7" + resolved "https://registry.yarnpkg.com/@bitcoinerlab/descriptors-core/-/descriptors-core-3.1.7.tgz#fd82f091342e530394ce8848a451595a7548b17a" + integrity sha512-7VccUDvKcHK7RF07Vo19Obax9jO3wlPWIXtvXy61GBqXptKv156O9Z4+sm2py1CuxPRpTXHlvH70G4KVVDoKlw== + dependencies: + "@bitcoinerlab/miniscript" "^2.0.0" + lodash.memoize "^4.1.2" + uint8array-tools "^0.0.9" + varuint-bitcoin "^2.0.0" + +"@bitcoinerlab/descriptors-scure@3.1.7": + version "3.1.7" + resolved "https://registry.yarnpkg.com/@bitcoinerlab/descriptors-scure/-/descriptors-scure-3.1.7.tgz#12d57ac92d4e4f5ecf7d2692a4c1da3a46b96b02" + integrity sha512-jeyi8L3hzOquJn3t5w+NY3G93B/amZw83xeF8hrpwe7w4FMt2SH2o9rithEydQ2tP3Tlqfog+LnJOOChmfFPWw== + dependencies: + "@bitcoinerlab/descriptors-core" "3.1.7" + "@noble/curves" "^2.0.1" + "@noble/hashes" "^2.0.1" + "@scure/base" "^2.0.0" + "@scure/bip32" "^2.0.1" + "@scure/btc-signer" "^2.0.1" + +"@bitcoinerlab/miniscript@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@bitcoinerlab/miniscript/-/miniscript-2.0.0.tgz#1d6516bf5be580e1a1890d33a7b44dd3cb8c10f0" + integrity sha512-P8yyubPf6lphmIZfyD/ZbhT/umJX7zH1mKjGql7z0Qt+xuffnz2AueQqq2/01VE2rTIq80VM0oRFdJClGBYx/g== + dependencies: + bip68 "^1.0.4" + "@esbuild/aix-ppc64@0.27.2": version "0.27.2" resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.27.2.tgz#521cbd968dcf362094034947f76fa1b18d2d403c" @@ -150,23 +199,88 @@ resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz#6912b00d2c631c0d15ce1a7ab57cd657f2a8f8ba" integrity sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og== +"@lendasat/lendaswap-sdk-pure@^0.2.36": + version "0.2.36" + resolved "https://registry.yarnpkg.com/@lendasat/lendaswap-sdk-pure/-/lendaswap-sdk-pure-0.2.36.tgz#a9eeb25c26912dff6a3dc0b4cf5ce9e2dbf95ac4" + integrity sha512-mgM/fGN9fG4+aYno3wmNQmsGwBgTwwYvFStWOYTha9Pa6V6PKu8DM8whmAXZuDchk4phlDgvClKQB0HoPzl84A== + dependencies: + "@arkade-os/sdk" "^0.4.6" + "@noble/curves" "^2.2.0" + "@noble/hashes" "^2.2.0" + "@scure/base" "^2.0.0" + "@scure/bip32" "^2.0.1" + "@scure/bip39" "^2.0.1" + "@scure/btc-signer" "^2.0.1" + "@zerodev/sdk" "^5.5.0" + dexie "^4.4.2" + openapi-fetch "^0.17.0" + viem "2.46.3" + optionalDependencies: + better-sqlite3 "^12.6.2" + +"@marcbachmann/cel-js@7.3.1": + version "7.3.1" + resolved "https://registry.yarnpkg.com/@marcbachmann/cel-js/-/cel-js-7.3.1.tgz#03b43ea949bce6b9da2f2d0063672c9b9b16db06" + integrity sha512-P6o26TvjStT8V8+8EF+yq9Pp7ZFV00bpiUMbssr76XbIZGxaB+NNWeBp6WNxOrR9gp0JPzvJueCKHpOs5LE9PQ== + "@noble/ciphers@2.1.1": version "2.1.1" resolved "https://registry.yarnpkg.com/@noble/ciphers/-/ciphers-2.1.1.tgz#c8c74fcda8c3d1f88797d0ecda24f9fc8b92b052" integrity sha512-bysYuiVfhxNJuldNXlFEitTVdNnYUc+XNJZd7Qm2a5j1vZHgY+fazadNFWFaMK/2vye0JVlxV3gHmC0WDfAOQw== -"@noble/curves@2.0.1": +"@noble/ciphers@^1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@noble/ciphers/-/ciphers-1.3.0.tgz#f64b8ff886c240e644e5573c097f86e5b43676dc" + integrity sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw== + +"@noble/curves@1.9.1": + version "1.9.1" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.9.1.tgz#9654a0bc6c13420ae252ddcf975eaf0f58f0a35c" + integrity sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA== + dependencies: + "@noble/hashes" "1.8.0" + +"@noble/curves@2.0.1", "@noble/curves@~2.0.0": version "2.0.1" resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-2.0.1.tgz#64ba8bd5e8564a02942655602515646df1cdb3ad" integrity sha512-vs1Az2OOTBiP4q0pwjW5aF0xp9n4MxVrmkFBxc6EKZc6ddYx5gaZiAsZoq0uRRXWbi3AT/sBqn05eRPtn1JCPw== dependencies: "@noble/hashes" "2.0.1" -"@noble/hashes@2.0.1", "@noble/hashes@^2.0.1": +"@noble/curves@2.2.0", "@noble/curves@^2.0.1", "@noble/curves@^2.2.0", "@noble/curves@~2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-2.2.0.tgz#981be3aadc3bbfbcdb245e78cc97aa6f759246c2" + integrity sha512-T/BoHgFXirb0ENSPBquzX0rcjXeM6Lo892a2jlYJkqk83LqZx0l1Of7DzlKJ6jkpvMrkHSnAcgb5JegL8SeIkQ== + dependencies: + "@noble/hashes" "2.2.0" + +"@noble/curves@~1.9.0": + version "1.9.7" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.9.7.tgz#79d04b4758a43e4bca2cbdc62e7771352fa6b951" + integrity sha512-gbKGcRUYIjA3/zCCNaWDciTMFI0dCkvou3TL8Zmy5Nc7sJ47a0jtOeZoTaMxkuqRo9cRhjOdZJXegxYE5FN/xw== + dependencies: + "@noble/hashes" "1.8.0" + +"@noble/hashes@1.8.0", "@noble/hashes@^1.8.0", "@noble/hashes@~1.8.0": + version "1.8.0" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.8.0.tgz#cee43d801fcef9644b11b8194857695acd5f815a" + integrity sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A== + +"@noble/hashes@2.0.1", "@noble/hashes@^2.0.1", "@noble/hashes@~2.0.0": version "2.0.1" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-2.0.1.tgz#fc1a928061d1232b0a52bb754393c37a5216c89e" integrity sha512-XlOlEbQcE9fmuXxrVTXCTlG2nlRXa9Rj3rr5Ue/+tX+nmkgbX720YHh0VR3hBF9xDvwnb8D2shVGOwNx+ulArw== +"@noble/hashes@2.2.0", "@noble/hashes@^2.2.0", "@noble/hashes@~2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-2.2.0.tgz#22da1d16a469954fce877055d559900a6c73b63b" + integrity sha512-IYqDGiTXab6FniAgnSdZwgWbomxpy9FtYvLKs7wCUs2a8RkITG+DFGO1DM9cr+E3/RgADRpFjrKVaJ1z6sjtEg== + +"@noble/secp256k1@3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@noble/secp256k1/-/secp256k1-3.0.0.tgz#29711361db8f37b1b7e0b8d80c933013fc887475" + integrity sha512-NJBaR352KyIvj3t6sgT/+7xrNyF9Xk9QlLSIqUGVUYlsnDTAUqY8LOmwpcgEx4AMJXRITQ5XEVHD+mMaPfr3mg== + "@rollup/rollup-android-arm-eabi@4.60.1": version "4.60.1" resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.60.1.tgz#043f145716234529052ef9e1ce1d847ffbe9e674" @@ -292,11 +406,30 @@ resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.60.1.tgz#23b860113e9f87eea015d1fa3a4240a52b42fcd4" integrity sha512-lWMnixq/QzxyhTV6NjQJ4SFo1J6PvOX8vUx5Wb4bBPsEb+8xZ89Bz6kOXpfXj9ak9AHTQVQzlgzBEc1SyM27xQ== -"@scure/base@2.0.0": +"@scure/base@2.0.0", "@scure/base@~2.0.0": version "2.0.0" resolved "https://registry.yarnpkg.com/@scure/base/-/base-2.0.0.tgz#ba6371fddf92c2727e88ad6ab485db6e624f9a98" integrity sha512-3E1kpuZginKkek01ovG8krQ0Z44E3DHPjc5S2rjJw9lZn3KSQOs8S7wqikF/AH7iRanHypj85uGyxk0XAyC37w== +"@scure/base@2.2.0", "@scure/base@^2.0.0", "@scure/base@~2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@scure/base/-/base-2.2.0.tgz#1311378ed247df6d58f8eb8941921965e97e5747" + integrity sha512-b8XEupJibegiXV+tDUseI8oLQc8ei3d/4Jkb2RpbHh3MfE054ov3uIz2dhFkB3FI8iwYkEh0gGCApkrYggkPNg== + +"@scure/base@~1.2.5": + version "1.2.6" + resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.2.6.tgz#ca917184b8231394dd8847509c67a0be522e59f6" + integrity sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg== + +"@scure/bip32@1.7.0", "@scure/bip32@^1.7.0": + version "1.7.0" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.7.0.tgz#b8683bab172369f988f1589640e53c4606984219" + integrity sha512-E4FFX/N3f4B80AKWp5dP6ow+flD1LQZo/w8UnLGYZO674jS6YnYeepycOOksv+vLPSpgN35wgKgy+ybfTb2SMw== + dependencies: + "@noble/curves" "~1.9.0" + "@noble/hashes" "~1.8.0" + "@scure/base" "~1.2.5" + "@scure/bip32@2.0.1": version "2.0.1" resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-2.0.1.tgz#4ceea207cee8626d3fe8f0b6ab68b6af8f81c482" @@ -306,6 +439,23 @@ "@noble/hashes" "2.0.1" "@scure/base" "2.0.0" +"@scure/bip32@^2.0.1": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-2.2.0.tgz#8b1b470f4079843df36a472f5e103c3bd9c11f7c" + integrity sha512-zFr7t2F+a9+5tB7QbarF2HQNYrgjCNaoLAupZdKkrFMYMozJf5zqH2WJCQibMzm1qQ0QogrxVGO3qXfQDYMaQg== + dependencies: + "@noble/curves" "2.2.0" + "@noble/hashes" "2.2.0" + "@scure/base" "2.2.0" + +"@scure/bip39@1.6.0", "@scure/bip39@^1.6.0": + version "1.6.0" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.6.0.tgz#475970ace440d7be87a6086cbee77cb8f1a684f9" + integrity sha512-+lF0BbLiJNwVlev4eKelw1WWLaiKXw7sSl8T6FvBlWkdX+94aGJ4o8XjUdlyhTCjd8c+B3KT3JfS8P0bLRNU6A== + dependencies: + "@noble/hashes" "~1.8.0" + "@scure/base" "~1.2.5" + "@scure/bip39@2.0.1": version "2.0.1" resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-2.0.1.tgz#47a6dc15e04faf200041239d46ae3bb7c3c96add" @@ -314,6 +464,34 @@ "@noble/hashes" "2.0.1" "@scure/base" "2.0.0" +"@scure/bip39@^2.0.1": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-2.2.0.tgz#7a3da0564aa2af919280a12b892d4b57e1bf30be" + integrity sha512-T/Bj/YvYMNkIPq6EENO6/rcs2e7qTNuyoUXf0KBFDmp0ZDu0H2X4Lq6yC3i0c8PcWkov5EbW+yQZZbdMmk154A== + dependencies: + "@noble/hashes" "2.2.0" + "@scure/base" "2.2.0" + +"@scure/btc-signer@2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@scure/btc-signer/-/btc-signer-2.0.1.tgz#06267325f80c8c6880dd846620ed859fea908a1e" + integrity sha512-vk5a/16BbSFZkhh1JIJ0+4H9nceZVo5WzKvJGGWiPp3sQOExeW+L53z3dI6u0adTPoE8ZbL+XEb6hEGzVZSvvQ== + dependencies: + "@noble/curves" "~2.0.0" + "@noble/hashes" "~2.0.0" + "@scure/base" "~2.0.0" + micro-packed "~0.8.0" + +"@scure/btc-signer@^2.0.1": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@scure/btc-signer/-/btc-signer-2.2.0.tgz#8aa38dcda9606a47deffb18fb1485e0c116ed17b" + integrity sha512-ZXZ08sZqSZKEcOuEQnxTF66ouHtl6+UA6U/QfQM06K9WiOlEkXF4LviZCaSgkdiFh9cyMt9+xdup7JtEv3p0fw== + dependencies: + "@noble/curves" "~2.2.0" + "@noble/hashes" "~2.2.0" + "@scure/base" "~2.2.0" + micro-packed "~0.9.0" + "@standard-schema/spec@^1.0.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@standard-schema/spec/-/spec-1.1.0.tgz#a79b55dbaf8604812f52d140b2c9ab41bc150bb8" @@ -407,21 +585,114 @@ resolved "https://registry.yarnpkg.com/@webbtc/webln-types/-/webln-types-3.0.0.tgz#448b2138423865087ba8859e9e6430fc2463b864" integrity sha512-aXfTHLKz5lysd+6xTeWl+qHNh/p3qVYbeLo+yDN5cUDmhie2ZoGvkppfWxzbGkcFBzb6dJyQ2/i2cbmDHas+zQ== +"@zerodev/sdk@^5.5.0": + version "5.5.10" + resolved "https://registry.yarnpkg.com/@zerodev/sdk/-/sdk-5.5.10.tgz#694d6088fa577266bd21fbfee2eba8eaf66c1051" + integrity sha512-WVyj2XR9F6zK2GdXrvappx7yo6zoJ46cWe42dOIArp3xDjFBninjA4O1O94MwohB0G+yFqtXNsEU+WxdE67SgQ== + dependencies: + semver "^7.6.0" + +abitype@1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/abitype/-/abitype-1.2.3.tgz#bec3e09dea97d99ef6c719140bee663a329ad1f4" + integrity sha512-Ofer5QUnuUdTFsBRwARMoWKOH1ND5ehwYhJ3OJ/BQO+StkwQjHw0XyVh4vDttzHB7QOFhPHa/o413PJ82gU/Tg== + +abitype@^1.2.3: + version "1.2.4" + resolved "https://registry.yarnpkg.com/abitype/-/abitype-1.2.4.tgz#8aab72949bcad4107031862ae998e5bd20eec76e" + integrity sha512-dpKH+N27vRjarMVTFFkeY445VTKftzGWpL0FiT7xmVmzQRKazZexzC5uHG0f6XKsVLAuUlndnbGau6lRejClxg== + assertion-error@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-2.0.1.tgz#f641a196b335690b1070bf00b6e7593fec190bf7" integrity sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA== +base64-js@^1.3.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a" + integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA== + +better-sqlite3@^12.6.2: + version "12.10.0" + resolved "https://registry.yarnpkg.com/better-sqlite3/-/better-sqlite3-12.10.0.tgz#bde622d14a18008583a53bc53501ae98f1a12221" + integrity sha512-CyzaZRQKyHkB2ZInfTTl2nvT33EbDpjkLEbE8/Zck3Ll6O0qqvuGdrJ45HgtH+HykRg88ITY3AdreBGN70aBSQ== + dependencies: + bindings "^1.5.0" + prebuild-install "^7.1.1" + +bindings@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.5.0.tgz#10353c9e945334bc0511a6d90b38fbc7c9c504df" + integrity sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ== + dependencies: + file-uri-to-path "1.0.0" + +bip68@1.0.4, bip68@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/bip68/-/bip68-1.0.4.tgz#78a95c7a43fad183957995cc2e08d79b0c372c4d" + integrity sha512-O1htyufFTYy3EO0JkHg2CLykdXEtV2ssqw47Gq9A0WByp662xpJnMEB9m43LZjsSDjIAOozWRExlFQk2hlV1XQ== + +bl@^4.0.3: + version "4.1.0" + resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" + integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== + dependencies: + buffer "^5.5.0" + inherits "^2.0.4" + readable-stream "^3.4.0" + +buffer@^5.5.0: + version "5.7.1" + resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" + integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== + dependencies: + base64-js "^1.3.1" + ieee754 "^1.1.13" + chai@^6.2.1: version "6.2.2" resolved "https://registry.yarnpkg.com/chai/-/chai-6.2.2.tgz#ae41b52c9aca87734505362717f3255facda360e" integrity sha512-NUPRluOfOiTKBKvWPtSD4PhFvWCqOi0BGStNWs57X9js7XGTprSmFoz5F0tWhR4WPjNeR9jXqdC7/UpSJTnlRg== +chownr@^1.1.1: + version "1.1.4" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" + integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== + commander@^14.0.3: version "14.0.3" resolved "https://registry.yarnpkg.com/commander/-/commander-14.0.3.tgz#425d79b48f9af82fcd9e4fc1ea8af6c5ec07bbc2" integrity sha512-H+y0Jo/T1RZ9qPP4Eh1pkcQcLRglraJaSLoyOtHxu6AapkjWVCy2Sit1QQ4x3Dng8qDlSsZEet7g5Pq06MvTgw== +decompress-response@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/decompress-response/-/decompress-response-6.0.0.tgz#ca387612ddb7e104bd16d85aab00d5ecf09c66fc" + integrity sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ== + dependencies: + mimic-response "^3.1.0" + +deep-extend@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/deep-extend/-/deep-extend-0.6.0.tgz#c4fa7c95404a17a9c3e8ca7e1537312b736330ac" + integrity sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA== + +detect-libc@^2.0.0: + version "2.1.2" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.1.2.tgz#689c5dcdc1900ef5583a4cb9f6d7b473742074ad" + integrity sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ== + +dexie@^4.4.2: + version "4.4.3" + resolved "https://registry.yarnpkg.com/dexie/-/dexie-4.4.3.tgz#6e3c286a53b0424ed49f648213611499597a7642" + integrity sha512-N+3IGQ3HPlyO2YAkntGAwitm42BpBGV86MttzUMiRzWLa4NGh0pltVRcUVF4ybL/OnXjCrr9k7SDPIKkFYP2Lg== + +end-of-stream@^1.1.0, end-of-stream@^1.4.1: + version "1.4.5" + resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.5.tgz#7344d711dea40e0b74abc2ed49778743ccedb08c" + integrity sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg== + dependencies: + once "^1.4.0" + es-module-lexer@^1.7.0: version "1.7.0" resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.7.0.tgz#9159601561880a85f2734560a9099b2c31e5372a" @@ -466,6 +737,16 @@ estree-walker@^3.0.3: dependencies: "@types/estree" "^1.0.0" +eventemitter3@5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-5.0.1.tgz#53f5ffd0a492ac800721bb42c66b841de96423c4" + integrity sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA== + +expand-template@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/expand-template/-/expand-template-2.0.3.tgz#6e14b3fcee0f3a6340ecb57d2e8918692052a47c" + integrity sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg== + expect-type@^1.2.2: version "1.3.0" resolved "https://registry.yarnpkg.com/expect-type/-/expect-type-1.3.0.tgz#0d58ed361877a31bbc4dd6cf71bbfef7faf6bd68" @@ -476,11 +757,56 @@ fdir@^6.5.0: resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.5.0.tgz#ed2ab967a331ade62f18d077dae192684d50d350" integrity sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg== +file-uri-to-path@1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz#553a7b8446ff6f684359c445f1e37a05dacc33dd" + integrity sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw== + +fs-constants@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" + integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== + fsevents@~2.3.2, fsevents@~2.3.3: version "2.3.3" resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== +github-from-package@0.0.0: + version "0.0.0" + resolved "https://registry.yarnpkg.com/github-from-package/-/github-from-package-0.0.0.tgz#97fb5d96bfde8973313f20e8288ef9a167fa64ce" + integrity sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw== + +ieee754@^1.1.13: + version "1.2.1" + resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352" + integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== + +inherits@^2.0.3, inherits@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +ini@~1.3.0: + version "1.3.8" + resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" + integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== + +isomorphic-ws@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz#e5529148912ecb9b451b46ed44d53dae1ce04bbf" + integrity sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw== + +isows@1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/isows/-/isows-1.0.7.tgz#1c06400b7eed216fbba3bcbd68f12490fc342915" + integrity sha512-I1fSfDCZL5P0v33sVqeTDSpcstAg/N+wF5HS033mogOVIp4B+oHC7oOCsA3axAbBSGTJ8QubbNmnIRN/h8U7hg== + +lodash.memoize@^4.1.2: + version "4.1.2" + resolved "https://registry.yarnpkg.com/lodash.memoize/-/lodash.memoize-4.1.2.tgz#bcc6c49a42a2840ed997f323eada5ecd182e0bfe" + integrity sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag== + magic-string@^0.30.21: version "0.30.21" resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.21.tgz#56763ec09a0fa8091df27879fd94d19078c00d91" @@ -488,11 +814,52 @@ magic-string@^0.30.21: dependencies: "@jridgewell/sourcemap-codec" "^1.5.5" +micro-packed@~0.8.0: + version "0.8.0" + resolved "https://registry.yarnpkg.com/micro-packed/-/micro-packed-0.8.0.tgz#fe516c50b7150fd84728b8456731f79e2925eaf8" + integrity sha512-AKb8znIvg9sooythbXzyFeChEY0SkW0C6iXECpy/ls0e5BtwXO45J9wD9SLzBztnS4XmF/5kwZknsq+jyynd/A== + dependencies: + "@scure/base" "2.0.0" + +micro-packed@~0.9.0: + version "0.9.0" + resolved "https://registry.yarnpkg.com/micro-packed/-/micro-packed-0.9.0.tgz#59202d4c848b79b14769f066c33982fe4fcf1ac3" + integrity sha512-gFdaWTxEXOwtSOcpxulO4AuXVtp3HWIRmB8eq8+3m1Zku0ubgva0UGpi03YhcvsTJasHngG9gTIUK5kHNKdesg== + dependencies: + "@scure/base" "~2.2.0" + +mimic-response@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/mimic-response/-/mimic-response-3.1.0.tgz#2d1d59af9c1b129815accc2c46a022a5ce1fa3c9" + integrity sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ== + +minimist@^1.2.0, minimist@^1.2.3: + version "1.2.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== + +mkdirp-classic@^0.5.2, mkdirp-classic@^0.5.3: + version "0.5.3" + resolved "https://registry.yarnpkg.com/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz#fa10c9115cc6d8865be221ba47ee9bed78601113" + integrity sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A== + nanoid@^3.3.11: version "3.3.11" resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.11.tgz#4f4f112cefbe303202f2199838128936266d185b" integrity sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w== +napi-build-utils@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/napi-build-utils/-/napi-build-utils-2.0.0.tgz#13c22c0187fcfccce1461844136372a47ddc027e" + integrity sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA== + +node-abi@^3.3.0: + version "3.92.0" + resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-3.92.0.tgz#18e2214677499b8dda81ffcd095afc763d5a9802" + integrity sha512-KdHvFWZjEKDf0cakgFjebl371GPsISX2oZHcuyKqM7DtogIsHrqKeLTo8wBHxaXRAQlY2PsPlZmfo+9ZCxEREQ== + dependencies: + semver "^7.3.5" + nostr-tools@^2.23.3: version "2.23.3" resolved "https://registry.yarnpkg.com/nostr-tools/-/nostr-tools-2.23.3.tgz#1a7501988b72499cf27c8f3951f00d11d9ac6025" @@ -516,6 +883,39 @@ obug@^2.1.1: resolved "https://registry.yarnpkg.com/obug/-/obug-2.1.1.tgz#2cba74ff241beb77d63055ddf4cd1e9f90b538be" integrity sha512-uTqF9MuPraAQ+IsnPf366RG4cP9RtUi7MLO1N3KEc+wb0a6yKpeL0lmk2IB1jY5KHPAlTc6T/JRdC/YqxHNwkQ== +once@^1.3.1, once@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +openapi-fetch@^0.17.0: + version "0.17.0" + resolved "https://registry.yarnpkg.com/openapi-fetch/-/openapi-fetch-0.17.0.tgz#0c392afbeed2c95a12056a50a8e6180c77c9ced3" + integrity sha512-PsbZR1wAPcG91eEthKhN+Zn92FMHxv+/faECIwjXdxfTODGSGegYv0sc1Olz+HYPvKOuoXfp+0pA2XVt2cI0Ig== + dependencies: + openapi-typescript-helpers "^0.1.0" + +openapi-typescript-helpers@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/openapi-typescript-helpers/-/openapi-typescript-helpers-0.1.0.tgz#2102a2ea1c473cb1cfe19f87c662ff053fbb1d70" + integrity sha512-OKTGPthhivLw/fHz6c3OPtg72vi86qaMlqbJuVJ23qOvQ+53uw1n7HdmkJFibloF7QEjDrDkzJiOJuockM/ljw== + +ox@0.12.4: + version "0.12.4" + resolved "https://registry.yarnpkg.com/ox/-/ox-0.12.4.tgz#469a1b3cfb033d92bc615567875942173a2ddeb5" + integrity sha512-+P+C7QzuwPV8lu79dOwjBKfB2CbnbEXe/hfyyrff1drrO1nOOj3Hc87svHfcW1yneRr3WXaKr6nz11nq+/DF9Q== + dependencies: + "@adraffy/ens-normalize" "^1.11.0" + "@noble/ciphers" "^1.3.0" + "@noble/curves" "1.9.1" + "@noble/hashes" "^1.8.0" + "@scure/bip32" "^1.7.0" + "@scure/bip39" "^1.6.0" + abitype "^1.2.3" + eventemitter3 "5.0.1" + pathe@^2.0.3: version "2.0.3" resolved "https://registry.yarnpkg.com/pathe/-/pathe-2.0.3.tgz#3ecbec55421685b70a9da872b2cff3e1cbed1716" @@ -540,6 +940,51 @@ postcss@^8.5.6: picocolors "^1.1.1" source-map-js "^1.2.1" +prebuild-install@^7.1.1: + version "7.1.3" + resolved "https://registry.yarnpkg.com/prebuild-install/-/prebuild-install-7.1.3.tgz#d630abad2b147443f20a212917beae68b8092eec" + integrity sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug== + dependencies: + detect-libc "^2.0.0" + expand-template "^2.0.3" + github-from-package "0.0.0" + minimist "^1.2.3" + mkdirp-classic "^0.5.3" + napi-build-utils "^2.0.0" + node-abi "^3.3.0" + pump "^3.0.0" + rc "^1.2.7" + simple-get "^4.0.0" + tar-fs "^2.0.0" + tunnel-agent "^0.6.0" + +pump@^3.0.0: + version "3.0.4" + resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.4.tgz#1f313430527fa8b905622ebd22fe1444e757ab3c" + integrity sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA== + dependencies: + end-of-stream "^1.1.0" + once "^1.3.1" + +rc@^1.2.7: + version "1.2.8" + resolved "https://registry.yarnpkg.com/rc/-/rc-1.2.8.tgz#cd924bf5200a075b83c188cd6b9e211b7fc0d3ed" + integrity sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw== + dependencies: + deep-extend "^0.6.0" + ini "~1.3.0" + minimist "^1.2.0" + strip-json-comments "~2.0.1" + +readable-stream@^3.1.1, readable-stream@^3.4.0: + version "3.6.2" + resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.2.tgz#56a9b36ea965c00c5a93ef31eb111a0f11056967" + integrity sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA== + dependencies: + inherits "^2.0.3" + string_decoder "^1.1.1" + util-deprecate "^1.0.1" + rollup@^4.43.0: version "4.60.1" resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.60.1.tgz#b4aa2bcb3a5e1437b5fad40d43fe42d4bde7a42d" @@ -574,11 +1019,35 @@ rollup@^4.43.0: "@rollup/rollup-win32-x64-msvc" "4.60.1" fsevents "~2.3.2" +safe-buffer@^5.0.1, safe-buffer@~5.2.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +semver@^7.3.5, semver@^7.6.0: + version "7.8.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.8.1.tgz#bf4970b5e70fda0686363cc18bfe8805d5ed957e" + integrity sha512-rkVq3IXh+4FDGch+KwzX3aV9W3kO54GyEgpvBzSyctDA6Xtd7RJQV1xmXbeQp5v7+VzLOfVqiutSE6GICgPFvg== + siginfo@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/siginfo/-/siginfo-2.0.0.tgz#32e76c70b79724e3bb567cb9d543eb858ccfaf30" integrity sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g== +simple-concat@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/simple-concat/-/simple-concat-1.0.1.tgz#f46976082ba35c2263f1c8ab5edfe26c41c9552f" + integrity sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q== + +simple-get@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/simple-get/-/simple-get-4.0.1.tgz#4a39db549287c979d352112fa03fd99fd6bc3543" + integrity sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA== + dependencies: + decompress-response "^6.0.0" + once "^1.3.1" + simple-concat "^1.0.0" + source-map-js@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46" @@ -594,6 +1063,39 @@ std-env@^3.10.0: resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.10.0.tgz#d810b27e3a073047b2b5e40034881f5ea6f9c83b" integrity sha512-5GS12FdOZNliM5mAOxFRg7Ir0pWz8MdpYm6AY6VPkGpbA7ZzmbzNcBJQ0GPvvyWgcY7QAhCgf9Uy89I03faLkg== +string_decoder@^1.1.1: + version "1.3.0" + resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.3.0.tgz#42f114594a46cf1a8e30b0a84f56c78c3edac21e" + integrity sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA== + dependencies: + safe-buffer "~5.2.0" + +strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== + +tar-fs@^2.0.0: + version "2.1.4" + resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-2.1.4.tgz#800824dbf4ef06ded9afea4acafe71c67c76b930" + integrity sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ== + dependencies: + chownr "^1.1.1" + mkdirp-classic "^0.5.2" + pump "^3.0.0" + tar-stream "^2.1.4" + +tar-stream@^2.1.4: + version "2.2.0" + resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-2.2.0.tgz#acad84c284136b060dc3faa64474aa9aebd77287" + integrity sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ== + dependencies: + bl "^4.0.3" + end-of-stream "^1.4.1" + fs-constants "^1.0.0" + inherits "^2.0.3" + readable-stream "^3.1.1" + tinybench@^2.9.0: version "2.9.0" resolved "https://registry.yarnpkg.com/tinybench/-/tinybench-2.9.0.tgz#103c9f8ba6d7237a47ab6dd1dcff77251863426b" @@ -617,16 +1119,59 @@ tinyrainbow@^3.0.3: resolved "https://registry.yarnpkg.com/tinyrainbow/-/tinyrainbow-3.0.3.tgz#984a5b1c1b25854a9b6bccbe77964d0593d1ea42" integrity sha512-PSkbLUoxOFRzJYjjxHJt9xro7D+iilgMX/C9lawzVuYiIdcihh9DXmVibBe8lmcFrRi/VzlPjBxbN7rH24q8/Q== +tunnel-agent@^0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" + integrity sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w== + dependencies: + safe-buffer "^5.0.1" + typescript@^5.9.3: version "5.9.3" resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.9.3.tgz#5b4f59e15310ab17a216f5d6cf53ee476ede670f" integrity sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw== +uint8array-tools@^0.0.8: + version "0.0.8" + resolved "https://registry.yarnpkg.com/uint8array-tools/-/uint8array-tools-0.0.8.tgz#712bab001f8347bd782f45bc47c76ffff32d1e0b" + integrity sha512-xS6+s8e0Xbx++5/0L+yyexukU7pz//Yg6IHg3BKhXotg1JcYtgxVcUctQ0HxLByiJzpAkNFawz1Nz5Xadzo82g== + +uint8array-tools@^0.0.9: + version "0.0.9" + resolved "https://registry.yarnpkg.com/uint8array-tools/-/uint8array-tools-0.0.9.tgz#e29e6d05f3472273db1b0e370ac1d91e4a0a4e6f" + integrity sha512-9vqDWmoSXOoi+K14zNaf6LBV51Q8MayF0/IiQs3GlygIKUYtog603e6virExkjjFosfJUBI4LhbQK1iq8IG11A== + undici-types@~7.16.0: version "7.16.0" resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-7.16.0.tgz#ffccdff36aea4884cbfce9a750a0580224f58a46" integrity sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw== +util-deprecate@^1.0.1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" + integrity sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw== + +varuint-bitcoin@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/varuint-bitcoin/-/varuint-bitcoin-2.0.0.tgz#59a53845a87ad18c42f184a3d325074465341523" + integrity sha512-6QZbU/rHO2ZQYpWFDALCDSRsXbAs1VOEmXAxtbtjLtKuMJ/FQ8YbhfxlaiKv5nklci0M6lZtlZyxo9Q+qNnyog== + dependencies: + uint8array-tools "^0.0.8" + +viem@2.46.3: + version "2.46.3" + resolved "https://registry.yarnpkg.com/viem/-/viem-2.46.3.tgz#0927e4da4380d6c87c7506a7c6b14cbdc0f3802f" + integrity sha512-2LJS+Hyh2sYjHXQtzfv1kU9pZx9dxFzvoU/ZKIcn0FNtOU0HQuIICuYdWtUDFHaGXbAdVo8J1eCvmjkL9JVGwg== + dependencies: + "@noble/curves" "1.9.1" + "@noble/hashes" "1.8.0" + "@scure/bip32" "1.7.0" + "@scure/bip39" "1.6.0" + abitype "1.2.3" + isows "1.0.7" + ox "0.12.4" + ws "8.18.3" + "vite@^6.0.0 || ^7.0.0": version "7.3.2" resolved "https://registry.yarnpkg.com/vite/-/vite-7.3.2.tgz#cb041794d4c1395e28baea98198fd6e8f4b96b5c" @@ -674,3 +1219,26 @@ why-is-node-running@^2.3.0: dependencies: siginfo "^2.0.0" stackback "0.0.2" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +ws-electrumx-client@1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/ws-electrumx-client/-/ws-electrumx-client-1.0.5.tgz#dc70508cbb66eec155133ad5934fec0d0174bf37" + integrity sha512-pBjfFqb9j2FBz7NPbnd8r2lOYanEw8ACzfKxOtHCgEGqre5QiTax5XHLVgbsiOvST0vmsHAiMtkJPvsZm77PIQ== + dependencies: + isomorphic-ws "^5.0.0" + ws "^8.12.1" + +ws@8.18.3: + version "8.18.3" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.18.3.tgz#b56b88abffde62791c639170400c93dcb0c95472" + integrity sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg== + +ws@^8.12.1: + version "8.21.0" + resolved "https://registry.yarnpkg.com/ws/-/ws-8.21.0.tgz#012e413fc07429945121b0c153158c4343086951" + integrity sha512-Vsp28b7DRcimFQvrqu2Wek3z1iYxDCWqHYB8Qsnk/S4RfaCQzPGPyBNuVjJV3cd6UiKtUtp6sNM77gWvzcCH+g==