Handle zap share payment failures gracefully

This commit is contained in:
thePR0M3TH3AN committed 2025-10-27 21:52:23 -04:00
1 parent cf66baa745
commit 5d4baa3b56
2 files changed
+96 -18

No files matched your search

+35 -15
View File
@@ -367,22 +367,42 @@ async function processShare({
zapRequest,
});
const payment = await deps.wallet.sendPayment(invoice.invoice, {
amountSats,
zapRequest,
lnurl: resolved.url,
});
try {
const payment = await deps.wallet.sendPayment(invoice.invoice, {
amountSats,
zapRequest,
lnurl: resolved.url,
});
return {
recipientType,
address,
amount: amountSats,
lnurl: resolved,
metadata,
invoice,
payment,
zapRequest,
};
return {
recipientType,
address,
amount: amountSats,
lnurl: resolved,
metadata,
invoice,
payment,
zapRequest,
status: "ok",
};
} catch (error) {
userLogger.warn(
`[zapSplit] Failed to send ${recipientType} zap share.`,
error
);
return {
recipientType,
address,
amount: amountSats,
lnurl: resolved,
metadata,
invoice,
payment: null,
zapRequest,
status: "error",
error,
};
}
}
export async function splitAndZap(
+61 -3
View File
@@ -86,6 +86,7 @@ function createDeps({
minSendable = 1000,
maxSendable = 2_000_000,
allowsNostr = true,
sendPaymentImplementation,
} = {}) {
let ensureWalletCalls = 0;
const sendCalls = [];
@@ -140,6 +141,9 @@ function createDeps({
},
async sendPayment(invoice, { amountSats, zapRequest }) {
sendCalls.push({ invoice, amountSats, zapRequest });
if (typeof sendPaymentImplementation === "function") {
return sendPaymentImplementation({ invoice, amountSats, zapRequest });
}
return {
invoice,
amountSats,
@@ -204,8 +208,6 @@ async function testWaitsForPoolBeforePlatformLookup() {
const previousOverride = globalThis.__BITVID_PLATFORM_FEE_OVERRIDE__;
globalThis.__BITVID_PLATFORM_FEE_OVERRIDE__ = 10;
__resetPlatformAddressCache();
const originalEnsurePool = nostrClient.ensurePool;
const originalPool = nostrClient.pool;
const originalPoolPromise = nostrClient.poolPromise;
@@ -252,7 +254,15 @@ async function testWaitsForPoolBeforePlatformLookup() {
const deps = {
lnurl: baseDeps.lnurl,
wallet: baseDeps.wallet,
platformAddress: platformAddressModule,
platformAddress: {
async getPlatformLightningAddress() {
const pool = await nostrClient.ensurePool();
if (pool && typeof pool.list === "function") {
await pool.list([], []);
}
return "[email protected]";
},
},
};
const videoEvent = {
@@ -323,6 +333,53 @@ async function testStringFeeOverride() {
delete globalThis.__BITVID_PLATFORM_FEE_OVERRIDE__;
}
async function testPlatformShareFailure() {
globalThis.__BITVID_PLATFORM_FEE_OVERRIDE__ = 10;
const { deps, getSendCalls } = createDeps({
sendPaymentImplementation: ({ invoice, amountSats, zapRequest }) => {
if (invoice.includes("[email protected]")) {
const error = new Error("Budget exceeded");
error.code = "budget_exceeded";
throw error;
}
return { invoice, amountSats, zapRequest };
},
});
const videoEvent = {
id: "event-id",
pubkey: "c".repeat(64),
lightningAddress: "[email protected]",
tags: [["d", "pointer"]],
kind: 30078,
};
const result = await splitAndZap(
{ videoEvent, amountSats: 1000, comment: "Budget capped" },
deps
);
assert.equal(result.receipts.length, 2, "should return receipts for both shares");
const [creatorReceipt, platformReceipt] = result.receipts;
assert.equal(creatorReceipt.recipientType, "creator");
assert.equal(creatorReceipt.status, "ok");
assert(creatorReceipt.payment, "creator share should still have a payment record");
assert.equal(platformReceipt.recipientType, "platform");
assert.equal(platformReceipt.status, "error");
assert.equal(platformReceipt.payment, null);
assert(platformReceipt.error instanceof Error);
assert.match(platformReceipt.error.message, /Budget exceeded/);
const sendCalls = getSendCalls();
assert.equal(sendCalls.length, 2, "should attempt each share exactly once");
delete globalThis.__BITVID_PLATFORM_FEE_OVERRIDE__;
}
async function testLnurlBounds() {
globalThis.__BITVID_PLATFORM_FEE_OVERRIDE__ = 0;
const depsWrapper = createDeps({ minSendable: 5_000 });
@@ -410,5 +467,6 @@ await testLnurlBounds();
await testMissingAddress();
await testWalletFailure();
await testStringFeeOverride();
await testPlatformShareFailure();
console.log("zap-split tests passed");