Merge branch 'fix-zap-amount-zero' into 'main'

Get zap amount from zap receipt if not present in zap request

See merge request soapbox-pub/ditto!385
This commit is contained in:
Alex Gleason 2024-06-18 00:16:09 +00:00
commit 1209b1c430
5 changed files with 60 additions and 12 deletions

View file

@ -62,7 +62,8 @@
"type-fest": "npm:type-fest@^4.3.0", "type-fest": "npm:type-fest@^4.3.0",
"unfurl.js": "npm:unfurl.js@^6.4.0", "unfurl.js": "npm:unfurl.js@^6.4.0",
"zod": "npm:zod@^3.23.8", "zod": "npm:zod@^3.23.8",
"~/fixtures/": "./fixtures/" "~/fixtures/": "./fixtures/",
"light-bolt11-decoder": "npm:light-bolt11-decoder"
}, },
"lint": { "lint": {
"include": ["src/", "scripts/"], "include": ["src/", "scripts/"],

13
deno.lock generated
View file

@ -37,7 +37,6 @@
"npm:@scure/base@^1.1.6": "npm:@scure/base@1.1.6", "npm:@scure/base@^1.1.6": "npm:@scure/base@1.1.6",
"npm:@scure/bip32@^1.4.0": "npm:@scure/bip32@1.4.0", "npm:@scure/bip32@^1.4.0": "npm:@scure/bip32@1.4.0",
"npm:@scure/bip39@^1.3.0": "npm:@scure/bip39@1.3.0", "npm:@scure/bip39@^1.3.0": "npm:@scure/bip39@1.3.0",
"npm:@types/node": "npm:@types/node@18.16.19",
"npm:comlink@^4.4.1": "npm:comlink@4.4.1", "npm:comlink@^4.4.1": "npm:comlink@4.4.1",
"npm:entities@^4.5.0": "npm:entities@4.5.0", "npm:entities@^4.5.0": "npm:entities@4.5.0",
"npm:fast-stable-stringify@^1.0.0": "npm:fast-stable-stringify@1.0.0", "npm:fast-stable-stringify@^1.0.0": "npm:fast-stable-stringify@1.0.0",
@ -47,6 +46,7 @@
"npm:kysely@0.27.3": "npm:kysely@0.27.3", "npm:kysely@0.27.3": "npm:kysely@0.27.3",
"npm:kysely@^0.27.2": "npm:kysely@0.27.3", "npm:kysely@^0.27.2": "npm:kysely@0.27.3",
"npm:kysely@^0.27.3": "npm:kysely@0.27.3", "npm:kysely@^0.27.3": "npm:kysely@0.27.3",
"npm:light-bolt11-decoder": "npm:light-bolt11-decoder@3.1.1",
"npm:linkify-plugin-hashtag@^4.1.1": "npm:linkify-plugin-hashtag@4.1.3_linkifyjs@4.1.3", "npm:linkify-plugin-hashtag@^4.1.1": "npm:linkify-plugin-hashtag@4.1.3_linkifyjs@4.1.3",
"npm:linkify-string@^4.1.1": "npm:linkify-string@4.1.3_linkifyjs@4.1.3", "npm:linkify-string@^4.1.1": "npm:linkify-string@4.1.3_linkifyjs@4.1.3",
"npm:linkifyjs@^4.1.1": "npm:linkifyjs@4.1.3", "npm:linkifyjs@^4.1.1": "npm:linkifyjs@4.1.3",
@ -313,10 +313,6 @@
"@types/trusted-types": "@types/trusted-types@2.0.7" "@types/trusted-types": "@types/trusted-types@2.0.7"
} }
}, },
"@types/node@18.16.19": {
"integrity": "sha512-IXl7o+R9iti9eBW4Wg2hx1xQDig183jj7YLn8F7udNceyfkbn1ZxmzZXuak20gR40D7pIkIY1kYGx5VIGbaHKA==",
"dependencies": {}
},
"@types/trusted-types@2.0.7": { "@types/trusted-types@2.0.7": {
"integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==",
"dependencies": {} "dependencies": {}
@ -636,6 +632,12 @@
"integrity": "sha512-lG03Ru+XyOJFsjH3OMY6R/9U38IjDPfnOfDgO3ynhbDr+Dz8fak+X6L62vqu3iybQnj+lG84OttBuU9KY3L9kA==", "integrity": "sha512-lG03Ru+XyOJFsjH3OMY6R/9U38IjDPfnOfDgO3ynhbDr+Dz8fak+X6L62vqu3iybQnj+lG84OttBuU9KY3L9kA==",
"dependencies": {} "dependencies": {}
}, },
"light-bolt11-decoder@3.1.1": {
"integrity": "sha512-sLg/KCwYkgsHWkefWd6KqpCHrLFWWaXTOX3cf6yD2hAzL0SLpX+lFcaFK2spkjbgzG6hhijKfORDc9WoUHwX0A==",
"dependencies": {
"@scure/base": "@scure/base@1.1.1"
}
},
"lilconfig@3.0.0": { "lilconfig@3.0.0": {
"integrity": "sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==", "integrity": "sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==",
"dependencies": {} "dependencies": {}
@ -1382,6 +1384,7 @@
"npm:iso-639-1@2.1.15", "npm:iso-639-1@2.1.15",
"npm:isomorphic-dompurify@^2.11.0", "npm:isomorphic-dompurify@^2.11.0",
"npm:kysely@^0.27.3", "npm:kysely@^0.27.3",
"npm:light-bolt11-decoder",
"npm:linkify-plugin-hashtag@^4.1.1", "npm:linkify-plugin-hashtag@^4.1.1",
"npm:linkify-string@^4.1.1", "npm:linkify-string@^4.1.1",
"npm:linkifyjs@^4.1.1", "npm:linkifyjs@^4.1.1",

View file

@ -8,8 +8,9 @@ import { z } from 'zod';
import { type AppController } from '@/app.ts'; import { type AppController } from '@/app.ts';
import { Conf } from '@/config.ts'; import { Conf } from '@/config.ts';
import { DittoDB } from '@/db/DittoDB.ts'; import { DittoDB } from '@/db/DittoDB.ts';
import { getUnattachedMediaByIds } from '@/db/unattached-media.ts'; import { getAmount } from '@/utils/bolt11.ts';
import { getAncestors, getAuthor, getDescendants, getEvent } from '@/queries.ts'; import { getAncestors, getAuthor, getDescendants, getEvent } from '@/queries.ts';
import { getUnattachedMediaByIds } from '@/db/unattached-media.ts';
import { renderEventAccounts } from '@/views.ts'; import { renderEventAccounts } from '@/views.ts';
import { renderReblog, renderStatus } from '@/views/mastodon/statuses.ts'; import { renderReblog, renderStatus } from '@/views/mastodon/statuses.ts';
import { Storages } from '@/storages.ts'; import { Storages } from '@/storages.ts';
@ -547,15 +548,22 @@ const zappedByController: AppController = async (c) => {
const store = await Storages.db(); const store = await Storages.db();
const amountSchema = z.coerce.number().int().nonnegative().catch(0); const amountSchema = z.coerce.number().int().nonnegative().catch(0);
const events: DittoEvent[] = (await store.query([{ kinds: [9735], '#e': [id], limit: 100 }])).map((event) => { const events = (await store.query([{ kinds: [9735], '#e': [id], limit: 100 }])).map((event) => {
const zapRequest = event.tags.find(([name]) => name === 'description')?.[1]; const zapRequestString = event.tags.find(([name]) => name === 'description')?.[1];
if (!zapRequest) return; if (!zapRequestString) return;
try { try {
return JSON.parse(zapRequest); const zapRequest = n.json().pipe(n.event()).parse(zapRequestString);
const amount = zapRequest?.tags.find(([name]: any) => name === 'amount')?.[1];
if (!amount) {
const amount = getAmount(event?.tags.find(([name]) => name === 'bolt11')?.[1]);
if (!amount) return;
zapRequest.tags.push(['amount', amount]);
}
return zapRequest;
} catch { } catch {
return; return;
} }
}).filter(Boolean); }).filter(Boolean) as DittoEvent[];
await hydrateEvents({ events, store }); await hydrateEvents({ events, store });

19
src/utils/bolt11.test.ts Normal file
View file

@ -0,0 +1,19 @@
import { assertEquals } from '@std/assert';
import { getAmount } from '@/utils/bolt11.ts';
Deno.test('Invoice is invalid', () => {
assertEquals(getAmount('hello'), undefined);
});
Deno.test('Invoice is undefined', () => {
assertEquals(getAmount(undefined), undefined);
});
Deno.test('Amount is 200000', () => {
assertEquals(
getAmount(
'lnbc2u1pn8qatypp5dweqaltlry2vgpxxyc0puxnc50335yznevj2g46wrhfm2694lhgqhp576ekte7lhhtsxdk6tfvkpyp8gdk2xccmuccdxwjd0fqdh34wfseqcqzzsxqyz5vqsp5n44zva7xndawg5l2r9d85v0tszwejtfzkc7v90d6c7d3nsdt0qds9qxpqysgqx2v2artsxmnfkpapdm9f5pahjs8etlpe7kcjue2kffhjg3jrtearstjvenr6lxzhpw3es4hpchzzeet7ul88elurfmvr9v94v0655rgpy7m7r5',
),
'200000',
);
});

17
src/utils/bolt11.ts Normal file
View file

@ -0,0 +1,17 @@
import bolt11 from 'light-bolt11-decoder';
/** Decodes the invoice and returns the amount in millisatoshis */
function getAmount(invoice: string | undefined): string | undefined {
if (!invoice) return;
try {
const amount = (bolt11.decode(invoice).sections as { name: string; value: string }[]).find(
({ name }) => name === 'amount',
)?.value;
return amount;
} catch {
return;
}
}
export { getAmount };