2023-08-08 18:19:31 +00:00
|
|
|
import { bech32 } from 'bech32'
|
Nostr crossposting all item types (#779)
* crosspost-item
* crosspost old items, update with nEventId
* Updating noteId encoding, cleaning up a little
* Fixing item-info condition, cleaning up
* Linting
* Add createdAt variable back
* Change instances of eventId to noteId
* Adding upsertNoteId mutation
* Cleaning up updateItem, using toasts to communivate success/failure in crosspost-item
* Linting
* Move crosspost to share button, make sure only OP can crosspost
* Lint
* Simplify conditions
* user might have no nostr extension installed
Co-authored-by: ekzyis <27162016+ekzyis@users.noreply.github.com>
* change upsertNoteId to updateNoteID for resolver and mutations, change isOp to mine, remove unused noteId params
* Basic setup for crossposting poll / link items
* post rebase fixes and Bounty and job crossposts
* Job crossposting working
* adding back accidentally removed import
* Lint / rebase
* Outsource as much crossposting logic from discussion-form into use-crossposter as possible
* Fix incorrect property for user relays, fix itemId param in updateNoteId
* Fix toast messages / error cases in use-crossposter
* Update item forms to for updated use-crossposter hook
* CrosspostDropdownItem in share updated to accomodate use-crossposter update
* Encode paramaterized replacable event id's in naddress format with nostr-tools, bounty to follw nip-99 spec
* Increase timeout on relay connection / cleaning up
* No longer crossposting job
* Add blastr, fix crosspost button in item-info for polls/discussions, finish removing job crosspostr code
* Fix toaster error, create reusable crossposterror function to surface toaster
* Cleaning up / comments / linting
* Update copy
* Simplify CrosspostdropdownItem, keep replies from being crossposted
* Moved query for missing item fields when crossposting to use-crossposter hook
* Remove unneeded param in CrosspostDropdownItem, lint
* Small fixes post rebase
* Remove unused import
* fix nostr-tools version, fix package-lock.json
* Update components/item-info.js
Co-authored-by: ekzyis <ek@stacker.news>
* Remove unused param, determine poll item type from pollCost field, add mutiny strfry relay to defaults
* Update toaster implementations, use no-cache for item query, restructure crosspostItem to use await with try catch
* crosspost info modal that lives under adv-post-form now has dynamic crossposting info
* Move determineItemType into handleEventCreation, mover item/event handing outside of do ... while loop
* Lint
* Reconcile skip method with onCancel function in toaster
* Handle failedRelays being undefined
* determine item type from router.query.type if available otherwise use item fields
* Initiliaze failerRelays as undefined but handle error explicitly
* Lint
* Fix crosspost default value for link, poll, bounty forms
---------
Co-authored-by: ekzyis <27162016+ekzyis@users.noreply.github.com>
Co-authored-by: ekzyis <ek@stacker.news>
Co-authored-by: Keyan <34140557+huumn@users.noreply.github.com>
2024-02-22 01:18:36 +00:00
|
|
|
import { nip19 } from 'nostr-tools'
|
2024-08-18 22:28:39 +00:00
|
|
|
import WebSocket from 'isomorphic-ws'
|
|
|
|
import { callWithTimeout, withTimeout } from '@/lib/time'
|
2024-08-21 15:13:27 +00:00
|
|
|
import crypto from 'crypto'
|
2023-08-08 18:19:31 +00:00
|
|
|
|
2023-02-08 19:38:04 +00:00
|
|
|
export const NOSTR_PUBKEY_HEX = /^[0-9a-fA-F]{64}$/
|
|
|
|
export const NOSTR_PUBKEY_BECH32 = /^npub1[02-9ac-hj-np-z]+$/
|
|
|
|
export const NOSTR_MAX_RELAY_NUM = 20
|
2023-08-08 18:19:31 +00:00
|
|
|
export const NOSTR_ZAPPLE_PAY_NPUB = 'npub1wxl6njlcgygduct7jkgzrvyvd9fylj4pqvll6p32h59wyetm5fxqjchcan'
|
2023-10-04 18:47:09 +00:00
|
|
|
export const DEFAULT_CROSSPOSTING_RELAYS = [
|
|
|
|
'wss://nostrue.com/',
|
|
|
|
'wss://relay.damus.io/',
|
|
|
|
'wss://relay.nostr.band/',
|
|
|
|
'wss://relay.snort.social/',
|
Nostr crossposting all item types (#779)
* crosspost-item
* crosspost old items, update with nEventId
* Updating noteId encoding, cleaning up a little
* Fixing item-info condition, cleaning up
* Linting
* Add createdAt variable back
* Change instances of eventId to noteId
* Adding upsertNoteId mutation
* Cleaning up updateItem, using toasts to communivate success/failure in crosspost-item
* Linting
* Move crosspost to share button, make sure only OP can crosspost
* Lint
* Simplify conditions
* user might have no nostr extension installed
Co-authored-by: ekzyis <27162016+ekzyis@users.noreply.github.com>
* change upsertNoteId to updateNoteID for resolver and mutations, change isOp to mine, remove unused noteId params
* Basic setup for crossposting poll / link items
* post rebase fixes and Bounty and job crossposts
* Job crossposting working
* adding back accidentally removed import
* Lint / rebase
* Outsource as much crossposting logic from discussion-form into use-crossposter as possible
* Fix incorrect property for user relays, fix itemId param in updateNoteId
* Fix toast messages / error cases in use-crossposter
* Update item forms to for updated use-crossposter hook
* CrosspostDropdownItem in share updated to accomodate use-crossposter update
* Encode paramaterized replacable event id's in naddress format with nostr-tools, bounty to follw nip-99 spec
* Increase timeout on relay connection / cleaning up
* No longer crossposting job
* Add blastr, fix crosspost button in item-info for polls/discussions, finish removing job crosspostr code
* Fix toaster error, create reusable crossposterror function to surface toaster
* Cleaning up / comments / linting
* Update copy
* Simplify CrosspostdropdownItem, keep replies from being crossposted
* Moved query for missing item fields when crossposting to use-crossposter hook
* Remove unneeded param in CrosspostDropdownItem, lint
* Small fixes post rebase
* Remove unused import
* fix nostr-tools version, fix package-lock.json
* Update components/item-info.js
Co-authored-by: ekzyis <ek@stacker.news>
* Remove unused param, determine poll item type from pollCost field, add mutiny strfry relay to defaults
* Update toaster implementations, use no-cache for item query, restructure crosspostItem to use await with try catch
* crosspost info modal that lives under adv-post-form now has dynamic crossposting info
* Move determineItemType into handleEventCreation, mover item/event handing outside of do ... while loop
* Lint
* Reconcile skip method with onCancel function in toaster
* Handle failedRelays being undefined
* determine item type from router.query.type if available otherwise use item fields
* Initiliaze failerRelays as undefined but handle error explicitly
* Lint
* Fix crosspost default value for link, poll, bounty forms
---------
Co-authored-by: ekzyis <27162016+ekzyis@users.noreply.github.com>
Co-authored-by: ekzyis <ek@stacker.news>
Co-authored-by: Keyan <34140557+huumn@users.noreply.github.com>
2024-02-22 01:18:36 +00:00
|
|
|
'wss://nostr21.com/',
|
|
|
|
'wss://nostr.mutinywallet.com/',
|
|
|
|
'wss://relay.mutinywallet.com/'
|
2023-10-04 18:47:09 +00:00
|
|
|
]
|
2023-08-08 18:19:31 +00:00
|
|
|
|
2024-08-18 22:28:39 +00:00
|
|
|
export class Relay {
|
|
|
|
constructor (relayUrl) {
|
|
|
|
const ws = new WebSocket(relayUrl)
|
|
|
|
|
2024-09-19 20:53:42 +00:00
|
|
|
ws.onmessage = (msg) => {
|
2024-08-18 22:28:39 +00:00
|
|
|
const [type, notice] = JSON.parse(msg.data)
|
|
|
|
if (type === 'NOTICE') {
|
|
|
|
console.log('relay notice:', notice)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-09-19 20:53:42 +00:00
|
|
|
ws.onerror = (err) => {
|
2024-08-21 15:13:27 +00:00
|
|
|
console.error('websocket error:', err.message)
|
|
|
|
this.error = err.message
|
2024-08-18 22:28:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
this.ws = ws
|
2024-08-21 15:13:27 +00:00
|
|
|
this.url = relayUrl
|
|
|
|
this.error = null
|
2024-08-18 22:28:39 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
static async connect (url, { timeout } = {}) {
|
|
|
|
const relay = new Relay(url)
|
|
|
|
await relay.waitUntilConnected({ timeout })
|
|
|
|
return relay
|
|
|
|
}
|
|
|
|
|
|
|
|
get connected () {
|
|
|
|
return this.ws.readyState === WebSocket.OPEN
|
|
|
|
}
|
|
|
|
|
|
|
|
get closed () {
|
|
|
|
return this.ws.readyState === WebSocket.CLOSING || this.ws.readyState === WebSocket.CLOSED
|
|
|
|
}
|
|
|
|
|
|
|
|
async waitUntilConnected ({ timeout } = {}) {
|
|
|
|
let interval
|
|
|
|
|
|
|
|
const checkPromise = new Promise((resolve, reject) => {
|
|
|
|
interval = setInterval(() => {
|
|
|
|
if (this.connected) {
|
|
|
|
resolve()
|
|
|
|
}
|
|
|
|
if (this.closed) {
|
|
|
|
reject(new Error(`failed to connect to ${this.url}: ` + this.error))
|
|
|
|
}
|
|
|
|
}, 100)
|
|
|
|
})
|
|
|
|
|
|
|
|
try {
|
|
|
|
return await withTimeout(checkPromise, timeout)
|
2024-08-27 16:15:00 +00:00
|
|
|
} catch (err) {
|
|
|
|
this.close()
|
|
|
|
throw err
|
2024-08-18 22:28:39 +00:00
|
|
|
} finally {
|
|
|
|
clearInterval(interval)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
close () {
|
|
|
|
const state = this.ws.readyState
|
|
|
|
if (state !== WebSocket.CLOSING && state !== WebSocket.CLOSED) {
|
|
|
|
this.ws.close()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async publish (event, { timeout } = {}) {
|
|
|
|
const ws = this.ws
|
|
|
|
|
|
|
|
let listener
|
|
|
|
const ackPromise = new Promise((resolve, reject) => {
|
|
|
|
listener = function onmessage (msg) {
|
|
|
|
const [type, eventId, accepted, reason] = JSON.parse(msg.data)
|
|
|
|
|
|
|
|
if (type !== 'OK' || eventId !== event.id) return
|
|
|
|
|
|
|
|
if (accepted) {
|
|
|
|
resolve(eventId)
|
|
|
|
} else {
|
|
|
|
reject(new Error(reason || `event rejected: ${eventId}`))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ws.addEventListener('message', listener)
|
2024-08-21 15:13:27 +00:00
|
|
|
|
|
|
|
ws.send(JSON.stringify(['EVENT', event]))
|
2024-08-18 22:28:39 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
try {
|
|
|
|
return await withTimeout(ackPromise, timeout)
|
|
|
|
} finally {
|
|
|
|
ws.removeEventListener('message', listener)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
async fetch (filter, { timeout } = {}) {
|
|
|
|
const ws = this.ws
|
|
|
|
|
|
|
|
let listener
|
|
|
|
const ackPromise = new Promise((resolve, reject) => {
|
2024-08-21 15:13:27 +00:00
|
|
|
const id = crypto.randomBytes(16).toString('hex')
|
2024-08-18 22:28:39 +00:00
|
|
|
|
|
|
|
const events = []
|
|
|
|
let eose = false
|
|
|
|
|
|
|
|
listener = function onmessage (msg) {
|
2024-08-21 15:13:27 +00:00
|
|
|
const [type, subId, event] = JSON.parse(msg.data)
|
2024-08-18 22:28:39 +00:00
|
|
|
|
2024-08-21 15:13:27 +00:00
|
|
|
if (subId !== id) return
|
2024-08-18 22:28:39 +00:00
|
|
|
|
|
|
|
if (type === 'EVENT') {
|
|
|
|
events.push(event)
|
|
|
|
if (eose) {
|
|
|
|
// EOSE was already received:
|
|
|
|
// return first event after EOSE
|
|
|
|
resolve(events)
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
if (type === 'CLOSED') {
|
|
|
|
return resolve(events)
|
|
|
|
}
|
|
|
|
|
|
|
|
if (type === 'EOSE') {
|
|
|
|
eose = true
|
|
|
|
if (events.length > 0) {
|
|
|
|
// we already received events before EOSE:
|
|
|
|
// return all events before EOSE
|
|
|
|
ws.send(JSON.stringify(['CLOSE', id]))
|
|
|
|
return resolve(events)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ws.addEventListener('message', listener)
|
2024-08-21 15:13:27 +00:00
|
|
|
|
|
|
|
ws.send(JSON.stringify(['REQ', id, ...filter]))
|
2024-08-18 22:28:39 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
try {
|
|
|
|
return await withTimeout(ackPromise, timeout)
|
|
|
|
} finally {
|
|
|
|
ws.removeEventListener('message', listener)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-08 18:19:31 +00:00
|
|
|
export function hexToBech32 (hex, prefix = 'npub') {
|
|
|
|
return bech32.encode(prefix, bech32.toWords(Buffer.from(hex, 'hex')))
|
|
|
|
}
|
|
|
|
|
|
|
|
export function nostrZapDetails (zap) {
|
|
|
|
let { pubkey, content, tags } = zap
|
|
|
|
let npub = hexToBech32(pubkey)
|
|
|
|
if (npub === NOSTR_ZAPPLE_PAY_NPUB) {
|
|
|
|
const znpub = content.match(/^From: nostr:(npub1[02-9ac-hj-np-z]+)$/)?.[1]
|
|
|
|
if (znpub) {
|
|
|
|
npub = znpub
|
|
|
|
// zapple pay does not support user content
|
|
|
|
content = null
|
|
|
|
}
|
|
|
|
}
|
|
|
|
const event = tags.filter(t => t?.length >= 2 && t[0] === 'e')?.[0]?.[1]
|
|
|
|
const note = event ? hexToBech32(event, 'note') : null
|
|
|
|
|
|
|
|
return { npub, content, note }
|
|
|
|
}
|
2023-10-04 18:47:09 +00:00
|
|
|
|
2024-08-18 22:28:39 +00:00
|
|
|
async function publishNostrEvent (signedEvent, relayUrl) {
|
|
|
|
const timeout = 3000
|
|
|
|
const relay = await Relay.connect(relayUrl, { timeout })
|
2024-08-27 16:15:00 +00:00
|
|
|
try {
|
|
|
|
await relay.publish(signedEvent, { timeout })
|
|
|
|
} finally {
|
|
|
|
relay.close()
|
|
|
|
}
|
2023-10-04 18:47:09 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
export async function crosspost (event, relays = DEFAULT_CROSSPOSTING_RELAYS) {
|
|
|
|
try {
|
Nostr crossposting all item types (#779)
* crosspost-item
* crosspost old items, update with nEventId
* Updating noteId encoding, cleaning up a little
* Fixing item-info condition, cleaning up
* Linting
* Add createdAt variable back
* Change instances of eventId to noteId
* Adding upsertNoteId mutation
* Cleaning up updateItem, using toasts to communivate success/failure in crosspost-item
* Linting
* Move crosspost to share button, make sure only OP can crosspost
* Lint
* Simplify conditions
* user might have no nostr extension installed
Co-authored-by: ekzyis <27162016+ekzyis@users.noreply.github.com>
* change upsertNoteId to updateNoteID for resolver and mutations, change isOp to mine, remove unused noteId params
* Basic setup for crossposting poll / link items
* post rebase fixes and Bounty and job crossposts
* Job crossposting working
* adding back accidentally removed import
* Lint / rebase
* Outsource as much crossposting logic from discussion-form into use-crossposter as possible
* Fix incorrect property for user relays, fix itemId param in updateNoteId
* Fix toast messages / error cases in use-crossposter
* Update item forms to for updated use-crossposter hook
* CrosspostDropdownItem in share updated to accomodate use-crossposter update
* Encode paramaterized replacable event id's in naddress format with nostr-tools, bounty to follw nip-99 spec
* Increase timeout on relay connection / cleaning up
* No longer crossposting job
* Add blastr, fix crosspost button in item-info for polls/discussions, finish removing job crosspostr code
* Fix toaster error, create reusable crossposterror function to surface toaster
* Cleaning up / comments / linting
* Update copy
* Simplify CrosspostdropdownItem, keep replies from being crossposted
* Moved query for missing item fields when crossposting to use-crossposter hook
* Remove unneeded param in CrosspostDropdownItem, lint
* Small fixes post rebase
* Remove unused import
* fix nostr-tools version, fix package-lock.json
* Update components/item-info.js
Co-authored-by: ekzyis <ek@stacker.news>
* Remove unused param, determine poll item type from pollCost field, add mutiny strfry relay to defaults
* Update toaster implementations, use no-cache for item query, restructure crosspostItem to use await with try catch
* crosspost info modal that lives under adv-post-form now has dynamic crossposting info
* Move determineItemType into handleEventCreation, mover item/event handing outside of do ... while loop
* Lint
* Reconcile skip method with onCancel function in toaster
* Handle failedRelays being undefined
* determine item type from router.query.type if available otherwise use item fields
* Initiliaze failerRelays as undefined but handle error explicitly
* Lint
* Fix crosspost default value for link, poll, bounty forms
---------
Co-authored-by: ekzyis <27162016+ekzyis@users.noreply.github.com>
Co-authored-by: ekzyis <ek@stacker.news>
Co-authored-by: Keyan <34140557+huumn@users.noreply.github.com>
2024-02-22 01:18:36 +00:00
|
|
|
const signedEvent = await callWithTimeout(() => window.nostr.signEvent(event), 10000)
|
2023-10-04 18:47:09 +00:00
|
|
|
if (!signedEvent) throw new Error('failed to sign event')
|
|
|
|
|
|
|
|
const promises = relays.map(r => publishNostrEvent(signedEvent, r))
|
|
|
|
const results = await Promise.allSettled(promises)
|
|
|
|
const successfulRelays = []
|
|
|
|
const failedRelays = []
|
|
|
|
|
|
|
|
results.forEach((result, index) => {
|
|
|
|
if (result.status === 'fulfilled') {
|
|
|
|
successfulRelays.push(relays[index])
|
|
|
|
} else {
|
|
|
|
failedRelays.push({ relay: relays[index], error: result.reason })
|
|
|
|
}
|
|
|
|
})
|
|
|
|
|
Nostr crossposting all item types (#779)
* crosspost-item
* crosspost old items, update with nEventId
* Updating noteId encoding, cleaning up a little
* Fixing item-info condition, cleaning up
* Linting
* Add createdAt variable back
* Change instances of eventId to noteId
* Adding upsertNoteId mutation
* Cleaning up updateItem, using toasts to communivate success/failure in crosspost-item
* Linting
* Move crosspost to share button, make sure only OP can crosspost
* Lint
* Simplify conditions
* user might have no nostr extension installed
Co-authored-by: ekzyis <27162016+ekzyis@users.noreply.github.com>
* change upsertNoteId to updateNoteID for resolver and mutations, change isOp to mine, remove unused noteId params
* Basic setup for crossposting poll / link items
* post rebase fixes and Bounty and job crossposts
* Job crossposting working
* adding back accidentally removed import
* Lint / rebase
* Outsource as much crossposting logic from discussion-form into use-crossposter as possible
* Fix incorrect property for user relays, fix itemId param in updateNoteId
* Fix toast messages / error cases in use-crossposter
* Update item forms to for updated use-crossposter hook
* CrosspostDropdownItem in share updated to accomodate use-crossposter update
* Encode paramaterized replacable event id's in naddress format with nostr-tools, bounty to follw nip-99 spec
* Increase timeout on relay connection / cleaning up
* No longer crossposting job
* Add blastr, fix crosspost button in item-info for polls/discussions, finish removing job crosspostr code
* Fix toaster error, create reusable crossposterror function to surface toaster
* Cleaning up / comments / linting
* Update copy
* Simplify CrosspostdropdownItem, keep replies from being crossposted
* Moved query for missing item fields when crossposting to use-crossposter hook
* Remove unneeded param in CrosspostDropdownItem, lint
* Small fixes post rebase
* Remove unused import
* fix nostr-tools version, fix package-lock.json
* Update components/item-info.js
Co-authored-by: ekzyis <ek@stacker.news>
* Remove unused param, determine poll item type from pollCost field, add mutiny strfry relay to defaults
* Update toaster implementations, use no-cache for item query, restructure crosspostItem to use await with try catch
* crosspost info modal that lives under adv-post-form now has dynamic crossposting info
* Move determineItemType into handleEventCreation, mover item/event handing outside of do ... while loop
* Lint
* Reconcile skip method with onCancel function in toaster
* Handle failedRelays being undefined
* determine item type from router.query.type if available otherwise use item fields
* Initiliaze failerRelays as undefined but handle error explicitly
* Lint
* Fix crosspost default value for link, poll, bounty forms
---------
Co-authored-by: ekzyis <27162016+ekzyis@users.noreply.github.com>
Co-authored-by: ekzyis <ek@stacker.news>
Co-authored-by: Keyan <34140557+huumn@users.noreply.github.com>
2024-02-22 01:18:36 +00:00
|
|
|
let noteId = null
|
|
|
|
if (signedEvent.kind !== 1) {
|
|
|
|
noteId = await nip19.naddrEncode({
|
|
|
|
kind: signedEvent.kind,
|
|
|
|
pubkey: signedEvent.pubkey,
|
|
|
|
identifier: signedEvent.tags[0][1]
|
|
|
|
})
|
|
|
|
} else {
|
|
|
|
noteId = hexToBech32(signedEvent.id, 'note')
|
|
|
|
}
|
2023-10-04 18:47:09 +00:00
|
|
|
|
2023-12-19 17:48:48 +00:00
|
|
|
return { successfulRelays, failedRelays, noteId }
|
2023-10-04 18:47:09 +00:00
|
|
|
} catch (error) {
|
Nostr crossposting all item types (#779)
* crosspost-item
* crosspost old items, update with nEventId
* Updating noteId encoding, cleaning up a little
* Fixing item-info condition, cleaning up
* Linting
* Add createdAt variable back
* Change instances of eventId to noteId
* Adding upsertNoteId mutation
* Cleaning up updateItem, using toasts to communivate success/failure in crosspost-item
* Linting
* Move crosspost to share button, make sure only OP can crosspost
* Lint
* Simplify conditions
* user might have no nostr extension installed
Co-authored-by: ekzyis <27162016+ekzyis@users.noreply.github.com>
* change upsertNoteId to updateNoteID for resolver and mutations, change isOp to mine, remove unused noteId params
* Basic setup for crossposting poll / link items
* post rebase fixes and Bounty and job crossposts
* Job crossposting working
* adding back accidentally removed import
* Lint / rebase
* Outsource as much crossposting logic from discussion-form into use-crossposter as possible
* Fix incorrect property for user relays, fix itemId param in updateNoteId
* Fix toast messages / error cases in use-crossposter
* Update item forms to for updated use-crossposter hook
* CrosspostDropdownItem in share updated to accomodate use-crossposter update
* Encode paramaterized replacable event id's in naddress format with nostr-tools, bounty to follw nip-99 spec
* Increase timeout on relay connection / cleaning up
* No longer crossposting job
* Add blastr, fix crosspost button in item-info for polls/discussions, finish removing job crosspostr code
* Fix toaster error, create reusable crossposterror function to surface toaster
* Cleaning up / comments / linting
* Update copy
* Simplify CrosspostdropdownItem, keep replies from being crossposted
* Moved query for missing item fields when crossposting to use-crossposter hook
* Remove unneeded param in CrosspostDropdownItem, lint
* Small fixes post rebase
* Remove unused import
* fix nostr-tools version, fix package-lock.json
* Update components/item-info.js
Co-authored-by: ekzyis <ek@stacker.news>
* Remove unused param, determine poll item type from pollCost field, add mutiny strfry relay to defaults
* Update toaster implementations, use no-cache for item query, restructure crosspostItem to use await with try catch
* crosspost info modal that lives under adv-post-form now has dynamic crossposting info
* Move determineItemType into handleEventCreation, mover item/event handing outside of do ... while loop
* Lint
* Reconcile skip method with onCancel function in toaster
* Handle failedRelays being undefined
* determine item type from router.query.type if available otherwise use item fields
* Initiliaze failerRelays as undefined but handle error explicitly
* Lint
* Fix crosspost default value for link, poll, bounty forms
---------
Co-authored-by: ekzyis <27162016+ekzyis@users.noreply.github.com>
Co-authored-by: ekzyis <ek@stacker.news>
Co-authored-by: Keyan <34140557+huumn@users.noreply.github.com>
2024-02-22 01:18:36 +00:00
|
|
|
console.error('Crosspost error:', error)
|
2023-10-04 18:47:09 +00:00
|
|
|
return { error }
|
|
|
|
}
|
|
|
|
}
|