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 npubToHex = (pubKey: string): string | null => { // If key is NPUB if (pubKey.startsWith('npub1')) { try { return nip19.decode(pubKey).data as string } catch (error) { return null } } // valid hex key if (validateHex(pubKey)) return pubKey // Not a valid hex key return 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): `npub1${string}` => { if (hexPubkey.startsWith('npub1')) return hexPubkey as `npub1${string}` 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') } } /** * @param pubkey in hex or npub format * @returns robohash.org url for the avatar */ export const getRoboHashPicture = (pubkey?: string, set: number = 1): string => { if (!pubkey) return '' const npub = hexToNpub(pubkey) return `https://robohash.org/${npub}.png?set=set${set}` }