verify description hash

This commit is contained in:
2023-02-04 13:30:05 +00:00
parent 1317669149
commit 140d87e071
3 changed files with 32 additions and 28 deletions

View File

@ -46,19 +46,19 @@ export default function Timeline({ subject, postsOnly = false, method, ignoreMod
function eventElement(e: TaggedRawEvent) { function eventElement(e: TaggedRawEvent) {
switch (e.kind) { switch (e.kind) {
case EventKind.SetMetadata: { case EventKind.SetMetadata: {
return <ProfilePreview pubkey={e.pubkey} className="card"/> return <ProfilePreview pubkey={e.pubkey} className="card" />
} }
case EventKind.TextNote: { case EventKind.TextNote: {
return <Note key={e.id} data={e} related={related.notes} ignoreModeration={ignoreModeration} /> return <Note key={e.id} data={e} related={related.notes} ignoreModeration={ignoreModeration} />
} }
case EventKind.ZapReceipt: { case EventKind.ZapReceipt: {
const zap = parseZap(e) const zap = parseZap(e)
return zap.e ? null : <Zap zap={zap} /> return zap.e ? null : <Zap zap={zap} key={e.id} />
} }
case EventKind.Reaction: case EventKind.Reaction:
case EventKind.Repost: { case EventKind.Repost: {
let eRef = e.tags.find(a => a[0] === "e")?.at(1); let eRef = e.tags.find(a => a[0] === "e")?.at(1);
return <NoteReaction data={e} key={e.id} root={parent.notes.find(a => a.id === eRef)}/> return <NoteReaction data={e} key={e.id} root={parent.notes.find(a => a.id === eRef)} />
} }
} }
} }
@ -66,12 +66,12 @@ export default function Timeline({ subject, postsOnly = false, method, ignoreMod
return ( return (
<div className="main-content"> <div className="main-content">
{latestFeed.length > 1 && (<div className="card latest-notes pointer" onClick={() => showLatest()}> {latestFeed.length > 1 && (<div className="card latest-notes pointer" onClick={() => showLatest()}>
<FontAwesomeIcon icon={faForward} size="xl"/> <FontAwesomeIcon icon={faForward} size="xl" />
&nbsp; &nbsp;
Show latest {latestFeed.length - 1} notes Show latest {latestFeed.length - 1} notes
</div>)} </div>)}
{mainFeed.map(eventElement)} {mainFeed.map(eventElement)}
<LoadMore onLoadMore={loadMore} shouldLoadMore={main.end}/> <LoadMore onLoadMore={loadMore} shouldLoadMore={main.end} />
</div> </div>
); );
} }

View File

@ -4,6 +4,7 @@ import { useSelector } from "react-redux";
// @ts-expect-error // @ts-expect-error
import { decode as invoiceDecode } from "light-bolt11-decoder"; import { decode as invoiceDecode } from "light-bolt11-decoder";
import { bytesToHex } from "@noble/hashes/utils"; import { bytesToHex } from "@noble/hashes/utils";
import { sha256 } from "Util";
//import { sha256 } from "Util"; //import { sha256 } from "Util";
import { formatShort } from "Number"; import { formatShort } from "Number";
@ -30,21 +31,24 @@ function getInvoice(zap: TaggedRawEvent) {
return { amount, hash: hash ? bytesToHex(hash) : undefined }; return { amount, hash: hash ? bytesToHex(hash) : undefined };
} }
function getZapper(zap: TaggedRawEvent, dhash: string) { interface Zapper {
pubkey?: HexKey,
isValid: boolean
}
function getZapper(zap: TaggedRawEvent, dhash: string): Zapper {
const zapRequest = findTag(zap, 'description') const zapRequest = findTag(zap, 'description')
if (zapRequest) { if (zapRequest) {
const rawEvent: TaggedRawEvent = JSON.parse(zapRequest); const rawEvent: TaggedRawEvent = JSON.parse(zapRequest);
if (Array.isArray(rawEvent)) { if (Array.isArray(rawEvent)) {
// old format, ignored // old format, ignored
const rawDescriptionTag = rawEvent.find(a => a[0] === 'application/nostr') return { isValid: false };
const rawDescription = rawDescriptionTag && rawDescriptionTag[1]
const request = typeof rawDescription === 'string' ? JSON.parse(rawDescription) : rawDescription
return request?.pubkey
} }
//const metaHash = sha256(zapRequest); const metaHash = sha256(zapRequest);
const ev = new Event(rawEvent) const ev = new Event(rawEvent)
return ev.PubKey return { pubkey: ev.PubKey, isValid: dhash === metaHash };
} }
return { isValid: false }
} }
interface ParsedZap { interface ParsedZap {
@ -59,7 +63,7 @@ interface ParsedZap {
export function parseZap(zap: TaggedRawEvent): ParsedZap { export function parseZap(zap: TaggedRawEvent): ParsedZap {
const { amount, hash } = getInvoice(zap) const { amount, hash } = getInvoice(zap)
const zapper = hash && getZapper(zap, hash) const zapper = hash ? getZapper(zap, hash) : { isValid: false };
const e = findTag(zap, 'e') const e = findTag(zap, 'e')
const p = findTag(zap, 'p')! const p = findTag(zap, 'p')!
return { return {
@ -67,9 +71,9 @@ export function parseZap(zap: TaggedRawEvent): ParsedZap {
e, e,
p, p,
amount: Number(amount) / 1000, amount: Number(amount) / 1000,
zapper, zapper: zapper.pubkey,
content: zap.content, content: zap.content,
valid: true, valid: zapper.isValid,
} }
} }

View File

@ -4,7 +4,7 @@ const intl = new Intl.NumberFormat("en", {
}); });
export function formatShort(n: number) { export function formatShort(n: number) {
if (n < 1e5) { if (n < 2e3) {
return n return n
} else if (n < 1e8) { } else if (n < 1e8) {
return `${intl.format(n / 1e3)}K` return `${intl.format(n / 1e3)}K`