Moves electrum client to the jvmAndroid scope
This commit is contained in:
@@ -68,6 +68,10 @@ import com.vitorpamplona.quartz.nip03Timestamp.VerificationStateCache
|
||||
import com.vitorpamplona.quartz.nip03Timestamp.ots.OtsBlockHeightCache
|
||||
import com.vitorpamplona.quartz.nip05DnsIdentifiers.Nip05Client
|
||||
import com.vitorpamplona.quartz.nip05DnsIdentifiers.OkHttpNip05Fetcher
|
||||
import com.vitorpamplona.quartz.nip05DnsIdentifiers.namecoin.DEFAULT_ELECTRUMX_SERVERS
|
||||
import com.vitorpamplona.quartz.nip05DnsIdentifiers.namecoin.ElectrumXClient
|
||||
import com.vitorpamplona.quartz.nip05DnsIdentifiers.namecoin.NamecoinNameResolver
|
||||
import com.vitorpamplona.quartz.nip05DnsIdentifiers.namecoin.TOR_ELECTRUMX_SERVERS
|
||||
import com.vitorpamplona.quartz.utils.Log
|
||||
import kotlinx.coroutines.CoroutineExceptionHandler
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
@@ -143,23 +147,20 @@ class AppModules(
|
||||
// Custom fetcher that considers tor settings and avoids forwarding.
|
||||
val nip05Fetcher = OkHttpNip05Fetcher(roleBasedHttpClientBuilder::okHttpClientForNip05)
|
||||
val namecoinElectrumxClient =
|
||||
com.vitorpamplona.quartz.nip05.namecoin.ElectrumxClient(
|
||||
ElectrumXClient(
|
||||
socketFactory = { roleBasedHttpClientBuilder.socketFactoryForNip05() },
|
||||
)
|
||||
val namecoinResolver =
|
||||
com.vitorpamplona.quartz.nip05.namecoin.NamecoinNameResolver(
|
||||
NamecoinNameResolver(
|
||||
electrumxClient = namecoinElectrumxClient,
|
||||
serverListProvider = {
|
||||
if (roleBasedHttpClientBuilder.shouldUseTorForNIP05("https://electrumx.example.com")) {
|
||||
com.vitorpamplona.quartz.nip05.namecoin.ElectrumxClient.TOR_SERVERS
|
||||
TOR_ELECTRUMX_SERVERS
|
||||
} else {
|
||||
com.vitorpamplona.quartz.nip05.namecoin.ElectrumxClient.DEFAULT_SERVERS
|
||||
DEFAULT_ELECTRUMX_SERVERS
|
||||
}
|
||||
},
|
||||
)
|
||||
val namecoinNameService =
|
||||
com.vitorpamplona.amethyst.service.namecoin.NamecoinNameService
|
||||
.init(namecoinElectrumxClient)
|
||||
val nip05Client = Nip05Client(nip05Fetcher, namecoinResolver)
|
||||
|
||||
// Application-wide block height request cache
|
||||
|
||||
+6
-22
@@ -20,11 +20,11 @@
|
||||
*/
|
||||
package com.vitorpamplona.amethyst.service.namecoin
|
||||
|
||||
import com.vitorpamplona.quartz.nip05.namecoin.ElectrumxClient
|
||||
import com.vitorpamplona.quartz.nip05.namecoin.ElectrumxServer
|
||||
import com.vitorpamplona.quartz.nip05.namecoin.NamecoinLookupCache
|
||||
import com.vitorpamplona.quartz.nip05.namecoin.NamecoinNameResolver
|
||||
import com.vitorpamplona.quartz.nip05.namecoin.NamecoinNostrResult
|
||||
import com.vitorpamplona.quartz.nip05DnsIdentifiers.namecoin.ElectrumXClient
|
||||
import com.vitorpamplona.quartz.nip05DnsIdentifiers.namecoin.ElectrumxServer
|
||||
import com.vitorpamplona.quartz.nip05DnsIdentifiers.namecoin.NamecoinLookupCache
|
||||
import com.vitorpamplona.quartz.nip05DnsIdentifiers.namecoin.NamecoinNameResolver
|
||||
import com.vitorpamplona.quartz.nip05DnsIdentifiers.namecoin.NamecoinNostrResult
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.SupervisorJob
|
||||
@@ -39,7 +39,7 @@ import kotlinx.coroutines.launch
|
||||
* into Amethyst's existing `ServiceManager` infrastructure.
|
||||
*/
|
||||
class NamecoinNameService(
|
||||
electrumxClient: ElectrumxClient = ElectrumxClient(),
|
||||
electrumxClient: ElectrumXClient,
|
||||
) {
|
||||
private val scope = CoroutineScope(Dispatchers.IO + SupervisorJob())
|
||||
|
||||
@@ -49,22 +49,6 @@ class NamecoinNameService(
|
||||
// Custom server list (user-configurable)
|
||||
private var customServers: List<ElectrumxServer> = emptyList()
|
||||
|
||||
companion object {
|
||||
@Volatile
|
||||
private var instance: NamecoinNameService? = null
|
||||
|
||||
fun getInstance(): NamecoinNameService =
|
||||
instance ?: throw IllegalStateException(
|
||||
"NamecoinNameService not initialized. Call init() first.",
|
||||
)
|
||||
|
||||
fun init(electrumxClient: ElectrumxClient): NamecoinNameService =
|
||||
synchronized(this) {
|
||||
instance?.let { return it }
|
||||
NamecoinNameService(electrumxClient).also { instance = it }
|
||||
}
|
||||
}
|
||||
|
||||
// ── Public API ─────────────────────────────────────────────────────
|
||||
|
||||
/**
|
||||
|
||||
+3
-3
@@ -29,14 +29,14 @@ import androidx.compose.ui.focus.FocusRequester
|
||||
import androidx.lifecycle.ViewModel
|
||||
import androidx.lifecycle.ViewModelProvider
|
||||
import androidx.lifecycle.viewModelScope
|
||||
import com.vitorpamplona.amethyst.Amethyst
|
||||
import com.vitorpamplona.amethyst.commons.ui.feeds.InvalidatableContent
|
||||
import com.vitorpamplona.amethyst.model.Account
|
||||
import com.vitorpamplona.amethyst.model.LocalCache
|
||||
import com.vitorpamplona.amethyst.model.User
|
||||
import com.vitorpamplona.amethyst.service.namecoin.NamecoinNameService
|
||||
import com.vitorpamplona.amethyst.service.relayClient.searchCommand.SearchQueryState
|
||||
import com.vitorpamplona.amethyst.ui.dal.DefaultFeedOrder
|
||||
import com.vitorpamplona.quartz.nip05.namecoin.NamecoinNameResolver
|
||||
import com.vitorpamplona.quartz.nip05DnsIdentifiers.namecoin.NamecoinNameResolver
|
||||
import com.vitorpamplona.quartz.nip10Notes.content.findHashtags
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.FlowPreview
|
||||
@@ -85,7 +85,7 @@ class SearchBarViewModel(
|
||||
.filter { NamecoinNameResolver.isNamecoinIdentifier(it) }
|
||||
.map { term ->
|
||||
try {
|
||||
val result = NamecoinNameService.getInstance().resolve(term)
|
||||
val result = Amethyst.instance.namecoinResolver.resolve(term)
|
||||
if (result != null) {
|
||||
LocalCache.getOrCreateUser(result.pubkey)
|
||||
} else {
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@
|
||||
package com.vitorpamplona.quartz.nip05DnsIdentifiers
|
||||
|
||||
import com.vitorpamplona.quartz.nip01Core.core.HexKey
|
||||
import com.vitorpamplona.quartz.nip05.namecoin.NamecoinNameResolver
|
||||
import com.vitorpamplona.quartz.nip05DnsIdentifiers.namecoin.NamecoinNameResolver
|
||||
import kotlinx.coroutines.CancellationException
|
||||
|
||||
data class Nip05KeyInfo(
|
||||
|
||||
+70
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip05DnsIdentifiers.namecoin
|
||||
|
||||
import kotlinx.serialization.Serializable
|
||||
|
||||
/**
|
||||
* Result of an ElectrumX name_show query.
|
||||
*
|
||||
* Maps to the JSON fields returned by Namecoin Core / Electrum-NMC:
|
||||
* { "name": "d/example", "value": "{...}", "txid": "abc...", "height": 12345, ... }
|
||||
*/
|
||||
@Serializable
|
||||
data class NameShowResult(
|
||||
val name: String,
|
||||
val value: String,
|
||||
val txid: String? = null,
|
||||
val height: Int? = null,
|
||||
val expiresIn: Int? = null,
|
||||
)
|
||||
|
||||
/**
|
||||
* Represents a single ElectrumX server endpoint.
|
||||
*/
|
||||
data class ElectrumxServer(
|
||||
val host: String,
|
||||
val port: Int,
|
||||
val useSsl: Boolean = true,
|
||||
/** If true, accept any certificate (self-signed, expired, etc.) */
|
||||
val trustAllCerts: Boolean = false,
|
||||
)
|
||||
|
||||
/** Well-known public Namecoin ElectrumX servers (clearnet). */
|
||||
val DEFAULT_ELECTRUMX_SERVERS =
|
||||
listOf(
|
||||
ElectrumxServer("electrumx.testls.space", 50002, useSsl = true, trustAllCerts = true),
|
||||
ElectrumxServer("nmc2.bitcoins.sk", 57002, useSsl = true, trustAllCerts = true),
|
||||
ElectrumxServer("46.229.238.187", 57002, useSsl = true, trustAllCerts = true),
|
||||
)
|
||||
|
||||
/** Tor-preferred server list: onion primary, clearnet fallback. */
|
||||
val TOR_ELECTRUMX_SERVERS =
|
||||
listOf(
|
||||
ElectrumxServer(
|
||||
"i665jpwsq46zlsdbnj4axgzd3s56uzey5uhotsnxzsknzbn36jaddsid.onion",
|
||||
50002,
|
||||
useSsl = true,
|
||||
trustAllCerts = true,
|
||||
),
|
||||
ElectrumxServer("electrumx.testls.space", 50002, useSsl = true, trustAllCerts = true),
|
||||
ElectrumxServer("nmc2.bitcoins.sk", 57002, useSsl = true, trustAllCerts = true),
|
||||
)
|
||||
+28
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) 2025 Vitor Pamplona
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
* this software and associated documentation files (the "Software"), to deal in
|
||||
* the Software without restriction, including without limitation the rights to use,
|
||||
* copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the
|
||||
* Software, and to permit persons to whom the Software is furnished to do so,
|
||||
* subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all
|
||||
* copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip05DnsIdentifiers.namecoin
|
||||
|
||||
interface IElectrumXClient {
|
||||
suspend fun nameShowWithFallback(
|
||||
identifier: String,
|
||||
servers: List<ElectrumxServer>,
|
||||
): NameShowResult?
|
||||
}
|
||||
+1
-1
@@ -18,7 +18,7 @@
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip05.namecoin
|
||||
package com.vitorpamplona.quartz.nip05DnsIdentifiers.namecoin
|
||||
|
||||
import androidx.collection.LruCache
|
||||
import com.vitorpamplona.quartz.utils.TimeUtils
|
||||
+3
-3
@@ -18,7 +18,7 @@
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip05.namecoin
|
||||
package com.vitorpamplona.quartz.nip05DnsIdentifiers.namecoin
|
||||
|
||||
import kotlinx.coroutines.withTimeoutOrNull
|
||||
import kotlinx.serialization.json.Json
|
||||
@@ -50,9 +50,9 @@ data class NamecoinNostrResult(
|
||||
* here instead of to the HTTP-based NIP-05 path.
|
||||
*/
|
||||
class NamecoinNameResolver(
|
||||
private val electrumxClient: ElectrumxClient = ElectrumxClient(),
|
||||
private val electrumxClient: IElectrumXClient,
|
||||
private val lookupTimeoutMs: Long = 20_000L,
|
||||
private val serverListProvider: () -> List<ElectrumxServer> = { ElectrumxClient.DEFAULT_SERVERS },
|
||||
private val serverListProvider: () -> List<ElectrumxServer> = { DEFAULT_ELECTRUMX_SERVERS },
|
||||
) {
|
||||
private val json =
|
||||
Json {
|
||||
+19
-63
@@ -18,15 +18,16 @@
|
||||
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip05.namecoin
|
||||
package com.vitorpamplona.quartz.nip05DnsIdentifiers.namecoin
|
||||
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.sync.Mutex
|
||||
import kotlinx.coroutines.sync.withLock
|
||||
import kotlinx.coroutines.withContext
|
||||
import kotlinx.serialization.Serializable
|
||||
import kotlinx.serialization.builtins.ListSerializer
|
||||
import kotlinx.serialization.json.Json
|
||||
import kotlinx.serialization.json.JsonElement
|
||||
import kotlinx.serialization.json.JsonNull
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
import kotlinx.serialization.json.JsonPrimitive
|
||||
import kotlinx.serialization.json.buildJsonObject
|
||||
@@ -41,6 +42,8 @@ import java.io.PrintWriter
|
||||
import java.net.InetSocketAddress
|
||||
import java.net.Socket
|
||||
import java.security.MessageDigest
|
||||
import java.security.SecureRandom
|
||||
import java.security.cert.X509Certificate
|
||||
import java.util.concurrent.atomic.AtomicInteger
|
||||
import javax.net.SocketFactory
|
||||
import javax.net.ssl.SSLContext
|
||||
@@ -48,32 +51,6 @@ import javax.net.ssl.SSLSocketFactory
|
||||
import javax.net.ssl.TrustManager
|
||||
import javax.net.ssl.X509TrustManager
|
||||
|
||||
/**
|
||||
* Result of an ElectrumX name_show query.
|
||||
*
|
||||
* Maps to the JSON fields returned by Namecoin Core / Electrum-NMC:
|
||||
* { "name": "d/example", "value": "{...}", "txid": "abc...", "height": 12345, ... }
|
||||
*/
|
||||
@Serializable
|
||||
data class NameShowResult(
|
||||
val name: String,
|
||||
val value: String,
|
||||
val txid: String? = null,
|
||||
val height: Int? = null,
|
||||
val expiresIn: Int? = null,
|
||||
)
|
||||
|
||||
/**
|
||||
* Represents a single ElectrumX server endpoint.
|
||||
*/
|
||||
data class ElectrumxServer(
|
||||
val host: String,
|
||||
val port: Int,
|
||||
val useSsl: Boolean = true,
|
||||
/** If true, accept any certificate (self-signed, expired, etc.) */
|
||||
val trustAllCerts: Boolean = false,
|
||||
)
|
||||
|
||||
/**
|
||||
* Lightweight, query-only ElectrumX client for Namecoin name resolution.
|
||||
*
|
||||
@@ -95,11 +72,11 @@ data class ElectrumxServer(
|
||||
* val result = client.nameShow("d/example", server)
|
||||
* ```
|
||||
*/
|
||||
class ElectrumxClient(
|
||||
class ElectrumXClient(
|
||||
private val connectTimeoutMs: Long = 10_000L,
|
||||
private val readTimeoutMs: Long = 15_000L,
|
||||
private val socketFactory: () -> SocketFactory = { SocketFactory.getDefault() },
|
||||
) {
|
||||
) : IElectrumXClient {
|
||||
private val json =
|
||||
Json {
|
||||
ignoreUnknownKeys = true
|
||||
@@ -109,27 +86,6 @@ class ElectrumxClient(
|
||||
private val mutex = Mutex()
|
||||
|
||||
companion object {
|
||||
/** Well-known public Namecoin ElectrumX servers (clearnet). */
|
||||
val DEFAULT_SERVERS =
|
||||
listOf(
|
||||
ElectrumxServer("electrumx.testls.space", 50002, useSsl = true, trustAllCerts = true),
|
||||
ElectrumxServer("nmc2.bitcoins.sk", 57002, useSsl = true, trustAllCerts = true),
|
||||
ElectrumxServer("46.229.238.187", 57002, useSsl = true, trustAllCerts = true),
|
||||
)
|
||||
|
||||
/** Tor-preferred server list: onion primary, clearnet fallback. */
|
||||
val TOR_SERVERS =
|
||||
listOf(
|
||||
ElectrumxServer(
|
||||
"i665jpwsq46zlsdbnj4axgzd3s56uzey5uhotsnxzsknzbn36jaddsid.onion",
|
||||
50002,
|
||||
useSsl = true,
|
||||
trustAllCerts = true,
|
||||
),
|
||||
ElectrumxServer("electrumx.testls.space", 50002, useSsl = true, trustAllCerts = true),
|
||||
ElectrumxServer("nmc2.bitcoins.sk", 57002, useSsl = true, trustAllCerts = true),
|
||||
)
|
||||
|
||||
private const val PROTOCOL_VERSION = "1.4"
|
||||
|
||||
/**
|
||||
@@ -162,7 +118,7 @@ class ElectrumxClient(
|
||||
*/
|
||||
suspend fun nameShow(
|
||||
identifier: String,
|
||||
server: ElectrumxServer = DEFAULT_SERVERS.first(),
|
||||
server: ElectrumxServer = DEFAULT_ELECTRUMX_SERVERS.first(),
|
||||
): NameShowResult? =
|
||||
withContext(Dispatchers.IO) {
|
||||
mutex.withLock {
|
||||
@@ -180,11 +136,11 @@ class ElectrumxClient(
|
||||
* Try each server in order until one succeeds.
|
||||
*
|
||||
* @param identifier Full Namecoin name, e.g. "d/example"
|
||||
* @param servers Ordered server list to try; defaults to [DEFAULT_SERVERS]
|
||||
* @param servers Ordered server list to try; defaults to [DEFAULT_ELECTRUMX_SERVERS]
|
||||
*/
|
||||
suspend fun nameShowWithFallback(
|
||||
override suspend fun nameShowWithFallback(
|
||||
identifier: String,
|
||||
servers: List<ElectrumxServer> = DEFAULT_SERVERS,
|
||||
servers: List<ElectrumxServer>,
|
||||
): NameShowResult? {
|
||||
for (server in servers) {
|
||||
val result = nameShow(identifier, server)
|
||||
@@ -329,7 +285,7 @@ class ElectrumxClient(
|
||||
private fun parseHistoryResponse(raw: String): List<Pair<String, Int>>? {
|
||||
val envelope = json.parseToJsonElement(raw).jsonObject
|
||||
val error = envelope["error"]
|
||||
if (error != null && error !is kotlinx.serialization.json.JsonNull) return null
|
||||
if (error != null && error !is JsonNull) return null
|
||||
|
||||
val result = envelope["result"]?.jsonArray ?: return null
|
||||
return result.mapNotNull { entry ->
|
||||
@@ -354,7 +310,7 @@ class ElectrumxClient(
|
||||
): NameShowResult? {
|
||||
val envelope = json.parseToJsonElement(raw).jsonObject
|
||||
val error = envelope["error"]
|
||||
if (error != null && error !is kotlinx.serialization.json.JsonNull) return null
|
||||
if (error != null && error !is JsonNull) return null
|
||||
|
||||
val result = envelope["result"]?.jsonObject ?: return null
|
||||
val vouts = result["vout"]?.jsonArray ?: return null
|
||||
@@ -505,20 +461,20 @@ class ElectrumxClient(
|
||||
arrayOf<TrustManager>(
|
||||
object : X509TrustManager {
|
||||
override fun checkClientTrusted(
|
||||
chain: Array<java.security.cert.X509Certificate>,
|
||||
chain: Array<X509Certificate>,
|
||||
authType: String,
|
||||
) {}
|
||||
|
||||
override fun checkServerTrusted(
|
||||
chain: Array<java.security.cert.X509Certificate>,
|
||||
chain: Array<X509Certificate>,
|
||||
authType: String,
|
||||
) {}
|
||||
|
||||
override fun getAcceptedIssuers(): Array<java.security.cert.X509Certificate> = arrayOf()
|
||||
override fun getAcceptedIssuers(): Array<X509Certificate> = arrayOf()
|
||||
},
|
||||
)
|
||||
val sslContext = SSLContext.getInstance("TLS")
|
||||
sslContext.init(null, trustAllCerts, java.security.SecureRandom())
|
||||
sslContext.init(null, trustAllCerts, SecureRandom())
|
||||
return sslContext.socketFactory
|
||||
}
|
||||
|
||||
@@ -535,8 +491,8 @@ class ElectrumxClient(
|
||||
put(
|
||||
"params",
|
||||
json.encodeToJsonElement(
|
||||
kotlinx.serialization.builtins.ListSerializer(
|
||||
kotlinx.serialization.json.JsonElement
|
||||
ListSerializer(
|
||||
JsonElement
|
||||
.serializer(),
|
||||
),
|
||||
params.map {
|
||||
+7
-1
@@ -20,6 +20,8 @@
|
||||
*/
|
||||
package com.vitorpamplona.quartz.nip05.namecoin
|
||||
|
||||
import com.vitorpamplona.quartz.nip05DnsIdentifiers.namecoin.NamecoinNameResolver
|
||||
import com.vitorpamplona.quartz.nip05DnsIdentifiers.namecoin.NamecoinNostrResult
|
||||
import org.junit.Assert.assertEquals
|
||||
import org.junit.Assert.assertFalse
|
||||
import org.junit.Assert.assertNotNull
|
||||
@@ -267,7 +269,11 @@ class NamecoinNameResolverTest {
|
||||
} catch (_: Exception) {
|
||||
emptyList()
|
||||
}
|
||||
return NamecoinNostrResult(pubkey = pubkey.lowercase(), relays = relays, namecoinName = namecoinName)
|
||||
return NamecoinNostrResult(
|
||||
pubkey = pubkey.lowercase(),
|
||||
relays = relays,
|
||||
namecoinName = namecoinName,
|
||||
)
|
||||
}
|
||||
}
|
||||
return null
|
||||
|
||||
Reference in New Issue
Block a user