| Commit message (Collapse) | Author | Age | Files | Lines |
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
It looked like the dot was flickering on and off after a refresh. It
wasn't: measured over the first twelve seconds it appeared once and never
went away, while its entrance animation started seven separate times.
render() rebuilds the whole DOM, so the pop replayed on every repaint.
A dot that means 'someone is waiting' has nothing to animate about, so
the animation is gone rather than gated. tools/unread-dot-test.js counts
animation starts against real appear/disappear transitions, so a future
entrance effect here fails instead of shipping as a flicker.
Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The message log had a fixed 62vh height, so the card was head + panels +
log + composer tall and the input fell off the bottom of the screen. The
card is now sized to the viewport and the log is the only part that
flexes: opening the invite or member panel shrinks the scroll area
instead of pushing the composer out of reach.
Three header changes, all the same idea — don't show a control for a
choice nobody is making:
'+' becomes 'Add person', because a plus sign doesn't say what it adds.
A lone channel isn't named at all. '#general' next to a composer that
says 'Message #general' points at a choice of one; several channels
become a select, which is what a choice looks like.
The new-channel field hides behind a 'New channel' button. Sitting open
right after you create a community, it reads as something you're
supposed to fill in.
tools/chat-layout-test.js holds the line at three viewport sizes with
both panels open, and covers the header behaviour through actually
adding a second channel.
Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
A remote signer dropped by a reload now says so above the composer, with
a button that reconnects in place — rather than letting someone write a
message and only then be told it can't be sent as them. Failing that it
opens the nostr settings, where logging in again is the fallback.
Every remote-signer login made before sessions were persisted lands in
exactly this state once.
Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The header carries a message button again, left of the wallet selector,
with a red dot when a conversation is waiting. Unread is a per-thread
watermark on the newest message from someone else, kept in the rumor's
own created_at so it means the same thing on every device it syncs to.
Rooms subscribe at startup now, or the dot could not speak for a
community nobody was listening to.
Communities no longer buzz a phone by default: push registration only
carries the stream keys of communities you have opted in, per community,
from a bell in the room header. DMs and payments are unchanged.
Presence and typing ride the channel stream as 21059 wraps, so who is
around stays inside the community's encryption rather than becoming a
public status. Measured against relay.coinos.io and nos.lol, neither
actually drops NIP-01 ephemeral kinds, so beats carry a NIP-40
expiration and relay.coinos.io sweeps kind 21059 hourly — and presence
is dated by the beat, never by arrival, or a replayed beat would light
up the whole member list.
The member list follows Telegram: online, then last seen in minutes and
hours, then a vague 'recently' rather than advertising how long someone
has been gone.
Co-Authored-By: Claude Opus 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
|
| |
|
|
|
|
|
|
|
|
| |
The placeholder repeated a minimum the line below already states, and it
was clipped anyway — the amount field had 14px of usable width at 360px
because "Move to Spending" crushed it. The row wraps to two full-width
lines when it's tight and stays on one line when there's room.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
|
| |
|
|
|
| |
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
|
| |
|
|
|
|
|
|
|
|
| |
"Instant · free to send" and "On-chain · mining fees apply" were one
line that swapped with the account; the card is just the balance now.
Strings, styles and stale translations removed with it, and the face's
reserved height comes down to match.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
|
| |
|
|
|
|
|
|
|
|
|
| |
The dots were an indicator pressed into service as a control — fine
under a thumb that can just swipe, too small for a mouse. They're
replaced by a pill in the header row naming the account it takes you to
(⇄ Savings / ⇄ Spending), which is both a proper click target and a
clearer answer to "what's the other one?". Swiping the card still works.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
|
| |
|
|
|
|
|
|
|
|
|
|
| |
Resolving a recipient (ark advert → BIP-353 → lightning) no longer
takes over the screen twice on the way: both steps keep the send form
in place and report progress as one inline line, so picking someone
goes straight to something actionable. The recipient chip on the zap
card gets a large variant — a 30px avatar and full-size name, since
it's who the money is going to.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
|
| |
|
|
|
|
|
|
|
|
|
|
| |
Into Spending gains a Max (fee-aware — it asks the tx builder what a
sweep would actually deliver, so the mining fee can't make the board
fail), and both directions now carry Max as a small affordance inside
the input's right edge instead of a button eating a third of the row.
It only appears when there's a balance to max. Balance face height
trimmed to match its shorter content.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Replaces the segmented toggle and the always-visible second balance.
The card now shows the account you're in at full size with a plain-word
descriptor ("Instant · free to send" / "On-chain · mining fees apply"),
two dots to flip, and a sideways slide when it changes. A swipe that
starts on the card switches account instead of tab; swipes anywhere
else still move between Receive/Send/History.
Fixes a real mobile bug found while testing: a touch sequence still
fires a compatibility click at the release point, so every swipe was
ALSO pressing whatever sat under the finger (which is what kept
bouncing the test wallet back to the unlock screen). One click is now
swallowed after a recognized swipe.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
|
| |
|
|
|
| |
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
|
| |
|
|
|
|
|
|
|
| |
72px, centered above the question (and the sign-in step), with a purple
glow and a slow float — the one place in the flow that isn't the coinos
brand, so it should look like nostr.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
coinos.io serves 502 for a third of the punk set (both the numbered and
hash endpoints), which is why a default avatar could come up blank. The
64 webps now ship with the app (53 salvaged, 11 gaps filled with
donors) and every reference is same-origin. Skipping the avatar step
publishes the deterministic punk as the kind-0 picture — your face is
the same on every nostr client. Success screen: checkmark now sits
below the title, bigger.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Fresh devices land in a full-screen flow instead of the unlock screen:
welcome → "do you have a nostr account?" (sign in brings wallet, name,
and profile along; No mints a wallet on the spot) → claim a username
(the background npub-default only surfaces a Keep button; a custom
claim — or a restored login's recovered name — advances by itself) →
pick a punk or upload a photo (nostr.build), published as the kind-0
name+picture → confetti. "Enter coinos" drops into a three-stop tour:
the avatar menu, the Spending/Savings toggle, and the tabs with the
swipe tip — each highlighted by a measured gold ring over a dimmed
page. One time only (localStorage flag), with an "I already have a
wallet" escape to the classic screen.
New seams: names.namesClaimForm, messages.publishProfile.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Tab changes no longer flash the whole page: only the content pane below
the tab strip slides sideways with a soft cross-fade — swipe direction
when a gesture caused it, index order for taps — while the balance card
and strip stay planted. Full-page entrances remain for real page
changes (settings, chat, profile, takeovers).
After a nostr sign-in the header briefly wore the wallet key's face:
nostrLoginIdentity now reports a just-connected live signer immediately
instead of waiting for the persisted link that only lands after the
wallet opens.
The nostrconnect URI carries a callbackUrl hint (NIP-55 style) so
signer apps that honor it can bounce back to the PWA after approval —
apps that don't will still find the session signed in when the user
returns, since the handshake completes over the relay in the
background.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
Horizontal-dominant quick swipes move through the main tabs, sliding
the page in from the swipe's direction (the nav animation picks a
directional variant when a gesture caused it). Gated to the wallet's
own tab pages — never chat, profiles, takeovers, or offline-forced
settings — with a vertical-dominance test so scrolling never
navigates, a touchcancel reset, and overscroll-behavior-x: none so the
browser's edge-back gesture doesn't fight ours.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The renderer rebuilds the DOM on every render, so naive CSS mount
animations would replay on every background repaint. Two primitives fix
that: uiChanged() gates one-shot animations to the render where the
thing actually happened, and animWindow() lets a rebuild that lands
mid-animation RESUME it via a negative animation-delay instead of
killing or restarting it.
On top of those: every real navigation rises in (screen/tab/subpage/
chat/profile — one keyed check in render()); the balance counts to its
new value and breathes green when money arrives; the avatar menu pops
from its corner; the move panel unfolds; the success check springs and
rings once when its page lands. Micro-transitions on buttons, tabs,
segs, inputs, list rows, avatars, and the settings chevrons.
One chromatic signature on the monochrome brand: a slow-drifting
bitcoin-gold ribbon across the top of the balance card, echoed by a
faint warm wash pooling at the top of the page, plus a film-grain
overlay for texture. All of it honors prefers-reduced-motion. The
nostr sign-in mark also gets a proper inset ostrich and a size bump.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
|
| |
|
|
|
|
|
|
|
|
| |
A watch-only wallet has no nostr identity, and the whole avatar menu —
including Settings and Logout — vanished with it. The menu now shows a
neutral face and keeps the keyless items; Edit profile and Messages
appear only when an identity exists.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
|
| |
|
|
|
| |
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
|
| |
|
|
|
|
|
|
|
|
|
| |
The punk is a statement about having no picture, not a loading state —
in-flight profiles show a quiet empty circle instead. Known profiles
persist (capped at 150, daily background refresh) so your own avatar
and regular correspondents paint correctly on the first frame of the
next session.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
|
| |
|
|
|
|
|
|
|
|
|
| |
The chat button leaves the header — the avatar's popup menu carries
Edit profile, Settings, Messages, and Logout (lock()). The menu is
available inside the chat takeover too, which now keeps the full
header. Messages provides just the avatar node via the headerAvatar
seam; the app owns the menu.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
|
| |
|
|
|
|
|
|
|
|
| |
The main page is just doors — Wallet (name, public key, recovery
phrase), Payments (payment address + Spending status), Network (chain +
data source), Nostr, Advanced. Every subpage keeps its own back button
and rides browser history via the existing settingsPage nav field.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
|
| |
|
|
|
|
|
|
| |
An npub isn't a key — no button, no label; just a small copy glyph
right-aligned in the box.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Everyone gets a face: profiles without a picture fall back to a coinos
punk, picked deterministically by the pubkey's last byte — the same 64
webps and formula the coinos app uses (initials show through if the
image can't load). Your own avatar moves from the chat home to the app
header next to the wallet selector, opening your editable profile from
anywhere.
Community owners can add channels from the room's + panel: one
owner-signed ChannelMetadata edition (CORD-03), and every member's
channel switcher grows when the fold lands.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
|
| |
|
|
|
|
|
|
|
|
| |
The main page ends with two doors — Nostr settings and Advanced
settings. The nostr subpage carries the address, account link, wallet
connect, and device sync cards; the inline section heading (and its
now-unused string/CSS) is gone.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Tapping any avatar or author name (chat rooms, DM threads, the chat
home) opens a profile page: avatar, name, nip05, lightning address,
about, npub, with Message and Pay actions (Pay runs the npub payment
cascade). Your own profile — reachable from your avatar on the chat
home — gets an editor for name, about, picture, and lightning address
(prefilled with your coinos address); saving merges over the newest
published kind 0 so fields we don't understand survive the round trip.
Zaps now remember who they went to: the ark feature keys the recipient
by what the movement already records (destination address or invoice)
and history rows wear a clickable avatar chip that opens the profile.
The messages feature exposes showProfile/profileChip seams so any
feature can do the same.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
A shared engine (src/recipient-search.js) merges three ranked sources:
an exact npub/hex paste, coinos usernames from the registrar's new
/search prefix endpoint, and NIP-50 kind-0 full-text search on
relay.nostr.band — the approach the major web clients take, since
ordinary relays don't index profiles. Results dedupe by pubkey, fill
avatars in one batched kind-0 fetch, and cache per query so narrowing
never re-hits the network. Input is debounced 300ms and gated by a
searchable() heuristic so addresses, invoices, and keys never trigger
a search.
Chat's New message panel narrows as you type and opens the thread on
pick; the Send form shows the same candidates under the destination
input and picking one runs the normal paste path (payment address →
BIP-353, npub → zap).
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The balance card's label becomes a Spending/Savings toggle and the
selection is app-wide state (persisted per device): the headline shows
the selected balance with the other quiet below, Receive shows the
payment address in Spending and a fresh on-chain address in Savings
(the per-page dropdown and its iconSelect widget are gone), and a
gift's source follows the account instead of its own toggle. Wallets
without Ark see the old single-balance card. Send stays
destination-driven — an invoice pays from Spending, an address from
Savings, as before.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Chat leaves the tab bar (which returns to its four evenly spaced tabs)
for an icon button in the header next to the wallet selector. It now
takes over the whole screen — no balance card, no tabs — with a back
button on the chat home view, and the logo still leads back to the
wallet. The generic tabs/tabContent seams this reverts to unused are
removed again.
Move panel: the direction toggle stretches across the card, and the
"X sats in Spending" line is gone — the balance sits right above it.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Refresh/consolidation is no longer a user concern: after each sync the
wallet renews automatically when any spendable vtxo is within ~a week of
expiry or fragmentation reaches six vtxos (a send needs one vtxo that
covers the amount), throttled to one attempt per half hour and never
while another round is in flight. The manual refresh button is gone.
The separate Move money page is gone too — the button on the balance
card now unfolds an inline panel with an Into Spending / Into Savings
toggle: boarding happens right there, and Into Savings hands off to the
existing exit page (cooperative offboard + unilateral exit unchanged).
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Advanced
The main Settings tab now inlines the active wallet's own cards
(recovery phrase, name, public key) instead of linking to a sub-page,
followed by payment address, Ark status, network, and data source. All
nostr cards — address, account link, wallet connect, device sync — sit
under one Nostr heading via a new nostrSettingsCards seam. Offline
transfer, address rescan, and auto-logout move to an Advanced sub-page.
The Ark provider picker is gone: mainnet always rides coinos (a stale
stored choice no longer wins); dev networks keep their per-network
defaults. The per-account screen (Accounts → ⚙) reuses the same card
builders unchanged.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
the only
- NIP-17 private DMs (src/dm.js): kind-14 rumors in sender-signed seals under
ephemeral wraps; interops with other nostr DM clients. Login signers gained
encryptTo/decryptFrom so extensions and bunkers can seal to a peer; the
inbox listens for both the login npub and the wallet key and publishes a
kind-10050 DM-relay list for the wallet key when none exists.
- Concord invites (CORD-05): mint shareable links (33301 bundle on relays,
keys only in the URL fragment), join by pasting a link or opening
v3.coinos.io/invite/…, and direct invites giftwrapped to an npub with the
k-tag index hint. Bundles self-certify the founder before anything joins.
- Multi-community: home view lists DM threads and communities; found your own
community in-app (owner-signed genesis). coinos stays baked in as default.
- Welcome DM: the names registrar DMs every first-time registrant from Adam's
npub on claim (config: welcome{sk,message}; deduped in registrar state).
Every new wallet auto-claims a payment address, so every new user gets one.
- relay.coinos.io write policy now allows 33301/13302/13303.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
|
| |
|
|
|
| |
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
|
| |
|
|
|
|
|
|
|
|
|
|
| |
Implements the Concord protocol (CORD-01..04) — private streams, the
control-plane fold, guestbook membership, owner-rooted authority — and
ships a built-in "coinos" community founded by Adam's npub (owner/admin).
Messages sign with the nostr login identity when a signer is live, else
the wallet's NIP-06 key; all encryption rides derived stream keys so
remote signers only ever sign seals.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Wvj4aoeMZwA7VUGdJP9Swi
|
| |
|
|
| |
Co-Authored-By: Claude Fable 5 <[email protected]>
|
| |
|
|
|
|
|
| |
The full logo from coinos.io (symbol + wordmark as drawn paths) at 28px,
inheriting the ink color for both themes; replaces the mark + text pair.
Co-Authored-By: Claude Fable 5 <[email protected]>
|
| |
|
|
|
|
|
| |
Inline single-color SVG of the brand symbol (ring + half-moon) that
inherits the ink color, next to the lowercase wordmark.
Co-Authored-By: Claude Fable 5 <[email protected]>
|
| |
|
|
| |
Co-Authored-By: Claude Fable 5 <[email protected]>
|
| |
|
|
|
|
|
|
|
| |
Icons, favicon, and PWA assets come from the coinos brand set; the
accent goes monochrome (black in light mode, white in dark, with a
proper on-accent text variable so buttons stay legible both ways) and
the inline bitcoin mark inherits the text color.
Co-Authored-By: Claude Fable 5 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
The receive address-type picker was a native <select>, which can't
render SVG in <option>s. Replace it with a lightweight custom dropdown
(icon-select) that shows a glyph per rail — ₿ Bitcoin, ⚡ Lightning,
the Second mark for Ark, 🕶️ Silent payment — closing on select or an
outside tap. Receive modes gained an icon field; the address option is
built in app.js. Silent-payment receipts (which merge into history as
on-chain-looking rows) now get a rail glyph + SP tag via a
decorateTxRow so they're distinguishable, matching how ark/gift rows
already decorate.
Co-Authored-By: Claude Fable 5 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
| |
- warn-box, addr-box, summary, toast and green badge/notice borders used
hardcoded light colors that washed out or vanished in dark mode; route
them through theme variables (new --toast-bg/-fg and --green-line pairs).
- Drive the footer "Install app" link from a persisted localStorage flag
instead of the live beforeinstallprompt event so it's present on first
paint after a refresh, eliminating the layout shift.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
- Dark mode: theme variables + a footer "Dark mode/Light mode" toggle,
persisted and applied pre-paint via a small head script (defaults to the
OS preference). Hardcoded surfaces moved to CSS variables.
- Gift amount: the unit label is now the clickable sats/BTC toggle, and the
amount is parsed in the selected unit.
- Gifts can now span multiple coins: createGift selects several confirmed
coins (first input SIGHASH_SINGLE to lock the change, the rest
SIGHASH_NONE), so a gift larger than any single coin works. Claim/preview
sum all inputs and size the fee by input count. Verified end-to-end.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
|
| |
|
|
|
|
|
|
|
| |
A footnote at the bottom: "The name Hal Wallet is a tribute to
legendary cypherpunk and Bitcoin pioneer, Hal Finney (1956–2014)",
with his name linking to his Wikipedia article. The contextual nod,
rather than leaning on his name up front.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
- Settings → Block explorer: pick mempool.space (default, with
blockstream.info as a silent failover), blockstream.info only, or a
custom Esplora/electrs REST URL (e.g. your own node). The realtime
WebSocket only applies to mempool.space; other explorers fall back to
polling. Switching rebuilds the API and rescans. Replaces the old
undocumented explorer-proxy hack.
- How it works: merge the "For the technically curious" disclosure into
the main body so it's all visible under "The basics", and dedupe the
overlapping no-server/offline sentences. Mentions the new explorer
setting.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
| |
- Name the app "Hal Wallet" (header, title, PWA manifest, package.json).
A nod to Hal Finney — just the name, no taglines or tributes.
- appTitle is a brand name now, so it's constant across locales (dropped
the translated overrides; they fall back to "Hal Wallet").
- Replace the native <select> caret with a custom chevron spaced off the
right border (the native one is crammed against the edge in Chrome).
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
- Headline balance now shows wallet.total (confirmed + mempool) instead
of confirmed, so a pending outgoing spend is debited immediately rather
than waiting for confirmation. The chain_stats-based confirmed balance
counts a coin as yours until the spend is mined, which is why it didn't
drop after broadcasting (incl. scanned-tx broadcasts). Incoming pending
is still surfaced by the "+X pending" line.
- summary { cursor: pointer } so the "Show QR" disclosure (and any other
<summary>) shows the hand cursor.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
|
| |
|
|
|
|
|
|
|
| |
The address input scrolls/truncates on mobile, hiding the ends. Render
the full address as wrapping text beneath it with the first/last 6
chars emphasized, so paste/type/scan can be verified without scrolling.
Updated imperatively on input so the field keeps focus.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Scan a Bitcoin address, a BIP21 URI (fills address + amount), or a
signed-transaction QR (opens a broadcast confirmation, then relays it)
from a viewfinder button on the Send form.
Decoder strategy keeps the main bundle small:
- Prefer the native BarcodeDetector (Chrome desktop/Android) — no lib.
- Otherwise lazy-load jsQR from a separate dist/jsqr.js, only when the
scanner is opened. jsQR stays out of index.html (~424 KB vs ~551 KB)
and off the initial load.
- The service worker precaches jsqr.js so offline scanning works for
installed PWAs on browsers without BarcodeDetector.
The scanner needs a camera + secure context, so it never shows on a
standalone file:// page; offline air-gapped signing is unaffected.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
- Rewrite the How it works page in a plainer, less generated voice;
drop the intro lead, the receive/send paragraph, and trim the rest.
- Fix passphrase wording: "13th word" (12-word phrase), not 25th.
- genIntro: "It's" instead of "It is".
- Unlock screen: label the field "Passphrase" (was "Optional
passphrase") and drop the "leave blank if unused" placeholder.
- Remove now-unused hiwLead / optionalPassphrase / leaveBlank keys
and the .lead style.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
|