| Commit message (Collapse) | Author | Age | Files | Lines |
| |
|
|
|
| |
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Tmfg8k5f3TbNJS34qiqHAp
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
StartLightningReceive on a payment hash with an unpaid invoice returns that
invoice — an earlier sale's amount and memo under a fresh QR (a 0.60 CAD
bill showed an 8,467-sat invoice on 2026-09-21). The returned invoice must
now carry the amount asked for and a comfortable expiry, or the index is
treated as spoken for and skipped. The counter is also floored above every
index an ln-recv action of ours already names, so a restored or merged
state can't rewind it.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Tmfg8k5f3TbNJS34qiqHAp
|
| |
|
|
|
|
|
| |
counter agree by eye.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Tmfg8k5f3TbNJS34qiqHAp
|
| |
|
|
|
|
|
| |
Amounts under one unit used to get four decimals; two now, like any price.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Tmfg8k5f3TbNJS34qiqHAp
|
| |
|
|
|
|
|
| |
own record.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Tmfg8k5f3TbNJS34qiqHAp
|
| |
|
|
|
|
|
|
|
|
|
|
| |
tip.
The row finds the ln-receive movement by the invoice it recorded and opens
the same detail screen the history page shows; the detail asks features
for more (arkMoveDetailExtra) and the till adds Bills, Tips (with the
percentage) and the note.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Tmfg8k5f3TbNJS34qiqHAp
|
| |
|
|
|
| |
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Tmfg8k5f3TbNJS34qiqHAp
|
| |
|
|
|
| |
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Tmfg8k5f3TbNJS34qiqHAp
|
| |
|
|
|
| |
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Tmfg8k5f3TbNJS34qiqHAp
|
| |
|
|
|
|
|
|
|
|
| |
from the right.
5 is 0.05, 277 is 2.77, 5588 is 55.88; backspace shifts out; the "." key
becomes "00". Sats are whole numbers and type plainly.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Tmfg8k5f3TbNJS34qiqHAp
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
the Receive tab.
v3.coinos.io/pos opens the point of sale once a wallet is up (claimed at
boot before any feature reads the path), so the till can be bookmarked or
put on a home screen. Settings → Payments gains "Start in point of sale on
this device" (localStorage, not synced: the till, not every phone the
owner carries). The amount and the custom tip get a 3×4 pad that edits the
same field a keyboard or a paste would. The button under the payment
address on Receive is gone.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Tmfg8k5f3TbNJS34qiqHAp
|
| |
|
|
|
|
|
|
|
| |
The ASP answers a settled hash with "already been paid" and a merely
issued one with "UNIQUE constraint failed: invoices.payment_hash"; both
mean the index is taken. Headroom raised to 200 skips.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Tmfg8k5f3TbNJS34qiqHAp
|
| |
|
|
|
| |
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Tmfg8k5f3TbNJS34qiqHAp
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
spent.
The ASP answered "invoice has already been paid" for a point-of-sale
invoice: the receive counter on the phone was behind the one the laptop
had used. createLnInvoice now retries on that answer with the next index
(the counter only moves up; the key index is allocated once an invoice
exists), so the Receive tab, NWC make_invoice and the point of sale all
recover instead of failing.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01Tmfg8k5f3TbNJS34qiqHAp
|
| |
|
|
|
|
| |
when the invoice is being made.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
|
| |
|
|
|
|
| |
the registry, not features/index.js.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
that keeps tips apart.
A new deferred feature (src/features/pos.js): type the amount in the display
unit, optionally a note, Charge. With the tip prompt on, the customer sees
the bill and picks a percentage (configurable, default 10/15/20), their own
figure, or no tip; one Lightning invoice is made for the total through the
Ark feature's receive (new hooks arkLnInvoice/arkLnWatch/arkLnUnwatch/
arkLnCancel wrap createLnInvoice and pollArkLn). Paid, expired and cancelled
sales are recorded with the bill and the tip as separate figures, and the
fiat rate at the time; the amount screen shows today's bills, tips and total.
Doors: Settings → Payments card, and a button under the payment address on
Receive (a receiveExtras hook the names pane renders).
Co-Authored-By: Claude Fable 5.1 <[email protected]>
|
| |
|
|
| |
Co-Authored-By: Claude Fable 5.1 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
| |
bitcoin: links.
njump's "Your default web app" is a web+nostr: link: it opens whichever
site registered that scheme. A card offers to register this app (the
browser asks), and ?u= now accepts the web+nostr: form.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
| |
route there; posts name the NIP-89 handler.
A NIP-89 handler event (kind 31990, d=coinos) under the coinos key points
njump and other pickers at /<npub> for people and /<note> for notes. The
client tag on public posts now carries that coordinate.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
|
| |
|
|
|
|
| |
the test clears its field between searches.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
| |
following.space's real link form.
NIP-50 search only knew the packs the search relay carried — 'Niche
Accounts' lives on damus and nos.lol, not relay.nostr.band. So the editor
now indexes the wide relays' packs once per session and matches titles and
descriptions by substring. A following.space link is /d/<id>?p=<pubkey>,
not an naddr; both are accepted.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
| |
A feed can name packs as well as people: the pack's current members are
its authors, read from the pack event itself and cached on disk, refreshed
hourly when a feed using it is opened — so a curator's change reaches the
feed by itself. The editor takes a pasted following.space link or naddr, or
searches packs by title (NIP-50 on relay.nostr.band). parseNostrRef learned
naddr.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
|
| |
|
|
| |
Co-Authored-By: Claude Fable 5.1 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
amber only for your own zap.
Custom feeds live in the synced messages state — a name, everyone you follow
and/or hand-picked people, and topics (hashtags, any of them; with people
set as well, only their posts on those topics — the way a nostr filter
composes authors and #t). Each feed keeps its own notes, clock and disk
cache; a chips row under the feed title switches between them and + opens
the editor (people are added through the same search the Send form uses).
A word in the header search is a topic too: 'Posts on this topic' opens a
session feed for it, as does a #tag in any post body — Save feed keeps it.
Topic-only feeds read the big public relays as well as ours, since a hashtag
has no author whose outbox we could follow.
The zap icon used to go amber once anyone had zapped a post; now only when
you have, like the heart.
tools/feed-custom-test.js drives the editor, the relay filter, a tagged post
landing, the #tag link, reload persistence and delete.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
A relay refusing the community-list write (rate limit, ban) left the remote
copy stale, and every resync asked for the same write again, each write
echoing back on the live fragment subscription and triggering the next —
five events every two seconds, forever. That filled relay.coinos.io's per-IP
budget for the whole household, and the phone behind the same IP could no
longer reach its remote signer: every NIP-46 request refused as
rate-limited, every incoming DM stuck undecrypted (2026-09-20).
An unchanged document is re-sent at most once per five minutes; a real
change goes out at once. Our own echoes are ignored, and another device's
write triggers a resync no more than once every ten seconds.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
|
| |
|
|
|
|
| |
unfolded.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
|
| |
|
|
| |
Co-Authored-By: Claude Fable 5.1 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
| |
Nostr.
A prefs flag (zapSound, absent = on) synced with the zap amount. The strike
and the tally are unchanged; only the clip stays quiet, and the clip chunk
is not even fetched while it's off.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
A pending zap no longer refuses the next tap: the optimistic tally keeps one
entry per zap and matches each report and receipt to the oldest it can
describe, so two default-amount zaps stack, settle and hand over to their
receipts one at a time. Instant post zaps run off the send screen's zap slot,
so a second tap can't evict the one still resolving, and send action ids are
unique within a millisecond.
Holding ⚡ (500ms) opens the amount screen in an edit mode — Save alone, or
Save and zap this note — from the action bar and the chat chips alike; the
press's timer lives on the element so a background repaint mid-press can't
turn a lifted finger into a hold.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
|
| |
|
|
| |
Co-Authored-By: Claude Fable 5.1 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
"Nothing new ever arrives" was four posts waiting behind the pill on the
phone and two on the laptop. Now a post that arrives on its own goes into
the feed at once, wherever you are: at the top it opens itself under your
eyes; further down it goes in above the fold with the page held still
(holdScroll), and the pill only says how many are up there. Its tap scrolls
to the top; reaching the top by yourself clears it, since only the pill
repaints and the keyed rows stay put. The small catch-up case gets the same
notice. The feed-live test says so.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
the top.
The catch-up on arriving at the feed asked every relay for its newest posts
with no lower bound, and everything not already in the fifty-post cache went
behind the pill, chunk by chunk: the count climbed in steps and stopped at
the pending list's cap of 200, whether there were 12 new posts or 500. Now
the pass is buffered and settled once, after every relay has answered. Posts
older than the newest we had are gap fills and merge silently. Up to twenty
genuinely new posts go in above what you're looking at with the page held
still (holdScroll: the row at the top of the viewport stays put, measured
after the paint so a browser that anchored on its own isn't corrected
twice), so scrolling up reveals them in order, newest at the top. More than
twenty means you've been away: the feed goes to the top, at the newest post,
as on a fresh open. The window grows only by posts landing inside it, so a
catch-up doesn't paint two hundred rows. The pill is now only for posts that
arrive live while you read further down. The feed-live test covers the three
arrivals, and its stale checks (auto-flush on scrolling up was removed on
purpose; a fresh <img> reports complete a task late) now say what the app
does.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Tap feedback: a bolt strike, the amount popping off the button, the post
trembling, and the zap.mp3 clip. The clip is 62KB of base64 and messages.js
is boot code, so it is its own chunk, fetched once a zappable post is on
screen and played inside the tap once loaded; the standalone build inlines
it. Ark zap receipts are signed by the wallet key, which has no profile: they
now carry the login identity as the sender (NIP-57's P tag), readers prefer
it, and our own older receipts read as us. The action bar is the same six
slots on every post: the zap button and the who-reacted chevron are always
there (inert until they have something to do), so the first zap no longer
reflows the row, and you can zap your own posts and messages. Community
rows centre their unread dot off the edge. Also in here: reactions with
custom emoji, reply-composer focus under the tapped post, profile fetch
retry, and Lightning zap failures that say so.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
grants.
Header buttons always leave the current feature screen; an account with
no remembered nostr identity opens Accounts instead of nothing. Logout
confirms in place. A scan finishing after logout or an account switch no
longer drops the new session into offline mode (stateGeneration guards in
sync + ark). Spending restores from the snapshot first. A migration grant
names the identity that owns an address; its manager may register it
without becoming that identity (names/ownership.js). Browser tests for
account access, profile retry, spending restore, thread reply focus,
custom-emoji reactions and registry ownership.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
|
| |
|
|
|
|
| |
Reviewer asked for no tags in commit: and no chained commands.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
|
| |
|
|
|
|
|
|
|
| |
The sats total used to sit up by the timestamp as its own chip; now it is the
count on the zap button, like likes and boosts have theirs. Amber once anyone
has zapped, breathing while ours is in flight, and shown read-only (no zap
handler) on posts you can't zap so the number still reads.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
|
| |
|
|
|
|
|
|
| |
F-Droid's APK check refuses the Play-only dependency-metadata signing
block AGP adds by default. Off for every flavor.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01JuwQqNWtDJcxPWtEm9134z
|
| |
|
|
|
| |
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01JuwQqNWtDJcxPWtEm9134z
|
| |
|
|
|
| |
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01JuwQqNWtDJcxPWtEm9134z
|
| |
|
|
|
|
|
|
|
|
|
|
| |
From the fdroiddata review and its pipeline: store text (summary,
description, icon, changelogs) belongs in fastlane/ here rather than in
the recipe; the category is "Wallet"; the scanner strips committed APKs
by itself, so the two scandelete entries go; and bun.lockb is a binary
the scanner flags — replaced by Bun's text lockfile (bun.lock, same
pinned versions). A new tag is needed for the new tree, so 1.7.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01JuwQqNWtDJcxPWtEm9134z
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The Android builds so far were shells around the live site: a verified
APK proved nothing about the code that ran. The new `fdroid` flavor
(io.coinos.fdroid) shares the WebView shell and carries the built web
app in its assets. The page still lives at the v3.coinos.io origin — same
storage, links and gift URLs — but every file under it is answered from
the APK (Assets.java); only the site's live API paths reach the network,
and the bundled page registers no service worker (HAL_NO_SW=1).
Two clean unsigned builds give the same APK. COINOS_UNSIGNED=1 builds
without the keystore; Bun is pinned via packageManager; the Gradle wrapper
properties pin 8.12. fdroid/io.coinos.fdroid.yml is the fdroiddata recipe
(checksum-pinned Bun in sudo, prebuild web build, scandelete, our signing
key allowed for the Binaries match) and docs/REPRODUCIBLE.md the how-to.
Verified on a phone: the bundled build cold-starts in airplane mode.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01JuwQqNWtDJcxPWtEm9134z
|
| |
|
|
|
| |
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01JuwQqNWtDJcxPWtEm9134z
|
| |
|
|
|
| |
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01JuwQqNWtDJcxPWtEm9134z
|
| |
|
|
|
|
|
|
|
|
|
| |
A tapped history row claims the whole tab area whichever tab is picked,
so jumping to ui.tab = 'send' from a profile's Pay button (or a zap's
form fallback) with a renewal's detail still open showed that detail
instead of the form. showSend() closes any open detail first; the three
feature paths that jump to Send use it.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01JuwQqNWtDJcxPWtEm9134z
|
| |
|
|
|
|
|
|
|
|
|
|
| |
A reaction's target was fetched once from our relays, and a miss was
final for the session — so with our own relay down for an evening, a
reply that sat on four relays showed as "no longer on your relays" until
a reload. A missing note is now retried when next wanted (half a minute
on), the reaction's e-tag relay hint rides along, and tapping the row
asks again instead of doing nothing.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01JuwQqNWtDJcxPWtEm9134z
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
Posts a refresh found slid in a beat after the cached page painted,
moving what you had begun reading, and reaching the top of the page let
waiting posts in with a re-render under a finger on its way to the pill —
the tap landed on the post beneath. Now everything that arrives after the
first paint, the boot catch-up included, waits behind the pill wherever
you are; the pill is a keyed node whose count bumps on each change; and a
tap scrolls to the top before painting so the new posts open under your
eyes. A rebuilt follow list still rebuilds the feed in place.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01JuwQqNWtDJcxPWtEm9134z
|
| |
|
|
|
|
|
|
|
|
| |
Vector writes a mention as @npub1… with no nostr: prefix; ours only
resolved the prefixed form, so the raw key sat in the bubble. Bare npubs
and nprofiles, with or without the @, now render as @name and open the
profile, like the prefixed ones. Keys inside URLs are left alone.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01JuwQqNWtDJcxPWtEm9134z
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
arrive.
One reaction per author was folded as "last one in wins". A reload's
backfill hands reactions back in relay order, so a flame swapped for
confetti came back as the flame. Rooms, DMs and the public page now keep
the newest by the rumor's own clock, and an optimistic send stamps its
time so an older one arriving afterwards stays out.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01JuwQqNWtDJcxPWtEm9134z
|
| |
|
|
|
|
|
|
|
| |
A reaction sent from v3 never showed in Vector: its parser requires the
NIP-25 p tag naming the reacted-to message's author (CORD examples §2.3
has e, p and k), and ours sent only e and k. Added.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01JuwQqNWtDJcxPWtEm9134z
|