aboutsummaryrefslogtreecommitdiffstats
path: root/src/features
diff options
context:
space:
mode:
Diffstat (limited to 'src/features')
-rw-r--r--src/features/ark.js2
-rw-r--r--src/features/messages.js11
-rw-r--r--src/features/names.js22
3 files changed, 35 insertions, 0 deletions
diff --git a/src/features/ark.js b/src/features/ark.js
index 075cf4b..1b8c591 100644
--- a/src/features/ark.js
+++ b/src/features/ark.js
@@ -4149,6 +4149,8 @@ export function arkFeature(ctx) {
return mgr.lnOutcome(paymentHash, timeoutMs);
},
arkSpendableSat() { const b = arkBalance(); return b ? b.spendableSat : 0; },
+ // everything Spending holds, settled or not
+ arkHeldSat() { const b = arkBalance(); return b ? b.spendableSat + b.pendingSat + b.boardingSat : 0; },
arkReady() { return arkAvailable(); },
// A Lightning invoice for another feature to watch (point of sale):
// the action id is the handle, the poller tells it when it settles.
diff --git a/src/features/messages.js b/src/features/messages.js
index f72d71d..005b20d 100644
--- a/src/features/messages.js
+++ b/src/features/messages.js
@@ -13205,6 +13205,8 @@ export function messagesFeature(ctx) {
if (opts.fieldWhen && opts.fieldWhen[k] && !opts.fieldWhen[k](base)) continue;
merged[k] = v;
}
+ // fields to take out altogether (an address that no longer exists)
+ for (const k of opts.remove || []) if (!opts.fieldWhen || !opts.fieldWhen[k] || opts.fieldWhen[k](base)) delete merged[k];
if (merged.name && !(fill.has('name') && taken('name'))) merged.display_name = merged.name;
if (JSON.stringify(merged) === JSON.stringify(base)) return true; // nothing to say
const partial = { kind: 0, content: JSON.stringify(merged), tags: [], created_at: kind0Stamp(id.pubkey) };
@@ -19089,6 +19091,15 @@ export function messagesFeature(ctx) {
// lud16 and nip05 — but only where they pointed at the released address
// (or were empty). Deliberately different values are not ours to touch.
addressRenamed(oldAddr, newAddr) { return repointAddress(oldAddr, newAddr).catch(() => {}); },
+ // the address was given up with nothing in its place (account deleted):
+ // a profile still naming it would send zaps to nobody
+ addressGone(oldAddr) {
+ const is = (k) => (base) => base[k] === oldAddr;
+ return publishProfileFields({}, {
+ onlyWhen: (base) => is('lud16')(base) || is('nip05')(base),
+ remove: ['lud16', 'nip05'], fieldWhen: { lud16: is('lud16'), nip05: is('nip05') },
+ }).catch(() => {});
+ },
// older copies of our kind 0 on history-keeping relays, and filling the
// open editor's empty fields from one (tests)
profileHistory() { return findProfileHistory(); },
diff --git a/src/features/names.js b/src/features/names.js
index e07e025..3f23a0c 100644
--- a/src/features/names.js
+++ b/src/features/names.js
@@ -132,6 +132,27 @@ export function namesFeature(ctx) {
return j;
}
+ // Delete the account at the registrar: every name this wallet's key owns
+ // or manages is freed and what the server filed under them goes with it
+ // (coinosv3-server names/forget.js). `check` only asks what stands in the
+ // way: sats still on their way here, or held in a withdraw link.
+ async function accountDelete(check) {
+ const url = `${REGISTRAR}/account/delete`;
+ const body = JSON.stringify(check ? { check: true } : {});
+ const auth = await withTimeout(nip98Header(walletSigner(), url, 'POST', body), 12000, 'signing');
+ const r = await withTimeout(fetch(url, { method: 'POST', headers: { 'content-type': 'application/json', authorization: auth }, body }), 30000, 'registrar');
+ const j = await r.json().catch(() => ({}));
+ if (j.error === 'funds') return { blocked: true, ...j };
+ if (!r.ok || j.error) throw new Error(j.error || `registrar refused (${r.status})`);
+ if (!check) {
+ // a profile still pointing at a freed address would pay nobody (or its next owner)
+ for (const key of j.names || [])
+ await Promise.race([Promise.resolve(hook('addressGone', key)).catch(() => {}), new Promise((res) => setTimeout(res, 8000))]);
+ wallet.saveFeatureState('names', {});
+ }
+ return j;
+ }
+
async function release() {
const st = load();
if (!st.name) return;
@@ -1056,6 +1077,7 @@ export function namesFeature(ctx) {
return null;
},
settingsCards() { return namesCards(); },
+ accountDelete(check) { return wallet.watchOnly || !wallet.nostrSign ? null : accountDelete(check); },
posSettingsCards() { return posSettingsCardsForName(); },
// the Ark server changed: the name's ark= instruction must follow
namesRefresh() { refresh().catch(() => {}); return true; },