feat: allow the user to login via nsecbunker using only domain part #79

Merged
s merged 1 commits from issue-77 into main 2024-05-27 10:02:08 +00:00
3 changed files with 45 additions and 12 deletions

2
src/constants.ts Normal file
View File

@ -0,0 +1,2 @@
// Regular expression to validate the NIP-05 identifier
export const NIP05_REGEX = /^(?:([\w.+-]+)@)?([\w_-]+(\.[\w_-]+)+)$/

View File

@ -21,6 +21,7 @@ import { Dispatch } from '../../store/store'
import { npubToHex, queryNip05 } from '../../utils'
import styles from './style.module.scss'
import { hexToBytes } from '@noble/hashes/utils'
import { NIP05_REGEX } from '../../constants'
export const Login = () => {
const [searchParams] = useSearchParams()
@ -158,7 +159,7 @@ export const Login = () => {
setLoadingSpinnerDesc('')
}
if (inputValue.includes('@')) {
if (inputValue.match(NIP05_REGEX)) {
const nip05Profile = await queryNip05(inputValue).catch((err) => {
toast.error('An error occurred while querying nip05 profile: ' + err)
return null
@ -319,7 +320,7 @@ export const Login = () => {
if (inputValue.startsWith('npub')) {
return loginWithNsecBunker()
}
if (inputValue.includes('@')) {
if (inputValue.match(NIP05_REGEX)) {
return loginWithNsecBunker()
}

View File

@ -1,6 +1,7 @@
import { nip19, verifyEvent } from 'nostr-tools'
import { SignedEvent } from '../types'
import axios from 'axios'
import { NIP05_REGEX } from '../constants'
/**
* @param hexKey hex private or public key
@ -72,18 +73,31 @@ export const verifySignedEvent = (event: SignedEvent) => {
}
}
/**
* Function to query NIP-05 data and return the public key and relays.
*
* @param {string} nip05 - The NIP-05 identifier in the format "name@domain".
* @returns {Promise<{ pubkey: string, relays: string[] }>} - The public key and an array of relay URLs.
* @throws Will throw an error if the NIP-05 identifier is invalid or if there is an issue with the network request.
*/
export const queryNip05 = async (
nip05: string
): Promise<{
pubkey: string
relays: string[]
}> => {
const NIP05_REGEX = /^(?:([\w.+-]+)@)?([\w_-]+(\.[\w_-]+)+)$/
const match = nip05.match(NIP05_REGEX)
// Throw an error if the NIP-05 identifier is invalid
if (!match) throw new Error('Invalid nip05')
// Destructure the match result, assigning default value '_' to name if not provided
const [_, name = '_', domain] = match
// Construct the URL to query the NIP-05 data
const url = `https://${domain}/.well-known/nostr.json?name=${name}`
// Perform the network request to get the NIP-05 data
const res = await axios(url)
.then((res) => {
return res.data
@ -93,25 +107,41 @@ export const queryNip05 = async (
throw err
})
// Extract the public key from the response data
const pubkey = res.names[name]
const relays: string[] = []
// If a public key is found
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
// Function to add relays if they exist and are not empty
const addRelays = (relayList?: string[]) => {
if (relayList && relayList.length > 0) {
relays.push(...relayList)
}
}
// Check for user-specific relays in the NIP-46 section of the response data
if (res.nip46) {
addRelays(res.nip46[pubkey] as string[])
}
// Check for user-specific relays in the relays section of the response data if not found in NIP-46
if (relays.length === 0 && res.relays) {
addRelays(res.relays[pubkey] as string[])
}
// If no user-specific relays are found, check for root user relays
if (relays.length === 0) {
const root = res.names['_']
if (root) {
const rootUserRelays = res.nip46?.[root] as string[]
if (rootUserRelays && rootUserRelays.length > 0)
relays.push(...rootUserRelays)
// Check for root user relays in both NIP-46 and relays sections
addRelays(res.nip46?.[root] as string[])
addRelays(res.relays?.[root] as string[])
}
}
}
// Return the public key and the array of relays
return {
pubkey,
relays