blob: 284c595d815f9153b9a711e61de2730320cf4acd (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
|
import { warn } from "$lib/logging";
import { fail } from "$lib/utils";
// The v3 registrar (coinos v3 / halwallet) owns any name it has a record for:
// routes/lnurl.ts serves a claimed name's lightning address from the registrar
// ahead of the local account. So a local account taking a name the registrar
// holds silently hands its incoming payments to whoever holds the v3 name.
// Both places that assign a username — registration and the profile rename —
// must therefore refuse a name the registrar holds, unless the account's own
// nostr key is the holder (a user re-creating their migrated name is fine).
const NAMES_URL = process.env.NAMES_URL || "https://names.coinos.io";
const DOMAIN = "coinos.io";
// Fail CLOSED: if the registrar can't be reached we don't know who owns the
// name, and handing out a squatted name is worse than a retry.
export const assertNameFree = async (username: string, ownPubkey?: string) => {
const name = username.toLowerCase();
let body: any;
try {
const r = await fetch(
`${NAMES_URL}/name/${encodeURIComponent(name)}?domain=${DOMAIN}`,
{ signal: AbortSignal.timeout(3000) },
);
if (!r.ok) throw new Error(`registrar said ${r.status}`);
body = await r.json();
} catch (e: any) {
warn("names registrar unreachable checking", name, e?.message);
fail("Username unavailable right now, please try again");
}
// `pubkey` is only present for a real v3 record. `taken` without one means
// the registrar is echoing our own account list back at us — not a claim.
const holder = body?.taken && typeof body.pubkey === "string" ? body.pubkey : null;
if (holder && holder !== ownPubkey) {
warn("username held by v3 registrar", name, holder.slice(0, 8));
fail(`Username ${name} taken`);
}
};
|