import { nip19, verifyEvent } from 'nostr-tools' import { SignedEvent } from '../types' import axios from 'axios' /** * @param hexKey hex private or public key * @returns whether or not is key valid */ const validateHex = (hexKey: string) => { return hexKey.match(/^[a-f0-9]{64}$/) } /** * NPUB provided - it will convert NPUB to HEX * HEX provided - it will return HEX * * @param pubKey in NPUB, HEX format * @returns HEX format */ export const pubToHex = async (pubKey: string): Promise => { // If key is NPUB if (pubKey.startsWith('npub')) { try { return nip19.decode(pubKey).data as string } catch (error) { return Promise.resolve(null) } } // valid hex key if (validateHex(pubKey)) return Promise.resolve(pubKey) // Not a valid hex key return Promise.resolve(null) } /** * If NSEC key is provided function will convert it to HEX * If HEX key Is provided function will validate the HEX format and return * * @param nsec or private key in HEX format */ export const nsecToHex = (nsec: string): string | null => { // If key is NSEC if (nsec.startsWith('nsec')) { try { return nip19.decode(nsec).data as string } catch (error) { return null } } // since it's not NSEC key we check if it's a valid hex key if (validateHex(nsec)) return nsec return null } export const hexToNpub = (hexPubkey: string | undefined): string => { if (!hexPubkey) return 'n/a' if (hexPubkey.includes('npub')) return hexPubkey return nip19.npubEncode(hexPubkey) } export const verifySignedEvent = (event: SignedEvent) => { const isGood = verifyEvent(event) if (!isGood) { throw new Error( 'Signed event did not pass verification. Check sig, id and pubkey.' ) } } export const queryNip05 = async ( nip05: string ): Promise<{ pubkey: string relays: string[] }> => { const NIP05_REGEX = /^(?:([\w.+-]+)@)?([\w_-]+(\.[\w_-]+)+)$/ const match = nip05.match(NIP05_REGEX) if (!match) throw new Error('Invalid nip05') const [_, name = '_', domain] = match const url = `https://${domain}/.well-known/nostr.json?name=${name}` const res = await axios(url) .then((res) => { return res.data }) .catch((err) => { console.log('err :>> ', err) throw err }) const pubkey = res.names[name] const relays: string[] = [] if (pubkey) { // check nip46 for user pubkey, if relays found for user, return those const userRelays = res.nip46?.[pubkey] as string[] if (userRelays && userRelays.length > 0) { relays.push(...userRelays) } else { // otherwise check nip46 for root user pubkey, if relays found, return those const root = res.names['_'] if (root) { const rootUserRelays = res.nip46?.[root] as string[] if (rootUserRelays && rootUserRelays.length > 0) relays.push(...rootUserRelays) } } } return { pubkey, relays } } export const base64EncodeSignedEvent = (event: SignedEvent) => { try { const authEventSerialized = JSON.stringify(event) const token = btoa(authEventSerialized) return token } catch (error) { throw new Error('An error occurred in JSON.stringify of signedAuthEvent') } } export const base64DecodeAuthToken = (authToken: string): SignedEvent => { const decodedToken = atob(authToken) try { const signedEvent = JSON.parse(decodedToken) return signedEvent } catch (error) { throw new Error('An error occurred in JSON.parse of the auth token') } } export const getRoboHashPicture = (npub: string): string => { return `https://robohash.org/${npub}.png?set=set3` }