a6ea29f59ecf21d3b97f481f1b2bec2cc49714968bc63d78180e295d23b9a919.json raw
1 {"ast":null,"code":"import _asyncToGenerator from \"/home/mleku/src/orly.dev/next/signer/node_modules/@babel/runtime/helpers/esm/asyncToGenerator.js\";\nimport { CashuMint as Mint, CashuWallet as Wallet, getDecodedToken, getEncodedTokenV4, CheckStateEnum } from '@cashu/cashu-ts';\nimport * as i0 from \"@angular/core\";\nimport * as i1 from \"@common\";\n/**\n * Angular service for managing Cashu ecash wallets\n */\nexport let CashuService = /*#__PURE__*/(() => {\n class CashuService {\n storageService;\n wallets = new Map();\n constructor(storageService) {\n this.storageService = storageService;\n }\n /**\n * Get all Cashu mints from storage\n */\n getMints() {\n const sessionData = this.storageService.getBrowserSessionHandler().browserSessionData;\n return sessionData?.cashuMints ?? [];\n }\n /**\n * Get a single Cashu mint by ID\n */\n getMint(mintId) {\n return this.getMints().find(m => m.id === mintId);\n }\n /**\n * Get a mint by URL\n */\n getMintByUrl(mintUrl) {\n const normalizedUrl = mintUrl.replace(/\\/$/, '');\n return this.getMints().find(m => m.mintUrl === normalizedUrl);\n }\n /**\n * Add a new Cashu mint connection\n */\n addMint(name, mintUrl) {\n var _this = this;\n return _asyncToGenerator(function* () {\n // Test the mint connection first\n yield _this.testMintConnection(mintUrl);\n // Add to storage\n return yield _this.storageService.addCashuMint({\n name,\n mintUrl,\n unit: 'sat'\n });\n })();\n }\n /**\n * Delete a Cashu mint connection\n */\n deleteMint(mintId) {\n var _this2 = this;\n return _asyncToGenerator(function* () {\n // Remove from cache\n _this2.wallets.delete(mintId);\n yield _this2.storageService.deleteCashuMint(mintId);\n })();\n }\n /**\n * Get or create a wallet for a mint\n */\n getWallet(mintId) {\n var _this3 = this;\n return _asyncToGenerator(function* () {\n // Check cache\n const cached = _this3.wallets.get(mintId);\n if (cached) {\n return cached;\n }\n // Get mint data from storage\n const mintData = _this3.getMint(mintId);\n if (!mintData) {\n throw new Error('Mint not found');\n }\n // Create mint and wallet instances\n const mint = new Mint(mintData.mintUrl);\n const wallet = new Wallet(mint, {\n unit: mintData.unit || 'sat'\n });\n // Load mint keys\n yield wallet.loadMint();\n // Cache it\n const cachedWallet = {\n wallet,\n mint,\n mintId\n };\n _this3.wallets.set(mintId, cachedWallet);\n return cachedWallet;\n })();\n }\n /**\n * Test a mint connection by fetching its info\n */\n testMintConnection(mintUrl) {\n return _asyncToGenerator(function* () {\n const normalizedUrl = mintUrl.replace(/\\/$/, '');\n const mint = new Mint(normalizedUrl);\n const info = yield mint.getInfo();\n return {\n name: info.name,\n description: info.description,\n version: info.version,\n contact: info.contact?.map(c => ({\n method: c.method,\n info: c.info\n })),\n nuts: info.nuts\n };\n })();\n }\n /**\n * Decode a Cashu token without claiming it\n */\n decodeToken(token) {\n try {\n const decoded = getDecodedToken(token);\n const proofs = decoded.proofs;\n const amount = proofs.reduce((sum, p) => sum + p.amount, 0);\n return {\n mint: decoded.mint,\n unit: decoded.unit || 'sat',\n amount,\n proofs\n };\n } catch {\n return null;\n }\n }\n /**\n * Receive a Cashu token\n * This validates and claims the proofs, then stores them\n */\n receive(token) {\n var _this4 = this;\n return _asyncToGenerator(function* () {\n // Decode the token\n const decoded = _this4.decodeToken(token);\n if (!decoded) {\n throw new Error('Invalid token format');\n }\n // Check if we have this mint\n let mintData = _this4.getMintByUrl(decoded.mint);\n // If we don't have this mint, add it automatically\n if (!mintData) {\n // Use the mint URL as the name initially\n const urlObj = new URL(decoded.mint);\n mintData = yield _this4.storageService.addCashuMint({\n name: urlObj.hostname,\n mintUrl: decoded.mint,\n unit: decoded.unit || 'sat'\n });\n }\n // Get the wallet for this mint\n const {\n wallet\n } = yield _this4.getWallet(mintData.id);\n // Receive the token (this swaps proofs with the mint)\n const receivedProofs = yield wallet.receive(token);\n // Convert to our proof format with timestamp\n const now = new Date().toISOString();\n const newProofs = receivedProofs.map(p => ({\n id: p.id,\n amount: p.amount,\n secret: p.secret,\n C: p.C,\n receivedAt: now\n }));\n // Merge with existing proofs\n const existingProofs = mintData.proofs || [];\n const allProofs = [...existingProofs, ...newProofs];\n // Update storage\n yield _this4.storageService.updateCashuMintProofs(mintData.id, allProofs);\n // Calculate received amount\n const amount = newProofs.reduce((sum, p) => sum + p.amount, 0);\n return {\n amount,\n mintUrl: decoded.mint,\n mintId: mintData.id\n };\n })();\n }\n /**\n * Send Cashu tokens\n * Creates an encoded token from existing proofs\n */\n send(mintId, amount) {\n var _this5 = this;\n return _asyncToGenerator(function* () {\n const mintData = _this5.getMint(mintId);\n if (!mintData) {\n throw new Error('Mint not found');\n }\n // Check we have enough balance\n const balance = _this5.getBalance(mintId);\n if (balance < amount) {\n throw new Error(`Insufficient balance. Have ${balance} sats, need ${amount} sats`);\n }\n // Get the wallet\n const {\n wallet\n } = yield _this5.getWallet(mintId);\n // Convert our proofs to the format cashu-ts expects\n const proofs = mintData.proofs.map(p => ({\n id: p.id,\n amount: p.amount,\n secret: p.secret,\n C: p.C\n }));\n // Send - this returns send proofs and keep proofs (change)\n const {\n send,\n keep\n } = yield wallet.send(amount, proofs);\n // Create the token to share\n const token = {\n mint: mintData.mintUrl,\n proofs: send,\n unit: mintData.unit || 'sat'\n };\n const encodedToken = getEncodedTokenV4(token);\n // Update our stored proofs to only keep the change (new proofs from mint)\n const now = new Date().toISOString();\n const keepProofs = keep.map(p => ({\n id: p.id,\n amount: p.amount,\n secret: p.secret,\n C: p.C,\n receivedAt: now\n }));\n yield _this5.storageService.updateCashuMintProofs(mintId, keepProofs);\n return {\n token: encodedToken,\n amount\n };\n })();\n }\n /**\n * Check if any proofs have been spent\n * Removes spent proofs from storage\n */\n checkProofsSpent(mintId) {\n var _this6 = this;\n return _asyncToGenerator(function* () {\n const mintData = _this6.getMint(mintId);\n if (!mintData) {\n throw new Error('Mint not found');\n }\n if (mintData.proofs.length === 0) {\n return 0;\n }\n const {\n wallet\n } = yield _this6.getWallet(mintId);\n // Only the secret field is needed for checking proof states\n const proofsToCheck = mintData.proofs.map(p => ({\n secret: p.secret\n }));\n // Check which proofs are spent using v3 API\n const proofStates = yield wallet.checkProofsStates(proofsToCheck);\n // Filter out spent proofs\n const unspentProofs = [];\n let removedAmount = 0;\n for (let i = 0; i < mintData.proofs.length; i++) {\n if (proofStates[i].state !== CheckStateEnum.SPENT) {\n unspentProofs.push(mintData.proofs[i]);\n } else {\n removedAmount += mintData.proofs[i].amount;\n }\n }\n // Update storage if any were spent\n if (removedAmount > 0) {\n yield _this6.storageService.updateCashuMintProofs(mintId, unspentProofs);\n }\n return removedAmount;\n })();\n }\n /**\n * Create a mint quote (Lightning invoice) for depositing sats\n * Returns a Lightning invoice that when paid will allow minting tokens\n */\n createMintQuote(mintId, amount) {\n var _this7 = this;\n return _asyncToGenerator(function* () {\n const mintData = _this7.getMint(mintId);\n if (!mintData) {\n throw new Error('Mint not found');\n }\n if (amount <= 0) {\n throw new Error('Amount must be greater than 0');\n }\n const {\n wallet\n } = yield _this7.getWallet(mintId);\n // Create a mint quote - this returns a Lightning invoice\n const quote = yield wallet.createMintQuote(amount);\n return {\n quoteId: quote.quote,\n invoice: quote.request,\n amount: amount,\n state: quote.state,\n expiry: quote.expiry\n };\n })();\n }\n /**\n * Check the status of a mint quote\n * Returns the current state (UNPAID, PAID, ISSUED)\n */\n checkMintQuote(mintId, quoteId) {\n var _this8 = this;\n return _asyncToGenerator(function* () {\n const mintData = _this8.getMint(mintId);\n if (!mintData) {\n throw new Error('Mint not found');\n }\n const {\n wallet\n } = yield _this8.getWallet(mintId);\n // Check the quote status\n const quote = yield wallet.checkMintQuote(quoteId);\n return {\n quoteId: quote.quote,\n invoice: quote.request,\n amount: 0,\n // Amount not returned in check response\n state: quote.state,\n expiry: quote.expiry\n };\n })();\n }\n /**\n * Mint tokens after paying the Lightning invoice\n * This claims the tokens and stores them\n */\n mintTokens(mintId, amount, quoteId) {\n var _this9 = this;\n return _asyncToGenerator(function* () {\n const mintData = _this9.getMint(mintId);\n if (!mintData) {\n throw new Error('Mint not found');\n }\n const {\n wallet\n } = yield _this9.getWallet(mintId);\n // Mint the proofs\n const mintedProofs = yield wallet.mintProofs(amount, quoteId);\n // Convert to our proof format with timestamp\n const now = new Date().toISOString();\n const newProofs = mintedProofs.map(p => ({\n id: p.id,\n amount: p.amount,\n secret: p.secret,\n C: p.C,\n receivedAt: now\n }));\n // Merge with existing proofs\n const existingProofs = mintData.proofs || [];\n const allProofs = [...existingProofs, ...newProofs];\n // Update storage\n yield _this9.storageService.updateCashuMintProofs(mintId, allProofs);\n // Calculate minted amount\n const mintedAmount = newProofs.reduce((sum, p) => sum + p.amount, 0);\n return {\n amount: mintedAmount,\n mintId: mintId\n };\n })();\n }\n /**\n * Get balance for a specific mint (in satoshis)\n */\n getBalance(mintId) {\n const mintData = this.getMint(mintId);\n if (!mintData) {\n return 0;\n }\n return mintData.proofs.reduce((sum, p) => sum + p.amount, 0);\n }\n /**\n * Get proofs for a specific mint\n */\n getProofs(mintId) {\n const mintData = this.getMint(mintId);\n if (!mintData) {\n return [];\n }\n return mintData.proofs;\n }\n /**\n * Get total balance across all mints (in satoshis)\n */\n getTotalBalance() {\n const mints = this.getMints();\n return mints.reduce((sum, m) => sum + this.getBalance(m.id), 0);\n }\n /**\n * Get cached total balance (same as getTotalBalance for Cashu since it's all local)\n */\n getCachedTotalBalance() {\n return this.getTotalBalance();\n }\n /**\n * Format a balance for display (Cashu uses satoshis, not millisatoshis)\n */\n formatBalance(sats) {\n if (sats === undefined) return '—';\n return sats.toLocaleString('en-US');\n }\n static ɵfac = function CashuService_Factory(__ngFactoryType__) {\n return new (__ngFactoryType__ || CashuService)(i0.ɵɵinject(i1.StorageService));\n };\n static ɵprov = /*@__PURE__*/i0.ɵɵdefineInjectable({\n token: CashuService,\n factory: CashuService.ɵfac,\n providedIn: 'root'\n });\n }\n return CashuService;\n})();","map":null,"metadata":{},"sourceType":"module","externalDependencies":[]}