<feed xmlns='http://www.w3.org/2005/Atom'>
<title>coinosv3.git/tools/ark, branch fdroid-v1.7</title>
<subtitle>coinos v3 — bitcoin, Ark, Lightning and nostr wallet (web + Android)</subtitle>
<id>https://git.coinos.io/coinosv3.git/atom?h=fdroid-v1.7</id>
<link rel='self' href='https://git.coinos.io/coinosv3.git/atom?h=fdroid-v1.7'/>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/'/>
<updated>2026-09-14T06:52:39Z</updated>
<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>Include mining fees in the Spending deposit preview</title>
<updated>2026-09-12T04:53:28Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-09-12T04:53:28Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=8beb1c17df8d1c96a43803c0d87a5c5f1ac2494e'/>
<id>urn:sha1:8beb1c17df8d1c96a43803c0d87a5c5f1ac2494e</id>
<content type='text'>
</content>
</entry>
<entry>
<title>Report rejected Ark sends and exclude server-rejected expired inputs</title>
<updated>2026-09-11T15:51:54Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-09-11T15:51:54Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=207cb4451a07417baf63b2586e6759cf8b471482'/>
<id>urn:sha1:207cb4451a07417baf63b2586e6759cf8b471482</id>
<content type='text'>
</content>
</entry>
<entry>
<title>A wallet too small to renew warns before its coins expire; dust never dies</title>
<updated>2026-08-04T16:28:36Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-08-04T16:28:36Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=e462bc1e7756dcbf7c651ee282e96ee8c48b5a14'/>
<id>urn:sha1:e462bc1e7756dcbf7c651ee282e96ee8c48b5a14</id>
<content type='text'>
The warning: when the Spending balance minus round fee is under the
330-sat round minimum AND a vtxo enters the renewal window, auto-refresh
can't save the coins — a wallet-screen notice (and a daily local
notification, when permitted) says to receive any amount or spend
before the deadline. New walletNotices feature hook renders under the
balance card.

The amnesty: sub-dust vtxos have no unilateral exit to protect, and
regtest proves captaind keeps cosigning their spends past expiryHeight —
even after the watchman claims the backing on-chain
(tools/ark/expired-dust-test.js). Only hal's own receive validation
stood in the way; it now exempts sub-330 vtxos from the expiry check.

Co-Authored-By: Claude Fable 5 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_015QwAtBSpKvECqp1rHLHjJk
</content>
</entry>
<entry>
<title>Ark gifts go down to 1 sat; negative amounts can't OOM the encoder</title>
<updated>2026-08-04T15:31:21Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-08-04T15:31:21Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=9fd8887dcdd5e0fc1067a91032bfd18eb25f0202'/>
<id>urn:sha1:9fd8887dcdd5e0fc1067a91032bfd18eb25f0202</id>
<content type='text'>
Regtest-proven (tools/ark/dust-gift-test.js): the ASP cosigns all-dust
arkoor sends, so a sub-dust bearer vtxo sweeps to its claimer fine, and
dust folds into rounds alongside bigger siblings. The 330-sat gift
floor guarded a failure that can't happen — dropped to 1 sat.

The experiment also caught a live bug: refresh() of a balance smaller
than the round fee computed a negative output amount, and pbWriter's
varint sign-extends negatives into an infinite loop — auto-refresh
would OOM the tab of any wallet too small to renew. varint now throws
on negatives and refresh() refuses cleanly, before marking coins
pending, when balance minus fee is under the server's 330-sat output
minimum.

Co-Authored-By: Claude Fable 5 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_015QwAtBSpKvECqp1rHLHjJk
</content>
</entry>
<entry>
<title>Note the Cloudflare managed-WAF exception the ASP hostname needs</title>
<updated>2026-08-01T15:10:33Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-08-01T15:10:33Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=93f167e074e1f6b0fd831f7f2f3b42fc172ef26c'/>
<id>urn:sha1:93f167e074e1f6b0fd831f7f2f3b42fc172ef26c</id>
<content type='text'>
Binary protobuf POSTs trip signature rules above ~1.5KB; the demo now runs
entirely over public HTTPS with a path-scoped skip in place.

Co-Authored-By: Claude Fable 5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>Add the live bridge demo against the coinos mutinynet ASP</title>
<updated>2026-08-01T01:17:25Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-08-01T01:17:25Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=3b8f2b63e9fe4ecc83e54e7cc8c757924927f83d'/>
<id>urn:sha1:3b8f2b63e9fe4ecc83e54e7cc8c757924927f83d</id>
<content type='text'>
Reference run for the upstream proposal: real deployed ASP, real deployed
bridge, real Lightning settlement — no regtest. Boards a fresh wallet, quotes
a 25 sat zap (1 sat fee vs second's 20 sat mainnet floor), locks the HTLC,
lets the bridge pay and claim, then reads the revealed preimage back out of
the ASP via GetHtlcPreimage.

Board funding goes through a helper on cs because a board output must be
vout 0 and sendtoaddress randomizes output order.

Co-Authored-By: Claude Fable 5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>Add the trustless Ark-&gt;Lightning swap bridge</title>
<updated>2026-07-31T22:46:22Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-07-31T22:46:22Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=52a88f58dba97926c57aad4765c0a67be9b6c9a5'/>
<id>urn:sha1:52a88f58dba97926c57aad4765c0a67be9b6c9a5</id>
<content type='text'>
A third-party swap provider built on the proposed VtxoPolicy::Htlc: users pay
bolt11 invoices from their Ark balance without the ASP being the counterparty
and without trusting the bridge with custody.

Scope is deliberately one-directional. An ASP's lightning *receive* is already
free (0 base / 0 ppm on mainnet); the expensive leg is *send*, with a 20 sat
floor that eats 80% of a 25 sat zap. Only that leg is worth undercutting.

- bridge/server.js: /info, /quote, /swap, /refund over Bun.serve. Validates
  the user's HTLC fully (policy, hash, amount, expiry margin, full vtxo chain)
  before spending anything on Lightning, pays, then claims with the preimage.
  Crash-safe: state is written atomically and every step re-checks reality
  (listpays before paying, so a resumed bridge never double-pays).
- bridge/ln.js: minimal CLN backend (unix socket or docker exec), named
  params, maxfee-capped pay, pending/paid introspection.
- /refund is safe to expose publicly: the ASP only cosigns a preimage-less
  HTLC spend when every output pays the refunder, so it cannot be redirected.

tools/ark/bridge-e2e-test.js drives the real HTTP API against the patched
regtest ASP: a 25 sat zap costs 1 sat, the far-end invoice really settles, the
preimage checks out, resubmission is idempotent, an unroutable invoice reports
refundable rather than done, and the refund lands every sat back.

Co-Authored-By: Claude Fable 5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>Client support for third-party HTLC vtxos (trustless swap bridges)</title>
<updated>2026-07-31T19:05:59Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-07-31T19:05:59Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=142fa01322e624ac12dc24ee7af2583bda89e891'/>
<id>urn:sha1:142fa01322e624ac12dc24ee7af2583bda89e891</id>
<content type='text'>
Speaks the proposed VtxoPolicy::Htlc (type byte 0x08): policy encode/decode,
two-leaf taproot (claimer-with-preimage / refunder-after-expiry), preimage
field on the arkoor cosign request, and GetHtlcPreimage.

ArkManager gains the swap primitives: htlcLock (lock funds claimable only
against a payment hash, refundable by us after expiry), htlcClaim (reveal the
preimage), htlcCosignRefund (hand an unclaimable HTLC back — the server
constrains the outputs to the refunder, so this is safe to expose publicly)
and acceptHtlcRefund.

tools/ark/htlc-bridge-test.js drives a full submarine swap between two
independent wallets against a patched captaind, and asserts the ASP rejects
both a wrong-preimage claim and a preimage-less spend to the bridge itself.

Co-Authored-By: Claude Fable 5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>Fix send-form UX around lightning pays; harden ln state machines</title>
<updated>2026-07-31T15:04:33Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-07-31T15:04:33Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=ad281e832ed9e36b777f03ed54e799df7d70ffc9'/>
<id>urn:sha1:ad281e832ed9e36b777f03ed54e799df7d70ffc9</id>
<content type='text'>
- a rejected cosign (gRPC INVALID_ARGUMENT) returns the input vtxo to
  spendable and fails the action instead of leaving it pending forever —
  the stuck-pending state that pushed small zaps onto Boltz's 25k minimum
- ark ln-pay now takes over when funds are settling (retrying quote) rather
  than falling through to Boltz
- typing a destination clears stale send errors (also cleared on tab
  switch); paste path likewise
- typed lightning addresses no longer auto-advance mid-keystroke (the
  matcher fired at `a@b.co` before `.com`, yanking the form away): the send
  form offers an explicit "Zap &lt;addr&gt;" button; pasted/scanned addresses
  still advance immediately
- ln-recv: HTLC vtxos anchored to a not-yet-confirmed pool round park and
  retry instead of throwing; the requested HTLC expiry is anchored on first
  prepare so retries can't inflate it past the server's grant

Co-Authored-By: Claude Fable 5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
</feed>
