156 lines
3.6 KiB
Svelte
156 lines
3.6 KiB
Svelte
<script lang="ts">
|
|
import Button from "./Button.svelte";
|
|
import { BASE_DOMAIN } from "$lib/config";
|
|
import { onMount } from "svelte";
|
|
import { getNpub } from "$lib/cashu.svelte";
|
|
|
|
let username = $state("");
|
|
let existingUsername = $state("");
|
|
let hasExistingUsername = $state(false);
|
|
let registrationStatus = $state("");
|
|
let isRegistering = $state(false);
|
|
let isCheckingUsername = $state(true);
|
|
|
|
onMount(async () => {
|
|
await checkExistingUsername();
|
|
});
|
|
|
|
async function checkExistingUsername() {
|
|
try {
|
|
const userNpub = await getNpub();
|
|
const response = await fetch(
|
|
`/api/check-username?npub=${encodeURIComponent(userNpub)}`
|
|
);
|
|
if (response.ok) {
|
|
const data = await response.json();
|
|
if (data.username) {
|
|
existingUsername = data.username;
|
|
hasExistingUsername = true;
|
|
}
|
|
}
|
|
} catch (err) {
|
|
console.error("Failed to check existing username:", err);
|
|
} finally {
|
|
isCheckingUsername = false;
|
|
}
|
|
}
|
|
|
|
async function registerUsername() {
|
|
if (!username.trim()) {
|
|
registrationStatus = "Please enter a username";
|
|
return;
|
|
}
|
|
|
|
isRegistering = true;
|
|
registrationStatus = "";
|
|
|
|
try {
|
|
const userNpub = await getNpub();
|
|
const response = await fetch(
|
|
`/.well-known/lnurlp/${encodeURIComponent(username)}`,
|
|
{
|
|
method: "POST",
|
|
headers: {
|
|
"Content-Type": "application/json",
|
|
},
|
|
body: JSON.stringify({
|
|
npub: userNpub,
|
|
}),
|
|
}
|
|
);
|
|
|
|
if (response.ok) {
|
|
registrationStatus = "Username registered successfully!";
|
|
existingUsername = username;
|
|
hasExistingUsername = true;
|
|
username = "";
|
|
} else {
|
|
const errorText = await response.text();
|
|
registrationStatus = `Registration failed: ${errorText}`;
|
|
}
|
|
} catch (err) {
|
|
registrationStatus = `Registration failed: ${err instanceof Error ? err.message : "Unknown error"}`;
|
|
} finally {
|
|
isRegistering = false;
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<div class="retro-card">
|
|
<h2>Lightning Address</h2>
|
|
|
|
{#if isCheckingUsername}
|
|
<p>Checking for existing username...</p>
|
|
{:else if hasExistingUsername}
|
|
<p>
|
|
Your Lightning address: <strong>{existingUsername}@{BASE_DOMAIN}</strong>
|
|
</p>
|
|
{:else}
|
|
<p>
|
|
Register a username to receive Lightning payments at {username ||
|
|
"yourname"}@{BASE_DOMAIN}
|
|
</p>
|
|
|
|
<div class="form-group">
|
|
<label for="username">Username:</label>
|
|
<input
|
|
id="username"
|
|
type="text"
|
|
value={username}
|
|
oninput={(e) => (username = (e.target as HTMLInputElement).value)}
|
|
placeholder="Enter username"
|
|
class="retro-input"
|
|
disabled={isRegistering}
|
|
/>
|
|
</div>
|
|
|
|
<Button
|
|
variant="primary"
|
|
onclick={registerUsername}
|
|
disabled={isRegistering}
|
|
>
|
|
{isRegistering ? "Registering..." : "Register Username"}
|
|
</Button>
|
|
|
|
{#if registrationStatus}
|
|
<p
|
|
class="status-message"
|
|
class:error={registrationStatus.includes("failed")}
|
|
>
|
|
{registrationStatus}
|
|
</p>
|
|
{/if}
|
|
{/if}
|
|
</div>
|
|
|
|
<style>
|
|
h2 {
|
|
margin: 0 0 1rem 0;
|
|
font-size: 1rem;
|
|
}
|
|
|
|
.form-group {
|
|
margin-bottom: 1rem;
|
|
}
|
|
|
|
label {
|
|
display: block;
|
|
margin-bottom: 0.5rem;
|
|
font-size: 0.8rem;
|
|
}
|
|
|
|
.retro-input {
|
|
width: 100%;
|
|
margin-bottom: 0.5rem;
|
|
}
|
|
|
|
.status-message {
|
|
margin-top: 0.5rem;
|
|
font-size: 0.7rem;
|
|
color: var(--success-color);
|
|
}
|
|
|
|
.status-message.error {
|
|
color: var(--error-color);
|
|
}
|
|
</style>
|