import "./login-signup.css"; import LoginHeader from "../login-start.jpg"; import LoginHeader2x from "../login-start@2x.jpg"; import LoginVault from "../login-vault.jpg"; import LoginVault2x from "../login-vault@2x.jpg"; import LoginProfile from "../login-profile.jpg"; import LoginProfile2x from "../login-profile@2x.jpg"; import LoginKey from "../login-key.jpg"; import LoginKey2x from "../login-key@2x.jpg"; import LoginWallet from "../login-wallet.jpg"; import LoginWallet2x from "../login-wallet@2x.jpg"; import { CSSProperties, useContext, useState } from "react"; import { FormattedMessage, FormattedNumber, useIntl } from "react-intl"; import { EventPublisher, UserMetadata } from "@snort/system"; import { schnorr } from "@noble/curves/secp256k1"; import { bytesToHex } from "@noble/curves/abstract/utils"; import { LNURL, bech32ToHex, getPublicKey, hexToBech32 } from "@snort/shared"; import { VoidApi } from "@void-cat/api"; import { SnortContext } from "@snort/system-react"; import { Login } from "@/index"; import { Icon } from "./icon"; import Copy from "./copy"; import { openFile } from "@/utils"; import { LoginType } from "@/login"; import { DefaultProvider, StreamProviderInfo } from "@/providers"; import { NostrStreamProvider } from "@/providers/zsz"; import { DefaultButton, Layer1Button } from "./buttons"; enum Stage { Login = 0, LoginInput = 1, Details = 2, LnAddress = 3, SaveKey = 4, } export function LoginSignup({ close }: { close: () => void }) { const system = useContext(SnortContext); const [error, setError] = useState(""); const [stage, setStage] = useState(Stage.Login); const [username, setUsername] = useState(""); const [lnAddress, setLnAddress] = useState(""); const [providerInfo, setProviderInfo] = useState(); const [avatar, setAvatar] = useState(""); const [key, setNewKey] = useState(""); const { formatMessage } = useIntl(); const hasNostrExtension = "nostr" in window && window.nostr; function doLoginNsec() { try { const hexKey = key.startsWith("nsec") ? bech32ToHex(key) : key; Login.loginWithPrivateKey(hexKey); close(); } catch (e) { console.error(e); if (e instanceof Error) { setError(e.message); } else { setError(e as string); } } } async function loginNip7() { try { const nip7 = await EventPublisher.nip7(); if (nip7) { Login.loginWithPubkey(nip7.pubKey, LoginType.Nip7); } } catch (e) { if (e instanceof Error) { setError(e.message); } else { setError(e as string); } } } function createAccount() { const newKey = bytesToHex(schnorr.utils.randomPrivateKey()); setNewKey(newKey); setLnAddress(`${getPublicKey(newKey)}@${window.location.host}`); setStage(Stage.Details); } function loginWithKey() { Login.loginWithPrivateKey(key); close(); } async function uploadAvatar() { const file = await openFile(); if (file) { const VoidCatHost = "https://void.cat"; const api = new VoidApi(VoidCatHost); const uploader = api.getUploader(file); const result = await uploader.upload({ "V-Strip-Metadata": "true", }); if (result.ok) { const resultUrl = result.file?.metadata?.url ?? `${VoidCatHost}/d/${result.file?.id}`; setAvatar(resultUrl); } else { setError(result.errorMessage ?? "Upload failed"); } } } async function setupProfile() { const px = new NostrStreamProvider(DefaultProvider.name, DefaultProvider.url, EventPublisher.privateKey(key)); const info = await px.info(); setProviderInfo(info); setStage(Stage.LnAddress); } async function saveProfile() { try { // validate LN addreess try { const lnurl = new LNURL(lnAddress); await lnurl.load(); } catch { throw new Error( formatMessage({ defaultMessage: "Hmm, your lightning address looks wrong", id: "4l69eO", }) ); } const pub = EventPublisher.privateKey(key); const profile = { name: username, picture: avatar, lud16: lnAddress, } as UserMetadata; const ev = await pub.metadata(profile); console.debug(ev); system.BroadcastEvent(ev); setStage(Stage.SaveKey); } catch (e) { if (e instanceof Error) { setError(e.message); } else { setError(e as string); } } } switch (stage) { case Stage.Login: { return ( <>



{hasNostrExtension && ( <> )} setStage(Stage.LoginInput)}> {error && {error}}
); } case Stage.LoginInput: { return ( <>

), }} />

setNewKey(e.target.value)} placeholder={formatMessage({ defaultMessage: "eg. nsec1xyz", id: "yzKwBQ" })} />
{ setNewKey(""); setStage(Stage.Login); }}>
{error && {error}}
); } case Stage.Details: { return ( <>

setUsername(e.target.value)} />
); } case Stage.LnAddress: { return ( <>

{providerInfo?.balance && (

, }} />

)}
setLnAddress(e.target.value)} />
{error && {error}}
); } case Stage.SaveKey: { return ( <>

); } } }