commit c8223908c172a4eec4399174aa86044c5540597c Author: Joachim Happel Date: Mon Aug 12 19:38:09 2024 +0200 initial diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..25c8fdb --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +node_modules +package-lock.json \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..d3162e0 --- /dev/null +++ b/README.md @@ -0,0 +1,25 @@ +# Nostr Playgraound to SC24 + + Prepare the environment by installing a docker container with the Nostr relay server. + + ```shell + docker pull scsibug/nostr-rs-relay + docker run -p 7000:8080 scsibug/nostr-rs-relay +``` + + Install the necessary dependencies by running the following commands: + + ```shell +git clone https://git.rpi-virtuell.de/Comenius-Institut/nostr-oer-client +cd nostr-oer-client +npm install +``` + + Run the script on your shell with the following command: `node listen.js` + This script listens for new messages on the Nostr network. + It connects to a Nostr relay server and subscribes to text notes/messages. + When a new message is received, it prints the message content, sender's public key, and timestamp. + + Test with the send.js script to send a message. + run the send.js script with the following command: `node send.js` + \ No newline at end of file diff --git a/createEventTextNote.js b/createEventTextNote.js new file mode 100644 index 0000000..b56fffe --- /dev/null +++ b/createEventTextNote.js @@ -0,0 +1,33 @@ +import { finalizeEvent, getEventHash, getPublicKey } from 'nostr-tools' + +const skHex = 'e8913a0b983c8678e3cce83a45ace14f6656bd06ff98803a38d72a5567e7e105' + +const event = { + kind: 1, + created_at: Math.floor(Date.now() / 1000), + tags: [], + content: 'Hello world! Welcome to SC24!', + pubkey: getPublicKey(skHex) +} + +event.id = getEventHash(event) +event.sig = finalizeEvent(event, skHex) + +const signedEvent = ['EVENT', event] + +function getCircularReplacer() { + const seen = new WeakSet(); + return (key, value) => { + if (typeof value === "object" && value !== null) { + if (seen.has(value)) { + return; //zyklische Referenzen lassen sich nicht anzeigen + } + seen.add(value); + } + return value; + }; +} + +console.log( + JSON.stringify(signedEvent, getCircularReplacer(), 2) // 2 für schönere Einrückung +) diff --git a/generateKeys.js b/generateKeys.js new file mode 100644 index 0000000..5d0a3f0 --- /dev/null +++ b/generateKeys.js @@ -0,0 +1,16 @@ +/** + * This script generates a secret key and a public key. + * to run this script, use the following command: node generateKeys.js + */ +import { bytesToHex, hexToBytes } from '@noble/hashes/utils' +import { generateSecretKey, getPublicKey } from 'nostr-tools/pure' + +const secretKey = generateSecretKey(); +const publicKey = getPublicKey(secretKey); + + +let skHex = bytesToHex(secretKey) +let backToBytes = hexToBytes(skHex) + +console.log('your sekret key:', skHex) +console.log('your public key = ', publicKey); diff --git a/listen.js b/listen.js new file mode 100644 index 0000000..b346259 --- /dev/null +++ b/listen.js @@ -0,0 +1,75 @@ +/** + * Prepare the environment by installing a docker container with the Nostr relay server. + * docker pull scsibug/nostr-rs-relay + * docker run -p 7000:8080 scsibug/nostr-rs-relay + * + * Install the necessary dependencies by running the following command: + * npm install + * + * Run the script with the following command: node listen.js + * This script listens for new messages on the Nostr network. + * It connects to a Nostr relay server and subscribes to text notes/messages. + * When a new message is received, it prints the message content, sender's public key, and timestamp. + * + * Test with the send.js script to send a message. + * run the send.js script with the following command: node send.js + */ + + +import { Relay } from 'nostr-tools/relay' +import { verifyEvent } from 'nostr-tools/pure' + +// If not running in Node.js, comment the following 3 lines: +import WebSocket from 'ws' +import { useWebSocketImplementation } from 'nostr-tools/relay' +useWebSocketImplementation(WebSocket) + +const RELAY_URL = 'ws://localhost:7000' // Replace with your preferred relay + +async function listenForMessages() { + try { + const relay = await Relay.connect(RELAY_URL) + console.log(`Connected to ${relay.url}`) + + const sub = relay.subscribe( + [ + { + kinds: [1], // Listen for text notes/messages + since: Math.floor(Date.now() / 1000) // Only get new messages from now on + } + ], + { + onevent(event) { + if (verifyEvent(event)) { + console.log('New message received:') + console.log(`From: ${event.pubkey}`) + console.log(`Content: ${event.content}`) + console.log(`Timestamp: ${new Date(event.created_at * 1000).toLocaleString()}`) + console.log('---') + } else { + console.log('Received an invalid event') + } + }, + oneose() { + console.log('Subscription stream ended') + }, + onerror(error) { + console.error('Subscription error:', error) + } + } + ) + + // Keep the script running + process.on('SIGINT', () => { + console.log('Closing subscription and relay connection') + sub.close() + relay.close() + process.exit() + }) + + } catch (error) { + console.error('Error connecting to relay:', error) + } +} + +listenForMessages() \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..04f7f47 --- /dev/null +++ b/package.json @@ -0,0 +1,17 @@ +{ + "dependencies": { + "nostr-tools": "^2.7.2", + "ws": "^8.18.0" + }, + "name": "nostr-oer-client", + "type": "module", + "version": "1.0.0", + "main": "createEventTextNote.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "", + "license": "ISC", + "description": "" +} diff --git a/send.js b/send.js new file mode 100644 index 0000000..61a8305 --- /dev/null +++ b/send.js @@ -0,0 +1,39 @@ +import { bytesToHex, hexToBytes } from '@noble/hashes/utils' // already an installed dependency +import { generateSecretKey, getPublicKey, finalizeEvent } from 'nostr-tools/pure' +import { Relay } from 'nostr-tools/relay' +import WebSocket from 'ws'; + +// Provide WebSocket implementation to nostr-tools +global.WebSocket = WebSocket; + +// Generate keys (or use existing ones) +//let secretKey = generateSecretKey() +//let pk = getPublicKey(secretKey) +//let sk = bytesToHex(secretKey) +let sk = 'e8913a0b983c8678e3cce83a45ace14f6656bd06ff98803a38d72a5567e7e105'; + + + +// Create event template +let eventTemplate = { + kind: 1, + created_at: Math.floor(Date.now() / 1000), + tags: [], + content: 'Hello world! Welcome to SC24!', +} + +// Finalize and sign the event +const signedEvent = finalizeEvent(eventTemplate, sk) + +// Connect to a relay and publish +async function publishMessage() { + const relay = await Relay.connect('ws://localhost:7000') + console.log(`connected to ${relay.url}`) + + await relay.publish(signedEvent) + console.log('Event published!') + + relay.close() +} + +publishMessage() \ No newline at end of file diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..bbc473a --- /dev/null +++ b/yarn.lock @@ -0,0 +1,78 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@noble/ciphers@^0.5.1": + version "0.5.3" + resolved "https://registry.npmjs.org/@noble/ciphers/-/ciphers-0.5.3.tgz" + integrity sha512-B0+6IIHiqEs3BPMT0hcRmHvEj2QHOLu+uwt+tqDDeVd0oyVzh7BPrDcPjRnV1PV/5LaknXJJQvOuRGR0zQJz+w== + +"@noble/curves@~1.1.0": + version "1.1.0" + resolved "https://registry.npmjs.org/@noble/curves/-/curves-1.1.0.tgz" + integrity sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA== + dependencies: + "@noble/hashes" "1.3.1" + +"@noble/curves@1.2.0": + version "1.2.0" + resolved "https://registry.npmjs.org/@noble/curves/-/curves-1.2.0.tgz" + integrity sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw== + dependencies: + "@noble/hashes" "1.3.2" + +"@noble/hashes@~1.3.0", "@noble/hashes@~1.3.1", "@noble/hashes@1.3.1": + version "1.3.1" + resolved "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz" + integrity sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA== + +"@noble/hashes@1.3.2": + version "1.3.2" + resolved "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.2.tgz" + integrity sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ== + +"@scure/base@~1.1.0", "@scure/base@1.1.1": + version "1.1.1" + resolved "https://registry.npmjs.org/@scure/base/-/base-1.1.1.tgz" + integrity sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA== + +"@scure/bip32@1.3.1": + version "1.3.1" + resolved "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.1.tgz" + integrity sha512-osvveYtyzdEVbt3OfwwXFr4P2iVBL5u1Q3q4ONBfDY/UpOuXmOlbgwc1xECEboY8wIays8Yt6onaWMUdUbfl0A== + dependencies: + "@noble/curves" "~1.1.0" + "@noble/hashes" "~1.3.1" + "@scure/base" "~1.1.0" + +"@scure/bip39@1.2.1": + version "1.2.1" + resolved "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.1.tgz" + integrity sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg== + dependencies: + "@noble/hashes" "~1.3.0" + "@scure/base" "~1.1.0" + +nostr-tools@^2.7.2: + version "2.7.2" + resolved "https://registry.npmjs.org/nostr-tools/-/nostr-tools-2.7.2.tgz" + integrity sha512-Bq3Ug0SZFtgtL1+0wCnAe8AJtI7yx/00/a2nUug9SkhfOwlKS92Tef12iCK9FdwXw+oFZWMtRnSwcLayQso+xA== + dependencies: + "@noble/ciphers" "^0.5.1" + "@noble/curves" "1.2.0" + "@noble/hashes" "1.3.1" + "@scure/base" "1.1.1" + "@scure/bip32" "1.3.1" + "@scure/bip39" "1.2.1" + optionalDependencies: + nostr-wasm v0.1.0 + +nostr-wasm@v0.1.0: + version "0.1.0" + resolved "https://registry.npmjs.org/nostr-wasm/-/nostr-wasm-0.1.0.tgz" + integrity sha512-78BTryCLcLYv96ONU8Ws3Q1JzjlAt+43pWQhIl86xZmWeegYCNLPml7yQ+gG3vR6V5h4XGj+TxO+SS5dsThQIA== + +ws@^8.18.0: + version "8.18.0" + resolved "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz" + integrity sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==