Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

(Tutorial) Nostr for Dummies: How to implement NOSTR Protocol from scratch with Python (NIP-01) #971

Open
ionextdebug opened this issue Jan 7, 2024 · 1 comment

Comments

@ionextdebug
Copy link

ionextdebug commented Jan 7, 2024

Baby steps to implement your backend for NOSTR using only general purpose packages (no NOSTR Toolkit or SDK).
Original: https://fullstackengineer.hashnode.dev/how-to-implement-nostr-protocol-from-scratch-with-python-nip-01

This tutorial teach you the simple way to implement NOSTR Protocol without NOSTR toolkit. The focus is only to implement a simple event [publish step].

IMPORTANT:
You can use any relay from nostr.watch, the relay applied in this tutorial is only for example usage - it's NOT a recommendation OR preference.

CLAUSE 1: To have a well-formed Relay or Client you MUST support NIP-01 features and syntax. Another NIPs are all optional, and you CAN create your own custom features.

Follow the bellow code reading the comments to understand what's happening.

MORE INFORMATION: This is a complementary tutorial, if you need more details about the meaning of each word please refer to NIP-01 declaration.

# Package installation for Python in a non-Jupyter environment
pip install websockets secp256k1 sha256


# Package installation on Jupyter Notebook environment (uncomment if you are using the Jupyter Notebook)
# ! pip install websockets # Connect you with the Relay
# ! pip install secp256k1 # Generate the private key and public key
# ! pip install sha256 # Generate needed hash




# package importation
import asyncio
import websockets
import secrets
import secp256k1
import time
import json
from hashlib import sha256
from time import time


# The custom content of note that will be publish in this tutorial
content = "Hello, world!" #input("What's your message to the world?")


# Token applied to generate public-private keypair
secrets_token_32bit = secrets.token_bytes(32)
# User's private key (use print(private_key.hex()) to print)
private_key = secp256k1.PrivateKey(secrets_token_32bit)
# User's public key
public_key = private_key.pubkey.serialize()[1:].hex()


# Definition of required elements according to NIP-01
tags = []
kind = 0
timestamp = int(time()) # timestamp in SECONDS


# Define the property "event_id"
event_id = sha256(
           json.dumps([
                      0, # ZERO is a CONSTANT, don't confuse with kind
                       public_key,
                       timestamp,
                       kind,
                       tags,
                       content], separators=(',', ':'))
                .encode('utf-8'))
                .hexdigest()

# Define the property "sig"
sig = private_key.schnorr_sign(bytes.fromhex(event_id), None, raw=True).hex()


# Define the note to send to Relays
note = json.dumps(["EVENT", {
  "id": event_id,
  "pubkey": public_key,
  "created_at": timestamp,
  "kind": kind,
  "tags": tags,
  "content": content,
  "sig": sig
}], separators=(',', ':'))


# Define the Relay for this tutorial (only for example)
relay : str = "wss://relay.geekiam.services"


# Connect to the Relay using Socket and send the note
async with websockets.connect(relay) as websocket:

    await websocket.send(note)
    print(f">>> {note}")

    greeting = await websocket.recv()
    print(f"<<< {greeting}")

You will receive the answer from the Relay. If the note was well-formed then the note will be published for the NOSTR network of relays and clients, if ill-formed you will receive an error message.

@FijiHasGithub
Copy link

It might be better to use the coincurve, as it's more cross-platform and properly maintained, unlike secp256k1

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants