<feed xmlns='http://www.w3.org/2005/Atom'>
<title>coinosv3.git/src/features/gifts.js, branch master</title>
<subtitle>coinos v3 — bitcoin, Ark, Lightning and nostr wallet (web + Android)</subtitle>
<id>https://git.coinos.io/coinosv3.git/atom?h=master</id>
<link rel='self' href='https://git.coinos.io/coinosv3.git/atom?h=master'/>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/'/>
<updated>2026-10-09T21:51:06Z</updated>
<entry>
<title>Amounts: no plus sign on money coming in either — the word (Received) and the green say it. History rows, transaction details, the "payment received" screens (wallet, Spending, gifts, boards/onboards) and the till's paid bills. The till's tip choices keep theirs: "+$2" there is what a tip adds to the bill.</title>
<updated>2026-10-09T21:51:06Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-10-09T21:51:06Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=dc00cc50befdc2603a15c2de624607010e5e7248'/>
<id>urn:sha1:dc00cc50befdc2603a15c2de624607010e5e7248</id>
<content type='text'>
Co-Authored-By: Claude Opus 5.5 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_01Vps2H27rhbG9ZqseGfMrc3
</content>
</entry>
<entry>
<title>Max fills the amount in the unit the field shows: in fiat that's money floored to the cent (so it never parses back above the maximum), not a BTC figure under a CAD label. One ctx.amountField helper for the ark send/LN Max, the gift Max and fixed-amount zap/BOLT 12 fills</title>
<updated>2026-10-08T23:34:06Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-10-08T23:34:06Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=e35764950b59bde6e36bdfad1ca671eef564a6d1'/>
<id>urn:sha1:e35764950b59bde6e36bdfad1ca671eef564a6d1</id>
<content type='text'>
Co-Authored-By: Claude Opus 5.5 &lt;noreply@anthropic.com&gt;
</content>
</entry>
<entry>
<title>Seed words read down each column; the Google central is a parameter with a door to the previous one.</title>
<updated>2026-09-21T19:16:17Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-09-21T19:16:17Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=8dbbe74b2bf9714370197816928c93fe3a34cbd4'/>
<id>urn:sha1:8dbbe74b2bf9714370197816928c93fe3a34cbd4</id>
<content type='text'>
Word grids flow down a column then the next, with the row count from the
word count — on a phone the first column is 1–6, the way a hand copies a
list. pomegranate.js takes the central as an option (CENTRALS.coinos is
auth.coinos.io, now deployed; the default stays auth.njump.me until its
Google client is live), and the sign-in card grows a "previous server"
line once the default moves, so accounts made under njump keep working.

Co-Authored-By: Claude Fable 5.1 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_01Tmfg8k5f3TbNJS34qiqHAp
</content>
</entry>
<entry>
<title>Gift detail links the coin behind the gift, and the claim once claimed.</title>
<updated>2026-09-16T04:56:18Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-09-16T04:56:18Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=b58e3dc1eb2a578f1cae441d8bba9503bec94567'/>
<id>urn:sha1:b58e3dc1eb2a578f1cae441d8bba9503bec94567</id>
<content type='text'>
An unclaimed on-chain gift has no transaction of its own yet — its
funding transaction is presigned and only broadcast when someone claims.
The coin it's locked against is on-chain from the start, so the detail
page now links that outpoint's transaction on the block explorer, and
the claim transaction once it exists.

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>Fix the on-chain gift front-running vulnerability architecturally: ephemeral-key (v2) gifts.</title>
<updated>2026-09-07T01:43:50Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-09-07T01:43:50Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=2e492ec499264ba84ec8cad30f788eff28556269'/>
<id>urn:sha1:2e492ec499264ba84ec8cad30f788eff28556269</id>
<content type='text'>
The old on-chain gift presigned a SIGHASH_NONE/SINGLE spend of the sender's own coin — a blank cheque whose claimer output isn't committed, so anyone (from the link, or a mempool watcher once a claim broadcast) could redirect the presigned input to their own address via a higher-fee tx. A sweeper bot had been front-running coinos gift links for ~a month; it drained a real 5000-sat gift ("claimed! → empty wallet"). Root-caused via chain + code forensics: theft tx input0 sighash = SINGLE.

New design (v2, lazy ephemeral key): the sender presigns a FULLY COMMITTED (SIGHASH_ALL) funding tx paying the gift to a throwaway key E, and puts E's private key in the link. The claimer broadcasts the funding tx, then a fresh SIGHASH_ALL sweep of E into their own wallet. Both txs commit to every output, so neither is redirectable in the mempool — redirecting needs E's key, which lives only in the link (the intended bearer property: holding the link is the only way to claim). Lazy: the funding tx isn't broadcast until claim, so an unclaimed gift moves no coins and is revoked for free by spending the still-reserved funding coin. Sender pays the funding fee (from change / the swept total); claimer pays the sweep fee (from the gift).

- gifts-wallet.js: _buildGiftPsbt now builds+signs the ephemeral funding tx (coin -&gt; E + change, SIGHASH_ALL); new GIFT_MAGIC_V2 codec (parseLazyGift/_encodeLazyGift: [magic][E priv:32][le32 len][funding tx]); giftClaimTxs returns the {funding, sweep} pair; giftOutpoints/previewGift read E's output; isRetiredGift flags the old v1 (compact + legacy PSBT) links. Fee threaded through _selectGiftCoins/createGift/createGiftAll/createGiftFromSplit.
- gifts.js doClaim: broadcast funding (tolerating "already in mempool" from a co-holder/retry) then sweep; refuse retired v1 links with a clear message; verifyClaimWon now watches E's output.
- i18n: giftChainWarn reworded (safe bearer link funding a fresh on-chain wallet); giftRetired added.

Verified: focused crypto test confirms codec round-trip + both inputs signed SIGHASH_ALL (committed). Full regtest end-to-end: funding + sweep both relayed (child accepted spending an unconfirmed parent), mined, claimer address credited the gift. UI morph smoke passes.

Co-Authored-By: Claude Opus 4.8 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_01MGzU12QrAA4G6BYGzGVdXz
</content>
</entry>
<entry>
<title>Interim safety for on-chain gifts ahead of the crypto redesign. (1) On-chain (Savings) gift creation now shows a hard bearer-risk warning: the presigned input is redirectable, a sweeper bot is actively front-running shared links, so share privately and claim immediately (Spending/ark gifts are unaffected). (2) The false "success" is fixed: a broadcast returning OK was never proof WE won — a higher-fee sweep can evict our claim (the "claimed! → empty wallet" the bot produced). verifyClaimWon now polls the funding coin after broadcast and, if it settles spent by a txid that isn't ours, retracts the celebration and shows the already-taken screen. Full architectural fix (ephemeral-key gifts, non-malleable SIGHASH_ALL claim) is next</title>
<updated>2026-09-07T01:09:16Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-09-07T01:09:16Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=95cf88f1246118eb6a672a5b4b6545331c9ddef4'/>
<id>urn:sha1:95cf88f1246118eb6a672a5b4b6545331c9ddef4</id>
<content type='text'>
Co-Authored-By: Claude Fable 5 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_01MGzU12QrAA4G6BYGzGVdXz
</content>
</entry>
<entry>
<title>On-chain gift claims can no longer strand funds at an address the claimer's backed-up seed doesn't control. A claim into a fresh wallet reportedly paid a DIFFERENT wallet's address than the seed shown for backup (5000-sat gift claimed in incognito → funds landed at an accumulator address the given seed couldn't derive), because the destination was wallet.receive[0] — which can be a stale address a previous account in the session left behind. Now the claim derives THIS wallet's own address fresh from the active seed (never receive[0]), and a hard guard refuses to broadcast unless that address is provably derivable from the wallet whose recovery phrase is about to be handed over — any future seed/wallet divergence becomes a safe error, not lost money</title>
<updated>2026-09-07T00:03:09Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-09-07T00:03:09Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=dcfabe9165e7b0f48d9d3f645f762b84e6bc48b8'/>
<id>urn:sha1:dcfabe9165e7b0f48d9d3f645f762b84e6bc48b8</id>
<content type='text'>
Co-Authored-By: Claude Fable 5 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_01MGzU12QrAA4G6BYGzGVdXz
</content>
</entry>
<entry>
<title>History becomes home: the tab bar slims to Receive | Send (tapping the lit one puts it away), every landing — login, account creation, an account snapped into the carousel — is the account's own timeline, and that timeline is now SCOPED: Savings shows the on-chain ledger and gift reservations, Spending shows the ark side. The carousel meanwhile learns mouse and mind-reading: desktop gets a real grab-and-pull drag (snap lifted mid-drag, restored on the glide), the peeking neighbor switches on a single click, and the strip wears grab cursors. And a thread's avatars and author names finally go somewhere: profiles stack on top of the conversation and back returns to it</title>
<updated>2026-09-03T02:57:57Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-09-03T02:57:46Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=52b411947bd6c61cf50c60a27249abeedc26c102'/>
<id>urn:sha1:52b411947bd6c61cf50c60a27249abeedc26c102</id>
<content type='text'>
Co-Authored-By: Claude Fable 5 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_01MrkLsNScXe9b6BviUSdmMr
</content>
</entry>
<entry>
<title>The phone's Back button closes a payment's details instead of teleporting to the last tab: the ark move/exit and gift detail views join NAV_FIELDS (an on-chain txDetail always had an entry; the ark rows — most Spending payments — minted none, so Back skipped the history list entirely), and their in-app Back buttons pop that entry rather than pushing another</title>
<updated>2026-08-31T05:32:45Z</updated>
<author>
<name>Adam Soltys</name>
<email>adam@coinos.io</email>
</author>
<published>2026-08-31T05:32:45Z</published>
<link rel='alternate' type='text/html' href='https://git.coinos.io/coinosv3.git/commit/?id=bfe6ee7f93d294e430718a91c96aef815ee6935a'/>
<id>urn:sha1:bfe6ee7f93d294e430718a91c96aef815ee6935a</id>
<content type='text'>
Co-Authored-By: Claude Fable 5 &lt;noreply@anthropic.com&gt;
Claude-Session: https://claude.ai/code/session_01MrkLsNScXe9b6BviUSdmMr
</content>
</entry>
</feed>
