diff --git a/apps/web/src/lib/pricing.js b/apps/web/src/lib/pricing.js index a9466a6..c9965d6 100644 --- a/apps/web/src/lib/pricing.js +++ b/apps/web/src/lib/pricing.js @@ -162,7 +162,12 @@ export function gatewayOptions(priceCents) { work: 17, css: true, paths: ['/i/', '/feeds/', '/tlds', '/tlds/'], - when: (_request, url) => url.pathname.startsWith('/i/') || url.search.length > 1, + // An invite link (/i/INV-…) is a person's first visit, often opened from a + // chat whose link preview cannot run the script; it is not an item page + // and nothing links to it, so the swarm never walks it. + when: (_request, url) => + (url.pathname.startsWith('/i/') && !/^\/i\/inv-/i.test(url.pathname)) || + url.search.length > 1, }, onSale: async (sale) => { console.log('[x402] sold a pass', { diff --git a/test/pricing.test.js b/test/pricing.test.js index 17bfcb4..f831d95 100644 --- a/test/pricing.test.js +++ b/test/pricing.test.js @@ -178,4 +178,10 @@ describe('the script challenge (faceted listings, item pages)', async () => { expect(on('/feeds/new')).toBe(false); expect(on('/feeds/new?')).toBe(false); }); + + test('an invite link is a first visit, not an item page', () => { + expect(on('/i/INV-7K3M-QX9D-2F8H')).toBe(false); + expect(on('/i/inv-7k3m-qx9d-2f8h')).toBe(false); + expect(on('/i/INV-7K3M-QX9D-2F8H?x=1')).toBe(true); + }); });