Commit Graph

1205 Commits

Author SHA1 Message Date
Vitor Pamplona 9054e45310 Fixes test case 2026-03-07 16:55:12 -05:00
Vitor Pamplona 0e3ca7ac35 Merge branch 'main' of https://github.com/vitorpamplona/amethyst
* 'main' of https://github.com/vitorpamplona/amethyst: (35 commits)
  New Crowdin translations by GitHub Action
  fix chess tests
  Replace subsequent checks with '!isNullOrEmpty()' call
  use forEach: no intermediate list created.
  Use filterIsInstance to avoid dual iteration
  Lambda argument should be moved out of parentheses
  replace null checks with Elvis
  merge call chain with flatMap (slight performance improvement)
  New Crowdin translations by GitHub Action
  New Crowdin translations by GitHub Action
  update cz, pt, de, sv
  was this meant to be withContext?
  add names to boolean params
  remove unused imports
  Explicit type arguments can be inferred
  remove redundant modifiers
  correct package name
  If-Null return/break/... foldable to '?:'
  Declaration has type inferred from a platform call, which can lead to unchecked nullability issues. Specify type explicitly as nullable or non-nullable.
  Declaration has type inferred from a platform call, which can lead to unchecked nullability issues. Specify type explicitly as nullable or non-nullable.
  ...

# Conflicts:
#	amethyst/src/main/java/com/vitorpamplona/amethyst/ui/screen/loggedIn/settings/ReactionsSettingsScreen.kt
2026-03-07 16:47:16 -05:00
Vitor Pamplona 966d02d89e Removes top level domain number of char limitations to accept nostr: uris 2026-03-07 16:41:11 -05:00
Vitor Pamplona e3f99051db Applies new UrlDetector to the RichTextViewer 2026-03-07 16:38:25 -05:00
Vitor Pamplona 030921c963 Adds treatment for the transition between ASCII and non-ASCII in the middle of urls 2026-03-07 15:19:24 -05:00
Vitor Pamplona 109a5e7cd7 Adds single label domains to parse nostr: urls too 2026-03-07 10:51:19 -05:00
davotoula 5658b14ad4 fix chess tests 2026-03-06 23:26:40 +01:00
Vitor Pamplona f4d401bc56 Switches to our own version of the Url Detector 2026-03-06 10:58:59 -05:00
M 4ecfbbb844 fix: add missing StateFlow import, merge duplicate KDoc blocks, and fix rebase conflicts
- Add missing 'import kotlinx.coroutines.flow.StateFlow' in SearchBarViewModel.kt
- Merge duplicate KDoc blocks on nameShowWithFallback in ElectrumXClient.kt
- Move NamecoinLookupException to ElectrumXServer.kt (avoid redeclaration)
- Remove duplicate NameShowResult/ElectrumxServer from ElectrumXClient.kt
- Fix ElectrumxClient -> ElectrumXClient renames in NamecoinNameService
- Extract namecoinElectrumxClient in AppModules.kt for NamecoinNameService.init()
- Update package paths from nip05.namecoin to nip05DnsIdentifiers.namecoin
2026-03-06 14:22:49 +11:00
M 050fd3a412 feat: propagate distinct error types from ElectrumX to search UI
Add NamecoinLookupException sealed class to distinguish:
- NameNotFound: name queried successfully but doesn't exist on blockchain
- NameExpired: name exists but expired (>36000 blocks since last update)
- ServersUnreachable: all ElectrumX servers failed with connection errors

Previously, all three cases returned null from nameShowWithFallback,
making it impossible for the UI to show meaningful feedback.

Changes:
- ElectrumxClient.connectAndQuery: throws NameNotFound/NameExpired
  instead of returning null for definitive blockchain answers
- ElectrumxClient.nameShow: lets NamecoinLookupException propagate
  (only catches connection/IO errors as null)
- ElectrumxClient.nameShowWithFallback: short-circuits on NameNotFound/
  NameExpired (no point trying other servers for definitive answers),
  throws ServersUnreachable when all servers fail with connection errors
- SearchBarViewModel: new namecoinSearchState flow with typed states
  (Idle/Loading/Resolved/NotFound/Expired/ServersUnreachable) for UI
  to show loading spinners, resolved profiles, and specific error
  messages. Derived namecoinResolvedUser from this flow.

Discovered while porting to notedeck (damus-io/notedeck#1314).
2026-03-06 14:15:11 +11:00
M ee418bdd0a fix: address race conditions and improve Namecoin NIP-05 resolution
Fixes discovered while porting Namecoin NIP-05 to Primal Android
(PrimalHQ/primal-android-app#934):

1. Race condition: stale intermediate lookups overwrite final result
   - Changed map to mapLatest in SearchBarViewModel so that previous
     in-flight ElectrumX lookups are cancelled when the query changes
   - Without this, typing 'd/testls' character by character causes
     stale results from 'd/test', 'd/testl' etc. to arrive after
     the correct 'd/testls' result and overwrite it with null

2. CancellationException swallowed in catch block
   - mapLatest cancels previous coroutines via CancellationException
   - The generic catch was catching it and emitting null, wiping the
     valid result. Now re-throws CancellationException

3. Root lookup fails when names object has no underscore key
   - extractFromDomainValue tried names[localPart] then names[underscore]
     which is the same thing for root lookups
   - Now falls back to first available entry for root lookups when
     no underscore key exists
   - Non-root lookups still fail correctly (no false matches)

4. Global Mutex serializes all lookups
   - Single Mutex in ElectrumxClient blocked unrelated lookups to
     different servers. A 25s timeout on one server stalled everything
   - Now uses per-server mutexes via ConcurrentHashMap

5. customServers set but never read
   - NamecoinNameService.setCustomServers() stored the list but the
     resolver was constructed with the default serverListProvider
   - Now wires customServers through to the resolver

6. resolveLive uses orphaned CoroutineScope
   - Now accepts an optional external scope parameter so callers can
     tie resolution to their own lifecycle

Adds 2 new tests: root fallback to first entry, non-root no-fallback.
2026-03-06 14:14:29 +11:00
Vitor Pamplona 4839535355 Fixes test case for new class names 2026-03-04 13:29:09 -05:00
Vitor Pamplona 1fa93788db android target seems to be creating some issues between plugin dependencies after adding spm 2026-03-04 12:19:47 -05:00
Vitor Pamplona da01c6ccd1 Moves smp plugin to version catalog 2026-03-04 12:18:55 -05:00
Vitor Pamplona d662cd6b64 Merge pull request #1757 from KotlinGeekDev/kmp-completeness
KMP Completeness, Part 1.
2026-03-04 10:27:24 -05:00
Vitor Pamplona 089600d7f0 Fixes test case 2026-03-04 10:26:21 -05:00
Vitor Pamplona 8501c86663 Further organizes Calendar events 2026-03-04 10:25:51 -05:00
Vitor Pamplona d3bab2f8cb Separate generics functions 2026-03-04 10:19:10 -05:00
Vitor Pamplona b563ab44b0 Merge pull request #1762 from vitorpamplona/claude/nip52-calendar-compliance-yXoXR
Add NIP-52 Calendar event builders and tag helpers
2026-03-04 10:06:03 -05:00
Vitor Pamplona 470b1680d0 Moves electrum client to the jvmAndroid scope 2026-03-04 10:00:33 -05:00
Vitor Pamplona 193561c336 Migrates to LruCache 2026-03-04 09:32:31 -05:00
Vitor Pamplona 9abd61e2de Improves package layout for nip64 chess 2026-03-04 09:25:38 -05:00
Vitor Pamplona 46dcd105c8 Organizes Chess class and common tags 2026-03-04 09:19:39 -05:00
Vitor Pamplona 4060bef2be Lint 2026-03-04 09:19:21 -05:00
KotlinGeekDev ff7aa3df79 Merge branch 'vitorpamplona:main' into kmp-completeness 2026-03-04 14:40:12 +01:00
Vitor Pamplona ad578b394d Merge pull request #1759 from vitorpamplona/claude/refactor-nip64chess-structure-3iFIB
refactor: restructure nip64Chess to match nip88Polls pattern
2026-03-04 08:30:35 -05:00
Vitor Pamplona e065cbc63b Merge branch 'main' into feature/namecoin-nip05-resolution 2026-03-04 08:29:48 -05:00
Claude c00295f6f2 feat: implement full NIP-52 calendar spec compliance
- CalendarDateSlotEvent (31922): Add title, summary, image, geohash,
  hashtags, participants, references, multiple locations accessors and
  build() method with DSL builder pattern
- CalendarTimeSlotEvent (31923): Fix timezone bug (startTzId/endTzId
  were parsed as Long instead of String), add all accessors like
  DateSlot, rename startTmz/endTmz to startTzId/endTzId, add build()
- CalendarRSVPEvent (31925): Remove incorrect location/start/end
  accessors (not in spec), add status/freebusy/calendarEventAddress/
  calendarEventId/calendarEventAuthor accessors, update from outdated
  L/l label format to current status/fb tag format, add build()
- CalendarEvent (31924): Add title and calendarEventAddresses accessors,
  add build() method
- Create NIP-52 tag classes: LocationTag, RSVPStatusTag (with enum),
  FreeBusyTag (with enum)
- Create TagArrayBuilderExt.kt with DSL builder extensions for all
  four calendar event types

https://claude.ai/code/session_01UMXgE3tNftmqNZqcYwF2kL
2026-03-04 13:29:04 +00:00
KotlinGeekDev 4cea4e4f5d Fix issues needing a fix caught by review. 2026-03-04 13:51:46 +01:00
Claude 2df8a106d4 refactor: restructure nip64Chess to match nip88Polls pattern
Reorganize nip64Chess event classes into individual packages with
dedicated tag classes, TagArrayBuilderExt, and TagArrayExt files,
following the same structure used by nip88Polls.

New package structure:
- challenge/ - LiveChessGameChallengeEvent with PlayerColorTag, TimeControlTag
- accept/ - LiveChessGameAcceptEvent with ChallengeEventTag
- move/ - LiveChessMoveEvent with GameIdTag, MoveNumberTag, SanTag, FenTag
- end/ - LiveChessGameEndEvent with ResultTag, TerminationTag, WinnerTag
- draw/ - LiveChessDrawOfferEvent
- game/ - ChessGameEvent (Kind 64)
- jester/ - JesterEvent, JesterProtocol, JesterContent, JesterGameEvents

Each tag class follows the companion object pattern with isTag(),
parse(), and assemble() methods. Each event package includes
TagArrayBuilderExt for building and TagArrayExt for parsing.

https://claude.ai/code/session_01Qtzhka3p5N3Hbns4xrRbsv
2026-03-04 00:51:43 +00:00
KotlinGeekDev a820082a6a Fix linter issues. 2026-03-04 01:30:38 +01:00
KotlinGeekDev bbd17e4e64 Fix build issues. 2026-03-04 01:06:33 +01:00
KotlinGeekDev 68a262fa88 Merge branch 'main' of https://github.com/vitorpamplona/amethyst into upstream-main
# Conflicts:
#	gradle/libs.versions.toml
#	quartz/build.gradle.kts
#	quartz/src/androidHostTest/kotlin/com/vitorpamplona/quartz/TestResourceLoader.android.kt
#	quartz/src/iosMain/kotlin/com/vitorpamplona/quartz/utils/GZip.ios.kt
#	quartz/src/iosTest/kotlin/com/vitorpamplona/quartz/TestResourceLoader.kt
2026-03-04 00:37:10 +01:00
KotlinGeekDev aaf3be98b7 Foundations(iOS Sourceset): Update SpmForKmp. Fix UnicodeNormalizer code. 2026-03-04 00:27:00 +01:00
M cb1031705b Remove dead ElectrumX servers ulrichard.ch and nmc2.lelux.fi
ulrichard.ch:50006 — connects but never responds (timeout)
nmc2.lelux.fi:50006 — DNS resolution fails (ENOTFOUND)
2026-03-04 06:34:39 +11:00
M c649f2163b Add nmc2.bitcoins.sk and 46.229.238.187 as backup ElectrumX servers
Both verified to resolve Namecoin names via scripthash lookups.
Port 57002, TLS with self-signed certs.
2026-03-04 06:30:50 +11:00
Vitor Pamplona edb73b3556 Updates AGP 2026-03-03 11:52:03 -05:00
Vitor Pamplona 2b80ab52b7 Merge pull request #1747 from vitorpamplona/claude/nip39-kind-10011-support-EACQk
Implement NIP-39 External Identities (kind 10011) event support
2026-03-03 10:01:52 -05:00
Claude 79b06d35b9 feat: add NIP-39 kind 10011 (ExternalIdentitiesEvent) support
- Add ExternalIdentitiesEvent (kind 10011) to quartz/nip39ExtIdentities
  with createNew/updateFromPast factory methods and identityClaims()
- Generalize TagArrayBuilderExt to work with any Event type (not just
  MetadataEvent) so claims/twitterClaim etc. work with both kinds
- Extract replaceClaims logic to List<IdentityClaimTag>.replaceClaims()
  shared extension used by both MetadataEvent and ExternalIdentitiesEvent
- Register ExternalIdentitiesEvent in EventFactory (kind 10011)
- Add consume(ExternalIdentitiesEvent) to LocalCache and dispatch in
  justConsumeInnerInner
- Add ExternalIdentitiesEvent.KIND to UserMetadataForKeyKinds relay filter
  so kind 10011 is fetched alongside kind 0 when loading user profiles
- Add UserExternalIdentitiesViewModel that observes the kind 10011
  AddressableNote for a user and exposes List<IdentityClaimTag> as a Flow
- Thread UserExternalIdentitiesViewModel through ProfileScreen →
  RenderScreen → ProfileHeader → DrawAdditionalInfo
- DrawAdditionalInfo now shows kind 10011 identities, falling back to
  kind 0 for backwards compatibility
- UserMetadataState: add sendNewUserIdentities() for kind 10011 and
  remove identity claim params from sendNewUserMetadata() (kind 0)
- NewUserMetadataViewModel: load identities from kind 10011 first
  (fallback to kind 0), save identities to kind 10011 separately

https://claude.ai/code/session_017iU6ZdRu5qRXPCeDztVeeV
2026-03-03 13:47:27 +00:00
Vitor Pamplona 0370e51e57 Merge branch 'main' of https://github.com/vitorpamplona/amethyst
* 'main' of https://github.com/vitorpamplona/amethyst:
  feat: add NIP-C0 code snippet support (kind:1337)
2026-03-02 19:27:27 -05:00
Claude 8c12d4d692 feat: add NIP-C0 code snippet support (kind:1337)
Adds full protocol support for NIP-C0 code snippet events following the
same structure used for NIP-88 polls.

Quartz (quartz/nipC0CodeSnippets/):
- CodeSnippetEvent (kind:1337) with accessors for all optional metadata
- TagArrayExt: parse language, extension, name, description, runtime,
  license, deps (repeatable), and repo from tag arrays
- TagArrayBuilderExt: typed builder functions for CodeSnippetEvent
- Tag classes: LanguageTag (l), ExtensionTag, SnippetNameTag (name),
  SnippetDescriptionTag (description), RuntimeTag, LicenseTag, DepTag,
  RepoTag

EventFactory: register kind 1337 → CodeSnippetEvent
LocalCache: add consume(CodeSnippetEvent) and dispatch in when block

https://claude.ai/code/session_013ykLNfJNdwWpXh8ZhZaSXY
2026-03-02 23:48:43 +00:00
Vitor Pamplona 254ef7081b Merge branch 'main' of https://github.com/vitorpamplona/amethyst
* 'main' of https://github.com/vitorpamplona/amethyst:
  feat: add NIP-66 relay monitor and discovery support to quartz
2026-03-02 17:32:37 -05:00
Vitor Pamplona 85330f932c Merge pull request #1742 from vitorpamplona/claude/add-nip66-support-GmCWu
feat: add NIP-66 relay monitor and discovery support to quartz
2026-03-02 17:17:33 -05:00
Vitor Pamplona 7ed0909169 Blocks the size of RelayAuthStatus arrays from growing forever with auth messages 2026-03-02 17:09:52 -05:00
Claude 49e2f2c7c9 feat: add NIP-66 relay monitor and discovery support to quartz
Implements both event kinds from NIP-66 (Relay Monitor Protocol):

- Kind 10166 (RelayMonitorEvent) - replaceable event published by
  monitoring services, declaring check frequency, timeout values, and
  supported check types (open, read, write, auth, nip11, dns, geo)

- Kind 30166 (RelayDiscoveryEvent) - addressable event (keyed by relay
  URL in d-tag) published per monitored relay, carrying RTT metrics,
  network type, relay type, supported NIPs, accepted kinds, access
  requirements, topics, and geohash

Package: nip66RelayMonitor/{monitor,discovery} following existing NIP-88
patterns with tag classes, TagArrayBuilderExt, and TagArrayExt. Both
events registered in EventFactory.

https://claude.ai/code/session_01Wtg56Vudthgfyz8ASTb4p7
2026-03-02 21:20:43 +00:00
Vitor Pamplona 7fabb6b554 Makes addresses serializable 2026-03-02 15:39:58 -05:00
M 69e95159e9 fix: check Namecoin name expiry before resolving
Query current block height via blockchain.headers.subscribe and reject
names that have expired (>= 36000 blocks since last update). Populate
expiresIn field in NameShowResult for downstream use.

Unconfirmed transactions (height <= 0) are treated as active.
2026-03-03 06:56:59 +11:00
M 3f39f96e81 fix: route ElectrumX through Tor proxy, add onion server
- ElectrumxClient accepts injected SocketFactory (lambda) so connections
  respect the user's Tor/proxy settings instead of leaking their IP
  through raw sockets
- Add ProxiedSocketFactory for SOCKS5 proxy routing
- Add .onion ElectrumX server as primary when Tor is enabled, with
  electrumx.testls.space as clearnet fallback
- NamecoinNameResolver accepts serverListProvider lambda for dynamic
  server selection based on current Tor settings
- RoleBasedHttpClientBuilder.socketFactoryForNip05() bridges Amethyst's
  Tor settings to the socket factory
- NamecoinNameService now requires explicit init with proxy-aware client
- Remove dead code: Nip05NamecoinAdapter (never referenced),
  NamecoinVerificationDisplay (never called)
- Update design documentation
2026-03-03 06:28:01 +11:00
davotoula 51ba076f26 remove unused imports 2026-03-02 15:52:03 +00:00
M d82ace2f63 feat: Namecoin NIP-05 identity verification via ElectrumX
Add censorship-resistant NIP-05 verification using the Namecoin blockchain.
Users can set their nip05 field to a .bit domain (e.g. alice@example.bit)
or direct Namecoin name (d/example, id/alice) and Amethyst will resolve
the pubkey mapping via ElectrumX instead of HTTP.

Resolution uses the standard Electrum protocol (scripthash-based lookups):
- Build canonical name index script matching ElectrumX-NMC indexing
- Query blockchain.scripthash.get_history for the name's tx history
- Parse NAME_UPDATE script from the latest transaction output
- Extract Nostr pubkey from the name's JSON value

Supports both d/ (domain) and id/ (identity) Namecoin namespaces,
simple and extended NIP-05-like value formats with relay hints,
LRU caching with 1h TTL, and self-signed TLS certificates.

New files:
- quartz: ElectrumxClient, NamecoinNameResolver, NamecoinLookupCache
- amethyst: NamecoinNameService, Nip05NamecoinAdapter, NamecoinVerificationDisplay
- docs: namecoin-nip05-design.md
- tests: NamecoinNameResolverTest

Modified:
- Nip05Client: optional namecoinResolver routes .bit to blockchain
- AppModules: wire up resolver

See docs/namecoin-nip05-design.md for full architecture and protocol details.
2026-03-02 13:07:46 +11:00