| Commit message (Collapse) | Author | Age | Files | Lines |
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
Gifts are plain bearer links again: the recipient-npub field, the
one-time claim code, the DM delivery, the /lg/ claim route and the
NIP-07 in-place decrypt are all gone, along with the crypto that only
they used. Unclaimed gifts remain reclaimable by the sender, so nothing
can be stranded by the removal.
The unlock screen shows a single 'Sign in with Nostr' button that
reveals the login options when tapped, instead of the full card
competing with create/import.
Co-Authored-By: Claude Fable 5 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The passive setup path asked the browser extension to sign the claim,
so it sat behind a permission popup — 20s per attempt, retried, hence
the minute-long spinner ending in the manual form. The wallet's own key
now makes that claim: no signer, no prompt, no wait. Tying the address
to the user's real npub happens at login instead, where the signer is
already live, and nominates the wallet key to manage the record after.
Failures are visible now rather than hidden: the pane shows why setup
failed, the watchdog is 12s instead of 60s, internal timeouts are
tighter, and the registrar logs every refusal with its reason.
Co-Authored-By: Claude Fable 5 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
| |
The auto-claim ran once at feature init — before Ark finishes
connecting — saw an unavailable wallet and gave up for good, so users
got a claim box instead of their npub address. It now retries while Ark
comes up (and after a failed claim), and shows a setting-up state
rather than the claim form while it works.
Co-Authored-By: Claude Fable 5 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Three ways in: a NIP-07 browser extension, a NIP-46 remote signer
(Amber, Amethyst — paste its bunker:// address), or a pasted
nsec/hex key that lives in memory for the session and is never stored.
How an account gets a wallet depends on what we can see, and the two
cases are genuinely different:
* We hold the key (pasted nsec): the seed is DERIVED from it —
sha256("coinos:wallet-seed:v1" | privkey) as BIP-39 entropy. The
same Nostr key always opens the same wallet, on any device, with
nothing stored anywhere.
* We only have a signer: deriving is impossible (we never see the
key, and neither signatures nor NIP-44 ciphertexts reproduce), so
the seed is ASSOCIATED instead — generated once and published as a
replaceable event encrypted to the user's own key, which only their
signer can decrypt. Later logins find and decrypt it.
The second path means the Nostr key can recover the money; the UI says
so before publishing anything. Linking an already-open wallet uses the
same publish path and refuses to overwrite an account's existing wallet.
Co-Authored-By: Claude Fable 5 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
Every wallet silently claims the first 20 characters of its npub as its
payment address the first time it opens: unique, free, and nothing to
decide. The pick-a-username gate is gone (the generic onboardingView
hook stays as an extension point). A custom name is an optional change
tucked into the payment-address card — and swapping to one releases the
old name so the registrar and DNS stay tidy. Custom names may become
paid later to deter squatting; the default tier keeps working
regardless.
Co-Authored-By: Claude Fable 5 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
New wallets must pick a username before entering the wallet: the
onboarding gate renders a claim screen until a name exists. Imported
seeds skip it — the registrar's new /pubkey lookup recovers the name
owned by the wallet's key, so nothing is retyped. If claiming errors
(registrar or ark unreachable) a do-it-later escape appears rather than
locking anyone away from funds; the prompt returns next open.
The Receive tab now defaults to the payment address — name QR + copy —
with the on-chain address and other modes behind it, and the claim form
inline for wallets that skipped onboarding.
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]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The wallet is the next version of coinos, deployed at v3.coinos.io
(same build as halwallet.app) ahead of an eventual migration of
coinos.io itself. App name, manifest, notifications, and the NWC alias
all say Coinos; the Hal Finney tribute stays.
The registrar is multi-domain (per-domain Cloudflare zones; existing
halwallet.app names keep working) and new claims default to @coinos.io.
Names belonging to existing coinos users are reserved for them — the
registrar checks the live coinos API before granting a claim — until
the migration gives those users a way to claim their own.
Co-Authored-By: Claude Fable 5 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
CLINK offers (noffer): every wallet gets a static offer keypair (synced
across devices, first-minted wins) answering kind-21001 invoice
requests — from open tabs and from the service worker while closed,
which mints against the mirrored state (the record now carries chain-4
and chain-5 key windows) and raises an open-to-receive notification.
Zap requests ride along and their kind-9735 receipts publish once the
payment is claimed. The code is shown in the payment-address card for
pasting into a Nostr profile; the notifier watches and relays kind
21001 alongside NWC.
Payment names also gain a Lightning offer: the registrar creates a
BOLT 12 offer per name on the node and appends lno= to the DNS record;
a settle-forwarder pushes each received payment on to the name's ark
destination from a small float wallet (custody window: seconds between
Lightning settle and the ark send).
Name resolution now runs full client-side DNSSEC validation
(src/dnssec.js): binary DoH, root-anchor chain walk, RSA + ECDSA via
WebCrypto — the resolver is untrusted transport, verified against live
signed zones including the canonical BIP-353 test name.
Co-Authored-By: Claude Fable 5 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Receiving: a Settings card claims a username, signed with the wallet's
nostr key; the new names registrar (names/server.js, deployed at
names.halwallet.app) enforces first-come ownership by that key and
mirrors the claim into a DNSSEC-signed TXT record at
<name>.user._bitcoin-payment.halwallet.app whose BIP-21 URI carries the
wallet's reusable ark address. The record re-registers itself if the
ark address ever changes, and a collapsible hint shows the single CNAME
a user adds to serve the same name from their own domain (BIP-353
supports delegation when both zones are DNSSEC-signed).
Sending: a pasted name@domain resolves over DNS first — two independent
DoH resolvers must agree and both report the DNSSEC AD flag (full
client-side chain validation is the stated follow-up) — an ark=
instruction pays natively, an on-chain path fills the send form, and a
name with no DNS record falls back to the Lightning-address zap flow.
Co-Authored-By: Claude Fable 5 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Dropped: silent payments (feature, wallet chains, scan worker, indexer
config), Boltz submarine/reverse swaps (feature + swap.js + tools), the
third-party ark swap bridge (config, client flows, settings card — the
ASP's own Lightning send is the one path now), and the Consolidate
coins settings action.
The NWC pouch is gone with them: background answering now spends the
WHOLE ark balance. The IndexedDB record mirrors the real manager state
plus the chain-3 keys for its live coins and a change-index window; the
worker pays through the ASP exactly like the open app, and the app
folds the worker's spends, change, and key allocations back in on
connect (additive merge + reconcile against the server). A leftover
chain-6 pouch from the short-lived pouch era is swept home
automatically using the keys stored in its own record. The stated
tradeoff: same-origin script access now reaches the ark balance, not a
carve-out — the ark balance is walking-around money, the on-chain
wallet's keys are never mirrored, and per-connection NWC budgets remain
the enforced ceiling.
Bundle: 726KB -> 602KB.
Co-Authored-By: Claude Fable 5 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The no-tap half of background wallet-connect. The push payload carries
the (encrypted, client-signed) request event; a bundled service-worker
responder (src/sw-nwc.js -> nwc-respond.js) finds the matching pouch in
IndexedDB, decrypts with the connection's service key, and answers
get_info/get_balance/list_transactions from pouch state. pay_invoice
pays through the swap bridge with an ArkManager running over the
pouch's chain-6 key window (one HTLC lock, one HTTP swap), enforcing
per-payment and daily budgets from the pouch's own spend log, checking
the notifier's /answered endpoint so it never double-pays or shouts
over an open device, and persisting the swap before handing it off so
the app can refund a crashed flight. Anything it can't handle falls
back to the wake-the-user notification.
The notifier grows /publish (verified 23195s only, rate-limited) as the
worker's reply pipe and /answered for race avoidance. The app gains
pouch funding (mailbox-less arkoor self-send whose recipient bytes we
keep), emptying, spend/budget reconciliation on open, and refund
recovery with the pouch's own keys.
Co-Authored-By: Claude Fable 5 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Step 3, first half. Android Chrome freezes backgrounded PWAs and closes their
relay sockets, so a phone with hal "open" answers nothing — which is what made
Amethyst spin. Push is the only way to reach a frozen app.
- service worker gains a `push` handler. It deliberately does NOT spend: if a
window is open it nudges it to re-listen, otherwise it raises a notification
that opens hal on tap. Putting a spend path in the worker is the remaining
half and wants its own testing.
- hal-side: request permission, subscribe with the notifier's VAPID key, and
register its service pubkeys with nwcpush.coinos.io. Turning it off
deregisters, unsubscribes, and clears the pouch — no reason to leave
spendable keys where a worker can read them if nothing will.
- a Settings toggle, and the ark feature exposes the ASP context the pouch
record needs.
Co-Authored-By: Claude Fable 5 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Other apps can connect over nostr and pay from this wallet without touching
its keys, within a per-payment and daily budget the user sets, revocable at
any time. hal holds no native Lightning balance, so every operation runs over
Ark: pay_invoice takes the swap bridge when configured and falls back to the
ASP's lightning-send, make_invoice mints on the ASP. NWC availability
therefore tracks Ark availability.
- kinds 13194/23194/23195, nip44_v2 and nip04, replying in whichever scheme
the request used; every request gets a reply so clients never hang
- each connection gets its own service keypair, so revoking one can't affect
the others and none is tied to the user's nostr identity
- budgets are checked BEFORE spending, not reconciled after
- requests are ignored unless signed by that connection's client key, and
replayed/stale events (>120s) can't re-trigger a payment
- Settings card to create, show (URI + QR) and revoke connections, and it
says plainly that this only works while a tab is open
tools/nwc-test.js drives it as a real client: both encryption schemes, budget
refusal with a genuine over-limit invoice, unsupported-method errors, and a
request from an unauthorized key being ignored.
Co-Authored-By: Claude Fable 5 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
- ark presets gain coinos entries (ark.coinos.io on mainnet,
ark-staging.coinos.io on mutinynet) alongside Second's
- new per-network swap-bridge setting (preset/custom URL + access token)
with its own Settings card
When a bridge is configured, a bolt11 quote asks it first and shows its fee;
paying locks an HTLC only the bridge can claim, and only by revealing the
invoice preimage. Any failure — unreachable bridge, refused swap, unpayable
invoice — refunds and falls back to the ASP's own lightning-send, so the
payment never dead-ends. Hanging swaps are refunded on reconnect.
Co-Authored-By: Claude Fable 5 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
- 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 `[email protected]` before `.com`, yanking the form away): the send
form offers an explicit "Zap <addr>" 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 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The ASP is the HTLC counterparty (second.tech's protocol), so no external
swap provider is needed: paying a bolt11 converts pubkey vtxos into
ServerHtlcSend vtxos the server can only claim by revealing the invoice
preimage; receiving grants ServerHtlcRecv vtxos claimed by revealing ours.
Failure paths cosign the HTLC back (revocation) — proven end-to-end against
regtest captaind, which independently derives the HTLC taproots.
- ark/lightning.js: bolt11 decode, lightning fee schedules, all pay/receive
gRPC-web wrappers (cosign, initiate, status, revocation, hold-invoice
receive flow, anti-DoS attestation)
- ark/send.js: arkoor builder generalized to policy outputs (pubkey /
serverHtlcSend / serverHtlcRecv), two-leaf taproot trees, HTLC clause
scripts, reusable per-part cosign helpers for package RPCs
- ark/manager.js: ln-pay and ln-recv crash-safe action state machines
(deterministic receive preimages from the seed, chain 5), mailbox
lightning notifications, unpayable-invoice -> instant revocation
- proto.js: lightning ArkInfo fields + mailbox lightning message decode
- validate/refresh: policy-aware vtxo validation and reconstruction
- features: bolt11 routes via ark when the balance covers it (Boltz stays
the fallback), lightning-invoice receive on the Ark pane
- tools/ark/ln-test.js: harness proving HTLC cosign + revocation against
captaind; manager-test.js updated for the consolidated bc-container chain
Co-Authored-By: Claude Fable 5 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Send a Lightning zap to a nostr npub, a lightning address (name@domain),
or an lnurl. New src/lnurl.js does the resolution half — target → LNURL-pay
params → signed kind-9734 zap request → callback → bolt11 — and the new
zaps feature (src/features/zaps.js) drives the amount/comment UI, then hands
the invoice to the existing Boltz submarine-swap flow via a new
swaps.startLnPay hook, so there's one tested pay/review/confirm/success path.
Routing: a bolt11 is still caught by swaps; an npub still prefers an instant
free Ark zap when Ark can serve it, and only falls through to a Lightning
zap otherwise — ark's "no Ark address" screen also offers an explicit
"Zap over Lightning" fallback (gated on the zaps feature's canLnZap). A real
zap receipt is attributed only when the server advertises allowsNostr and we
know the recipient's pubkey; otherwise it degrades to a plain LNURL-pay.
Nostr seam gains nostrSign (finalize without publishing), nostrProfile
(kind-0 with lud16/lud06), and nostrRelays. Lightning addresses are
debounced in matchSendText since their regex matches mid-typing.
Verified: unit tests for parse/encode/zap-request; a live resolve→signed
9734→payable mainnet bolt11 against coinos; and an in-browser DOM smoke
(zap form + LNURL params over CORS + allowsNostr hint + handoff).
Co-Authored-By: Claude Opus 4.8 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
The cooperative offboard was buried under the receive-tab board form
and the unilateral exit lived in Settings — both unintuitive. Now a
small 'Exit' link next to the Ark balance opens a dedicated page that
explains and offers both: cooperative (server co-signs, fast, no
on-chain funds needed, small server fee) and unilateral (trustless,
timelocked, pays mining fees). In-flight exit progress (hop counter,
timelock countdown, cancel) moved here from Settings; the receive pane
loses the offboard button and Settings loses the exit button.
Co-Authored-By: Claude Fable 5 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
The ⚔ was a U+2694 emoji stand-in. Swap in Second's actual mark
(second.tech logo: a triangle with an evenodd inner cutout) as two
format.js helpers — ARK_ICON (dark rounded-square app badge + white
mark, for card/section headers) and ARK_MARK (bare currentColor glyph,
for the history-row circle). Wired into the Ark settings card, the
boarding/withdrawal/exit history rows + detail section, and the
How-it-works Ark section; the gift source toggle drops the emoji for
plain 'Ark'. Verified the badge renders (18px, #00090C square, white
evenodd mark).
Co-Authored-By: Claude Fable 5 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Lightning zaps are welded to LNURL+bolt11; nutzaps (NIP-61) proved the
alternative shape, and ark fits it better than Cashu because delivery
already exists (the mailbox). Draft protocol, kinds provisional:
kind 10037 (replaceable) announces the wallet's ark address+network;
the zap itself is a plain instant arkoor send; kind 9737 is the
sender-signed receipt tagging recipient, amount, comment, and the
delivered vtxo id — so the receipt is checkable against the actual
payment, unlike a bare attestation.
UX: paste an npub into Send and hal offers the zap (needs both the ark
and sync features; npub decoding is inline bech32 so ark-only builds
stay lean). The nostr layer gains generic publishEvent/fetchEvents,
exposed through the sync seam as wallet.nostrPublish/nostrFetch.
Proven on regtest against a mini NIP-01 relay: announce, resolve,
zap 1,000 sats with a comment, instant receipt+delivery, vtxo match.
Co-Authored-By: Claude Fable 5 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
| |
The in-app page grows plain-language cards for Lightning swaps, Ark
(instant off-chain, the unilateral escape hatch, expiry housekeeping,
fees), silent payments, and gift links. The README catches up with
reality: the native-JS Ark client headlines the feature list, and the
modular HAL_FEATURES build system gets its own section — every feature
is a plugin behind a build seam, and excluded code never ships.
Co-Authored-By: Claude Fable 5 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
| |
submitpackage answers HTTP 200 even when it rejects the package — the
verdict hides in package_msg/tx-results — so a mainnet no-fee-coin exit
sat at 'publishing on-chain…' forever believing its bare hop had
relayed. Rejections now surface (and become the actionable needs-a-fee-
coin message on the bumpless path). The status line shows hop progress
(step 2 of 9), the timelock wait counts down in blocks with a rough
wall-clock estimate, and a stuck exit that never published anything
gets a 'Cancel this exit' link that returns the vtxo to spendable.
Co-Authored-By: Claude Fable 5 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
| |
100,000 in, 99,670 out was a surprise: the ASP's board fee (min/base/
ppm from its published schedule; it funds the exit tx's P2A fee anchor)
was only visible after the fact. The board form now shows the fee and
the net amount live as you type, and the funding tx's detail view gets
an 'Ark server fee' line.
Co-Authored-By: Claude Fable 5 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
| |
submitPackage falls back to sequential /tx posts when the esplora lacks
POST /txs/package (regtest electrs) — works wherever the node relays
zero-fee v3 parents. The ark card stops speaking developer: in-flight
operations summarize as '{n} deposit(s) confirming' instead of
'board:funded, exit:chain, …', exit lines read 'Exiting N sats —
publishing on-chain…', and transient errors show 'hit a snag — retrying
automatically' instead of raw gRPC/HTTP text.
Co-Authored-By: Claude Fable 5 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
The trustless backstop behind the Ark card's promise. The vtxo's
genesis chain reconstructs to fully-signed txs (keyspend sigs for
cosigned/arkoor transitions, preimage script-path for hark leaves);
they are zero-fee v3 with P2A anchors, so each hop broadcasts as a
[parent, CPFP child] package via esplora POST /txs/package, one
confirmed hop at a time (TRUC allows a single unconfirmed parent).
After the vtxo tx confirms and the CSV exit delta passes, the claim
spends the delayed_sign leaf with only the user key into the wallet's
own receive address.
Settings gains 'Exit on-chain without the server' with live per-exit
status lines; the claim tx is labeled 'Ark exit' in History. Probing
uses /tx/:txid (definitive 404), never /tx/:txid/status, which answers
confirmed:false for unknown txids.
Also: a fresh visitor opening an ark gift link now adopts the gift's
network automatically instead of being sent to Settings.
Co-Authored-By: Claude Fable 5 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Ark can't presign a bearer spend, so an ark gift is a vtxo sent to an
ephemeral ark identity whose seed IS the link (/ag/<code>: net, amount,
32-byte secret). The claimer rebuilds the identity, reads its mailbox,
and sweeps to their own ark address — instant, free, and it works for a
brand-new empty wallet with zero on-chain footprint. The sender keeps
the secret, which is what makes revoke possible (first cosign wins).
The gift form gains an On-chain/Ark source toggle when ark balance
exists; ark gifts skip the lock/split logic entirely. Claim, choose-
wallet, already-claimed, and nostr-locked (/lg/) flows all branch by
code kind; unclaimed ark gifts list with one-tap revoke and lazily
mark themselves claimed via GetVtxoStatus. Features stay decoupled:
gifts asks for ark support via the new ctx.hook seam, so either
feature builds alone.
Also restores goHome in the feature ctx — lost in the plugin-seam
extraction, it made the already-claimed screen throw on render.
Co-Authored-By: Claude Fable 5 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
PrepareOffboard/FinishOffboard against captaind — per-input ownership
attestations, connector-based musig forfeits (with the deterministic
fanout tx when there is more than one input), and fee math that mirrors
the server bit-for-bit (weight fee rounds up, ppm-by-expiry rounds
down) since it rejects any other net amount. The receive pane gains a
'Move back on-chain' button that withdraws everything to the wallet's
own fresh address; the incoming tx is labeled 'Ark withdrawal' in
History and the ark side records the movement. Crash-safe: the txid
persists before FinishOffboard and resume asks GetVtxoStatus whether
the forfeits landed (the server broadcasts the tx itself).
Also fixes boarding to applySentTx after broadcasting the funding tx —
without it the spent coin lingered in the utxo set (a second board
double-spent it), and the post-board scan() could resurrect it by
racing the explorer's indexing.
Co-Authored-By: Claude Fable 5 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
| |
The board's on-chain send showed as a generic 'Sent' and the sats
vanished from the balance until the vtxo registered. The funding tx now
reads 'Ark board' in History (with a detail section showing the net
credit), and an 'Ark (boarding…)' line carries the pending amount from
broadcast until the board completes.
Co-Authored-By: Claude Fable 5 <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Gift links now sort into the send/receive timeline like any entry: a
clickable row (🎁, status tag, age, amount) opening a detail page that
carries the date/status plus the actions that used to crowd the list
row (view gift link, cancel/reclaim with the existing confirm flow).
A claimed gift merges into its claim transaction's row — labeled as the
gift, clickable to the tx detail, which gains a "This transaction
delivered your gift" section (claim txid resolved via outspend and
cached on the gift record). The old pinned gifts header and the
paginated all-gifts view are gone.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01QFAcD4V284DvYZZHP7Rxxy
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
| |
Claiming a gift whose funding tx is unknown to the claimer's data
source (different network/chain, or not yet propagated) used to fail
with the misleading "already been claimed". Now:
- the claim screen probes the funding tx up front (esplora's status/
outspend endpoints don't 404 for unknown txids, so outspend alone
can't detect this) and shows a network/data-source notice, and
- a missing-inputs broadcast rejection maps to the same explanation
instead of the generic already-claimed message.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01QFAcD4V284DvYZZHP7Rxxy
|
| |
|
|
|
|
|
|
|
| |
"Claim it into a brand-new wallet that only you control." only fits the
new-wallet path; claiming into an existing wallet now says which wallet
it lands in ("Claim it into your wallet "Wallet 1".").
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01QFAcD4V284DvYZZHP7Rxxy
|
| |
|
|
|
|
|
|
|
|
|
|
| |
The existing-wallet buttons looked like inert inputs. Now: a "Receive
into one of your wallets:" label, a chevron on each wallet row so it
reads as tappable, and an "or" divider before the new-wallet button.
(tools/ark/gift-shot.js: screenshot harness that mints a real regtest
gift and opens its link.)
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01QFAcD4V284DvYZZHP7Rxxy
|
| |
|
|
|
|
|
|
|
|
|
| |
Ark movements are clickable like on-chain txs. The detail view shows
amount, date, status, the destination address (sends, copyable), the
vtxo id, and for boards the funding txid with copy + explorer link.
Movements now record those fields at completion time; older records
without them still render (amount/date/status only).
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01QFAcD4V284DvYZZHP7Rxxy
|
| |
|
|
|
|
|
|
|
| |
An arkoor send has no mining fee and no coin selection, so pasting an
Ark address now shows just the amount field plus a hint line; the
irrelevant on-chain controls stay hidden.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01QFAcD4V284DvYZZHP7Rxxy
|
| |
|
|
|
|
|
|
|
|
| |
Broadcasting a board now lands on a checkmark screen showing the amount
that will arrive (after the board fee), a note about the confirmation,
and the funding txid with copy + explorer link; Done returns to the
Receive tab.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01QFAcD4V284DvYZZHP7Rxxy
|
| |
|
|
|
|
|
|
|
|
|
| |
Selecting Ark on Receive now shows the address plus an inline "move
on-chain funds into Ark" form (with available balance / minimum hints).
The Settings card slims down to server choice, coin count, in-progress
operations, and refresh/consolidate; the balance already shows on the
balance card.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01QFAcD4V284DvYZZHP7Rxxy
|
| |
|
|
|
|
|
|
|
|
|
| |
Opening a wallet no longer contacts the ASP unless it already holds
vtxos / history / unfinished operations. Fresh wallets connect on first
use instead: selecting Ark on the Receive tab, confirming an Ark send,
or the Connect button on the Settings card. connectArk() is idempotent
and generation-guarded against wallet switches mid-dial.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01QFAcD4V284DvYZZHP7Rxxy
|
| |
|
|
|
|
|
|
|
|
| |
Mainnet defaults to Second (ark.second.tech), regtest to the local
stack. Testnet/mutinynet get their own preset lists (off/custom only —
no public ASP exists there) instead of falling back to mainnet's, and
stay off by default.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01QFAcD4V284DvYZZHP7Rxxy
|
| |
|
|
|
|
|
|
| |
History is the home for Ark movements now; the Settings card keeps
balance, coin count, board, refresh, and in-progress operations.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01QFAcD4V284DvYZZHP7Rxxy
|
| |
|
|
|
|
|
|
|
| |
Receives, sends, and boards interleave with on-chain transactions in one
time-sorted, paginated timeline, each tagged 'Ark'. Refreshes are
internal churn and stay in the Settings activity list only.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01QFAcD4V284DvYZZHP7Rxxy
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
- Settings: Ark server card (off by default, per-network presets incl.
Second mainnet + local regtest, custom URLs) with balance, coin count,
board form (on-chain -> Ark; funding output pinned to vout 0 via the
new buildTx noSort option), refresh/consolidate, and recent activity.
- Receive: Ark option in the address-type dropdown (QR + copy).
- Send: t?ark1 addresses are recognized in the normal send form and
route to an Ark confirmation (no mining fee) with a success view.
- Balance card: Ark balance line under the on-chain figure.
- ArkManager lifecycle: per-wallet instance created on account
activation, background sync every 5s (regtest) / 30s, state persisted
under the wallet cache key.
Verified end-to-end in a real browser (tools/ark/ui-test.js, puppeteer
against the regtest stack): receive, send, board, and refresh all green.
Co-Authored-By: Claude Fable 5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01QFAcD4V284DvYZZHP7Rxxy
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
- Send: show only the destination input ('Address or Lightning invoice') until a
valid on-chain/SP address is entered, then reveal amount + fee rate + coin
selection + Review. A pasted bolt11 still auto-advances to its own confirmation,
so those controls never appear for it. New wallet.isOnchainAddress() validator +
a destReady() gate; recipient onInput/paste re-render only when validity flips.
- History: stop listing swaps at the top. Instead, a send/receive that was part of
a swap shows its Lightning context (invoice, swap fee, status, refund) on the tx
detail screen via swaps.findByTxid(). Removed the dead swapListView.
- Lightning receive: drop the '50000' amount placeholder — a bare number looked
like a value was already entered; the min/max hint below covers it.
Verified in-browser: controls hidden until a valid address, then revealed; LN
receive placeholder empty; no errors.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
|
| |
|
|
| |
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
|
| |
|
|
|
|
|
|
| |
The 'Receive over' label was redundant above a self-explanatory dropdown; remove
it (and the now-unused i18n key). Rename the first option to 'Bitcoin address' so
it's clear alongside Lightning and Silent payment.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
|
| |
|
|
|
|
|
|
|
| |
The fee label and status copy shouldn't hardcode the provider, since the swap
backend is configurable. 'Boltz fee' → 'Swap fee', and the pay/settle messages no
longer name Boltz. (The settings card still says 'Boltz-compatible provider',
which is an accurate description of the API standard.)
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
- Receive: replace the 3-button segmented control (too wide on mobile) with a
compact 'Receive over' dropdown that scales to more address types.
- Remove the standalone Swap tab. Paying an invoice now lives in Send; the
in-flight/recent swap list folds into the top of History. Deleted the dead
swapTab + doSubmarine.
- Send: as soon as a valid bolt11 is pasted/typed/scanned into the recipient
field, jump straight to the Lightning confirmation (submarine-swap quote with
itemized cost) — the invoice's baked-in amount is used, so the amount field is
skipped entirely. Wired into the recipient onInput, the paste button, and QR scan.
Verified in-browser: Swap tab gone, dropdown renders, and a pasted 60k invoice
auto-progresses to 'Pay over Lightning' with the Boltz fee shown, no Review tap.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Paste a bolt11 into the normal Send recipient field and Review now detects it and
routes through a Boltz submarine swap — no 'swap' concept surfaced. Split
startSubmarine into quoteSubmarine (POST + build-but-don't-broadcast the funding
tx) and fundQuotedSubmarine, so the review shows an itemized cost before
committing: Amount + Boltz fee + on-chain network fee = Total. Pay funds the
lockup; Boltz pays the invoice once it confirms.
Verified on regtest: a 60,000-sat invoice quotes to Amount 60,000 / Boltz 362 /
network 442 / Total 60,804, with a Pay button.
Lightning-address (LNURL) input + removing the standalone Swap tab are the
remaining pieces.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
| |
Receive now has a segmented [Address | Lightning | Silent payment] toggle.
'Lightning' takes an amount and creates a Boltz reverse-swap bolt11 to share;
when it's paid, Boltz locks up on-chain and the SwapManager claims it into this
wallet automatically (shown live, then 'Received!'). Gated to non-watch-only
wallets (a reverse swap needs our keys). Removed the duplicate 'Receive over
Lightning' card from the Swap tab. Verified in-browser on regtest: real limits
(Min 50,000) load via the proxy and an invoice is created.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
|
| |
|
|
|
|
|
|
|
|
|
|
|
|
|
| |
Opening a gift link when you already have wallet(s) now shows a 'Choose where to
receive it' screen — each known wallet (full accounts this session plus the
durable directory, deduped by xpub) plus 'Receive into a new wallet'. A
first-timer with no wallets goes straight to a fresh wallet as before.
Claiming into an existing wallet activates it non-provisionally and sweeps the
gift to its receive address (watch-only is fine — re-enter the seed to spend),
skipping the new-seed backup step. Both bearer and locked (NIP-17) gifts route
through the same claimGift() entry. Verified in-browser: selection lists the
wallet + new option + amount; claim-into-address mechanic proven on regtest.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
|