verify description hash
This commit is contained in:
@ -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" />
|
||||||
|
|
||||||
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>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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`
|
||||||
|
Reference in New Issue
Block a user