add timeouts for nostr extension calls
This commit is contained in:
parent
efd48afd61
commit
9455847484
|
@ -15,6 +15,7 @@ import { useMe } from './me'
|
|||
import useCrossposter from './use-crossposter'
|
||||
import { useToast } from './toast'
|
||||
import { ItemButtonBar } from './post'
|
||||
import { callWithTimeout } from '../lib/nostr'
|
||||
|
||||
export function DiscussionForm ({
|
||||
item, sub, editThreshold, titleLabel = 'title',
|
||||
|
@ -53,10 +54,12 @@ export function DiscussionForm ({
|
|||
const onSubmit = useCallback(
|
||||
async ({ boost, crosspost, ...values }) => {
|
||||
try {
|
||||
if (crosspost && !(await window.nostr.getPublicKey())) {
|
||||
throw new Error('not available')
|
||||
if (crosspost) {
|
||||
const pubkey = await callWithTimeout(() => window.nostr.getPublicKey(), 5000)
|
||||
if (!pubkey) throw new Error('failed to get pubkey')
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
throw new Error(`Nostr extension error: ${e.message}`)
|
||||
}
|
||||
|
||||
|
@ -81,11 +84,6 @@ export function DiscussionForm ({
|
|||
if (crosspost && discussionId) {
|
||||
const crosspostResult = await crossposter({ ...values, id: discussionId })
|
||||
noteId = crosspostResult?.noteId
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
}
|
||||
|
||||
if (noteId) {
|
||||
await updateNoteId({
|
||||
variables: {
|
||||
|
@ -94,6 +92,11 @@ export function DiscussionForm ({
|
|||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
toaster.danger('Error crossposting to Nostr', e.message)
|
||||
}
|
||||
|
||||
if (item) {
|
||||
await router.push(`/items/${item.id}`)
|
||||
|
@ -122,7 +125,7 @@ export function DiscussionForm ({
|
|||
initial={{
|
||||
title: item?.title || shareTitle || '',
|
||||
text: item?.text || '',
|
||||
crosspost: me?.privates?.nostrCrossposting,
|
||||
crosspost: item ? !!item.noteId : me?.privates?.nostrCrossposting,
|
||||
...AdvPostInitial({ forward: normalizeForwards(item?.forwards), boost: item?.boost }),
|
||||
...SubSelectInitial({ sub: item?.subName || sub?.name })
|
||||
}}
|
||||
|
|
|
@ -8,6 +8,7 @@ import { useRouter } from 'next/router'
|
|||
import AccordianItem from './accordian-item'
|
||||
import BackIcon from '../svgs/arrow-left-line.svg'
|
||||
import styles from './lightning-auth.module.css'
|
||||
import { callWithTimeout } from '../lib/nostr'
|
||||
|
||||
function ExtensionError ({ message, details }) {
|
||||
return (
|
||||
|
@ -94,12 +95,12 @@ export function NostrAuth ({ text, callbackUrl }) {
|
|||
// have them sign a message with the challenge
|
||||
let event
|
||||
try {
|
||||
event = await window.nostr.signEvent({
|
||||
event = await callWithTimeout(() => window.nostr.signEvent({
|
||||
kind: 22242,
|
||||
created_at: Math.floor(Date.now() / 1000),
|
||||
tags: [['challenge', k1]],
|
||||
content: 'Stacker News Authentication'
|
||||
})
|
||||
}), 5000)
|
||||
if (!event) throw new Error('extension returned empty event')
|
||||
} catch (e) {
|
||||
if (e.message === 'window.nostr call already executing' || !mounted) return
|
||||
|
|
|
@ -6,6 +6,7 @@ import { useMutation, gql } from '@apollo/client'
|
|||
import { useMe } from './me'
|
||||
import { useToast } from './toast'
|
||||
import { SSR } from '../lib/constants'
|
||||
import { callWithTimeout } from '../lib/nostr'
|
||||
|
||||
const getShareUrl = (item, me) => {
|
||||
const path = `/items/${item?.id}${me ? `/r/${me.name}` : ''}`
|
||||
|
@ -77,7 +78,8 @@ export default function Share ({ item }) {
|
|||
<Dropdown.Item
|
||||
onClick={async () => {
|
||||
try {
|
||||
if (!(await window.nostr?.getPublicKey())) {
|
||||
const pubkey = await callWithTimeout(() => window.nostr.getPublicKey(), 5000)
|
||||
if (!pubkey) {
|
||||
throw new Error('not available')
|
||||
}
|
||||
} catch (e) {
|
||||
|
|
12
lib/nostr.js
12
lib/nostr.js
|
@ -82,7 +82,7 @@ async function publishNostrEvent (signedEvent, relay) {
|
|||
|
||||
export async function crosspost (event, relays = DEFAULT_CROSSPOSTING_RELAYS) {
|
||||
try {
|
||||
const signedEvent = await window.nostr.signEvent(event)
|
||||
const signedEvent = await callWithTimeout(() => window.nostr.signEvent(event), 5000)
|
||||
if (!signedEvent) throw new Error('failed to sign event')
|
||||
|
||||
const promises = relays.map(r => publishNostrEvent(signedEvent, r))
|
||||
|
@ -106,3 +106,13 @@ export async function crosspost (event, relays = DEFAULT_CROSSPOSTING_RELAYS) {
|
|||
return { error }
|
||||
}
|
||||
}
|
||||
|
||||
export function callWithTimeout (targetFunction, timeoutMs) {
|
||||
return new Promise((resolve, reject) => {
|
||||
Promise.race([
|
||||
targetFunction(),
|
||||
new Promise((resolve, reject) => setTimeout(() => reject(new Error('timeouted after ' + timeoutMs + ' ms waiting for extension')), timeoutMs))
|
||||
]).then(resolve)
|
||||
.catch(reject)
|
||||
})
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue