Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
da1d1b0d53 | ||
|
|
0ab66479d9 | ||
|
|
1129fb9341 | ||
|
|
4afe3f6d3e | ||
|
|
21bbd0fab1 | ||
|
|
bb3b5604a1 |
64
.gitignore
vendored
Normal file
64
.gitignore
vendored
Normal file
@@ -0,0 +1,64 @@
|
||||
# Dependencies
|
||||
node_modules/
|
||||
|
||||
# Production builds
|
||||
dist/
|
||||
dist-ssr/
|
||||
build/
|
||||
|
||||
# Vite and tooling caches
|
||||
.vite/
|
||||
.esbuild/
|
||||
.rollup.cache/
|
||||
.parcel-cache/
|
||||
.turbo/
|
||||
|
||||
# Logs
|
||||
logs/
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
lerna-debug.log*
|
||||
|
||||
# Environment files
|
||||
.env
|
||||
.env.local
|
||||
.env.*.local
|
||||
.env.production.local
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
!.env.example
|
||||
|
||||
# Coverage
|
||||
coverage/
|
||||
|
||||
# TypeScript build info
|
||||
*.tsbuildinfo
|
||||
|
||||
# Editor directories and files
|
||||
.vscode/
|
||||
.idea/
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
*.sln
|
||||
*.sw?
|
||||
*~
|
||||
|
||||
# OS metadata
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Misc secrets/keys (if present)
|
||||
*.pem
|
||||
*.key
|
||||
*.crt
|
||||
*.p12
|
||||
*.pfx
|
||||
|
||||
# Package tarballs
|
||||
*.tgz
|
||||
|
||||
|
||||
@@ -45,4 +45,5 @@ We reserve the right to terminate or suspend access to our service immediately,
|
||||
|
||||
## 8. Changes to Terms
|
||||
|
||||
We reserve the right to modify these terms at any time. We will notify users of any changes by updating the date at the top of this page.
|
||||
We reserve the right to modify these terms at any time. We will notify users of any changes by updating the date at the top of this page.
|
||||
|
||||
@@ -11,7 +11,7 @@ export const apiService = {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
body: JSON.stringify({
|
||||
identifier: pubkey,
|
||||
npub: pubkey,
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -48,7 +48,7 @@ export const apiService = {
|
||||
'X-Api-Key': apiKey,
|
||||
},
|
||||
body: JSON.stringify({
|
||||
identifier: pubkey,
|
||||
npub: pubkey,
|
||||
}),
|
||||
});
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ const api = axios.create({
|
||||
headers: {
|
||||
'X-Api-Key': API_KEY,
|
||||
'Content-Type': 'application/json',
|
||||
Accept: 'application/json',
|
||||
},
|
||||
});
|
||||
|
||||
@@ -62,16 +63,26 @@ export const lnbitsService = {
|
||||
extra = {},
|
||||
}: CreateInvoiceParams): Promise<Invoice> {
|
||||
try {
|
||||
const response = await api.post('/api/v1/payments', {
|
||||
// Build a V1-safe payload: only include known/supported fields when defined
|
||||
const payload: Record<string, any> = {
|
||||
out: false,
|
||||
amount,
|
||||
memo,
|
||||
unit,
|
||||
webhook,
|
||||
internal,
|
||||
extra,
|
||||
});
|
||||
return response.data;
|
||||
};
|
||||
if (unit) payload.unit = unit;
|
||||
if (webhook) payload.webhook = webhook;
|
||||
if (typeof internal === 'boolean') payload.internal = internal;
|
||||
if (extra && Object.keys(extra).length > 0) payload.extra = extra;
|
||||
|
||||
const response = await api.post('/api/v1/payments', payload);
|
||||
const data = response.data ?? {};
|
||||
// Normalize response to ensure payment_request is always populated for the UI
|
||||
const normalized: Invoice = {
|
||||
...data,
|
||||
payment_request: data.payment_request || data.bolt11,
|
||||
bolt11: data.bolt11 || data.payment_request,
|
||||
};
|
||||
return normalized;
|
||||
} catch (error) {
|
||||
console.error('Error creating invoice:', error);
|
||||
throw error;
|
||||
@@ -82,10 +93,13 @@ export const lnbitsService = {
|
||||
async checkPayment(paymentHash: string): Promise<PaymentStatus> {
|
||||
try {
|
||||
const response = await api.get(`/api/v1/payments/${paymentHash}`);
|
||||
const data = response.data || {};
|
||||
// Normalize potential V1 shapes
|
||||
const paid: boolean = (data.paid === true) || (data.status === 'paid') || (data.settled === true);
|
||||
return {
|
||||
paid: response.data.paid,
|
||||
preimage: response.data.preimage,
|
||||
details: response.data.details,
|
||||
paid,
|
||||
preimage: data.preimage,
|
||||
details: data.details,
|
||||
};
|
||||
} catch (error) {
|
||||
console.error('Error checking payment:', error);
|
||||
@@ -150,17 +164,24 @@ export const lnbitsService = {
|
||||
|
||||
// Long poll payment status
|
||||
async longPollPayment(paymentHash: string, timeout = 60000): Promise<boolean> {
|
||||
try {
|
||||
const response = await api.get(`/public/v1/payment/${paymentHash}`, {
|
||||
timeout,
|
||||
});
|
||||
return response.data.paid;
|
||||
} catch (error) {
|
||||
if (axios.isAxiosError(error) && error.code === 'ECONNABORTED') {
|
||||
return false; // Timeout reached
|
||||
// Fallback to authenticated polling against V1 status endpoint to ensure compatibility
|
||||
const start = Date.now();
|
||||
const pollIntervalMs = 2000;
|
||||
while (Date.now() - start < timeout) {
|
||||
try {
|
||||
const status = await this.checkPayment(paymentHash);
|
||||
if (status.paid) return true;
|
||||
} catch (error) {
|
||||
// If transient error, keep polling until timeout
|
||||
if (axios.isAxiosError(error) && (error.response?.status ?? 0) >= 500) {
|
||||
// continue
|
||||
} else {
|
||||
console.error('Error polling payment:', error);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
console.error('Error polling payment:', error);
|
||||
throw error;
|
||||
await new Promise((r) => setTimeout(r, pollIntervalMs));
|
||||
}
|
||||
return false;
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user