import { Event, EventTemplate } from 'nostr-tools' import { useCallback } from 'react' import { NostrController } from '../controllers' import { appPrivateRoutes } from '../routes' import { setAuthState, setMetadataEvent, setRelayMapAction } from '../store/actions' import { base64DecodeAuthToken, compareObjects, createAndSaveAuthToken, getAuthToken, getEmptyMetadataEvent, getRelayMapFromNDKRelayList, unixNow } from '../utils' import { useAppDispatch, useAppSelector } from './store' import { useNDKContext } from './useNDKContext' import { useDvm } from './useDvm' export const useAuth = () => { const dispatch = useAppDispatch() const { getRelayInfo } = useDvm() const { findMetadata, getNDKRelayList } = useNDKContext() const authState = useAppSelector((state) => state.auth) const relaysState = useAppSelector((state) => state.relays) const checkSession = useCallback(() => { const savedAuthToken = getAuthToken() if (savedAuthToken) { const signedEvent = base64DecodeAuthToken(savedAuthToken) dispatch( setAuthState({ loggedIn: true, usersPubkey: signedEvent.pubkey }) ) return } dispatch( setAuthState({ loggedIn: false, usersPubkey: undefined }) ) }, [dispatch]) /** * Function will authenticate user by signing an auth event * which is done by calling the sign() function, where appropriate * method will be chosen (extension or keys) * * @param pubkey of the user trying to login * @returns url to redirect if authentication successfull * or error if otherwise */ const authAndGetMetadataAndRelaysMap = useCallback( async (pubkey: string) => { const emptyMetadata = getEmptyMetadataEvent() try { const profile = await findMetadata(pubkey) if (profile && profile.profileEvent) { const event: Event = JSON.parse(profile.profileEvent) dispatch(setMetadataEvent(event)) } else { dispatch(setMetadataEvent(emptyMetadata)) } } catch (err) { console.warn('Error occurred while finding metadata', err) dispatch(setMetadataEvent(emptyMetadata)) } const timestamp = unixNow() const { href } = window.location const authEvent: EventTemplate = { kind: 27235, tags: [ ['u', href], ['method', 'GET'] ], content: '', created_at: timestamp } const nostrController = NostrController.getInstance() const signedAuthEvent = await nostrController.signEvent(authEvent) createAndSaveAuthToken(signedAuthEvent) dispatch( setAuthState({ loggedIn: true, usersPubkey: pubkey }) ) const ndkRelayList = await getNDKRelayList(pubkey) const relays = ndkRelayList.relays if (relays.length < 1) { // Navigate user to relays page if relay map is empty return appPrivateRoutes.relays } getRelayInfo(relays) const relayMap = getRelayMapFromNDKRelayList(ndkRelayList) if (authState.loggedIn && !compareObjects(relaysState?.map, relayMap)) { dispatch(setRelayMapAction(relayMap)) } return appPrivateRoutes.homePage }, [ dispatch, findMetadata, getNDKRelayList, getRelayInfo, authState, relaysState ] ) return { authAndGetMetadataAndRelaysMap, checkSession } }