Upgrade to cashu-ts v4 and drop unused deps.

Adapt amount handling for v4 Amount objects, replace axios/uuid with fetch and crypto.randomUUID, and remove dead helpers.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Michilis
2026-07-23 03:46:59 +00:00
co-authored by Cursor
parent bd18271957
commit 449a8dda0d
9 changed files with 696 additions and 1197 deletions
+20 -39
View File
@@ -1,6 +1,21 @@
const axios = require('axios');
const bolt11 = require('bolt11');
/**
* GET a JSON resource with a 10s timeout using native fetch
*/
async function fetchJson(url) {
const response = await fetch(url, {
signal: AbortSignal.timeout(10000),
headers: { 'User-Agent': 'Cashu-Redeem-API/1.0.0' }
});
if (!response.ok) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
return response.json();
}
class LightningComponent {
constructor() {
this.allowedDomains = process.env.ALLOW_REDEEM_DOMAINS
@@ -82,17 +97,8 @@ class LightningComponent {
*/
async fetchLNURLpResponse(lnurlpUrl) {
try {
const response = await axios.get(lnurlpUrl, {
timeout: 10000,
headers: { 'User-Agent': 'Cashu-Redeem-API/1.0.0' }
});
const data = await fetchJson(lnurlpUrl);
if (response.status !== 200) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const data = response.data;
if (data.status === 'ERROR') {
throw new Error(data.reason || 'LNURLp endpoint returned error');
}
@@ -103,7 +109,8 @@ class LightningComponent {
return data;
} catch (error) {
if (error.code === 'ECONNREFUSED' || error.code === 'ENOTFOUND') {
const code = error.cause?.code;
if (code === 'ECONNREFUSED' || code === 'ENOTFOUND') {
throw new Error('Unable to connect to Lightning address provider');
}
throw new Error(`LNURLp fetch failed: ${error.message}`);
@@ -122,17 +129,8 @@ class LightningComponent {
url.searchParams.set('comment', comment.substring(0, 144));
}
const response = await axios.get(url.toString(), {
timeout: 10000,
headers: { 'User-Agent': 'Cashu-Redeem-API/1.0.0' }
});
const data = await fetchJson(url.toString());
if (response.status !== 200) {
throw new Error(`HTTP ${response.status}: ${response.statusText}`);
}
const data = response.data;
if (data.status === 'ERROR') {
throw new Error(data.reason || 'Invoice generation failed');
}
@@ -226,23 +224,6 @@ class LightningComponent {
}
}
/**
* Decode Lightning invoice (basic parsing)
*/
parseInvoice(bolt11Invoice) {
try {
if (!bolt11Invoice.toLowerCase().startsWith('lnbc') && !bolt11Invoice.toLowerCase().startsWith('lntb')) {
throw new Error('Invalid Lightning invoice format');
}
return {
bolt11: bolt11Invoice,
network: bolt11Invoice.toLowerCase().startsWith('lnbc') ? 'mainnet' : 'testnet'
};
} catch (error) {
throw new Error(`Invoice parsing failed: ${error.message}`);
}
}
/**
* Verify that a Lightning invoice is valid and for the expected amount
*/