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 { useContext, useState } from "react" import { FormattedMessage, FormattedNumber, useIntl } from "react-intl" import { EventPublisher, PrivateKeySigner, type UserMetadata } from "@snort/system" import { LNURL, bech32ToHex, getPublicKey, hexToBech32, isHex } from "@snort/shared" import { SnortContext } from "@snort/system-react" import { Login, LoginType } from "@/login" import { Icon } from "./icon" import Copy from "./copy" import { type AccountResponse, NostrStreamProvider, adaptPublisher } from "@/providers" import { DefaultButton, Layer1Button } from "./buttons" import { ExternalLink } from "./external-link" import { FileUploader } from "./file-uploader" import { Link } from "react-router" import { useStreamProvider } from "@/hooks/stream-provider" import { gtag } from "@/gtm" 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 const { config } = useStreamProvider() 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 signer = PrivateKeySigner.random() setNewKey(signer.privateKey) setLnAddress(`${getPublicKey(signer.getPubKey())}@${window.location.host}`) setStage(Stage.Details) } function loginWithKey() { Login.loginWithPrivateKey(key) gtag("event", "conversion", { send_to: "AW-17854661671/Rr6ECM36090bEKeI4sFC", }) close() } async function setupProfile() { const px = new NostrStreamProvider(config.name, config.url, adaptPublisher(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 { if (!lnAddress.includes("localhost") && import.meta.env.DEV) { 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) } } } function imageUploadSection() { const signer = key && key.length === 64 && isHex(key) ? new PrivateKeySigner(key) : undefined if (!signer) return return ( setAvatar(e ?? "")} onError={e => setError(e.toString())} className="absolute flex items-center justify-center w-full h-full hover:opacity-30 opacity-0 transition bg-black cursor-pointer" imageWidth={512} imageHeight={512} > ) } switch (stage) { case Stage.Login: { return ( <>

{!hasNostrExtension && ( Nos2X ), nostore: ( Nostore ), alby: ( Alby ), }} /> )}
setStage(Stage.LoginInput)}> {error && {error}}
) } case Stage.LoginInput: { return ( <>

), }} />

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

{avatar && } {imageUploadSection()}
setUsername(e.target.value)} /> {error && {error}}
) } case Stage.LnAddress: { return ( <>

{providerInfo?.balance && (

, }} />

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

) } } }