From deafb776bbe5ee32244e452ac114030617b1c8c4 Mon Sep 17 00:00:00 2001
From: MSghais
Date: Thu, 1 Aug 2024 17:42:43 +0200
Subject: [PATCH 1/2] simple config nip-89 creation and view + how it works
---
askeladd-dvm-marketplace/.env.example | 4 +-
.../src/app/components/EventCard.tsx | 37 +++
.../src/app/components/TagsCard.tsx | 24 ++
.../src/app/config-marketplace/page.tsx | 309 ++++++++++++++++++
.../src/app/utils/generateAppHandler.ts | 93 ++++++
.../src/constants/relay.ts | 3 +
askeladd-dvm-marketplace/src/types/index.ts | 28 +-
7 files changed, 496 insertions(+), 2 deletions(-)
create mode 100644 askeladd-dvm-marketplace/src/app/components/EventCard.tsx
create mode 100644 askeladd-dvm-marketplace/src/app/components/TagsCard.tsx
create mode 100644 askeladd-dvm-marketplace/src/app/config-marketplace/page.tsx
create mode 100644 askeladd-dvm-marketplace/src/app/utils/generateAppHandler.ts
diff --git a/askeladd-dvm-marketplace/.env.example b/askeladd-dvm-marketplace/.env.example
index 7234561..676644f 100644
--- a/askeladd-dvm-marketplace/.env.example
+++ b/askeladd-dvm-marketplace/.env.example
@@ -1,3 +1,5 @@
DEFAULT_NOSTR_USER_SK=9f...f4
NEXT_PUBLIC_DEFAULT_NOSTR_USER_SK=9f...f4 # We can generate Nostr private key for user after
-NEXT_PUBLIC_DEFAULT_RELAYER="wss"
\ No newline at end of file
+NEXT_PUBLIC_DEFAULT_RELAYER="wss"
+DVM_PUBKEY=1OM...lfg
+NEXT_PUBLIC_DVM_PUBKEY=1OM...lfg
\ No newline at end of file
diff --git a/askeladd-dvm-marketplace/src/app/components/EventCard.tsx b/askeladd-dvm-marketplace/src/app/components/EventCard.tsx
new file mode 100644
index 0000000..591e4ef
--- /dev/null
+++ b/askeladd-dvm-marketplace/src/app/components/EventCard.tsx
@@ -0,0 +1,37 @@
+import { NDKEvent } from '@nostr-dev-kit/ndk';
+import { Event as NostrEvent } from 'nostr-tools';
+import React, { useState } from 'react';
+import TagsCard from './TagsCard';
+// Define the props for the component
+interface TagsCardProps {
+ event: NDKEvent | NostrEvent; // Array of array of strings
+}
+const EventCard: React.FC = ({ event }) => {
+
+ const [seeTag, setSeeTag] = useState(false)
+
+
+ const date:string|undefined = event?.created_at ? new Date(event?.created_at).toDateString() : undefined
+ return (
+ //
+
+
+ {date &&
+
{date}
+ }
+
Job id: {event?.kind}
+
{event?.content}
+
+ {seeTag &&
+
+ }
+
+
+
+
+ );
+};
+
+export default EventCard;
diff --git a/askeladd-dvm-marketplace/src/app/components/TagsCard.tsx b/askeladd-dvm-marketplace/src/app/components/TagsCard.tsx
new file mode 100644
index 0000000..906df29
--- /dev/null
+++ b/askeladd-dvm-marketplace/src/app/components/TagsCard.tsx
@@ -0,0 +1,24 @@
+import React from 'react';
+// Define the props for the component
+interface TagsCardProps {
+ tags: string[][]; // Array of array of strings
+}
+const TagsCard: React.FC
= ({ tags }) => {
+ return (
+
+ {tags.map((tagGroup, index) => (
+
+ {index}
+ {tagGroup.map((tag, idx) => (
+ //
+
+ {tag}
+
+ ))}
+
+ ))}
+
+ );
+};
+
+export default TagsCard;
diff --git a/askeladd-dvm-marketplace/src/app/config-marketplace/page.tsx b/askeladd-dvm-marketplace/src/app/config-marketplace/page.tsx
new file mode 100644
index 0000000..b15024d
--- /dev/null
+++ b/askeladd-dvm-marketplace/src/app/config-marketplace/page.tsx
@@ -0,0 +1,309 @@
+"use client";
+
+import { useState, useEffect } from "react";
+import { NDKEvent, NDKKind } from '@nostr-dev-kit/ndk';
+import { useSendNote } from "@/hooks/useSendNote";
+import { useFetchEvents } from "@/hooks/useFetchEvents";
+import { APPLICATION_PUBKEY_DVM, ASKELADD_RELAY } from "@/constants/relay";
+import { Event as EventNostr, SimplePool } from "nostr-tools";
+import { ASKELADD_KINDS, ConfigHandle } from "@/types";
+import EventCard from "../components/EventCard";
+import { generateContentAndTags } from "../utils/generateAppHandler";
+
+export default function Home() {
+ const [publicKey, setPublicKey] = useState();
+ const [appKind, setAppKind] = useState(ASKELADD_KINDS.KIND_JOB_REQUEST)
+ const [configKind, setConfigKind] = useState(ConfigHandle.ALL_KIND)
+ const [jobId, setJobId] = useState();
+ const [error, setError] = useState()
+ const [lastConfig, setLastConfig] = useState()
+ const [events, setEvents] = useState([])
+ const [proofStatus, setProofStatus] = useState<
+ "idle" | "pending" | "received" | "verified"
+ >("idle");
+ const [isLoading, setIsLoading] = useState(false);
+ const [isInitialized, setIsInitialized] = useState(false);
+ const [openHowItWork, setOpenHowItWork] = useState(false);
+ const [isNeedLoadEvents, setIsNeedLoadEvents] = useState(true);
+ const [isAdmin, setIsAdmin] = useState(false);
+ const [timestampJob, setTimestampJob] = useState();
+ const { fetchEvents, fetchEventsTools, setupSubscriptionNostr } = useFetchEvents()
+ const { sendNote, publishNote } = useSendNote()
+
+ useEffect(() => {
+ if (isNeedLoadEvents || !isInitialized) {
+ fetchEventsApp()
+ setIsNeedLoadEvents(false)
+ setIsInitialized(true)
+ }
+ }, [isNeedLoadEvents])
+
+ useEffect(() => {
+
+ if (publicKey) {
+
+ if (process.env.NEXT_PUBLIC_DVM_PUBKEY && process.env.NEXT_PUBLIC_DVM_PUBKEY != publicKey) {
+ setIsAdmin(true)
+ }
+ }
+ }, [publicKey])
+
+ const fetchEventsApp = async () => {
+ console.log("fetch events config");
+ const { events } = await fetchEventsTools({
+ kinds: [NDKKind.AppHandler],
+ limit: 100,
+ })
+ console.log("events config NIP-89", events);
+ setLastConfig(events[0])
+ setEvents(events);
+ setIsNeedLoadEvents(false)
+ }
+
+
+ /** Connect you */
+ const connectExtension = async () => {
+ try {
+
+ if (typeof window !== "undefined" && window.nostr) {
+ const pubkey = await window.nostr.getPublicKey();
+ let created_at = new Date().getTime();
+ setPublicKey(pubkey)
+ }
+
+ } catch (e) {
+ console.log("connect extension error", e)
+ } finally {
+ setIsLoading(false);
+ }
+
+ };
+
+ /** Submit Recommended App Handler for:
+ * JOB_REQUEST 5600: Prove
+ * JOB_RESULT 6600: Result
+ */
+ const submitJob = async () => {
+ try {
+ setIsLoading(true);
+ setJobId(undefined)
+ setProofStatus("pending");
+ setError(undefined);
+
+ submitApplicationHandler()
+ setIsNeedLoadEvents(true)
+
+ } catch (e) {
+ } finally {
+ setIsLoading(false);
+
+ }
+
+ };
+
+ const submitApplicationHandler = async () => {
+ try {
+ setIsLoading(true);
+ setProofStatus("pending");
+ setLastConfig(undefined);
+ setError(undefined);
+
+ setTimestampJob(new Date().getTime())
+ /** Use Nostr extension to send event */
+ const pool = new SimplePool();
+ let pubkey;
+ if (typeof window !== "undefined" && window.nostr) {
+ console.log("pubkey", pubkey)
+ if (!pubkey) return;
+ const { tags, content } = generateContentAndTags(configKind, appKind, pubkey)
+ console.log("tags", tags)
+ console.log("content", content)
+ if (!content || !tags) return;
+
+ let created_at = new Date().getTime();
+ const event = await window.nostr.signEvent({
+ pubkey: publicKey ?? pubkey,
+ created_at: created_at,
+ kind: NDKKind.AppHandler,
+ tags: tags,
+ content: content
+ }) // takes an event object, adds `id`, `pubkey` and `sig` and returns it
+ // Setup job request to fetch job id
+
+ // let eventID = await relay.publish(event as EventNostr);
+ const eventID = await Promise.any(pool.publish(ASKELADD_RELAY, event as EventNostr));
+ console.log("eventID", eventID[0])
+ setIsNeedLoadEvents(true)
+
+ } else {
+
+ /** @TODO flow is user doesn't have NIP-07 extension */
+ // let { result, event } = await sendNote({ content, tags, kind: 5600 })
+ // console.log("event", event)
+ // if (event?.sig) {
+ // setJobId(event?.sig);
+ // }
+ // setIsWaitingJob(true)
+ /** NDK event
+ * Generate or import private key after
+ */
+ }
+ } catch (e) {
+ } finally {
+ setIsLoading(false);
+ }
+
+ };
+
+ const handleSetAppKindSpecific = (kind: ASKELADD_KINDS, config: ConfigHandle) => {
+ if (kind) {
+ setAppKind(kind)
+ setConfigKind(ConfigHandle.SPECIFIC_KIND);
+ }
+ if (config == ConfigHandle?.ALL_KIND) {
+ setConfigKind(config);
+ setAppKind(undefined)
+ }
+ }
+
+ return (
+
+
+
+
+
+
+ {publicKey && publicKey != APPLICATION_PUBKEY_DVM ?
+
+
+
+
+ {publicKey &&
+
Connected: {publicKey}
}
+
You can't config this if you are not an admin of ASKELADD
+
+
+
+
+
+ : publicKey && publicKey == APPLICATION_PUBKEY_DVM &&
+
+
+
Askeladd DVM Marketplace
+
+ {publicKey == APPLICATION_PUBKEY_DVM &&
+
DVM admin
+ }
+ {publicKey &&
+
Connected: {publicKey}
}
+
+
+
+
+
+
Selected config: {configKind == ConfigHandle?.ALL_KIND ? "All" : "Specific"}
+
Change your config
+
+
+ {configKind == ConfigHandle.SPECIFIC_KIND &&
+ <>
+
+
+
Selected event: {appKind}
+
+
+
+
+ >
+ }
+
+
+ {isLoading &&
}
+
+
+
+ }
+
+
+
+
+
+
+ setOpenHowItWork(!openHowItWork)}
+ className="cursor-pointer my-5 p-5"
+ >
+
How the ASKELADD DVM ZK works?
+ {!openHowItWork &&
+
+ }
+ {openHowItWork &&
+ <>
+
+
As an User
+
User send a JOB_REQUEST with different params on the Nostr event:
+
You need theses params on the Nostr event:
+
It can change with all STWO Prover enabled on the Marketplace
+
Request: {JSON.stringify({
+ "claim": "413300",
+ "log_size":"5"
+ })} // The input of the Program
+
Tags: ["param", "input_name", "value"]
+
+
+ >
+ }
+
+
+
+
+
Existing Config of DVM
+
Last config
+ {lastConfig &&
+ <>
+
+ >
+ }
+
+
By Event KIND enabled on ASKELADD (WIP)
+
(5600, 6600 and more soon)
+
+
Admin config (WIP)
+
TODO
+
+
Others config
+
+
{events?.map((event, i) => {
+ return (
+
+ )
+
+ })}
+
+
+
+
+
+
+
+ );
+}
diff --git a/askeladd-dvm-marketplace/src/app/utils/generateAppHandler.ts b/askeladd-dvm-marketplace/src/app/utils/generateAppHandler.ts
new file mode 100644
index 0000000..449b092
--- /dev/null
+++ b/askeladd-dvm-marketplace/src/app/utils/generateAppHandler.ts
@@ -0,0 +1,93 @@
+import { APPLICATION_PUBKEY_DVM, ASKELADD_RELAY } from "@/constants/relay";
+import { ASKELADD_KINDS, ConfigHandle, KIND_JOB_REQUEST, KIND_JOB_RESULT } from "@/types";
+
+const PARAMS_JOB_REQUEST_ZK = {
+ request: {
+
+ },
+ params: {
+
+ },
+ program: {
+
+ }
+}
+
+const PARAMS_JOB_RESULT_ZK = {
+ job_id: {
+
+ },
+ proof: {
+
+ },
+ result: {
+
+ }
+}
+
+const PARAMS_ALL_KIND = {
+ [KIND_JOB_REQUEST]:PARAMS_JOB_REQUEST_ZK,
+ [KIND_JOB_RESULT]:PARAMS_JOB_RESULT_ZK,
+}
+export const generateTagsByAppKind = (tags: string[][], appKind: ASKELADD_KINDS, config:ConfigHandle) => {
+
+ const randomId = Math.random().toString(36).substring(7);
+
+ if(config == ConfigHandle.SPECIFIC_KIND) {
+ tags = [
+ ["d", randomId],
+ ["k", appKind?.toString()],
+ ["a", `31990:app1-pubkey:${APPLICATION_PUBKEY_DVM}`, ASKELADD_RELAY[0], "ios"],
+ ["a", `31990:app2-pubkey:${APPLICATION_PUBKEY_DVM}`, ASKELADD_RELAY[0], "web"],
+ ["a", `31990:app3-pubkey:${APPLICATION_PUBKEY_DVM}`, ASKELADD_RELAY[0], "android"],
+ ['output', 'text/json']
+ ];
+ } else {
+ tags = [
+ ["d", randomId],
+ ["k", ASKELADD_KINDS.KIND_JOB_REQUEST.toString()],
+ ["k", ASKELADD_KINDS.KIND_JOB_RESULT.toString()],
+ ["a", `31990:app1-pubkey:${APPLICATION_PUBKEY_DVM}`, ASKELADD_RELAY[0], "ios"],
+ ["a", `31990:app2-pubkey:${APPLICATION_PUBKEY_DVM}`, ASKELADD_RELAY[0], "web"],
+ ["a", `31990:app3-pubkey:${APPLICATION_PUBKEY_DVM}`, ASKELADD_RELAY[0], "android"],
+ // ["web", "https://..../a/", "nevent"],
+ // ["web", "https://..../p/", "nprofile"],
+ // ["web", "https://..../e/"],
+ ['output', 'text/json']
+ ];
+ }
+ return tags
+
+}
+export const generateContentAndTags = (configKind: ConfigHandle, appKind?: ASKELADD_KINDS, pubkey?:string): { tags?: string[][], content?: string } => {
+ let tags: string[][] = []
+ let content = "";
+ if (configKind == ConfigHandle?.ALL_KIND) {
+ content = JSON.stringify(PARAMS_ALL_KIND);
+ tags = [
+ ["d",],
+ ["k", ASKELADD_KINDS.KIND_JOB_REQUEST.toString()],
+ ["k", ASKELADD_KINDS.KIND_JOB_RESULT.toString()],
+ ["a", `31990:app1-pubkey:${APPLICATION_PUBKEY_DVM}`, ASKELADD_RELAY[0], "ios"],
+ ["a", `31990:app2-pubkey:${APPLICATION_PUBKEY_DVM}`, ASKELADD_RELAY[0], "web"],
+ ["a", `31990:app3-pubkey:${APPLICATION_PUBKEY_DVM}`, ASKELADD_RELAY[0], "android"],
+ // ["web", "https://..../a/", "nevent"],
+ // ["web", "https://..../p/", "nprofile"],
+ // ["web", "https://..../e/"],
+ ['output', 'text/json']
+ ];
+
+ } else if (configKind == ConfigHandle?.SPECIFIC_KIND) {
+ if (!appKind) return { tags, content }
+ tags = generateTagsByAppKind(tags, appKind, configKind)
+ if (appKind && appKind?.toString() == ASKELADD_KINDS.KIND_JOB_REQUEST.toString()) {
+ content = JSON.stringify(PARAMS_JOB_REQUEST_ZK)
+ }
+ else if (appKind && appKind == ASKELADD_KINDS.KIND_JOB_RESULT) {
+ content = JSON.stringify(PARAMS_JOB_RESULT_ZK)
+ }
+
+ }
+
+ return { tags, content }
+}
diff --git a/askeladd-dvm-marketplace/src/constants/relay.ts b/askeladd-dvm-marketplace/src/constants/relay.ts
index 7b9a182..39ca656 100644
--- a/askeladd-dvm-marketplace/src/constants/relay.ts
+++ b/askeladd-dvm-marketplace/src/constants/relay.ts
@@ -4,3 +4,6 @@ export const ASKELADD_RELAY= [
// "wss://relay.nostr.net",
process.env.NEXT_PUBLIC_DEFAULT_RELAYER ?? 'wss://nostr-relay-nestjs-production.up.railway.app',// AFK relayer
]
+
+
+export const APPLICATION_PUBKEY_DVM= process.env.NEXT_PUBLIC_DVM_PUBKEY
diff --git a/askeladd-dvm-marketplace/src/types/index.ts b/askeladd-dvm-marketplace/src/types/index.ts
index 0a99b42..a35ecf2 100644
--- a/askeladd-dvm-marketplace/src/types/index.ts
+++ b/askeladd-dvm-marketplace/src/types/index.ts
@@ -1,6 +1,7 @@
export const KIND_JOB_RESULT = 6600
export const KIND_JOB_REQUEST = 5600
+
export interface JobResultProver {
job_id: string;
response: {
@@ -39,7 +40,32 @@ export interface CommitmentSchemeProof {
fri_proof: {
inner_layers: ProofInnerLayer[] | any[];
last_layer_poly: {
- coeffs:any[];
+ coeffs: any[];
}
};
}
+
+export enum ASKELADD_KINDS {
+ KIND_JOB_REQUEST = 5600,
+ KIND_JOB_RESULT = 6600,
+ // KIND_SUBMIT_PROGRAM
+}
+
+export enum ASKELADD_KINDS_NAME {
+ KIND_JOB_REQUEST = "Job request",
+ KIND_JOB_RESULT = "Job result",
+ KIND_SUBMIT_PROGRAM = "Submit result",
+}
+// export const ASKELADD_KINDS= {
+// KIND_JOB_REQUEST,
+// KIND_JOB_RESULT
+// }
+
+export interface IFormRecommendedApplicationHandlerEvent {
+
+}
+
+export enum ConfigHandle {
+ SPECIFIC_KIND,
+ ALL_KIND
+}
\ No newline at end of file
From c516479f815192dee5767d91a07ee906d3ce654e Mon Sep 17 00:00:00 2001
From: MSghais
Date: Thu, 1 Aug 2024 17:57:02 +0200
Subject: [PATCH 2/2] fix build no comment text node
---
.../src/app/config-marketplace/page.tsx | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/askeladd-dvm-marketplace/src/app/config-marketplace/page.tsx b/askeladd-dvm-marketplace/src/app/config-marketplace/page.tsx
index b15024d..c9ac42f 100644
--- a/askeladd-dvm-marketplace/src/app/config-marketplace/page.tsx
+++ b/askeladd-dvm-marketplace/src/app/config-marketplace/page.tsx
@@ -186,7 +186,7 @@ export default function Home() {
{publicKey &&
Connected: {publicKey}
}
-
You can't config this if you are not an admin of ASKELADD
+
You can't config this if you are not an admin of ASKELADD
@@ -266,8 +266,8 @@ export default function Home() {
Request: {JSON.stringify({
"claim": "413300",
"log_size":"5"
- })} // The input of the Program
- Tags: ["param", "input_name", "value"]
+ })} " The input of the Program
+ Tags: {`["param", "input_name", "value"]`}
>