refactor: simplify NostrClient API for beginner-friendliness
Comprehensive rename of the NostrClient relay infrastructure to use intuitive, self-documenting names instead of protocol-level jargon. Interface/class renames: - INostrClient → NostrClient (interface) - NostrClient → DefaultNostrClient (implementation) - IRequestListener → SubscriptionListener - IRelayClientListener → RelayConnectionListener - IOpenNostrRequest → SubscriptionHandle - NostrClientStaticReq → StaticSubscription - NostrClientDynamicReq → DynamicSubscription Method renames: - openReqSubscription() → subscribe() - close(subId) → unsubscribe(subId) - send() → publish() - queryCount() → count() - subscribe/unsubscribe(listener) → addConnectionListener/removeConnectionListener - renewFilters() → syncFilters() Callback renames: - onEose → onCaughtUp - isLive → isRealTime - onStartReq → onSubscriptionStarted - onCloseReq → onSubscriptionClosed Extension function renames: - query() → fetchAll() - downloadFirstEvent() → fetchFirst() - req() → subscribe() - reqAsFlow() → subscribeAsFlow() - reqUntilEoseAsFlow() → fetchAsFlow() - sendAndWaitForResponse() → publishAndConfirm() - queryCountSuspend() → count() - queryCountMergedHll() → countMerged() - reqBypassingRelayLimits() → fetchAllPages() - updateFilter() → refresh() on SubscriptionHandle https://claude.ai/code/session_01JPcYCcRx5eZN4GvgGxGwbf
This commit is contained in:
+10
-10
@@ -21,8 +21,8 @@
|
||||
package com.vitorpamplona.amethyst.commons.chess
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.INostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.reqs.IRequestListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.reqs.SubscriptionListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.single.newSubId
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
||||
@@ -49,7 +49,7 @@ enum class RelayFetchStatus {
|
||||
/**
|
||||
* One-shot relay fetch helper for chess events.
|
||||
*
|
||||
* Follows the existing INostrClient + IRequestListener + Channel pattern
|
||||
* Follows the existing NostrClient + SubscriptionListener + Channel pattern
|
||||
* from quartz (see NostrClientSingleDownloadExt.kt).
|
||||
*
|
||||
* Each fetch opens a subscription, collects events until EOSE from all relays,
|
||||
@@ -57,12 +57,12 @@ enum class RelayFetchStatus {
|
||||
* no state is cached between fetches.
|
||||
*/
|
||||
class ChessRelayFetchHelper(
|
||||
private val client: INostrClient,
|
||||
private val client: NostrClient,
|
||||
) {
|
||||
/**
|
||||
* Fetch events matching filters from relays, waiting for EOSE.
|
||||
*
|
||||
* @param filters Map of relay → filter list (same format as INostrClient.openReqSubscription)
|
||||
* @param filters Map of relay → filter list (same format as NostrClient.subscribe)
|
||||
* @param timeoutMs Max time to wait for relays to respond (default from ChessConfig)
|
||||
* @param onProgress Optional callback for progress updates per relay
|
||||
* @return Deduplicated list of events received before timeout/EOSE
|
||||
@@ -88,10 +88,10 @@ class ChessRelayFetchHelper(
|
||||
}
|
||||
|
||||
val listener =
|
||||
object : IRequestListener {
|
||||
object : SubscriptionListener {
|
||||
override fun onEvent(
|
||||
event: Event,
|
||||
isLive: Boolean,
|
||||
isRealTime: Boolean,
|
||||
relay: NormalizedRelayUrl,
|
||||
forFilters: List<Filter>?,
|
||||
) {
|
||||
@@ -100,7 +100,7 @@ class ChessRelayFetchHelper(
|
||||
onProgress?.invoke(RelayFetchProgress(relay, RelayFetchStatus.RECEIVING, count))
|
||||
}
|
||||
|
||||
override fun onEose(
|
||||
override fun onCaughtUp(
|
||||
relay: NormalizedRelayUrl,
|
||||
forFilters: List<Filter>?,
|
||||
) {
|
||||
@@ -114,7 +114,7 @@ class ChessRelayFetchHelper(
|
||||
}
|
||||
}
|
||||
|
||||
client.openReqSubscription(subId, filters, listener)
|
||||
client.subscribe(subId, filters, listener)
|
||||
val eoseResult = withTimeoutOrNull(timeoutMs) { allEose.await() }
|
||||
|
||||
// Mark timed-out relays
|
||||
@@ -127,7 +127,7 @@ class ChessRelayFetchHelper(
|
||||
}
|
||||
}
|
||||
|
||||
client.close(subId)
|
||||
client.unsubscribe(subId)
|
||||
|
||||
return events.values.toList()
|
||||
}
|
||||
|
||||
+2
-2
@@ -20,7 +20,7 @@
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.commons.domain.nip46
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.INostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.signers.NostrSignerInternal
|
||||
import com.vitorpamplona.quartz.nip46RemoteSigner.signer.NostrSignerRemote
|
||||
import kotlinx.coroutines.flow.first
|
||||
@@ -32,7 +32,7 @@ object BunkerLoginUseCase {
|
||||
suspend fun execute(
|
||||
bunkerUri: String,
|
||||
ephemeralSigner: NostrSignerInternal,
|
||||
client: INostrClient,
|
||||
client: NostrClient,
|
||||
): BunkerLoginResult {
|
||||
val remoteSigner = NostrSignerRemote.fromBunkerUri(bunkerUri, ephemeralSigner, client)
|
||||
remoteSigner.openSubscription()
|
||||
|
||||
+17
-14
@@ -24,8 +24,8 @@ import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.core.OptimizedJsonMapper
|
||||
import com.vitorpamplona.quartz.nip01Core.core.toHexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.crypto.KeyPair
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.INostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.reqs.req
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.reqs.StaticSubscription
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
||||
import com.vitorpamplona.quartz.nip01Core.signers.NostrSignerInternal
|
||||
@@ -83,7 +83,7 @@ object NostrConnectLoginUseCase {
|
||||
|
||||
suspend fun awaitAndLogin(
|
||||
uriData: NostrConnectUri,
|
||||
client: INostrClient,
|
||||
client: NostrClient,
|
||||
): BunkerLoginResult {
|
||||
val connectData =
|
||||
waitForConnectRequest(
|
||||
@@ -117,19 +117,22 @@ object NostrConnectLoginUseCase {
|
||||
ephemeralPubKey: HexKey,
|
||||
relays: Set<NormalizedRelayUrl>,
|
||||
expectedSecret: String,
|
||||
client: INostrClient,
|
||||
client: NostrClient,
|
||||
): ConnectRequestData {
|
||||
val deferred = CompletableDeferred<NostrConnectEvent>()
|
||||
|
||||
val subscription =
|
||||
client.req(
|
||||
relays = relays.toList(),
|
||||
filter =
|
||||
Filter(
|
||||
kinds = listOf(NostrConnectEvent.KIND),
|
||||
tags = mapOf("p" to listOf(ephemeralPubKey)),
|
||||
since = TimeUtils.now() - 60,
|
||||
),
|
||||
StaticSubscription(
|
||||
client,
|
||||
relays.associateWith {
|
||||
listOf(
|
||||
Filter(
|
||||
kinds = listOf(NostrConnectEvent.KIND),
|
||||
tags = mapOf("p" to listOf(ephemeralPubKey)),
|
||||
since = TimeUtils.now() - 60,
|
||||
),
|
||||
)
|
||||
},
|
||||
) { event ->
|
||||
if (event is NostrConnectEvent && !deferred.isCompleted) {
|
||||
deferred.complete(event)
|
||||
@@ -198,7 +201,7 @@ object NostrConnectLoginUseCase {
|
||||
ephemeralSigner: NostrSignerInternal,
|
||||
connectData: ConnectRequestData,
|
||||
relays: Set<NormalizedRelayUrl>,
|
||||
client: INostrClient,
|
||||
client: NostrClient,
|
||||
) {
|
||||
val ackResponse = BunkerResponseAck(id = connectData.requestId!!)
|
||||
val ackEvent =
|
||||
@@ -207,7 +210,7 @@ object NostrConnectLoginUseCase {
|
||||
remoteKey = connectData.signerPubkey,
|
||||
signer = ephemeralSigner,
|
||||
)
|
||||
client.send(ackEvent, relays)
|
||||
client.publish(ackEvent, relays)
|
||||
}
|
||||
|
||||
private fun generateSecret(): String {
|
||||
|
||||
+6
-6
@@ -27,8 +27,8 @@ import com.vitorpamplona.amethyst.commons.relayClient.subscriptions.Subscription
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.metadata.MetadataEvent
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.INostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.reqs.IRequestListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.reqs.SubscriptionListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.single.newSubId
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
||||
@@ -55,7 +55,7 @@ import kotlinx.coroutines.CoroutineScope
|
||||
* ```
|
||||
*/
|
||||
class FeedMetadataCoordinator(
|
||||
private val client: INostrClient,
|
||||
private val client: NostrClient,
|
||||
private val scope: CoroutineScope,
|
||||
private val indexRelays: Set<NormalizedRelayUrl>,
|
||||
private val preloader: MetadataPreloader? = null,
|
||||
@@ -79,10 +79,10 @@ class FeedMetadataCoordinator(
|
||||
// Create listener to pass events to the callback
|
||||
val listener =
|
||||
if (onEvent != null) {
|
||||
object : IRequestListener {
|
||||
object : SubscriptionListener {
|
||||
override fun onEvent(
|
||||
event: Event,
|
||||
isLive: Boolean,
|
||||
isRealTime: Boolean,
|
||||
relay: NormalizedRelayUrl,
|
||||
forFilters: List<Filter>?,
|
||||
) {
|
||||
@@ -93,7 +93,7 @@ class FeedMetadataCoordinator(
|
||||
null
|
||||
}
|
||||
|
||||
client.openReqSubscription(
|
||||
client.subscribe(
|
||||
subId = newSubId(),
|
||||
filters = filterMap,
|
||||
listener = listener,
|
||||
|
||||
+2
-2
@@ -24,7 +24,7 @@ import com.vitorpamplona.amethyst.commons.relayClient.eoseManagers.SingleSubEose
|
||||
import com.vitorpamplona.amethyst.commons.relays.SincePerRelayMap
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.metadata.MetadataEvent
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.INostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.pool.RelayBasedFilter
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
||||
@@ -48,7 +48,7 @@ data class MetadataQueryState(
|
||||
* - Caches EOSE to avoid re-fetching known metadata
|
||||
*/
|
||||
class MetadataFilterAssembler(
|
||||
client: INostrClient,
|
||||
client: NostrClient,
|
||||
allKeys: () -> Set<MetadataQueryState>,
|
||||
) : SingleSubEoseManager<MetadataQueryState>(client, allKeys, invalidateAfterEose = true) {
|
||||
override fun distinct(key: MetadataQueryState): Any = key.pubkeys.hashCode()
|
||||
|
||||
+2
-2
@@ -23,7 +23,7 @@ package com.vitorpamplona.amethyst.commons.relayClient.assemblers
|
||||
import com.vitorpamplona.amethyst.commons.relayClient.eoseManagers.SingleSubEoseManager
|
||||
import com.vitorpamplona.amethyst.commons.relays.SincePerRelayMap
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.INostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.pool.RelayBasedFilter
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
||||
@@ -48,7 +48,7 @@ data class ReactionsQueryState(
|
||||
* - Caches EOSE to avoid re-fetching known reactions
|
||||
*/
|
||||
class ReactionsFilterAssembler(
|
||||
client: INostrClient,
|
||||
client: NostrClient,
|
||||
allKeys: () -> Set<ReactionsQueryState>,
|
||||
) : SingleSubEoseManager<ReactionsQueryState>(client, allKeys, invalidateAfterEose = true) {
|
||||
override fun distinct(key: ReactionsQueryState): Any = key.noteIds.hashCode()
|
||||
|
||||
+4
-4
@@ -21,14 +21,14 @@
|
||||
package com.vitorpamplona.amethyst.commons.relayClient.eoseManagers
|
||||
|
||||
import com.vitorpamplona.amethyst.commons.service.BundledUpdate
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.INostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.reqs.IRequestListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.reqs.SubscriptionListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.single.newSubId
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.subscriptions.SubscriptionController
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
|
||||
abstract class BaseEoseManager<T>(
|
||||
val client: INostrClient,
|
||||
val client: NostrClient,
|
||||
val allKeys: () -> Set<T>,
|
||||
val sampleTime: Long = 500,
|
||||
) : IEoseManager {
|
||||
@@ -38,7 +38,7 @@ abstract class BaseEoseManager<T>(
|
||||
|
||||
fun getSubscription(subId: String) = orchestrator.getSub(subId)
|
||||
|
||||
fun requestNewSubscription(listener: IRequestListener) = orchestrator.requestNewSubscription(newSubId(), listener)
|
||||
fun requestNewSubscription(listener: SubscriptionListener) = orchestrator.requestNewSubscription(newSubId(), listener)
|
||||
|
||||
fun dismissSubscription(subId: String) = orchestrator.dismissSubscription(subId)
|
||||
|
||||
|
||||
+7
-7
@@ -23,10 +23,10 @@ package com.vitorpamplona.amethyst.commons.relayClient.eoseManagers
|
||||
import com.vitorpamplona.amethyst.commons.relays.EOSECache
|
||||
import com.vitorpamplona.amethyst.commons.relays.SincePerRelayMap
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.INostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.pool.RelayBasedFilter
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.pool.groupByRelay
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.reqs.IRequestListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.reqs.SubscriptionListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.subscriptions.Subscription
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
||||
@@ -46,7 +46,7 @@ import com.vitorpamplona.quartz.utils.TimeUtils
|
||||
* shared among multiple query states that map to the same key.
|
||||
*/
|
||||
abstract class PerKeyEoseManager<T, K : Any>(
|
||||
client: INostrClient,
|
||||
client: NostrClient,
|
||||
allKeys: () -> Set<T>,
|
||||
val invalidateAfterEose: Boolean = false,
|
||||
cacheSize: Int = 200,
|
||||
@@ -82,8 +82,8 @@ abstract class PerKeyEoseManager<T, K : Any>(
|
||||
*/
|
||||
open fun newSub(queryState: T): Subscription =
|
||||
requestNewSubscription(
|
||||
object : IRequestListener {
|
||||
override fun onEose(
|
||||
object : SubscriptionListener {
|
||||
override fun onCaughtUp(
|
||||
relay: NormalizedRelayUrl,
|
||||
forFilters: List<Filter>?,
|
||||
) {
|
||||
@@ -92,11 +92,11 @@ abstract class PerKeyEoseManager<T, K : Any>(
|
||||
|
||||
override fun onEvent(
|
||||
event: Event,
|
||||
isLive: Boolean,
|
||||
isRealTime: Boolean,
|
||||
relay: NormalizedRelayUrl,
|
||||
forFilters: List<Filter>?,
|
||||
) {
|
||||
if (isLive) {
|
||||
if (isRealTime) {
|
||||
newEose(queryState, relay, TimeUtils.now(), forFilters)
|
||||
}
|
||||
}
|
||||
|
||||
+7
-7
@@ -23,10 +23,10 @@ package com.vitorpamplona.amethyst.commons.relayClient.eoseManagers
|
||||
import com.vitorpamplona.amethyst.commons.relays.EOSERelayList
|
||||
import com.vitorpamplona.amethyst.commons.relays.SincePerRelayMap
|
||||
import com.vitorpamplona.quartz.nip01Core.core.Event
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.INostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.NostrClient
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.pool.RelayBasedFilter
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.pool.groupByRelay
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.reqs.IRequestListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.client.reqs.SubscriptionListener
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.filters.Filter
|
||||
import com.vitorpamplona.quartz.nip01Core.relay.normalizer.NormalizedRelayUrl
|
||||
import com.vitorpamplona.quartz.utils.TimeUtils
|
||||
@@ -44,7 +44,7 @@ import com.vitorpamplona.quartz.utils.TimeUtils
|
||||
* shares all EOSEs among all users.
|
||||
*/
|
||||
abstract class SingleSubEoseManager<T>(
|
||||
client: INostrClient,
|
||||
client: NostrClient,
|
||||
allKeys: () -> Set<T>,
|
||||
val invalidateAfterEose: Boolean = false,
|
||||
) : BaseEoseManager<T>(client, allKeys) {
|
||||
@@ -66,8 +66,8 @@ abstract class SingleSubEoseManager<T>(
|
||||
|
||||
val sub =
|
||||
requestNewSubscription(
|
||||
object : IRequestListener {
|
||||
override fun onEose(
|
||||
object : SubscriptionListener {
|
||||
override fun onCaughtUp(
|
||||
relay: NormalizedRelayUrl,
|
||||
forFilters: List<Filter>?,
|
||||
) {
|
||||
@@ -76,11 +76,11 @@ abstract class SingleSubEoseManager<T>(
|
||||
|
||||
override fun onEvent(
|
||||
event: Event,
|
||||
isLive: Boolean,
|
||||
isRealTime: Boolean,
|
||||
relay: NormalizedRelayUrl,
|
||||
forFilters: List<Filter>?,
|
||||
) {
|
||||
if (isLive) {
|
||||
if (isRealTime) {
|
||||
newEose(relay, TimeUtils.now(), forFilters)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user