<feed xmlns='http://www.w3.org/2005/Atom'>
<title>coinosv3.git/src/features/ark.js, branch fdroid-v1.8</title>
<subtitle>coinos v3 — bitcoin, Ark, Lightning and nostr wallet (web + Android)</subtitle>
<id>https://git.coinos.io/coinosv3.git/atom?h=fdroid-v1.8</id>
<link rel='self' href='https://git.coinos.io/coinosv3.git/atom?h=fdroid-v1.8'/>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/'/>
<updated>2026-09-17T04:27:00Z</updated>
<entry>
<title>Pay from a profile opens the Send form, not a lingering payment detail.</title>
<updated>2026-09-17T04:27:00Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-09-17T04:27:00Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=9360ca6806332a9c7e3a2e11f0b973511493c192'/>
<id>urn:sha1:9360ca6806332a9c7e3a2e11f0b973511493c192</id>
<content type='text'>
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 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_01JuwQqNWtDJcxPWtEm9134z
</content>
</entry>
<entry>
<title>Coins page: renewal is automatic, and the copy says so first.</title>
<updated>2026-09-16T04:46:24Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-09-16T04:46:24Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=f7a6a2bb49ce2d718f1f2ef7b5692be873bb2734'/>
<id>urn:sha1:f7a6a2bb49ce2d718f1f2ef7b5692be873bb2734</id>
<content type='text'>
The renewal card opened with how to renew and mentioned only at the end
that the wallet does it by itself, which read as an invitation to renew
by hand. It now leads with the automatic, free renewal before expiry,
then says renewing early is only for someone who would rather not count
on the coinos server, with the round cadence taken from the server's
own info (two minutes now, not the hour the old text claimed). The
"past its expiry" footnote under the table is gone. Stale translations
of the rewritten strings fall back to English.

Co-Authored-By: Claude Fable 5.1 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_01JuwQqNWtDJcxPWtEm9134z
</content>
</entry>
<entry>
<title>Spending coins as a headed table instead of chip rows.</title>
<updated>2026-09-16T04:25:37Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-09-16T04:25:37Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=0f6fd7f06d27fa9860bd04bde13fb4ae3794fdf8'/>
<id>urn:sha1:0f6fd7f06d27fa9860bd04bde13fb4ae3794fdf8</id>
<content type='text'>
Every row repeated "expiry", "exit cost", "renewal cost" as pills. The
labels now sit once in a header row over right-aligned tabular figures;
the table's wrapper scrolls sideways on a screen too narrow for it (the
page never does), and it fits a 390px phone without scrolling. A tap
anywhere on a row toggles it. A sub-satoshi renewal share reads "&lt; 1 sat".

Co-Authored-By: Claude Fable 5.1 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_01JuwQqNWtDJcxPWtEm9134z
</content>
</entry>
<entry>
<title>A tiny coin's renewal chip says "under 1 sat", not "1 sat".</title>
<updated>2026-09-16T04:18:17Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-09-16T04:18:17Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=229dea361b719128cf2657b6ab51aad9aca463b1'/>
<id>urn:sha1:229dea361b719128cf2657b6ab51aad9aca463b1</id>
<content type='text'>
The server prices a renewal on all the coins together: ppm accumulates
sub-satoshi across every input and rounds up once. The per-coin chip
rounded each coin's share up on its own, so nine 1-sat coins each showed
"renewal cost 1 sat" under a total of 4 sats — as if the page were
skipping them. The chip now shows the coin's real share: "under 1 sat"
for a sub-satoshi one, rounded otherwise, and its tooltip says how the
fee is priced.

Co-Authored-By: Claude Fable 5.1 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_01JuwQqNWtDJcxPWtEm9134z
</content>
</entry>
<entry>
<title>A gift locked from Savings shows under Savings, not Spending.</title>
<updated>2026-09-15T04:58:33Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-09-15T04:58:33Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=a493b12aca18a670296f0f7142ad041b87ec1b69'/>
<id>urn:sha1:a493b12aca18a670296f0f7142ad041b87ec1b69</id>
<content type='text'>
Every feature balance line landed on the Spending face, but a gift's
locked reservation is on-chain money still sitting in Savings. Lines now
say which side they belong to and draw on that card: gifts on Savings
beside pending incoming, ark's Moving… on Spending as before.

Co-Authored-By: Claude Fable 5.1 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>The balance says everything it has to say in one card.</title>
<updated>2026-09-14T21:28:33Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-09-14T21:28:33Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=b2d12093a935683e69af3e92d620326dcf7a2710'/>
<id>urn:sha1:b2d12093a935683e69af3e92d620326dcf7a2710</id>
<content type='text'>
Under the Spending balance, warnings stacked up as separate boxes — two
red cards and a grey line, with three Manage links between them, all
pointing at the same page. They are one card now: red if anything in it
is a warning, plain otherwise, each notice on its own line, and a single
Manage at the bottom right. A lone quiet advisory (the exit-cost line most
wallets show) keeps its centred grey line.

Co-Authored-By: Claude Fable 5.1 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_01QYJfZ4A1TDCEY4Foq3CApR
</content>
</entry>
<entry>
<title>A zap answers as fast as the route allows.</title>
<updated>2026-09-14T16:16:23Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-09-14T16:16:23Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=dd1489303f59ccef6b322142f94e08d750c06e79'/>
<id>urn:sha1:dd1489303f59ccef6b322142f94e08d750c06e79</id>
<content type='text'>
The wallet used to add two to four seconds of its own around a Lightning
send: a random pause plus a relay look-back before paying, and a
two-second poll for the result after. The notifier's claim now decides
who pays in one round trip, with the relay look-back kept only for
replays and for when the notifier gives no verdict; a phone answering
from behind another app waits a second so a desktop tab wins the claim
instead of paying at a throttled crawl. After the send, one held
CheckLightningPayment call brings the preimage the moment CLN has it —
for wallet-connect pays, the background worker, and the app's own Send.

Co-Authored-By: Claude Fable 5.1 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_01QYJfZ4A1TDCEY4Foq3CApR
</content>
</entry>
<entry>
<title>A zap answered by two tabs no longer reports as failed.</title>
<updated>2026-09-14T15:53:35Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-09-14T15:53:35Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=6394de43d4e596aaeddd2b262bb7a595679d8fbc'/>
<id>urn:sha1:6394de43d4e596aaeddd2b262bb7a595679d8fbc</id>
<content type='text'>
Every open tab of the same wallet sees every wallet-connect request. Two
hidden tabs on one laptop both tried to pay the same zap: the ASP refused
the second with "payment already in progress", and that error reached
Amethyst half a second before the first tab's preimage. A Web Lock per
request now lets one tab (or the worker) answer while the rest stay
quiet, and a device that does meet "already in progress" waits for the
sibling payment's outcome — relaying its preimage only if the payer never
speaks — instead of shouting a failure over sats that went through. The
losing side also stops writing a failed row into history for it.

Co-Authored-By: Claude Fable 5.1 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_01QYJfZ4A1TDCEY4Foq3CApR
</content>
</entry>
<entry>
<title>The renewal happens whether or not anyone opens the app.</title>
<updated>2026-09-14T06:52:39Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-09-14T06:52:39Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=4131e5ee24c4891caffdd8f4ca903ee973d104f7'/>
<id>urn:sha1:4131e5ee24c4891caffdd8f4ca903ee973d104f7</id>
<content type='text'>
Every coin expires, and until now the only thing standing between a
balance and its expiry was maybeAutoRefresh: it renews when the wallet is
opened inside the last 96 blocks, roughly sixteen hours. Bark's own
developers say the same premise fails on mobile — people don't reliably
open a wallet at the right hour, which is why every mobile Ark client
they know of has moved to delegated refreshes and why they are building
server-driven renewal.

captaind already has it, and ark.coinos.io has been carrying the column
unused: SubmitRoundParticipation takes a scheduled_height, and the server
holds that participation out of every round until the height arrives,
then runs it with nobody online — the round tree branch is signed by the
server, which is the whole point of a delegated refresh. The fee is
priced at the height it will run at, so a standing order lands in the
free bracket rather than today's.

So each spendable coin now gets one registered 36 blocks before its
expiry, six hourly rounds of slack. It is deliberately not an action:
the coin stays spendable, the wallet never reads as busy, and spending it
simply kills the order — the server drops a participation whose input is
gone, and _driveScheduled drops ours. The claim comes later, whenever the
wallet next opens: the mailbox breadcrumb we already post wakes it, and
the leaf cosign and forfeit are the ordinary refresh path from there.

Nothing about the input's expiry blocks that claim, which is what makes
this worth having. A wallet that goes quiet for a month comes back to a
coin already renewed and anchored in a fresh tree, instead of one the ASP
has swept and would have to honor out of goodwill.

One cycle per visit is all it can buy — the replacement's id doesn't
exist yet, so its own backstop waits for the next time the app is opened.

tools/ark/scheduled-refresh-test.js covers the five behaviours on
regtest: the server holds the order until its height, runs it while the
wallet is closed, the wallet claims on return, a spend voids the order,
and a claim still works after the input has EXPIRED (the last one mines a
coin's whole lifetime, so it also re-refreshes the funding wallet first —
an expired vtxo can be renewed but not sent).

Riding along: the expired-coin notice that was already sitting in the
working tree, and manager-test's tampered-vtxo check, which had been
reading base64 vtxo bytes as hex since they moved to IndexedDB.

Co-Authored-By: Claude Opus 5 (1M context) &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_019fMdLypdg5JaU7bdeUFF8v
</content>
</entry>
<entry>
<title>Say the currency once, and stop hedging about old prices.</title>
<updated>2026-09-12T06:05:49Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-09-12T06:05:49Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=d3234dfaf12dc3d7970c099fdc777a9b4ccc8e9d'/>
<id>urn:sha1:d3234dfaf12dc3d7970c099fdc777a9b4ccc8e9d</id>
<content type='text'>
The balance read "US$74.67 USD" — the symbol and the unit tag saying the same
thing twice. Amounts now format bare, like sats and BTC do: whatever labels
the number says which money it is. The currency symbol stays where a number
stands alone in prose, which is the "Worth then" line and nowhere else.

The '~' marking a payment older than any price we sampled is gone too. It was
bookkeeping the beta doesn't need: a payment we have a price for is shown at
that price, one we don't is shown at today's, and nobody has to learn a
squiggle.

The currency picker has moved to sit beside the language picker at the foot
of the page — display preferences together, where they're findable. It spent
one day under Settings → Network, where it wasn't.

And a bug this feature exposed rather than caused: nine notices end in the
word "sats" in every language we ship, and were being handed the display
unit. "Uncooperative exit costs about US$2.03 sats" — and long before fiat,
"about 0.00435397 sats" for anyone in BTC. They're given sats now, which is
what they claim to be showing.

Co-Authored-By: Claude Opus 5 (1M context) &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_019mrt228Upn9nNCwGixzSLx
</content>
</entry>
</feed>
