diff --git a/client/src/components/forms/PostFormCard.tsx b/client/src/components/forms/PostFormCard.tsx index 2059dd3..ed2029d 100644 --- a/client/src/components/forms/PostFormCard.tsx +++ b/client/src/components/forms/PostFormCard.tsx @@ -7,6 +7,7 @@ import { useSubmitForm } from "./handleSubmit"; import "../../styles/Form.css"; import EmotePicker from "../modals/EmotePicker/EmotePicker"; import emotes from "../modals/EmotePicker/custom_emojis.json" +import { DEFAULT_DIFFICULTY } from "../../config"; interface FormProps { refEvent?: NostrEvent; @@ -16,7 +17,7 @@ interface FormProps { const NewNoteCard = ({ refEvent, - tagType, + tagType, hashtag, }: FormProps) => { const [comment, setComment] = useState(""); @@ -33,7 +34,7 @@ const NewNoteCard = ({ pubkey: "", }); const [difficulty, setDifficulty] = useState( - localStorage.getItem("difficulty") || "21" + localStorage.getItem("difficulty") || DEFAULT_DIFFICULTY.toString() ); useEffect(() => { @@ -44,7 +45,7 @@ const NewNoteCard = ({ if (refEvent && tagType) { unsigned.tags = Array.from(new Set(unsigned.tags.concat(refEvent.tags))); unsigned.tags.push(['p', refEvent.pubkey]); - + if (tagType === 'Reply') { unsigned.tags.push(['e', refEvent.id, refEvent.tags.some(tag => tag[0] === 'e') ? 'root' : '']); } else { @@ -78,7 +79,7 @@ const NewNoteCard = ({ })); }, [comment]); - const { handleSubmit: originalHandleSubmit, doingWorkProp, doingWorkProgress } = useSubmitForm(unsigned, difficulty); + const { handleSubmit: originalHandleSubmit, doingWorkProp, hashrate, bestPow } = useSubmitForm(unsigned, difficulty); const handleSubmit = async (event: React.FormEvent) => { await originalHandleSubmit(event); @@ -127,13 +128,30 @@ const NewNoteCard = ({ rows={comment.split('\n').length || 1} />
-
+
-

- {difficulty} Work -

+ setDifficulty(e.target.value)} + min="10" // Assuming a minimum difficulty value of 1 + /> + +
@@ -148,14 +166,15 @@ const NewNoteCard = ({
+ {doingWorkProp ? ( +
+ + Doing Work: + {hashrate && {hashrate > 100000 ? `${(hashrate / 1000).toFixed(0)}k` : hashrate}}H/s + (PB:{bestPow}) +
+ ) : null}
- {doingWorkProp ? ( -
- - Doing Work: - {doingWorkProgress && {doingWorkProgress} hashes} -
- ) : null}
); diff --git a/client/src/components/forms/RepostNote.tsx b/client/src/components/forms/RepostNote.tsx index 388ab72..99729d8 100644 --- a/client/src/components/forms/RepostNote.tsx +++ b/client/src/components/forms/RepostNote.tsx @@ -5,6 +5,7 @@ import { useState, useEffect } from "react"; import { UnsignedEvent, Event as NostrEvent, nip19 } from "nostr-tools"; import { useSubmitForm } from "./handleSubmit"; import "../../styles/Form.css"; +import { DEFAULT_DIFFICULTY } from "../../config"; interface FormProps { refEvent: NostrEvent; @@ -14,7 +15,7 @@ const RepostNote = ({ refEvent }: FormProps) => { const [difficulty, setDifficulty] = useState( - localStorage.getItem("difficulty") || "21" + localStorage.getItem("difficulty") || DEFAULT_DIFFICULTY.toString() ); const [unsigned] = useState({ kind: 6, @@ -42,7 +43,7 @@ const RepostNote = ({ }; }, []); - const { handleSubmit, doingWorkProp, doingWorkProgress } = useSubmitForm(unsigned, difficulty); + const { handleSubmit, doingWorkProp, hashrate } = useSubmitForm(unsigned, difficulty); return (
Doing Work: - {doingWorkProgress && {doingWorkProgress} hashes} + {hashrate && {hashrate} H/s}
) : null}
diff --git a/client/src/components/forms/handleSubmit.ts b/client/src/components/forms/handleSubmit.ts index 909721f..c2542e2 100644 --- a/client/src/components/forms/handleSubmit.ts +++ b/client/src/components/forms/handleSubmit.ts @@ -4,7 +4,10 @@ import { publish } from "../../utils/relays"; const useWorkers = (numCores: number, unsigned: UnsignedEvent, difficulty: string, deps: any[]) => { const [messageFromWorker, setMessageFromWorker] = useState(null); - const [doingWorkProgress, setDoingWorkProgress] = useState(0); + const [hashrate, setHashrate] = useState(0); + const [bestPow, setBestPow] = useState(0); + + const startTime = Date.now(); const startWork = () => { const workers = Array(numCores).fill(null).map(() => new Worker(new URL("../../powWorker", import.meta.url))); @@ -12,8 +15,10 @@ const useWorkers = (numCores: number, unsigned: UnsignedEvent, difficulty: strin workers.forEach((worker, index) => { worker.onmessage = (event) => { if (event.data.status === 'progress') { - console.log(`Worker progress: Checked ${event.data.currentNonce} nonces.`); - setDoingWorkProgress(event.data.currentNonce); + setHashrate(Math.floor(event.data.currentNonce/((Date.now() - startTime)/1000))); + if (event.data.bestPoW > bestPow) { + setBestPow(event.data.bestPoW) + } } else if (event.data.found) { setMessageFromWorker(event.data.event); // Terminate all workers once a solution is found @@ -30,7 +35,7 @@ const useWorkers = (numCores: number, unsigned: UnsignedEvent, difficulty: strin }); }; - return { startWork, messageFromWorker, doingWorkProgress }; + return { startWork, messageFromWorker, hashrate, bestPow }; }; export const useSubmitForm = (unsigned: UnsignedEvent, difficulty: string) => { @@ -44,7 +49,7 @@ export const useSubmitForm = (unsigned: UnsignedEvent, difficulty: string) => { // Initialize the worker outside of any effects const numCores = navigator.hardwareConcurrency || 4; - const { startWork, messageFromWorker, doingWorkProgress } = useWorkers(numCores, unsignedWithPubkey, difficulty, [unsignedWithPubkey]); + const { startWork, messageFromWorker, hashrate, bestPow } = useWorkers(numCores, unsignedWithPubkey, difficulty, [unsignedWithPubkey]); useEffect(() => { if (unsignedPoWEvent) { @@ -99,5 +104,5 @@ export const useSubmitForm = (unsigned: UnsignedEvent, difficulty: string) => { } }, [messageFromWorker]); - return { handleSubmit, doingWorkProp, doingWorkProgress }; + return { handleSubmit, doingWorkProp, hashrate, bestPow }; }; \ No newline at end of file diff --git a/client/src/components/routes/Home.tsx b/client/src/components/routes/Home.tsx index 4680b9a..94048b7 100644 --- a/client/src/components/routes/Home.tsx +++ b/client/src/components/routes/Home.tsx @@ -17,16 +17,7 @@ const Home = () => { (event.kind !== 1 || !event.tags.some((tag) => tag[0] === "e" || tag[0] === "a")) ) - const sortedEvents = postEvents - .sort((a, b) => { - // Sort by PoW in descending order - const powDiff = verifyPow(b) - verifyPow(a); - if (powDiff !== 0) return powDiff; - - // If PoW is the same, sort by created_at in descending order - return b.created_at - a.created_at; - } - ); + const sortedEvents = postEvents.sort((a, b) => b.created_at - a.created_at); // Render the component return ( diff --git a/client/src/powWorker.ts b/client/src/powWorker.ts index 61c6fce..9d126e1 100644 --- a/client/src/powWorker.ts +++ b/client/src/powWorker.ts @@ -45,7 +45,8 @@ export function getPow(hex: string): number { */ export function minePow(unsigned: UnsignedEvent, difficulty: number, nonceStart: number, nonceStep: number): { found: boolean, event?: Omit } { let nonce = nonceStart; - + let bestPoW = 0; + const event = unsigned as Omit const tag = ['nonce', nonce.toString(), difficulty.toString()] @@ -57,15 +58,20 @@ export function minePow(unsigned: UnsignedEvent, difficulty: n tag[1] = (nonce).toString(); event.id = getEventHash(event); + let leadingZeroes = getPow(event.id); - if (getPow(event.id) >= difficulty) { + if (leadingZeroes > bestPoW) { + bestPoW = leadingZeroes; + } + + if (leadingZeroes >= difficulty) { return { found: true, event: event }; } nonce += nonceStep; if (nonce % (nonceStep * 10000) === 0) { - ctx.postMessage({ status: 'progress', currentNonce: nonce }); + ctx.postMessage({ status: 'progress', currentNonce: nonce, bestPoW}); } } return { found: false }; diff --git a/client/src/styles/Form.css b/client/src/styles/Form.css index e83d125..041ac41 100644 --- a/client/src/styles/Form.css +++ b/client/src/styles/Form.css @@ -1,3 +1,14 @@ textarea { caret-color: rgb(0, 38, 255); +} + +/* Hide the increment and decrement buttons on number inputs */ +input[type="number"]::-webkit-inner-spin-button, +input[type="number"]::-webkit-outer-spin-button { + -webkit-appearance: none; + margin: 0; +} + +input[type="number"] { + -moz-appearance: textfield; /* Firefox */ } \ No newline at end of file