import browser from 'webextension-polyfill' import React, {useState, useCallback, useEffect} from 'react' import {render} from 'react-dom' import {generatePrivateKey, getPublicKey, nip19} from 'nostr-tools' import QRCode from 'react-qr-code' import { getPermissionsString, readPermissions, removePermissions } from './common' function Options() { let [pubKey, setPubKey] = useState('') let [privKey, setPrivKey] = useState('') let [relays, setRelays] = useState([]) let [newRelayURL, setNewRelayURL] = useState('') let [permissions, setPermissions] = useState() let [protocolHandler, setProtocolHandler] = useState(null) let [hidingPrivateKey, hidePrivateKey] = useState(true) let [message, setMessage] = useState('') let [showQR, setShowQR] = useState('') const showMessage = useCallback(msg => { setMessage(msg) setTimeout(setMessage, 3000) }) useEffect(() => { browser.storage.local .get(['private_key', 'relays', 'protocol_handler']) .then(results => { if (results.private_key) { setPrivKey(nip19.nsecEncode(results.private_key)) let hexKey = getPublicKey(results.private_key) let npubKey = nip19.npubEncode(hexKey) setPubKey(npubKey) } if (results.relays) { let relaysList = [] for (let url in results.relays) { relaysList.push({ url, policy: results.relays[url] }) } setRelays(relaysList) } if (results.protocol_handler) { setProtocolHandler(results.protocol_handler) } }) }, []) useEffect(() => { loadPermissions() }, []) function loadPermissions() { readPermissions().then(permissions => { setPermissions( Object.entries(permissions).map( ([host, {level, condition, created_at}]) => ({ host, level, condition, created_at }) ) ) }) } return ( <>

nos2x

nostr signer extension

options

preferred relays:
{relays.map(({url, policy}, i) => (
))}
setNewRelayURL(e.target.value)} onBlur={addNewRelay} />
{permissions?.length > 0 && ( <>

permissions

{permissions.map(({host, level, condition, created_at}) => ( ))}
domain permissions condition since
{host} {getPermissionsString(level)} {condition} {new Date(created_at * 1000) .toISOString() .split('.')[0] .split('T') .join(' ')}
)}

handle{' '} nostr:{' '} links:

{protocolHandler !== null && (
{`
  {hex} = hex pubkey for npub or nprofile, hex event id for note or nevent
  {p_or_e} = "p" for npub or nprofile, "e" for note or nevent
  {u_or_n} = "u" for npub or nprofile, "n" for note or nevent
  {relay0} = first relay in a nprofile or nevent
  {relay1} = second relay in a nprofile or nevent
  {relay2} = third relay in a nprofile or nevent
  {raw} = anything after the colon, i.e. the full nip19 bech32 string
  {hrp} = human-readable prefix of the nip19 string

  examples:
    - https://nostr.guru/{p_or_e}/{hex}
    - https://brb.io/{u_or_n}/{hex}
    - https://notes.blockcore.net/{p_or_e}/{hex}
              `}
)}
{message}
) async function handleKeyChange(e) { let key = e.target.value.toLowerCase().trim() setPrivKey(key) } async function generate() { setPrivKey(nip19.nsecEncode(generatePrivateKey())) } async function saveKey() { if (!isKeyValid()) return let hexOrEmptyKey = privKey try { let {type, data} = nip19.decode(privKey) if (type === 'nsec') hexOrEmptyKey = data } catch (_) {} await browser.storage.local.set({ private_key: hexOrEmptyKey }) if (hexOrEmptyKey !== '') { setPrivKey(nip19.nsecEncode(hexOrEmptyKey)) } showMessage('saved private key!') } function isKeyValid() { if (privKey === '') return true if (privKey.match(/^[a-f0-9]{64}$/)) return true try { if (nip19.decode(privKey).type === 'nsec') return true } catch (_) {} return false } function changeRelayURL(i, ev) { setRelays([ ...relays.slice(0, i), {url: ev.target.value, policy: relays[i].policy}, ...relays.slice(i + 1) ]) } function toggleRelayPolicy(i, cat) { setRelays([ ...relays.slice(0, i), { url: relays[i].url, policy: {...relays[i].policy, [cat]: !relays[i].policy[cat]} }, ...relays.slice(i + 1) ]) } function addNewRelay() { relays.push({ url: newRelayURL, policy: {read: true, write: true} }) setRelays(relays) setNewRelayURL('') } async function handleRevoke(e) { let host = e.target.dataset.domain if (window.confirm(`revoke all permissions from ${host}?`)) { await removePermissions(host) showMessage(`removed permissions from ${host}`) loadPermissions() } } async function saveRelays() { await browser.storage.local.set({ relays: Object.fromEntries( relays .filter(({url}) => url.trim() !== '') .map(({url, policy}) => [url.trim(), policy]) ) }) showMessage('saved relays!') } function handleChangeProtocolHandler(e) { if (e.target.type === 'text') setProtocolHandler(e.target.value) else switch (e.target.value) { case 'no': setProtocolHandler(null) break case 'yes': setProtocolHandler('') break } } async function saveNostrProtocolHandlerSettings() { await browser.storage.local.set({protocol_handler: protocolHandler}) showMessage('saved protocol handler!') } } render(, document.getElementById('main'))