diff options
| author | Adam Soltys <[email protected]> | 2026-09-27 15:07:31 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2026-09-27 15:07:31 -0700 |
| commit | 10b7a97a3ecfc2f8e084c81520c78942ac745ec5 (patch) | |
| tree | a8778b6d22a6bb6d4f750bcb221b455c187b0731 /src/features | |
| parent | 31fea2d1e463424387828163bda9facc2fee8c0d (diff) | |
| download | coinosv3-10b7a97a3ecfc2f8e084c81520c78942ac745ec5.tar.gz coinosv3-10b7a97a3ecfc2f8e084c81520c78942ac745ec5.zip | |
Sending to a coinos.io name shows the person, not the ark address it became.
The recipient box keeps the name, with their face beside it and "Sent
instantly, no fee."; the review names them too. The ark1… the name resolved
to is plumbing, and read as gibberish to anyone new to this.
Co-Authored-By: Claude Fable 5.1 <[email protected]>
Claude-Session: https://claude.ai/code/session_01VhUKyXKtsJ67QAFfb7QR9D
Diffstat (limited to 'src/features')
| -rw-r--r-- | src/features/ark.js | 7 | ||||
| -rw-r--r-- | src/features/messages.js | 1 | ||||
| -rw-r--r-- | src/features/names.js | 13 |
3 files changed, 16 insertions, 5 deletions
diff --git a/src/features/ark.js b/src/features/ark.js index 2a47ef5..eae6b75 100644 --- a/src/features/ark.js +++ b/src/features/ark.js @@ -766,7 +766,9 @@ export function arkFeature(ctx) { { class: 'card col', style: 'gap:12px' }, h('h3', {}, t('arkSendTitle')), row(t('lnPayAmount'), fmtAmount(a.amountSat) + ' ' + unitLabel()), - row(t('arkPayTo'), shortAddr(a.address, 14)), + row(t('arkPayTo'), a.via + ? h('span', { class: 'row gap6', style: 'align-items:center' }, a.via.pk ? ctx.hook('avatarNode', a.via.pk) : null, a.via.name) + : shortAddr(a.address, 14)), row(t('networkFee'), t('arkNoFee')), ui.sendError ? h('div', { class: 'notice err' }, ui.sendError) : null, // An amount Spending can't cover isn't a dead end while Savings can: @@ -3446,7 +3448,8 @@ export function arkFeature(ctx) { // spend a different balance than the one selected. ui.sendError = t('arkPayFromSpending'); } else { - ui.arkSend = { address: dest, amountSat: sats }; + const via = s.recipients[0].via && s.recipients[0].via.ark === dest ? s.recipients[0].via : null; + ui.arkSend = { address: dest, amountSat: sats, via }; } render(); })(); diff --git a/src/features/messages.js b/src/features/messages.js index a55e735..cd0631a 100644 --- a/src/features/messages.js +++ b/src/features/messages.js @@ -8504,6 +8504,7 @@ export function messagesFeature(ctx) { // nobody yet — an established nostr user keeps their own list. identitySignedInNew() { setTimeout(() => seedNewIdentity({ onlyIfNoFollows: true }), 0); return true; }, openProfile(pk) { openProfile(pk); return true; }, + avatarNode(pk, cls) { return avatar(pk, cls || 'chat-avatar mini', false); }, init() { const session = ++feedWarmSession; // this wallet's cached faces, from its own namespace — the keys are diff --git a/src/features/names.js b/src/features/names.js index f6afc95..a34334f 100644 --- a/src/features/names.js +++ b/src/features/names.js @@ -322,14 +322,15 @@ export function namesFeature(ctx) { // mirrors, so ask it directly instead of dead-ending in the Lightning // fallback — which for staging names points at a webroot that serves HTML. const OUR_DOMAINS = ['coinos.io', 'staging.coinos.io', 'halwallet.app']; - async function registrarUri(name, domain) { + async function registrarLookup(name, domain) { try { const r = await withTimeout( fetch(`${REGISTRAR}/name/${encodeURIComponent(name)}?domain=${encodeURIComponent(domain)}`).then((x) => x.json()), 8000, 'registrar'); - return r && r.taken && r.uri ? r.uri : null; + return r && r.taken ? { uri: r.uri || null, pubkey: /^[0-9a-f]{64}$/.test(r.pubkey || '') ? r.pubkey : null } : null; } catch { return null; } } + const registrarUri = (name, domain) => registrarLookup(name, domain).then((r) => (r && r.uri) || null); function beginResolve(text) { const parsed = parsePaymentName(text); @@ -338,9 +339,14 @@ export function namesFeature(ctx) { render(); (async () => { let uri = null, resolveErr = null; + // our registrar also knows WHO owns the name: the send form shows the + // person (face + name) rather than the ark address the name resolves + // to, which reads as gibberish to anyone new to this + const ownerP = OUR_DOMAINS.includes(parsed.domain) ? registrarLookup(parsed.name, parsed.domain) : Promise.resolve(null); try { uri = await resolveBip353(parsed.name, parsed.domain); } catch (e) { resolveErr = e; } if (ui.nameResolve?.text !== text) return; - if (!uri && OUR_DOMAINS.includes(parsed.domain)) uri = await registrarUri(parsed.name, parsed.domain); + const owner = await ownerP; + if (!uri && owner) uri = owner.uri; if (ui.nameResolve?.text !== text) return; ui.nameResolve = null; if (!uri && resolveErr) { @@ -357,6 +363,7 @@ export function namesFeature(ctx) { // whose review would only send it back there. if (await Promise.resolve(hook('arkBoardIfOwn', ark)).catch(() => false)) return; ui.send.recipients[0].address = ark; + ui.send.recipients[0].via = { name: `${parsed.name}@${parsed.domain}`, ark, pk: (owner && owner.pubkey) || null }; render(); return; } |
