Skip to content

Namehold v0.4.0

Choose a tag to compare

@github-actions github-actions released this 08 Aug 00:35
ed23f4c

Added

  • System tray / menu-bar presence — Namehold now lives in the system tray
    so it keeps running (local hsd node + background sync daemon alive) when the
    main window is closed. The tray menu offers Open Namehold, a live node
    status label with a Start/Stop node toggle, a Sync in background
    checkbox, and Quit. A new System Tray section in Settings adds two
    toggles: Close to tray (default ON — closing the window hides it instead
    of quitting; click the tray icon or use Open to restore) and Launch at
    login
    (registers the app to auto-start, via tauri-plugin-autostart:
    LaunchAgent on macOS, Run key on Windows, .desktop on Linux). The tray
    icon reflects node state with three variants (normal / syncing / stopped),
    rendered as a macOS template image so it adapts to light/dark menu bars. A
    3-second reconciliation ticker keeps the tray in sync with changes made
    outside it (frontend actions, hsd autostart, sync transitions). New Tauri
    commands: is_close_to_tray_enabled, set_close_to_tray_enabled. New
    settings keys: close_to_tray, launch_at_login.

  • Recover lost bids from any hsd wallet — if you reinstall, seed-restore,
    or import a bid from another hsd-compatible wallet, Namehold can recover the
    bid value without you remembering the exact amount. The Name Actions modal
    shows a Recover bid panel during the REVEAL phase with two options:
    enter the amount if you remember it, or click Auto-recover (brute-force)
    to sweep candidate values. Recovery uses only the account xpub (public) —
    never needs your passphrase — and works because the nonce derivation is the
    hsd standard, not Namehold-specific. Typical bids under 100 HNS recover in
    seconds. See docs/RECOVER_LOST_BIDS.md for the
    full guide.

  • Background HSD Sync Daemon — a separate Rust binary (namehold-syncd) that
    syncs wallet profiles (UTXOs, name states, transactions) from the local hsd node
    every 60 seconds, even when the app is closed. Controlled by a Settings checkbox
    "Sync in background" (default ON). When enabled, hsd stays running after app
    exit; the next launch adopts it. A cross-process DB lock table (sync_locks)
    coordinates the app's manual Sync and the daemon via heartbeats (10s) and
    stale-lock takeover (30s) to prevent concurrent writes. Crash recovery: the app
    respawns the daemon on startup if the toggle is ON and the daemon is dead.
    Bundled as a Tauri sidecar (externalBin).

  • New DB migration 021_sync_locks.sql — creates the sync_locks table for
    cross-process sync coordination.

  • SPV (Simplified Payment Verification) mode — an opt-in lightweight alternative
    to the full node mode. SPV downloads only block headers (~几十MB vs ~15GB),
    enabling fast first launch and minimal disk usage. Balance and name data come from
    the explorer; sending is blocked in SPV mode (read-only). Controlled via a
    "Node mode" dropdown in Settings → Connections (default: Full node).

  • Explorer failover — all explorer HTTP requests now support automatic failover
    to a configurable fallback URL. Configured via "Explorer fallback URL" in Settings.

  • SPV UI indicators — StatusStrip shows "Explorer (SPV)" when in SPV mode to
    explain why reads come from the explorer.

  • SPV-aware write capability — SPV mode shows a clear "SPV mode cannot send
    transactions" message instead of the generic "node not address-indexed" error.

  • TLD Management P1 — Batch operations — renew, reveal, redeem, or finalize
    multiple names in one transaction. Multi-select checkboxes on the Owned Names
    table with a batch action bar ("Renew Selected" / "Reveal Selected" /
    "Redeem Selected" / "Finalize Selected"). Each action opens a
    BatchConfirmModal showing the count and estimated fee with a collapsible
    name list before signing + broadcasting.

  • TLD Management P2 — Watchlist — track names you don't own for monitoring.
    New "Watchlist" page in the sidebar with add/remove, tags (comma-separated),
    bulk state fetch via get_watchlist_status, CSV import/export (name,tags, notes,added_at,state,expiry), and an "Add to Watchlist" toggle in both
    NameActionsModal and NameInfoModal. Database migrations
    022_watchlist.sql (base table) and 024_watchlist_tags.sql (adds tags
    column).

  • TLD Management P3 — Atomic paid name swaps — atomic finalize-with-payment
    covenant: the buyer finalizes a TRANSFER and pays the seller in the same
    transaction, so no party can renege after the lockup expires. Buyer side:
    "Buy with payment" button on names in TRANSFER state. Seller side: "Sell
    with payment" flow with saved offer tracking (023_paid_swap_offers.sql)
    and a verify-only claim_paid_transfer command that inspects the
    broadcast tx before marking an offer paid.

Changed

  • Removed the Portfolio page and the "Show Portfolio in the sidebar"
    setting.
    The hidden advanced_mode-gated Portfolio workspace (Inventory,
    Batches, Renewals, DNS tabs) and its /portfolio route have been removed
    entirely, along with the advanced_mode setting key. The sidebar no longer
    has any advanced-mode gating.

  • MIT LICENSE — repo now carries an explicit MIT license file.

  • get_resource Tauri command — returns combined name info + DNS resource
    records from the local hsd node with graceful degradation to the explorer for
    name state. Currently backend-only (no frontend consumer after the DNS page
    removal in a later commit).

  • Watchlist v2 — richer columns + background alerts. The Watchlist table
    now shows three additional columns pulled from the live name info: a
    Countdown to the next phase transition (e.g. "Bidding closes in 42
    blocks (~7h)"), the Highest bid so far, and Expires (days-until-
    expire, colour-graded like the Renewals view). Names owned by the active
    wallet profile get an inline Owned badge next to the name. Combined
    with a new opt-in Watchlist notifications section in Settings, the
    background sync daemon (namehold-syncd) polls each watched name every
    60s, diffs against the last-seen snapshot in a new watched_name_states
    cache table, and fires OS notifications on: entry into BIDDING, a
    previously CLOSED name becoming available again, bidding-soon lead
    time (default 144 blocks / ~1 day), and a configurable global
    highest-bid threshold
    crossing (in HNS). Adaptive polling skips names
    whose next transition is > 300 blocks out when the state was refreshed
    within the last 5 minutes. The daemon is the sole notifier — the in-app
    scanner still owns reveal/renewal deadlines for names you've bid on or own,
    so there's no double-fire. Alerts fire even when the Namehold app is closed
    (as long as background sync is enabled). New Tauri command:
    get_watched_states (read-only, hydrates the columns without RPC on first
    page open — currently unwired on the frontend; columns hydrate via
    read_name_info). New settings keys: watchlist_notify_enabled,
    watchlist_notify_bidding_soon_lead_blocks,
    watchlist_notify_highest_bid_threshold_hns. New DB migration:
    025_watched_name_states.sql. New crate: notify-rust (cross-platform
    OS notifications, no Tauri AppHandle required).

  • Unified input/button sizing. Input and Select now accept an
    inputSize prop ("sm" | "md", default "md") that shares the exact
    padding + text-size tokens with Button's size prop, so a control and the
    button beside it render at identical heights. All Button variants now carry
    a (transparent) 1px border so bordered inputs and borderless buttons line up
    to the pixel. Replaced ad-hoc raw <input>/<select> elements across the
    Auctions, Activity, Namebase dashboard/import, wallet name filter, DNS
    records editor, and the DataTable search box with the shared Input/
    Select components. Fixes the visible ~10px height gap between the
    add-name/look-up inputs and their adjacent buttons.

  • Inline node lifecycle actions. The StatusStrip node pill now opens a
    popover menu with Start node / Stop node / Re-sync chain actions
    (plus an "Open Settings" escape hatch), replacing the old Settings link. The
    WalletView "needs node sync" callout has an inline Start node button
    with an "Open Settings" fallback on failure. The update-installed banner
    shows a Relaunch now button instead of directing users to Settings.
    New reusable Popover component (src/components/ui/Popover.tsx).

Fixed

  • macOS notification sender identity — OS notifications from the
    background sync daemon (namehold-syncd) now attribute to Namehold
    instead of "Terminal" / Finder / a generic sender. Because the daemon runs
    unbundled (no Tauri AppHandle), it now claims the Namehold bundle ID via a
    Once-guarded ensure_notify_identity() before emitting; the Tauri app
    pre-empts the same identity before the notification plugin initializes. A
    new Debug Notifications panel in Settings (debug builds only) fires each
    notification path on demand for verification, backed by the
    #[cfg(debug_assertions)] simulate_notification Tauri command.
  • TldInventory bulk Transfer/Finalize — bulk actions on N selected names
    now actually operate on all N, not just the first. Transfer loops N single
    transactions (per-name recipient safety); Finalize uses the batch draft
    command for a single atomic transaction. (Historical: the Portfolio/
    TldInventory workspace this fixed is removed in this same release.)
  • Layout badge color inversion — the wallet capability badge now renders
    CAN SEND in green (safe) and READ-ONLY in neutral gray, matching intuitive
    traffic-light semantics (previously CAN SEND was red).
  • Sync UI view jumping — automatic sync (every 60s) no longer expands the
    full sync status panel. Auto-sync shows "Syncing…" on the button with a
    spinner; the full progress panel only appears for manual Sync.
  • Stale-data banner suppressed when node is live — the "Couldn't verify
    urgent auction tasks — data may be stale." banner no longer appears during
    transient query hiccups while the node is synced; it only shows when the
    node is actually offline.
  • Unicode/IDN name lookup — the "Get a TLD" input now accepts Unicode
    characters (e.g. сбер, münchen) and encodes them to ACE (Punycode) at
    lookup time, instead of silently stripping non-ASCII input. Added tr46
    UTS-46 processing library and src/lib/idnEncode.ts module.

Removed

  • Dead migration UISyncVerification and MigrationAssistant
    components (plus their test) and the compare_inventory_with_provider
    backend command have been removed. These were scaffolding for a one-time
    Namebase migration flow that is no longer needed.

CI / tooling

  • sccache + mold linker + debuginfo thinning — CI cold-compile speedup
    via distributed compilation caching (sccache), the mold linker for
    faster linking, and stripped debuginfo in CI builds.
  • Parallel rust-lint + rust-test jobs, nextest adoption — lint and test
    run concurrently; cargo-nextest replaces cargo test for per-test
    parallelism and structured output.
  • Fast/full lane split — PR pushes run a fast lane (subset of tests);
    pushes to main run the full suite. Configured via nextest.toml.
  • sccache resilience — graceful degradation when the GHA cache backend
    is unreachable; CI continues uncached rather than failing.
  • Argon2id test-mode cost reductioncfg(test) drops KDF from 256 MiB
    to 8 MiB, cutting vault-related tests from ~50s to <0.25s each.
  • Per-process temp DB paths — fixes nextest parallelism flakes where
    concurrent test processes collided on the same SQLite file.