commit f476611d115f0c9030a8c45ca9da0a15efb6da0f
parent 7104657813fd3f783ecf9a23f164ec40519ddc01
Author: triesap <triesap@radroots.dev>
Date: Thu, 25 Dec 2025 01:53:26 +0000
kit: add Swift nostr posting and stream helpers
- Bump RadrootsCore submodule to latest runtime APIs
- Add NostrEventId wrapper for typed event identifiers
- Expose profile/text/reply posting helpers on Radroots
- Add start/next/stop post stream helpers with runtime guard
Diffstat:
1 file changed, 93 insertions(+), 0 deletions(-)
diff --git a/RadrootsKit/Sources/RadrootsKit/Nostr.swift b/RadrootsKit/Sources/RadrootsKit/Nostr.swift
@@ -0,0 +1,93 @@
+import Foundation
+
+public struct NostrEventId: Hashable, Sendable {
+ public let rawValue: String
+
+ public init(_ rawValue: String) {
+ self.rawValue = rawValue
+ }
+}
+
+public extension NostrPostEventMetadata {
+ var eventId: NostrEventId {
+ NostrEventId(id)
+ }
+}
+
+public extension NostrProfileEventMetadata {
+ var eventId: NostrEventId {
+ NostrEventId(id)
+ }
+}
+
+public enum RadrootsRuntimeError: LocalizedError {
+ case runtimeNotStarted
+
+ public var errorDescription: String? {
+ "Radroots runtime not started."
+ }
+}
+
+@MainActor
+public extension Radroots {
+ func nostrPostProfile(
+ name: String? = nil,
+ displayName: String? = nil,
+ nip05: String? = nil,
+ about: String? = nil
+ ) throws -> NostrEventId {
+ let rt = try requireRuntime()
+ let id = try rt.nostrPostProfile(
+ name: name,
+ displayName: displayName,
+ nip05: nip05,
+ about: about
+ )
+ return NostrEventId(id)
+ }
+
+ func nostrPostTextNote(content: String) throws -> NostrEventId {
+ let rt = try requireRuntime()
+ let id = try rt.nostrPostTextNote(content: content)
+ return NostrEventId(id)
+ }
+
+ func nostrPostReply(
+ parentEventIdHex: String,
+ parentAuthorHex: String,
+ content: String,
+ rootEventIdHex: String? = nil
+ ) throws -> NostrEventId {
+ let rt = try requireRuntime()
+ let id = try rt.nostrPostReply(
+ parentEventIdHex: parentEventIdHex,
+ parentAuthorHex: parentAuthorHex,
+ content: content,
+ rootEventIdHex: rootEventIdHex
+ )
+ return NostrEventId(id)
+ }
+
+ func nostrStartPostStream(sinceUnix: UInt64? = nil) throws {
+ let rt = try requireRuntime()
+ try rt.nostrStartPostEventStream(sinceUnix: sinceUnix)
+ }
+
+ func nostrNextPostStreamEvent() -> NostrPostEventMetadata? {
+ guard let rt = runtime else { return nil }
+ return rt.nostrNextPostEvent()
+ }
+
+ func nostrStopPostStream() throws {
+ let rt = try requireRuntime()
+ try rt.nostrStopPostEventStream()
+ }
+}
+
+@MainActor
+private extension Radroots {
+ func requireRuntime() throws -> RadrootsRuntime {
+ guard let rt = runtime else { throw RadrootsRuntimeError.runtimeNotStarted }
+ return rt
+ }
+}