bitchat-nostr
BitChat-over-Nostr transport for Python.
Implements the relay transport layer for BitChat: NIP-17 gift-wrap private messages, async relay client (NIP-01), and helpers for embedding BitChat binary packets inside Nostr events.
Installation
pip install bitchat-nostr
# Optional: NIP-44 encryption requires a secp256k1 library
pip install nostr-sdk # or pynostr, etc.
Quick Start
Listen for BitChat packets via Nostr relay
import asyncio
from bitchat_nostr import RelayClient, RelayConfig, NostrFilter, NostrKind, extract_packet_from_event
async def main():
async with RelayClient(RelayConfig(url='wss://relay.example.com')) as relay:
async def on_event(event, sub_id):
# After decrypting the gift wrap, extract the BitChat packet:
embedded = extract_packet_from_event(event)
if embedded:
print('Received BitChat packet from', embedded.sender_id_hex)
await relay.subscribe(
'bitchat-dm',
[NostrFilter(kinds=[int(NostrKind.GIFT_WRAP)])],
on_event,
)
await asyncio.sleep(60) # listen for 60 seconds
asyncio.run(main())
Send a BitChat packet via NIP-17
from bitchat_protocol import encode as encode_packet, BitchatPacket, MessageType
from bitchat_nostr import build_dm_rumor, wrap_and_send, RelayClient, RelayConfig
async def send():
# 1. Encode your BitChat packet
packet = BitchatPacket(version=1, type=int(MessageType.NOISE_ENCRYPTED), ...)
wire = encode_packet(packet, padding=False)
# 2. Build a NIP-17 DM rumor carrying the packet
rumor = build_dm_rumor(wire, sender_nostr_pubkey, recipient_nostr_pubkey)
# 3. Wrap and publish (requires your CryptoProvider implementation)
gift_wrap_event = wrap_and_send(rumor, sender_privkey, recipient_pubkey, crypto)
async with RelayClient(RelayConfig(url='wss://relay.example.com')) as relay:
ok = await relay.publish(gift_wrap_event)
print('Published:', ok)
API
RelayClient
RelayClient(config: RelayConfig, *, connect_timeout=5.0, publish_timeout=3.0, ...)
async with client:
await client.subscribe(id, filters, on_event, on_eose=None)
await client.unsubscribe(id)
await client.publish(event) -> bool
await client.close()
Embedding Helpers
encode_packet_to_base64(packet_bytes: bytes) -> str
decode_packet_from_base64(content: str) -> bytes | None
extract_packet_from_event(event: NostrEvent) -> EmbeddedBitChatPayload | None
build_dm_rumor(packet_bytes, sender_pubkey, recipient_pubkey) -> NostrRumor
build_geohash_presence_event(packet_bytes, sender_pubkey, geohash) -> NostrRumor
NIP-17 Gift Wrap
wrap_and_send(rumor, sender_privkey, recipient_pubkey, crypto) -> NostrEvent
receive_and_unwrap(gift_wrap_event, recipient_privkey, crypto) -> NostrRumor | None
# Individual steps:
seal_rumor(rumor, sender_privkey, recipient_pubkey, crypto) -> NostrEvent
gift_wrap(seal, recipient_pubkey, crypto) -> NostrEvent
unwrap_gift(gift_wrap_event, recipient_privkey, crypto) -> NostrEvent | None
unseal_rumor(seal_event, recipient_privkey, crypto) -> NostrRumor | None
CryptoProvider Protocol
class MyCrypto:
def nip44_encrypt(self, plaintext, sender_privkey, recipient_pubkey) -> str: ...
def nip44_decrypt(self, ciphertext, recipient_privkey, sender_pubkey) -> str | None: ...
def get_public_key(self, private_key) -> str: ...
def sign_event(self, event, private_key) -> NostrEvent: ...
def generate_ephemeral_key(self) -> bytes: ...
Running Tests
pip install -e ".[dev]"
pytest
License
Unlicense — public domain.
Metadata
Release files for bitchat-nostr 0.1.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| bitchat_nostr-0.1.2.tar.gz | 11.2 kB | Without provenance | Details for bitchat_nostr-0.1.2.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| bitchat_nostr-0.1.2-py3-none-any.whl | Python 3 | none | any | Details for bitchat_nostr-0.1.2-py3-none-any.whl |
Total release size: 22.6 kB
Release files / bitchat_nostr-0.1.2.tar.gz
| Download URL | bitchat_nostr-0.1.2.tar.gz |
|---|---|
| Size | 11.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
499a744d9ff530b287d7e2d62aa45a738e2ec793b18a6ad374d10aea50a8079d
|
|
BLAKE2b-256 checksum How to use checksums |
e5c14b98db6384fc3dd8f4178086b0fdaa8daf1f90d42cb87b4418b10cca8d01
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.2
|
Release files / bitchat_nostr-0.1.2-py3-none-any.whl
| Download URL | bitchat_nostr-0.1.2-py3-none-any.whl |
|---|---|
| Size | 11.4 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6c055a8e0da97c21701794d2f97912a70faf0b11266a6bd54a9ea05b5efb702f
|
|
BLAKE2b-256 checksum How to use checksums |
aeb38ddc971d736f342d387c5ec07f97ea627e6dedac9222e3e66b7ec97bcc2a
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.2
|
Security for bitchat-nostr 0.1.2
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.