aboutsummaryrefslogtreecommitdiffstats
path: root/src/features
diff options
context:
space:
mode:
authorAdam Soltys <[email protected]>2026-08-30 19:56:05 -0700
committerAdam Soltys <[email protected]>2026-08-30 19:56:05 -0700
commit470a37ca9cddc6ef03e06c873f59c4ffc699de48 (patch)
tree966134532ef9c280ea02eea15b139c3df67134ea /src/features
parent698b6b5431d31a54ddf30c234f95a92bf5c8bf0d (diff)
downloadcoinosv3-470a37ca9cddc6ef03e06c873f59c4ffc699de48.tar.gz
coinosv3-470a37ca9cddc6ef03e06c873f59c4ffc699de48.zip
Pasting your own coinos name (or ark address) opens the boarding panel at paste time, not at review: the names resolver asks the ark feature before filling the send form, a raw address paste runs the same check, and the review path still carries a typed amount into the panel — one boardOwnAddress helper serves all three doors
Co-Authored-By: Claude Fable 5 <[email protected]> Claude-Session: https://claude.ai/code/session_01MrkLsNScXe9b6BviUSdmMr
Diffstat (limited to 'src/features')
-rw-r--r--src/features/ark.js53
-rw-r--r--src/features/names.js4
2 files changed, 42 insertions, 15 deletions
diff --git a/src/features/ark.js b/src/features/ark.js
index 5a97ae1..9cc2222 100644
--- a/src/features/ark.js
+++ b/src/features/ark.js
@@ -2206,6 +2206,30 @@ export function arkFeature(ctx) {
// under the server's 330-sat output minimum) AND a vtxo is inside the
// renewal window: { deadlineMs, sat }. The wallet-screen notice reads this.
let arkRenewWarn = null;
+ // Pasting your OWN ark address — or a coinos name that resolves to it —
+ // is never a payment: it means "top up Spending". Route to the board
+ // panel, funded from on-chain Savings; prefill an amount when the caller
+ // has one (the review path carries the typed amount, paste-time has none
+ // and the panel's own field takes over).
+ async function boardOwnAddress(addr, { connect = false, amountSat = 0 } = {}) {
+ if (!arkAvailable() || wallet.watchOnly) return false;
+ let mgr = ark;
+ if (!mgr) {
+ if (!connect) return false;
+ try { mgr = await connectArk(); } catch { return false; }
+ }
+ try { if (addr !== mgr.address()) return false; } catch { return false; }
+ ctx.goHome();
+ ui.arkMoveOpen = true;
+ ui.arkMoveDir = 'toSpending';
+ ui.arkBoardAmt = amountSat > 0 ? String(amountSat) : '';
+ ui.send = blankSend();
+ ui.sendError = '';
+ toast(t('arkOwnAddrBoard'));
+ render();
+ return true;
+ }
+
async function maybeAutoRefresh(mgr) {
if (wallet.watchOnly || !mgr || !mgr.state) return;
if (Date.now() - arkAutoRefreshAt < 30 * 60_000) return;
@@ -2587,22 +2611,12 @@ export function arkFeature(ctx) {
const fromSavings = ctx.getAccount() !== 'spending';
(async () => {
// Whose address is this? The manager may still be connecting, so
- // resolve async before painting a review.
- let own = false;
- try { const mgr = await connectArk(); own = dest === mgr.address(); }
+ // resolve async before painting a review. Our own address routes
+ // to the board panel with the typed amount riding along.
+ try { await connectArk(); }
catch (e) { ui.sendError = e.message; render(); return; }
- if (own) {
- // Your OWN ark address is never a payment — pasting it (or a
- // coinos name that resolves to it) means "top up Spending", so
- // open the board panel, funded from on-chain Savings. The old
- // path made a silent Spending→Spending self-send.
- ctx.goHome();
- ui.arkMoveOpen = true;
- ui.arkMoveDir = 'toSpending';
- ui.arkBoardAmt = String(sats);
- ui.send = blankSend();
- toast(t('arkOwnAddrBoard'));
- } else if (fromSavings) {
+ if (await boardOwnAddress(dest, { amountSat: sats })) return;
+ if (fromSavings) {
// An ark payment spends the Spending balance — never silently
// spend a different balance than the one selected.
ui.sendError = t('arkPayFromSpending');
@@ -2698,12 +2712,21 @@ export function arkFeature(ctx) {
}
mgr._save();
},
+ // A name that resolved to OUR OWN ark address: the names feature asks
+ // before filling the send form, so the board panel opens at paste time —
+ // nobody should have to type an amount into a payment form just to be
+ // told they were topping themselves up.
+ arkBoardIfOwn(addr) { return boardOwnAddress(addr, { connect: true }); },
// An npub pasted into Send becomes an ark zap (needs the nostr seam from
// the sync feature and a connected-able ark). A bolt11 is handled here
// only in builds without the swaps feature (whose matcher runs first and
// delegates back via the startArkLnPay hook).
matchSendText(text) {
const inv = (text || '').trim().replace(/^lightning:/i, '');
+ // A raw paste of our own ark address means the same thing — start the
+ // check now (the manager may need to connect); if it's ours the board
+ // panel replaces the filled form a beat later.
+ if (isArkAddress(inv) && arkAvailable()) boardOwnAddress(inv, { connect: true }).catch(() => {});
// In a Spending wallet an on-chain address means "exit ark to there":
// the offboard happens right in the send flow, no Move money ceremony.
if (ctx.getAccount() === 'spending' && wallet.isOnchainAddress(inv) && arkAvailable()) {
diff --git a/src/features/names.js b/src/features/names.js
index d8d3dd9..ac54079 100644
--- a/src/features/names.js
+++ b/src/features/names.js
@@ -320,6 +320,10 @@ export function namesFeature(ctx) {
const dec = parseBip21(uri);
const ark = dec?.params?.ark;
if (ark && isArkAddress(ark) && hook('arkReady')) {
+ // Your own name is a top-up, not a payment: the ark feature routes
+ // it straight to the board panel instead of filling a send form
+ // whose review would only send it back there.
+ if (await Promise.resolve(hook('arkBoardIfOwn', ark)).catch(() => false)) return;
ui.send.recipients[0].address = ark;
render();
return;