Support RIP-02 alongside NIP-91 for provider discovery protocol

Co-authored-by: db2002dominic <db2002dominic@gmail.com>
This commit is contained in:
Cursor Agent
2025-08-10 18:50:54 +00:00
co-authored by db2002dominic
parent 6b1f432c58
commit 2a934dbda4
3 changed files with 20 additions and 19 deletions
+1 -1
View File
@@ -33,7 +33,7 @@ sequenceDiagram
- **API Key Management** Hashed keys stored in SQLite with balance tracking and optional expiry/refund address
- **Model-Based Pricing** Convert USD prices in `models.json` to sats using live BTC/USD rates
- **Admin Dashboard** Simple HTML interface at `/admin/` to view balances and API keys
- **Discovery** Fetch available providers from Nostr relays using NIP-91 protocol
- **Discovery** Fetch available providers from Nostr relays using both RIP-02 and NIP-91 protocols
- **NIP-91 Auto-Announcement** Automatically announce this provider to Nostr relays when NSEC is provided
- **Docker Support** Provided `Dockerfile` and `compose.yml` for running with an optional Tor hidden service
+9 -8
View File
@@ -25,13 +25,13 @@ async def query_nostr_relay_for_providers(
) -> list[dict[str, Any]]:
"""
Query a Nostr relay for provider announcements.
Searches for NIP-91 (kind:38421) events.
Searches for both RIP-02 and NIP-91 (kind:38421) events.
"""
events = []
# Build filter for NIP-91 events
filter_obj: dict[str, Any] = {
"kinds": [38421], # NIP-91 Provider Announcements
"kinds": [38421], # Both RIP-02 and NIP-91 Provider Announcements
"limit": limit,
}
@@ -81,7 +81,7 @@ async def query_nostr_relay_for_providers(
def parse_provider_announcement(event: dict[str, Any]) -> dict[str, Any] | None:
"""
Parse provider announcement events.
Handles NIP-91 (kind:38421) format.
Handles both RIP-02 and NIP-91 (kind:38421) formats.
Returns structured provider data or None if invalid.
"""
try:
@@ -100,7 +100,7 @@ def parse_provider_announcement(event: dict[str, Any]) -> dict[str, Any] | None:
version = None
# Parse NIP-91 format
if kind == 38421: # NIP-91 format
if kind == 38421: # RIP-02/NIP-91 format
for tag in tags:
if len(tag) >= 2:
if tag[0] == "d":
@@ -133,7 +133,7 @@ def parse_provider_announcement(event: dict[str, Any]) -> dict[str, Any] | None:
# Validate NIP-91 required fields
if not endpoint_url or not d_tag:
print(f"Invalid NIP-91 announcement - missing required fields: {event['id']}")
print(f"Invalid RIP-02/NIP-91 announcement - missing required fields: {event['id']}")
return None
else:
print(f"Unknown event kind: {kind}")
@@ -222,11 +222,12 @@ async def get_providers(
include_json: bool = False, pubkey: str | None = None
) -> dict[str, list[dict[str, Any]]]:
"""
Discover Routstr providers using NIP-91 specification.
Discover Routstr providers using both RIP-02 and NIP-91 specifications.
Searches for provider announcement events on Nostr relays:
- kind:38421 (NIP-91)
- kind:38421 (RIP-02/NIP-91)
References:
- RIP-02: https://github.com/Routstr/protocol/blob/main/RIP-02.md
- NIP-91: https://github.com/nostr-protocol/nips/pull/1987
"""
# Default relays for provider discovery
@@ -263,7 +264,7 @@ async def get_providers(
print(f"Found {len(all_events)} total unique provider announcements")
# Parse provider announcements according to NIP-91
# Parse provider announcements according to RIP-02/NIP-91
providers = []
for event in all_events:
parsed_provider = parse_provider_announcement(event)
+10 -10
View File
@@ -27,7 +27,7 @@ async def test_providers_endpoint_default_response(
{
"id": "event1",
"pubkey": "test_pubkey1",
"kind": 38421, # NIP-91 event kind
"kind": 38421, # RIP-02/NIP-91 event kind
"created_at": 1234567890,
"content": '{"name": "Provider 1", "about": "Test provider 1"}',
"tags": [
@@ -38,7 +38,7 @@ async def test_providers_endpoint_default_response(
{
"id": "event2",
"pubkey": "test_pubkey2",
"kind": 38421, # NIP-91 event kind
"kind": 38421, # RIP-02/NIP-91 event kind
"created_at": 1234567891,
"content": '{"name": "Provider 2", "about": "Test provider 2"}',
"tags": [
@@ -100,7 +100,7 @@ async def test_providers_endpoint_with_include_json(
{
"id": "event1",
"pubkey": "test_pubkey",
"kind": 38421, # NIP-91 event kind
"kind": 38421, # RIP-02/NIP-91 event kind
"created_at": 1234567890,
"content": '{"name": "Test Provider", "about": "A test provider"}',
"tags": [
@@ -165,13 +165,13 @@ async def test_providers_data_structure_validation(
) -> None:
"""Test provider data structure contains expected fields"""
# Mock NIP-91 provider announcement event
# Mock RIP-02/NIP-91 provider announcement event
mock_events: list[dict[str, Any]] = [
{
"id": "event1",
"pubkey": "test_pubkey",
"created_at": 1234567890,
"kind": 38421, # NIP-91 event kind
"kind": 38421, # RIP-02/NIP-91 event kind
"content": '{"name": "Comprehensive Provider", "about": "A comprehensive AI provider"}',
"tags": [
["d", "provider-123"],
@@ -212,7 +212,7 @@ async def test_providers_data_structure_validation(
assert "health" in provider_data
provider_info = provider_data["provider"]
# Expected fields from NIP-91 parser
# Expected fields from RIP-02/NIP-91 parser
expected_fields = ["id", "name", "endpoint_url", "supported_models"]
for field in expected_fields:
assert field in provider_info
@@ -261,7 +261,7 @@ async def test_providers_endpoint_offline_providers(
{
"id": "event1",
"pubkey": "healthy_provider_pubkey",
"kind": 38421, # NIP-91 event kind
"kind": 38421, # RIP-02/NIP-91 event kind
"created_at": 1234567890,
"content": '{"name": "Healthy Provider", "about": "Healthy provider announcement"}',
"tags": [
@@ -272,7 +272,7 @@ async def test_providers_endpoint_offline_providers(
{
"id": "event2",
"pubkey": "offline_provider_pubkey",
"kind": 38421, # NIP-91 event kind
"kind": 38421, # RIP-02/NIP-91 event kind
"created_at": 1234567891,
"content": '{"name": "Offline Provider", "about": "Offline provider announcement"}',
"tags": [
@@ -334,7 +334,7 @@ async def test_providers_endpoint_duplicate_urls(
{
"id": "event1",
"pubkey": "provider_pubkey",
"kind": 38421, # NIP-91 event kind
"kind": 38421, # RIP-02/NIP-91 event kind
"created_at": 1234567890,
"content": '{"name": "Provider", "about": "Provider announcement"}',
"tags": [
@@ -345,7 +345,7 @@ async def test_providers_endpoint_duplicate_urls(
{
"id": "event2",
"pubkey": "other_provider_pubkey",
"kind": 38421, # NIP-91 event kind
"kind": 38421, # RIP-02/NIP-91 event kind
"created_at": 1234567892,
"content": '{"name": "Other Provider", "about": "Different provider announcement"}',
"tags": [