aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/nwc-sw-test.js32
1 files changed, 23 insertions, 9 deletions
diff --git a/tools/nwc-sw-test.js b/tools/nwc-sw-test.js
index 5a15d48..376a12e 100644
--- a/tools/nwc-sw-test.js
+++ b/tools/nwc-sw-test.js
@@ -47,11 +47,16 @@ function makeReq(method, params = {}, scheme = 'nip44_v2', ageSec = 0) {
function harness({ rec = baseRec(), recs = null, answered = false } = {}) {
const published = [];
+ const declined = []; // wait replies left with the notifier (sent only if nobody answers)
const fetchFn = async (url, opts) => {
if (url.includes('/publish')) {
published.push(JSON.parse(opts.body).event);
return { ok: true, json: async () => ({ ok: true }) };
}
+ if (url.includes('/decline')) {
+ declined.push(JSON.parse(opts.body).event);
+ return { ok: true, json: async () => ({ ok: true, scheduled: true }) };
+ }
if (url.includes('/claim')) {
return { ok: true, json: async () => ({ ok: true }) };
}
@@ -73,7 +78,7 @@ function harness({ rec = baseRec(), recs = null, answered = false } = {}) {
? nip44.decrypt(ev.content, nip44.getConversationKey(clientSk, conn.servicePk))
: nip04.decrypt(clientSk, conn.servicePk, ev.content));
};
- return { deps, published, decryptReply };
+ return { deps, published, declined, decryptReply };
}
const ev = (e) => JSON.parse(JSON.stringify(e)); // strip verified symbol like a push payload would
@@ -137,15 +142,19 @@ console.log('\n[merchant methods (BTCPay)]');
check('…one still in flight (ASP unreachable here) → outgoing, pending, inside the push budget', r2.type === 'outgoing' && r2.state === 'pending' && Date.now() - t0 < 4000, JSON.stringify(r2) + ` ${Date.now() - t0} ms`);
}
{
- const { deps } = harness(); // a mirror without receive keys
- check('make_invoice on an old mirror → wake the user', (await respondFromBg({ type: 'nwc', event: ev(makeReq('make_invoice', { amount: 21000 })) }, deps)) === false);
+ const { deps, declined, decryptReply } = harness(); // a mirror without receive keys
+ const handled = await respondFromBg({ type: 'nwc', event: ev(makeReq('make_invoice', { amount: 21000 })) }, deps);
+ const r = declined.length ? decryptReply(declined[0]) : null;
+ check('make_invoice on an old mirror → wake the user, wait reply left behind', handled === false && declined.length === 1 && r.result_type === 'make_invoice' && r.error?.code === 'OTHER', JSON.stringify(r));
}
console.log('\n[guards]');
{
- const { deps } = harness();
+ const { deps, published, declined } = harness();
const stale = ev(makeReq('get_balance', {}, 'nip44_v2', 300));
- check('stale request refused', (await respondFromBg({ type: 'nwc', event: stale }, deps)) === false);
+ // a push that sat at APNs past the request window: nothing to answer, and
+ // no "Payment request" for it either (true = handled quietly)
+ check('stale request ignored quietly', (await respondFromBg({ type: 'nwc', event: stale }, deps)) === true && !published.length && !declined.length);
}
{
const { deps } = harness();
@@ -185,16 +194,21 @@ const INV21 = 'lnbc210n1p4xuk2wpp506wkjr0xk3677nu7je9c55vq4lzlkyd0ztcq2mlvumap0z
{
const rec = baseRec();
rec.mgr.vtxos = []; // nothing spendable in the mirror
- const { deps } = harness({ rec });
+ const { deps, published, declined, decryptReply } = harness({ rec });
const handled = await respondFromBg({ type: 'nwc', event: ev(makeReq('pay_invoice', { invoice: INV21 })) }, deps);
- check('empty mirror → wake the user', handled === false);
+ const r = declined.length ? decryptReply(declined[0]) : null;
+ // the wait reply is NOT published by the worker: the notifier holds it and
+ // sends it only if nobody answers — a sibling's payment can't be shouted over
+ check('empty mirror → wake the user, wait reply left with the notifier', handled === false && published.length === 0 && declined.length === 1
+ && r.result_type === 'pay_invoice' && r.error?.code === 'OTHER' && /open the app/.test(r.error.message), JSON.stringify(r));
+ check('…addressed to the request', declined[0].kind === 23195 && declined[0].tags.some((t) => t[0] === 'e'));
}
{
const rec = baseRec();
delete rec.keys['5']; // change index outside the mirrored window
- const { deps } = harness({ rec });
+ const { deps, declined } = harness({ rec });
const handled = await respondFromBg({ type: 'nwc', event: ev(makeReq('pay_invoice', { invoice: INV21 })) }, deps);
- check('exhausted key window → wake the user', handled === false);
+ check('exhausted key window → wake the user, wait reply left behind', handled === false && declined.length === 1);
}
console.log('\n[pay outcome]');