import { useEffect, useState } from 'react' import { gql, useMutation } from '@apollo/client' import { signIn } from 'next-auth/react' import Container from 'react-bootstrap/Container' import Col from 'react-bootstrap/Col' import Row from 'react-bootstrap/Row' import { useRouter } from 'next/router' import AccordianItem from './accordian-item' import BackIcon from '@/svgs/arrow-left-line.svg' import styles from './lightning-auth.module.css' import { callWithTimeout } from '@/lib/time' function ExtensionError ({ message, details }) { return ( <>

error: {message}

{details}
) } function NostrExplainer ({ text }) { return ( <>
  • Alby
    available for: chrome, firefox, and safari
  • Flamingo
    available for: chrome
  • nos2x
    available for: chrome
  • nos2x-fox
    available for: firefox
  • horse
    available for: chrome
    supports hardware signing
} />
) } export function NostrAuth ({ text, callbackUrl }) { const [createAuth, { data, error }] = useMutation(gql` mutation createAuth { createAuth { k1 } }`, { // don't cache this mutation fetchPolicy: 'no-cache' }) const [hasExtension, setHasExtension] = useState(undefined) const [extensionError, setExtensionError] = useState(null) useEffect(() => { createAuth() setHasExtension(!!window.nostr) }, []) const k1 = data?.createAuth.k1 useEffect(() => { if (!k1 || !hasExtension) return console.info('nostr extension detected') let mounted = true; (async function () { try { // have them sign a message with the challenge let event try { event = await callWithTimeout(() => window.nostr.signEvent({ kind: 22242, created_at: Math.floor(Date.now() / 1000), tags: [['challenge', k1]], content: 'Stacker News Authentication' }), 5000) if (!event) throw new Error('extension returned empty event') } catch (e) { if (e.message === 'window.nostr call already executing' || !mounted) return setExtensionError({ message: 'nostr extension failed to sign event', details: e.message }) return } // sign them in try { await signIn('nostr', { event: JSON.stringify(event), callbackUrl }) } catch (e) { throw new Error('authorization failed', e) } } catch (e) { if (!mounted) return console.log('nostr auth error', e) setExtensionError({ message: `${text} failed`, details: e.message }) } })() return () => { mounted = false } }, [k1, hasExtension]) if (error) return
error
return ( <> {hasExtension === false && } {extensionError && } {hasExtension && !extensionError && <>

nostr extension found

authorize event signature in extension
} ) } export default function NostrAuthWithExplainer ({ text, callbackUrl }) { const router = useRouter() return (
router.back()}>

{text || 'Login'} with Nostr

) }