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":[]}