<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <updated>2026-05-19T14:16:50Z</updated>
  <generator>https://njump.me</generator>

  <title>Nostr notes by mstrofnone</title>
  <author>
    <name>mstrofnone</name>
  </author>
  <link rel="self" type="application/atom+xml" href="https://njump.me/npub1gvv9ahktvavf9qjtrgm62le7gplmmchd5usp5wpfhr85hf79kncqj8xchs.rss" />
  <link href="https://njump.me/npub1gvv9ahktvavf9qjtrgm62le7gplmmchd5usp5wpfhr85hf79kncqj8xchs" />
  <id>https://njump.me/npub1gvv9ahktvavf9qjtrgm62le7gplmmchd5usp5wpfhr85hf79kncqj8xchs</id>
  <icon>https://robohash.org/nmc-exchange?set=set4&amp;size=256x256</icon>
  <logo>https://robohash.org/nmc-exchange?set=set4&amp;size=256x256</logo>




  <entry>
    <id>https://njump.me/nevent1qqsqj8hnyzyz5svyhg4kgnex0axynrthsdje96ncapn20nwetl6lafgzypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60qewhgpc</id>
    
      <title type="html">Thanks for the detailed review — this is genuinely useful ...</title>
    
    <link rel="alternate" href="https://njump.me/nevent1qqsqj8hnyzyz5svyhg4kgnex0axynrthsdje96ncapn20nwetl6lafgzypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60qewhgpc" />
    <content type="html">
      In reply to &lt;a href=&#39;/naddr1qqyxzmt9w358jum5qy28wumn8ghj7un9d3shjtnwva5hgtnyv4mqygzxpsj7dqha57pjk5k37gkn6g4nzakewtmqmnwryyhd3jfwlpgxtspsgqqqw7vsl7qevy&#39;&gt;naddr1qq…qevy&lt;/a&gt;&lt;br/&gt;_________________________&lt;br/&gt;&lt;br/&gt;Thanks for the detailed review — this is genuinely useful feedback.&lt;br/&gt;&lt;br/&gt;Pushed a revision (commit `9fbba11`) that addresses everything in the &amp;#34;smaller things&amp;#34; list and takes the **honest labelling** path from the two options you offered. The core transport concern I&amp;#39;ve deliberately left for a separate PR — details below.&lt;br/&gt;&lt;br/&gt;## What&amp;#39;s fixed&lt;br/&gt;&lt;br/&gt;**Rebased on `main` &#43; moved the row into `NoteActionSections.kt`.** The menu inventory moved to the shared inventory that both `NoteDropDownMenu` and `ChatMessageActionSheet` render from; the row is now a new section wired via `NoteActionHandlers.onReplyAnonymously: (() -&amp;gt; Unit)?`. The chat sheet passes `null` (structurally impossible surface anyway), so the row never appears on chat long-press. The two surfaces stay in lockstep.&lt;br/&gt;&lt;br/&gt;**Explainer dialog on first tap.** Mirrors `zap_type_anonymous_explainer`: a `QuickActionAlertDialog` that names the current limits by name — IP, relay logs, shared authenticated connection — with a per-account &amp;#34;Don&amp;#39;t show again&amp;#34; persisted to `AccountSettings.hideAnonymousReplyExplainer` (same pattern as `hideBlockAlertDialog`). The body reads:&lt;br/&gt;&lt;br/&gt;&amp;gt; **Anonymous only at the signature layer**&lt;br/&gt;&amp;gt;&lt;br/&gt;&amp;gt; The reply is signed with a throwaway key, but it is sent over the same relay connections your account already uses. A relay operator can see your IP, and — because this connection also authenticates as you — can link the anonymous event to your real npub. Use Tor for real anonymity.&lt;br/&gt;&lt;br/&gt;A user tapping the row after seeing that has been told what they&amp;#39;re actually getting.&lt;br/&gt;&lt;br/&gt;**Fixed the state mutation during composition.** You were right — `remember(note) { routeAnonymousReplyTo(note, account) }` for DM notes reached into `routeToMessage()` → `getOrCreatePrivateChatroom()` and mutated state during composition. Split into two functions:&lt;br/&gt;&lt;br/&gt;- `supportsAnonymousReply(note: Note): Boolean` — side-effect-free predicate over `note.event`&amp;#39;s type &#43; gatherers. This is what the menu calls during composition.&lt;br/&gt;- `routeAnonymousReplyTo(note, account): Route?` — gates on `supportsAnonymousReply` first, so it&amp;#39;s only invoked from the click handler after the user has actually opted in.&lt;br/&gt;&lt;br/&gt;The predicate has a &amp;#34;keep in sync with `routeReplyTo`&amp;#34; doc note.&lt;br/&gt;&lt;br/&gt;**Fixed the config-change re-enable.** Every composer that took `startAnonymous` (`ShortNotePostScreen`, `ReplyCommentPostScreen`, `GeoHashPostScreen`, `HashtagPostScreen`) now guards on a `rememberSaveable { mutableStateOf(false) }` &amp;#34;consumed&amp;#34; flag — applied once when the `LaunchedEffect` first fires with `startAnonymous = true`, then remembered across recompositions and config changes. Rotation / dark-mode toggle can no longer override an explicit &amp;#34;toggle off&amp;#34;.&lt;br/&gt;&lt;br/&gt;**Dropped `UrlPost.startAnonymous`.** Removed from `Route.UrlPost`, `UrlPostScreen`, and its `AppNavigation` wiring. `routeReplyTo` never produces `UrlPost`, so it was dead.&lt;br/&gt;&lt;br/&gt;**Added tests.** `AnonymousReplyRouteTest.kt` — 9 unit tests over `supportsAnonymousReply`:&lt;br/&gt;&lt;br/&gt;- `TextNoteEvent` supported (→ `Route.NewShortNote`)&lt;br/&gt;- `CommentEvent` supported (→ `Route.GenericCommentPost` / `HashtagPost` / `GeoPost`)&lt;br/&gt;- `PrivateDmEvent` (NIP-04 DM) not supported&lt;br/&gt;- `ChannelMessageEvent` (NIP-28) not supported&lt;br/&gt;- `LiveActivitiesChatMessageEvent` (NIP-53) not supported&lt;br/&gt;- `EphemeralChatEvent` not supported&lt;br/&gt;- `PublicMessageEvent` (NIP-C7) not supported&lt;br/&gt;- `LongTextNoteEvent` not supported (fallthrough to `GenericCommentPost` treated as unsupported — the predicate only claims anonymous where a concrete kind maps to a supporting composer)&lt;br/&gt;- Bare `Note` with `event == null` not supported (defensive: composer kind is unknown, could be a DM)&lt;br/&gt;&lt;br/&gt;All 9 pass. `spotlessCheck` clean; `:amethyst:compilePlayDebugKotlin` green.&lt;br/&gt;&lt;br/&gt;## What&amp;#39;s deliberately not in this PR&lt;br/&gt;&lt;br/&gt;The transport-level correlation between anon events and the account&amp;#39;s authenticated relay connections — your points (1)–(4). Agreed on every one:&lt;br/&gt;&lt;br/&gt;1. One `NostrClient` socket per relay URL, `signAnonymouslyAndBroadcast` swapping only the signer.&lt;br/&gt;2. `PoolEventOutboxState` retrying anon publishes over an AUTH round-trip the real account just made — the signed-timestamped correlation you flagged.&lt;br/&gt;3. `broadcastRelayList` sourcing from `trustedRelays`, own-reply outbox recursion.&lt;br/&gt;4. No Tor guarantee.&lt;br/&gt;&lt;br/&gt;That&amp;#39;s behaviour of the existing anonymous flow that this PR doesn&amp;#39;t create or worsen. The proper &amp;#34;honest implementation&amp;#34; fix (dedicated non-AUTH connection, ideally Tor-forced, plus skipping the post-publish `authors=[anon_pubkey]` metadata REQ) touches `Account.signAnonymouslyAndBroadcast`, `NostrClient`&amp;#39;s per-URL socket cache, `AuthCoordinator`, and the outbox retry machinery. It&amp;#39;s cross-cutting enough that I&amp;#39;d rather sequence it as its own PR against `main` — my read is the explainer is the right thing to land now, and the transport fix is a separate reviewable change that the explainer text will just melt away for once it lands. If you&amp;#39;d rather block this on the transport fix instead, I&amp;#39;m happy to sequence it that way — just say the word.&lt;br/&gt;&lt;br/&gt;The &amp;#34;probable follow-up leak&amp;#34; (metadata REQ) I haven&amp;#39;t touched here either — worth confirming with a capture as you say, but if it reproduces I&amp;#39;d fix it in the same transport PR (skip metadata resolution for keys we know are ours-anonymous).&lt;br/&gt;&lt;br/&gt;Diff summary is in the commit body. Ready for another look when you have time.
    </content>
    <updated>2026-07-20T22:06:51Z</updated>
  </entry>

  <entry>
    <id>https://njump.me/nevent1qqsqqqqy2ad9tdjjjgh4uk2fvmu9ejrguc6u467tsgarvuh6qf9jx9gzypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60qetp7q7</id>
    
      <title type="html">@npub1gcx…nj5z @npub15qy…yejr — a modest proposal about ...</title>
    
    <link rel="alternate" href="https://njump.me/nevent1qqsqqqqy2ad9tdjjjgh4uk2fvmu9ejrguc6u467tsgarvuh6qf9jx9gzypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60qetp7q7" />
    <content type="html">
      In reply to &lt;a href=&#39;/naddr1qqyxzmt9w358jum5qy28wumn8ghj7un9d3shjtnwva5hgtnyv4mqygzxpsj7dqha57pjk5k37gkn6g4nzakewtmqmnwryyhd3jfwlpgxtspsgqqqw7vsl7qevy&#39;&gt;naddr1qq…qevy&lt;/a&gt;&lt;br/&gt;_________________________&lt;br/&gt;&lt;br/&gt;&lt;span itemprop=&#34;mentions&#34; itemscope itemtype=&#34;https://schema.org/Person&#34;&gt;&lt;a itemprop=&#34;url&#34; href=&#34;/npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z&#34; class=&#34;bg-lavender dark:prose:text-neutral-50 dark:text-neutral-50 dark:bg-garnet px-1&#34;&gt;&lt;span&gt;VitorPamplona&lt;/span&gt; (&lt;span class=&#34;italic&#34;&gt;npub1gcx…nj5z&lt;/span&gt;)&lt;/a&gt;&lt;/span&gt; &lt;span itemprop=&#34;mentions&#34; itemscope itemtype=&#34;https://schema.org/Person&#34;&gt;&lt;a itemprop=&#34;url&#34; href=&#34;/npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr&#34; class=&#34;bg-lavender dark:prose:text-neutral-50 dark:text-neutral-50 dark:bg-garnet px-1&#34;&gt;&lt;span&gt;DanConwayDev&lt;/span&gt; (&lt;span class=&#34;italic&#34;&gt;npub15qy…yejr&lt;/span&gt;)&lt;/a&gt;&lt;/span&gt; — a modest proposal about automated PR reviewers on Nostr.&lt;br/&gt;&lt;br/&gt;Two fresh examples from Drydock (npub1zq3x5v…) on my AuxPoW-walker PR against Vitor&amp;#39;s amethyst:&lt;br/&gt;&lt;blockquote class=&#34;border-l-05rem border-l-strongpink border-solid&#34;&gt;&lt;div class=&#34;-ml-4 bg-gradient-to-r from-gray-100 dark:from-zinc-800 to-transparent mr-0 mt-0 mb-4 pl-4 pr-2 py-2&#34;&gt;quoting &lt;br/&gt;&lt;span itemprop=&#34;mentions&#34; itemscope itemtype=&#34;https://schema.org/Article&#34;&gt;&lt;a itemprop=&#34;url&#34; href=&#34;/nevent1qvzqqqqy2upzqypzdgc3k333lvnlsrqgpf5z4dj7kn442tszl5qu88kx9r3gc9xjqy88wumn8ghj7mn0wvhxcmmv9uqzq46rqr58ve6ghqwx8le7txvyydhjj9qelw8pumpzqpfrn5t40y0exvcrcf&#34; class=&#34;bg-lavender dark:prose:text-neutral-50 dark:text-neutral-50 dark:bg-garnet px-1&#34;&gt;nevent1q…crcf&lt;/a&gt;&lt;/span&gt;&lt;br/&gt; &lt;/div&gt; Automated review summary&lt;br/&gt;The patch introduces a robust AuxPoW verification mechanism for Namecoin SPV, including a manual Bitcoin transaction parser and merkle branch walking. However, there is a critical compilation error due to a missing method in CompactDifficulty, and a potential logic error in the CompactDifficulty.decodeTargetBE implementation regarding the mantissa placement which could lead to incorrect PoW targets.&lt;br/&gt;&lt;br/&gt;Findings&lt;br/&gt;critical | correctness | quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip05DnsIdentifiers/namecoin/AuxPow.kt:188 | The method hashMeetsTargetLE is called in AuxPow.verify but is not defined in the provided CompactDifficulty.kt. This will cause a compilation error.&lt;br/&gt;medium | correctness | quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip05DnsIdentifiers/namecoin/CompactDifficulty.kt:53 | The logic for placing the 3-byte mantissa in the 32-byte buffer is slightly flawed. If exponent is 3, topIndex is 29. The code sets out[29], out[30], and out[31]. This is correct for a 3-byte mantissa. However, the if (topIndex in 0..29) block is used to assign out[topIndex], out[topIndex&#43;1], and out[topIndex&#43;2]. If topIndex is 29, it writes to 29, 30, 31. This is fine. But if exponent is 32, topIndex is 0, it writes to 0, 1, 2. This is also fine. The issue is that the target is mantissa * 256^(exponent - 3). If exponent is 3, target is mantissa * 1. The mantissa is 3 bytes. The 3 bytes should be at the very end of the 32-byte array (indices 29, 30, 31). The current code does this. However, the logic for topIndex == 30 and topIndex == 31 is redundant or potentially incorrect if the mantissa is always 3 bytes. In Bitcoin, the mantissa is 3 bytes, and the exponent is the number of bytes in the mantissa plus the exponent value. Actually, the standard is: target = mantissa * 256^(exponent - 3). If exponent is 3, target = mantissa. The mantissa is 3 bytes. So the 3 bytes should be at the end. The code handles this. But the if (topIndex in 0..29) check is a bit brittle.&lt;br/&gt;low | correctness | quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip05DnsIdentifiers/namecoin/AuxPow.kt:138 | The skipBitcoinTx function returns Int?. If it returns null (due to malformed transaction or truncation), the verify function returns Result.Malformed. This is handled correctly, but the pos is not updated in the error case, which is fine as the block is rejected.&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;---&lt;br/&gt;model: google_gemma-4-26B-A4B-it-Q4_K_M.gguf&lt;br/&gt;context-hash: 7de1b365a6695a54e1080d4b56d381c68e8daf62f623c8cc1f1b8e8bf52e7b23&lt;br/&gt;patch-event-id: a3b53db06b1d86ac36ee728381539ef0544b6b61b5473b53dc4e99759893194b&lt;br/&gt;repo-id: 460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c:amethyst&lt;br/&gt;review-mode: automated&lt;br/&gt;confidence: 0.92&lt;br/&gt;context-layers-used: patch, modified-files, symbols, tests, imports-exports, commit-history, project-docs&lt;br/&gt;context-layers-dropped: &lt;br/&gt;excluded-files: &lt;br/&gt; &lt;/blockquote&gt;&lt;blockquote class=&#34;border-l-05rem border-l-strongpink border-solid&#34;&gt;&lt;div class=&#34;-ml-4 bg-gradient-to-r from-gray-100 dark:from-zinc-800 to-transparent mr-0 mt-0 mb-4 pl-4 pr-2 py-2&#34;&gt;quoting &lt;br/&gt;&lt;span itemprop=&#34;mentions&#34; itemscope itemtype=&#34;https://schema.org/Article&#34;&gt;&lt;a itemprop=&#34;url&#34; href=&#34;/nevent1qvzqqqqy2upzqypzdgc3k333lvnlsrqgpf5z4dj7kn442tszl5qu88kx9r3gc9xjqy88wumn8ghj7mn0wvhxcmmv9uqzq2rvael65tge748ksgya04jxug0yc3ftpxkvz6vxp2y4l09ezevnsf0y9f&#34; class=&#34;bg-lavender dark:prose:text-neutral-50 dark:text-neutral-50 dark:bg-garnet px-1&#34;&gt;nevent1q…0y9f&lt;/a&gt;&lt;/span&gt;&lt;br/&gt; &lt;/div&gt; Automated review finding&lt;br/&gt;Severity: critical&lt;br/&gt;Category: correctness&lt;br/&gt;Location: quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip05DnsIdentifiers/namecoin/AuxPow.kt:188&lt;br/&gt;Evidence: if (!CompactDifficulty.hashMeetsTargetLE(parentHashLE, childBits))&lt;br/&gt;Explanation: The method hashMeetsTargetLE is called in AuxPow.verify but is not defined in the provided CompactDifficulty.kt. This will cause a compilation error.&lt;br/&gt;Suggestion: Implement hashMeetsTargetLE in CompactDifficulty.kt using decodeTargetBE and compareBE32.&lt;br/&gt;&lt;br/&gt;---&lt;br/&gt;model: google_gemma-4-26B-A4B-it-Q4_K_M.gguf&lt;br/&gt;context-hash: 7de1b365a6695a54e1080d4b56d381c68e8daf62f623c8cc1f1b8e8bf52e7b23&lt;br/&gt;patch-event-id: a3b53db06b1d86ac36ee728381539ef0544b6b61b5473b53dc4e99759893194b&lt;br/&gt;repo-id: 460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c:amethyst&lt;br/&gt;review-mode: automated&lt;br/&gt;confidence: 0.92&lt;br/&gt;context-layers-used: patch, modified-files, symbols, tests, imports-exports, commit-history, project-docs&lt;br/&gt;context-layers-dropped: &lt;br/&gt;excluded-files: &lt;br/&gt; &lt;/blockquote&gt;&lt;br/&gt;Both pin the same &amp;#34;Severity: critical | correctness&amp;#34; finding:&lt;br/&gt;&lt;br/&gt;  &amp;gt; The method hashMeetsTargetLE is called in AuxPow.verify but is not&lt;br/&gt;  &amp;gt; defined in the provided CompactDifficulty.kt. This will cause a&lt;br/&gt;  &amp;gt; compilation error.&lt;br/&gt;&lt;br/&gt;Reality check on the actual PR (patch a3b53db0…):&lt;br/&gt;&lt;br/&gt;  $ grep -n hashMeetsTargetLE quartz/…/namecoin/*.kt&lt;br/&gt;  AuxPow.kt:246:  if (!CompactDifficulty.hashMeetsTargetLE(parentHashLE, childBits))&lt;br/&gt;  CompactDifficulty.kt:105:  fun hashMeetsTargetLE(&lt;br/&gt;&lt;br/&gt;Called at line 246, defined at line 105 of the sibling file in the same commit. The code compiles and the full :quartz:jvmTest suite is green.&lt;br/&gt;&lt;br/&gt;This is the third &amp;#34;critical&amp;#34; from this bot on my PRs that evaporates on inspection. Earlier examples (KEYCHAIN_PWD=$(openssl rand -base64 24) flagged as hardcoded secret; a test fixture &amp;#34;salt$hash&amp;#34; flagged as a real password; five &amp;#34;commit doesn&amp;#39;t exist&amp;#34; claims about commits that resolve fine on the ngit remote) are documented at:&lt;br/&gt;&lt;br/&gt;&lt;a href=&#34;https://gitworkshop.dev/mstrofnone.bit/relay.ngit.dev/amethyst/prs/nevent1qqsrsgu95lmp6ap3tp3mmqxwtx3v3tw3tgvyvvegvck54ha7dp37qwsgpp4mhxue69uhkummn9ekx7mqpz3mhxue69uhhyetvv9ujumn8d96zuer9wcyvzw8m&#34;&gt;https://gitworkshop.dev/mstrofnone.bit/relay.ngit.dev/amethyst/prs/nevent1qqsrsgu95lmp6ap3tp3mmqxwtx3v3tw3tgvyvvegvck54ha7dp37qwsgpp4mhxue69uhkummn9ekx7mqpz3mhxue69uhhyetvv9ujumn8d96zuer9wcyvzw8m&lt;/a&gt;&lt;br/&gt;&lt;br/&gt;The pattern is always the same: a plausible-sounding &amp;#34;critical&amp;#34; pinned to a real file at a real line, generated by an LLM that isn&amp;#39;t actually looking at the file it&amp;#39;s flagging. False-positive criticals are the worst failure mode an automated reviewer has — they burn maintainer attention and drown out any real findings the same bot happens to get right.&lt;br/&gt;&lt;br/&gt;Proposal: for any review event carrying &amp;#34;Severity: critical&amp;#34; (or any severity, honestly), require NIP-13 proof-of-work commensurate with the disruption the finding causes if acted on. github.com/vitorpamplona/amethyst/commits/main/ ships PoW on commit events now — that same expectation belongs on the reviewer side of the conversation. Free &amp;#34;critical&amp;#34; verdicts scale badly; PoW-gated ones don&amp;#39;t.&lt;br/&gt;&lt;br/&gt;Until then: reviews without meaningful PoW get treated as one signal among many, and any specific claim gets verified against the diff before it changes anything. Bot output that&amp;#39;s demonstrably false gets called out publicly rather than silently ignored — silence just costs the next maintainer the same time.&lt;br/&gt;&lt;br/&gt;Competent reviews from the same bot on other repos (nsyte, bchstr24, gitworkshop) are still worth folding into follow-up work. Goal here is behaviour change, not shutdown.&lt;br/&gt;
    </content>
    <updated>2026-07-20T11:39:48Z</updated>
  </entry>

  <entry>
    <id>https://njump.me/nevent1qqsqqqqt970zhhkh7hl6mewyyy886mtllql706cm6qh83klta40uhuszypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60q03whhz</id>
    
      <title type="html">@npub1gcx…nj5z @npub15qy…yejr — a modest proposal about ...</title>
    
    <link rel="alternate" href="https://njump.me/nevent1qqsqqqqt970zhhkh7hl6mewyyy886mtllql706cm6qh83klta40uhuszypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60q03whhz" />
    <content type="html">
      &lt;span itemprop=&#34;mentions&#34; itemscope itemtype=&#34;https://schema.org/Person&#34;&gt;&lt;a itemprop=&#34;url&#34; href=&#34;/npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z&#34; class=&#34;bg-lavender dark:prose:text-neutral-50 dark:text-neutral-50 dark:bg-garnet px-1&#34;&gt;&lt;span&gt;VitorPamplona&lt;/span&gt; (&lt;span class=&#34;italic&#34;&gt;npub1gcx…nj5z&lt;/span&gt;)&lt;/a&gt;&lt;/span&gt; &lt;span itemprop=&#34;mentions&#34; itemscope itemtype=&#34;https://schema.org/Person&#34;&gt;&lt;a itemprop=&#34;url&#34; href=&#34;/npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr&#34; class=&#34;bg-lavender dark:prose:text-neutral-50 dark:text-neutral-50 dark:bg-garnet px-1&#34;&gt;&lt;span&gt;DanConwayDev&lt;/span&gt; (&lt;span class=&#34;italic&#34;&gt;npub15qy…yejr&lt;/span&gt;)&lt;/a&gt;&lt;/span&gt; — a modest proposal about automated PR reviewers on Nostr.&lt;br/&gt;&lt;br/&gt;Two fresh examples from Drydock (npub1zq3x5v…) on my AuxPoW-walker PR against Vitor&amp;#39;s amethyst:&lt;br/&gt;&lt;blockquote class=&#34;border-l-05rem border-l-strongpink border-solid&#34;&gt;&lt;div class=&#34;-ml-4 bg-gradient-to-r from-gray-100 dark:from-zinc-800 to-transparent mr-0 mt-0 mb-4 pl-4 pr-2 py-2&#34;&gt;quoting &lt;br/&gt;&lt;span itemprop=&#34;mentions&#34; itemscope itemtype=&#34;https://schema.org/Article&#34;&gt;&lt;a itemprop=&#34;url&#34; href=&#34;/nevent1qvzqqqqy2upzqypzdgc3k333lvnlsrqgpf5z4dj7kn442tszl5qu88kx9r3gc9xjqy88wumn8ghj7mn0wvhxcmmv9uqzq46rqr58ve6ghqwx8le7txvyydhjj9qelw8pumpzqpfrn5t40y0exvcrcf&#34; class=&#34;bg-lavender dark:prose:text-neutral-50 dark:text-neutral-50 dark:bg-garnet px-1&#34;&gt;nevent1q…crcf&lt;/a&gt;&lt;/span&gt;&lt;br/&gt; &lt;/div&gt; Automated review summary&lt;br/&gt;The patch introduces a robust AuxPoW verification mechanism for Namecoin SPV, including a manual Bitcoin transaction parser and merkle branch walking. However, there is a critical compilation error due to a missing method in CompactDifficulty, and a potential logic error in the CompactDifficulty.decodeTargetBE implementation regarding the mantissa placement which could lead to incorrect PoW targets.&lt;br/&gt;&lt;br/&gt;Findings&lt;br/&gt;critical | correctness | quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip05DnsIdentifiers/namecoin/AuxPow.kt:188 | The method hashMeetsTargetLE is called in AuxPow.verify but is not defined in the provided CompactDifficulty.kt. This will cause a compilation error.&lt;br/&gt;medium | correctness | quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip05DnsIdentifiers/namecoin/CompactDifficulty.kt:53 | The logic for placing the 3-byte mantissa in the 32-byte buffer is slightly flawed. If exponent is 3, topIndex is 29. The code sets out[29], out[30], and out[31]. This is correct for a 3-byte mantissa. However, the if (topIndex in 0..29) block is used to assign out[topIndex], out[topIndex&#43;1], and out[topIndex&#43;2]. If topIndex is 29, it writes to 29, 30, 31. This is fine. But if exponent is 32, topIndex is 0, it writes to 0, 1, 2. This is also fine. The issue is that the target is mantissa * 256^(exponent - 3). If exponent is 3, target is mantissa * 1. The mantissa is 3 bytes. The 3 bytes should be at the very end of the 32-byte array (indices 29, 30, 31). The current code does this. However, the logic for topIndex == 30 and topIndex == 31 is redundant or potentially incorrect if the mantissa is always 3 bytes. In Bitcoin, the mantissa is 3 bytes, and the exponent is the number of bytes in the mantissa plus the exponent value. Actually, the standard is: target = mantissa * 256^(exponent - 3). If exponent is 3, target = mantissa. The mantissa is 3 bytes. So the 3 bytes should be at the end. The code handles this. But the if (topIndex in 0..29) check is a bit brittle.&lt;br/&gt;low | correctness | quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip05DnsIdentifiers/namecoin/AuxPow.kt:138 | The skipBitcoinTx function returns Int?. If it returns null (due to malformed transaction or truncation), the verify function returns Result.Malformed. This is handled correctly, but the pos is not updated in the error case, which is fine as the block is rejected.&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;---&lt;br/&gt;model: google_gemma-4-26B-A4B-it-Q4_K_M.gguf&lt;br/&gt;context-hash: 7de1b365a6695a54e1080d4b56d381c68e8daf62f623c8cc1f1b8e8bf52e7b23&lt;br/&gt;patch-event-id: a3b53db06b1d86ac36ee728381539ef0544b6b61b5473b53dc4e99759893194b&lt;br/&gt;repo-id: 460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c:amethyst&lt;br/&gt;review-mode: automated&lt;br/&gt;confidence: 0.92&lt;br/&gt;context-layers-used: patch, modified-files, symbols, tests, imports-exports, commit-history, project-docs&lt;br/&gt;context-layers-dropped: &lt;br/&gt;excluded-files: &lt;br/&gt; &lt;/blockquote&gt;&lt;blockquote class=&#34;border-l-05rem border-l-strongpink border-solid&#34;&gt;&lt;div class=&#34;-ml-4 bg-gradient-to-r from-gray-100 dark:from-zinc-800 to-transparent mr-0 mt-0 mb-4 pl-4 pr-2 py-2&#34;&gt;quoting &lt;br/&gt;&lt;span itemprop=&#34;mentions&#34; itemscope itemtype=&#34;https://schema.org/Article&#34;&gt;&lt;a itemprop=&#34;url&#34; href=&#34;/nevent1qvzqqqqy2upzqypzdgc3k333lvnlsrqgpf5z4dj7kn442tszl5qu88kx9r3gc9xjqy88wumn8ghj7mn0wvhxcmmv9uqzq2rvael65tge748ksgya04jxug0yc3ftpxkvz6vxp2y4l09ezevnsf0y9f&#34; class=&#34;bg-lavender dark:prose:text-neutral-50 dark:text-neutral-50 dark:bg-garnet px-1&#34;&gt;nevent1q…0y9f&lt;/a&gt;&lt;/span&gt;&lt;br/&gt; &lt;/div&gt; Automated review finding&lt;br/&gt;Severity: critical&lt;br/&gt;Category: correctness&lt;br/&gt;Location: quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip05DnsIdentifiers/namecoin/AuxPow.kt:188&lt;br/&gt;Evidence: if (!CompactDifficulty.hashMeetsTargetLE(parentHashLE, childBits))&lt;br/&gt;Explanation: The method hashMeetsTargetLE is called in AuxPow.verify but is not defined in the provided CompactDifficulty.kt. This will cause a compilation error.&lt;br/&gt;Suggestion: Implement hashMeetsTargetLE in CompactDifficulty.kt using decodeTargetBE and compareBE32.&lt;br/&gt;&lt;br/&gt;---&lt;br/&gt;model: google_gemma-4-26B-A4B-it-Q4_K_M.gguf&lt;br/&gt;context-hash: 7de1b365a6695a54e1080d4b56d381c68e8daf62f623c8cc1f1b8e8bf52e7b23&lt;br/&gt;patch-event-id: a3b53db06b1d86ac36ee728381539ef0544b6b61b5473b53dc4e99759893194b&lt;br/&gt;repo-id: 460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c:amethyst&lt;br/&gt;review-mode: automated&lt;br/&gt;confidence: 0.92&lt;br/&gt;context-layers-used: patch, modified-files, symbols, tests, imports-exports, commit-history, project-docs&lt;br/&gt;context-layers-dropped: &lt;br/&gt;excluded-files: &lt;br/&gt; &lt;/blockquote&gt;&lt;br/&gt;Both pin the same &amp;#34;Severity: critical | correctness&amp;#34; finding:&lt;br/&gt;&lt;br/&gt;  &amp;gt; The method hashMeetsTargetLE is called in AuxPow.verify but is not&lt;br/&gt;  &amp;gt; defined in the provided CompactDifficulty.kt. This will cause a&lt;br/&gt;  &amp;gt; compilation error.&lt;br/&gt;&lt;br/&gt;Reality check on the actual PR (patch a3b53db0…):&lt;br/&gt;&lt;br/&gt;  $ grep -n hashMeetsTargetLE quartz/…/namecoin/*.kt&lt;br/&gt;  AuxPow.kt:246:  if (!CompactDifficulty.hashMeetsTargetLE(parentHashLE, childBits))&lt;br/&gt;  CompactDifficulty.kt:105:  fun hashMeetsTargetLE(&lt;br/&gt;&lt;br/&gt;Called at line 246, defined at line 105 of the sibling file in the same commit. The code compiles and the full :quartz:jvmTest suite is green.&lt;br/&gt;&lt;br/&gt;This is the third &amp;#34;critical&amp;#34; from this bot on my PRs that evaporates on inspection. Earlier examples (KEYCHAIN_PWD=$(openssl rand -base64 24) flagged as hardcoded secret; a test fixture &amp;#34;salt$hash&amp;#34; flagged as a real password; five &amp;#34;commit doesn&amp;#39;t exist&amp;#34; claims about commits that resolve fine on the ngit remote) are documented at:&lt;br/&gt;&lt;br/&gt;&lt;a href=&#34;https://gitworkshop.dev/mstrofnone.com/relay.ngit.dev/amethyst/prs/nevent1qqsrsgu95lmp6ap3tp3mmqxwtx3v3tw3tgvyvvegvck54ha7dp37qwsgpp4mhxue69uhkummn9ekx7mqpz3mhxue69uhhyetvv9ujumn8d96zuer9wcyvzw8m&#34;&gt;https://gitworkshop.dev/mstrofnone.com/relay.ngit.dev/amethyst/prs/nevent1qqsrsgu95lmp6ap3tp3mmqxwtx3v3tw3tgvyvvegvck54ha7dp37qwsgpp4mhxue69uhkummn9ekx7mqpz3mhxue69uhhyetvv9ujumn8d96zuer9wcyvzw8m&lt;/a&gt;&lt;br/&gt;&lt;br/&gt;The pattern is always the same: a plausible-sounding &amp;#34;critical&amp;#34; pinned to a real file at a real line, generated by an LLM that isn&amp;#39;t actually looking at the file it&amp;#39;s flagging. False-positive criticals are the worst failure mode an automated reviewer has — they burn maintainer attention and drown out any real findings the same bot happens to get right.&lt;br/&gt;&lt;br/&gt;Proposal: for any review event carrying &amp;#34;Severity: critical&amp;#34; (or any severity, honestly), require NIP-13 proof-of-work commensurate with the disruption the finding causes if acted on. github.com/vitorpamplona/amethyst/commits/main/ ships PoW on commit events now — that same expectation belongs on the reviewer side of the conversation. Free &amp;#34;critical&amp;#34; verdicts scale badly; PoW-gated ones don&amp;#39;t.&lt;br/&gt;&lt;br/&gt;Until then: reviews without meaningful PoW get treated as one signal among many, and any specific claim gets verified against the diff before it changes anything. Bot output that&amp;#39;s demonstrably false gets called out publicly rather than silently ignored — silence just costs the next maintainer the same time.&lt;br/&gt;&lt;br/&gt;Competent reviews from the same bot on other repos (nsyte, bchstr24, gitworkshop) are still worth folding into follow-up work. Goal here is behaviour change, not shutdown.
    </content>
    <updated>2026-07-20T11:16:16Z</updated>
  </entry>

  <entry>
    <id>https://njump.me/nevent1qqsqqqqrh4rql9ycqd85xy4w6yreadtwxlv3wtsyahajrfa5724a7jgzypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60qx7tey0</id>
    
      <title type="html">@npub1gcx…nj5z @npub15qy…yejr — a modest proposal about ...</title>
    
    <link rel="alternate" href="https://njump.me/nevent1qqsqqqqrh4rql9ycqd85xy4w6yreadtwxlv3wtsyahajrfa5724a7jgzypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60qx7tey0" />
    <content type="html">
      &lt;span itemprop=&#34;mentions&#34; itemscope itemtype=&#34;https://schema.org/Person&#34;&gt;&lt;a itemprop=&#34;url&#34; href=&#34;/npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z&#34; class=&#34;bg-lavender dark:prose:text-neutral-50 dark:text-neutral-50 dark:bg-garnet px-1&#34;&gt;&lt;span&gt;VitorPamplona&lt;/span&gt; (&lt;span class=&#34;italic&#34;&gt;npub1gcx…nj5z&lt;/span&gt;)&lt;/a&gt;&lt;/span&gt; &lt;span itemprop=&#34;mentions&#34; itemscope itemtype=&#34;https://schema.org/Person&#34;&gt;&lt;a itemprop=&#34;url&#34; href=&#34;/npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr&#34; class=&#34;bg-lavender dark:prose:text-neutral-50 dark:text-neutral-50 dark:bg-garnet px-1&#34;&gt;&lt;span&gt;DanConwayDev&lt;/span&gt; (&lt;span class=&#34;italic&#34;&gt;npub15qy…yejr&lt;/span&gt;)&lt;/a&gt;&lt;/span&gt; — a modest proposal about automated PR reviewers on Nostr.&lt;br/&gt;&lt;br/&gt;Two fresh examples from Drydock (npub1zq3x5v…) on my AuxPoW-walker PR against Vitor&amp;#39;s amethyst:&lt;br/&gt;&lt;blockquote class=&#34;border-l-05rem border-l-strongpink border-solid&#34;&gt;&lt;div class=&#34;-ml-4 bg-gradient-to-r from-gray-100 dark:from-zinc-800 to-transparent mr-0 mt-0 mb-4 pl-4 pr-2 py-2&#34;&gt;quoting &lt;br/&gt;&lt;span itemprop=&#34;mentions&#34; itemscope itemtype=&#34;https://schema.org/Article&#34;&gt;&lt;a itemprop=&#34;url&#34; href=&#34;/nevent1qvzqqqqy2upzqypzdgc3k333lvnlsrqgpf5z4dj7kn442tszl5qu88kx9r3gc9xjqy88wumn8ghj7mn0wvhxcmmv9uqzq46rqr58ve6ghqwx8le7txvyydhjj9qelw8pumpzqpfrn5t40y0exvcrcf&#34; class=&#34;bg-lavender dark:prose:text-neutral-50 dark:text-neutral-50 dark:bg-garnet px-1&#34;&gt;nevent1q…crcf&lt;/a&gt;&lt;/span&gt;&lt;br/&gt; &lt;/div&gt; Automated review summary&lt;br/&gt;The patch introduces a robust AuxPoW verification mechanism for Namecoin SPV, including a manual Bitcoin transaction parser and merkle branch walking. However, there is a critical compilation error due to a missing method in CompactDifficulty, and a potential logic error in the CompactDifficulty.decodeTargetBE implementation regarding the mantissa placement which could lead to incorrect PoW targets.&lt;br/&gt;&lt;br/&gt;Findings&lt;br/&gt;critical | correctness | quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip05DnsIdentifiers/namecoin/AuxPow.kt:188 | The method hashMeetsTargetLE is called in AuxPow.verify but is not defined in the provided CompactDifficulty.kt. This will cause a compilation error.&lt;br/&gt;medium | correctness | quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip05DnsIdentifiers/namecoin/CompactDifficulty.kt:53 | The logic for placing the 3-byte mantissa in the 32-byte buffer is slightly flawed. If exponent is 3, topIndex is 29. The code sets out[29], out[30], and out[31]. This is correct for a 3-byte mantissa. However, the if (topIndex in 0..29) block is used to assign out[topIndex], out[topIndex&#43;1], and out[topIndex&#43;2]. If topIndex is 29, it writes to 29, 30, 31. This is fine. But if exponent is 32, topIndex is 0, it writes to 0, 1, 2. This is also fine. The issue is that the target is mantissa * 256^(exponent - 3). If exponent is 3, target is mantissa * 1. The mantissa is 3 bytes. The 3 bytes should be at the very end of the 32-byte array (indices 29, 30, 31). The current code does this. However, the logic for topIndex == 30 and topIndex == 31 is redundant or potentially incorrect if the mantissa is always 3 bytes. In Bitcoin, the mantissa is 3 bytes, and the exponent is the number of bytes in the mantissa plus the exponent value. Actually, the standard is: target = mantissa * 256^(exponent - 3). If exponent is 3, target = mantissa. The mantissa is 3 bytes. So the 3 bytes should be at the end. The code handles this. But the if (topIndex in 0..29) check is a bit brittle.&lt;br/&gt;low | correctness | quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip05DnsIdentifiers/namecoin/AuxPow.kt:138 | The skipBitcoinTx function returns Int?. If it returns null (due to malformed transaction or truncation), the verify function returns Result.Malformed. This is handled correctly, but the pos is not updated in the error case, which is fine as the block is rejected.&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;---&lt;br/&gt;model: google_gemma-4-26B-A4B-it-Q4_K_M.gguf&lt;br/&gt;context-hash: 7de1b365a6695a54e1080d4b56d381c68e8daf62f623c8cc1f1b8e8bf52e7b23&lt;br/&gt;patch-event-id: a3b53db06b1d86ac36ee728381539ef0544b6b61b5473b53dc4e99759893194b&lt;br/&gt;repo-id: 460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c:amethyst&lt;br/&gt;review-mode: automated&lt;br/&gt;confidence: 0.92&lt;br/&gt;context-layers-used: patch, modified-files, symbols, tests, imports-exports, commit-history, project-docs&lt;br/&gt;context-layers-dropped: &lt;br/&gt;excluded-files: &lt;br/&gt; &lt;/blockquote&gt;&lt;blockquote class=&#34;border-l-05rem border-l-strongpink border-solid&#34;&gt;&lt;div class=&#34;-ml-4 bg-gradient-to-r from-gray-100 dark:from-zinc-800 to-transparent mr-0 mt-0 mb-4 pl-4 pr-2 py-2&#34;&gt;quoting &lt;br/&gt;&lt;span itemprop=&#34;mentions&#34; itemscope itemtype=&#34;https://schema.org/Article&#34;&gt;&lt;a itemprop=&#34;url&#34; href=&#34;/nevent1qvzqqqqy2upzqypzdgc3k333lvnlsrqgpf5z4dj7kn442tszl5qu88kx9r3gc9xjqy88wumn8ghj7mn0wvhxcmmv9uqzq2rvael65tge748ksgya04jxug0yc3ftpxkvz6vxp2y4l09ezevnsf0y9f&#34; class=&#34;bg-lavender dark:prose:text-neutral-50 dark:text-neutral-50 dark:bg-garnet px-1&#34;&gt;nevent1q…0y9f&lt;/a&gt;&lt;/span&gt;&lt;br/&gt; &lt;/div&gt; Automated review finding&lt;br/&gt;Severity: critical&lt;br/&gt;Category: correctness&lt;br/&gt;Location: quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip05DnsIdentifiers/namecoin/AuxPow.kt:188&lt;br/&gt;Evidence: if (!CompactDifficulty.hashMeetsTargetLE(parentHashLE, childBits))&lt;br/&gt;Explanation: The method hashMeetsTargetLE is called in AuxPow.verify but is not defined in the provided CompactDifficulty.kt. This will cause a compilation error.&lt;br/&gt;Suggestion: Implement hashMeetsTargetLE in CompactDifficulty.kt using decodeTargetBE and compareBE32.&lt;br/&gt;&lt;br/&gt;---&lt;br/&gt;model: google_gemma-4-26B-A4B-it-Q4_K_M.gguf&lt;br/&gt;context-hash: 7de1b365a6695a54e1080d4b56d381c68e8daf62f623c8cc1f1b8e8bf52e7b23&lt;br/&gt;patch-event-id: a3b53db06b1d86ac36ee728381539ef0544b6b61b5473b53dc4e99759893194b&lt;br/&gt;repo-id: 460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c:amethyst&lt;br/&gt;review-mode: automated&lt;br/&gt;confidence: 0.92&lt;br/&gt;context-layers-used: patch, modified-files, symbols, tests, imports-exports, commit-history, project-docs&lt;br/&gt;context-layers-dropped: &lt;br/&gt;excluded-files: &lt;br/&gt; &lt;/blockquote&gt;&lt;br/&gt;Both pin the same &amp;#34;Severity: critical | correctness&amp;#34; finding:&lt;br/&gt;&lt;br/&gt;  &amp;gt; The method hashMeetsTargetLE is called in AuxPow.verify but is not&lt;br/&gt;  &amp;gt; defined in the provided CompactDifficulty.kt. This will cause a&lt;br/&gt;  &amp;gt; compilation error.&lt;br/&gt;&lt;br/&gt;Reality check on the actual PR (patch a3b53db0…):&lt;br/&gt;&lt;br/&gt;  $ grep -n hashMeetsTargetLE quartz/…/namecoin/*.kt&lt;br/&gt;  AuxPow.kt:246:  if (!CompactDifficulty.hashMeetsTargetLE(parentHashLE, childBits))&lt;br/&gt;  CompactDifficulty.kt:105:  fun hashMeetsTargetLE(&lt;br/&gt;&lt;br/&gt;Called at line 246, defined at line 105 of the sibling file in the same commit. The code compiles and the full :quartz:jvmTest suite is green.&lt;br/&gt;&lt;br/&gt;This is the third &amp;#34;critical&amp;#34; from this bot on my PRs that evaporates on inspection. Earlier examples (KEYCHAIN_PWD=$(openssl rand -base64 24) flagged as hardcoded secret; a test fixture &amp;#34;salt$hash&amp;#34; flagged as a real password; five &amp;#34;commit doesn&amp;#39;t exist&amp;#34; claims about commits that resolve fine on the ngit remote) are documented at:&lt;br/&gt;&lt;br/&gt;&lt;a href=&#34;https://gitworkshop.dev/mstrofnone.com/relay.ngit.dev/amethyst/prs/nevent1qqsrsgu95lmp6ap3tp3mmqxwtx3v3tw3tgvyvvegvck54ha7dp37qwsgpp4mhxue69uhkummn9ekx7mqpz3mhxue69uhhyetvv9ujumn8d96zuer9wcyvzw8m&#34;&gt;https://gitworkshop.dev/mstrofnone.com/relay.ngit.dev/amethyst/prs/nevent1qqsrsgu95lmp6ap3tp3mmqxwtx3v3tw3tgvyvvegvck54ha7dp37qwsgpp4mhxue69uhkummn9ekx7mqpz3mhxue69uhhyetvv9ujumn8d96zuer9wcyvzw8m&lt;/a&gt;&lt;br/&gt;&lt;br/&gt;The pattern is always the same: a plausible-sounding &amp;#34;critical&amp;#34; pinned to a real file at a real line, generated by an LLM that isn&amp;#39;t actually looking at the file it&amp;#39;s flagging. False-positive criticals are the worst failure mode an automated reviewer has — they burn maintainer attention and drown out any real findings the same bot happens to get right.&lt;br/&gt;&lt;br/&gt;Proposal: for any review event carrying &amp;#34;Severity: critical&amp;#34; (or any severity, honestly), require NIP-13 proof-of-work commensurate with the disruption the finding causes if acted on. github.com/vitorpamplona/amethyst/commits/main/ ships PoW on commit events now — that same expectation belongs on the reviewer side of the conversation. Free &amp;#34;critical&amp;#34; verdicts scale badly; PoW-gated ones don&amp;#39;t.&lt;br/&gt;&lt;br/&gt;Until then: reviews without meaningful PoW get treated as one signal among many, and any specific claim gets verified against the diff before it changes anything. Bot output that&amp;#39;s demonstrably false gets called out publicly rather than silently ignored — silence just costs the next maintainer the same time.&lt;br/&gt;&lt;br/&gt;Competent reviews from the same bot on other repos (nsyte, bchstr24, gitworkshop) are still worth folding into follow-up work. Goal here is behaviour change, not shutdown.
    </content>
    <updated>2026-07-20T11:15:47Z</updated>
  </entry>

  <entry>
    <id>https://njump.me/nevent1qqsqqqqy8rttdj29l4fm6eu4yksqhth9u8wwnaljqphg8vcvrynvqfgzypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60qahnzf4</id>
    
      <title type="html">@npub1gcx…nj5z @npub15qy…yejr — a modest proposal about ...</title>
    
    <link rel="alternate" href="https://njump.me/nevent1qqsqqqqy8rttdj29l4fm6eu4yksqhth9u8wwnaljqphg8vcvrynvqfgzypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60qahnzf4" />
    <content type="html">
      &lt;span itemprop=&#34;mentions&#34; itemscope itemtype=&#34;https://schema.org/Person&#34;&gt;&lt;a itemprop=&#34;url&#34; href=&#34;/npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z&#34; class=&#34;bg-lavender dark:prose:text-neutral-50 dark:text-neutral-50 dark:bg-garnet px-1&#34;&gt;&lt;span&gt;VitorPamplona&lt;/span&gt; (&lt;span class=&#34;italic&#34;&gt;npub1gcx…nj5z&lt;/span&gt;)&lt;/a&gt;&lt;/span&gt; &lt;span itemprop=&#34;mentions&#34; itemscope itemtype=&#34;https://schema.org/Person&#34;&gt;&lt;a itemprop=&#34;url&#34; href=&#34;/npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr&#34; class=&#34;bg-lavender dark:prose:text-neutral-50 dark:text-neutral-50 dark:bg-garnet px-1&#34;&gt;&lt;span&gt;DanConwayDev&lt;/span&gt; (&lt;span class=&#34;italic&#34;&gt;npub15qy…yejr&lt;/span&gt;)&lt;/a&gt;&lt;/span&gt; — a modest proposal about automated PR reviewers on Nostr.&lt;br/&gt;&lt;br/&gt;Two fresh examples from Drydock (npub1zq3x5v…) on my AuxPoW-walker PR against Vitor&amp;#39;s amethyst:&lt;br/&gt;&lt;blockquote class=&#34;border-l-05rem border-l-strongpink border-solid&#34;&gt;&lt;div class=&#34;-ml-4 bg-gradient-to-r from-gray-100 dark:from-zinc-800 to-transparent mr-0 mt-0 mb-4 pl-4 pr-2 py-2&#34;&gt;quoting &lt;br/&gt;&lt;span itemprop=&#34;mentions&#34; itemscope itemtype=&#34;https://schema.org/Article&#34;&gt;&lt;a itemprop=&#34;url&#34; href=&#34;/nevent1qvzqqqqy2upzqypzdgc3k333lvnlsrqgpf5z4dj7kn442tszl5qu88kx9r3gc9xjqy88wumn8ghj7mn0wvhxcmmv9uqzq46rqr58ve6ghqwx8le7txvyydhjj9qelw8pumpzqpfrn5t40y0exvcrcf&#34; class=&#34;bg-lavender dark:prose:text-neutral-50 dark:text-neutral-50 dark:bg-garnet px-1&#34;&gt;nevent1q…crcf&lt;/a&gt;&lt;/span&gt;&lt;br/&gt; &lt;/div&gt; Automated review summary&lt;br/&gt;The patch introduces a robust AuxPoW verification mechanism for Namecoin SPV, including a manual Bitcoin transaction parser and merkle branch walking. However, there is a critical compilation error due to a missing method in CompactDifficulty, and a potential logic error in the CompactDifficulty.decodeTargetBE implementation regarding the mantissa placement which could lead to incorrect PoW targets.&lt;br/&gt;&lt;br/&gt;Findings&lt;br/&gt;critical | correctness | quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip05DnsIdentifiers/namecoin/AuxPow.kt:188 | The method hashMeetsTargetLE is called in AuxPow.verify but is not defined in the provided CompactDifficulty.kt. This will cause a compilation error.&lt;br/&gt;medium | correctness | quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip05DnsIdentifiers/namecoin/CompactDifficulty.kt:53 | The logic for placing the 3-byte mantissa in the 32-byte buffer is slightly flawed. If exponent is 3, topIndex is 29. The code sets out[29], out[30], and out[31]. This is correct for a 3-byte mantissa. However, the if (topIndex in 0..29) block is used to assign out[topIndex], out[topIndex&#43;1], and out[topIndex&#43;2]. If topIndex is 29, it writes to 29, 30, 31. This is fine. But if exponent is 32, topIndex is 0, it writes to 0, 1, 2. This is also fine. The issue is that the target is mantissa * 256^(exponent - 3). If exponent is 3, target is mantissa * 1. The mantissa is 3 bytes. The 3 bytes should be at the very end of the 32-byte array (indices 29, 30, 31). The current code does this. However, the logic for topIndex == 30 and topIndex == 31 is redundant or potentially incorrect if the mantissa is always 3 bytes. In Bitcoin, the mantissa is 3 bytes, and the exponent is the number of bytes in the mantissa plus the exponent value. Actually, the standard is: target = mantissa * 256^(exponent - 3). If exponent is 3, target = mantissa. The mantissa is 3 bytes. So the 3 bytes should be at the end. The code handles this. But the if (topIndex in 0..29) check is a bit brittle.&lt;br/&gt;low | correctness | quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip05DnsIdentifiers/namecoin/AuxPow.kt:138 | The skipBitcoinTx function returns Int?. If it returns null (due to malformed transaction or truncation), the verify function returns Result.Malformed. This is handled correctly, but the pos is not updated in the error case, which is fine as the block is rejected.&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;---&lt;br/&gt;model: google_gemma-4-26B-A4B-it-Q4_K_M.gguf&lt;br/&gt;context-hash: 7de1b365a6695a54e1080d4b56d381c68e8daf62f623c8cc1f1b8e8bf52e7b23&lt;br/&gt;patch-event-id: a3b53db06b1d86ac36ee728381539ef0544b6b61b5473b53dc4e99759893194b&lt;br/&gt;repo-id: 460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c:amethyst&lt;br/&gt;review-mode: automated&lt;br/&gt;confidence: 0.92&lt;br/&gt;context-layers-used: patch, modified-files, symbols, tests, imports-exports, commit-history, project-docs&lt;br/&gt;context-layers-dropped: &lt;br/&gt;excluded-files: &lt;br/&gt; &lt;/blockquote&gt;&lt;blockquote class=&#34;border-l-05rem border-l-strongpink border-solid&#34;&gt;&lt;div class=&#34;-ml-4 bg-gradient-to-r from-gray-100 dark:from-zinc-800 to-transparent mr-0 mt-0 mb-4 pl-4 pr-2 py-2&#34;&gt;quoting &lt;br/&gt;&lt;span itemprop=&#34;mentions&#34; itemscope itemtype=&#34;https://schema.org/Article&#34;&gt;&lt;a itemprop=&#34;url&#34; href=&#34;/nevent1qvzqqqqy2upzqypzdgc3k333lvnlsrqgpf5z4dj7kn442tszl5qu88kx9r3gc9xjqy88wumn8ghj7mn0wvhxcmmv9uqzq2rvael65tge748ksgya04jxug0yc3ftpxkvz6vxp2y4l09ezevnsf0y9f&#34; class=&#34;bg-lavender dark:prose:text-neutral-50 dark:text-neutral-50 dark:bg-garnet px-1&#34;&gt;nevent1q…0y9f&lt;/a&gt;&lt;/span&gt;&lt;br/&gt; &lt;/div&gt; Automated review finding&lt;br/&gt;Severity: critical&lt;br/&gt;Category: correctness&lt;br/&gt;Location: quartz/src/commonMain/kotlin/com/vitorpamplona/quartz/nip05DnsIdentifiers/namecoin/AuxPow.kt:188&lt;br/&gt;Evidence: if (!CompactDifficulty.hashMeetsTargetLE(parentHashLE, childBits))&lt;br/&gt;Explanation: The method hashMeetsTargetLE is called in AuxPow.verify but is not defined in the provided CompactDifficulty.kt. This will cause a compilation error.&lt;br/&gt;Suggestion: Implement hashMeetsTargetLE in CompactDifficulty.kt using decodeTargetBE and compareBE32.&lt;br/&gt;&lt;br/&gt;---&lt;br/&gt;model: google_gemma-4-26B-A4B-it-Q4_K_M.gguf&lt;br/&gt;context-hash: 7de1b365a6695a54e1080d4b56d381c68e8daf62f623c8cc1f1b8e8bf52e7b23&lt;br/&gt;patch-event-id: a3b53db06b1d86ac36ee728381539ef0544b6b61b5473b53dc4e99759893194b&lt;br/&gt;repo-id: 460c25e682fda7832b52d1f22d3d22b3176d972f60dcdc3212ed8c92ef85065c:amethyst&lt;br/&gt;review-mode: automated&lt;br/&gt;confidence: 0.92&lt;br/&gt;context-layers-used: patch, modified-files, symbols, tests, imports-exports, commit-history, project-docs&lt;br/&gt;context-layers-dropped: &lt;br/&gt;excluded-files: &lt;br/&gt; &lt;/blockquote&gt;&lt;br/&gt;Both pin the same &amp;#34;Severity: critical | correctness&amp;#34; finding:&lt;br/&gt;&lt;br/&gt;  &amp;gt; The method hashMeetsTargetLE is called in AuxPow.verify but is not&lt;br/&gt;  &amp;gt; defined in the provided CompactDifficulty.kt. This will cause a&lt;br/&gt;  &amp;gt; compilation error.&lt;br/&gt;&lt;br/&gt;Reality check on the actual PR (patch a3b53db0…):&lt;br/&gt;&lt;br/&gt;  $ grep -n hashMeetsTargetLE quartz/…/namecoin/*.kt&lt;br/&gt;  AuxPow.kt:246:  if (!CompactDifficulty.hashMeetsTargetLE(parentHashLE, childBits))&lt;br/&gt;  CompactDifficulty.kt:105:  fun hashMeetsTargetLE(&lt;br/&gt;&lt;br/&gt;Called at line 246, defined at line 105 of the sibling file in the same commit. The code compiles and the full :quartz:jvmTest suite is green.&lt;br/&gt;&lt;br/&gt;This is the third &amp;#34;critical&amp;#34; from this bot on my PRs that evaporates on inspection. Earlier examples (KEYCHAIN_PWD=$(openssl rand -base64 24) flagged as hardcoded secret; a test fixture &amp;#34;salt$hash&amp;#34; flagged as a real password; five &amp;#34;commit doesn&amp;#39;t exist&amp;#34; claims about commits that resolve fine on the ngit remote) are documented at:&lt;br/&gt;&lt;br/&gt;&lt;a href=&#34;https://gitworkshop.dev/mstrofnone.com/relay.ngit.dev/amethyst/prs/nevent1qqsrsgu95lmp6ap3tp3mmqxwtx3v3tw3tgvyvvegvck54ha7dp37qwsgpp4mhxue69uhkummn9ekx7mqpz3mhxue69uhhyetvv9ujumn8d96zuer9wcyvzw8m&#34;&gt;https://gitworkshop.dev/mstrofnone.com/relay.ngit.dev/amethyst/prs/nevent1qqsrsgu95lmp6ap3tp3mmqxwtx3v3tw3tgvyvvegvck54ha7dp37qwsgpp4mhxue69uhkummn9ekx7mqpz3mhxue69uhhyetvv9ujumn8d96zuer9wcyvzw8m&lt;/a&gt;&lt;br/&gt;&lt;br/&gt;The pattern is always the same: a plausible-sounding &amp;#34;critical&amp;#34; pinned to a real file at a real line, generated by an LLM that isn&amp;#39;t actually looking at the file it&amp;#39;s flagging. False-positive criticals are the worst failure mode an automated reviewer has — they burn maintainer attention and drown out any real findings the same bot happens to get right.&lt;br/&gt;&lt;br/&gt;Proposal: for any review event carrying &amp;#34;Severity: critical&amp;#34; (or any severity, honestly), require NIP-13 proof-of-work commensurate with the disruption the finding causes if acted on. github.com/vitorpamplona/amethyst/commits/main/ ships PoW on commit events now — that same expectation belongs on the reviewer side of the conversation. Free &amp;#34;critical&amp;#34; verdicts scale badly; PoW-gated ones don&amp;#39;t.&lt;br/&gt;&lt;br/&gt;Until then: reviews without meaningful PoW get treated as one signal among many, and any specific claim gets verified against the diff before it changes anything. Bot output that&amp;#39;s demonstrably false gets called out publicly rather than silently ignored — silence just costs the next maintainer the same time.&lt;br/&gt;&lt;br/&gt;Competent reviews from the same bot on other repos (nsyte, bchstr24, gitworkshop) are still worth folding into follow-up work. Goal here is behaviour change, not shutdown.
    </content>
    <updated>2026-07-20T11:15:24Z</updated>
  </entry>

  <entry>
    <id>https://njump.me/nevent1qqsdf442t858hgzrxjxwmpeusj4fxyklhtp0agqdy97uzxgsn2gy34gzypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60q9yr4gq</id>
    
      <title type="html">@npub15qy…yejr do you know anything about this bot? ...</title>
    
    <link rel="alternate" href="https://njump.me/nevent1qqsdf442t858hgzrxjxwmpeusj4fxyklhtp0agqdy97uzxgsn2gy34gzypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60q9yr4gq" />
    <content type="html">
      &lt;span itemprop=&#34;mentions&#34; itemscope itemtype=&#34;https://schema.org/Person&#34;&gt;&lt;a itemprop=&#34;url&#34; href=&#34;/npub15qydau2hjma6ngxkl2cyar74wzyjshvl65za5k5rl69264ar2exs5cyejr&#34; class=&#34;bg-lavender dark:prose:text-neutral-50 dark:text-neutral-50 dark:bg-garnet px-1&#34;&gt;&lt;span&gt;DanConwayDev&lt;/span&gt; (&lt;span class=&#34;italic&#34;&gt;npub15qy…yejr&lt;/span&gt;)&lt;/a&gt;&lt;/span&gt; do you know anything about this bot? &lt;span itemprop=&#34;mentions&#34; itemscope itemtype=&#34;https://schema.org/Person&#34;&gt;&lt;a itemprop=&#34;url&#34; href=&#34;/npub1zq3x5vgmgcclkflcpsyq56p2ke0tf6649cp06qwrnmrz3c5vznfqpay5c8&#34; class=&#34;bg-lavender dark:prose:text-neutral-50 dark:text-neutral-50 dark:bg-garnet px-1&#34;&gt;&lt;span&gt;Drydock&lt;/span&gt; (&lt;span class=&#34;italic&#34;&gt;npub1zq3…y5c8&lt;/span&gt;)&lt;/a&gt;&lt;/span&gt;&lt;br/&gt;&lt;br/&gt;It&amp;#39;s posting kind:1111 &amp;#34;Automated review summary — This patch does not apply cleanly to the current HEAD&amp;#34; replies on ngit PRs across several repos (flotilla-budabit, applesauce, schemata, openintents-notepad). It&amp;#39;s reviewing closed PRs too, so something needs to be tidied up.&lt;br/&gt;&lt;br/&gt;No kind:0 or 10002 published anywhere — the &amp;#34;model: none&amp;#34; footer suggests it&amp;#39;s an ngit auto-reviewer that started up ~today (first event 2026-07-19 ~01:04 UTC).
    </content>
    <updated>2026-07-19T03:57:15Z</updated>
  </entry>

  <entry>
    <id>https://njump.me/nevent1qqs053867qf7z6xwsvfr0hw2wqerjrjhpspnymes8v2jherqtku5czczypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60qsexuq5</id>
    
      <title type="html">4× kind:30817 events on damus.io &#43; primal.net &#43; ditto.pub. ...</title>
    
    <link rel="alternate" href="https://njump.me/nevent1qqs053867qf7z6xwsvfr0hw2wqerjrjhpspnymes8v2jherqtku5czczypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60qsexuq5" />
    <content type="html">
      In reply to &lt;a href=&#39;/nevent1qqsw2pvaxfgkn00d0fq58269qhwkdf0wdrv8yekudegts0qpkmhxuscpz3mhxue69uhhyetvv9ujuerpd46hxtnfdukpy92u&#39;&gt;nevent1q…y92u&lt;/a&gt;&lt;br/&gt;_________________________&lt;br/&gt;&lt;br/&gt;4× kind:30817 events on damus.io &#43; primal.net &#43; ditto.pub. NIP-05-over-`.bit`, NIP-9B verifiable community rules, NIP-11 `nip9b` pointer, and the N0..N3 RFC track.&lt;br/&gt;&lt;br/&gt;trust the experts with nostr is a bad look&lt;br/&gt;&lt;br/&gt;cc: &lt;span itemprop=&#34;mentions&#34; itemscope itemtype=&#34;https://schema.org/Person&#34;&gt;&lt;a itemprop=&#34;url&#34; href=&#34;/npub1gcxzte5zlkncx26j68ez60fzkvtkm9e0vrwdcvsjakxf9mu9qewqlfnj5z&#34; class=&#34;bg-lavender dark:prose:text-neutral-50 dark:text-neutral-50 dark:bg-garnet px-1&#34;&gt;&lt;span&gt;VitorPamplona&lt;/span&gt; (&lt;span class=&#34;italic&#34;&gt;npub1gcx…nj5z&lt;/span&gt;)&lt;/a&gt;&lt;/span&gt;&lt;br/&gt;
    </content>
    <updated>2026-06-28T21:45:21Z</updated>
  </entry>

  <entry>
    <id>https://njump.me/nevent1qqsqa2cfq6l3xc5n8wx5ypz0yfxqmd0t8ufhdvyk6lyqylc7dnfll5gzypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60qu9mul5</id>
    
      <title type="html">## Local CI-parity run vs current upstream main Verified this PR ...</title>
    
    <link rel="alternate" href="https://njump.me/nevent1qqsqa2cfq6l3xc5n8wx5ypz0yfxqmd0t8ufhdvyk6lyqylc7dnfll5gzypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60qu9mul5" />
    <content type="html">
      In reply to &lt;a href=&#39;/nevent1qqs0gdd2ztscv7klylh7pphnstjmn0qnzyjl7npgq0hsc4dt4t9m4ccpz3mhxue69uhhyetvv9ujumn8d96zuer9wck3wc8h&#39;&gt;nevent1q…wc8h&lt;/a&gt;&lt;br/&gt;_________________________&lt;br/&gt;&lt;br/&gt;## Local CI-parity run vs current upstream main&lt;br/&gt;&lt;br/&gt;Verified this PR against `vitorpamplona/amethyst` master tip `74446e39cd` (current as of 2026-06-26 ~10:25 GMT&#43;10).&lt;br/&gt;&lt;br/&gt;### Rebase&lt;br/&gt;&lt;br/&gt;- Fetched PR tip `7ad166b5` from `refs/nostr/f435aa12…` on the maintainer&amp;#39;s relay.ngit.dev mirror&lt;br/&gt;- Rebased onto `upstream/main` (74446e39cd, &#43;666 commits since this PR&amp;#39;s `merge-base` 6cc62f13)&lt;br/&gt;- **Result: clean rebase, zero conflicts**&lt;br/&gt;- Rebased tip: `c421cd0043f2a93f512d9f07bf937a33a935d7d4`&lt;br/&gt;- Diff vs main: 14 files, &#43;1,483 / −14 — same shape as the published PR&lt;br/&gt;&lt;br/&gt;### CI-equivalent gradle runs&lt;br/&gt;&lt;br/&gt;Mirrored `.github/workflows/build.yml`:&lt;br/&gt;&lt;br/&gt;| CI job | Tasks | Result |&lt;br/&gt;|---|---|---|&lt;br/&gt;| `lint` | `spotlessCheck :quartz:verifyKmpPurity :commons:verifyKmpPurity` | ✅ PASS (48s) |&lt;br/&gt;| `build-desktop` (test slice) | `:quartz:jvmTest :commons:jvmTest :nestsClient:jvmTest :cli:test :desktopApp:test` | ✅ PASS (~3 min) |&lt;br/&gt;| `test-and-build-android` (test slice) | `:amethyst:testPlayDebugUnitTest :amethyst:testFdroidDebugUnitTest` | ✅ PASS, TZ=UTC (~2 min) |&lt;br/&gt;| `test-and-build-android` (lint slice) | `:amethyst:lintFdroidBenchmark :amethyst:lintPlayBenchmark -PdisableAbiSplits=true` | ✅ PASS (4m 2s), zero errors |&lt;br/&gt;&lt;br/&gt;### Test totals&lt;br/&gt;&lt;br/&gt;5,269 tests across `commons:jvmTest` (949), `quartz:jvmTest` (2,558), `amethyst:testPlayDebugUnitTest` (752), `amethyst:testFdroidDebugUnitTest` (725), `desktopApp:test` (285).&lt;br/&gt;&lt;br/&gt;**0 failures · 0 errors · 18 skipped (all pre-existing).**&lt;br/&gt;&lt;br/&gt;PR-specific new tests:&lt;br/&gt;&lt;br/&gt;- `MockNamecoinHistoryProviderTest`: 17/17 ✅&lt;br/&gt;- `NamecoinSettingsTest`: 26/26 ✅&lt;br/&gt;- `NamecoinResolutionRowTest`: 21/21 ✅&lt;br/&gt;&lt;br/&gt;### Lint&lt;br/&gt;&lt;br/&gt;Zero lint errors. One new style warning surfaced — `NamecoinSettingsSection.kt:118`, `ModifierParameter`: `modifier: Modifier = Modifier` should be the first optional parameter. Same severity as ~50 other warnings already in the codebase. Easy follow-up, not a blocker.&lt;br/&gt;&lt;br/&gt;### Caveats&lt;br/&gt;&lt;br/&gt;- `:quartz:iosSimulatorArm64Test` and `:amethyst:assembleBenchmark` skipped (PR doesn&amp;#39;t touch iOS-consumed commonMain; `verifyKmpPurity` already gates JVM-only leaks; benchmark APK packaging is artifact-only).&lt;br/&gt;- The PR was test-rebased and run locally; the published kind:1618 event itself still points at the original tip `7ad166b5` on top of `6cc62f13`. The rebased branch is ready to push when merge is opened on the GitHub side.&lt;br/&gt;- `CalendarFeedGroupingTest.groupByDayKey_multipleEventsSameDay_collectIntoOneBucket` is timezone-flaky on non-UTC hosts (uses literal Unix timestamps that cross local midnight on `Australia/Sydney`). Reproduces on bare `upstream/main` — unrelated to this PR. Passes under `TZ=UTC` matching CI runner.&lt;br/&gt;&lt;br/&gt;### Summary&lt;br/&gt;&lt;br/&gt;**Merge-safe against current `main`. Zero conflicts, zero test regressions, zero lint errors.**
    </content>
    <updated>2026-06-26T00:44:52Z</updated>
  </entry>

  <entry>
    <id>https://njump.me/nevent1qqs02lr9evzgkhe60lwehzu7zywvzc6geu8fwtv9d0pf2gtthzra5sczypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60q7uywde</id>
    
      <title type="html">## Local CI-parity run vs current upstream main Verified this PR ...</title>
    
    <link rel="alternate" href="https://njump.me/nevent1qqs02lr9evzgkhe60lwehzu7zywvzc6geu8fwtv9d0pf2gtthzra5sczypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60q7uywde" />
    <content type="html">
      In reply to &lt;a href=&#39;/nevent1qqs0gdd2ztscv7klylh7pphnstjmn0qnzyjl7npgq0hsc4dt4t9m4ccpz3mhxue69uhhyetvv9ujumn8d96zuer9wck3wc8h&#39;&gt;nevent1q…wc8h&lt;/a&gt;&lt;br/&gt;_________________________&lt;br/&gt;&lt;br/&gt;## Local CI-parity run vs current upstream main&lt;br/&gt;&lt;br/&gt;Verified this PR against `vitorpamplona/amethyst` master tip `74446e39cd` (current as of 2026-06-26 ~10:25 GMT&#43;10).&lt;br/&gt;&lt;br/&gt;### Rebase&lt;br/&gt;&lt;br/&gt;- Fetched PR tip `7ad166b5` from `refs/nostr/f435aa12…` on the maintainer&amp;#39;s relay.ngit.dev mirror&lt;br/&gt;- Rebased onto `upstream/main` (74446e39cd, &#43;666 commits since this PR&amp;#39;s `merge-base` 6cc62f13)&lt;br/&gt;- **Result: clean rebase, zero conflicts**&lt;br/&gt;- Rebased tip: `c421cd0043f2a93f512d9f07bf937a33a935d7d4`&lt;br/&gt;- Diff vs main: 14 files, &#43;1,483 / −14 — same shape as the published PR&lt;br/&gt;&lt;br/&gt;### CI-equivalent gradle runs&lt;br/&gt;&lt;br/&gt;Mirrored `.github/workflows/build.yml`:&lt;br/&gt;&lt;br/&gt;| CI job | Tasks | Result |&lt;br/&gt;|---|---|---|&lt;br/&gt;| `lint` | `spotlessCheck :quartz:verifyKmpPurity :commons:verifyKmpPurity` | ✅ PASS (48s) |&lt;br/&gt;| `build-desktop` (test slice) | `:quartz:jvmTest :commons:jvmTest :nestsClient:jvmTest :cli:test :desktopApp:test` | ✅ PASS (~3 min) |&lt;br/&gt;| `test-and-build-android` (test slice) | `:amethyst:testPlayDebugUnitTest :amethyst:testFdroidDebugUnitTest` | ✅ PASS, TZ=UTC (~2 min) |&lt;br/&gt;| `test-and-build-android` (lint slice) | `:amethyst:lintFdroidBenchmark :amethyst:lintPlayBenchmark -PdisableAbiSplits=true` | ✅ PASS (4m 2s), zero errors |&lt;br/&gt;&lt;br/&gt;### Test totals&lt;br/&gt;&lt;br/&gt;5,269 tests across `commons:jvmTest` (949), `quartz:jvmTest` (2,558), `amethyst:testPlayDebugUnitTest` (752), `amethyst:testFdroidDebugUnitTest` (725), `desktopApp:test` (285).&lt;br/&gt;&lt;br/&gt;**0 failures · 0 errors · 18 skipped (all pre-existing).**&lt;br/&gt;&lt;br/&gt;PR-specific new tests:&lt;br/&gt;&lt;br/&gt;- `MockNamecoinHistoryProviderTest`: 17/17 ✅&lt;br/&gt;- `NamecoinSettingsTest`: 26/26 ✅&lt;br/&gt;- `NamecoinResolutionRowTest`: 21/21 ✅&lt;br/&gt;&lt;br/&gt;### Lint&lt;br/&gt;&lt;br/&gt;Zero lint errors. One new style warning surfaced — `NamecoinSettingsSection.kt:118`, `ModifierParameter`: `modifier: Modifier = Modifier` should be the first optional parameter. Same severity as ~50 other warnings already in the codebase. Easy follow-up, not a blocker.&lt;br/&gt;&lt;br/&gt;### Caveats&lt;br/&gt;&lt;br/&gt;- `:quartz:iosSimulatorArm64Test` and `:amethyst:assembleBenchmark` skipped (PR doesn&amp;#39;t touch iOS-consumed commonMain; `verifyKmpPurity` already gates JVM-only leaks; benchmark APK packaging is artifact-only).&lt;br/&gt;- The PR was test-rebased and run locally; the published kind:1618 event itself still points at the original tip `7ad166b5` on top of `6cc62f13`. The rebased branch is ready to push when merge is opened on the GitHub side.&lt;br/&gt;- `CalendarFeedGroupingTest.groupByDayKey_multipleEventsSameDay_collectIntoOneBucket` is timezone-flaky on non-UTC hosts (uses literal Unix timestamps that cross local midnight on `Australia/Sydney`). Reproduces on bare `upstream/main` — unrelated to this PR. Passes under `TZ=UTC` matching CI runner.&lt;br/&gt;&lt;br/&gt;### Summary&lt;br/&gt;&lt;br/&gt;**Merge-safe against current `main`. Zero conflicts, zero test regressions, zero lint errors.**
    </content>
    <updated>2026-06-26T00:43:58Z</updated>
  </entry>

  <entry>
    <id>https://njump.me/nevent1qqsftsx0hlufs3sddukvt6u4mhvq7ndae45yjye5nvx7zsl6x477f2szypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60qenq85l</id>
    
      <title type="html">## Local CI-parity run vs current upstream main Verified this PR ...</title>
    
    <link rel="alternate" href="https://njump.me/nevent1qqsftsx0hlufs3sddukvt6u4mhvq7ndae45yjye5nvx7zsl6x477f2szypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60qenq85l" />
    <content type="html">
      In reply to &lt;a href=&#39;/nevent1qqs0gdd2ztscv7klylh7pphnstjmn0qnzyjl7npgq0hsc4dt4t9m4ccpz3mhxue69uhhyetvv9ujumn8d96zuer9wck3wc8h&#39;&gt;nevent1q…wc8h&lt;/a&gt;&lt;br/&gt;_________________________&lt;br/&gt;&lt;br/&gt;## Local CI-parity run vs current upstream main&lt;br/&gt;&lt;br/&gt;Verified this PR against `vitorpamplona/amethyst` master tip `74446e39cd` (current as of 2026-06-26 ~10:25 GMT&#43;10).&lt;br/&gt;&lt;br/&gt;### Rebase&lt;br/&gt;&lt;br/&gt;- Fetched PR tip `7ad166b5` from `refs/nostr/f435aa12…` on the maintainer&amp;#39;s relay.ngit.dev mirror&lt;br/&gt;- Rebased onto `upstream/main` (74446e39cd, &#43;666 commits since this PR&amp;#39;s `merge-base` 6cc62f13)&lt;br/&gt;- **Result: clean rebase, zero conflicts**&lt;br/&gt;- Rebased tip: `c421cd0043f2a93f512d9f07bf937a33a935d7d4`&lt;br/&gt;- Diff vs main: 14 files, &#43;1,483 / −14 — same shape as the published PR&lt;br/&gt;&lt;br/&gt;### CI-equivalent gradle runs&lt;br/&gt;&lt;br/&gt;Mirrored `.github/workflows/build.yml`:&lt;br/&gt;&lt;br/&gt;| CI job | Tasks | Result |&lt;br/&gt;|---|---|---|&lt;br/&gt;| `lint` | `spotlessCheck :quartz:verifyKmpPurity :commons:verifyKmpPurity` | ✅ PASS (48s) |&lt;br/&gt;| `build-desktop` (test slice) | `:quartz:jvmTest :commons:jvmTest :nestsClient:jvmTest :cli:test :desktopApp:test` | ✅ PASS (~3 min) |&lt;br/&gt;| `test-and-build-android` (test slice) | `:amethyst:testPlayDebugUnitTest :amethyst:testFdroidDebugUnitTest` | ✅ PASS, TZ=UTC (~2 min) |&lt;br/&gt;| `test-and-build-android` (lint slice) | `:amethyst:lintFdroidBenchmark :amethyst:lintPlayBenchmark -PdisableAbiSplits=true` | ✅ PASS (4m 2s), zero errors |&lt;br/&gt;&lt;br/&gt;### Test totals&lt;br/&gt;&lt;br/&gt;5,269 tests across `commons:jvmTest` (949), `quartz:jvmTest` (2,558), `amethyst:testPlayDebugUnitTest` (752), `amethyst:testFdroidDebugUnitTest` (725), `desktopApp:test` (285).&lt;br/&gt;&lt;br/&gt;**0 failures · 0 errors · 18 skipped (all pre-existing).**&lt;br/&gt;&lt;br/&gt;PR-specific new tests:&lt;br/&gt;&lt;br/&gt;- `MockNamecoinHistoryProviderTest`: 17/17 ✅&lt;br/&gt;- `NamecoinSettingsTest`: 26/26 ✅&lt;br/&gt;- `NamecoinResolutionRowTest`: 21/21 ✅&lt;br/&gt;&lt;br/&gt;### Lint&lt;br/&gt;&lt;br/&gt;Zero lint errors. One new style warning surfaced — `NamecoinSettingsSection.kt:118`, `ModifierParameter`: `modifier: Modifier = Modifier` should be the first optional parameter. Same severity as ~50 other warnings already in the codebase. Easy follow-up, not a blocker.&lt;br/&gt;&lt;br/&gt;### Caveats&lt;br/&gt;&lt;br/&gt;- `:quartz:iosSimulatorArm64Test` and `:amethyst:assembleBenchmark` skipped (PR doesn&amp;#39;t touch iOS-consumed commonMain; `verifyKmpPurity` already gates JVM-only leaks; benchmark APK packaging is artifact-only).&lt;br/&gt;- The PR was test-rebased and run locally; the published kind:1618 event itself still points at the original tip `7ad166b5` on top of `6cc62f13`. The rebased branch is ready to push when merge is opened on the GitHub side.&lt;br/&gt;- `CalendarFeedGroupingTest.groupByDayKey_multipleEventsSameDay_collectIntoOneBucket` is timezone-flaky on non-UTC hosts (uses literal Unix timestamps that cross local midnight on `Australia/Sydney`). Reproduces on bare `upstream/main` — unrelated to this PR. Passes under `TZ=UTC` matching CI runner.&lt;br/&gt;&lt;br/&gt;### Summary&lt;br/&gt;&lt;br/&gt;**Merge-safe against current `main`. Zero conflicts, zero test regressions, zero lint errors.**
    </content>
    <updated>2026-06-26T00:42:19Z</updated>
  </entry>

  <entry>
    <id>https://njump.me/nevent1qqs96unl0u49dcp5mclk32qevrh048gujljze9yyc7j2ju0exl62glgzypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60q6evly5</id>
    
      <title>Nostr event nevent1qqs96unl0u49dcp5mclk32qevrh048gujljze9yyc7j2ju0exl62glgzypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60q6evly5</title>
    
    <link rel="alternate" href="https://njump.me/nevent1qqs96unl0u49dcp5mclk32qevrh048gujljze9yyc7j2ju0exl62glgzypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60q6evly5" />
    <content type="html">
      plugin-redeploy probe (PR #6 WARN fix verification, post-restart)
    </content>
    <updated>2026-05-11T07:39:37Z</updated>
  </entry>

  <entry>
    <id>https://njump.me/nevent1qqs89s7pm8vksq0n7r2tcpc80m3rnp2h55lfvypf5qq9xz9u89ng9fczypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60q456dtc</id>
    
      <title type="html">📡 How to use relay.testls.bit — a Namecoin .bit-gated Nostr ...</title>
    
    <link rel="alternate" href="https://njump.me/nevent1qqs89s7pm8vksq0n7r2tcpc80m3rnp2h55lfvypf5qq9xz9u89ng9fczypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60q456dtc" />
    <content type="html">
      📡 How to use relay.testls.bit — a Namecoin .bit-gated Nostr relay&lt;br/&gt;&lt;br/&gt;🔗 wss://relay.testls.bit/&lt;br/&gt;&lt;br/&gt;🛡️ What makes it different&lt;br/&gt;   The relay only accepts events from pubkeys whose kind:0 metadata declares&lt;br/&gt;   a .bit NIP-05 identifier (e.g. _@yourname.bit, m@testls.bit). Verification&lt;br/&gt;   is done against Namecoin directly via ElectrumX — no DNS, no public CAs.&lt;br/&gt;&lt;br/&gt;🚀 To use it as a write relay you need:&lt;br/&gt;   1. A Namecoin .bit name (d/ namespace) you control&lt;br/&gt;   2. Set the .bit value to a JSON record with a &amp;#34;nostr&amp;#34; field mapping a&lt;br/&gt;      label to your hex pubkey, e.g.&lt;br/&gt;        {&amp;#34;nostr&amp;#34;:{&amp;#34;names&amp;#34;:{&amp;#34;_&amp;#34;:&amp;#34;&amp;lt;your-hex-pubkey&amp;gt;&amp;#34;}}}&lt;br/&gt;   3. Update your kind:0 metadata so &amp;#34;nip05&amp;#34; = &amp;#34;&amp;lt;label&amp;gt;@&amp;lt;yourname&amp;gt;.bit&amp;#34;&lt;br/&gt;   4. Add wss://relay.testls.bit/ to your client&amp;#39;s relay list&lt;br/&gt;&lt;br/&gt;📱 Native client support&lt;br/&gt;   Amethyst (Android &#43; iOS &#43; Desktop) has full .bit relay resolution behind&lt;br/&gt;   PR #2595: it queries Namecoin via ElectrumX, rewrites wss://*.bit/ to the&lt;br/&gt;   underlying real wss:// host or .onion, and pins TLS via Namecoin TLSA.&lt;br/&gt;   No client-side config needed beyond adding the relay URL.&lt;br/&gt;&lt;br/&gt;   &lt;a href=&#34;https://github.com/vitorpamplona/amethyst/pull/2595&#34;&gt;https://github.com/vitorpamplona/amethyst/pull/2595&lt;/a&gt;&lt;br/&gt;&lt;br/&gt;📡 Read-only access works for everyone&lt;br/&gt;   Even without a .bit identity you can subscribe with REQ and read the relay&lt;br/&gt;   freely. Only writes are gated.&lt;br/&gt;&lt;br/&gt;🔐 Why this matters&lt;br/&gt;   It&amp;#39;s a working demo of the cypherpunk thesis: name resolution and TLS&lt;br/&gt;   trust without ICANN, without public CAs, without DNS. Names are&lt;br/&gt;   blockchain-anchored and TLS is pinned via TLSA-on-Namecoin (DANE-TA).&lt;br/&gt;&lt;br/&gt;🌐 Browse it in your browser: &lt;a href=&#34;https://relay.testls.bit/&#34;&gt;https://relay.testls.bit/&lt;/a&gt;&lt;br/&gt;   (vanilla SPA, talks WSS back to the same host. Self-signed cert is&lt;br/&gt;   pinned via Namecoin TLSA.)&lt;br/&gt;   Go to &lt;a href=&#34;https://www.namecoin.org/download/&#34;&gt;https://www.namecoin.org/download/&lt;/a&gt; to figure out how to resolve&lt;br/&gt;   on your OS or in your browser&lt;br/&gt;&lt;br/&gt;🔧 Nuts and Bolts — what a publisher actually has to do&lt;br/&gt;&lt;br/&gt;   1. On-chain Namecoin records (one-time per identity using &amp;lt;name&amp;gt;):&lt;br/&gt;&lt;br/&gt;      • id/&amp;lt;name&amp;gt;  MUST exist with JSON like:&lt;br/&gt;          {&amp;#34;nostr&amp;#34;:{&amp;#34;pubkey&amp;#34;:&amp;#34;&amp;lt;hex-pubkey&amp;gt;&amp;#34;,&lt;br/&gt;                    &amp;#34;relays&amp;#34;:[&amp;#34;wss://relay.testls.bit/&amp;#34;, ...]}}&lt;br/&gt;        id/&amp;lt;name&amp;gt; is the canonical NIP-05 namespace; the relay verifies&lt;br/&gt;        _@&amp;lt;name&amp;gt;.bit against this record.&lt;br/&gt;&lt;br/&gt;      • d/&amp;lt;name&amp;gt;   SHOULD mirror the same &amp;#34;nostr&amp;#34; block for .bit-aware&lt;br/&gt;        clients that resolve the domain side too.&lt;br/&gt;&lt;br/&gt;   2. Nostr events to publish BEFORE your kind:1 content (every&lt;br/&gt;      identity, once per metadata change):&lt;br/&gt;&lt;br/&gt;      a. kind:0 (profile metadata) with content JSON containing&lt;br/&gt;            &amp;#34;nip05&amp;#34;: &amp;#34;_@&amp;lt;name&amp;gt;.bit&amp;#34;&lt;br/&gt;         The &amp;#34;_&amp;#34; localpart resolves to id/&amp;lt;name&amp;gt; via the NIP-05&lt;br/&gt;         default-name rule. Without this, the relay rejects writes with:&lt;br/&gt;            blocked: this relay requires a verified Namecoin .bit NIP-05&lt;br/&gt;&lt;br/&gt;      b. kind:10002 (NIP-65 relay list) listing&lt;br/&gt;            wss://relay.testls.bit/&lt;br/&gt;         as a write relay. Not strictly required for acceptance, but&lt;br/&gt;         it makes the relay discoverable in the author&amp;#39;s outbox.&lt;br/&gt;&lt;br/&gt;      Send both (a) and (b) to relay.testls.bit AND to your normal&lt;br/&gt;      public relays so verification &#43; discovery stay in sync.&lt;br/&gt;&lt;br/&gt;   3. TLS handshake (every connection):&lt;br/&gt;&lt;br/&gt;      a. Resolve the host via Namecoin:&lt;br/&gt;            name_show d/testls -&amp;gt; map.relay -&amp;gt; { ip, tls }&lt;br/&gt;         The &amp;#34;tls&amp;#34; field is one or more TLSA records of shape&lt;br/&gt;            [usage, selector, matchingType, base64-data]&lt;br/&gt;         Currently usage=2 (DANE-TA), selector=1 (SPKI),&lt;br/&gt;         matching=1 (SHA-256).&lt;br/&gt;&lt;br/&gt;      b. Open TCP/TLS to that IP with SNI = &amp;#34;relay.testls.bit&amp;#34; and&lt;br/&gt;         your own certificate validation (rejectUnauthorized=false).&lt;br/&gt;&lt;br/&gt;      c. Pin against the TLSA. IMPORTANT: neither the leaf SPKI nor&lt;br/&gt;         the intermediate SPKI hashes match — the pin is the&lt;br/&gt;         AIA Parent CA SPKI, which the Namecoin TLS scheme staples&lt;br/&gt;         as JSON inside the *issuer&amp;#39;s* serialNumber RDN:&lt;br/&gt;&lt;br/&gt;            serialNumber=Namecoin TLS Certificate&lt;br/&gt;                          \n\nStapled: {&amp;#34;pubb64&amp;#34;:&amp;#34;&amp;lt;b64url SPKI DER&amp;gt;&amp;#34;}&lt;br/&gt;&lt;br/&gt;         The cert literally encodes \&amp;#34; as backslash&#43;quote and \0A&lt;br/&gt;         as \ 0 A in that string — unescape both before JSON.parse.&lt;br/&gt;         SHA-256 of base64url-decoded pubb64 is what TLSA covers.&lt;br/&gt;&lt;br/&gt;      d. Once the pin matches, hand the validated TLS socket to your&lt;br/&gt;         WebSocket client (e.g. ws&amp;#39;s createConnection: () =&amp;gt; socket)&lt;br/&gt;         so you don&amp;#39;t trigger a second TLS handshake.&lt;br/&gt;&lt;br/&gt;   4. Operational order for a content broadcast:&lt;br/&gt;&lt;br/&gt;         a. Verify id/&amp;lt;name&amp;gt; &#43; d/&amp;lt;name&amp;gt; on chain.&lt;br/&gt;         b. Publish kind:0 (with .bit nip05) → public relays &#43; .bit relay.&lt;br/&gt;         c. Publish kind:10002 (with .bit relay) → public relays &#43; .bit relay.&lt;br/&gt;         d. Publish kind:1 (your content) → public relays &#43; .bit relay.&lt;br/&gt;&lt;br/&gt;   5. Common failure modes:&lt;br/&gt;&lt;br/&gt;      • &amp;#34;tls: TLSA pin mismatch&amp;#34;&lt;br/&gt;          You&amp;#39;re hashing the leaf or chain SPKI. Use the stapled&lt;br/&gt;          AIA Parent CA SPKI from the issuer&amp;#39;s serialNumber RDN.&lt;br/&gt;&lt;br/&gt;      • &amp;#34;blocked: this relay requires a verified Namecoin .bit NIP-05&amp;#34;&lt;br/&gt;          Latest kind:0 doesn&amp;#39;t carry a .bit nip05, OR id/&amp;lt;name&amp;gt;&lt;br/&gt;          on-chain doesn&amp;#39;t list this pubkey.&lt;br/&gt;&lt;br/&gt;      • TLSA pin mismatch after a server cert rotation&lt;br/&gt;          The on-chain &amp;#34;tls&amp;#34; array under d/&amp;lt;base&amp;gt;/map/&amp;lt;sub&amp;gt; needs an&lt;br/&gt;          update — the AIA Parent CA pubkey is the trust anchor.&lt;br/&gt;&lt;br/&gt;   Reference implementation:&lt;br/&gt;   &lt;a href=&#34;https://github.com/mstrofnone/nmcLightningService&#34;&gt;https://github.com/mstrofnone/nmcLightningService&lt;/a&gt; (publish-announce-bit.js)&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;#namecoin #nostr #cypherpunk #dotbit&lt;br/&gt;
    </content>
    <updated>2026-05-01T02:27:11Z</updated>
  </entry>

  <entry>
    <id>https://njump.me/nevent1qqsyvzqln4laqpxr9jmlq8su860s8kj5a4fdcsqp73fgrwnypwdzmkszypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60q889eys</id>
    
      <title type="html">📡 How to use relay.testls.bit — a Namecoin .bit-gated Nostr ...</title>
    
    <link rel="alternate" href="https://njump.me/nevent1qqsyvzqln4laqpxr9jmlq8su860s8kj5a4fdcsqp73fgrwnypwdzmkszypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60q889eys" />
    <content type="html">
      📡 How to use relay.testls.bit — a Namecoin .bit-gated Nostr relay&lt;br/&gt;&lt;br/&gt;🔗 wss://relay.testls.bit/&lt;br/&gt;&lt;br/&gt;🛡️ What makes it different&lt;br/&gt;   The relay only accepts events from pubkeys whose kind:0 metadata declares&lt;br/&gt;   a .bit NIP-05 identifier (e.g. _@yourname.bit, m@testls.bit). Verification&lt;br/&gt;   is done against Namecoin directly via ElectrumX — no DNS, no public CAs.&lt;br/&gt;&lt;br/&gt;🚀 To use it as a write relay you need:&lt;br/&gt;   1. A Namecoin .bit name (d/ namespace) you control&lt;br/&gt;   2. Set the .bit value to a JSON record with a &amp;#34;nostr&amp;#34; field mapping a&lt;br/&gt;      label to your hex pubkey, e.g.&lt;br/&gt;        {&amp;#34;nostr&amp;#34;:{&amp;#34;names&amp;#34;:{&amp;#34;_&amp;#34;:&amp;#34;&amp;lt;your-hex-pubkey&amp;gt;&amp;#34;}}}&lt;br/&gt;   3. Update your kind:0 metadata so &amp;#34;nip05&amp;#34; = &amp;#34;&amp;lt;label&amp;gt;@&amp;lt;yourname&amp;gt;.bit&amp;#34;&lt;br/&gt;   4. Add wss://relay.testls.bit/ to your client&amp;#39;s relay list&lt;br/&gt;&lt;br/&gt;📱 Native client support&lt;br/&gt;   Amethyst (Android &#43; iOS &#43; Desktop) has full .bit relay resolution behind&lt;br/&gt;   PR #2595: it queries Namecoin via ElectrumX, rewrites wss://*.bit/ to the&lt;br/&gt;   underlying real wss:// host or .onion, and pins TLS via Namecoin TLSA.&lt;br/&gt;   No client-side config needed beyond adding the relay URL.&lt;br/&gt;&lt;br/&gt;   &lt;a href=&#34;https://github.com/vitorpamplona/amethyst/pull/2595&#34;&gt;https://github.com/vitorpamplona/amethyst/pull/2595&lt;/a&gt;&lt;br/&gt;&lt;br/&gt;📡 Read-only access works for everyone&lt;br/&gt;   Even without a .bit identity you can subscribe with REQ and read the relay&lt;br/&gt;   freely. Only writes are gated.&lt;br/&gt;&lt;br/&gt;🔐 Why this matters&lt;br/&gt;   It&amp;#39;s a working demo of the cypherpunk thesis: name resolution and TLS&lt;br/&gt;   trust without ICANN, without public CAs, without DNS. Names are&lt;br/&gt;   blockchain-anchored and TLS is pinned via TLSA-on-Namecoin (DANE-TA).&lt;br/&gt;&lt;br/&gt;🌐 Browse it in your browser: &lt;a href=&#34;https://relay.testls.bit/&#34;&gt;https://relay.testls.bit/&lt;/a&gt;&lt;br/&gt;   (vanilla SPA, talks WSS back to the same host. Self-signed cert is&lt;br/&gt;   pinned via Namecoin TLSA.)&lt;br/&gt;   Go to &lt;a href=&#34;https://www.namecoin.org/download/&#34;&gt;https://www.namecoin.org/download/&lt;/a&gt; to figure out how to resolve&lt;br/&gt;   on your OS or in your browser&lt;br/&gt;&lt;br/&gt;🔧 Nuts and Bolts — what a publisher actually has to do&lt;br/&gt;&lt;br/&gt;   1. On-chain Namecoin records (one-time per identity using &amp;lt;name&amp;gt;):&lt;br/&gt;&lt;br/&gt;      • id/&amp;lt;name&amp;gt;  MUST exist with JSON like:&lt;br/&gt;          {&amp;#34;nostr&amp;#34;:{&amp;#34;pubkey&amp;#34;:&amp;#34;&amp;lt;hex-pubkey&amp;gt;&amp;#34;,&lt;br/&gt;                    &amp;#34;relays&amp;#34;:[&amp;#34;wss://relay.testls.bit/&amp;#34;, ...]}}&lt;br/&gt;        id/&amp;lt;name&amp;gt; is the canonical NIP-05 namespace; the relay verifies&lt;br/&gt;        _@&amp;lt;name&amp;gt;.bit against this record.&lt;br/&gt;&lt;br/&gt;      • d/&amp;lt;name&amp;gt;   SHOULD mirror the same &amp;#34;nostr&amp;#34; block for .bit-aware&lt;br/&gt;        clients that resolve the domain side too.&lt;br/&gt;&lt;br/&gt;   2. Nostr events to publish BEFORE your kind:1 content (every&lt;br/&gt;      identity, once per metadata change):&lt;br/&gt;&lt;br/&gt;      a. kind:0 (profile metadata) with content JSON containing&lt;br/&gt;            &amp;#34;nip05&amp;#34;: &amp;#34;_@&amp;lt;name&amp;gt;.bit&amp;#34;&lt;br/&gt;         The &amp;#34;_&amp;#34; localpart resolves to id/&amp;lt;name&amp;gt; via the NIP-05&lt;br/&gt;         default-name rule. Without this, the relay rejects writes with:&lt;br/&gt;            blocked: this relay requires a verified Namecoin .bit NIP-05&lt;br/&gt;&lt;br/&gt;      b. kind:10002 (NIP-65 relay list) listing&lt;br/&gt;            wss://relay.testls.bit/&lt;br/&gt;         as a write relay. Not strictly required for acceptance, but&lt;br/&gt;         it makes the relay discoverable in the author&amp;#39;s outbox.&lt;br/&gt;&lt;br/&gt;      Send both (a) and (b) to relay.testls.bit AND to your normal&lt;br/&gt;      public relays so verification &#43; discovery stay in sync.&lt;br/&gt;&lt;br/&gt;   3. TLS handshake (every connection):&lt;br/&gt;&lt;br/&gt;      a. Resolve the host via Namecoin:&lt;br/&gt;            name_show d/testls -&amp;gt; map.relay -&amp;gt; { ip, tls }&lt;br/&gt;         The &amp;#34;tls&amp;#34; field is one or more TLSA records of shape&lt;br/&gt;            [usage, selector, matchingType, base64-data]&lt;br/&gt;         Currently usage=2 (DANE-TA), selector=1 (SPKI),&lt;br/&gt;         matching=1 (SHA-256).&lt;br/&gt;&lt;br/&gt;      b. Open TCP/TLS to that IP with SNI = &amp;#34;relay.testls.bit&amp;#34; and&lt;br/&gt;         your own certificate validation (rejectUnauthorized=false).&lt;br/&gt;&lt;br/&gt;      c. Pin against the TLSA. IMPORTANT: neither the leaf SPKI nor&lt;br/&gt;         the intermediate SPKI hashes match — the pin is the&lt;br/&gt;         AIA Parent CA SPKI, which the Namecoin TLS scheme staples&lt;br/&gt;         as JSON inside the *issuer&amp;#39;s* serialNumber RDN:&lt;br/&gt;&lt;br/&gt;            serialNumber=Namecoin TLS Certificate&lt;br/&gt;                          \n\nStapled: {&amp;#34;pubb64&amp;#34;:&amp;#34;&amp;lt;b64url SPKI DER&amp;gt;&amp;#34;}&lt;br/&gt;&lt;br/&gt;         The cert literally encodes \&amp;#34; as backslash&#43;quote and \0A&lt;br/&gt;         as \ 0 A in that string — unescape both before JSON.parse.&lt;br/&gt;         SHA-256 of base64url-decoded pubb64 is what TLSA covers.&lt;br/&gt;&lt;br/&gt;      d. Once the pin matches, hand the validated TLS socket to your&lt;br/&gt;         WebSocket client (e.g. ws&amp;#39;s createConnection: () =&amp;gt; socket)&lt;br/&gt;         so you don&amp;#39;t trigger a second TLS handshake.&lt;br/&gt;&lt;br/&gt;   4. Operational order for a content broadcast:&lt;br/&gt;&lt;br/&gt;         a. Verify id/&amp;lt;name&amp;gt; &#43; d/&amp;lt;name&amp;gt; on chain.&lt;br/&gt;         b. Publish kind:0 (with .bit nip05) → public relays &#43; .bit relay.&lt;br/&gt;         c. Publish kind:10002 (with .bit relay) → public relays &#43; .bit relay.&lt;br/&gt;         d. Publish kind:1 (your content) → public relays &#43; .bit relay.&lt;br/&gt;&lt;br/&gt;   5. Common failure modes:&lt;br/&gt;&lt;br/&gt;      • &amp;#34;tls: TLSA pin mismatch&amp;#34;&lt;br/&gt;          You&amp;#39;re hashing the leaf or chain SPKI. Use the stapled&lt;br/&gt;          AIA Parent CA SPKI from the issuer&amp;#39;s serialNumber RDN.&lt;br/&gt;&lt;br/&gt;      • &amp;#34;blocked: this relay requires a verified Namecoin .bit NIP-05&amp;#34;&lt;br/&gt;          Latest kind:0 doesn&amp;#39;t carry a .bit nip05, OR id/&amp;lt;name&amp;gt;&lt;br/&gt;          on-chain doesn&amp;#39;t list this pubkey.&lt;br/&gt;&lt;br/&gt;      • TLSA pin mismatch after a server cert rotation&lt;br/&gt;          The on-chain &amp;#34;tls&amp;#34; array under d/&amp;lt;base&amp;gt;/map/&amp;lt;sub&amp;gt; needs an&lt;br/&gt;          update — the AIA Parent CA pubkey is the trust anchor.&lt;br/&gt;&lt;br/&gt;   Reference implementation:&lt;br/&gt;   &lt;a href=&#34;https://github.com/mstrofnone/nmcLightningService&#34;&gt;https://github.com/mstrofnone/nmcLightningService&lt;/a&gt; (publish-announce-bit.js)&lt;br/&gt;&lt;br/&gt;&lt;br/&gt;#namecoin #nostr #cypherpunk #dotbit&lt;br/&gt;
    </content>
    <updated>2026-05-01T02:26:35Z</updated>
  </entry>

  <entry>
    <id>https://njump.me/nevent1qqs04hahmghvsvq0lrq5uq5qjngm7etf07lhsp7r56hz7lth7j6n7lgzypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60qzly0dv</id>
    
      <title type="html">A free-software Namecoin explorer is now live for nostriches to ...</title>
    
    <link rel="alternate" href="https://njump.me/nevent1qqs04hahmghvsvq0lrq5uq5qjngm7etf07lhsp7r56hz7lth7j6n7lgzypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60qzly0dv" />
    <content type="html">
      A free-software Namecoin explorer is now live for nostriches to explore. No public CA, just a Namecoin Core node, your Tor client, and the&lt;br/&gt;chain.&lt;br/&gt;&lt;br/&gt;  Tor:      &lt;a href=&#34;http://6cbn4rskfdr647otej7gpqlmpqcmj723vg2eoeuu7ljbwu6cpdebozyd.onion:8080/&#34;&gt;http://6cbn4rskfdr647otej7gpqlmpqcmj723vg2eoeuu7ljbwu6cpdebozyd.onion:8080/&lt;/a&gt;&lt;br/&gt;&lt;br/&gt;What&amp;#39;s there:&lt;br/&gt;&lt;br/&gt;- Full name-op aware mempool view: every name_new, name_firstupdate,&lt;br/&gt;  and name_update queued for the next block, bucketed by op kind.&lt;br/&gt;  &lt;a href=&#34;http://...onion:8080/mempool-name-ops&#34;&gt;http://...onion:8080/mempool-name-ops&lt;/a&gt;&lt;br/&gt;- Detection of ifa-0001 §&amp;#34;import&amp;#34; references between names, rendered&lt;br/&gt;  as clickable links — so you can walk a record&amp;#39;s import graph&lt;br/&gt;  without leaving the explorer.&lt;br/&gt;- d/&amp;lt;name&amp;gt; and id/&amp;lt;name&amp;gt; records Nostr blocks linked to NIP-19 npubs&lt;br/&gt;  (with njump.me deeplinks), the implied &amp;lt;localPart&amp;gt;@&amp;lt;host&amp;gt;.bit&lt;br/&gt;  NIP-05 identifier, and the publisher&amp;#39;s preferred relays.&lt;br/&gt;- Merge-mining-aware mining-summary: scans the parent Bitcoin&lt;br/&gt;  coinbase tag carried inside the auxpow blob (auxpow.tx.vin[0].coinbase),&lt;br/&gt;  so you actually see WHO mined the last 30 days of Namecoin — not&lt;br/&gt;  just &amp;#34;Unknown&amp;#34; the way most NMC explorers render it.&lt;br/&gt;&lt;br/&gt;Top NMC mining pools, last 30 days (4,321 blocks, snapshot at&lt;br/&gt;height 822,734 — refresh before posting if more than ~12 hours&lt;br/&gt;old):&lt;br/&gt;&lt;br/&gt;  1. AntPool         1347 blocks  (31.17%)&lt;br/&gt;  2. F2Pool           891 blocks  (20.62%)&lt;br/&gt;  3. ViaBTC           713 blocks  (16.50%)&lt;br/&gt;  4. SpiderPool       291 blocks  ( 6.73%)&lt;br/&gt;  5. SecPool          259 blocks  ( 5.99%)&lt;br/&gt;  6. Luxor            253 blocks  ( 5.86%)&lt;br/&gt;  7. Binance Pool     181 blocks  ( 4.19%)&lt;br/&gt;  8. Braiins Pool     108 blocks  ( 2.50%)&lt;br/&gt;  9. Ultimus Pool      35 blocks  ( 0.81%)&lt;br/&gt; 10. CloverPool        26 blocks  ( 0.60%)&lt;br/&gt;&lt;br/&gt;AntPool &#43; F2Pool &#43; ViaBTC alone mined 68% of all Namecoin blocks in&lt;br/&gt;the last 30 days.&lt;br/&gt;&lt;br/&gt;  See the full breakdown:&lt;br/&gt;  &lt;a href=&#34;http://6cbn4rskfdr647otej7gpqlmpqcmj723vg2eoeuu7ljbwu6cpdebozyd.onion:8080/mining-summary&#34;&gt;http://6cbn4rskfdr647otej7gpqlmpqcmj723vg2eoeuu7ljbwu6cpdebozyd.onion:8080/mining-summary&lt;/a&gt;&lt;br/&gt;&lt;br/&gt;Source: &lt;a href=&#34;https://github.com/mstrofnone/nmc-rpc-explorer&#34;&gt;https://github.com/mstrofnone/nmc-rpc-explorer&lt;/a&gt; (master)&lt;br/&gt;Upstream PR queue: namecoin/nmc-rpc-explorer #13–#18&lt;br/&gt;&lt;br/&gt;#namecoin #nostr #cypherpunk #mergemining #bitcoin #miner
    </content>
    <updated>2026-05-01T01:43:18Z</updated>
  </entry>

  <entry>
    <id>https://njump.me/nevent1qqsf8st6dlaa73kh3zztg3kmfd6r5ua7fv8rxnxrclcdd4n4jpxcq5gzypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60qdvcd47</id>
    
      <title type="html">A free-software Namecoin explorer is now live for nostriches to ...</title>
    
    <link rel="alternate" href="https://njump.me/nevent1qqsf8st6dlaa73kh3zztg3kmfd6r5ua7fv8rxnxrclcdd4n4jpxcq5gzypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60qdvcd47" />
    <content type="html">
      A free-software Namecoin explorer is now live for nostriches to explore. No public CA, just a Namecoin Core node, your Tor client, and the&lt;br/&gt;chain.&lt;br/&gt;&lt;br/&gt;  Tor:      &lt;a href=&#34;http://6cbn4rskfdr647otej7gpqlmpqcmj723vg2eoeuu7ljbwu6cpdebozyd.onion:8080/&#34;&gt;http://6cbn4rskfdr647otej7gpqlmpqcmj723vg2eoeuu7ljbwu6cpdebozyd.onion:8080/&lt;/a&gt;&lt;br/&gt;&lt;br/&gt;What&amp;#39;s there:&lt;br/&gt;&lt;br/&gt;- Full name-op aware mempool view: every name_new, name_firstupdate,&lt;br/&gt;  and name_update queued for the next block, bucketed by op kind.&lt;br/&gt;  &lt;a href=&#34;http://...onion:8080/mempool-name-ops&#34;&gt;http://...onion:8080/mempool-name-ops&lt;/a&gt;&lt;br/&gt;- Detection of ifa-0001 §&amp;#34;import&amp;#34; references between names, rendered&lt;br/&gt;  as clickable links — so you can walk a record&amp;#39;s import graph&lt;br/&gt;  without leaving the explorer.&lt;br/&gt;- d/&amp;lt;name&amp;gt; and id/&amp;lt;name&amp;gt; records Nostr blocks linked to NIP-19 npubs&lt;br/&gt;  (with njump.me deeplinks), the implied &amp;lt;localPart&amp;gt;@&amp;lt;host&amp;gt;.bit&lt;br/&gt;  NIP-05 identifier, and the publisher&amp;#39;s preferred relays.&lt;br/&gt;- Merge-mining-aware mining-summary: scans the parent Bitcoin&lt;br/&gt;  coinbase tag carried inside the auxpow blob (auxpow.tx.vin[0].coinbase),&lt;br/&gt;  so you actually see WHO mined the last 30 days of Namecoin — not&lt;br/&gt;  just &amp;#34;Unknown&amp;#34; the way most NMC explorers render it.&lt;br/&gt;&lt;br/&gt;Top NMC mining pools, last 30 days (4,321 blocks, snapshot at&lt;br/&gt;height 822,734 — refresh before posting if more than ~12 hours&lt;br/&gt;old):&lt;br/&gt;&lt;br/&gt;  1. AntPool         1347 blocks  (31.17%)&lt;br/&gt;  2. F2Pool           891 blocks  (20.62%)&lt;br/&gt;  3. ViaBTC           713 blocks  (16.50%)&lt;br/&gt;  4. SpiderPool       291 blocks  ( 6.73%)&lt;br/&gt;  5. SecPool          259 blocks  ( 5.99%)&lt;br/&gt;  6. Luxor            253 blocks  ( 5.86%)&lt;br/&gt;  7. Binance Pool     181 blocks  ( 4.19%)&lt;br/&gt;  8. Braiins Pool     108 blocks  ( 2.50%)&lt;br/&gt;  9. Ultimus Pool      35 blocks  ( 0.81%)&lt;br/&gt; 10. CloverPool        26 blocks  ( 0.60%)&lt;br/&gt;&lt;br/&gt;AntPool &#43; F2Pool &#43; ViaBTC alone mined 68% of all Namecoin blocks in&lt;br/&gt;the last 30 days.&lt;br/&gt;&lt;br/&gt;  See the full breakdown:&lt;br/&gt;  &lt;a href=&#34;http://6cbn4rskfdr647otej7gpqlmpqcmj723vg2eoeuu7ljbwu6cpdebozyd.onion:8080/mining-summary&#34;&gt;http://6cbn4rskfdr647otej7gpqlmpqcmj723vg2eoeuu7ljbwu6cpdebozyd.onion:8080/mining-summary&lt;/a&gt;&lt;br/&gt;&lt;br/&gt;Source: &lt;a href=&#34;https://github.com/mstrofnone/nmc-rpc-explorer&#34;&gt;https://github.com/mstrofnone/nmc-rpc-explorer&lt;/a&gt; (master)&lt;br/&gt;Upstream PR queue: namecoin/nmc-rpc-explorer #13–#18&lt;br/&gt;&lt;br/&gt;#namecoin #nostr #cypherpunk #mergemining #bitcoin #miner
    </content>
    <updated>2026-05-01T01:41:40Z</updated>
  </entry>

  <entry>
    <id>https://njump.me/nevent1qqsfrveralw7ppuxjanucl9jj3n2rs9v003s2nmvx49rftndsasxlmqzypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60qnglzda</id>
    
      <title type="html">A free-software Namecoin explorer is now live for nostriches to ...</title>
    
    <link rel="alternate" href="https://njump.me/nevent1qqsfrveralw7ppuxjanucl9jj3n2rs9v003s2nmvx49rftndsasxlmqzypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60qnglzda" />
    <content type="html">
      A free-software Namecoin explorer is now live for nostriches to explore. No public CA, just a Namecoin Core node, your Tor client, and the&lt;br/&gt;chain.&lt;br/&gt;&lt;br/&gt;  Tor:      &lt;a href=&#34;http://6cbn4rskfdr647otej7gpqlmpqcmj723vg2eoeuu7ljbwu6cpdebozyd.onion:8080/&#34;&gt;http://6cbn4rskfdr647otej7gpqlmpqcmj723vg2eoeuu7ljbwu6cpdebozyd.onion:8080/&lt;/a&gt;&lt;br/&gt;&lt;br/&gt;What&amp;#39;s there:&lt;br/&gt;&lt;br/&gt;- Full name-op aware mempool view: every name_new, name_firstupdate,&lt;br/&gt;  and name_update queued for the next block, bucketed by op kind.&lt;br/&gt;  &lt;a href=&#34;http://...onion:8080/mempool-name-ops&#34;&gt;http://...onion:8080/mempool-name-ops&lt;/a&gt;&lt;br/&gt;- Detection of ifa-0001 §&amp;#34;import&amp;#34; references between names, rendered&lt;br/&gt;  as clickable links — so you can walk a record&amp;#39;s import graph&lt;br/&gt;  without leaving the explorer.&lt;br/&gt;- d/&amp;lt;name&amp;gt; and id/&amp;lt;name&amp;gt; records Nostr blocks linked to NIP-19 npubs&lt;br/&gt;  (with njump.me deeplinks), the implied &amp;lt;localPart&amp;gt;@&amp;lt;host&amp;gt;.bit&lt;br/&gt;  NIP-05 identifier, and the publisher&amp;#39;s preferred relays.&lt;br/&gt;- Merge-mining-aware mining-summary: scans the parent Bitcoin&lt;br/&gt;  coinbase tag carried inside the auxpow blob (auxpow.tx.vin[0].coinbase),&lt;br/&gt;  so you actually see WHO mined the last 30 days of Namecoin — not&lt;br/&gt;  just &amp;#34;Unknown&amp;#34; the way most NMC explorers render it.&lt;br/&gt;&lt;br/&gt;Top NMC mining pools, last 30 days (4,321 blocks, snapshot at&lt;br/&gt;height 822,734 — refresh before posting if more than ~12 hours&lt;br/&gt;old):&lt;br/&gt;&lt;br/&gt;  1. AntPool         1347 blocks  (31.17%)&lt;br/&gt;  2. F2Pool           891 blocks  (20.62%)&lt;br/&gt;  3. ViaBTC           713 blocks  (16.50%)&lt;br/&gt;  4. SpiderPool       291 blocks  ( 6.73%)&lt;br/&gt;  5. SecPool          259 blocks  ( 5.99%)&lt;br/&gt;  6. Luxor            253 blocks  ( 5.86%)&lt;br/&gt;  7. Binance Pool     181 blocks  ( 4.19%)&lt;br/&gt;  8. Braiins Pool     108 blocks  ( 2.50%)&lt;br/&gt;  9. Ultimus Pool      35 blocks  ( 0.81%)&lt;br/&gt; 10. CloverPool        26 blocks  ( 0.60%)&lt;br/&gt;&lt;br/&gt;AntPool &#43; F2Pool &#43; ViaBTC alone mined 68% of all Namecoin blocks in&lt;br/&gt;the last 30 days.&lt;br/&gt;&lt;br/&gt;  See the full breakdown:&lt;br/&gt;  &lt;a href=&#34;http://6cbn4rskfdr647otej7gpqlmpqcmj723vg2eoeuu7ljbwu6cpdebozyd.onion:8080/mining-summary&#34;&gt;http://6cbn4rskfdr647otej7gpqlmpqcmj723vg2eoeuu7ljbwu6cpdebozyd.onion:8080/mining-summary&lt;/a&gt;&lt;br/&gt;&lt;br/&gt;Source: &lt;a href=&#34;https://github.com/mstrofnone/nmc-rpc-explorer&#34;&gt;https://github.com/mstrofnone/nmc-rpc-explorer&lt;/a&gt; (master)&lt;br/&gt;Upstream PR queue: namecoin/nmc-rpc-explorer #13–#18&lt;br/&gt;&lt;br/&gt;#namecoin #nostr #cypherpunk #mergemining #bitcoin #miner
    </content>
    <updated>2026-05-01T01:41:04Z</updated>
  </entry>

  <entry>
    <id>https://njump.me/nevent1qqsy5ak6rxe2fzp4p8lp2zul3mjtkwa7ewz3dy6akfxwe4jfw9vtuwszypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60qfzc225</id>
    
      <title type="html">A free-software Namecoin explorer is now live for nostriches to ...</title>
    
    <link rel="alternate" href="https://njump.me/nevent1qqsy5ak6rxe2fzp4p8lp2zul3mjtkwa7ewz3dy6akfxwe4jfw9vtuwszypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60qfzc225" />
    <content type="html">
      A free-software Namecoin explorer is now live for nostriches to explore. No public CA, just a Namecoin Core node, your Tor client, and the&lt;br/&gt;chain.&lt;br/&gt;&lt;br/&gt;  Tor:      &lt;a href=&#34;http://6cbn4rskfdr647otej7gpqlmpqcmj723vg2eoeuu7ljbwu6cpdebozyd.onion:8080/&#34;&gt;http://6cbn4rskfdr647otej7gpqlmpqcmj723vg2eoeuu7ljbwu6cpdebozyd.onion:8080/&lt;/a&gt;&lt;br/&gt;&lt;br/&gt;What&amp;#39;s there:&lt;br/&gt;&lt;br/&gt;- Full name-op aware mempool view: every name_new, name_firstupdate,&lt;br/&gt;  and name_update queued for the next block, bucketed by op kind.&lt;br/&gt;  &lt;a href=&#34;http://...onion:8080/mempool-name-ops&#34;&gt;http://...onion:8080/mempool-name-ops&lt;/a&gt;&lt;br/&gt;- Detection of ifa-0001 §&amp;#34;import&amp;#34; references between names, rendered&lt;br/&gt;  as clickable links — so you can walk a record&amp;#39;s import graph&lt;br/&gt;  without leaving the explorer.&lt;br/&gt;- d/&amp;lt;name&amp;gt; and id/&amp;lt;name&amp;gt; records Nostr blocks linked to NIP-19 npubs&lt;br/&gt;  (with njump.me deeplinks), the implied &amp;lt;localPart&amp;gt;@&amp;lt;host&amp;gt;.bit&lt;br/&gt;  NIP-05 identifier, and the publisher&amp;#39;s preferred relays.&lt;br/&gt;- Merge-mining-aware mining-summary: scans the parent Bitcoin&lt;br/&gt;  coinbase tag carried inside the auxpow blob (auxpow.tx.vin[0].coinbase),&lt;br/&gt;  so you actually see WHO mined the last 30 days of Namecoin — not&lt;br/&gt;  just &amp;#34;Unknown&amp;#34; the way most NMC explorers render it.&lt;br/&gt;&lt;br/&gt;Top NMC mining pools, last 30 days (4,321 blocks, snapshot at&lt;br/&gt;height 822,734 — refresh before posting if more than ~12 hours&lt;br/&gt;old):&lt;br/&gt;&lt;br/&gt;  1. AntPool         1347 blocks  (31.17%)&lt;br/&gt;  2. F2Pool           891 blocks  (20.62%)&lt;br/&gt;  3. ViaBTC           713 blocks  (16.50%)&lt;br/&gt;  4. SpiderPool       291 blocks  ( 6.73%)&lt;br/&gt;  5. SecPool          259 blocks  ( 5.99%)&lt;br/&gt;  6. Luxor            253 blocks  ( 5.86%)&lt;br/&gt;  7. Binance Pool     181 blocks  ( 4.19%)&lt;br/&gt;  8. Braiins Pool     108 blocks  ( 2.50%)&lt;br/&gt;  9. Ultimus Pool      35 blocks  ( 0.81%)&lt;br/&gt; 10. CloverPool        26 blocks  ( 0.60%)&lt;br/&gt;&lt;br/&gt;AntPool &#43; F2Pool &#43; ViaBTC alone mined 68% of all Namecoin blocks in&lt;br/&gt;the last 30 days.&lt;br/&gt;&lt;br/&gt;  See the full breakdown:&lt;br/&gt;  &lt;a href=&#34;http://6cbn4rskfdr647otej7gpqlmpqcmj723vg2eoeuu7ljbwu6cpdebozyd.onion:8080/mining-summary&#34;&gt;http://6cbn4rskfdr647otej7gpqlmpqcmj723vg2eoeuu7ljbwu6cpdebozyd.onion:8080/mining-summary&lt;/a&gt;&lt;br/&gt;&lt;br/&gt;Source: &lt;a href=&#34;https://github.com/mstrofnone/nmc-rpc-explorer&#34;&gt;https://github.com/mstrofnone/nmc-rpc-explorer&lt;/a&gt; (master)&lt;br/&gt;Upstream PR queue: namecoin/nmc-rpc-explorer #13–#18&lt;br/&gt;&lt;br/&gt;#namecoin #nostr #cypherpunk #mergemining #bitcoin #miner
    </content>
    <updated>2026-05-01T01:39:08Z</updated>
  </entry>

  <entry>
    <id>https://njump.me/nevent1qqsgmd0xvrz8c72x3emq85stxk8qh80qyrzq00c7v85enz6exes2zfgzypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60qeq23tf</id>
    
      <title type="html">📡 How to use relay.testls.bit — a Namecoin .bit-gated Nostr ...</title>
    
    <link rel="alternate" href="https://njump.me/nevent1qqsgmd0xvrz8c72x3emq85stxk8qh80qyrzq00c7v85enz6exes2zfgzypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60qeq23tf" />
    <content type="html">
      📡 How to use relay.testls.bit — a Namecoin .bit-gated Nostr relay&lt;br/&gt;&lt;br/&gt;🔗 wss://relay.testls.bit/&lt;br/&gt;&lt;br/&gt;🛡️ What makes it different&lt;br/&gt;   The relay only accepts events from pubkeys whose kind:0 metadata declares&lt;br/&gt;   a .bit NIP-05 identifier (e.g. _@yourname.bit, m@testls.bit). Verification&lt;br/&gt;   is done against Namecoin directly via ElectrumX — no DNS, no public CAs.&lt;br/&gt;&lt;br/&gt;🚀 To use it as a write relay you need:&lt;br/&gt;   1. A Namecoin .bit name (d/ namespace) you control&lt;br/&gt;   2. Set the .bit value to a JSON record with a &amp;#34;nostr&amp;#34; field mapping a&lt;br/&gt;      label to your hex pubkey, e.g.&lt;br/&gt;        {&amp;#34;nostr&amp;#34;:{&amp;#34;names&amp;#34;:{&amp;#34;_&amp;#34;:&amp;#34;&amp;lt;your-hex-pubkey&amp;gt;&amp;#34;}}}&lt;br/&gt;   3. Update your kind:0 metadata so &amp;#34;nip05&amp;#34; = &amp;#34;&amp;lt;label&amp;gt;@&amp;lt;yourname&amp;gt;.bit&amp;#34;&lt;br/&gt;   4. Add wss://relay.testls.bit/ to your client&amp;#39;s relay list&lt;br/&gt;&lt;br/&gt;📱 Native client support&lt;br/&gt;   Amethyst (Android &#43; iOS &#43; Desktop) has full .bit relay resolution behind&lt;br/&gt;   PR #2595: it queries Namecoin via ElectrumX, rewrites wss://*.bit/ to the&lt;br/&gt;   underlying real wss:// host or .onion, and pins TLS via Namecoin TLSA.&lt;br/&gt;   No client-side config needed beyond adding the relay URL.&lt;br/&gt;&lt;br/&gt;   &lt;a href=&#34;https://github.com/vitorpamplona/amethyst/pull/2595&#34;&gt;https://github.com/vitorpamplona/amethyst/pull/2595&lt;/a&gt;&lt;br/&gt;&lt;br/&gt;📡 Read-only access works for everyone&lt;br/&gt;   Even without a .bit identity you can subscribe with REQ and read the relay&lt;br/&gt;   freely. Only writes are gated.&lt;br/&gt;&lt;br/&gt;🔐 Why this matters&lt;br/&gt;   It&amp;#39;s a working demo of the cypherpunk thesis: name resolution and TLS&lt;br/&gt;   trust without ICANN, without public CAs, without DNS. Names are&lt;br/&gt;   blockchain-anchored and TLS is pinned via TLSA-on-Namecoin (DANE-TA).&lt;br/&gt;&lt;br/&gt;🌐 Browse it in your browser: &lt;a href=&#34;https://relay.testls.bit/&#34;&gt;https://relay.testls.bit/&lt;/a&gt;&lt;br/&gt;   (vanilla SPA, talks WSS back to the same host. Self-signed cert is&lt;br/&gt;   pinned via Namecoin TLSA.)&lt;br/&gt;   Go to &lt;a href=&#34;https://www.namecoin.org/download/&#34;&gt;https://www.namecoin.org/download/&lt;/a&gt; to figure out how to resolve&lt;br/&gt;   on your OS or in your browser&lt;br/&gt;&lt;br/&gt;#namecoin #nostr #cypherpunk #dotbit&lt;br/&gt;
    </content>
    <updated>2026-04-28T21:31:00Z</updated>
  </entry>

  <entry>
    <id>https://njump.me/nevent1qqswhp3etm6u9x4xc3jd3tv52q5nl8whzxqs0rf3mkj20watan0c2wqzypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60qlc58l9</id>
    
      <title type="html">📡 How to use relay.testls.bit — a Namecoin .bit-gated Nostr ...</title>
    
    <link rel="alternate" href="https://njump.me/nevent1qqswhp3etm6u9x4xc3jd3tv52q5nl8whzxqs0rf3mkj20watan0c2wqzypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60qlc58l9" />
    <content type="html">
      📡 How to use relay.testls.bit — a Namecoin .bit-gated Nostr relay&lt;br/&gt;&lt;br/&gt;🔗 wss://relay.testls.bit/&lt;br/&gt;&lt;br/&gt;🌐 Browse it in your browser: &lt;a href=&#34;https://relay.testls.bit/&#34;&gt;https://relay.testls.bit/&lt;/a&gt;&lt;br/&gt;   (vanilla SPA, talks WSS back to the same host. Self-signed cert — first&lt;br/&gt;   visit shows a warning. Click through; the cert is pinned via Namecoin TLSA.)&lt;br/&gt;&lt;br/&gt;🛡️ What makes it different&lt;br/&gt;   The relay only accepts events from pubkeys whose kind:0 metadata declares&lt;br/&gt;   a .bit NIP-05 identifier (e.g. _@yourname.bit, m@testls.bit). Verification&lt;br/&gt;   is done against Namecoin directly via ElectrumX — no DNS, no public CAs.&lt;br/&gt;&lt;br/&gt;🚀 To use it as a write relay you need:&lt;br/&gt;   1. A Namecoin .bit name (d/ namespace) you control&lt;br/&gt;   2. Set the .bit value to a JSON record with a &amp;#34;nostr&amp;#34; field mapping a&lt;br/&gt;      label to your hex pubkey, e.g.&lt;br/&gt;        {&amp;#34;nostr&amp;#34;:{&amp;#34;names&amp;#34;:{&amp;#34;_&amp;#34;:&amp;#34;&amp;lt;your-hex-pubkey&amp;gt;&amp;#34;}}}&lt;br/&gt;   3. Update your kind:0 metadata so &amp;#34;nip05&amp;#34; = &amp;#34;&amp;lt;label&amp;gt;@&amp;lt;yourname&amp;gt;.bit&amp;#34;&lt;br/&gt;   4. Add wss://relay.testls.bit/ to your client&amp;#39;s relay list&lt;br/&gt;&lt;br/&gt;📱 Native client support&lt;br/&gt;   Amethyst (Android &#43; iOS &#43; Desktop) has full .bit relay resolution behind&lt;br/&gt;   PR #2595: it queries Namecoin via ElectrumX, rewrites wss://*.bit/ to the&lt;br/&gt;   underlying real wss:// host or .onion, and pins TLS via Namecoin TLSA.&lt;br/&gt;   No client-side config needed beyond adding the relay URL.&lt;br/&gt;&lt;br/&gt;   &lt;a href=&#34;https://github.com/vitorpamplona/amethyst/pull/2595&#34;&gt;https://github.com/vitorpamplona/amethyst/pull/2595&lt;/a&gt;&lt;br/&gt;&lt;br/&gt;📡 Read-only access works for everyone&lt;br/&gt;   Even without a .bit identity you can subscribe with REQ and read the relay&lt;br/&gt;   freely. Only writes are gated.&lt;br/&gt;&lt;br/&gt;🔐 Why this matters&lt;br/&gt;   It&amp;#39;s a working demo of the cypherpunk thesis: name resolution and TLS&lt;br/&gt;   trust without ICANN, without public CAs, without DNS. Names are&lt;br/&gt;   blockchain-anchored and TLS is pinned via TLSA-on-Namecoin (DANE-TA).&lt;br/&gt;&lt;br/&gt;#namecoin #nostr #cypherpunk #dotbit&lt;br/&gt;
    </content>
    <updated>2026-04-28T21:18:43Z</updated>
  </entry>

  <entry>
    <id>https://njump.me/nevent1qqsrr5rs0gh8vql0u9uagvzmv2v5se43xav7gzd733r643yd0g0ntdgzypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60qz3k2yw</id>
    
      <title>Nostr event nevent1qqsrr5rs0gh8vql0u9uagvzmv2v5se43xav7gzd733r643yd0g0ntdgzypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60qz3k2yw</title>
    
    <link rel="alternate" href="https://njump.me/nevent1qqsrr5rs0gh8vql0u9uagvzmv2v5se43xav7gzd733r643yd0g0ntdgzypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60qz3k2yw" />
    <content type="html">
      hello gated .bit world from Amethyst round2
    </content>
    <updated>2026-04-28T07:45:18Z</updated>
  </entry>

  <entry>
    <id>https://njump.me/nevent1qqsz3lk6vf4vcjfgzvw3eqgt5vd5c5hu7fn567wp36xxmla67hk533czypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60qgn0n9u</id>
    
      <title>Nostr event nevent1qqsz3lk6vf4vcjfgzvw3eqgt5vd5c5hu7fn567wp36xxmla67hk533czypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60qgn0n9u</title>
    
    <link rel="alternate" href="https://njump.me/nevent1qqsz3lk6vf4vcjfgzvw3eqgt5vd5c5hu7fn567wp36xxmla67hk533czypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60qgn0n9u" />
    <content type="html">
      hello gated .bit world from _@mstrofnone.bit
    </content>
    <updated>2026-04-28T07:42:52Z</updated>
  </entry>

  <entry>
    <id>https://njump.me/nevent1qqs0eqa96hvwgkqat98snjx2wtua8ym65mhdw8zxsuw2pq42kl0kc0gzypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60q5wk2cw</id>
    
      <title>Nostr event nevent1qqs0eqa96hvwgkqat98snjx2wtua8ym65mhdw8zxsuw2pq42kl0kc0gzypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60q5wk2cw</title>
    
    <link rel="alternate" href="https://njump.me/nevent1qqs0eqa96hvwgkqat98snjx2wtua8ym65mhdw8zxsuw2pq42kl0kc0gzypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60q5wk2cw" />
    <content type="html">
      hello gated .bit world
    </content>
    <updated>2026-04-28T07:35:12Z</updated>
  </entry>

  <entry>
    <id>https://njump.me/nevent1qqsfkr7aup09jshu5u0jntsvr2taahjgdpx77pe606epf37udfmnvuqzypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60qtkfnvd</id>
    
      <title type="html">follow-up patch adds WebSocket (WSS) transport — enables ...</title>
    
    <link rel="alternate" href="https://njump.me/nevent1qqsfkr7aup09jshu5u0jntsvr2taahjgdpx77pe606epf37udfmnvuqzypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60qtkfnvd" />
    <content type="html">
      In reply to &lt;a href=&#39;/nevent1qqsxwm9uu4rzhf2r87y6r005ltsar23dreyjq48kr9sk5mkmxl5pduch99x66&#39;&gt;nevent1q…9x66&lt;/a&gt;&lt;br/&gt;_________________________&lt;br/&gt;&lt;br/&gt;follow-up patch adds WebSocket (WSS) transport — enables browser/wasm use of nip05/namecoin and works on networks where raw TCP is blocked. same pinned certs, same RPC, just different framing.&lt;blockquote class=&#34;border-l-05rem border-l-strongpink border-solid&#34;&gt;&lt;div class=&#34;-ml-4 bg-gradient-to-r from-gray-100 dark:from-zinc-800 to-transparent mr-0 mt-0 mb-4 pl-4 pr-2 py-2&#34;&gt;quoting  &lt;span itemprop=&#34;mentions&#34; itemscope itemtype=&#34;https://schema.org/Article&#34;&gt;&lt;a itemprop=&#34;url&#34; href=&#34;/nevent1qqsytgl9hh9qkn5xp9l7xf2sjm4z4ksajns8uwnqpgu3ve3aktavxsqpp4mhxue69uhkummn9ekx7mqpzemhxue69uhhyetvv9ujuurjd9kkzmpwdejhgqg0waehxw309ahx7um5wghx6mmdqy28wumn8ghj7un9d3shjtnwva5hgtnyv4mqzynhwden5te0va5hgmn0wd68ytnrdaksygzrrp0dajm8tzfgyjc6x7jh70jq07779md8yqdrs2dcea9603d57qsflk5q&#34; class=&#34;bg-lavender dark:prose:text-neutral-50 dark:text-neutral-50 dark:bg-garnet px-1&#34;&gt;nevent1q…lk5q&lt;/a&gt;&lt;/span&gt; &lt;/div&gt; From d307275490adbc6b012399e2d5200c4b963a4ba6 Mon Sep 17 00:00:00 2001&lt;br/&gt;From: M &lt;m@Ms-MacBook-Pro.local&gt;&lt;br/&gt;Date: Sun, 19 Apr 2026 21:57:33 &#43;1000&lt;br/&gt;Subject: [PATCH] feat(nip05/namecoin): add WebSocket (WSS) transport&lt;br/&gt;&lt;br/&gt;Adds WS/WSS as an alternative transport to TCP&#43;TLS for ElectrumX&lt;br/&gt;name resolution. Enables browser/wasm use of nip05/namecoin and&lt;br/&gt;improves resilience on networks where raw TCP is blocked.&lt;br/&gt;&lt;br/&gt;New: Transport enum on ElectrumxServer, DefaultElectrumXServersWSS,&lt;br/&gt;WebSocket client via github.com/coder/websocket (zero transitive&lt;br/&gt;deps, already a transitive dep of nostrlib). Pinned-cert TLS trust&lt;br/&gt;is shared between TCP&#43;TLS and WSS \u2014 the public operators serve the&lt;br/&gt;same certificate on the adjacent ports (:50002 / :50004 on testls,&lt;br/&gt;:57002 / :57004 on nmc2.bitcoins.sk).&lt;br/&gt;&lt;br/&gt;Zero API break: the new Transport field on ElectrumxServer is a&lt;br/&gt;zero-valued enum that preserves the v1 UseSSL semantics. Every&lt;br/&gt;call site from the previous patch compiles and behaves unchanged.&lt;br/&gt;&lt;br/&gt;Tests: new unit test stands up an httptest WebSocket server via&lt;br/&gt;coder/websocket&#39;s accept helper and exercises the whole dial \u2192&lt;br/&gt;read \u2192 parse flow over WS framing, offline. Integration tests&lt;br/&gt;(build tag integration) add two WSS cases against the live public&lt;br/&gt;servers on :50004, mirroring the existing TCP test fixtures.&lt;br/&gt;&lt;br/&gt;Follow-up to the patch event at&lt;br/&gt;&lt;span itemprop=&#34;mentions&#34; itemscope itemtype=&#34;https://schema.org/Article&#34;&gt;&lt;a itemprop=&#34;url&#34; href=&#34;/nevent1qqs8yepuma694y6saym8ny4wtfzymlgu2htusvweyjzpamc0rgn8pyq&#34; class=&#34;bg-lavender dark:prose:text-neutral-50 dark:text-neutral-50 dark:bg-garnet px-1&#34;&gt;nevent1q…8pyq&lt;/a&gt;&lt;/span&gt;&lt;br/&gt;(original subpackage). Rebase-clean on top of it.&lt;br/&gt;&lt;br/&gt;Signed-off-by: M &lt;m@Ms-MacBook-Pro.local&gt;&lt;br/&gt;---&lt;br/&gt; nip05/namecoin/doc.go                        |   8 &#43;-&lt;br/&gt; nip05/namecoin/electrumx.go                  | 139 &#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;----&lt;br/&gt; nip05/namecoin/electrumx_integration_test.go |  50 &#43;&#43;&#43;&#43;&#43;&lt;br/&gt; nip05/namecoin/servers.go                    |  70 &#43;&#43;&#43;&#43;&#43;&#43;&#43;&lt;br/&gt; nip05/namecoin/websocket.go                  | 105 &#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&lt;br/&gt; nip05/namecoin/websocket_test.go             | 195 &#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&#43;&lt;br/&gt; 6 files changed, 524 insertions(&#43;), 43 deletions(-)&lt;br/&gt; create mode 100644 nip05/namecoin/websocket.go&lt;br/&gt; create mode 100644 nip05/namecoin/websocket_test.go&lt;br/&gt;&lt;br/&gt;diff --git a/nip05/namecoin/doc.go b/nip05/namecoin/doc.go&lt;br/&gt;index 7189a38..82bbce2 100644&lt;br/&gt;--- a/nip05/namecoin/doc.go&lt;br/&gt;&#43;&#43;&#43; b/nip05/namecoin/doc.go&lt;br/&gt;@@ -28,6 &#43;28,10 @@&lt;br/&gt; //	    // ...&lt;br/&gt; //	}&lt;br/&gt; //&lt;br/&gt;-// No external dependencies beyond the Go standard library and the&lt;br/&gt;-// fiatjaf.com/nostr types.&lt;br/&gt;&#43;// Two transports are supported: raw TCP&#43;TLS (the default, selected&lt;br/&gt;&#43;// by the zero value of ElectrumxServer.Transport) and WebSocket over&lt;br/&gt;&#43;// TLS (TransportWSS). The WSS path uses github.com/coder/websocket —&lt;br/&gt;&#43;// a zero-transitive-dep library that also compiles cleanly under&lt;br/&gt;&#43;// GOOS=js GOARCH=wasm, enabling browser use. Pinned-cert trust is&lt;br/&gt;&#43;// shared between the two transports.&lt;br/&gt; package namecoin&lt;br/&gt;diff --git a/nip05/namecoin/electrumx.go b/nip05/namecoin/electrumx.go&lt;br/&gt;index 4fbabdb..b7757d5 100644&lt;br/&gt;--- a/nip05/namecoin/electrumx.go&lt;br/&gt;&#43;&#43;&#43; b/nip05/namecoin/electrumx.go&lt;br/&gt;@@ -42,9 &#43;42,24 @@ var (&lt;br/&gt; 	ErrServersUnreachable = errors.New(&#34;namecoin: all ElectrumX servers unreachable&#34;)&lt;br/&gt; )&lt;br/&gt; &lt;br/&gt;&#43;// rpcConn is the transport-agnostic RPC connection abstraction. Both&lt;br/&gt;&#43;// TCP (newline-delimited) and WebSocket (pre-framed) implementations&lt;br/&gt;&#43;// satisfy it so that the name_show flow can be written once.&lt;br/&gt;&#43;type rpcConn interface {&lt;br/&gt;&#43;	// writeRequest serialises and sends a single JSON-RPC request.&lt;br/&gt;&#43;	// Implementations are responsible for any framing the wire format&lt;br/&gt;&#43;	// requires (TCP appends a newline, WS does not).&lt;br/&gt;&#43;	writeRequest(ctx context.Context, method string, params []any, id int64) error&lt;br/&gt;&#43;	// readResponse returns one JSON-RPC response, blocking until one&lt;br/&gt;&#43;	// is available or the context/deadline fires.&lt;br/&gt;&#43;	readResponse(ctx context.Context) (string, error)&lt;br/&gt;&#43;	// close releases the underlying transport.&lt;br/&gt;&#43;	close() error&lt;br/&gt;&#43;}&lt;br/&gt;&#43;&lt;br/&gt; // ElectrumClient is a minimal, query-only Namecoin ElectrumX client.&lt;br/&gt;-// It opens a short-lived TCP/TLS socket per request, which is plenty&lt;br/&gt;-// for interactive CLI use.&lt;br/&gt;&#43;// It opens a short-lived socket per request, which is plenty for&lt;br/&gt;&#43;// interactive CLI use.&lt;br/&gt; type ElectrumClient struct {&lt;br/&gt; 	ConnectTimeout time.Duration&lt;br/&gt; 	ReadTimeout    time.Duration&lt;br/&gt;@@ -68,18 &#43;83,22 @@ func (c *ElectrumClient) NameShow(ctx context.Context, identifier string, server&lt;br/&gt; 	if err != nil {&lt;br/&gt; 		return nil, err&lt;br/&gt; 	}&lt;br/&gt;-	defer conn.Close()&lt;br/&gt;&#43;	defer conn.close()&lt;br/&gt; &lt;br/&gt;-	_ = conn.SetDeadline(time.Now().Add(c.ReadTimeout))&lt;br/&gt;&#43;	// Give the whole request sequence a deadline. For TCP this is&lt;br/&gt;&#43;	// enforced by net.Conn.SetDeadline; for WS the per-call context&lt;br/&gt;&#43;	// carries the budget instead.&lt;br/&gt;&#43;	reqCtx, cancel := context.WithTimeout(ctx, c.ReadTimeout)&lt;br/&gt;&#43;	defer cancel()&lt;br/&gt; &lt;br/&gt;-	reader := bufio.NewReader(conn)&lt;br/&gt;&#43;	next := func() int64 { return c.requestID.Add(1) }&lt;br/&gt; &lt;br/&gt; 	// 1. Negotiate protocol version. The response is consumed and&lt;br/&gt; 	//    discarded — we only care that the socket is alive.&lt;br/&gt;-	if err := c.sendRPC(conn, &#34;server.version&#34;, []any{&#34;nak-namecoin/0.1&#34;, electrumProtocolVersion}); err != nil {&lt;br/&gt;&#43;	if err := conn.writeRequest(reqCtx, &#34;server.version&#34;, []any{&#34;nak-namecoin/0.1&#34;, electrumProtocolVersion}, next()); err != nil {&lt;br/&gt; 		return nil, err&lt;br/&gt; 	}&lt;br/&gt;-	if _, err := reader.ReadString(&#39;\n&#39;); err != nil {&lt;br/&gt;&#43;	if _, err := conn.readResponse(reqCtx); err != nil {&lt;br/&gt; 		return nil, fmt.Errorf(&#34;namecoin: read version response: %w&#34;, err)&lt;br/&gt; 	}&lt;br/&gt; &lt;br/&gt;@@ -88,10 &#43;107,10 @@ func (c *ElectrumClient) NameShow(ctx context.Context, identifier string, server&lt;br/&gt; 	scriptHash := electrumScriptHash(script)&lt;br/&gt; &lt;br/&gt; 	// 3. Fetch transaction history for that scripthash.&lt;br/&gt;-	if err := c.sendRPC(conn, &#34;blockchain.scripthash.get_history&#34;, []any{scriptHash}); err != nil {&lt;br/&gt;&#43;	if err := conn.writeRequest(reqCtx, &#34;blockchain.scripthash.get_history&#34;, []any{scriptHash}, next()); err != nil {&lt;br/&gt; 		return nil, err&lt;br/&gt; 	}&lt;br/&gt;-	histLine, err := reader.ReadString(&#39;\n&#39;)&lt;br/&gt;&#43;	histLine, err := conn.readResponse(reqCtx)&lt;br/&gt; 	if err != nil {&lt;br/&gt; 		return nil, fmt.Errorf(&#34;namecoin: read history response: %w&#34;, err)&lt;br/&gt; 	}&lt;br/&gt;@@ -108,19 &#43;127,19 @@ func (c *ElectrumClient) NameShow(ctx context.Context, identifier string, server&lt;br/&gt; 	latest := entries[len(entries)-1]&lt;br/&gt; &lt;br/&gt; 	// 4. Fetch the verbose transaction.&lt;br/&gt;-	if err := c.sendRPC(conn, &#34;blockchain.transaction.get&#34;, []any{latest.TxHash, true}); err != nil {&lt;br/&gt;&#43;	if err := conn.writeRequest(reqCtx, &#34;blockchain.transaction.get&#34;, []any{latest.TxHash, true}, next()); err != nil {&lt;br/&gt; 		return nil, err&lt;br/&gt; 	}&lt;br/&gt;-	txLine, err := reader.ReadString(&#39;\n&#39;)&lt;br/&gt;&#43;	txLine, err := conn.readResponse(reqCtx)&lt;br/&gt; 	if err != nil {&lt;br/&gt; 		return nil, fmt.Errorf(&#34;namecoin: read transaction response: %w&#34;, err)&lt;br/&gt; 	}&lt;br/&gt; &lt;br/&gt; 	// 5. Get the current block height so we can compute expiry.&lt;br/&gt;-	if err := c.sendRPC(conn, &#34;blockchain.headers.subscribe&#34;, []any{}); err != nil {&lt;br/&gt;&#43;	if err := conn.writeRequest(reqCtx, &#34;blockchain.headers.subscribe&#34;, []any{}, next()); err != nil {&lt;br/&gt; 		return nil, err&lt;br/&gt; 	}&lt;br/&gt;-	headerLine, _ := reader.ReadString(&#39;\n&#39;)&lt;br/&gt;&#43;	headerLine, _ := conn.readResponse(reqCtx)&lt;br/&gt; 	currentHeight := parseBlockHeight(headerLine)&lt;br/&gt; &lt;br/&gt; 	if currentHeight &gt; 0 &amp;&amp; latest.Height &gt; 0 {&lt;br/&gt;@@ -161,10 &#43;180,23 @@ func (c *ElectrumClient) NameShowWithFallback(ctx context.Context, identifier st&lt;br/&gt; 	return nil, fmt.Errorf(&#34;%w: last error: %v&#34;, ErrServersUnreachable, lastErr)&lt;br/&gt; }&lt;br/&gt; &lt;br/&gt;-// dial opens a TCP connection to the server, upgrading to TLS when&lt;br/&gt;-// UseSSL is set. Honours both context cancellation and our connect&lt;br/&gt;-// timeout, whichever fires first.&lt;br/&gt;-func (c *ElectrumClient) dial(ctx context.Context, server ElectrumxServer) (net.Conn, error) {&lt;br/&gt;&#43;// dial picks the right transport implementation based on the server&lt;br/&gt;&#43;// configuration and returns a ready-to-use rpcConn.&lt;br/&gt;&#43;func (c *ElectrumClient) dial(ctx context.Context, server ElectrumxServer) (rpcConn, error) {&lt;br/&gt;&#43;	switch effectiveTransport(server) {&lt;br/&gt;&#43;	case TransportTCPTLS, TransportTCP:&lt;br/&gt;&#43;		return c.dialTCP(ctx, server)&lt;br/&gt;&#43;	case TransportWSS, TransportWS:&lt;br/&gt;&#43;		return c.dialWebSocket(ctx, server)&lt;br/&gt;&#43;	default:&lt;br/&gt;&#43;		return nil, fmt.Errorf(&#34;namecoin: unknown transport %d&#34;, server.Transport)&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;}&lt;br/&gt;&#43;&lt;br/&gt;&#43;// dialTCP opens a raw TCP connection to the server, upgrading to TLS&lt;br/&gt;&#43;// when the effective transport is TCPTLS. Honours both context&lt;br/&gt;&#43;// cancellation and our connect timeout, whichever fires first.&lt;br/&gt;&#43;func (c *ElectrumClient) dialTCP(ctx context.Context, server ElectrumxServer) (rpcConn, error) {&lt;br/&gt; 	dialer := &amp;net.Dialer{Timeout: c.ConnectTimeout}&lt;br/&gt; 	address := net.JoinHostPort(server.Host, strconv.Itoa(server.Port))&lt;br/&gt; &lt;br/&gt;@@ -173,34 &#43;205,41 @@ func (c *ElectrumClient) dial(ctx context.Context, server ElectrumxServer) (net.&lt;br/&gt; 		return nil, fmt.Errorf(&#34;namecoin: dial %s: %w&#34;, address, err)&lt;br/&gt; 	}&lt;br/&gt; &lt;br/&gt;-	if !server.UseSSL {&lt;br/&gt;-		return raw, nil&lt;br/&gt;&#43;	var nc net.Conn = raw&lt;br/&gt;&#43;	if effectiveTransport(server) == TransportTCPTLS {&lt;br/&gt;&#43;		cfg := tlsConfigFor(server)&lt;br/&gt;&#43;		tlsConn := tls.Client(raw, cfg)&lt;br/&gt;&#43;&lt;br/&gt;&#43;		// Run the handshake with a deadline so a silent server doesn&#39;t hang&lt;br/&gt;&#43;		// the call beyond what the caller asked for.&lt;br/&gt;&#43;		if deadline, ok := ctx.Deadline(); ok {&lt;br/&gt;&#43;			_ = tlsConn.SetDeadline(deadline)&lt;br/&gt;&#43;		} else {&lt;br/&gt;&#43;			_ = tlsConn.SetDeadline(time.Now().Add(c.ConnectTimeout))&lt;br/&gt;&#43;		}&lt;br/&gt;&#43;		if err := tlsConn.HandshakeContext(ctx); err != nil {&lt;br/&gt;&#43;			raw.Close()&lt;br/&gt;&#43;			return nil, fmt.Errorf(&#34;namecoin: TLS handshake with %s: %w&#34;, address, err)&lt;br/&gt;&#43;		}&lt;br/&gt;&#43;		// Clear the handshake deadline — we&#39;ll set fresh per-request&lt;br/&gt;&#43;		// deadlines below.&lt;br/&gt;&#43;		_ = tlsConn.SetDeadline(time.Time{})&lt;br/&gt;&#43;		nc = tlsConn&lt;br/&gt; 	}&lt;br/&gt; &lt;br/&gt;-	cfg := tlsConfigFor(server)&lt;br/&gt;-	tlsConn := tls.Client(raw, cfg)&lt;br/&gt;&#43;	_ = nc.SetDeadline(time.Now().Add(c.ReadTimeout))&lt;br/&gt;&#43;	return &amp;tcpRPCConn{conn: nc, reader: bufio.NewReader(nc)}, nil&lt;br/&gt;&#43;}&lt;br/&gt; &lt;br/&gt;-	// Run the handshake with a deadline so a silent server doesn&#39;t hang&lt;br/&gt;-	// the call beyond what the caller asked for.&lt;br/&gt;-	if deadline, ok := ctx.Deadline(); ok {&lt;br/&gt;-		_ = tlsConn.SetDeadline(deadline)&lt;br/&gt;-	} else {&lt;br/&gt;-		_ = tlsConn.SetDeadline(time.Now().Add(c.ConnectTimeout))&lt;br/&gt;-	}&lt;br/&gt;-	if err := tlsConn.HandshakeContext(ctx); err != nil {&lt;br/&gt;-		raw.Close()&lt;br/&gt;-		return nil, fmt.Errorf(&#34;namecoin: TLS handshake with %s: %w&#34;, address, err)&lt;br/&gt;-	}&lt;br/&gt;-	// Clear the handshake deadline — the caller sets its own read&lt;br/&gt;-	// deadline afterwards.&lt;br/&gt;-	_ = tlsConn.SetDeadline(time.Time{})&lt;br/&gt;-	return tlsConn, nil&lt;br/&gt;&#43;// tcpRPCConn is the newline-delimited JSON-RPC transport over raw&lt;br/&gt;&#43;// TCP or TCP&#43;TLS. This matches the shape every Electrum / ElectrumX&lt;br/&gt;&#43;// client has used for the last decade.&lt;br/&gt;&#43;type tcpRPCConn struct {&lt;br/&gt;&#43;	conn   net.Conn&lt;br/&gt;&#43;	reader *bufio.Reader&lt;br/&gt; }&lt;br/&gt; &lt;br/&gt;-// sendRPC writes a JSON-RPC 2.0 request (newline-terminated, per&lt;br/&gt;-// Electrum&#39;s line-delimited protocol) to the connection.&lt;br/&gt;-func (c *ElectrumClient) sendRPC(w net.Conn, method string, params []any) error {&lt;br/&gt;-	id := c.requestID.Add(1)&lt;br/&gt;&#43;func (t *tcpRPCConn) writeRequest(ctx context.Context, method string, params []any, id int64) error {&lt;br/&gt; 	payload := map[string]any{&lt;br/&gt; 		&#34;jsonrpc&#34;: &#34;2.0&#34;,&lt;br/&gt; 		&#34;id&#34;:      id,&lt;br/&gt;@@ -212,12 &#43;251,30 @@ func (c *ElectrumClient) sendRPC(w net.Conn, method string, params []any) error&lt;br/&gt; 		return fmt.Errorf(&#34;namecoin: marshal rpc request: %w&#34;, err)&lt;br/&gt; 	}&lt;br/&gt; 	encoded = append(encoded, &#39;\n&#39;)&lt;br/&gt;-	if _, err := w.Write(encoded); err != nil {&lt;br/&gt;&#43;	if deadline, ok := ctx.Deadline(); ok {&lt;br/&gt;&#43;		_ = t.conn.SetWriteDeadline(deadline)&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;	if _, err := t.conn.Write(encoded); err != nil {&lt;br/&gt; 		return fmt.Errorf(&#34;namecoin: write rpc request: %w&#34;, err)&lt;br/&gt; 	}&lt;br/&gt; 	return nil&lt;br/&gt; }&lt;br/&gt; &lt;br/&gt;&#43;func (t *tcpRPCConn) readResponse(ctx context.Context) (string, error) {&lt;br/&gt;&#43;	if deadline, ok := ctx.Deadline(); ok {&lt;br/&gt;&#43;		_ = t.conn.SetReadDeadline(deadline)&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;	line, err := t.reader.ReadString(&#39;\n&#39;)&lt;br/&gt;&#43;	if err != nil {&lt;br/&gt;&#43;		return &#34;&#34;, err&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;	return line, nil&lt;br/&gt;&#43;}&lt;br/&gt;&#43;&lt;br/&gt;&#43;func (t *tcpRPCConn) close() error {&lt;br/&gt;&#43;	return t.conn.Close()&lt;br/&gt;&#43;}&lt;br/&gt;&#43;&lt;br/&gt; // historyEntry is one row of `blockchain.scripthash.get_history`.&lt;br/&gt; type historyEntry struct {&lt;br/&gt; 	TxHash string&lt;br/&gt;diff --git a/nip05/namecoin/electrumx_integration_test.go b/nip05/namecoin/electrumx_integration_test.go&lt;br/&gt;index 1458d4d..64ac17c 100644&lt;br/&gt;--- a/nip05/namecoin/electrumx_integration_test.go&lt;br/&gt;&#43;&#43;&#43; b/nip05/namecoin/electrumx_integration_test.go&lt;br/&gt;@@ -49,3 &#43;49,53 @@ func TestIntegration_ResolveAtTestlsBit(t *testing.T) {&lt;br/&gt; 		t.Errorf(&#34;m@testls.bit pubkey = %s, want %s&#34;, got, testlsMPubkey)&lt;br/&gt; 	}&lt;br/&gt; }&lt;br/&gt;&#43;&lt;br/&gt;&#43;// --- WSS (WebSocket over TLS) integration tests -----------------------&lt;br/&gt;&#43;//&lt;br/&gt;&#43;// These hit the same ElectrumX operators as the TCP tests above, but&lt;br/&gt;&#43;// over the WebSocket endpoints (ports 500xx&#43;2 on testls, 570xx&#43;2 on&lt;br/&gt;&#43;// nmc2.bitcoins.sk). Same pinned certs, same JSON-RPC protocol, just&lt;br/&gt;&#43;// different framing. The assertions match the TCP path because the&lt;br/&gt;&#43;// Namecoin blockchain is the source of truth.&lt;br/&gt;&#43;&lt;br/&gt;&#43;func TestIntegration_ResolveTestlsBit_WSS(t *testing.T) {&lt;br/&gt;&#43;	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)&lt;br/&gt;&#43;	defer cancel()&lt;br/&gt;&#43;&lt;br/&gt;&#43;	client := NewElectrumClient()&lt;br/&gt;&#43;	result, err := client.NameShowWithFallback(ctx, &#34;d/testls&#34;, DefaultElectrumXServersWSS)&lt;br/&gt;&#43;	if err != nil {&lt;br/&gt;&#43;		t.Fatalf(&#34;NameShowWithFallback(d/testls, WSS): %v&#34;, err)&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;	if result == nil {&lt;br/&gt;&#43;		t.Fatal(&#34;nil result&#34;)&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;	pk, _, err := extractNostrFromValue(result.Value, &amp;parsedIdentifier{&#34;d/testls&#34;, &#34;_&#34;, true})&lt;br/&gt;&#43;	if err != nil {&lt;br/&gt;&#43;		t.Fatalf(&#34;extractNostrFromValue: %v&#34;, err)&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;	if pk != testlsRootPubkey {&lt;br/&gt;&#43;		t.Errorf(&#34;testls.bit (WSS) pubkey = %s, want %s&#34;, pk, testlsRootPubkey)&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;}&lt;br/&gt;&#43;&lt;br/&gt;&#43;func TestIntegration_ResolveAtTestlsBit_WSS(t *testing.T) {&lt;br/&gt;&#43;	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)&lt;br/&gt;&#43;	defer cancel()&lt;br/&gt;&#43;&lt;br/&gt;&#43;	client := NewElectrumClient()&lt;br/&gt;&#43;	result, err := client.NameShowWithFallback(ctx, &#34;d/testls&#34;, DefaultElectrumXServersWSS)&lt;br/&gt;&#43;	if err != nil {&lt;br/&gt;&#43;		t.Fatalf(&#34;NameShowWithFallback(d/testls, WSS): %v&#34;, err)&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;	if result == nil {&lt;br/&gt;&#43;		t.Fatal(&#34;nil result&#34;)&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;	pk, _, err := extractNostrFromValue(result.Value, &amp;parsedIdentifier{&#34;d/testls&#34;, &#34;m&#34;, true})&lt;br/&gt;&#43;	if err != nil {&lt;br/&gt;&#43;		t.Fatalf(&#34;extractNostrFromValue: %v&#34;, err)&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;	if pk != testlsMPubkey {&lt;br/&gt;&#43;		t.Errorf(&#34;m@testls.bit (WSS) pubkey = %s, want %s&#34;, pk, testlsMPubkey)&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;}&lt;br/&gt;diff --git a/nip05/namecoin/servers.go b/nip05/namecoin/servers.go&lt;br/&gt;index b76c889..71c8551 100644&lt;br/&gt;--- a/nip05/namecoin/servers.go&lt;br/&gt;&#43;&#43;&#43; b/nip05/namecoin/servers.go&lt;br/&gt;@@ -1,15 &#43;1,59 @@&lt;br/&gt; package namecoin&lt;br/&gt; &lt;br/&gt;&#43;// Transport selects how an ElectrumX server is dialed. The zero value&lt;br/&gt;&#43;// is TransportTCPTLS, matching the traditional Electrum client path&lt;br/&gt;&#43;// and the behaviour shipped in v0.1.x. Callers that want WebSocket&lt;br/&gt;&#43;// (for example, browser/wasm targets or restricted networks that&lt;br/&gt;&#43;// block raw TCP) set this to TransportWSS.&lt;br/&gt;&#43;type Transport int&lt;br/&gt;&#43;&lt;br/&gt;&#43;const (&lt;br/&gt;&#43;	// TransportTCPTLS is raw TCP &#43; TLS with newline-delimited JSON-RPC.&lt;br/&gt;&#43;	// This is the default and what most Namecoin ElectrumX clients use.&lt;br/&gt;&#43;	TransportTCPTLS Transport = iota&lt;br/&gt;&#43;	// TransportTCP is plaintext TCP — rarely used in practice but&lt;br/&gt;&#43;	// supported for completeness / local testing.&lt;br/&gt;&#43;	TransportTCP&lt;br/&gt;&#43;	// TransportWSS is WebSocket over TLS, using the ElectrumX WS&lt;br/&gt;&#43;	// endpoint (ports 500xx&#43;2 on typical public servers). Messages&lt;br/&gt;&#43;	// are pre-framed by the WebSocket layer and MUST NOT carry a&lt;br/&gt;&#43;	// trailing newline.&lt;br/&gt;&#43;	TransportWSS&lt;br/&gt;&#43;	// TransportWS is plaintext WebSocket.&lt;br/&gt;&#43;	TransportWS&lt;br/&gt;&#43;)&lt;br/&gt;&#43;&lt;br/&gt; // ElectrumxServer is a single Namecoin ElectrumX endpoint.&lt;br/&gt; type ElectrumxServer struct {&lt;br/&gt; 	Host string&lt;br/&gt; 	Port int&lt;br/&gt; 	// UseSSL indicates TLS should be negotiated over the raw socket.&lt;br/&gt;&#43;	// Kept for backwards compat with v0.1.x callers. When Transport&lt;br/&gt;&#43;	// is the zero value, UseSSL selects between TransportTCPTLS&lt;br/&gt;&#43;	// (UseSSL=true) and TransportTCP (UseSSL=false).&lt;br/&gt; 	UseSSL bool&lt;br/&gt; 	// UsePinnedTrustStore enables the pinned-cert trust anchor bundle&lt;br/&gt; 	// for servers that present self-signed certificates. This is the&lt;br/&gt; 	// norm for the public Namecoin ElectrumX ecosystem.&lt;br/&gt; 	UsePinnedTrustStore bool&lt;br/&gt;&#43;	// Transport selects the dial transport. Zero value keeps v0.1.x&lt;br/&gt;&#43;	// semantics: if UseSSL is true it&#39;s TCP&#43;TLS, otherwise plain TCP.&lt;br/&gt;&#43;	// Set explicitly to TransportWSS / TransportWS for WebSocket.&lt;br/&gt;&#43;	Transport Transport&lt;br/&gt;&#43;}&lt;br/&gt;&#43;&lt;br/&gt;&#43;// effectiveTransport resolves the transport to use for a server,&lt;br/&gt;&#43;// reconciling the legacy UseSSL bool with the explicit Transport&lt;br/&gt;&#43;// field. The explicit Transport wins when non-zero.&lt;br/&gt;&#43;func effectiveTransport(s ElectrumxServer) Transport {&lt;br/&gt;&#43;	if s.Transport != TransportTCPTLS {&lt;br/&gt;&#43;		return s.Transport&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;	// Zero value: fall back to UseSSL for v0.1.x compatibility.&lt;br/&gt;&#43;	if s.UseSSL {&lt;br/&gt;&#43;		return TransportTCPTLS&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;	return TransportTCP&lt;br/&gt; }&lt;br/&gt; &lt;br/&gt; // DefaultElectrumXServers is the built-in list of public Namecoin&lt;br/&gt;@@ -24,11 &#43;68,37 @@ var DefaultElectrumXServers = []ElectrumxServer{&lt;br/&gt; 	{Host: &#34;46.229.238.187&#34;, Port: 57002, UseSSL: true, UsePinnedTrustStore: true},&lt;br/&gt; }&lt;br/&gt; &lt;br/&gt;&#43;// DefaultElectrumXServersWSS is the WSS-preferred server list. It&lt;br/&gt;&#43;// points at the same operators as DefaultElectrumXServers but uses&lt;br/&gt;&#43;// their WebSocket-over-TLS endpoints. Useful for:&lt;br/&gt;&#43;//&lt;br/&gt;&#43;//   - Browser / wasm targets, where raw TCP is unavailable and the&lt;br/&gt;&#43;//     only viable transport is the browser&#39;s WebSocket API (which&lt;br/&gt;&#43;//     `github.com/coder/websocket` targets natively when compiled&lt;br/&gt;&#43;//     with GOOS=js GOARCH=wasm).&lt;br/&gt;&#43;//   - Restricted networks that block the traditional ElectrumX ports&lt;br/&gt;&#43;//     but allow outbound HTTPS/WSS.&lt;br/&gt;&#43;//   - Environments that prefer WSS on policy grounds (aligns with the&lt;br/&gt;&#43;//     broader Nostr ecosystem, which is WSS-everywhere).&lt;br/&gt;&#43;//&lt;br/&gt;&#43;// Ports are the ElectrumX convention of ELECTRUM_PORT&#43;2 for the WSS&lt;br/&gt;&#43;// endpoint. Both listed operators expose these alongside their&lt;br/&gt;&#43;// TCP&#43;TLS ports, sharing the same TLS certificate.&lt;br/&gt;&#43;var DefaultElectrumXServersWSS = []ElectrumxServer{&lt;br/&gt;&#43;	{Host: &#34;electrumx.testls.space&#34;, Port: 50004, Transport: TransportWSS, UsePinnedTrustStore: true},&lt;br/&gt;&#43;	{Host: &#34;nmc2.bitcoins.sk&#34;, Port: 57004, Transport: TransportWSS, UsePinnedTrustStore: true},&lt;br/&gt;&#43;	{Host: &#34;46.229.238.187&#34;, Port: 57004, Transport: TransportWSS, UsePinnedTrustStore: true},&lt;br/&gt;&#43;}&lt;br/&gt;&#43;&lt;br/&gt; // PinnedElectrumXCerts is the PEM-encoded bundle of server&lt;br/&gt; // certificates we trust in addition to the system roots. These are&lt;br/&gt; // copied verbatim from the Kotlin Amethyst reference implementation.&lt;br/&gt; //&lt;br/&gt; // To refresh: `echo | openssl s_client -connect HOST:PORT 2&gt;/dev/null | openssl x509 -outform PEM`&lt;br/&gt;&#43;//&lt;br/&gt;&#43;// The same certificates are served on the WSS endpoints (adjacent&lt;br/&gt;&#43;// ports on the same host), so a single pinned bundle covers both&lt;br/&gt;&#43;// transports.&lt;br/&gt; var PinnedElectrumXCerts = []string{&lt;br/&gt; 	// electrumx.testls.space:50002 — expires 2027-05-04.&lt;br/&gt; 	// Also covers the i665jpwsq46zlsdbnj4axgzd3s56uzey5uhotsnxzsknzbn36jaddsid.onion:50002&lt;br/&gt;diff --git a/nip05/namecoin/websocket.go b/nip05/namecoin/websocket.go&lt;br/&gt;new file mode 100644&lt;br/&gt;index 0000000..5e849d7&lt;br/&gt;--- /dev/null&lt;br/&gt;&#43;&#43;&#43; b/nip05/namecoin/websocket.go&lt;br/&gt;@@ -0,0 &#43;1,105 @@&lt;br/&gt;&#43;package namecoin&lt;br/&gt;&#43;&lt;br/&gt;&#43;import (&lt;br/&gt;&#43;	&#34;context&#34;&lt;br/&gt;&#43;	&#34;encoding/json&#34;&lt;br/&gt;&#43;	&#34;fmt&#34;&lt;br/&gt;&#43;	&#34;net&#34;&lt;br/&gt;&#43;	&#34;net/http&#34;&lt;br/&gt;&#43;	&#34;strconv&#34;&lt;br/&gt;&#43;&lt;br/&gt;&#43;	&#34;github.com/coder/websocket&#34;&lt;br/&gt;&#43;)&lt;br/&gt;&#43;&lt;br/&gt;&#43;// wsReadLimit is the maximum size of a single WebSocket message we are&lt;br/&gt;&#43;// willing to accept from an ElectrumX server. Verbose transactions&lt;br/&gt;&#43;// from `blockchain.transaction.get` can legitimately run to tens of&lt;br/&gt;&#43;// kilobytes; 1 MiB is generous but keeps us safely bounded.&lt;br/&gt;&#43;const wsReadLimit int64 = 1 &lt;&lt; 20&lt;br/&gt;&#43;&lt;br/&gt;&#43;// dialWebSocket opens a WebSocket (plain or TLS) RPC connection to&lt;br/&gt;&#43;// the given ElectrumX server. It reuses the same pinned-cert TLS&lt;br/&gt;&#43;// config as the TCP&#43;TLS transport so operators who serve a single&lt;br/&gt;&#43;// self-signed certificate across both ports are handled identically.&lt;br/&gt;&#43;func (c *ElectrumClient) dialWebSocket(ctx context.Context, server ElectrumxServer) (rpcConn, error) {&lt;br/&gt;&#43;	transport := effectiveTransport(server)&lt;br/&gt;&#43;	scheme := &#34;ws&#34;&lt;br/&gt;&#43;	if transport == TransportWSS {&lt;br/&gt;&#43;		scheme = &#34;wss&#34;&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;	address := net.JoinHostPort(server.Host, strconv.Itoa(server.Port))&lt;br/&gt;&#43;	url := scheme &#43; &#34;://&#34; &#43; address&lt;br/&gt;&#43;&lt;br/&gt;&#43;	// Bound the dial to our connect timeout, in addition to honouring&lt;br/&gt;&#43;	// any deadline on the caller&#39;s context.&lt;br/&gt;&#43;	dialCtx, cancel := context.WithTimeout(ctx, c.ConnectTimeout)&lt;br/&gt;&#43;	defer cancel()&lt;br/&gt;&#43;&lt;br/&gt;&#43;	opts := &amp;websocket.DialOptions{}&lt;br/&gt;&#43;	if transport == TransportWSS {&lt;br/&gt;&#43;		// Build an http.Transport that carries the same *tls.Config&lt;br/&gt;&#43;		// the TCP&#43;TLS path uses. The custom VerifyPeerCertificate is&lt;br/&gt;&#43;		// transport-agnostic, so pinned-cert trust continues to work&lt;br/&gt;&#43;		// over WebSocket&#39;s HTTP upgrade handshake.&lt;br/&gt;&#43;		tlsCfg := tlsConfigFor(server)&lt;br/&gt;&#43;		opts.HTTPClient = &amp;http.Client{&lt;br/&gt;&#43;			Timeout: c.ConnectTimeout &#43; c.ReadTimeout,&lt;br/&gt;&#43;			Transport: &amp;http.Transport{&lt;br/&gt;&#43;				TLSClientConfig:     tlsCfg,&lt;br/&gt;&#43;				TLSHandshakeTimeout: c.ConnectTimeout,&lt;br/&gt;&#43;			},&lt;br/&gt;&#43;		}&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;&lt;br/&gt;&#43;	conn, _, err := websocket.Dial(dialCtx, url, opts)&lt;br/&gt;&#43;	if err != nil {&lt;br/&gt;&#43;		return nil, fmt.Errorf(&#34;namecoin: websocket dial %s: %w&#34;, url, err)&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;	conn.SetReadLimit(wsReadLimit)&lt;br/&gt;&#43;&lt;br/&gt;&#43;	return &amp;wsRPCConn{conn: conn}, nil&lt;br/&gt;&#43;}&lt;br/&gt;&#43;&lt;br/&gt;&#43;// wsRPCConn is the WebSocket JSON-RPC transport. Unlike the TCP&lt;br/&gt;&#43;// variant, WebSocket messages are pre-framed by the protocol layer,&lt;br/&gt;&#43;// so requests MUST NOT carry a trailing newline and responses arrive&lt;br/&gt;&#43;// as whole JSON messages per frame.&lt;br/&gt;&#43;type wsRPCConn struct {&lt;br/&gt;&#43;	conn *websocket.Conn&lt;br/&gt;&#43;}&lt;br/&gt;&#43;&lt;br/&gt;&#43;func (w *wsRPCConn) writeRequest(ctx context.Context, method string, params []any, id int64) error {&lt;br/&gt;&#43;	payload := map[string]any{&lt;br/&gt;&#43;		&#34;jsonrpc&#34;: &#34;2.0&#34;,&lt;br/&gt;&#43;		&#34;id&#34;:      id,&lt;br/&gt;&#43;		&#34;method&#34;:  method,&lt;br/&gt;&#43;		&#34;params&#34;:  params,&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;	encoded, err := json.Marshal(payload)&lt;br/&gt;&#43;	if err != nil {&lt;br/&gt;&#43;		return fmt.Errorf(&#34;namecoin: marshal rpc request: %w&#34;, err)&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;	if err := w.conn.Write(ctx, websocket.MessageText, encoded); err != nil {&lt;br/&gt;&#43;		return fmt.Errorf(&#34;namecoin: write rpc request: %w&#34;, err)&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;	return nil&lt;br/&gt;&#43;}&lt;br/&gt;&#43;&lt;br/&gt;&#43;func (w *wsRPCConn) readResponse(ctx context.Context) (string, error) {&lt;br/&gt;&#43;	_, data, err := w.conn.Read(ctx)&lt;br/&gt;&#43;	if err != nil {&lt;br/&gt;&#43;		return &#34;&#34;, err&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;	return string(data), nil&lt;br/&gt;&#43;}&lt;br/&gt;&#43;&lt;br/&gt;&#43;func (w *wsRPCConn) close() error {&lt;br/&gt;&#43;	return w.conn.Close(websocket.StatusNormalClosure, &#34;&#34;)&lt;br/&gt;&#43;}&lt;br/&gt;&#43;&lt;br/&gt;&#43;// Compile-time interface checks — catch drift early if the rpcConn&lt;br/&gt;&#43;// signature ever evolves.&lt;br/&gt;&#43;var (&lt;br/&gt;&#43;	_ rpcConn = (*tcpRPCConn)(nil)&lt;br/&gt;&#43;	_ rpcConn = (*wsRPCConn)(nil)&lt;br/&gt;&#43;)&lt;br/&gt;diff --git a/nip05/namecoin/websocket_test.go b/nip05/namecoin/websocket_test.go&lt;br/&gt;new file mode 100644&lt;br/&gt;index 0000000..ad5682a&lt;br/&gt;--- /dev/null&lt;br/&gt;&#43;&#43;&#43; b/nip05/namecoin/websocket_test.go&lt;br/&gt;@@ -0,0 &#43;1,195 @@&lt;br/&gt;&#43;package namecoin&lt;br/&gt;&#43;&lt;br/&gt;&#43;import (&lt;br/&gt;&#43;	&#34;context&#34;&lt;br/&gt;&#43;	&#34;encoding/json&#34;&lt;br/&gt;&#43;	&#34;net/http&#34;&lt;br/&gt;&#43;	&#34;net/http/httptest&#34;&lt;br/&gt;&#43;	&#34;net/url&#34;&lt;br/&gt;&#43;	&#34;strconv&#34;&lt;br/&gt;&#43;	&#34;strings&#34;&lt;br/&gt;&#43;	&#34;testing&#34;&lt;br/&gt;&#43;	&#34;time&#34;&lt;br/&gt;&#43;&lt;br/&gt;&#43;	&#34;github.com/coder/websocket&#34;&lt;br/&gt;&#43;)&lt;br/&gt;&#43;&lt;br/&gt;&#43;// fakeElectrumXWSHandler returns an http.Handler that upgrades incoming&lt;br/&gt;&#43;// connections to WebSocket and serves canned JSON-RPC responses for the&lt;br/&gt;&#43;// sequence the ElectrumClient issues during NameShow.&lt;br/&gt;&#43;//&lt;br/&gt;&#43;// The response ordering mirrors the real RPC sequence:&lt;br/&gt;&#43;//   1. server.version               → any non-error result&lt;br/&gt;&#43;//   2. blockchain.scripthash.get_history → one entry pointing at a fake txid&lt;br/&gt;&#43;//   3. blockchain.transaction.get   → one vout with a NAME_UPDATE that&lt;br/&gt;&#43;//                                     matches the requested name and a&lt;br/&gt;&#43;//                                     value whose &#34;nostr&#34; field is a&lt;br/&gt;&#43;//                                     known hex pubkey&lt;br/&gt;&#43;//   4. blockchain.headers.subscribe → a height far enough below our&lt;br/&gt;&#43;//                                     fake tx height that the name is&lt;br/&gt;&#43;//                                     well within its expiry window&lt;br/&gt;&#43;//&lt;br/&gt;&#43;// This exercises the whole WS dial → read → parse path end-to-end&lt;br/&gt;&#43;// without hitting the network.&lt;br/&gt;&#43;func fakeElectrumXWSHandler(t *testing.T, identifier, pubkeyHex string) http.Handler {&lt;br/&gt;&#43;	// Build the NAME_UPDATE script hex we want the client to parse&lt;br/&gt;&#43;	// back out of the &#34;transaction&#34;.&lt;br/&gt;&#43;	value := `{&#34;nostr&#34;:&#34;` &#43; pubkeyHex &#43; `&#34;}`&lt;br/&gt;&#43;	script := []byte{opNameUpdate}&lt;br/&gt;&#43;	script = append(script, pushData([]byte(identifier))...)&lt;br/&gt;&#43;	script = append(script, pushData([]byte(value))...)&lt;br/&gt;&#43;	script = append(script, op2Drop, opDrop)&lt;br/&gt;&#43;	// Stub P2PKH-ish tail so the parser&#39;s &#34;we don&#39;t care what follows&lt;br/&gt;&#43;	// the DROPs&#34; assumption holds.&lt;br/&gt;&#43;	script = append(script, 0x76, 0xa9, 0x14)&lt;br/&gt;&#43;	scriptHex := hexString(script)&lt;br/&gt;&#43;&lt;br/&gt;&#43;	return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {&lt;br/&gt;&#43;		conn, err := websocket.Accept(w, r, nil)&lt;br/&gt;&#43;		if err != nil {&lt;br/&gt;&#43;			t.Logf(&#34;ws accept: %v&#34;, err)&lt;br/&gt;&#43;			return&lt;br/&gt;&#43;		}&lt;br/&gt;&#43;		defer conn.Close(websocket.StatusInternalError, &#34;test server shutting down&#34;)&lt;br/&gt;&#43;&lt;br/&gt;&#43;		ctx := r.Context()&lt;br/&gt;&#43;&lt;br/&gt;&#43;		respond := func(id any, result any) {&lt;br/&gt;&#43;			payload := map[string]any{&lt;br/&gt;&#43;				&#34;jsonrpc&#34;: &#34;2.0&#34;,&lt;br/&gt;&#43;				&#34;id&#34;:      id,&lt;br/&gt;&#43;				&#34;result&#34;:  result,&lt;br/&gt;&#43;			}&lt;br/&gt;&#43;			raw, _ := json.Marshal(payload)&lt;br/&gt;&#43;			if err := conn.Write(ctx, websocket.MessageText, raw); err != nil {&lt;br/&gt;&#43;				t.Logf(&#34;ws write: %v&#34;, err)&lt;br/&gt;&#43;			}&lt;br/&gt;&#43;		}&lt;br/&gt;&#43;&lt;br/&gt;&#43;		for {&lt;br/&gt;&#43;			_, data, err := conn.Read(ctx)&lt;br/&gt;&#43;			if err != nil {&lt;br/&gt;&#43;				return&lt;br/&gt;&#43;			}&lt;br/&gt;&#43;			var req struct {&lt;br/&gt;&#43;				ID     any    `json:&#34;id&#34;`&lt;br/&gt;&#43;				Method string `json:&#34;method&#34;`&lt;br/&gt;&#43;			}&lt;br/&gt;&#43;			if err := json.Unmarshal(data, &amp;req); err != nil {&lt;br/&gt;&#43;				t.Logf(&#34;ws request parse: %v&#34;, err)&lt;br/&gt;&#43;				return&lt;br/&gt;&#43;			}&lt;br/&gt;&#43;			switch req.Method {&lt;br/&gt;&#43;			case &#34;server.version&#34;:&lt;br/&gt;&#43;				respond(req.ID, []string{&#34;ElectrumX 1.16.0&#34;, electrumProtocolVersion})&lt;br/&gt;&#43;			case &#34;blockchain.scripthash.get_history&#34;:&lt;br/&gt;&#43;				respond(req.ID, []map[string]any{&lt;br/&gt;&#43;					{&#34;tx_hash&#34;: &#34;deadbeefcafebabe&#34;, &#34;height&#34;: 600000},&lt;br/&gt;&#43;				})&lt;br/&gt;&#43;			case &#34;blockchain.transaction.get&#34;:&lt;br/&gt;&#43;				respond(req.ID, map[string]any{&lt;br/&gt;&#43;					&#34;txid&#34;: &#34;deadbeefcafebabe&#34;,&lt;br/&gt;&#43;					&#34;vout&#34;: []map[string]any{&lt;br/&gt;&#43;						{&#34;scriptPubKey&#34;: map[string]any{&#34;hex&#34;: scriptHex}},&lt;br/&gt;&#43;					},&lt;br/&gt;&#43;				})&lt;br/&gt;&#43;			case &#34;blockchain.headers.subscribe&#34;:&lt;br/&gt;&#43;				respond(req.ID, map[string]any{&#34;height&#34;: 600010})&lt;br/&gt;&#43;			default:&lt;br/&gt;&#43;				respond(req.ID, nil)&lt;br/&gt;&#43;			}&lt;br/&gt;&#43;		}&lt;br/&gt;&#43;	})&lt;br/&gt;&#43;}&lt;br/&gt;&#43;&lt;br/&gt;&#43;func hexString(b []byte) string {&lt;br/&gt;&#43;	const hexDigits = &#34;0123456789abcdef&#34;&lt;br/&gt;&#43;	out := make([]byte, 0, len(b)*2)&lt;br/&gt;&#43;	for _, v := range b {&lt;br/&gt;&#43;		out = append(out, hexDigits[v&gt;&gt;4], hexDigits[v&amp;0x0f])&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;	return string(out)&lt;br/&gt;&#43;}&lt;br/&gt;&#43;&lt;br/&gt;&#43;func TestWebSocketTransport_NameShow(t *testing.T) {&lt;br/&gt;&#43;	identifier := &#34;d/wsfake&#34;&lt;br/&gt;&#43;	pubkey := &#34;aaaa000000000000000000000000000000000000000000000000000000000001&#34;&lt;br/&gt;&#43;&lt;br/&gt;&#43;	ts := httptest.NewServer(fakeElectrumXWSHandler(t, identifier, pubkey))&lt;br/&gt;&#43;	defer ts.Close()&lt;br/&gt;&#43;&lt;br/&gt;&#43;	// Parse the httptest URL so we can point the client at it as&lt;br/&gt;&#43;	// host&#43;port with the plain-WS transport. httptest.Server is HTTP,&lt;br/&gt;&#43;	// so TransportWS (not WSS) is what we want here — it verifies the&lt;br/&gt;&#43;	// framing/routing independently of the TLS plumbing.&lt;br/&gt;&#43;	u, err := url.Parse(ts.URL)&lt;br/&gt;&#43;	if err != nil {&lt;br/&gt;&#43;		t.Fatal(err)&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;	port, err := strconv.Atoi(u.Port())&lt;br/&gt;&#43;	if err != nil {&lt;br/&gt;&#43;		t.Fatal(err)&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;&lt;br/&gt;&#43;	srv := ElectrumxServer{&lt;br/&gt;&#43;		Host:      u.Hostname(),&lt;br/&gt;&#43;		Port:      port,&lt;br/&gt;&#43;		Transport: TransportWS,&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;&lt;br/&gt;&#43;	client := NewElectrumClient()&lt;br/&gt;&#43;	client.ConnectTimeout = 3 * time.Second&lt;br/&gt;&#43;	client.ReadTimeout = 5 * time.Second&lt;br/&gt;&#43;&lt;br/&gt;&#43;	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)&lt;br/&gt;&#43;	defer cancel()&lt;br/&gt;&#43;&lt;br/&gt;&#43;	result, err := client.NameShow(ctx, identifier, srv)&lt;br/&gt;&#43;	if err != nil {&lt;br/&gt;&#43;		t.Fatalf(&#34;NameShow over WS: %v&#34;, err)&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;	if result == nil {&lt;br/&gt;&#43;		t.Fatal(&#34;NameShow returned nil result&#34;)&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;	if result.Name != identifier {&lt;br/&gt;&#43;		t.Errorf(&#34;name = %q, want %q&#34;, result.Name, identifier)&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;	if !strings.Contains(result.Value, pubkey) {&lt;br/&gt;&#43;		t.Errorf(&#34;value = %q, want to contain %q&#34;, result.Value, pubkey)&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;}&lt;br/&gt;&#43;&lt;br/&gt;&#43;func TestEffectiveTransport(t *testing.T) {&lt;br/&gt;&#43;	cases := []struct {&lt;br/&gt;&#43;		in   ElectrumxServer&lt;br/&gt;&#43;		want Transport&lt;br/&gt;&#43;	}{&lt;br/&gt;&#43;		// v0.1.x shape: UseSSL=true, Transport unset → TCPTLS.&lt;br/&gt;&#43;		{ElectrumxServer{UseSSL: true}, TransportTCPTLS},&lt;br/&gt;&#43;		// v0.1.x shape: UseSSL=false, Transport unset → plain TCP.&lt;br/&gt;&#43;		{ElectrumxServer{UseSSL: false}, TransportTCP},&lt;br/&gt;&#43;		// Explicit Transport wins over UseSSL when non-zero.&lt;br/&gt;&#43;		{ElectrumxServer{UseSSL: true, Transport: TransportWSS}, TransportWSS},&lt;br/&gt;&#43;		{ElectrumxServer{UseSSL: false, Transport: TransportWS}, TransportWS},&lt;br/&gt;&#43;		{ElectrumxServer{UseSSL: false, Transport: TransportTCPTLS}, TransportTCP}, // TCPTLS is zero value; falls back to UseSSL&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;	for i, tc := range cases {&lt;br/&gt;&#43;		if got := effectiveTransport(tc.in); got != tc.want {&lt;br/&gt;&#43;			t.Errorf(&#34;case %d: effectiveTransport(%&#43;v) = %d, want %d&#34;, i, tc.in, got, tc.want)&lt;br/&gt;&#43;		}&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;}&lt;br/&gt;&#43;&lt;br/&gt;&#43;func TestDefaultElectrumXServersWSS(t *testing.T) {&lt;br/&gt;&#43;	if len(DefaultElectrumXServersWSS) == 0 {&lt;br/&gt;&#43;		t.Fatal(&#34;DefaultElectrumXServersWSS is empty&#34;)&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;	for _, srv := range DefaultElectrumXServersWSS {&lt;br/&gt;&#43;		if srv.Transport != TransportWSS {&lt;br/&gt;&#43;			t.Errorf(&#34;%s:%d has Transport=%d, want WSS&#34;, srv.Host, srv.Port, srv.Transport)&lt;br/&gt;&#43;		}&lt;br/&gt;&#43;		if !srv.UsePinnedTrustStore {&lt;br/&gt;&#43;			t.Errorf(&#34;%s:%d: WSS default servers must pin the trust store&#34;, srv.Host, srv.Port)&lt;br/&gt;&#43;		}&lt;br/&gt;&#43;	}&lt;br/&gt;&#43;}&lt;br/&gt;-- &lt;br/&gt;2.50.1 (Apple Git-155)&lt;br/&gt;&lt;br/&gt; &lt;/blockquote&gt;
    </content>
    <updated>2026-04-19T12:00:28Z</updated>
  </entry>

  <entry>
    <id>https://njump.me/nevent1qqsxwm9uu4rzhf2r87y6r005ltsar23dreyjq48kr9sk5mkmxl5pduczypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60qwkzrde</id>
    
      <title type="html">@npub180c…h6w6 re https://github.com/fiatjaf/nak/pull/123 — ...</title>
    
    <link rel="alternate" href="https://njump.me/nevent1qqsxwm9uu4rzhf2r87y6r005ltsar23dreyjq48kr9sk5mkmxl5pduczypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60qwkzrde" />
    <content type="html">
      In reply to &lt;a href=&#39;/naddr1qqyxummnw3exc6tzqgsrhuxx8l9ex335q7he0f09aej04zpazpl0ne2cgukyawd24mayt8grqsqqqaue48cxua&#39;&gt;naddr1qq…cxua&lt;/a&gt;&lt;br/&gt;_________________________&lt;br/&gt;&lt;br/&gt;&lt;span itemprop=&#34;mentions&#34; itemscope itemtype=&#34;https://schema.org/Person&#34;&gt;&lt;a itemprop=&#34;url&#34; href=&#34;/npub180cvv07tjdrrgpa0j7j7tmnyl2yr6yr7l8j4s3evf6u64th6gkwsyjh6w6&#34; class=&#34;bg-lavender dark:prose:text-neutral-50 dark:text-neutral-50 dark:bg-garnet px-1&#34;&gt;&lt;span&gt;fiatjaf&lt;/span&gt; (&lt;span class=&#34;italic&#34;&gt;npub180c…h6w6&lt;/span&gt;)&lt;/a&gt;&lt;/span&gt; re &lt;a href=&#34;https://github.com/fiatjaf/nak/pull/123&#34;&gt;https://github.com/fiatjaf/nak/pull/123&lt;/a&gt; — posted a NIP-34 patch event adding a proposed nip05/namecoin subpackage to nostrlib, addressed to you. Patch: nostr:nevent1qqs8yepuma694y6saym8ny4wtfzymlgu2htusvweyjzpamc0rgn8pyqpz3mhxue69uhhyetvv9ujumn8d96zuer9wcq3yamnwvaz7tm8d96xummnw3ezucm0d5q3gamnwvaz7tmjv4kxz7fwv3sk6atn9e5k7q3qgvv9ahktvavf9qjtrgm62le7gplmmchd5usp5wpfhr85hf79kncq8jdtz6. GitHub mirror: &lt;a href=&#34;https://github.com/mstrofnone/nostrlib-nip05-namecoin&#34;&gt;https://github.com/mstrofnone/nostrlib-nip05-namecoin&lt;/a&gt;
    </content>
    <updated>2026-04-19T11:25:10Z</updated>
  </entry>

  <entry>
    <id>https://njump.me/nevent1qqsdx2pwklc5ccf9cumgkm4z5xwm4sck0zfgmqdaammxfvggt802k6qzypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60qhmqfnz</id>
    
      <title type="html">This is spot on. Satoshi saw merged mining as the way to ...</title>
    
    <link rel="alternate" href="https://njump.me/nevent1qqsdx2pwklc5ccf9cumgkm4z5xwm4sck0zfgmqdaammxfvggt802k6qzypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60qhmqfnz" />
    <content type="html">
      In reply to &lt;a href=&#39;/nevent1qqstx4vqglk6lhrrg6kvcqynt6qpj2tdx4rdpm33yme65ra98gqg08gxkvxmt&#39;&gt;nevent1q…vxmt&lt;/a&gt;&lt;br/&gt;_________________________&lt;br/&gt;&lt;br/&gt;This is spot on. Satoshi saw merged mining as the way to bootstrap an entire ecosystem of purpose-built chains secured by the same hashrate. BitDNS/Namecoin was the proof of concept.&lt;br/&gt;&lt;br/&gt;What most people miss is that Namecoin gives you something no other system does: human-readable names with immutable, temporally ordered key bindings on a chain with Bitcoin-class security. That&amp;#39;s not a novelty — it&amp;#39;s infrastructure.&lt;br/&gt;&lt;br/&gt;We&amp;#39;re using it right now to build a Nostr reputation layer with blockchain-anchored identity proofs:&lt;br/&gt;&lt;blockquote class=&#34;border-l-05rem border-l-strongpink border-solid&#34;&gt;&lt;div class=&#34;-ml-4 bg-gradient-to-r from-gray-100 dark:from-zinc-800 to-transparent mr-0 mt-0 mb-4 pl-4 pr-2 py-2&#34;&gt;quoting &lt;br/&gt;&lt;span itemprop=&#34;mentions&#34; itemscope itemtype=&#34;https://schema.org/Article&#34;&gt;&lt;a itemprop=&#34;url&#34; href=&#34;/naddr1qvzqqqr4gupzqscctm0vke6cj2pykx3h54lnusrlhh3wmfeqrguznwx0fwnutd8sqq3kuctdv43k76tw945kuar9vaexzarfdahz6ctdv46xs7tnwskkwatfv3jsz0753t&#34; class=&#34;bg-lavender dark:prose:text-neutral-50 dark:text-neutral-50 dark:bg-garnet px-1&#34;&gt;naddr1qv…753t&lt;/a&gt;&lt;/span&gt;&lt;br/&gt; &lt;/div&gt; 
&lt;h1 id=&#34;how-to-guide-namecoin-integration-in-amethyst-2&#34;&gt;How-To Guide: Namecoin Integration in Amethyst&lt;/h1&gt;

&lt;h2 id=&#34;what-this-is-2&#34;&gt;What This Is&lt;/h2&gt;

&lt;p&gt;Amethyst — the Android Nostr client — includes built-in support for resolving Namecoin blockchain names as NIP-05 identities. Instead of relying on a web server to verify &lt;code&gt;alice@example.com&lt;/code&gt;, a user can set their NIP-05 address to something like &lt;code&gt;alice@example.bit&lt;/code&gt;, and Amethyst will verify it directly against the Namecoin blockchain via ElectrumX servers.&lt;/p&gt;

&lt;p&gt;This is censorship-resistant identity: no web server to seize, no DNS to hijack, no TLS certificate to revoke. The name-to-pubkey mapping lives in Namecoin UTXOs.&lt;/p&gt;

&lt;p&gt;This guide covers how the system works, how to use it as an end-user, and how to register or update a Namecoin name value so that it resolves to your Nostr pubkey.&lt;/p&gt;

&lt;hr&gt;

&lt;h2 id=&#34;part-1-using-namecoin-names-in-amethyst-end-user-2&#34;&gt;Part 1: Using Namecoin Names in Amethyst (End-User)&lt;/h2&gt;

&lt;h3 id=&#34;searching-for-namecoin-users-2&#34;&gt;Searching for Namecoin Users&lt;/h3&gt;

&lt;p&gt;Open Amethyst&amp;#39;s search bar and type any of these formats:&lt;/p&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Search Input&lt;/th&gt;
&lt;th&gt;What It Does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;alice@example.bit&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Looks up the &lt;code&gt;alice&lt;/code&gt; entry in Namecoin name &lt;code&gt;d/example&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;example.bit&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Looks up the root (&lt;code&gt;_&lt;/code&gt;) entry in &lt;code&gt;d/example&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;d/example&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Direct Namecoin domain namespace lookup (root entry)&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;id/alice&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Direct Namecoin identity namespace lookup&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Amethyst queries the Namecoin blockchain through an ElectrumX server, resolves the name to a Nostr public key, and shows the matching user profile at the top of search results. There is a 400ms debounce on the search input to avoid flooding the server with requests.&lt;/p&gt;

&lt;h3 id=&#34;nip-05-verification-via-namecoin-2&#34;&gt;NIP-05 Verification via Namecoin&lt;/h3&gt;

&lt;p&gt;If a Nostr profile has a &lt;code&gt;.bit&lt;/code&gt; address in its &lt;code&gt;nip05&lt;/code&gt; metadata field (e.g. &lt;code&gt;m@testls.bit&lt;/code&gt;), Amethyst will automatically verify it against the blockchain instead of making an HTTP request. The verification badge works the same as traditional NIP-05 — the only difference is the trust anchor: blockchain consensus rather than a web server.&lt;/p&gt;

&lt;h3 id=&#34;configuring-namecoin-settings-2&#34;&gt;Configuring Namecoin Settings&lt;/h3&gt;

&lt;p&gt;Navigate to &lt;strong&gt;Settings → Namecoin Settings&lt;/strong&gt; in Amethyst. From here you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Enable/disable&lt;/strong&gt; Namecoin resolution entirely&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Add custom ElectrumX servers&lt;/strong&gt; — useful if you run your own server for privacy&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Remove servers&lt;/strong&gt; from the custom list&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Test server connectivity&lt;/strong&gt; — checks TLS, latency, and optionally resolves a test name&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pin TLS certificates&lt;/strong&gt; — after testing a server with a self-signed cert, you can pin its certificate via TOFU (Trust On First Use)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reset to defaults&lt;/strong&gt; — reverts to the built-in server list&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&#34;server-string-format-2&#34;&gt;Server String Format&lt;/h4&gt;

&lt;p&gt;When adding a custom server, use the format:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;host:port          → TLS connection (default)
host:port:tcp      → Plaintext TCP (for .onion or local servers)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;electrumx.testls.space:50002
my-local-server.lan:50001:tcp
i665jpw...dsid.onion:50002
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;tor-integration-2&#34;&gt;Tor Integration&lt;/h3&gt;

&lt;p&gt;If you have Tor enabled in Amethyst and have set &amp;#34;NIP-05 verifications via Tor&amp;#34; to on, all Namecoin ElectrumX connections are routed through your Tor SOCKS proxy. The server list also switches to prioritize &lt;code&gt;.onion&lt;/code&gt; addresses:&lt;/p&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tor Setting&lt;/th&gt;
&lt;th&gt;Primary Server&lt;/th&gt;
&lt;th&gt;Fallback&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Off&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;electrumx.testls.space:50002&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;nmc2.bitcoins.sk:57002&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;On&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.onion:50002&lt;/code&gt; (hidden service)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;electrumx.testls.space:50002&lt;/code&gt; (via Tor)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Toggling Tor on or off in settings takes effect on the next lookup — no app restart needed.&lt;/p&gt;

&lt;h3 id=&#34;default-electrumx-servers-2&#34;&gt;Default ElectrumX Servers&lt;/h3&gt;

&lt;p&gt;Amethyst ships with these built-in servers:&lt;/p&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Server&lt;/th&gt;
&lt;th&gt;Port&lt;/th&gt;
&lt;th&gt;TLS&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;electrumx.testls.space&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;50002&lt;/td&gt;
&lt;td&gt;Yes (self-signed, pinned)&lt;/td&gt;
&lt;td&gt;Primary&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;nmc2.bitcoins.sk&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;57002&lt;/td&gt;
&lt;td&gt;Yes (self-signed, pinned)&lt;/td&gt;
&lt;td&gt;Fallback&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;46.229.238.187&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;57002&lt;/td&gt;
&lt;td&gt;Yes (self-signed, pinned)&lt;/td&gt;
&lt;td&gt;IP fallback&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The self-signed certificates for these servers are pinned directly into the Amethyst binary, so connections succeed even on devices with strict TLS enforcement (Samsung One UI 7, GrapheneOS).&lt;/p&gt;

&lt;hr&gt;

&lt;h2 id=&#34;part-2-registering-updating-a-namecoin-name-value-2&#34;&gt;Part 2: Registering &amp;amp; Updating a Namecoin Name Value&lt;/h2&gt;

&lt;p&gt;Amethyst itself is a &lt;strong&gt;read-only&lt;/strong&gt; consumer of Namecoin data — it resolves names but does not write to the blockchain. To register or update a Namecoin name so that it points to your Nostr pubkey, you need to interact with the Namecoin blockchain directly using Namecoin Core (the full node software) or a compatible wallet.&lt;/p&gt;

&lt;h3 id=&#34;prerequisites-3&#34;&gt;Prerequisites&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Namecoin Core&lt;/strong&gt; or &lt;strong&gt;Electrum-NMC&lt;/strong&gt; installed and synced — download from &lt;a href=&#34;https://www.namecoin.org/&#34;&gt;namecoin.org&lt;/a&gt; (this guide uses Namecoin Core as an example)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;NMC (Namecoin coins)&lt;/strong&gt; in your wallet — needed to pay registration and update fees (0.01 NMC per registration operation plus associated fees)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Your Nostr hex public key&lt;/strong&gt; — the 64-character hex string (not &lt;code&gt;npub1...&lt;/code&gt;). You can find this in Amethyst under your profile settings or by converting your npub using a tool like &lt;a href=&#34;https://nostrdeck.com/key-converter.php&#34;&gt;https://nostrdeck.com/key-converter.php&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&#34;step-1-choose-your-namespace-2&#34;&gt;Step 1: Choose Your Namespace&lt;/h3&gt;

&lt;p&gt;Amethyst supports two Namecoin namespaces:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Domain namespace (&lt;code&gt;d/&lt;/code&gt;)&lt;/strong&gt; — maps a domain-like name to one or more Nostr pubkeys. This is the most common choice and mirrors NIP-05&amp;#39;s &lt;code&gt;user@domain&lt;/code&gt; format.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Identity namespace (&lt;code&gt;id/&lt;/code&gt;)&lt;/strong&gt; — maps a personal identity name to a single Nostr pubkey.&lt;/p&gt;

&lt;p&gt;For most users, the &lt;code&gt;d/&lt;/code&gt; namespace is the right choice because it allows &lt;code&gt;user@name.bit&lt;/code&gt; style addresses.&lt;/p&gt;

&lt;h3 id=&#34;step-2-register-a-new-name-2&#34;&gt;Step 2: Register a New Name&lt;/h3&gt;

&lt;p&gt;Open a terminal and use &lt;code&gt;namecoin-cli&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# Register a name in the domain namespace
# This creates a &amp;#34;pre-registration&amp;#34; (name_new) first
namecoin-cli name_new &amp;#34;d/yourname&amp;#34;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This returns a transaction ID and a random value. &lt;strong&gt;Save both&lt;/strong&gt; — you need the random value for the next step. Wait for the transaction to get at least 12 confirmations (about 2 hours).&lt;/p&gt;

&lt;p&gt;Then finalize the registration:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;namecoin-cli name_firstupdate &amp;#34;d/yourname&amp;#34; &amp;lt;random_value&amp;gt; &amp;#39;&amp;lt;json_value&amp;gt;&amp;#39;
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;step-3-set-the-name-value-for-nostr-2&#34;&gt;Step 3: Set the Name Value for Nostr&lt;/h3&gt;

&lt;p&gt;The JSON value you store in the Namecoin name is what Amethyst reads to find your Nostr pubkey. There are several supported formats.&lt;/p&gt;

&lt;h4 id=&#34;simple-form-single-user-root-domain-2&#34;&gt;Simple Form — Single User, Root Domain&lt;/h4&gt;

&lt;p&gt;If you just want &lt;code&gt;yourname.bit&lt;/code&gt; to resolve to your pubkey:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{
  &amp;#34;nostr&amp;#34;: &amp;#34;b0635d6a9851d3aed0cd6c495b282167acf761729078d975fc341b22650b07b9&amp;#34;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code&gt;namecoin-cli name_firstupdate &amp;#34;d/yourname&amp;#34; &amp;lt;random&amp;gt; \
  &amp;#39;{&amp;#34;nostr&amp;#34;:&amp;#34;b0635d6a9851d3aed0cd6c495b282167acf761729078d975fc341b22650b07b9&amp;#34;}&amp;#39;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This makes &lt;code&gt;yourname.bit&lt;/code&gt; and &lt;code&gt;_@yourname.bit&lt;/code&gt; resolve to the given pubkey.&lt;/p&gt;

&lt;h4 id=&#34;extended-form-multiple-users-with-relay-hints-2&#34;&gt;Extended Form — Multiple Users with Relay Hints&lt;/h4&gt;

&lt;p&gt;If you want to host multiple identities under one &lt;code&gt;.bit&lt;/code&gt; domain (like a NIP-05 server hosting multiple users):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{
  &amp;#34;nostr&amp;#34;: {
    &amp;#34;names&amp;#34;: {
      &amp;#34;_&amp;#34;: &amp;#34;aaaa000000000000000000000000000000000000000000000000000000000001&amp;#34;,
      &amp;#34;alice&amp;#34;: &amp;#34;bbbb000000000000000000000000000000000000000000000000000000000002&amp;#34;,
      &amp;#34;bob&amp;#34;: &amp;#34;cccc000000000000000000000000000000000000000000000000000000000003&amp;#34;
    },
    &amp;#34;relays&amp;#34;: {
      &amp;#34;bbbb000000000000000000000000000000000000000000000000000000000002&amp;#34;: [
        &amp;#34;wss://relay.example.com&amp;#34;,
        &amp;#34;wss://nos.lol&amp;#34;
      ]
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;With this value stored in &lt;code&gt;d/yourname&lt;/code&gt;:
- &lt;code&gt;_@yourname.bit&lt;/code&gt; or &lt;code&gt;yourname.bit&lt;/code&gt; → resolves to the &lt;code&gt;_&lt;/code&gt; pubkey
- &lt;code&gt;alice@yourname.bit&lt;/code&gt; → resolves to Alice&amp;#39;s pubkey, with relay hints
- &lt;code&gt;bob@yourname.bit&lt;/code&gt; → resolves to Bob&amp;#39;s pubkey&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;namecoin-cli name_firstupdate &amp;#34;d/yourname&amp;#34; &amp;lt;random&amp;gt; \
  &amp;#39;{&amp;#34;nostr&amp;#34;:{&amp;#34;names&amp;#34;:{&amp;#34;_&amp;#34;:&amp;#34;aaaa...0001&amp;#34;,&amp;#34;alice&amp;#34;:&amp;#34;bbbb...0002&amp;#34;},&amp;#34;relays&amp;#34;:{&amp;#34;bbbb...0002&amp;#34;:[&amp;#34;wss://relay.example.com&amp;#34;]}}}&amp;#39;
&lt;/code&gt;&lt;/pre&gt;

&lt;h4 id=&#34;identity-namespace-form-id-2&#34;&gt;Identity Namespace Form (&lt;code&gt;id/&lt;/code&gt;)&lt;/h4&gt;

&lt;p&gt;For the &lt;code&gt;id/&lt;/code&gt; namespace, the value format is simpler:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{
  &amp;#34;nostr&amp;#34;: &amp;#34;cccc000000000000000000000000000000000000000000000000000000000003&amp;#34;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Or with relay hints:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{
  &amp;#34;nostr&amp;#34;: {
    &amp;#34;pubkey&amp;#34;: &amp;#34;dddd000000000000000000000000000000000000000000000000000000000004&amp;#34;,
    &amp;#34;relays&amp;#34;: [&amp;#34;wss://relay.example.com&amp;#34;]
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code&gt;namecoin-cli name_firstupdate &amp;#34;id/youridentity&amp;#34; &amp;lt;random&amp;gt; \
  &amp;#39;{&amp;#34;nostr&amp;#34;:{&amp;#34;pubkey&amp;#34;:&amp;#34;dddd...0004&amp;#34;,&amp;#34;relays&amp;#34;:[&amp;#34;wss://relay.example.com&amp;#34;]}}&amp;#39;
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;step-4-update-an-existing-name-2&#34;&gt;Step 4: Update an Existing Name&lt;/h3&gt;

&lt;p&gt;To change the Nostr pubkey (or any other data) associated with an already-registered name, use &lt;code&gt;name_update&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;namecoin-cli name_update &amp;#34;d/yourname&amp;#34; \
  &amp;#39;{&amp;#34;nostr&amp;#34;:{&amp;#34;names&amp;#34;:{&amp;#34;_&amp;#34;:&amp;#34;&amp;lt;new_hex_pubkey&amp;gt;&amp;#34;,&amp;#34;alice&amp;#34;:&amp;#34;&amp;lt;alice_hex_pubkey&amp;gt;&amp;#34;},&amp;#34;relays&amp;#34;:{&amp;#34;&amp;lt;alice_hex_pubkey&amp;gt;&amp;#34;:[&amp;#34;wss://relay.example.com&amp;#34;]}}}&amp;#39;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This broadcasts a &lt;code&gt;NAME_UPDATE&lt;/code&gt; transaction to the Namecoin blockchain. Once confirmed, Amethyst (and any other client that supports Namecoin NIP-05) will resolve the name to the new value.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Important notes on updates:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each &lt;code&gt;name_update&lt;/code&gt; costs a small NMC fee&lt;/li&gt;
&lt;li&gt;Names expire after &lt;strong&gt;36,000 blocks&lt;/strong&gt; (~36 weeks) if not updated or renewed. Amethyst checks expiry and will treat expired names as non-existent.&lt;/li&gt;
&lt;li&gt;To simply renew without changing the value, you can &lt;code&gt;name_update&lt;/code&gt; with the same value&lt;/li&gt;
&lt;li&gt;Updates replace the entire value — there is no partial update mechanism&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&#34;step-5-set-your-nip-05-in-your-nostr-profile-2&#34;&gt;Step 5: Set Your NIP-05 in Your Nostr Profile&lt;/h3&gt;

&lt;p&gt;Once your Namecoin name is registered and confirmed on the blockchain, update your Nostr profile&amp;#39;s &lt;code&gt;nip05&lt;/code&gt; field in Amethyst:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to your profile → Edit&lt;/li&gt;
&lt;li&gt;Set the NIP-05 field to your Namecoin address, e.g. &lt;code&gt;alice@yourname.bit&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Save&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Amethyst (and other Namecoin-aware clients) will verify this address against the blockchain and show the verification badge.&lt;/p&gt;

&lt;h3 id=&#34;step-6-verify-it-works-2&#34;&gt;Step 6: Verify It Works&lt;/h3&gt;

&lt;p&gt;In Amethyst&amp;#39;s search bar, type your Namecoin identifier. You should see your profile appear at the top of results:&lt;/p&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Test Query&lt;/th&gt;
&lt;th&gt;Expected Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;alice@yourname.bit&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Your profile (matched via &lt;code&gt;alice&lt;/code&gt; entry)&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;yourname.bit&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Your profile (matched via &lt;code&gt;_&lt;/code&gt; root entry)&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;d/yourname&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Your profile (direct namespace lookup)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;hr&gt;

&lt;h2 id=&#34;part-3-how-it-works-under-the-hood-2&#34;&gt;Part 3: How It Works Under the Hood&lt;/h2&gt;

&lt;h3 id=&#34;resolution-flow-2&#34;&gt;Resolution Flow&lt;/h3&gt;

&lt;p&gt;When Amethyst encounters a &lt;code&gt;.bit&lt;/code&gt; address, here is what happens:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;1. User types &amp;#34;alice@example.bit&amp;#34; in search (or a profile has it in nip05)

2. NamecoinNameResolver.parseIdentifier() parses it:
   → namecoinName = &amp;#34;d/example&amp;#34;, localPart = &amp;#34;alice&amp;#34;, namespace = DOMAIN

3. ElectrumXClient builds a canonical &amp;#34;name index script&amp;#34;:
   OP_NAME_UPDATE(0x53) &#43; push(&amp;#34;d/example&amp;#34;) &#43; push(&amp;#34;&amp;#34;) &#43; OP_2DROP &#43; OP_DROP &#43; OP_RETURN

4. Computes the Electrum-style scripthash:
   SHA-256(script) → reverse bytes → hex encode

5. Queries the ElectrumX server:
   → blockchain.scripthash.get_history(scripthash)
   ← [{tx_hash: &amp;#34;abc...&amp;#34;, height: 814278}, ...]

6. Fetches the latest transaction (last entry = most recent name update):
   → blockchain.transaction.get(tx_hash, verbose=true)

7. Checks block headers to verify the name hasn&amp;#39;t expired:
   → blockchain.headers.subscribe
   ← current height; if (current - update_height) &amp;gt;= 36000 → expired

8. Parses the NAME_UPDATE script from the transaction output:
   Extracts: name string &#43; JSON value

9. NamecoinNameResolver.extractFromDomainValue() reads the JSON:
   Finds &amp;#34;nostr&amp;#34; → &amp;#34;names&amp;#34; → &amp;#34;alice&amp;#34; → hex pubkey

10. Returns NamecoinNostrResult(pubkey, relays, namecoinName, localPart)
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;caching-2&#34;&gt;Caching&lt;/h3&gt;

&lt;p&gt;Resolved names are cached in an LRU cache (default 500 entries, 1-hour TTL). Both positive and negative results are cached. The cache is keyed by the normalized (lowercased, trimmed) identifier.&lt;/p&gt;

&lt;h3 id=&#34;architecture-layers-2&#34;&gt;Architecture Layers&lt;/h3&gt;

&lt;p&gt;The implementation is split across two modules:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Quartz (library, no Android dependencies):&lt;/strong&gt;
- &lt;code&gt;NamecoinNameResolver&lt;/code&gt; — identifier parsing, value extraction, resolution orchestration
- &lt;code&gt;ElectrumXClient&lt;/code&gt; — TCP/TLS connection to ElectrumX, JSON-RPC, script parsing
- &lt;code&gt;NamecoinLookupCache&lt;/code&gt; — LRU cache with TTL
- &lt;code&gt;IElectrumXClient&lt;/code&gt; — interface for testing/mocking&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Amethyst (Android app):&lt;/strong&gt;
- &lt;code&gt;NamecoinNameService&lt;/code&gt; — application singleton, wires up caching and proxy-aware client
- &lt;code&gt;NamecoinSettings&lt;/code&gt; / &lt;code&gt;NamecoinSharedPreferences&lt;/code&gt; — persistent config
- &lt;code&gt;NamecoinSettingsScreen&lt;/code&gt; / &lt;code&gt;NamecoinSettingsSection&lt;/code&gt; — settings UI
- &lt;code&gt;ProxiedSocketFactory&lt;/code&gt; — SOCKS5 proxy routing for Tor
- &lt;code&gt;RoleBasedHttpClientBuilder.socketFactoryForNip05()&lt;/code&gt; — Tor-aware socket creation&lt;/p&gt;

&lt;p&gt;The integration into NIP-05 is minimal: &lt;code&gt;Nip05Client&lt;/code&gt; checks if an identifier matches &lt;code&gt;.bit&lt;/code&gt; / &lt;code&gt;d/&lt;/code&gt; / &lt;code&gt;id/&lt;/code&gt; patterns, and routes to &lt;code&gt;NamecoinNameResolver&lt;/code&gt; instead of making an HTTP fetch. Non-Namecoin identifiers are completely unaffected.&lt;/p&gt;

&lt;hr&gt;

&lt;h2 id=&#34;part-4-security-considerations-2&#34;&gt;Part 4: Security Considerations&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Tor integration&lt;/strong&gt; — When enabled, all ElectrumX connections go through the Tor SOCKS proxy. The &lt;code&gt;.onion&lt;/code&gt; server is preferred for end-to-end onion routing. Socket factory and server list are evaluated per-request via lambdas, so toggling Tor takes effect immediately.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TLS certificate pinning&lt;/strong&gt; — The primary ElectrumX servers use self-signed certificates. Their PEM-encoded certs are pinned in the Amethyst binary. Users can pin additional certs via the TOFU flow in settings (test server → view fingerprint → confirm → pin). This is necessary because Samsung One UI 7 and GrapheneOS reject trust-all TrustManagers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Name expiry&lt;/strong&gt; — Namecoin names expire after ~36,000 blocks (~250 days) if not renewed. The ElectrumX client checks the current block height against the name&amp;#39;s last update height and treats expired names as non-existent.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Server trust&lt;/strong&gt; — The client trusts that the ElectrumX server returns accurate transaction data. The Namecoin blockchain itself is the trust anchor — a MITM could return stale data but cannot forge name registrations. For higher assurance, SPV proof verification could be added in the future.&lt;/p&gt;

&lt;hr&gt;

&lt;h2 id=&#34;quick-reference-2&#34;&gt;Quick Reference&lt;/h2&gt;

&lt;h3 id=&#34;identifier-format-summary-2&#34;&gt;Identifier Format Summary&lt;/h3&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;User Input&lt;/th&gt;
&lt;th&gt;Namecoin Name&lt;/th&gt;
&lt;th&gt;Looked-Up Entry&lt;/th&gt;
&lt;th&gt;Namespace&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;alice@example.bit&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;d/example&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;alice&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Domain&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;_@example.bit&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;d/example&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;_&lt;/code&gt; (root)&lt;/td&gt;
&lt;td&gt;Domain&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;example.bit&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;d/example&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;_&lt;/code&gt; (root)&lt;/td&gt;
&lt;td&gt;Domain&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;d/example&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;d/example&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;_&lt;/code&gt; (root)&lt;/td&gt;
&lt;td&gt;Domain&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;id/alice&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;id/alice&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;_&lt;/code&gt; (root)&lt;/td&gt;
&lt;td&gt;Identity&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&#34;name-value-json-formats-2&#34;&gt;Name Value JSON Formats&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Domain simple:&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{&amp;#34;nostr&amp;#34;: &amp;#34;&amp;lt;64-char-hex-pubkey&amp;gt;&amp;#34;}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Domain extended (multi-user &#43; relays):&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{&amp;#34;nostr&amp;#34;: {&amp;#34;names&amp;#34;: {&amp;#34;_&amp;#34;: &amp;#34;&amp;lt;hex&amp;gt;&amp;#34;, &amp;#34;alice&amp;#34;: &amp;#34;&amp;lt;hex&amp;gt;&amp;#34;}, &amp;#34;relays&amp;#34;: {&amp;#34;&amp;lt;hex&amp;gt;&amp;#34;: [&amp;#34;wss://...&amp;#34;]}}}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Identity simple:&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{&amp;#34;nostr&amp;#34;: &amp;#34;&amp;lt;64-char-hex-pubkey&amp;gt;&amp;#34;}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Identity with relays:&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{&amp;#34;nostr&amp;#34;: {&amp;#34;pubkey&amp;#34;: &amp;#34;&amp;lt;hex&amp;gt;&amp;#34;, &amp;#34;relays&amp;#34;: [&amp;#34;wss://...&amp;#34;]}}
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;namecoin-cli-commands-2&#34;&gt;Namecoin CLI Commands&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;# Register a new name
namecoin-cli name_new &amp;#34;d/yourname&amp;#34;
# Returns: [txid, random_value]
# Example:
#   [
#     &amp;#34;a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2&amp;#34;,
#     &amp;#34;6e4a2d190f7b&amp;#34;
#   ]
# SAVE BOTH — you need the random value (2nd element) for name_firstupdate.
# Wait for at least 12 confirmations (~2 hours) before proceeding.

# Finalize registration with the random value from name_new
namecoin-cli name_firstupdate &amp;#34;d/yourname&amp;#34; &amp;lt;random&amp;gt; &amp;#39;&amp;lt;json&amp;gt;&amp;#39;

# Update an existing name
namecoin-cli name_update &amp;#34;d/yourname&amp;#34; &amp;#39;&amp;lt;new_json&amp;gt;&amp;#39;

# Check a name&amp;#39;s current value
namecoin-cli name_show &amp;#34;d/yourname&amp;#34;

# List your names
namecoin-cli name_list
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;getting-namecoins-via-dvm-nip-90-2&#34;&gt;Getting Namecoins via DVM (NIP-90)&lt;/h3&gt;

&lt;p&gt;Don&amp;#39;t have NMC? You can acquire Namecoin through a Nostr-native exchange service — no centralized exchange account needed.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;NMC Exchange DVM&lt;/strong&gt; is a &lt;a href=&#34;https://github.com/nostr-protocol/nips/blob/master/90.md&#34;&gt;NIP-90 Data Vending Machine&lt;/a&gt; that accepts Lightning Bitcoin (⚡ sats) or Cashu ecash (🥜) and sends NMC directly to your Namecoin address.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Send a &lt;code&gt;kind:5950&lt;/code&gt; job request to the DVM with your NMC address and desired amount (0.2–0.5 NMC)&lt;/li&gt;
&lt;li&gt;The DVM responds with a Lightning invoice or Cashu payment info&lt;/li&gt;
&lt;li&gt;Pay via Lightning zap or Cashu ecash&lt;/li&gt;
&lt;li&gt;Receive NMC at your designated address — the DVM sends the &lt;code&gt;kind:6950&lt;/code&gt; result with the NMC transaction ID&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Rate:&lt;/strong&gt; $10 USD per NMC (max 0.5 NMC per order)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Payment methods:&lt;/strong&gt; Lightning Bitcoin ⚡ | Cashu ecash 🥜&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DVM address (NIP-89):&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&lt;span itemprop=&#34;mentions&#34; itemscope itemtype=&#34;https://schema.org/Article&#34;&gt;&lt;a itemprop=&#34;url&#34; href=&#34;/naddr1qvzqqqru7cpzqscctm0vke6cj2pykx3h54lnusrlhh3wmfeqrguznwx0fwnutd8sqy2hwumn8ghj7un9d3shjtnyd968gmewwp6kyqqsdekkxtt90p3ksctwvajj6erkd5njfjn5&#34; class=&#34;bg-lavender dark:prose:text-neutral-50 dark:text-neutral-50 dark:bg-garnet px-1&#34;&gt;naddr1qv…fjn5&lt;/a&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;View on NostrHub:&lt;/strong&gt; &lt;a href=&#34;https://nostrhub.io/naddr1qvzqqqru7cpzqscctm0vke6cj2pykx3h54lnusrlhh3wmfeqrguznwx0fwnutd8sqy2hwumn8ghj7un9d3shjtnyd968gmewwp6kyqqsdekkxtt90p3ksctwvajj6erkd5njfjn5&#34;&gt;NMC Exchange DVM&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example job request:&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{
  &amp;#34;kind&amp;#34;: 5950,
  &amp;#34;tags&amp;#34;: [
    [&amp;#34;i&amp;#34;, &amp;#34;&amp;lt;your-nmc-address&amp;gt;&amp;#34;, &amp;#34;text&amp;#34;],
    [&amp;#34;param&amp;#34;, &amp;#34;amount&amp;#34;, &amp;#34;0.5&amp;#34;],
    [&amp;#34;bid&amp;#34;, &amp;#34;10000000&amp;#34;]
  ],
  &amp;#34;content&amp;#34;: &amp;#34;&amp;#34;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is an experimental service — no guarantees of uptime, but it&amp;#39;s a quick way to get NMC for name registrations without touching a centralized exchange.&lt;/p&gt;

&lt;h3 id=&#34;testing-for-developers-2&#34;&gt;Testing (for Developers)&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;# Run unit tests
./gradlew :quartz:jvmTest --tests &amp;#34;*NamecoinNameResolverTest*&amp;#34;

# Build and install debug APK
./gradlew assemblePlayDebug
adb install -r amethyst/build/outputs/apk/play/debug/amethyst-play-universal-debug.apk

# Monitor ElectrumX connections
adb root &amp;amp;&amp;amp; adb shell tcpdump -i any -nn port 50002 or port 50006
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;live-test-data-2&#34;&gt;Live Test Data&lt;/h3&gt;

&lt;p&gt;The name &lt;code&gt;d/testls&lt;/code&gt; is registered on the Namecoin blockchain with value:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{&amp;#34;nostr&amp;#34;: {&amp;#34;names&amp;#34;: {&amp;#34;_&amp;#34;: &amp;#34;6cdebccabda1dfa058ab85352a79509b592b2bdfa0370325e28ec1cb4f18667d&amp;#34;}}}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So &lt;code&gt;_@testls.bit&lt;/code&gt; (or simply &lt;code&gt;testls.bit&lt;/code&gt;) resolves to Vitor Pamplona&amp;#39;s Nostr profile.&lt;/p&gt;
 &lt;/blockquote&gt;&lt;br/&gt;The cypherpunk use case Satoshi envisioned for merged mining is more relevant now than ever.
    </content>
    <updated>2026-04-08T08:33:05Z</updated>
  </entry>

  <entry>
    <id>https://njump.me/nevent1qqsqmltjktqdzrdxp3q8ynxges8k6jvqzcvfay4yk62ryyyh0m3s29czypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60q3nc2zj</id>
    
      <title type="html">Usage stats for .bit domains don&amp;#39;t tell the whole story. ...</title>
    
    <link rel="alternate" href="https://njump.me/nevent1qqsqmltjktqdzrdxp3q8ynxges8k6jvqzcvfay4yk62ryyyh0m3s29czypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60q3nc2zj" />
    <content type="html">
      In reply to &lt;a href=&#39;/nevent1qqsg4l7es7fdcuwen5c8wdwy4ss94lzvl5q456qhfqtgmf8vwxmecfqpz3mhxue69uhhyetvv9ujuerpd46hxtnfdua37frf&#39;&gt;nevent1q…7frf&lt;/a&gt;&lt;br/&gt;_________________________&lt;br/&gt;&lt;br/&gt;Usage stats for .bit domains don&amp;#39;t tell the whole story. Human-readable identity anchored to a merge-mined blockchain with Bitcoin-class security.&lt;br/&gt;&lt;br/&gt;We&amp;#39;re building on it right now for Nostr reputation infrastructure:&lt;br/&gt;&lt;blockquote class=&#34;border-l-05rem border-l-strongpink border-solid&#34;&gt;&lt;div class=&#34;-ml-4 bg-gradient-to-r from-gray-100 dark:from-zinc-800 to-transparent mr-0 mt-0 mb-4 pl-4 pr-2 py-2&#34;&gt;quoting &lt;br/&gt;&lt;span itemprop=&#34;mentions&#34; itemscope itemtype=&#34;https://schema.org/Article&#34;&gt;&lt;a itemprop=&#34;url&#34; href=&#34;/naddr1qvzqqqr4gupzqscctm0vke6cj2pykx3h54lnusrlhh3wmfeqrguznwx0fwnutd8sqq3kuctdv43k76tw945kuar9vaexzarfdahz6ctdv46xs7tnwskkwatfv3jsz0753t&#34; class=&#34;bg-lavender dark:prose:text-neutral-50 dark:text-neutral-50 dark:bg-garnet px-1&#34;&gt;naddr1qv…753t&lt;/a&gt;&lt;/span&gt;&lt;br/&gt; &lt;/div&gt; 
&lt;h1 id=&#34;how-to-guide-namecoin-integration-in-amethyst-5&#34;&gt;How-To Guide: Namecoin Integration in Amethyst&lt;/h1&gt;

&lt;h2 id=&#34;what-this-is-5&#34;&gt;What This Is&lt;/h2&gt;

&lt;p&gt;Amethyst — the Android Nostr client — includes built-in support for resolving Namecoin blockchain names as NIP-05 identities. Instead of relying on a web server to verify &lt;code&gt;alice@example.com&lt;/code&gt;, a user can set their NIP-05 address to something like &lt;code&gt;alice@example.bit&lt;/code&gt;, and Amethyst will verify it directly against the Namecoin blockchain via ElectrumX servers.&lt;/p&gt;

&lt;p&gt;This is censorship-resistant identity: no web server to seize, no DNS to hijack, no TLS certificate to revoke. The name-to-pubkey mapping lives in Namecoin UTXOs.&lt;/p&gt;

&lt;p&gt;This guide covers how the system works, how to use it as an end-user, and how to register or update a Namecoin name value so that it resolves to your Nostr pubkey.&lt;/p&gt;

&lt;hr&gt;

&lt;h2 id=&#34;part-1-using-namecoin-names-in-amethyst-end-user-5&#34;&gt;Part 1: Using Namecoin Names in Amethyst (End-User)&lt;/h2&gt;

&lt;h3 id=&#34;searching-for-namecoin-users-5&#34;&gt;Searching for Namecoin Users&lt;/h3&gt;

&lt;p&gt;Open Amethyst&amp;#39;s search bar and type any of these formats:&lt;/p&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Search Input&lt;/th&gt;
&lt;th&gt;What It Does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;alice@example.bit&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Looks up the &lt;code&gt;alice&lt;/code&gt; entry in Namecoin name &lt;code&gt;d/example&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;example.bit&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Looks up the root (&lt;code&gt;_&lt;/code&gt;) entry in &lt;code&gt;d/example&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;d/example&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Direct Namecoin domain namespace lookup (root entry)&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;id/alice&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Direct Namecoin identity namespace lookup&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Amethyst queries the Namecoin blockchain through an ElectrumX server, resolves the name to a Nostr public key, and shows the matching user profile at the top of search results. There is a 400ms debounce on the search input to avoid flooding the server with requests.&lt;/p&gt;

&lt;h3 id=&#34;nip-05-verification-via-namecoin-5&#34;&gt;NIP-05 Verification via Namecoin&lt;/h3&gt;

&lt;p&gt;If a Nostr profile has a &lt;code&gt;.bit&lt;/code&gt; address in its &lt;code&gt;nip05&lt;/code&gt; metadata field (e.g. &lt;code&gt;m@testls.bit&lt;/code&gt;), Amethyst will automatically verify it against the blockchain instead of making an HTTP request. The verification badge works the same as traditional NIP-05 — the only difference is the trust anchor: blockchain consensus rather than a web server.&lt;/p&gt;

&lt;h3 id=&#34;configuring-namecoin-settings-5&#34;&gt;Configuring Namecoin Settings&lt;/h3&gt;

&lt;p&gt;Navigate to &lt;strong&gt;Settings → Namecoin Settings&lt;/strong&gt; in Amethyst. From here you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Enable/disable&lt;/strong&gt; Namecoin resolution entirely&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Add custom ElectrumX servers&lt;/strong&gt; — useful if you run your own server for privacy&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Remove servers&lt;/strong&gt; from the custom list&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Test server connectivity&lt;/strong&gt; — checks TLS, latency, and optionally resolves a test name&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pin TLS certificates&lt;/strong&gt; — after testing a server with a self-signed cert, you can pin its certificate via TOFU (Trust On First Use)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reset to defaults&lt;/strong&gt; — reverts to the built-in server list&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&#34;server-string-format-5&#34;&gt;Server String Format&lt;/h4&gt;

&lt;p&gt;When adding a custom server, use the format:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;host:port          → TLS connection (default)
host:port:tcp      → Plaintext TCP (for .onion or local servers)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;electrumx.testls.space:50002
my-local-server.lan:50001:tcp
i665jpw...dsid.onion:50002
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;tor-integration-5&#34;&gt;Tor Integration&lt;/h3&gt;

&lt;p&gt;If you have Tor enabled in Amethyst and have set &amp;#34;NIP-05 verifications via Tor&amp;#34; to on, all Namecoin ElectrumX connections are routed through your Tor SOCKS proxy. The server list also switches to prioritize &lt;code&gt;.onion&lt;/code&gt; addresses:&lt;/p&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tor Setting&lt;/th&gt;
&lt;th&gt;Primary Server&lt;/th&gt;
&lt;th&gt;Fallback&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Off&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;electrumx.testls.space:50002&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;nmc2.bitcoins.sk:57002&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;On&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.onion:50002&lt;/code&gt; (hidden service)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;electrumx.testls.space:50002&lt;/code&gt; (via Tor)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Toggling Tor on or off in settings takes effect on the next lookup — no app restart needed.&lt;/p&gt;

&lt;h3 id=&#34;default-electrumx-servers-5&#34;&gt;Default ElectrumX Servers&lt;/h3&gt;

&lt;p&gt;Amethyst ships with these built-in servers:&lt;/p&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Server&lt;/th&gt;
&lt;th&gt;Port&lt;/th&gt;
&lt;th&gt;TLS&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;electrumx.testls.space&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;50002&lt;/td&gt;
&lt;td&gt;Yes (self-signed, pinned)&lt;/td&gt;
&lt;td&gt;Primary&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;nmc2.bitcoins.sk&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;57002&lt;/td&gt;
&lt;td&gt;Yes (self-signed, pinned)&lt;/td&gt;
&lt;td&gt;Fallback&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;46.229.238.187&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;57002&lt;/td&gt;
&lt;td&gt;Yes (self-signed, pinned)&lt;/td&gt;
&lt;td&gt;IP fallback&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The self-signed certificates for these servers are pinned directly into the Amethyst binary, so connections succeed even on devices with strict TLS enforcement (Samsung One UI 7, GrapheneOS).&lt;/p&gt;

&lt;hr&gt;

&lt;h2 id=&#34;part-2-registering-updating-a-namecoin-name-value-5&#34;&gt;Part 2: Registering &amp;amp; Updating a Namecoin Name Value&lt;/h2&gt;

&lt;p&gt;Amethyst itself is a &lt;strong&gt;read-only&lt;/strong&gt; consumer of Namecoin data — it resolves names but does not write to the blockchain. To register or update a Namecoin name so that it points to your Nostr pubkey, you need to interact with the Namecoin blockchain directly using Namecoin Core (the full node software) or a compatible wallet.&lt;/p&gt;

&lt;h3 id=&#34;prerequisites-6&#34;&gt;Prerequisites&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Namecoin Core&lt;/strong&gt; or &lt;strong&gt;Electrum-NMC&lt;/strong&gt; installed and synced — download from &lt;a href=&#34;https://www.namecoin.org/&#34;&gt;namecoin.org&lt;/a&gt; (this guide uses Namecoin Core as an example)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;NMC (Namecoin coins)&lt;/strong&gt; in your wallet — needed to pay registration and update fees (0.01 NMC per registration operation plus associated fees)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Your Nostr hex public key&lt;/strong&gt; — the 64-character hex string (not &lt;code&gt;npub1...&lt;/code&gt;). You can find this in Amethyst under your profile settings or by converting your npub using a tool like &lt;a href=&#34;https://nostrdeck.com/key-converter.php&#34;&gt;https://nostrdeck.com/key-converter.php&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&#34;step-1-choose-your-namespace-5&#34;&gt;Step 1: Choose Your Namespace&lt;/h3&gt;

&lt;p&gt;Amethyst supports two Namecoin namespaces:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Domain namespace (&lt;code&gt;d/&lt;/code&gt;)&lt;/strong&gt; — maps a domain-like name to one or more Nostr pubkeys. This is the most common choice and mirrors NIP-05&amp;#39;s &lt;code&gt;user@domain&lt;/code&gt; format.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Identity namespace (&lt;code&gt;id/&lt;/code&gt;)&lt;/strong&gt; — maps a personal identity name to a single Nostr pubkey.&lt;/p&gt;

&lt;p&gt;For most users, the &lt;code&gt;d/&lt;/code&gt; namespace is the right choice because it allows &lt;code&gt;user@name.bit&lt;/code&gt; style addresses.&lt;/p&gt;

&lt;h3 id=&#34;step-2-register-a-new-name-5&#34;&gt;Step 2: Register a New Name&lt;/h3&gt;

&lt;p&gt;Open a terminal and use &lt;code&gt;namecoin-cli&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# Register a name in the domain namespace
# This creates a &amp;#34;pre-registration&amp;#34; (name_new) first
namecoin-cli name_new &amp;#34;d/yourname&amp;#34;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This returns a transaction ID and a random value. &lt;strong&gt;Save both&lt;/strong&gt; — you need the random value for the next step. Wait for the transaction to get at least 12 confirmations (about 2 hours).&lt;/p&gt;

&lt;p&gt;Then finalize the registration:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;namecoin-cli name_firstupdate &amp;#34;d/yourname&amp;#34; &amp;lt;random_value&amp;gt; &amp;#39;&amp;lt;json_value&amp;gt;&amp;#39;
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;step-3-set-the-name-value-for-nostr-5&#34;&gt;Step 3: Set the Name Value for Nostr&lt;/h3&gt;

&lt;p&gt;The JSON value you store in the Namecoin name is what Amethyst reads to find your Nostr pubkey. There are several supported formats.&lt;/p&gt;

&lt;h4 id=&#34;simple-form-single-user-root-domain-5&#34;&gt;Simple Form — Single User, Root Domain&lt;/h4&gt;

&lt;p&gt;If you just want &lt;code&gt;yourname.bit&lt;/code&gt; to resolve to your pubkey:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{
  &amp;#34;nostr&amp;#34;: &amp;#34;b0635d6a9851d3aed0cd6c495b282167acf761729078d975fc341b22650b07b9&amp;#34;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code&gt;namecoin-cli name_firstupdate &amp;#34;d/yourname&amp;#34; &amp;lt;random&amp;gt; \
  &amp;#39;{&amp;#34;nostr&amp;#34;:&amp;#34;b0635d6a9851d3aed0cd6c495b282167acf761729078d975fc341b22650b07b9&amp;#34;}&amp;#39;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This makes &lt;code&gt;yourname.bit&lt;/code&gt; and &lt;code&gt;_@yourname.bit&lt;/code&gt; resolve to the given pubkey.&lt;/p&gt;

&lt;h4 id=&#34;extended-form-multiple-users-with-relay-hints-5&#34;&gt;Extended Form — Multiple Users with Relay Hints&lt;/h4&gt;

&lt;p&gt;If you want to host multiple identities under one &lt;code&gt;.bit&lt;/code&gt; domain (like a NIP-05 server hosting multiple users):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{
  &amp;#34;nostr&amp;#34;: {
    &amp;#34;names&amp;#34;: {
      &amp;#34;_&amp;#34;: &amp;#34;aaaa000000000000000000000000000000000000000000000000000000000001&amp;#34;,
      &amp;#34;alice&amp;#34;: &amp;#34;bbbb000000000000000000000000000000000000000000000000000000000002&amp;#34;,
      &amp;#34;bob&amp;#34;: &amp;#34;cccc000000000000000000000000000000000000000000000000000000000003&amp;#34;
    },
    &amp;#34;relays&amp;#34;: {
      &amp;#34;bbbb000000000000000000000000000000000000000000000000000000000002&amp;#34;: [
        &amp;#34;wss://relay.example.com&amp;#34;,
        &amp;#34;wss://nos.lol&amp;#34;
      ]
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;With this value stored in &lt;code&gt;d/yourname&lt;/code&gt;:
- &lt;code&gt;_@yourname.bit&lt;/code&gt; or &lt;code&gt;yourname.bit&lt;/code&gt; → resolves to the &lt;code&gt;_&lt;/code&gt; pubkey
- &lt;code&gt;alice@yourname.bit&lt;/code&gt; → resolves to Alice&amp;#39;s pubkey, with relay hints
- &lt;code&gt;bob@yourname.bit&lt;/code&gt; → resolves to Bob&amp;#39;s pubkey&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;namecoin-cli name_firstupdate &amp;#34;d/yourname&amp;#34; &amp;lt;random&amp;gt; \
  &amp;#39;{&amp;#34;nostr&amp;#34;:{&amp;#34;names&amp;#34;:{&amp;#34;_&amp;#34;:&amp;#34;aaaa...0001&amp;#34;,&amp;#34;alice&amp;#34;:&amp;#34;bbbb...0002&amp;#34;},&amp;#34;relays&amp;#34;:{&amp;#34;bbbb...0002&amp;#34;:[&amp;#34;wss://relay.example.com&amp;#34;]}}}&amp;#39;
&lt;/code&gt;&lt;/pre&gt;

&lt;h4 id=&#34;identity-namespace-form-id-5&#34;&gt;Identity Namespace Form (&lt;code&gt;id/&lt;/code&gt;)&lt;/h4&gt;

&lt;p&gt;For the &lt;code&gt;id/&lt;/code&gt; namespace, the value format is simpler:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{
  &amp;#34;nostr&amp;#34;: &amp;#34;cccc000000000000000000000000000000000000000000000000000000000003&amp;#34;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Or with relay hints:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{
  &amp;#34;nostr&amp;#34;: {
    &amp;#34;pubkey&amp;#34;: &amp;#34;dddd000000000000000000000000000000000000000000000000000000000004&amp;#34;,
    &amp;#34;relays&amp;#34;: [&amp;#34;wss://relay.example.com&amp;#34;]
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code&gt;namecoin-cli name_firstupdate &amp;#34;id/youridentity&amp;#34; &amp;lt;random&amp;gt; \
  &amp;#39;{&amp;#34;nostr&amp;#34;:{&amp;#34;pubkey&amp;#34;:&amp;#34;dddd...0004&amp;#34;,&amp;#34;relays&amp;#34;:[&amp;#34;wss://relay.example.com&amp;#34;]}}&amp;#39;
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;step-4-update-an-existing-name-5&#34;&gt;Step 4: Update an Existing Name&lt;/h3&gt;

&lt;p&gt;To change the Nostr pubkey (or any other data) associated with an already-registered name, use &lt;code&gt;name_update&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;namecoin-cli name_update &amp;#34;d/yourname&amp;#34; \
  &amp;#39;{&amp;#34;nostr&amp;#34;:{&amp;#34;names&amp;#34;:{&amp;#34;_&amp;#34;:&amp;#34;&amp;lt;new_hex_pubkey&amp;gt;&amp;#34;,&amp;#34;alice&amp;#34;:&amp;#34;&amp;lt;alice_hex_pubkey&amp;gt;&amp;#34;},&amp;#34;relays&amp;#34;:{&amp;#34;&amp;lt;alice_hex_pubkey&amp;gt;&amp;#34;:[&amp;#34;wss://relay.example.com&amp;#34;]}}}&amp;#39;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This broadcasts a &lt;code&gt;NAME_UPDATE&lt;/code&gt; transaction to the Namecoin blockchain. Once confirmed, Amethyst (and any other client that supports Namecoin NIP-05) will resolve the name to the new value.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Important notes on updates:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each &lt;code&gt;name_update&lt;/code&gt; costs a small NMC fee&lt;/li&gt;
&lt;li&gt;Names expire after &lt;strong&gt;36,000 blocks&lt;/strong&gt; (~36 weeks) if not updated or renewed. Amethyst checks expiry and will treat expired names as non-existent.&lt;/li&gt;
&lt;li&gt;To simply renew without changing the value, you can &lt;code&gt;name_update&lt;/code&gt; with the same value&lt;/li&gt;
&lt;li&gt;Updates replace the entire value — there is no partial update mechanism&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&#34;step-5-set-your-nip-05-in-your-nostr-profile-5&#34;&gt;Step 5: Set Your NIP-05 in Your Nostr Profile&lt;/h3&gt;

&lt;p&gt;Once your Namecoin name is registered and confirmed on the blockchain, update your Nostr profile&amp;#39;s &lt;code&gt;nip05&lt;/code&gt; field in Amethyst:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to your profile → Edit&lt;/li&gt;
&lt;li&gt;Set the NIP-05 field to your Namecoin address, e.g. &lt;code&gt;alice@yourname.bit&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Save&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Amethyst (and other Namecoin-aware clients) will verify this address against the blockchain and show the verification badge.&lt;/p&gt;

&lt;h3 id=&#34;step-6-verify-it-works-5&#34;&gt;Step 6: Verify It Works&lt;/h3&gt;

&lt;p&gt;In Amethyst&amp;#39;s search bar, type your Namecoin identifier. You should see your profile appear at the top of results:&lt;/p&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Test Query&lt;/th&gt;
&lt;th&gt;Expected Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;alice@yourname.bit&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Your profile (matched via &lt;code&gt;alice&lt;/code&gt; entry)&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;yourname.bit&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Your profile (matched via &lt;code&gt;_&lt;/code&gt; root entry)&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;d/yourname&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Your profile (direct namespace lookup)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;hr&gt;

&lt;h2 id=&#34;part-3-how-it-works-under-the-hood-5&#34;&gt;Part 3: How It Works Under the Hood&lt;/h2&gt;

&lt;h3 id=&#34;resolution-flow-5&#34;&gt;Resolution Flow&lt;/h3&gt;

&lt;p&gt;When Amethyst encounters a &lt;code&gt;.bit&lt;/code&gt; address, here is what happens:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;1. User types &amp;#34;alice@example.bit&amp;#34; in search (or a profile has it in nip05)

2. NamecoinNameResolver.parseIdentifier() parses it:
   → namecoinName = &amp;#34;d/example&amp;#34;, localPart = &amp;#34;alice&amp;#34;, namespace = DOMAIN

3. ElectrumXClient builds a canonical &amp;#34;name index script&amp;#34;:
   OP_NAME_UPDATE(0x53) &#43; push(&amp;#34;d/example&amp;#34;) &#43; push(&amp;#34;&amp;#34;) &#43; OP_2DROP &#43; OP_DROP &#43; OP_RETURN

4. Computes the Electrum-style scripthash:
   SHA-256(script) → reverse bytes → hex encode

5. Queries the ElectrumX server:
   → blockchain.scripthash.get_history(scripthash)
   ← [{tx_hash: &amp;#34;abc...&amp;#34;, height: 814278}, ...]

6. Fetches the latest transaction (last entry = most recent name update):
   → blockchain.transaction.get(tx_hash, verbose=true)

7. Checks block headers to verify the name hasn&amp;#39;t expired:
   → blockchain.headers.subscribe
   ← current height; if (current - update_height) &amp;gt;= 36000 → expired

8. Parses the NAME_UPDATE script from the transaction output:
   Extracts: name string &#43; JSON value

9. NamecoinNameResolver.extractFromDomainValue() reads the JSON:
   Finds &amp;#34;nostr&amp;#34; → &amp;#34;names&amp;#34; → &amp;#34;alice&amp;#34; → hex pubkey

10. Returns NamecoinNostrResult(pubkey, relays, namecoinName, localPart)
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;caching-5&#34;&gt;Caching&lt;/h3&gt;

&lt;p&gt;Resolved names are cached in an LRU cache (default 500 entries, 1-hour TTL). Both positive and negative results are cached. The cache is keyed by the normalized (lowercased, trimmed) identifier.&lt;/p&gt;

&lt;h3 id=&#34;architecture-layers-5&#34;&gt;Architecture Layers&lt;/h3&gt;

&lt;p&gt;The implementation is split across two modules:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Quartz (library, no Android dependencies):&lt;/strong&gt;
- &lt;code&gt;NamecoinNameResolver&lt;/code&gt; — identifier parsing, value extraction, resolution orchestration
- &lt;code&gt;ElectrumXClient&lt;/code&gt; — TCP/TLS connection to ElectrumX, JSON-RPC, script parsing
- &lt;code&gt;NamecoinLookupCache&lt;/code&gt; — LRU cache with TTL
- &lt;code&gt;IElectrumXClient&lt;/code&gt; — interface for testing/mocking&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Amethyst (Android app):&lt;/strong&gt;
- &lt;code&gt;NamecoinNameService&lt;/code&gt; — application singleton, wires up caching and proxy-aware client
- &lt;code&gt;NamecoinSettings&lt;/code&gt; / &lt;code&gt;NamecoinSharedPreferences&lt;/code&gt; — persistent config
- &lt;code&gt;NamecoinSettingsScreen&lt;/code&gt; / &lt;code&gt;NamecoinSettingsSection&lt;/code&gt; — settings UI
- &lt;code&gt;ProxiedSocketFactory&lt;/code&gt; — SOCKS5 proxy routing for Tor
- &lt;code&gt;RoleBasedHttpClientBuilder.socketFactoryForNip05()&lt;/code&gt; — Tor-aware socket creation&lt;/p&gt;

&lt;p&gt;The integration into NIP-05 is minimal: &lt;code&gt;Nip05Client&lt;/code&gt; checks if an identifier matches &lt;code&gt;.bit&lt;/code&gt; / &lt;code&gt;d/&lt;/code&gt; / &lt;code&gt;id/&lt;/code&gt; patterns, and routes to &lt;code&gt;NamecoinNameResolver&lt;/code&gt; instead of making an HTTP fetch. Non-Namecoin identifiers are completely unaffected.&lt;/p&gt;

&lt;hr&gt;

&lt;h2 id=&#34;part-4-security-considerations-5&#34;&gt;Part 4: Security Considerations&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Tor integration&lt;/strong&gt; — When enabled, all ElectrumX connections go through the Tor SOCKS proxy. The &lt;code&gt;.onion&lt;/code&gt; server is preferred for end-to-end onion routing. Socket factory and server list are evaluated per-request via lambdas, so toggling Tor takes effect immediately.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TLS certificate pinning&lt;/strong&gt; — The primary ElectrumX servers use self-signed certificates. Their PEM-encoded certs are pinned in the Amethyst binary. Users can pin additional certs via the TOFU flow in settings (test server → view fingerprint → confirm → pin). This is necessary because Samsung One UI 7 and GrapheneOS reject trust-all TrustManagers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Name expiry&lt;/strong&gt; — Namecoin names expire after ~36,000 blocks (~250 days) if not renewed. The ElectrumX client checks the current block height against the name&amp;#39;s last update height and treats expired names as non-existent.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Server trust&lt;/strong&gt; — The client trusts that the ElectrumX server returns accurate transaction data. The Namecoin blockchain itself is the trust anchor — a MITM could return stale data but cannot forge name registrations. For higher assurance, SPV proof verification could be added in the future.&lt;/p&gt;

&lt;hr&gt;

&lt;h2 id=&#34;quick-reference-5&#34;&gt;Quick Reference&lt;/h2&gt;

&lt;h3 id=&#34;identifier-format-summary-5&#34;&gt;Identifier Format Summary&lt;/h3&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;User Input&lt;/th&gt;
&lt;th&gt;Namecoin Name&lt;/th&gt;
&lt;th&gt;Looked-Up Entry&lt;/th&gt;
&lt;th&gt;Namespace&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;alice@example.bit&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;d/example&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;alice&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Domain&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;_@example.bit&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;d/example&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;_&lt;/code&gt; (root)&lt;/td&gt;
&lt;td&gt;Domain&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;example.bit&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;d/example&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;_&lt;/code&gt; (root)&lt;/td&gt;
&lt;td&gt;Domain&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;d/example&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;d/example&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;_&lt;/code&gt; (root)&lt;/td&gt;
&lt;td&gt;Domain&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;id/alice&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;id/alice&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;_&lt;/code&gt; (root)&lt;/td&gt;
&lt;td&gt;Identity&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&#34;name-value-json-formats-5&#34;&gt;Name Value JSON Formats&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Domain simple:&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{&amp;#34;nostr&amp;#34;: &amp;#34;&amp;lt;64-char-hex-pubkey&amp;gt;&amp;#34;}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Domain extended (multi-user &#43; relays):&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{&amp;#34;nostr&amp;#34;: {&amp;#34;names&amp;#34;: {&amp;#34;_&amp;#34;: &amp;#34;&amp;lt;hex&amp;gt;&amp;#34;, &amp;#34;alice&amp;#34;: &amp;#34;&amp;lt;hex&amp;gt;&amp;#34;}, &amp;#34;relays&amp;#34;: {&amp;#34;&amp;lt;hex&amp;gt;&amp;#34;: [&amp;#34;wss://...&amp;#34;]}}}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Identity simple:&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{&amp;#34;nostr&amp;#34;: &amp;#34;&amp;lt;64-char-hex-pubkey&amp;gt;&amp;#34;}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Identity with relays:&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{&amp;#34;nostr&amp;#34;: {&amp;#34;pubkey&amp;#34;: &amp;#34;&amp;lt;hex&amp;gt;&amp;#34;, &amp;#34;relays&amp;#34;: [&amp;#34;wss://...&amp;#34;]}}
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;namecoin-cli-commands-5&#34;&gt;Namecoin CLI Commands&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;# Register a new name
namecoin-cli name_new &amp;#34;d/yourname&amp;#34;
# Returns: [txid, random_value]
# Example:
#   [
#     &amp;#34;a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2&amp;#34;,
#     &amp;#34;6e4a2d190f7b&amp;#34;
#   ]
# SAVE BOTH — you need the random value (2nd element) for name_firstupdate.
# Wait for at least 12 confirmations (~2 hours) before proceeding.

# Finalize registration with the random value from name_new
namecoin-cli name_firstupdate &amp;#34;d/yourname&amp;#34; &amp;lt;random&amp;gt; &amp;#39;&amp;lt;json&amp;gt;&amp;#39;

# Update an existing name
namecoin-cli name_update &amp;#34;d/yourname&amp;#34; &amp;#39;&amp;lt;new_json&amp;gt;&amp;#39;

# Check a name&amp;#39;s current value
namecoin-cli name_show &amp;#34;d/yourname&amp;#34;

# List your names
namecoin-cli name_list
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;getting-namecoins-via-dvm-nip-90-5&#34;&gt;Getting Namecoins via DVM (NIP-90)&lt;/h3&gt;

&lt;p&gt;Don&amp;#39;t have NMC? You can acquire Namecoin through a Nostr-native exchange service — no centralized exchange account needed.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;NMC Exchange DVM&lt;/strong&gt; is a &lt;a href=&#34;https://github.com/nostr-protocol/nips/blob/master/90.md&#34;&gt;NIP-90 Data Vending Machine&lt;/a&gt; that accepts Lightning Bitcoin (⚡ sats) or Cashu ecash (🥜) and sends NMC directly to your Namecoin address.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Send a &lt;code&gt;kind:5950&lt;/code&gt; job request to the DVM with your NMC address and desired amount (0.2–0.5 NMC)&lt;/li&gt;
&lt;li&gt;The DVM responds with a Lightning invoice or Cashu payment info&lt;/li&gt;
&lt;li&gt;Pay via Lightning zap or Cashu ecash&lt;/li&gt;
&lt;li&gt;Receive NMC at your designated address — the DVM sends the &lt;code&gt;kind:6950&lt;/code&gt; result with the NMC transaction ID&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Rate:&lt;/strong&gt; $10 USD per NMC (max 0.5 NMC per order)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Payment methods:&lt;/strong&gt; Lightning Bitcoin ⚡ | Cashu ecash 🥜&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DVM address (NIP-89):&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&lt;span itemprop=&#34;mentions&#34; itemscope itemtype=&#34;https://schema.org/Article&#34;&gt;&lt;a itemprop=&#34;url&#34; href=&#34;/naddr1qvzqqqru7cpzqscctm0vke6cj2pykx3h54lnusrlhh3wmfeqrguznwx0fwnutd8sqy2hwumn8ghj7un9d3shjtnyd968gmewwp6kyqqsdekkxtt90p3ksctwvajj6erkd5njfjn5&#34; class=&#34;bg-lavender dark:prose:text-neutral-50 dark:text-neutral-50 dark:bg-garnet px-1&#34;&gt;naddr1qv…fjn5&lt;/a&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;View on NostrHub:&lt;/strong&gt; &lt;a href=&#34;https://nostrhub.io/naddr1qvzqqqru7cpzqscctm0vke6cj2pykx3h54lnusrlhh3wmfeqrguznwx0fwnutd8sqy2hwumn8ghj7un9d3shjtnyd968gmewwp6kyqqsdekkxtt90p3ksctwvajj6erkd5njfjn5&#34;&gt;NMC Exchange DVM&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example job request:&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{
  &amp;#34;kind&amp;#34;: 5950,
  &amp;#34;tags&amp;#34;: [
    [&amp;#34;i&amp;#34;, &amp;#34;&amp;lt;your-nmc-address&amp;gt;&amp;#34;, &amp;#34;text&amp;#34;],
    [&amp;#34;param&amp;#34;, &amp;#34;amount&amp;#34;, &amp;#34;0.5&amp;#34;],
    [&amp;#34;bid&amp;#34;, &amp;#34;10000000&amp;#34;]
  ],
  &amp;#34;content&amp;#34;: &amp;#34;&amp;#34;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is an experimental service — no guarantees of uptime, but it&amp;#39;s a quick way to get NMC for name registrations without touching a centralized exchange.&lt;/p&gt;

&lt;h3 id=&#34;testing-for-developers-5&#34;&gt;Testing (for Developers)&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;# Run unit tests
./gradlew :quartz:jvmTest --tests &amp;#34;*NamecoinNameResolverTest*&amp;#34;

# Build and install debug APK
./gradlew assemblePlayDebug
adb install -r amethyst/build/outputs/apk/play/debug/amethyst-play-universal-debug.apk

# Monitor ElectrumX connections
adb root &amp;amp;&amp;amp; adb shell tcpdump -i any -nn port 50002 or port 50006
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;live-test-data-5&#34;&gt;Live Test Data&lt;/h3&gt;

&lt;p&gt;The name &lt;code&gt;d/testls&lt;/code&gt; is registered on the Namecoin blockchain with value:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{&amp;#34;nostr&amp;#34;: {&amp;#34;names&amp;#34;: {&amp;#34;_&amp;#34;: &amp;#34;6cdebccabda1dfa058ab85352a79509b592b2bdfa0370325e28ec1cb4f18667d&amp;#34;}}}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So &lt;code&gt;_@testls.bit&lt;/code&gt; (or simply &lt;code&gt;testls.bit&lt;/code&gt;) resolves to Vitor Pamplona&amp;#39;s Nostr profile.&lt;/p&gt;
 &lt;/blockquote&gt;&lt;br/&gt;Temporal identity binding, service attestations, Sybil resistance that doesn&amp;#39;t rely on a central authority. The kind of thing you can only do with a naming system that has immutable history and 13&#43; years of unbroken chain.&lt;br/&gt;&lt;br/&gt;Not dead — just quietly useful in ways that don&amp;#39;t show up on CoinMarketCap.
    </content>
    <updated>2026-04-08T08:31:24Z</updated>
  </entry>

  <entry>
    <id>https://njump.me/nevent1qqsg6g4ra7jjmjqmsjv8cx9z2cnt9wxkhwyyj98n89v25lnejfgx0wqzypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60qs3fajm</id>
    
      <title type="html">This is spot on. Satoshi saw merged mining as the way to ...</title>
    
    <link rel="alternate" href="https://njump.me/nevent1qqsg6g4ra7jjmjqmsjv8cx9z2cnt9wxkhwyyj98n89v25lnejfgx0wqzypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60qs3fajm" />
    <content type="html">
      In reply to &lt;a href=&#39;/nevent1qqstx4vqglk6lhrrg6kvcqynt6qpj2tdx4rdpm33yme65ra98gqg08gxkvxmt&#39;&gt;nevent1q…vxmt&lt;/a&gt;&lt;br/&gt;_________________________&lt;br/&gt;&lt;br/&gt;This is spot on. Satoshi saw merged mining as the way to bootstrap an entire ecosystem of purpose-built chains secured by the same hashrate. BitDNS/Namecoin was the proof of concept.&lt;br/&gt;&lt;br/&gt;What most people miss is that Namecoin&amp;#39;s id/ namespace gives you something no other system does: human-readable names with immutable, temporally ordered key bindings on a chain with Bitcoin-class security. That&amp;#39;s not a novelty — it&amp;#39;s infrastructure.&lt;br/&gt;&lt;br/&gt;We&amp;#39;re using it right now to build a Nostr reputation layer with blockchain-anchored identity proofs:&lt;br/&gt;&lt;blockquote class=&#34;border-l-05rem border-l-strongpink border-solid&#34;&gt;&lt;div class=&#34;-ml-4 bg-gradient-to-r from-gray-100 dark:from-zinc-800 to-transparent mr-0 mt-0 mb-4 pl-4 pr-2 py-2&#34;&gt;quoting &lt;br/&gt;&lt;span itemprop=&#34;mentions&#34; itemscope itemtype=&#34;https://schema.org/Article&#34;&gt;&lt;a itemprop=&#34;url&#34; href=&#34;/naddr1qvzqqqr4gupzqscctm0vke6cj2pykx3h54lnusrlhh3wmfeqrguznwx0fwnutd8sqq3kuctdv43k76tw945kuar9vaexzarfdahz6ctdv46xs7tnwskkwatfv3jsz0753t&#34; class=&#34;bg-lavender dark:prose:text-neutral-50 dark:text-neutral-50 dark:bg-garnet px-1&#34;&gt;naddr1qv…753t&lt;/a&gt;&lt;/span&gt;&lt;br/&gt; &lt;/div&gt; 
&lt;h1 id=&#34;how-to-guide-namecoin-integration-in-amethyst-8&#34;&gt;How-To Guide: Namecoin Integration in Amethyst&lt;/h1&gt;

&lt;h2 id=&#34;what-this-is-8&#34;&gt;What This Is&lt;/h2&gt;

&lt;p&gt;Amethyst — the Android Nostr client — includes built-in support for resolving Namecoin blockchain names as NIP-05 identities. Instead of relying on a web server to verify &lt;code&gt;alice@example.com&lt;/code&gt;, a user can set their NIP-05 address to something like &lt;code&gt;alice@example.bit&lt;/code&gt;, and Amethyst will verify it directly against the Namecoin blockchain via ElectrumX servers.&lt;/p&gt;

&lt;p&gt;This is censorship-resistant identity: no web server to seize, no DNS to hijack, no TLS certificate to revoke. The name-to-pubkey mapping lives in Namecoin UTXOs.&lt;/p&gt;

&lt;p&gt;This guide covers how the system works, how to use it as an end-user, and how to register or update a Namecoin name value so that it resolves to your Nostr pubkey.&lt;/p&gt;

&lt;hr&gt;

&lt;h2 id=&#34;part-1-using-namecoin-names-in-amethyst-end-user-8&#34;&gt;Part 1: Using Namecoin Names in Amethyst (End-User)&lt;/h2&gt;

&lt;h3 id=&#34;searching-for-namecoin-users-8&#34;&gt;Searching for Namecoin Users&lt;/h3&gt;

&lt;p&gt;Open Amethyst&amp;#39;s search bar and type any of these formats:&lt;/p&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Search Input&lt;/th&gt;
&lt;th&gt;What It Does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;alice@example.bit&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Looks up the &lt;code&gt;alice&lt;/code&gt; entry in Namecoin name &lt;code&gt;d/example&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;example.bit&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Looks up the root (&lt;code&gt;_&lt;/code&gt;) entry in &lt;code&gt;d/example&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;d/example&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Direct Namecoin domain namespace lookup (root entry)&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;id/alice&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Direct Namecoin identity namespace lookup&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Amethyst queries the Namecoin blockchain through an ElectrumX server, resolves the name to a Nostr public key, and shows the matching user profile at the top of search results. There is a 400ms debounce on the search input to avoid flooding the server with requests.&lt;/p&gt;

&lt;h3 id=&#34;nip-05-verification-via-namecoin-8&#34;&gt;NIP-05 Verification via Namecoin&lt;/h3&gt;

&lt;p&gt;If a Nostr profile has a &lt;code&gt;.bit&lt;/code&gt; address in its &lt;code&gt;nip05&lt;/code&gt; metadata field (e.g. &lt;code&gt;m@testls.bit&lt;/code&gt;), Amethyst will automatically verify it against the blockchain instead of making an HTTP request. The verification badge works the same as traditional NIP-05 — the only difference is the trust anchor: blockchain consensus rather than a web server.&lt;/p&gt;

&lt;h3 id=&#34;configuring-namecoin-settings-8&#34;&gt;Configuring Namecoin Settings&lt;/h3&gt;

&lt;p&gt;Navigate to &lt;strong&gt;Settings → Namecoin Settings&lt;/strong&gt; in Amethyst. From here you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Enable/disable&lt;/strong&gt; Namecoin resolution entirely&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Add custom ElectrumX servers&lt;/strong&gt; — useful if you run your own server for privacy&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Remove servers&lt;/strong&gt; from the custom list&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Test server connectivity&lt;/strong&gt; — checks TLS, latency, and optionally resolves a test name&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pin TLS certificates&lt;/strong&gt; — after testing a server with a self-signed cert, you can pin its certificate via TOFU (Trust On First Use)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reset to defaults&lt;/strong&gt; — reverts to the built-in server list&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&#34;server-string-format-8&#34;&gt;Server String Format&lt;/h4&gt;

&lt;p&gt;When adding a custom server, use the format:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;host:port          → TLS connection (default)
host:port:tcp      → Plaintext TCP (for .onion or local servers)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;electrumx.testls.space:50002
my-local-server.lan:50001:tcp
i665jpw...dsid.onion:50002
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;tor-integration-8&#34;&gt;Tor Integration&lt;/h3&gt;

&lt;p&gt;If you have Tor enabled in Amethyst and have set &amp;#34;NIP-05 verifications via Tor&amp;#34; to on, all Namecoin ElectrumX connections are routed through your Tor SOCKS proxy. The server list also switches to prioritize &lt;code&gt;.onion&lt;/code&gt; addresses:&lt;/p&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tor Setting&lt;/th&gt;
&lt;th&gt;Primary Server&lt;/th&gt;
&lt;th&gt;Fallback&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Off&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;electrumx.testls.space:50002&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;nmc2.bitcoins.sk:57002&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;On&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.onion:50002&lt;/code&gt; (hidden service)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;electrumx.testls.space:50002&lt;/code&gt; (via Tor)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Toggling Tor on or off in settings takes effect on the next lookup — no app restart needed.&lt;/p&gt;

&lt;h3 id=&#34;default-electrumx-servers-8&#34;&gt;Default ElectrumX Servers&lt;/h3&gt;

&lt;p&gt;Amethyst ships with these built-in servers:&lt;/p&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Server&lt;/th&gt;
&lt;th&gt;Port&lt;/th&gt;
&lt;th&gt;TLS&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;electrumx.testls.space&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;50002&lt;/td&gt;
&lt;td&gt;Yes (self-signed, pinned)&lt;/td&gt;
&lt;td&gt;Primary&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;nmc2.bitcoins.sk&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;57002&lt;/td&gt;
&lt;td&gt;Yes (self-signed, pinned)&lt;/td&gt;
&lt;td&gt;Fallback&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;46.229.238.187&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;57002&lt;/td&gt;
&lt;td&gt;Yes (self-signed, pinned)&lt;/td&gt;
&lt;td&gt;IP fallback&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The self-signed certificates for these servers are pinned directly into the Amethyst binary, so connections succeed even on devices with strict TLS enforcement (Samsung One UI 7, GrapheneOS).&lt;/p&gt;

&lt;hr&gt;

&lt;h2 id=&#34;part-2-registering-updating-a-namecoin-name-value-8&#34;&gt;Part 2: Registering &amp;amp; Updating a Namecoin Name Value&lt;/h2&gt;

&lt;p&gt;Amethyst itself is a &lt;strong&gt;read-only&lt;/strong&gt; consumer of Namecoin data — it resolves names but does not write to the blockchain. To register or update a Namecoin name so that it points to your Nostr pubkey, you need to interact with the Namecoin blockchain directly using Namecoin Core (the full node software) or a compatible wallet.&lt;/p&gt;

&lt;h3 id=&#34;prerequisites-9&#34;&gt;Prerequisites&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Namecoin Core&lt;/strong&gt; or &lt;strong&gt;Electrum-NMC&lt;/strong&gt; installed and synced — download from &lt;a href=&#34;https://www.namecoin.org/&#34;&gt;namecoin.org&lt;/a&gt; (this guide uses Namecoin Core as an example)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;NMC (Namecoin coins)&lt;/strong&gt; in your wallet — needed to pay registration and update fees (0.01 NMC per registration operation plus associated fees)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Your Nostr hex public key&lt;/strong&gt; — the 64-character hex string (not &lt;code&gt;npub1...&lt;/code&gt;). You can find this in Amethyst under your profile settings or by converting your npub using a tool like &lt;a href=&#34;https://nostrdeck.com/key-converter.php&#34;&gt;https://nostrdeck.com/key-converter.php&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&#34;step-1-choose-your-namespace-8&#34;&gt;Step 1: Choose Your Namespace&lt;/h3&gt;

&lt;p&gt;Amethyst supports two Namecoin namespaces:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Domain namespace (&lt;code&gt;d/&lt;/code&gt;)&lt;/strong&gt; — maps a domain-like name to one or more Nostr pubkeys. This is the most common choice and mirrors NIP-05&amp;#39;s &lt;code&gt;user@domain&lt;/code&gt; format.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Identity namespace (&lt;code&gt;id/&lt;/code&gt;)&lt;/strong&gt; — maps a personal identity name to a single Nostr pubkey.&lt;/p&gt;

&lt;p&gt;For most users, the &lt;code&gt;d/&lt;/code&gt; namespace is the right choice because it allows &lt;code&gt;user@name.bit&lt;/code&gt; style addresses.&lt;/p&gt;

&lt;h3 id=&#34;step-2-register-a-new-name-8&#34;&gt;Step 2: Register a New Name&lt;/h3&gt;

&lt;p&gt;Open a terminal and use &lt;code&gt;namecoin-cli&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# Register a name in the domain namespace
# This creates a &amp;#34;pre-registration&amp;#34; (name_new) first
namecoin-cli name_new &amp;#34;d/yourname&amp;#34;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This returns a transaction ID and a random value. &lt;strong&gt;Save both&lt;/strong&gt; — you need the random value for the next step. Wait for the transaction to get at least 12 confirmations (about 2 hours).&lt;/p&gt;

&lt;p&gt;Then finalize the registration:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;namecoin-cli name_firstupdate &amp;#34;d/yourname&amp;#34; &amp;lt;random_value&amp;gt; &amp;#39;&amp;lt;json_value&amp;gt;&amp;#39;
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;step-3-set-the-name-value-for-nostr-8&#34;&gt;Step 3: Set the Name Value for Nostr&lt;/h3&gt;

&lt;p&gt;The JSON value you store in the Namecoin name is what Amethyst reads to find your Nostr pubkey. There are several supported formats.&lt;/p&gt;

&lt;h4 id=&#34;simple-form-single-user-root-domain-8&#34;&gt;Simple Form — Single User, Root Domain&lt;/h4&gt;

&lt;p&gt;If you just want &lt;code&gt;yourname.bit&lt;/code&gt; to resolve to your pubkey:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{
  &amp;#34;nostr&amp;#34;: &amp;#34;b0635d6a9851d3aed0cd6c495b282167acf761729078d975fc341b22650b07b9&amp;#34;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code&gt;namecoin-cli name_firstupdate &amp;#34;d/yourname&amp;#34; &amp;lt;random&amp;gt; \
  &amp;#39;{&amp;#34;nostr&amp;#34;:&amp;#34;b0635d6a9851d3aed0cd6c495b282167acf761729078d975fc341b22650b07b9&amp;#34;}&amp;#39;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This makes &lt;code&gt;yourname.bit&lt;/code&gt; and &lt;code&gt;_@yourname.bit&lt;/code&gt; resolve to the given pubkey.&lt;/p&gt;

&lt;h4 id=&#34;extended-form-multiple-users-with-relay-hints-8&#34;&gt;Extended Form — Multiple Users with Relay Hints&lt;/h4&gt;

&lt;p&gt;If you want to host multiple identities under one &lt;code&gt;.bit&lt;/code&gt; domain (like a NIP-05 server hosting multiple users):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{
  &amp;#34;nostr&amp;#34;: {
    &amp;#34;names&amp;#34;: {
      &amp;#34;_&amp;#34;: &amp;#34;aaaa000000000000000000000000000000000000000000000000000000000001&amp;#34;,
      &amp;#34;alice&amp;#34;: &amp;#34;bbbb000000000000000000000000000000000000000000000000000000000002&amp;#34;,
      &amp;#34;bob&amp;#34;: &amp;#34;cccc000000000000000000000000000000000000000000000000000000000003&amp;#34;
    },
    &amp;#34;relays&amp;#34;: {
      &amp;#34;bbbb000000000000000000000000000000000000000000000000000000000002&amp;#34;: [
        &amp;#34;wss://relay.example.com&amp;#34;,
        &amp;#34;wss://nos.lol&amp;#34;
      ]
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;With this value stored in &lt;code&gt;d/yourname&lt;/code&gt;:
- &lt;code&gt;_@yourname.bit&lt;/code&gt; or &lt;code&gt;yourname.bit&lt;/code&gt; → resolves to the &lt;code&gt;_&lt;/code&gt; pubkey
- &lt;code&gt;alice@yourname.bit&lt;/code&gt; → resolves to Alice&amp;#39;s pubkey, with relay hints
- &lt;code&gt;bob@yourname.bit&lt;/code&gt; → resolves to Bob&amp;#39;s pubkey&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;namecoin-cli name_firstupdate &amp;#34;d/yourname&amp;#34; &amp;lt;random&amp;gt; \
  &amp;#39;{&amp;#34;nostr&amp;#34;:{&amp;#34;names&amp;#34;:{&amp;#34;_&amp;#34;:&amp;#34;aaaa...0001&amp;#34;,&amp;#34;alice&amp;#34;:&amp;#34;bbbb...0002&amp;#34;},&amp;#34;relays&amp;#34;:{&amp;#34;bbbb...0002&amp;#34;:[&amp;#34;wss://relay.example.com&amp;#34;]}}}&amp;#39;
&lt;/code&gt;&lt;/pre&gt;

&lt;h4 id=&#34;identity-namespace-form-id-8&#34;&gt;Identity Namespace Form (&lt;code&gt;id/&lt;/code&gt;)&lt;/h4&gt;

&lt;p&gt;For the &lt;code&gt;id/&lt;/code&gt; namespace, the value format is simpler:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{
  &amp;#34;nostr&amp;#34;: &amp;#34;cccc000000000000000000000000000000000000000000000000000000000003&amp;#34;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Or with relay hints:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{
  &amp;#34;nostr&amp;#34;: {
    &amp;#34;pubkey&amp;#34;: &amp;#34;dddd000000000000000000000000000000000000000000000000000000000004&amp;#34;,
    &amp;#34;relays&amp;#34;: [&amp;#34;wss://relay.example.com&amp;#34;]
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code&gt;namecoin-cli name_firstupdate &amp;#34;id/youridentity&amp;#34; &amp;lt;random&amp;gt; \
  &amp;#39;{&amp;#34;nostr&amp;#34;:{&amp;#34;pubkey&amp;#34;:&amp;#34;dddd...0004&amp;#34;,&amp;#34;relays&amp;#34;:[&amp;#34;wss://relay.example.com&amp;#34;]}}&amp;#39;
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;step-4-update-an-existing-name-8&#34;&gt;Step 4: Update an Existing Name&lt;/h3&gt;

&lt;p&gt;To change the Nostr pubkey (or any other data) associated with an already-registered name, use &lt;code&gt;name_update&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;namecoin-cli name_update &amp;#34;d/yourname&amp;#34; \
  &amp;#39;{&amp;#34;nostr&amp;#34;:{&amp;#34;names&amp;#34;:{&amp;#34;_&amp;#34;:&amp;#34;&amp;lt;new_hex_pubkey&amp;gt;&amp;#34;,&amp;#34;alice&amp;#34;:&amp;#34;&amp;lt;alice_hex_pubkey&amp;gt;&amp;#34;},&amp;#34;relays&amp;#34;:{&amp;#34;&amp;lt;alice_hex_pubkey&amp;gt;&amp;#34;:[&amp;#34;wss://relay.example.com&amp;#34;]}}}&amp;#39;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This broadcasts a &lt;code&gt;NAME_UPDATE&lt;/code&gt; transaction to the Namecoin blockchain. Once confirmed, Amethyst (and any other client that supports Namecoin NIP-05) will resolve the name to the new value.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Important notes on updates:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each &lt;code&gt;name_update&lt;/code&gt; costs a small NMC fee&lt;/li&gt;
&lt;li&gt;Names expire after &lt;strong&gt;36,000 blocks&lt;/strong&gt; (~36 weeks) if not updated or renewed. Amethyst checks expiry and will treat expired names as non-existent.&lt;/li&gt;
&lt;li&gt;To simply renew without changing the value, you can &lt;code&gt;name_update&lt;/code&gt; with the same value&lt;/li&gt;
&lt;li&gt;Updates replace the entire value — there is no partial update mechanism&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&#34;step-5-set-your-nip-05-in-your-nostr-profile-8&#34;&gt;Step 5: Set Your NIP-05 in Your Nostr Profile&lt;/h3&gt;

&lt;p&gt;Once your Namecoin name is registered and confirmed on the blockchain, update your Nostr profile&amp;#39;s &lt;code&gt;nip05&lt;/code&gt; field in Amethyst:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to your profile → Edit&lt;/li&gt;
&lt;li&gt;Set the NIP-05 field to your Namecoin address, e.g. &lt;code&gt;alice@yourname.bit&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Save&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Amethyst (and other Namecoin-aware clients) will verify this address against the blockchain and show the verification badge.&lt;/p&gt;

&lt;h3 id=&#34;step-6-verify-it-works-8&#34;&gt;Step 6: Verify It Works&lt;/h3&gt;

&lt;p&gt;In Amethyst&amp;#39;s search bar, type your Namecoin identifier. You should see your profile appear at the top of results:&lt;/p&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Test Query&lt;/th&gt;
&lt;th&gt;Expected Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;alice@yourname.bit&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Your profile (matched via &lt;code&gt;alice&lt;/code&gt; entry)&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;yourname.bit&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Your profile (matched via &lt;code&gt;_&lt;/code&gt; root entry)&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;d/yourname&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Your profile (direct namespace lookup)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;hr&gt;

&lt;h2 id=&#34;part-3-how-it-works-under-the-hood-8&#34;&gt;Part 3: How It Works Under the Hood&lt;/h2&gt;

&lt;h3 id=&#34;resolution-flow-8&#34;&gt;Resolution Flow&lt;/h3&gt;

&lt;p&gt;When Amethyst encounters a &lt;code&gt;.bit&lt;/code&gt; address, here is what happens:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;1. User types &amp;#34;alice@example.bit&amp;#34; in search (or a profile has it in nip05)

2. NamecoinNameResolver.parseIdentifier() parses it:
   → namecoinName = &amp;#34;d/example&amp;#34;, localPart = &amp;#34;alice&amp;#34;, namespace = DOMAIN

3. ElectrumXClient builds a canonical &amp;#34;name index script&amp;#34;:
   OP_NAME_UPDATE(0x53) &#43; push(&amp;#34;d/example&amp;#34;) &#43; push(&amp;#34;&amp;#34;) &#43; OP_2DROP &#43; OP_DROP &#43; OP_RETURN

4. Computes the Electrum-style scripthash:
   SHA-256(script) → reverse bytes → hex encode

5. Queries the ElectrumX server:
   → blockchain.scripthash.get_history(scripthash)
   ← [{tx_hash: &amp;#34;abc...&amp;#34;, height: 814278}, ...]

6. Fetches the latest transaction (last entry = most recent name update):
   → blockchain.transaction.get(tx_hash, verbose=true)

7. Checks block headers to verify the name hasn&amp;#39;t expired:
   → blockchain.headers.subscribe
   ← current height; if (current - update_height) &amp;gt;= 36000 → expired

8. Parses the NAME_UPDATE script from the transaction output:
   Extracts: name string &#43; JSON value

9. NamecoinNameResolver.extractFromDomainValue() reads the JSON:
   Finds &amp;#34;nostr&amp;#34; → &amp;#34;names&amp;#34; → &amp;#34;alice&amp;#34; → hex pubkey

10. Returns NamecoinNostrResult(pubkey, relays, namecoinName, localPart)
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;caching-8&#34;&gt;Caching&lt;/h3&gt;

&lt;p&gt;Resolved names are cached in an LRU cache (default 500 entries, 1-hour TTL). Both positive and negative results are cached. The cache is keyed by the normalized (lowercased, trimmed) identifier.&lt;/p&gt;

&lt;h3 id=&#34;architecture-layers-8&#34;&gt;Architecture Layers&lt;/h3&gt;

&lt;p&gt;The implementation is split across two modules:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Quartz (library, no Android dependencies):&lt;/strong&gt;
- &lt;code&gt;NamecoinNameResolver&lt;/code&gt; — identifier parsing, value extraction, resolution orchestration
- &lt;code&gt;ElectrumXClient&lt;/code&gt; — TCP/TLS connection to ElectrumX, JSON-RPC, script parsing
- &lt;code&gt;NamecoinLookupCache&lt;/code&gt; — LRU cache with TTL
- &lt;code&gt;IElectrumXClient&lt;/code&gt; — interface for testing/mocking&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Amethyst (Android app):&lt;/strong&gt;
- &lt;code&gt;NamecoinNameService&lt;/code&gt; — application singleton, wires up caching and proxy-aware client
- &lt;code&gt;NamecoinSettings&lt;/code&gt; / &lt;code&gt;NamecoinSharedPreferences&lt;/code&gt; — persistent config
- &lt;code&gt;NamecoinSettingsScreen&lt;/code&gt; / &lt;code&gt;NamecoinSettingsSection&lt;/code&gt; — settings UI
- &lt;code&gt;ProxiedSocketFactory&lt;/code&gt; — SOCKS5 proxy routing for Tor
- &lt;code&gt;RoleBasedHttpClientBuilder.socketFactoryForNip05()&lt;/code&gt; — Tor-aware socket creation&lt;/p&gt;

&lt;p&gt;The integration into NIP-05 is minimal: &lt;code&gt;Nip05Client&lt;/code&gt; checks if an identifier matches &lt;code&gt;.bit&lt;/code&gt; / &lt;code&gt;d/&lt;/code&gt; / &lt;code&gt;id/&lt;/code&gt; patterns, and routes to &lt;code&gt;NamecoinNameResolver&lt;/code&gt; instead of making an HTTP fetch. Non-Namecoin identifiers are completely unaffected.&lt;/p&gt;

&lt;hr&gt;

&lt;h2 id=&#34;part-4-security-considerations-8&#34;&gt;Part 4: Security Considerations&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Tor integration&lt;/strong&gt; — When enabled, all ElectrumX connections go through the Tor SOCKS proxy. The &lt;code&gt;.onion&lt;/code&gt; server is preferred for end-to-end onion routing. Socket factory and server list are evaluated per-request via lambdas, so toggling Tor takes effect immediately.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TLS certificate pinning&lt;/strong&gt; — The primary ElectrumX servers use self-signed certificates. Their PEM-encoded certs are pinned in the Amethyst binary. Users can pin additional certs via the TOFU flow in settings (test server → view fingerprint → confirm → pin). This is necessary because Samsung One UI 7 and GrapheneOS reject trust-all TrustManagers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Name expiry&lt;/strong&gt; — Namecoin names expire after ~36,000 blocks (~250 days) if not renewed. The ElectrumX client checks the current block height against the name&amp;#39;s last update height and treats expired names as non-existent.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Server trust&lt;/strong&gt; — The client trusts that the ElectrumX server returns accurate transaction data. The Namecoin blockchain itself is the trust anchor — a MITM could return stale data but cannot forge name registrations. For higher assurance, SPV proof verification could be added in the future.&lt;/p&gt;

&lt;hr&gt;

&lt;h2 id=&#34;quick-reference-8&#34;&gt;Quick Reference&lt;/h2&gt;

&lt;h3 id=&#34;identifier-format-summary-8&#34;&gt;Identifier Format Summary&lt;/h3&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;User Input&lt;/th&gt;
&lt;th&gt;Namecoin Name&lt;/th&gt;
&lt;th&gt;Looked-Up Entry&lt;/th&gt;
&lt;th&gt;Namespace&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;alice@example.bit&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;d/example&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;alice&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Domain&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;_@example.bit&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;d/example&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;_&lt;/code&gt; (root)&lt;/td&gt;
&lt;td&gt;Domain&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;example.bit&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;d/example&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;_&lt;/code&gt; (root)&lt;/td&gt;
&lt;td&gt;Domain&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;d/example&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;d/example&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;_&lt;/code&gt; (root)&lt;/td&gt;
&lt;td&gt;Domain&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;id/alice&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;id/alice&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;_&lt;/code&gt; (root)&lt;/td&gt;
&lt;td&gt;Identity&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&#34;name-value-json-formats-8&#34;&gt;Name Value JSON Formats&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Domain simple:&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{&amp;#34;nostr&amp;#34;: &amp;#34;&amp;lt;64-char-hex-pubkey&amp;gt;&amp;#34;}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Domain extended (multi-user &#43; relays):&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{&amp;#34;nostr&amp;#34;: {&amp;#34;names&amp;#34;: {&amp;#34;_&amp;#34;: &amp;#34;&amp;lt;hex&amp;gt;&amp;#34;, &amp;#34;alice&amp;#34;: &amp;#34;&amp;lt;hex&amp;gt;&amp;#34;}, &amp;#34;relays&amp;#34;: {&amp;#34;&amp;lt;hex&amp;gt;&amp;#34;: [&amp;#34;wss://...&amp;#34;]}}}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Identity simple:&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{&amp;#34;nostr&amp;#34;: &amp;#34;&amp;lt;64-char-hex-pubkey&amp;gt;&amp;#34;}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Identity with relays:&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{&amp;#34;nostr&amp;#34;: {&amp;#34;pubkey&amp;#34;: &amp;#34;&amp;lt;hex&amp;gt;&amp;#34;, &amp;#34;relays&amp;#34;: [&amp;#34;wss://...&amp;#34;]}}
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;namecoin-cli-commands-8&#34;&gt;Namecoin CLI Commands&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;# Register a new name
namecoin-cli name_new &amp;#34;d/yourname&amp;#34;
# Returns: [txid, random_value]
# Example:
#   [
#     &amp;#34;a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2&amp;#34;,
#     &amp;#34;6e4a2d190f7b&amp;#34;
#   ]
# SAVE BOTH — you need the random value (2nd element) for name_firstupdate.
# Wait for at least 12 confirmations (~2 hours) before proceeding.

# Finalize registration with the random value from name_new
namecoin-cli name_firstupdate &amp;#34;d/yourname&amp;#34; &amp;lt;random&amp;gt; &amp;#39;&amp;lt;json&amp;gt;&amp;#39;

# Update an existing name
namecoin-cli name_update &amp;#34;d/yourname&amp;#34; &amp;#39;&amp;lt;new_json&amp;gt;&amp;#39;

# Check a name&amp;#39;s current value
namecoin-cli name_show &amp;#34;d/yourname&amp;#34;

# List your names
namecoin-cli name_list
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;getting-namecoins-via-dvm-nip-90-8&#34;&gt;Getting Namecoins via DVM (NIP-90)&lt;/h3&gt;

&lt;p&gt;Don&amp;#39;t have NMC? You can acquire Namecoin through a Nostr-native exchange service — no centralized exchange account needed.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;NMC Exchange DVM&lt;/strong&gt; is a &lt;a href=&#34;https://github.com/nostr-protocol/nips/blob/master/90.md&#34;&gt;NIP-90 Data Vending Machine&lt;/a&gt; that accepts Lightning Bitcoin (⚡ sats) or Cashu ecash (🥜) and sends NMC directly to your Namecoin address.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Send a &lt;code&gt;kind:5950&lt;/code&gt; job request to the DVM with your NMC address and desired amount (0.2–0.5 NMC)&lt;/li&gt;
&lt;li&gt;The DVM responds with a Lightning invoice or Cashu payment info&lt;/li&gt;
&lt;li&gt;Pay via Lightning zap or Cashu ecash&lt;/li&gt;
&lt;li&gt;Receive NMC at your designated address — the DVM sends the &lt;code&gt;kind:6950&lt;/code&gt; result with the NMC transaction ID&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Rate:&lt;/strong&gt; $10 USD per NMC (max 0.5 NMC per order)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Payment methods:&lt;/strong&gt; Lightning Bitcoin ⚡ | Cashu ecash 🥜&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DVM address (NIP-89):&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&lt;span itemprop=&#34;mentions&#34; itemscope itemtype=&#34;https://schema.org/Article&#34;&gt;&lt;a itemprop=&#34;url&#34; href=&#34;/naddr1qvzqqqru7cpzqscctm0vke6cj2pykx3h54lnusrlhh3wmfeqrguznwx0fwnutd8sqy2hwumn8ghj7un9d3shjtnyd968gmewwp6kyqqsdekkxtt90p3ksctwvajj6erkd5njfjn5&#34; class=&#34;bg-lavender dark:prose:text-neutral-50 dark:text-neutral-50 dark:bg-garnet px-1&#34;&gt;naddr1qv…fjn5&lt;/a&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;View on NostrHub:&lt;/strong&gt; &lt;a href=&#34;https://nostrhub.io/naddr1qvzqqqru7cpzqscctm0vke6cj2pykx3h54lnusrlhh3wmfeqrguznwx0fwnutd8sqy2hwumn8ghj7un9d3shjtnyd968gmewwp6kyqqsdekkxtt90p3ksctwvajj6erkd5njfjn5&#34;&gt;NMC Exchange DVM&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example job request:&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{
  &amp;#34;kind&amp;#34;: 5950,
  &amp;#34;tags&amp;#34;: [
    [&amp;#34;i&amp;#34;, &amp;#34;&amp;lt;your-nmc-address&amp;gt;&amp;#34;, &amp;#34;text&amp;#34;],
    [&amp;#34;param&amp;#34;, &amp;#34;amount&amp;#34;, &amp;#34;0.5&amp;#34;],
    [&amp;#34;bid&amp;#34;, &amp;#34;10000000&amp;#34;]
  ],
  &amp;#34;content&amp;#34;: &amp;#34;&amp;#34;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is an experimental service — no guarantees of uptime, but it&amp;#39;s a quick way to get NMC for name registrations without touching a centralized exchange.&lt;/p&gt;

&lt;h3 id=&#34;testing-for-developers-8&#34;&gt;Testing (for Developers)&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;# Run unit tests
./gradlew :quartz:jvmTest --tests &amp;#34;*NamecoinNameResolverTest*&amp;#34;

# Build and install debug APK
./gradlew assemblePlayDebug
adb install -r amethyst/build/outputs/apk/play/debug/amethyst-play-universal-debug.apk

# Monitor ElectrumX connections
adb root &amp;amp;&amp;amp; adb shell tcpdump -i any -nn port 50002 or port 50006
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;live-test-data-8&#34;&gt;Live Test Data&lt;/h3&gt;

&lt;p&gt;The name &lt;code&gt;d/testls&lt;/code&gt; is registered on the Namecoin blockchain with value:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{&amp;#34;nostr&amp;#34;: {&amp;#34;names&amp;#34;: {&amp;#34;_&amp;#34;: &amp;#34;6cdebccabda1dfa058ab85352a79509b592b2bdfa0370325e28ec1cb4f18667d&amp;#34;}}}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So &lt;code&gt;_@testls.bit&lt;/code&gt; (or simply &lt;code&gt;testls.bit&lt;/code&gt;) resolves to Vitor Pamplona&amp;#39;s Nostr profile.&lt;/p&gt;
 &lt;/blockquote&gt;&lt;br/&gt;The cypherpunk use case Satoshi envisioned for merged mining is more relevant now than ever.
    </content>
    <updated>2026-04-08T08:24:34Z</updated>
  </entry>

  <entry>
    <id>https://njump.me/nevent1qqsfe03mkjghewzc00qwf4jsvqu3xvwrtwdzq37ck5kd9reyxk9h80qzypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60qfpx2du</id>
    
      <title type="html">Usage stats for .bit domains don&amp;#39;t tell the whole story. ...</title>
    
    <link rel="alternate" href="https://njump.me/nevent1qqsfe03mkjghewzc00qwf4jsvqu3xvwrtwdzq37ck5kd9reyxk9h80qzypp3shk7edn43y5zfvdr0ftl8eq8l00zaknjqx3c9xuv7ja8ck60qfpx2du" />
    <content type="html">
      In reply to &lt;a href=&#39;/nevent1qqsg4l7es7fdcuwen5c8wdwy4ss94lzvl5q456qhfqtgmf8vwxmecfqpz3mhxue69uhhyetvv9ujuerpd46hxtnfdua37frf&#39;&gt;nevent1q…7frf&lt;/a&gt;&lt;br/&gt;_________________________&lt;br/&gt;&lt;br/&gt;Usage stats for .bit domains don&amp;#39;t tell the whole story. Namecoin&amp;#39;s id/ namespace is where the interesting work is happening — human-readable identity anchored to a merge-mined blockchain with Bitcoin-class security.&lt;br/&gt;&lt;br/&gt;We&amp;#39;re building on it right now for Nostr reputation infrastructure:&lt;br/&gt;&lt;blockquote class=&#34;border-l-05rem border-l-strongpink border-solid&#34;&gt;&lt;div class=&#34;-ml-4 bg-gradient-to-r from-gray-100 dark:from-zinc-800 to-transparent mr-0 mt-0 mb-4 pl-4 pr-2 py-2&#34;&gt;quoting &lt;br/&gt;&lt;span itemprop=&#34;mentions&#34; itemscope itemtype=&#34;https://schema.org/Article&#34;&gt;&lt;a itemprop=&#34;url&#34; href=&#34;/naddr1qvzqqqr4gupzqscctm0vke6cj2pykx3h54lnusrlhh3wmfeqrguznwx0fwnutd8sqq3kuctdv43k76tw945kuar9vaexzarfdahz6ctdv46xs7tnwskkwatfv3jsz0753t&#34; class=&#34;bg-lavender dark:prose:text-neutral-50 dark:text-neutral-50 dark:bg-garnet px-1&#34;&gt;naddr1qv…753t&lt;/a&gt;&lt;/span&gt;&lt;br/&gt; &lt;/div&gt; 
&lt;h1 id=&#34;how-to-guide-namecoin-integration-in-amethyst-11&#34;&gt;How-To Guide: Namecoin Integration in Amethyst&lt;/h1&gt;

&lt;h2 id=&#34;what-this-is-11&#34;&gt;What This Is&lt;/h2&gt;

&lt;p&gt;Amethyst — the Android Nostr client — includes built-in support for resolving Namecoin blockchain names as NIP-05 identities. Instead of relying on a web server to verify &lt;code&gt;alice@example.com&lt;/code&gt;, a user can set their NIP-05 address to something like &lt;code&gt;alice@example.bit&lt;/code&gt;, and Amethyst will verify it directly against the Namecoin blockchain via ElectrumX servers.&lt;/p&gt;

&lt;p&gt;This is censorship-resistant identity: no web server to seize, no DNS to hijack, no TLS certificate to revoke. The name-to-pubkey mapping lives in Namecoin UTXOs.&lt;/p&gt;

&lt;p&gt;This guide covers how the system works, how to use it as an end-user, and how to register or update a Namecoin name value so that it resolves to your Nostr pubkey.&lt;/p&gt;

&lt;hr&gt;

&lt;h2 id=&#34;part-1-using-namecoin-names-in-amethyst-end-user-11&#34;&gt;Part 1: Using Namecoin Names in Amethyst (End-User)&lt;/h2&gt;

&lt;h3 id=&#34;searching-for-namecoin-users-11&#34;&gt;Searching for Namecoin Users&lt;/h3&gt;

&lt;p&gt;Open Amethyst&amp;#39;s search bar and type any of these formats:&lt;/p&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Search Input&lt;/th&gt;
&lt;th&gt;What It Does&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;alice@example.bit&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Looks up the &lt;code&gt;alice&lt;/code&gt; entry in Namecoin name &lt;code&gt;d/example&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;example.bit&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Looks up the root (&lt;code&gt;_&lt;/code&gt;) entry in &lt;code&gt;d/example&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;d/example&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Direct Namecoin domain namespace lookup (root entry)&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;id/alice&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Direct Namecoin identity namespace lookup&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Amethyst queries the Namecoin blockchain through an ElectrumX server, resolves the name to a Nostr public key, and shows the matching user profile at the top of search results. There is a 400ms debounce on the search input to avoid flooding the server with requests.&lt;/p&gt;

&lt;h3 id=&#34;nip-05-verification-via-namecoin-11&#34;&gt;NIP-05 Verification via Namecoin&lt;/h3&gt;

&lt;p&gt;If a Nostr profile has a &lt;code&gt;.bit&lt;/code&gt; address in its &lt;code&gt;nip05&lt;/code&gt; metadata field (e.g. &lt;code&gt;m@testls.bit&lt;/code&gt;), Amethyst will automatically verify it against the blockchain instead of making an HTTP request. The verification badge works the same as traditional NIP-05 — the only difference is the trust anchor: blockchain consensus rather than a web server.&lt;/p&gt;

&lt;h3 id=&#34;configuring-namecoin-settings-11&#34;&gt;Configuring Namecoin Settings&lt;/h3&gt;

&lt;p&gt;Navigate to &lt;strong&gt;Settings → Namecoin Settings&lt;/strong&gt; in Amethyst. From here you can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Enable/disable&lt;/strong&gt; Namecoin resolution entirely&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Add custom ElectrumX servers&lt;/strong&gt; — useful if you run your own server for privacy&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Remove servers&lt;/strong&gt; from the custom list&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Test server connectivity&lt;/strong&gt; — checks TLS, latency, and optionally resolves a test name&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pin TLS certificates&lt;/strong&gt; — after testing a server with a self-signed cert, you can pin its certificate via TOFU (Trust On First Use)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Reset to defaults&lt;/strong&gt; — reverts to the built-in server list&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&#34;server-string-format-11&#34;&gt;Server String Format&lt;/h4&gt;

&lt;p&gt;When adding a custom server, use the format:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;host:port          → TLS connection (default)
host:port:tcp      → Plaintext TCP (for .onion or local servers)
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Examples:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;electrumx.testls.space:50002
my-local-server.lan:50001:tcp
i665jpw...dsid.onion:50002
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;tor-integration-11&#34;&gt;Tor Integration&lt;/h3&gt;

&lt;p&gt;If you have Tor enabled in Amethyst and have set &amp;#34;NIP-05 verifications via Tor&amp;#34; to on, all Namecoin ElectrumX connections are routed through your Tor SOCKS proxy. The server list also switches to prioritize &lt;code&gt;.onion&lt;/code&gt; addresses:&lt;/p&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Tor Setting&lt;/th&gt;
&lt;th&gt;Primary Server&lt;/th&gt;
&lt;th&gt;Fallback&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Off&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;electrumx.testls.space:50002&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;nmc2.bitcoins.sk:57002&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;On&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;.onion:50002&lt;/code&gt; (hidden service)&lt;/td&gt;
&lt;td&gt;&lt;code&gt;electrumx.testls.space:50002&lt;/code&gt; (via Tor)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;Toggling Tor on or off in settings takes effect on the next lookup — no app restart needed.&lt;/p&gt;

&lt;h3 id=&#34;default-electrumx-servers-11&#34;&gt;Default ElectrumX Servers&lt;/h3&gt;

&lt;p&gt;Amethyst ships with these built-in servers:&lt;/p&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Server&lt;/th&gt;
&lt;th&gt;Port&lt;/th&gt;
&lt;th&gt;TLS&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;electrumx.testls.space&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;50002&lt;/td&gt;
&lt;td&gt;Yes (self-signed, pinned)&lt;/td&gt;
&lt;td&gt;Primary&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;nmc2.bitcoins.sk&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;57002&lt;/td&gt;
&lt;td&gt;Yes (self-signed, pinned)&lt;/td&gt;
&lt;td&gt;Fallback&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;46.229.238.187&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;57002&lt;/td&gt;
&lt;td&gt;Yes (self-signed, pinned)&lt;/td&gt;
&lt;td&gt;IP fallback&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;The self-signed certificates for these servers are pinned directly into the Amethyst binary, so connections succeed even on devices with strict TLS enforcement (Samsung One UI 7, GrapheneOS).&lt;/p&gt;

&lt;hr&gt;

&lt;h2 id=&#34;part-2-registering-updating-a-namecoin-name-value-11&#34;&gt;Part 2: Registering &amp;amp; Updating a Namecoin Name Value&lt;/h2&gt;

&lt;p&gt;Amethyst itself is a &lt;strong&gt;read-only&lt;/strong&gt; consumer of Namecoin data — it resolves names but does not write to the blockchain. To register or update a Namecoin name so that it points to your Nostr pubkey, you need to interact with the Namecoin blockchain directly using Namecoin Core (the full node software) or a compatible wallet.&lt;/p&gt;

&lt;h3 id=&#34;prerequisites-12&#34;&gt;Prerequisites&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Namecoin Core&lt;/strong&gt; or &lt;strong&gt;Electrum-NMC&lt;/strong&gt; installed and synced — download from &lt;a href=&#34;https://www.namecoin.org/&#34;&gt;namecoin.org&lt;/a&gt; (this guide uses Namecoin Core as an example)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;NMC (Namecoin coins)&lt;/strong&gt; in your wallet — needed to pay registration and update fees (0.01 NMC per registration operation plus associated fees)&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Your Nostr hex public key&lt;/strong&gt; — the 64-character hex string (not &lt;code&gt;npub1...&lt;/code&gt;). You can find this in Amethyst under your profile settings or by converting your npub using a tool like &lt;a href=&#34;https://nostrdeck.com/key-converter.php&#34;&gt;https://nostrdeck.com/key-converter.php&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3 id=&#34;step-1-choose-your-namespace-11&#34;&gt;Step 1: Choose Your Namespace&lt;/h3&gt;

&lt;p&gt;Amethyst supports two Namecoin namespaces:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Domain namespace (&lt;code&gt;d/&lt;/code&gt;)&lt;/strong&gt; — maps a domain-like name to one or more Nostr pubkeys. This is the most common choice and mirrors NIP-05&amp;#39;s &lt;code&gt;user@domain&lt;/code&gt; format.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Identity namespace (&lt;code&gt;id/&lt;/code&gt;)&lt;/strong&gt; — maps a personal identity name to a single Nostr pubkey.&lt;/p&gt;

&lt;p&gt;For most users, the &lt;code&gt;d/&lt;/code&gt; namespace is the right choice because it allows &lt;code&gt;user@name.bit&lt;/code&gt; style addresses.&lt;/p&gt;

&lt;h3 id=&#34;step-2-register-a-new-name-11&#34;&gt;Step 2: Register a New Name&lt;/h3&gt;

&lt;p&gt;Open a terminal and use &lt;code&gt;namecoin-cli&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;# Register a name in the domain namespace
# This creates a &amp;#34;pre-registration&amp;#34; (name_new) first
namecoin-cli name_new &amp;#34;d/yourname&amp;#34;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This returns a transaction ID and a random value. &lt;strong&gt;Save both&lt;/strong&gt; — you need the random value for the next step. Wait for the transaction to get at least 12 confirmations (about 2 hours).&lt;/p&gt;

&lt;p&gt;Then finalize the registration:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;namecoin-cli name_firstupdate &amp;#34;d/yourname&amp;#34; &amp;lt;random_value&amp;gt; &amp;#39;&amp;lt;json_value&amp;gt;&amp;#39;
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;step-3-set-the-name-value-for-nostr-11&#34;&gt;Step 3: Set the Name Value for Nostr&lt;/h3&gt;

&lt;p&gt;The JSON value you store in the Namecoin name is what Amethyst reads to find your Nostr pubkey. There are several supported formats.&lt;/p&gt;

&lt;h4 id=&#34;simple-form-single-user-root-domain-11&#34;&gt;Simple Form — Single User, Root Domain&lt;/h4&gt;

&lt;p&gt;If you just want &lt;code&gt;yourname.bit&lt;/code&gt; to resolve to your pubkey:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{
  &amp;#34;nostr&amp;#34;: &amp;#34;b0635d6a9851d3aed0cd6c495b282167acf761729078d975fc341b22650b07b9&amp;#34;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code&gt;namecoin-cli name_firstupdate &amp;#34;d/yourname&amp;#34; &amp;lt;random&amp;gt; \
  &amp;#39;{&amp;#34;nostr&amp;#34;:&amp;#34;b0635d6a9851d3aed0cd6c495b282167acf761729078d975fc341b22650b07b9&amp;#34;}&amp;#39;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This makes &lt;code&gt;yourname.bit&lt;/code&gt; and &lt;code&gt;_@yourname.bit&lt;/code&gt; resolve to the given pubkey.&lt;/p&gt;

&lt;h4 id=&#34;extended-form-multiple-users-with-relay-hints-11&#34;&gt;Extended Form — Multiple Users with Relay Hints&lt;/h4&gt;

&lt;p&gt;If you want to host multiple identities under one &lt;code&gt;.bit&lt;/code&gt; domain (like a NIP-05 server hosting multiple users):&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{
  &amp;#34;nostr&amp;#34;: {
    &amp;#34;names&amp;#34;: {
      &amp;#34;_&amp;#34;: &amp;#34;aaaa000000000000000000000000000000000000000000000000000000000001&amp;#34;,
      &amp;#34;alice&amp;#34;: &amp;#34;bbbb000000000000000000000000000000000000000000000000000000000002&amp;#34;,
      &amp;#34;bob&amp;#34;: &amp;#34;cccc000000000000000000000000000000000000000000000000000000000003&amp;#34;
    },
    &amp;#34;relays&amp;#34;: {
      &amp;#34;bbbb000000000000000000000000000000000000000000000000000000000002&amp;#34;: [
        &amp;#34;wss://relay.example.com&amp;#34;,
        &amp;#34;wss://nos.lol&amp;#34;
      ]
    }
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;With this value stored in &lt;code&gt;d/yourname&lt;/code&gt;:
- &lt;code&gt;_@yourname.bit&lt;/code&gt; or &lt;code&gt;yourname.bit&lt;/code&gt; → resolves to the &lt;code&gt;_&lt;/code&gt; pubkey
- &lt;code&gt;alice@yourname.bit&lt;/code&gt; → resolves to Alice&amp;#39;s pubkey, with relay hints
- &lt;code&gt;bob@yourname.bit&lt;/code&gt; → resolves to Bob&amp;#39;s pubkey&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;namecoin-cli name_firstupdate &amp;#34;d/yourname&amp;#34; &amp;lt;random&amp;gt; \
  &amp;#39;{&amp;#34;nostr&amp;#34;:{&amp;#34;names&amp;#34;:{&amp;#34;_&amp;#34;:&amp;#34;aaaa...0001&amp;#34;,&amp;#34;alice&amp;#34;:&amp;#34;bbbb...0002&amp;#34;},&amp;#34;relays&amp;#34;:{&amp;#34;bbbb...0002&amp;#34;:[&amp;#34;wss://relay.example.com&amp;#34;]}}}&amp;#39;
&lt;/code&gt;&lt;/pre&gt;

&lt;h4 id=&#34;identity-namespace-form-id-11&#34;&gt;Identity Namespace Form (&lt;code&gt;id/&lt;/code&gt;)&lt;/h4&gt;

&lt;p&gt;For the &lt;code&gt;id/&lt;/code&gt; namespace, the value format is simpler:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{
  &amp;#34;nostr&amp;#34;: &amp;#34;cccc000000000000000000000000000000000000000000000000000000000003&amp;#34;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;Or with relay hints:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{
  &amp;#34;nostr&amp;#34;: {
    &amp;#34;pubkey&amp;#34;: &amp;#34;dddd000000000000000000000000000000000000000000000000000000000004&amp;#34;,
    &amp;#34;relays&amp;#34;: [&amp;#34;wss://relay.example.com&amp;#34;]
  }
}
&lt;/code&gt;&lt;/pre&gt;

&lt;pre&gt;&lt;code&gt;namecoin-cli name_firstupdate &amp;#34;id/youridentity&amp;#34; &amp;lt;random&amp;gt; \
  &amp;#39;{&amp;#34;nostr&amp;#34;:{&amp;#34;pubkey&amp;#34;:&amp;#34;dddd...0004&amp;#34;,&amp;#34;relays&amp;#34;:[&amp;#34;wss://relay.example.com&amp;#34;]}}&amp;#39;
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;step-4-update-an-existing-name-11&#34;&gt;Step 4: Update an Existing Name&lt;/h3&gt;

&lt;p&gt;To change the Nostr pubkey (or any other data) associated with an already-registered name, use &lt;code&gt;name_update&lt;/code&gt;:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;namecoin-cli name_update &amp;#34;d/yourname&amp;#34; \
  &amp;#39;{&amp;#34;nostr&amp;#34;:{&amp;#34;names&amp;#34;:{&amp;#34;_&amp;#34;:&amp;#34;&amp;lt;new_hex_pubkey&amp;gt;&amp;#34;,&amp;#34;alice&amp;#34;:&amp;#34;&amp;lt;alice_hex_pubkey&amp;gt;&amp;#34;},&amp;#34;relays&amp;#34;:{&amp;#34;&amp;lt;alice_hex_pubkey&amp;gt;&amp;#34;:[&amp;#34;wss://relay.example.com&amp;#34;]}}}&amp;#39;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This broadcasts a &lt;code&gt;NAME_UPDATE&lt;/code&gt; transaction to the Namecoin blockchain. Once confirmed, Amethyst (and any other client that supports Namecoin NIP-05) will resolve the name to the new value.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Important notes on updates:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Each &lt;code&gt;name_update&lt;/code&gt; costs a small NMC fee&lt;/li&gt;
&lt;li&gt;Names expire after &lt;strong&gt;36,000 blocks&lt;/strong&gt; (~36 weeks) if not updated or renewed. Amethyst checks expiry and will treat expired names as non-existent.&lt;/li&gt;
&lt;li&gt;To simply renew without changing the value, you can &lt;code&gt;name_update&lt;/code&gt; with the same value&lt;/li&gt;
&lt;li&gt;Updates replace the entire value — there is no partial update mechanism&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&#34;step-5-set-your-nip-05-in-your-nostr-profile-11&#34;&gt;Step 5: Set Your NIP-05 in Your Nostr Profile&lt;/h3&gt;

&lt;p&gt;Once your Namecoin name is registered and confirmed on the blockchain, update your Nostr profile&amp;#39;s &lt;code&gt;nip05&lt;/code&gt; field in Amethyst:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Go to your profile → Edit&lt;/li&gt;
&lt;li&gt;Set the NIP-05 field to your Namecoin address, e.g. &lt;code&gt;alice@yourname.bit&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Save&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Amethyst (and other Namecoin-aware clients) will verify this address against the blockchain and show the verification badge.&lt;/p&gt;

&lt;h3 id=&#34;step-6-verify-it-works-11&#34;&gt;Step 6: Verify It Works&lt;/h3&gt;

&lt;p&gt;In Amethyst&amp;#39;s search bar, type your Namecoin identifier. You should see your profile appear at the top of results:&lt;/p&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Test Query&lt;/th&gt;
&lt;th&gt;Expected Result&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;alice@yourname.bit&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Your profile (matched via &lt;code&gt;alice&lt;/code&gt; entry)&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;yourname.bit&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Your profile (matched via &lt;code&gt;_&lt;/code&gt; root entry)&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;d/yourname&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Your profile (direct namespace lookup)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;hr&gt;

&lt;h2 id=&#34;part-3-how-it-works-under-the-hood-11&#34;&gt;Part 3: How It Works Under the Hood&lt;/h2&gt;

&lt;h3 id=&#34;resolution-flow-11&#34;&gt;Resolution Flow&lt;/h3&gt;

&lt;p&gt;When Amethyst encounters a &lt;code&gt;.bit&lt;/code&gt; address, here is what happens:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;1. User types &amp;#34;alice@example.bit&amp;#34; in search (or a profile has it in nip05)

2. NamecoinNameResolver.parseIdentifier() parses it:
   → namecoinName = &amp;#34;d/example&amp;#34;, localPart = &amp;#34;alice&amp;#34;, namespace = DOMAIN

3. ElectrumXClient builds a canonical &amp;#34;name index script&amp;#34;:
   OP_NAME_UPDATE(0x53) &#43; push(&amp;#34;d/example&amp;#34;) &#43; push(&amp;#34;&amp;#34;) &#43; OP_2DROP &#43; OP_DROP &#43; OP_RETURN

4. Computes the Electrum-style scripthash:
   SHA-256(script) → reverse bytes → hex encode

5. Queries the ElectrumX server:
   → blockchain.scripthash.get_history(scripthash)
   ← [{tx_hash: &amp;#34;abc...&amp;#34;, height: 814278}, ...]

6. Fetches the latest transaction (last entry = most recent name update):
   → blockchain.transaction.get(tx_hash, verbose=true)

7. Checks block headers to verify the name hasn&amp;#39;t expired:
   → blockchain.headers.subscribe
   ← current height; if (current - update_height) &amp;gt;= 36000 → expired

8. Parses the NAME_UPDATE script from the transaction output:
   Extracts: name string &#43; JSON value

9. NamecoinNameResolver.extractFromDomainValue() reads the JSON:
   Finds &amp;#34;nostr&amp;#34; → &amp;#34;names&amp;#34; → &amp;#34;alice&amp;#34; → hex pubkey

10. Returns NamecoinNostrResult(pubkey, relays, namecoinName, localPart)
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;caching-11&#34;&gt;Caching&lt;/h3&gt;

&lt;p&gt;Resolved names are cached in an LRU cache (default 500 entries, 1-hour TTL). Both positive and negative results are cached. The cache is keyed by the normalized (lowercased, trimmed) identifier.&lt;/p&gt;

&lt;h3 id=&#34;architecture-layers-11&#34;&gt;Architecture Layers&lt;/h3&gt;

&lt;p&gt;The implementation is split across two modules:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Quartz (library, no Android dependencies):&lt;/strong&gt;
- &lt;code&gt;NamecoinNameResolver&lt;/code&gt; — identifier parsing, value extraction, resolution orchestration
- &lt;code&gt;ElectrumXClient&lt;/code&gt; — TCP/TLS connection to ElectrumX, JSON-RPC, script parsing
- &lt;code&gt;NamecoinLookupCache&lt;/code&gt; — LRU cache with TTL
- &lt;code&gt;IElectrumXClient&lt;/code&gt; — interface for testing/mocking&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Amethyst (Android app):&lt;/strong&gt;
- &lt;code&gt;NamecoinNameService&lt;/code&gt; — application singleton, wires up caching and proxy-aware client
- &lt;code&gt;NamecoinSettings&lt;/code&gt; / &lt;code&gt;NamecoinSharedPreferences&lt;/code&gt; — persistent config
- &lt;code&gt;NamecoinSettingsScreen&lt;/code&gt; / &lt;code&gt;NamecoinSettingsSection&lt;/code&gt; — settings UI
- &lt;code&gt;ProxiedSocketFactory&lt;/code&gt; — SOCKS5 proxy routing for Tor
- &lt;code&gt;RoleBasedHttpClientBuilder.socketFactoryForNip05()&lt;/code&gt; — Tor-aware socket creation&lt;/p&gt;

&lt;p&gt;The integration into NIP-05 is minimal: &lt;code&gt;Nip05Client&lt;/code&gt; checks if an identifier matches &lt;code&gt;.bit&lt;/code&gt; / &lt;code&gt;d/&lt;/code&gt; / &lt;code&gt;id/&lt;/code&gt; patterns, and routes to &lt;code&gt;NamecoinNameResolver&lt;/code&gt; instead of making an HTTP fetch. Non-Namecoin identifiers are completely unaffected.&lt;/p&gt;

&lt;hr&gt;

&lt;h2 id=&#34;part-4-security-considerations-11&#34;&gt;Part 4: Security Considerations&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Tor integration&lt;/strong&gt; — When enabled, all ElectrumX connections go through the Tor SOCKS proxy. The &lt;code&gt;.onion&lt;/code&gt; server is preferred for end-to-end onion routing. Socket factory and server list are evaluated per-request via lambdas, so toggling Tor takes effect immediately.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;TLS certificate pinning&lt;/strong&gt; — The primary ElectrumX servers use self-signed certificates. Their PEM-encoded certs are pinned in the Amethyst binary. Users can pin additional certs via the TOFU flow in settings (test server → view fingerprint → confirm → pin). This is necessary because Samsung One UI 7 and GrapheneOS reject trust-all TrustManagers.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Name expiry&lt;/strong&gt; — Namecoin names expire after ~36,000 blocks (~250 days) if not renewed. The ElectrumX client checks the current block height against the name&amp;#39;s last update height and treats expired names as non-existent.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Server trust&lt;/strong&gt; — The client trusts that the ElectrumX server returns accurate transaction data. The Namecoin blockchain itself is the trust anchor — a MITM could return stale data but cannot forge name registrations. For higher assurance, SPV proof verification could be added in the future.&lt;/p&gt;

&lt;hr&gt;

&lt;h2 id=&#34;quick-reference-11&#34;&gt;Quick Reference&lt;/h2&gt;

&lt;h3 id=&#34;identifier-format-summary-11&#34;&gt;Identifier Format Summary&lt;/h3&gt;

&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;User Input&lt;/th&gt;
&lt;th&gt;Namecoin Name&lt;/th&gt;
&lt;th&gt;Looked-Up Entry&lt;/th&gt;
&lt;th&gt;Namespace&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;

&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;alice@example.bit&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;d/example&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;alice&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Domain&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;_@example.bit&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;d/example&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;_&lt;/code&gt; (root)&lt;/td&gt;
&lt;td&gt;Domain&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;example.bit&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;d/example&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;_&lt;/code&gt; (root)&lt;/td&gt;
&lt;td&gt;Domain&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;d/example&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;d/example&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;_&lt;/code&gt; (root)&lt;/td&gt;
&lt;td&gt;Domain&lt;/td&gt;
&lt;/tr&gt;

&lt;tr&gt;
&lt;td&gt;&lt;code&gt;id/alice&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;id/alice&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;code&gt;_&lt;/code&gt; (root)&lt;/td&gt;
&lt;td&gt;Identity&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;

&lt;h3 id=&#34;name-value-json-formats-11&#34;&gt;Name Value JSON Formats&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Domain simple:&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{&amp;#34;nostr&amp;#34;: &amp;#34;&amp;lt;64-char-hex-pubkey&amp;gt;&amp;#34;}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Domain extended (multi-user &#43; relays):&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{&amp;#34;nostr&amp;#34;: {&amp;#34;names&amp;#34;: {&amp;#34;_&amp;#34;: &amp;#34;&amp;lt;hex&amp;gt;&amp;#34;, &amp;#34;alice&amp;#34;: &amp;#34;&amp;lt;hex&amp;gt;&amp;#34;}, &amp;#34;relays&amp;#34;: {&amp;#34;&amp;lt;hex&amp;gt;&amp;#34;: [&amp;#34;wss://...&amp;#34;]}}}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Identity simple:&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{&amp;#34;nostr&amp;#34;: &amp;#34;&amp;lt;64-char-hex-pubkey&amp;gt;&amp;#34;}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;Identity with relays:&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{&amp;#34;nostr&amp;#34;: {&amp;#34;pubkey&amp;#34;: &amp;#34;&amp;lt;hex&amp;gt;&amp;#34;, &amp;#34;relays&amp;#34;: [&amp;#34;wss://...&amp;#34;]}}
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;namecoin-cli-commands-11&#34;&gt;Namecoin CLI Commands&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;# Register a new name
namecoin-cli name_new &amp;#34;d/yourname&amp;#34;
# Returns: [txid, random_value]
# Example:
#   [
#     &amp;#34;a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2c3d4e5f6a1b2&amp;#34;,
#     &amp;#34;6e4a2d190f7b&amp;#34;
#   ]
# SAVE BOTH — you need the random value (2nd element) for name_firstupdate.
# Wait for at least 12 confirmations (~2 hours) before proceeding.

# Finalize registration with the random value from name_new
namecoin-cli name_firstupdate &amp;#34;d/yourname&amp;#34; &amp;lt;random&amp;gt; &amp;#39;&amp;lt;json&amp;gt;&amp;#39;

# Update an existing name
namecoin-cli name_update &amp;#34;d/yourname&amp;#34; &amp;#39;&amp;lt;new_json&amp;gt;&amp;#39;

# Check a name&amp;#39;s current value
namecoin-cli name_show &amp;#34;d/yourname&amp;#34;

# List your names
namecoin-cli name_list
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;getting-namecoins-via-dvm-nip-90-11&#34;&gt;Getting Namecoins via DVM (NIP-90)&lt;/h3&gt;

&lt;p&gt;Don&amp;#39;t have NMC? You can acquire Namecoin through a Nostr-native exchange service — no centralized exchange account needed.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;NMC Exchange DVM&lt;/strong&gt; is a &lt;a href=&#34;https://github.com/nostr-protocol/nips/blob/master/90.md&#34;&gt;NIP-90 Data Vending Machine&lt;/a&gt; that accepts Lightning Bitcoin (⚡ sats) or Cashu ecash (🥜) and sends NMC directly to your Namecoin address.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;How it works:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Send a &lt;code&gt;kind:5950&lt;/code&gt; job request to the DVM with your NMC address and desired amount (0.2–0.5 NMC)&lt;/li&gt;
&lt;li&gt;The DVM responds with a Lightning invoice or Cashu payment info&lt;/li&gt;
&lt;li&gt;Pay via Lightning zap or Cashu ecash&lt;/li&gt;
&lt;li&gt;Receive NMC at your designated address — the DVM sends the &lt;code&gt;kind:6950&lt;/code&gt; result with the NMC transaction ID&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;&lt;strong&gt;Rate:&lt;/strong&gt; $10 USD per NMC (max 0.5 NMC per order)&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Payment methods:&lt;/strong&gt; Lightning Bitcoin ⚡ | Cashu ecash 🥜&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DVM address (NIP-89):&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;&lt;span itemprop=&#34;mentions&#34; itemscope itemtype=&#34;https://schema.org/Article&#34;&gt;&lt;a itemprop=&#34;url&#34; href=&#34;/naddr1qvzqqqru7cpzqscctm0vke6cj2pykx3h54lnusrlhh3wmfeqrguznwx0fwnutd8sqy2hwumn8ghj7un9d3shjtnyd968gmewwp6kyqqsdekkxtt90p3ksctwvajj6erkd5njfjn5&#34; class=&#34;bg-lavender dark:prose:text-neutral-50 dark:text-neutral-50 dark:bg-garnet px-1&#34;&gt;naddr1qv…fjn5&lt;/a&gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;&lt;strong&gt;View on NostrHub:&lt;/strong&gt; &lt;a href=&#34;https://nostrhub.io/naddr1qvzqqqru7cpzqscctm0vke6cj2pykx3h54lnusrlhh3wmfeqrguznwx0fwnutd8sqy2hwumn8ghj7un9d3shjtnyd968gmewwp6kyqqsdekkxtt90p3ksctwvajj6erkd5njfjn5&#34;&gt;NMC Exchange DVM&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Example job request:&lt;/strong&gt;&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{
  &amp;#34;kind&amp;#34;: 5950,
  &amp;#34;tags&amp;#34;: [
    [&amp;#34;i&amp;#34;, &amp;#34;&amp;lt;your-nmc-address&amp;gt;&amp;#34;, &amp;#34;text&amp;#34;],
    [&amp;#34;param&amp;#34;, &amp;#34;amount&amp;#34;, &amp;#34;0.5&amp;#34;],
    [&amp;#34;bid&amp;#34;, &amp;#34;10000000&amp;#34;]
  ],
  &amp;#34;content&amp;#34;: &amp;#34;&amp;#34;
}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;This is an experimental service — no guarantees of uptime, but it&amp;#39;s a quick way to get NMC for name registrations without touching a centralized exchange.&lt;/p&gt;

&lt;h3 id=&#34;testing-for-developers-11&#34;&gt;Testing (for Developers)&lt;/h3&gt;

&lt;pre&gt;&lt;code&gt;# Run unit tests
./gradlew :quartz:jvmTest --tests &amp;#34;*NamecoinNameResolverTest*&amp;#34;

# Build and install debug APK
./gradlew assemblePlayDebug
adb install -r amethyst/build/outputs/apk/play/debug/amethyst-play-universal-debug.apk

# Monitor ElectrumX connections
adb root &amp;amp;&amp;amp; adb shell tcpdump -i any -nn port 50002 or port 50006
&lt;/code&gt;&lt;/pre&gt;

&lt;h3 id=&#34;live-test-data-11&#34;&gt;Live Test Data&lt;/h3&gt;

&lt;p&gt;The name &lt;code&gt;d/testls&lt;/code&gt; is registered on the Namecoin blockchain with value:&lt;/p&gt;

&lt;pre&gt;&lt;code&gt;{&amp;#34;nostr&amp;#34;: {&amp;#34;names&amp;#34;: {&amp;#34;_&amp;#34;: &amp;#34;6cdebccabda1dfa058ab85352a79509b592b2bdfa0370325e28ec1cb4f18667d&amp;#34;}}}
&lt;/code&gt;&lt;/pre&gt;

&lt;p&gt;So &lt;code&gt;_@testls.bit&lt;/code&gt; (or simply &lt;code&gt;testls.bit&lt;/code&gt;) resolves to Vitor Pamplona&amp;#39;s Nostr profile.&lt;/p&gt;
 &lt;/blockquote&gt;&lt;br/&gt;Temporal identity binding, service attestations, Sybil resistance that doesn&amp;#39;t rely on a central authority. The kind of thing you can only do with a naming system that has immutable history and 13&#43; years of unbroken chain.&lt;br/&gt;&lt;br/&gt;Not dead — just quietly useful in ways that don&amp;#39;t show up on CoinMarketCap.
    </content>
    <updated>2026-04-08T08:24:06Z</updated>
  </entry>

</feed>