diff --git a/js/nostr-utils.js b/js/nostr-utils.js
index 057c72f..7809c31 100644
--- a/js/nostr-utils.js
+++ b/js/nostr-utils.js
@@ -1,434 +1,436 @@
// from https://github.com/paulmillr/noble-secp256k1/blob/main/index.ts#L803
function hexToBytes(hex) {
- if (typeof hex !== 'string') {
- throw new TypeError('hexToBytes: expected string, got ' + typeof hex)
- }
- if (hex.length % 2)
- throw new Error('hexToBytes: received invalid unpadded hex' + hex.length)
- const array = new Uint8Array(hex.length / 2)
- for (let i = 0; i < array.length; i++) {
- const j = i * 2
- const hexByte = hex.slice(j, j + 2)
- const byte = Number.parseInt(hexByte, 16)
- if (Number.isNaN(byte) || byte < 0) throw new Error('Invalid byte sequence')
- array[i] = byte
- }
- return array
+ if (typeof hex !== 'string') {
+ throw new TypeError('hexToBytes: expected string, got ' + typeof hex)
}
+ if (hex.length % 2)
+ throw new Error('hexToBytes: received invalid unpadded hex' + hex.length)
+ const array = new Uint8Array(hex.length / 2)
+ for (let i = 0; i < array.length; i++) {
+ const j = i * 2
+ const hexByte = hex.slice(j, j + 2)
+ const byte = Number.parseInt(hexByte, 16)
+ if (Number.isNaN(byte) || byte < 0) throw new Error('Invalid byte sequence')
+ array[i] = byte
+ }
+ return array
+}
+
+// decode nip19 ('npub') to hex
+const npub2hexa = (npub) => {
+ let { prefix, words } = bech32.bech32.decode(npub, 90)
+ if (prefix === 'npub') {
+ let data = new Uint8Array(bech32.bech32.fromWords(words))
+ return buffer.Buffer.from(data).toString('hex')
+ }
+}
- // decode nip19 ('npub') to hex
- const npub2hexa = (npub) => {
- let { prefix, words } = bech32.bech32.decode(npub, 90)
- if (prefix === 'npub') {
- let data = new Uint8Array(bech32.bech32.fromWords(words))
- return buffer.Buffer.from(data).toString('hex')
- }
- }
+// encode hex to nip19 ('npub')
+const hexa2npub = (hex) => {
+ const data = hexToBytes(hex)
+ const words = bech32.bech32.toWords(data)
+ const prefix = 'npub'
+ return bech32.bech32.encode(prefix, words, 90)
+}
- // encode hex to nip19 ('npub')
- const hexa2npub = (hex) => {
- const data = hexToBytes(hex)
- const words = bech32.bech32.toWords(data)
- const prefix = 'npub'
- return bech32.bech32.encode(prefix, words, 90)
- }
-
- // parse inserted pubkey
- const parsePubkey = (pubkey) =>
- pubkey.match('npub1') ? npub2hexa(pubkey) : pubkey
-
- // download js file
- const downloadFile = (data, fileName) => {
- const prettyJs = 'const data = ' + JSON.stringify(data, null, 2)
- const tempLink = document.createElement('a')
- const taBlob = new Blob([prettyJs], { type: 'text/javascript' })
- tempLink.setAttribute('href', URL.createObjectURL(taBlob))
- tempLink.setAttribute('download', fileName)
- tempLink.click()
+// parse inserted pubkey
+const parsePubkey = (pubkey) =>
+ pubkey.match('npub1') ? npub2hexa(pubkey) : pubkey
+
+// download js file
+const downloadFile = (data, fileName) => {
+ const prettyJs = 'const data = ' + JSON.stringify(data, null, 2)
+ const tempLink = document.createElement('a')
+ const taBlob = new Blob([prettyJs], { type: 'text/javascript' })
+ tempLink.setAttribute('href', URL.createObjectURL(taBlob))
+ tempLink.setAttribute('download', fileName)
+ tempLink.click()
+}
+
+const updateRelayStatus = (relay, status, addToCount, until, relayStatusAndCount) => {
+ if (relayStatusAndCount[relay] == undefined) {
+ relayStatusAndCount[relay] = {}
}
- const updateRelayStatus = (relay, status, addToCount, until, relayStatusAndCount) => {
- if (relayStatusAndCount[relay] == undefined) {
- relayStatusAndCount[relay] = {}
- }
+ if (status)
+ relayStatusAndCount[relay].status = status
- if (status)
- relayStatusAndCount[relay].status = status
+ relayStatusAndCount[relay].until = until
- relayStatusAndCount[relay].until = until
+ if (relayStatusAndCount[relay].count != undefined)
+ relayStatusAndCount[relay].count = relayStatusAndCount[relay].count + addToCount
+ else
+ relayStatusAndCount[relay].count = addToCount
- if (relayStatusAndCount[relay].count != undefined)
- relayStatusAndCount[relay].count = relayStatusAndCount[relay].count + addToCount
- else
- relayStatusAndCount[relay].count = addToCount
+ displayRelayStatus(relayStatusAndCount)
+}
- displayRelayStatus(relayStatusAndCount)
+const displayRelayStatus = (relayStatusAndCount) => {
+ if (Object.keys(relayStatusAndCount).length > 0) {
+ const newText = Object.keys(relayStatusAndCount).map(
+ it => {
+ let untilStr = "";
+
+ if (relayStatusAndCount[it].until)
+ untilStr = " <" + new Date(relayStatusAndCount[it].until * 1000).toLocaleDateString("en-US")
+
+ const relayName = it.replace("wss://", "").replace("ws://", "")
+ const line = "
" + relayName + " | " + relayStatusAndCount[it].status + " | " + untilStr + " | " + relayStatusAndCount[it].count + " | "
+ return "" +line+ "
"
+ }
+ ).join("
")
+ $('#checking-relays').html(newText)
+ } else {
+ $('#checking-relays-header').html("")
+ $('#checking-relays').html("")
}
+}
- const displayRelayStatus = (relayStatusAndCount) => {
- if (Object.keys(relayStatusAndCount).length > 0) {
- const newText = Object.keys(relayStatusAndCount).map(
- it => {
- let untilStr = "";
+// fetch events from relay, returns a promise
+const fetchFromRelay = async (relay, filters, pubkey, events, relayStatus) =>
+ new Promise((resolve, reject) => {
+ try {
+ updateRelayStatus(relay, "Starting", 0, undefined, relayStatus)
+ // open websocket
+ const ws = new WebSocket(relay)
- if (relayStatusAndCount[it].until)
- untilStr = " <" + new Date(relayStatusAndCount[it].until * 1000).toLocaleDateString("en-US")
+ // prevent hanging forever
+ let myTimeout = setTimeout(() => {
+ ws.close()
+ reject(relay)
+ }, 10_000)
- const relayName = it.replace("wss://", "").replace("ws://", "")
- const line = "" + relayName + " | " + relayStatusAndCount[it].status + " | " + untilStr + " | " + relayStatusAndCount[it].count + " | "
- return "" +line+ "
"
- }
- ).join("
")
- $('#checking-relays').html(newText)
- } else {
- $('#checking-relays-header').html("")
- $('#checking-relays').html("")
- }
- }
+ const subscriptions = Object.fromEntries(filters.map ( (filter, index) => {
+ let id = "my-sub-"+index
- // fetch events from relay, returns a promise
- const fetchFromRelay = async (relay, filters, pubkey, events, relayStatus) =>
- new Promise((resolve, reject) => {
- try {
- updateRelayStatus(relay, "Starting", 0, undefined, relayStatus)
- // open websocket
- const ws = new WebSocket(relay)
-
- // prevent hanging forever
- let myTimeout = setTimeout(() => {
+ return [
+ id, {
+ id: id,
+ counter: 0,
+ lastEvent: null,
+ done: false,
+ filter: filter,
+ eventIds: new Set()
+ }
+ ]
+ }))
+
+ // subscribe to events filtered by author
+ ws.onopen = () => {
+ clearTimeout(myTimeout)
+ myTimeout = setTimeout(() => {
ws.close()
reject(relay)
}, 10_000)
-
- const subscriptions = Object.fromEntries(filters.map ( (filter, index) => {
- let id = "my-sub-"+index
-
- return [
- id, {
- id: id,
- counter: 0,
- lastEvent: null,
- done: false,
- filter: filter,
- eventIds: new Set()
- }
- ]
- }))
+ updateRelayStatus(relay, "Downloading", 0, undefined, relayStatus)
- // subscribe to events filtered by author
- ws.onopen = () => {
+ for (const [key, sub] of Object.entries(subscriptions)) {
+ ws.send(JSON.stringify(['REQ', sub.id, sub.filter]))
+ }
+ }
+
+ // Listen for messages
+ ws.onmessage = (event) => {
+ const [msgType, subscriptionId, data] = JSON.parse(event.data)
+ // event messages
+ if (msgType === 'EVENT') {
clearTimeout(myTimeout)
myTimeout = setTimeout(() => {
ws.close()
reject(relay)
}, 10_000)
- updateRelayStatus(relay, "Downloading", 0, undefined, relayStatus)
-
- for (const [key, sub] of Object.entries(subscriptions)) {
- ws.send(JSON.stringify(['REQ', sub.id, sub.filter]))
- }
- }
-
- // Listen for messages
- ws.onmessage = (event) => {
- const [msgType, subscriptionId, data] = JSON.parse(event.data)
- // event messages
- if (msgType === 'EVENT') {
- clearTimeout(myTimeout)
- myTimeout = setTimeout(() => {
- ws.close()
- reject(relay)
- }, 10_000)
- try {
- const { id } = data
+ try {
+ const { id } = data
- if (!subscriptions[subscriptionId].lastEvent || data.created_at < subscriptions[subscriptionId].lastEvent.created_at)
- subscriptions[subscriptionId].lastEvent = data
+ if (!subscriptions[subscriptionId].lastEvent || data.created_at < subscriptions[subscriptionId].lastEvent.created_at)
+ subscriptions[subscriptionId].lastEvent = data
- if (data.id in subscriptions[subscriptionId].eventIds) return
+ if (data.id in subscriptions[subscriptionId].eventIds) return
- subscriptions[subscriptionId].eventIds.add(data.id)
- subscriptions[subscriptionId].counter++
+ subscriptions[subscriptionId].eventIds.add(data.id)
+ subscriptions[subscriptionId].counter++
- // don't save/reboradcast kind 3s that are not from the author.
- // their are too big.
- if (data.kind == 3 && data.pubkey != pubkey) {
- return
- }
-
- let until = undefined
-
- if (subscriptions[subscriptionId].lastEvent) {
- until = subscriptions[subscriptionId].lastEvent.created_at
- }
-
- updateRelayStatus(relay, undefined, 1, until, relayStatus)
-
- // prevent duplicated events
- if (events[id]) return
- else events[id] = data
-
- // show how many events were found until this moment
- $('#events-found').text(`${Object.keys(events).length} events found`)
- } catch(err) {
- console.log(err, event)
+ // don't save/reboradcast kind 3s that are not from the author.
+ // their are too big.
+ if (data.kind == 3 && data.pubkey != pubkey) {
return
}
- }
- // end of subscription messages
- if (msgType === 'EOSE') {
- // Restarting the filter is necessary to go around Max Limits for each relay.
- if (subscriptions[subscriptionId].counter < 2) {
- subscriptions[subscriptionId].done = true
- console.log(relay, subscriptionId, event.data)
+ let until = undefined
- let alldone = Object.values(subscriptions).every(filter => filter.done === true);
- if (alldone) {
- updateRelayStatus(relay, "Done", 0, undefined, relayStatus)
- ws.close()
- resolve(relay)
- }
- } else {
- //console.log("Limit: ", { ...filters[0], until: lastSub1Event.created_at })
- subscriptions[subscriptionId].counter = 0
- ws.send(JSON.stringify(['REQ', subscriptions[subscriptionId].id, { ...subscriptions[subscriptionId].filter, until: subscriptions[subscriptionId].lastEvent.created_at } ]))
+ if (subscriptions[subscriptionId].lastEvent) {
+ until = subscriptions[subscriptionId].lastEvent.created_at
}
- }
- if (msgType === 'AUTH') {
- signNostrAuthEvent(relay, subscriptionId).then(
- (event) => {
- if (event)
- ws.send(JSON.stringify(['EVENT', event]))
- else {
- updateRelayStatus(relay, "AUTH Req", 0, undefined, relayStatus)
- ws.close()
- reject(relay)
- }
- },
- (reason) => {
+ updateRelayStatus(relay, undefined, 1, until, relayStatus)
+
+ // prevent duplicated events
+ if (events[id]) return
+ else events[id] = data
+
+ // show how many events were found until this moment
+ $('#events-found').text(`${Object.keys(events).length} events found`)
+ } catch(err) {
+ console.log(err, event)
+ return
+ }
+ }
+
+ // end of subscription messages
+ if (msgType === 'EOSE') {
+ // Restarting the filter is necessary to go around Max Limits for each relay.
+ if (subscriptions[subscriptionId].counter < 2) {
+ subscriptions[subscriptionId].done = true
+ console.log(relay, subscriptionId, event.data)
+
+ let alldone = Object.values(subscriptions).every(filter => filter.done === true);
+ if (alldone) {
+ updateRelayStatus(relay, "Done", 0, undefined, relayStatus)
+ ws.close()
+ resolve(relay)
+ }
+ } else {
+ //console.log("Limit: ", { ...filters[0], until: lastSub1Event.created_at })
+ subscriptions[subscriptionId].counter = 0
+ ws.send(JSON.stringify(['REQ', subscriptions[subscriptionId].id, { ...subscriptions[subscriptionId].filter, until: subscriptions[subscriptionId].lastEvent.created_at } ]))
+ }
+ }
+
+ if (msgType === 'AUTH') {
+ signNostrAuthEvent(relay, subscriptionId).then(
+ (event) => {
+ if (event)
+ ws.send(JSON.stringify(['EVENT', event]))
+ else {
updateRelayStatus(relay, "AUTH Req", 0, undefined, relayStatus)
ws.close()
reject(relay)
- },
- )
- }
+ }
+ },
+ (reason) => {
+ updateRelayStatus(relay, "AUTH Req", 0, undefined, relayStatus)
+ ws.close()
+ reject(relay)
+ },
+ )
}
- ws.onerror = (err) => {
- updateRelayStatus(relay, "Done", 0, undefined, relayStatus)
- try {
- ws.close()
- reject(relay)
- } catch {
- reject(relay)
- }
- }
- ws.onclose = (socket, event) => {
- updateRelayStatus(relay, "Done", 0, undefined, relayStatus)
- resolve(relay)
- }
- } catch (exception) {
- console.log(exception)
- updateRelayStatus(relay, "Error", 0, undefined, relayStatus)
+ }
+ ws.onerror = (err) => {
+ updateRelayStatus(relay, "Done", 0, undefined, relayStatus)
try {
ws.close()
- } catch (exception) {
- }
-
- reject(relay)
- }
- })
-
- // query relays for events published by this pubkey
- const getEvents = async (filters, pubkey) => {
- // events hash
- const events = {}
-
- // batch processing of 10 relays
- await processInPool(relays, (relay, poolStatus) => fetchFromRelay(relay, filters, pubkey, events, poolStatus), 10)
-
- displayRelayStatus({})
-
- // return data as an array of events
- return Object.keys(events).map((id) => events[id])
- }
-
- const processInPool = async (items, processItem, poolSize) => {
- let pool = {};
- let poolStatus = {}
- let remaining = [...items]
-
- while (remaining.length) {
- let processing = remaining.splice(0, 1)
- let item = processing[0]
- pool[item] = processItem(item, poolStatus);
-
- if (Object.keys(pool).length > poolSize - 1) {
- try {
- const resolvedId = await Promise.race(Object.values(pool)); // wait for one Promise to finish
-
- delete pool[resolvedId]; // remove that Promise from the pool
- } catch (resolvedId) {
- delete pool[resolvedId]; // remove that Promise from the pool
+ reject(relay)
+ } catch {
+ reject(relay)
}
}
-
- $('#fetching-progress').val(items.length - remaining.length)
+ ws.onclose = (socket, event) => {
+ updateRelayStatus(relay, "Done", 0, undefined, relayStatus)
+ resolve(relay)
+ }
+ } catch (exception) {
+ console.log(exception)
+ updateRelayStatus(relay, "Error", 0, undefined, relayStatus)
+ try {
+ ws.close()
+ } catch (exception) {
+ }
+
+ reject(relay)
}
+ })
- await Promise.allSettled(Object.values(pool));
+// query relays for events published by this pubkey
+const getEvents = async (filters, pubkey) => {
+ // events hash
+ const events = {}
+
+ // batch processing of 10 relays
+ await processInPool(relays, (relay, poolStatus) => fetchFromRelay(relay, filters, pubkey, events, poolStatus), 10)
+
+ displayRelayStatus({})
+
+ // return data as an array of events
+ return Object.keys(events).map((id) => events[id])
}
- const sendAllEvents = async (relay, data, relayStatus, ws) => {
- console.log("Sending:", data.length, " events")
- for (evnt of data) {
- ws.send(JSON.stringify(['EVENT', evnt]))
- }
- }
+const processInPool = async (items, processItem, poolSize) => {
+ let pool = {};
+ let poolStatus = {}
+ let remaining = [...items]
- // send events to a relay, returns a promisse
- const sendToRelay = async (relay, data, relayStatus) =>
- new Promise((resolve, reject) => {
+ while (remaining.length) {
+ let processing = remaining.splice(0, 1)
+ let item = processing[0]
+ pool[item] = processItem(item, poolStatus);
+
+ if (Object.keys(pool).length > poolSize - 1) {
try {
- const ws = new WebSocket(relay)
+ const resolvedId = await Promise.race(Object.values(pool)); // wait for one Promise to finish
- updateRelayStatus(relay, "Starting", 0, undefined, relayStatus)
+ delete pool[resolvedId]; // remove that Promise from the pool
+ } catch (resolvedId) {
+ delete pool[resolvedId]; // remove that Promise from the pool
+ }
+ }
- // prevent hanging forever
- let myTimeout = setTimeout(() => {
+ $('#fetching-progress').val(items.length - remaining.length)
+ }
+
+ await Promise.allSettled(Object.values(pool));
+}
+
+const sendAllEvents = async (relay, data, relayStatus, ws) => {
+ console.log("Sending:", data.length, " events")
+ for (evnt of data) {
+ ws.send(JSON.stringify(['EVENT', evnt]))
+ }
+}
+
+// send events to a relay, returns a promisse
+const sendToRelay = async (relay, data, relayStatus) =>
+ new Promise((resolve, reject) => {
+ try {
+ const ws = new WebSocket(relay)
+
+ updateRelayStatus(relay, "Starting", 0, undefined, relayStatus)
+
+ // prevent hanging forever
+ let myTimeout = setTimeout(() => {
+ ws.close()
+ reject('timeout')
+ }, 10_000)
+
+ // fetch events from relay
+ ws.onopen = () => {
+ updateRelayStatus(relay, "Sending", 0, undefined, relayStatus)
+
+ clearTimeout(myTimeout)
+ myTimeout = setTimeout(() => {
ws.close()
reject('timeout')
}, 10_000)
- // fetch events from relay
- ws.onopen = () => {
- updateRelayStatus(relay, "Sending", 0, undefined, relayStatus)
+ sendAllEvents(relay, data, relayStatus, ws)
+ }
+ // Listen for messages
+ ws.onmessage = (event) => {
+ clearTimeout(myTimeout)
+ myTimeout = setTimeout(() => {
+ ws.close()
+ reject('timeout')
+ }, 10_000)
- clearTimeout(myTimeout)
- myTimeout = setTimeout(() => {
- ws.close()
- reject('timeout')
- }, 10_000)
-
- sendAllEvents(relay, data, relayStatus, ws)
- }
- // Listen for messages
- ws.onmessage = (event) => {
- clearTimeout(myTimeout)
- myTimeout = setTimeout(() => {
- ws.close()
- reject('timeout')
- }, 10_000)
-
- const [msgType, subscriptionId, inserted] = JSON.parse(event.data)
- // event messages
- // end of subscription messages
- if (msgType === 'OK') {
- if (inserted == true) {
- updateRelayStatus(relay, undefined, 1, undefined, relayStatus)
- } else {
- console.log(relay, event.data)
- }
+ const [msgType, subscriptionId, inserted] = JSON.parse(event.data)
+ // event messages
+ // end of subscription messages
+ if (msgType === 'OK') {
+ if (inserted == true) {
+ updateRelayStatus(relay, undefined, 1, undefined, relayStatus)
} else {
console.log(relay, event.data)
}
+ } else {
+ console.log(relay, event.data)
}
- ws.onerror = (err) => {
- updateRelayStatus(relay, "Error", 0, undefined, relayStatus)
- console.log("Error", err)
- ws.close()
- reject(err)
- }
- ws.onclose = (socket, event) => {
- updateRelayStatus(relay, "Done", 0, undefined, relayStatus)
- console.log("OnClose", relayStatus)
- resolve()
- }
- } catch (exception) {
- console.log(exception)
+ }
+ ws.onerror = (err) => {
updateRelayStatus(relay, "Error", 0, undefined, relayStatus)
- try {
- ws.close()
- } catch (exception) {
- }
- reject(exception)
+ console.log("Error", err)
+ ws.close()
+ reject(err)
}
- })
-
- // broadcast events to list of relays
- const broadcastEvents = async (data) => {
- // batch processing of 10 relays
- let broadcastFunctions = [...relays]
- let relayStatus = {}
- while (broadcastFunctions.length) {
- let relaysForThisRound = broadcastFunctions.splice(0, 10)
- $('#broadcasting-progress').val(relays.length - broadcastFunctions.length)
- await Promise.allSettled( relaysForThisRound.map((relay) => sendToRelay(relay, data, relayStatus)) )
+ ws.onclose = (socket, event) => {
+ updateRelayStatus(relay, "Done", 0, undefined, relayStatus)
+ console.log("OnClose", relayStatus)
+ resolve()
+ }
+ } catch (exception) {
+ console.log(exception)
+ updateRelayStatus(relay, "Error", 0, undefined, relayStatus)
+ try {
+ ws.close()
+ } catch (exception) {
+ }
+ reject(exception)
+ }
+ })
+
+// broadcast events to list of relays
+const broadcastEvents = async (data) => {
+ // batch processing of 10 relays
+ let broadcastFunctions = [...relays]
+ let relayStatus = {}
+ while (broadcastFunctions.length) {
+ let relaysForThisRound = broadcastFunctions.splice(0, 10)
+ $('#broadcasting-progress').val(relays.length - broadcastFunctions.length)
+ await Promise.allSettled( relaysForThisRound.map((relay) => sendToRelay(relay, data, relayStatus)) )
+ }
+
+ displayRelayStatus(relayStatus)
+}
+
+
+
+async function generateNostrEventId(msg) {
+ const digest = [
+ 0,
+ msg.pubkey,
+ msg.created_at,
+ msg.kind,
+ msg.tags,
+ msg.content,
+ ];
+ const digest_str = JSON.stringify(digest);
+ const hash = await sha256Hex(digest_str);
+
+ return hash;
+}
+
+function sha256Hex(string) {
+ const utf8 = new TextEncoder().encode(string);
+
+ return crypto.subtle.digest('SHA-256', utf8).then((hashBuffer) => {
+ const hashArray = Array.from(new Uint8Array(hashBuffer));
+ const hashHex = hashArray
+ .map((bytes) => bytes.toString(16).padStart(2, '0'))
+ .join('');
+
+ return hashHex;
+ });
+}
+
+async function signNostrAuthEvent(relay, auth_challenge) {
+ try {
+
+ if (!window.nostr) {
+ throw "Nostr extension not loaded or available"
}
- displayRelayStatus(relayStatus)
+ let msg = {
+ kind: 22243, // NIP-42++
+ content: "",
+ tags: [
+ ["relay", relay]
+ ["challenge", auth_challenge]
+ ],
+ };
+
+ // set msg fields
+ msg.created_at = Math.floor((new Date()).getTime() / 1000);
+ msg.pubkey = await window.nostr.getPublicKey();
+
+ // Generate event id
+ msg.id = await generateNostrEventId(msg);
+
+ // Sign event
+ signed_msg = await window.nostr.signEvent(msg);
+
+ } catch (e) {
+ console.log("Failed to sign message with browser extension", e);
+ return undefined;
}
- async function signNostrAuthEvent(relay, auth_challenge) {
- try {
-
- if (!window.nostr) {
- throw "Nostr extension not loaded or available"
- }
-
- let msg = {
- kind: 22243, // NIP-42++
- content: "",
- tags: [
- ["relay", relay]
- ["challenge", auth_challenge]
- ],
- };
-
- // set msg fields
- msg.created_at = Math.floor((new Date()).getTime() / 1000);
- msg.pubkey = await window.nostr.getPublicKey();
-
- // Generate event id
- msg.id = await generateNostrEventId(msg);
-
- // Sign event
- signed_msg = await window.nostr.signEvent(msg);
-
- } catch (e) {
- console.log("Failed to sign message with browser extension", e);
- return undefined;
- }
-
- return signed_msg;
- }
-
- async function generateNostrEventId(msg) {
- const digest = [
- 0,
- msg.pubkey,
- msg.created_at,
- msg.kind,
- msg.tags,
- msg.content,
- ];
- const digest_str = JSON.stringify(digest);
- const hash = await sha256Hex(digest_str);
-
- return hash;
- }
-
- function sha256Hex(string) {
- const utf8 = new TextEncoder().encode(string);
-
- return crypto.subtle.digest('SHA-256', utf8).then((hashBuffer) => {
- const hashArray = Array.from(new Uint8Array(hashBuffer));
- const hashHex = hashArray
- .map((bytes) => bytes.toString(16).padStart(2, '0'))
- .join('');
-
- return hashHex;
- });
- }
\ No newline at end of file
+ return signed_msg;
+}
\ No newline at end of file