{"id":43878464,"url":"https://github.com/yysskk/swift-nostr-client","last_synced_at":"2026-03-01T17:37:46.221Z","repository":{"id":335614991,"uuid":"1137297056","full_name":"yysskk/swift-nostr-client","owner":"yysskk","description":"A Swift library for the Nostr protocol, built with Swift 6 concurrency support.","archived":false,"fork":false,"pushed_at":"2026-01-31T07:00:26.000Z","size":75,"stargazers_count":6,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-02-18T10:43:11.662Z","etag":null,"topics":["bitcoin","ios","macos","nostr","tvos","watchos"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/yysskk.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-01-19T07:25:26.000Z","updated_at":"2026-02-03T04:38:33.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/yysskk/swift-nostr-client","commit_stats":null,"previous_names":["yysskk/swift-nostr-client"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/yysskk/swift-nostr-client","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yysskk%2Fswift-nostr-client","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yysskk%2Fswift-nostr-client/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yysskk%2Fswift-nostr-client/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yysskk%2Fswift-nostr-client/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/yysskk","download_url":"https://codeload.github.com/yysskk/swift-nostr-client/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/yysskk%2Fswift-nostr-client/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":29976296,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-01T16:35:47.903Z","status":"ssl_error","status_checked_at":"2026-03-01T16:35:44.899Z","response_time":124,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bitcoin","ios","macos","nostr","tvos","watchos"],"created_at":"2026-02-06T15:00:42.825Z","updated_at":"2026-03-01T17:37:46.165Z","avatar_url":"https://github.com/yysskk.png","language":"Swift","funding_links":[],"categories":["Libraries"],"sub_categories":["Client reviews and/or comparisons"],"readme":"# NostrClient\n\nA modern Swift library for the Nostr protocol, built with Swift 6 concurrency support.\n\n## Features\n\n- **Full NIP-01 Support**: Events, subscriptions, and relay communication\n- **NIP-02 Contact List**: Follow/unfollow users and manage contact lists\n- **NIP-03 OpenTimestamps**: Attach OTS attestations to events\n- **NIP-05 Verification**: DNS-based identifier verification\n- **NIP-06 Key Derivation**: Generate keys from BIP-39 mnemonic seed phrases\n- **NIP-17 Private DMs**: End-to-end encrypted direct messages with sender anonymity\n- **Cryptographic Operations**: Schnorr signatures with secp256k1\n- **Bech32 Encoding**: npub/nsec key encoding (NIP-19)\n- **Async/Await**: Modern Swift concurrency with actors\n- **Multi-Relay Support**: Connect to multiple relays with RelayPool\n- **Type-Safe**: Full Sendable compliance for thread safety\n\n## Requirements\n\n- Swift 6.2+\n- iOS 17.0+ / macOS 14.0+ / tvOS 17.0+ / watchOS 10.0+ / visionOS 1.0+\n\n## Installation\n\n### Swift Package Manager\n\nAdd to your `Package.swift`:\n\n```swift\ndependencies: [\n    .package(url: \"https://github.com/yysskk/swift-nostr-client\", from: \"1.0.0\")\n]\n```\n\nOr add via Xcode: File → Add Package Dependencies → Enter repository URL.\n\n## Quick Start\n\n### Generate Keys\n\n```swift\nimport NostrClient\n\n// Generate a new random keypair\nlet keyPair = try KeyPair()\nprint(\"Public Key: \\(keyPair.publicKeyHex)\")\nprint(\"npub: \\(keyPair.npub)\")\nprint(\"nsec: \\(keyPair.nsec)\")\n\n// Import from nsec\nlet imported = try KeyPair(nsec: \"nsec1...\")\n\n// Generate from mnemonic (NIP-06)\nlet (mnemonic, keyPairFromMnemonic) = try KeyPair.generate(wordCount: 12)\nprint(\"Mnemonic: \\(mnemonic.phrase)\")\nprint(\"Public Key: \\(keyPairFromMnemonic.npub)\")\n\n// Restore from existing mnemonic\nlet restored = try KeyPair(mnemonicPhrase: \"leader monkey parrot ring guide accident before fence cannon height naive bean\")\n```\n\n### Connect to Relays\n\n```swift\nlet client = NostrClient()\n\n// Add relays\ntry await client.addRelays([\n    \"wss://relay.damus.io\",\n    \"wss://nos.lol\",\n    \"wss://relay.nostr.band\"\n])\n\n// Connect\ntry await client.connect()\n```\n\n### Publish Events\n\n```swift\n// Set your private key\ntry await client.setNsec(\"nsec1...\")\n\n// Publish a text note\nlet event = try await client.publishTextNote(content: \"Hello, Nostr!\")\n\n// Publish with tags\nlet tagged = try await client.publishTextNote(\n    content: \"Check out #nostr\",\n    tags: [[\"t\", \"nostr\"]]\n)\n\n// React to an event\ntry await client.publishReaction(to: event, content: \"🤙\")\n```\n\n### Subscribe to Events\n\n```swift\n// Subscribe to a user's notes\nlet subscriptionId = try await client.subscribeToUserTimeline(pubkey: \"...\") { event in\n    print(\"New note: \\(event.content)\")\n}\n\n// Subscribe to the global feed\ntry await client.subscribeToGlobalFeed(limit: 50) { event in\n    print(\"Global: \\(event.content)\")\n}\n\n// Custom filter subscription\nlet filter = Filter(\n    kinds: [1],\n    authors: [\"pubkey1\", \"pubkey2\"],\n    limit: 100\n)\ntry await client.subscribe(filters: [filter]) { event in\n    print(\"Received: \\(event.id)\")\n}\n\n// Unsubscribe\ntry await client.unsubscribe(subscriptionId: subscriptionId)\n```\n\n### Fetch Events\n\n```swift\n// Fetch specific event\nlet event = try await client.fetchEvent(id: \"eventid...\")\n\n// Fetch user metadata\nlet metadata = try await client.fetchMetadata(pubkey: \"...\")\nprint(\"Name: \\(metadata?.name ?? \"Unknown\")\")\n```\n\n## Models\n\n### Event\n\n```swift\npublic struct Event: Codable, Identifiable, Hashable, Sendable {\n    public let id: String\n    public let pubkey: String\n    public let createdAt: Int64\n    public let kind: Int\n    public let tags: [[String]]\n    public let content: String\n    public let sig: String\n}\n```\n\n### Filter\n\n```swift\npublic struct Filter: Codable, Sendable, Hashable {\n    public var ids: [String]?\n    public var authors: [String]?\n    public var kinds: [Int]?\n    public var eventReferences: [String]?    // #e\n    public var pubkeyReferences: [String]?   // #p\n    public var since: Int64?\n    public var until: Int64?\n    public var limit: Int?\n}\n```\n\n### Event Kinds\n\n```swift\nEvent.Kind.setMetadata          // 0\nEvent.Kind.textNote             // 1\nEvent.Kind.recommendRelay       // 2\nEvent.Kind.contacts             // 3\nEvent.Kind.eventDeletion        // 5\nEvent.Kind.repost               // 6\nEvent.Kind.reaction             // 7\nEvent.Kind.seal                 // 13 (NIP-59)\nEvent.Kind.privateDirectMessage // 14 (NIP-17)\nEvent.Kind.giftWrap             // 1059 (NIP-59)\nEvent.Kind.zapRequest           // 9734\nEvent.Kind.zap                  // 9735\n// ... and more\n```\n\n## Low-Level API\n\n### Direct Relay Connection\n\n```swift\nlet connection = try RelayConnection(urlString: \"wss://relay.damus.io\")\nawait connection.connect()\n\n// Subscribe\ntry await connection.subscribe(\n    subscriptionId: \"sub1\",\n    filters: [Filter(kinds: [1], limit: 10)]\n)\n\n// Listen for messages\nfor await message in await connection.messages() {\n    switch message {\n    case .event(let subId, let event):\n        print(\"Event: \\(event.content)\")\n    case .endOfStoredEvents(let subId):\n        print(\"EOSE for \\(subId)\")\n    case .notice(let msg):\n        print(\"Notice: \\(msg)\")\n    default:\n        break\n    }\n}\n```\n\n### Manual Event Signing\n\n```swift\nlet keyPair = try KeyPair()\nlet signer = EventSigner(keyPair: keyPair)\n\nlet unsigned = UnsignedEvent(\n    pubkey: keyPair.publicKeyHex,\n    kind: .textNote,\n    tags: [[\"t\", \"test\"]],\n    content: \"Manual signing example\"\n)\n\nlet signed = try signer.sign(unsigned)\n\n// Verify signature\nlet isValid = try signed.verify()\n```\n\n## Supported NIPs\n\n- [x] NIP-01: Basic protocol\n- [x] NIP-02: Contact list and petnames\n- [x] NIP-03: OpenTimestamps attestations\n- [x] NIP-05: DNS-based identifiers\n- [x] NIP-06: Basic key derivation from mnemonic seed phrase\n- [x] NIP-17: Private direct messages\n- [x] NIP-19: bech32-encoded entities (npub, nsec)\n- [x] NIP-20: Command Results (OK)\n- [x] NIP-42: Authentication (AUTH message parsing)\n- [x] NIP-44: Versioned encryption\n- [x] NIP-59: Gift wrap\n\n## License\n\nMIT License\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyysskk%2Fswift-nostr-client","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fyysskk%2Fswift-nostr-client","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fyysskk%2Fswift-nostr-client/lists"}