rx-nostr
Version:
A library based on RxJS, which allows Nostr applications to easily communicate with relays.
1 lines • 333 kB
Source Map (JSON)
{"version":3,"file":"rx-nostr.cjs","sources":["../src/error.ts","../src/utils/config.ts","../src/nostr/event.ts","../src/utils/inline-throw.ts","../src/config/signer.ts","../src/config/config.ts","../src/config/verifier.ts","../src/lazy-filter.ts","../src/nostr/nip11.ts","../src/utils/inline-try.ts","../src/utils/normalize-url.ts","../src/utils/url-map.ts","../src/nip11.ts","../../../node_modules/@noble/hashes/esm/_assert.js","../../../node_modules/@noble/hashes/esm/utils.js","../../../node_modules/@scure/base/lib/esm/index.js","../src/nostr/bech32.ts","../src/nostr/filter.ts","../src/nostr/nip40.ts","../node_modules/tslib/tslib.es6.mjs","../node_modules/rxjs/dist/esm5/internal/util/isFunction.js","../node_modules/rxjs/dist/esm5/internal/util/createErrorClass.js","../node_modules/rxjs/dist/esm5/internal/util/UnsubscriptionError.js","../node_modules/rxjs/dist/esm5/internal/util/arrRemove.js","../node_modules/rxjs/dist/esm5/internal/Subscription.js","../node_modules/rxjs/dist/esm5/internal/config.js","../node_modules/rxjs/dist/esm5/internal/scheduler/timeoutProvider.js","../node_modules/rxjs/dist/esm5/internal/util/reportUnhandledError.js","../node_modules/rxjs/dist/esm5/internal/util/noop.js","../node_modules/rxjs/dist/esm5/internal/util/errorContext.js","../node_modules/rxjs/dist/esm5/internal/Subscriber.js","../node_modules/rxjs/dist/esm5/internal/symbol/observable.js","../node_modules/rxjs/dist/esm5/internal/util/identity.js","../node_modules/rxjs/dist/esm5/internal/util/pipe.js","../node_modules/rxjs/dist/esm5/internal/Observable.js","../node_modules/rxjs/dist/esm5/internal/util/lift.js","../node_modules/rxjs/dist/esm5/internal/operators/OperatorSubscriber.js","../node_modules/rxjs/dist/esm5/internal/util/ObjectUnsubscribedError.js","../node_modules/rxjs/dist/esm5/internal/Subject.js","../node_modules/rxjs/dist/esm5/internal/BehaviorSubject.js","../node_modules/rxjs/dist/esm5/internal/scheduler/dateTimestampProvider.js","../node_modules/rxjs/dist/esm5/internal/scheduler/Action.js","../node_modules/rxjs/dist/esm5/internal/scheduler/intervalProvider.js","../node_modules/rxjs/dist/esm5/internal/scheduler/AsyncAction.js","../node_modules/rxjs/dist/esm5/internal/Scheduler.js","../node_modules/rxjs/dist/esm5/internal/scheduler/AsyncScheduler.js","../node_modules/rxjs/dist/esm5/internal/scheduler/async.js","../node_modules/rxjs/dist/esm5/internal/observable/empty.js","../node_modules/rxjs/dist/esm5/internal/util/isScheduler.js","../node_modules/rxjs/dist/esm5/internal/util/args.js","../node_modules/rxjs/dist/esm5/internal/util/isArrayLike.js","../node_modules/rxjs/dist/esm5/internal/util/isPromise.js","../node_modules/rxjs/dist/esm5/internal/util/isInteropObservable.js","../node_modules/rxjs/dist/esm5/internal/util/isAsyncIterable.js","../node_modules/rxjs/dist/esm5/internal/util/throwUnobservableError.js","../node_modules/rxjs/dist/esm5/internal/symbol/iterator.js","../node_modules/rxjs/dist/esm5/internal/util/isIterable.js","../node_modules/rxjs/dist/esm5/internal/util/isReadableStreamLike.js","../node_modules/rxjs/dist/esm5/internal/observable/innerFrom.js","../node_modules/rxjs/dist/esm5/internal/util/executeSchedule.js","../node_modules/rxjs/dist/esm5/internal/operators/observeOn.js","../node_modules/rxjs/dist/esm5/internal/operators/subscribeOn.js","../node_modules/rxjs/dist/esm5/internal/scheduled/scheduleObservable.js","../node_modules/rxjs/dist/esm5/internal/scheduled/schedulePromise.js","../node_modules/rxjs/dist/esm5/internal/scheduled/scheduleArray.js","../node_modules/rxjs/dist/esm5/internal/scheduled/scheduleIterable.js","../node_modules/rxjs/dist/esm5/internal/scheduled/scheduleAsyncIterable.js","../node_modules/rxjs/dist/esm5/internal/scheduled/scheduleReadableStreamLike.js","../node_modules/rxjs/dist/esm5/internal/scheduled/scheduled.js","../node_modules/rxjs/dist/esm5/internal/observable/from.js","../node_modules/rxjs/dist/esm5/internal/observable/of.js","../node_modules/rxjs/dist/esm5/internal/util/EmptyError.js","../node_modules/rxjs/dist/esm5/internal/firstValueFrom.js","../node_modules/rxjs/dist/esm5/internal/util/isDate.js","../node_modules/rxjs/dist/esm5/internal/operators/timeout.js","../node_modules/rxjs/dist/esm5/internal/operators/map.js","../node_modules/rxjs/dist/esm5/internal/util/mapOneOrManyArgs.js","../node_modules/rxjs/dist/esm5/internal/util/argsArgArrayOrObject.js","../node_modules/rxjs/dist/esm5/internal/util/createObject.js","../node_modules/rxjs/dist/esm5/internal/observable/combineLatest.js","../node_modules/rxjs/dist/esm5/internal/operators/mergeInternals.js","../node_modules/rxjs/dist/esm5/internal/operators/mergeMap.js","../node_modules/rxjs/dist/esm5/internal/operators/mergeAll.js","../node_modules/rxjs/dist/esm5/internal/operators/concatAll.js","../node_modules/rxjs/dist/esm5/internal/observable/concat.js","../node_modules/rxjs/dist/esm5/internal/observable/timer.js","../node_modules/rxjs/dist/esm5/internal/observable/merge.js","../node_modules/rxjs/dist/esm5/internal/operators/filter.js","../node_modules/rxjs/dist/esm5/internal/operators/catchError.js","../node_modules/rxjs/dist/esm5/internal/operators/scanInternals.js","../node_modules/rxjs/dist/esm5/internal/operators/defaultIfEmpty.js","../node_modules/rxjs/dist/esm5/internal/operators/take.js","../node_modules/rxjs/dist/esm5/internal/operators/ignoreElements.js","../node_modules/rxjs/dist/esm5/internal/operators/mapTo.js","../node_modules/rxjs/dist/esm5/internal/operators/delayWhen.js","../node_modules/rxjs/dist/esm5/internal/operators/delay.js","../node_modules/rxjs/dist/esm5/internal/operators/distinct.js","../node_modules/rxjs/dist/esm5/internal/operators/distinctUntilChanged.js","../node_modules/rxjs/dist/esm5/internal/operators/throwIfEmpty.js","../node_modules/rxjs/dist/esm5/internal/operators/finalize.js","../node_modules/rxjs/dist/esm5/internal/operators/first.js","../node_modules/rxjs/dist/esm5/internal/operators/groupBy.js","../node_modules/rxjs/dist/esm5/internal/operators/scan.js","../node_modules/rxjs/dist/esm5/internal/operators/switchMap.js","../node_modules/rxjs/dist/esm5/internal/operators/switchAll.js","../node_modules/rxjs/dist/esm5/internal/operators/takeUntil.js","../node_modules/rxjs/dist/esm5/internal/operators/takeWhile.js","../node_modules/rxjs/dist/esm5/internal/operators/tap.js","../src/operator.ts","../src/connection/auth.ts","../src/connection/utils.ts","../src/connection/publish.ts","../src/websocket.ts","../src/connection/relay.ts","../src/connection/subscribe.ts","../src/connection/connection.ts","../src/utils/array-operation.ts","../src/rx-nostr/utils.ts","../src/rx-nostr/rx-nostr.ts","../src/rx-nostr/rx-req.ts","../src/index.ts"],"sourcesContent":["export abstract class RxNostrError extends Error {}\n\n/**\n * This is thrown when WebSocket connection is closed unexpectedly.\n * You may see them in a stream made by `rxNostr.createAllErrorObservable()`.\n */\nexport class RxNostrWebSocketError extends RxNostrError {\n constructor(public code?: number) {\n super(\n `RxNostrWebSocketError: WebSocket was closed with code ${code} by relay.`,\n );\n this.name = \"RxNostrWebSocketError\";\n }\n}\n\n/**\n * This is usually thrown when rx-nostr is used incorrectly (or possibly rx-nostr has a bug).\n * Please fix your program according to the message.\n *\n * Normally, you should not catch the exception.\n */\nexport class RxNostrInvalidUsageError extends RxNostrError {\n constructor(message: string) {\n super(`RxNostrInvalidUsageError: ${message}`);\n this.name = \"RxNostrInvalidUsageError\";\n }\n}\n\n/**\n * This is usually thrown when rx-nostr is used properly\n * but an error occurs due to external environmental causes.\n */\nexport class RxNostrEnvironmentError extends RxNostrError {\n constructor(message: string) {\n super(`RxNostrEnvironmentError: ${message}`);\n this.name = \"RxNostrEnvironmentError\";\n }\n}\n\n/**\n * This is thrown only by a bug inside rx-nostr.\n *\n * Normally, you should not catch the exception.\n */\nexport class RxNostrLogicError extends RxNostrError {\n constructor() {\n super(\n \"RxNostrLogicError: This is rx-nostr's internal bug. Please report to the author of the library.\",\n );\n this.name = \"RxNostrLogicError\";\n }\n}\n\n/**\n * This is thrown when you attempt to access a disposed rx-nostr's resource.\n *\n * Normally, you should not catch the exception.\n */\nexport class RxNostrAlreadyDisposedError extends RxNostrError {\n constructor() {\n super(\n \"RxNostrAlreadyDisposedError: Attempted to access a disposed resource.\",\n );\n this.name = \"RxNostrAlreadyDisposedError\";\n }\n}\n","import { RxNostrLogicError } from \"../error.js\";\nimport { EMPTY, Empty } from \"./empty.js\";\nimport type { OptionalPart, RequiredPart } from \"./types.js\";\n\ntype FilledConfig<C, D> = RequiredPart<C> & {\n [K in keyof OptionalPart<C>]: K extends keyof D ? NonNullable<C[K]> : C[K];\n};\n\nexport const config = <C>() => ({\n default: <const D extends Partial<OptionalPart<C>>>(factory: () => D) => {\n const defaults = factory();\n let inputs: C | Empty = EMPTY;\n\n return {\n set(config: C) {\n inputs = config;\n },\n get<const K extends keyof FilledConfig<C, D>>(\n key: K,\n ): FilledConfig<C, D>[K] {\n if (inputs === EMPTY) {\n throw new RxNostrLogicError();\n }\n\n return (inputs[key] ?? defaults[key]) as FilledConfig<C, D>[K];\n },\n };\n },\n});\n\nexport const fill = <\n C,\n const D extends Partial<OptionalPart<C>> = Partial<OptionalPart<C>>,\n>(\n config: C,\n defaults: D,\n): FilledConfig<C, D> =>\n ({\n ...defaults,\n ...config,\n }) as FilledConfig<C, D>;\n","import * as Nostr from \"nostr-typedef\";\n\nexport function ensureEventFields(\n event: Partial<Nostr.Event>,\n): event is Nostr.Event {\n if (typeof event.id !== \"string\") return false;\n if (typeof event.sig !== \"string\") return false;\n if (typeof event.kind !== \"number\") return false;\n if (typeof event.pubkey !== \"string\") return false;\n if (typeof event.content !== \"string\") return false;\n if (typeof event.created_at !== \"number\") return false;\n\n if (!Array.isArray(event.tags)) return false;\n for (let i = 0; i < event.tags.length; i++) {\n const tag = event.tags[i];\n if (!Array.isArray(tag)) return false;\n for (let j = 0; j < tag.length; j++) {\n if (typeof tag[j] === \"object\") return false;\n }\n }\n\n return true;\n}\n\n/** Return an event that has earlier `created_at`. */\nexport function earlierEvent(a: Nostr.Event, b: Nostr.Event): Nostr.Event {\n return compareEvents(a, b) < 0 ? a : b;\n}\n\n/** Return an event that has later `created_at`. */\nexport function laterEvent(a: Nostr.Event, b: Nostr.Event): Nostr.Event {\n return compareEvents(a, b) < 0 ? b : a;\n}\n\n/** Sort key function to sort events based on `created_at`. */\nexport function compareEvents(a: Nostr.Event, b: Nostr.Event): number {\n if (a.id === b.id) {\n return 0;\n }\n\n return a.created_at < b.created_at ||\n // https://github.com/nostr-protocol/nips/blob/master/16.md#replaceable-events\n (a.created_at === b.created_at && a.id < b.id)\n ? -1\n : 1;\n}\n","export function inlineThrow(err: Error): never {\n throw err;\n}\n","import * as Nostr from \"nostr-typedef\";\n\nimport { RxNostrEnvironmentError, RxNostrInvalidUsageError } from \"../error.js\";\nimport { ensureEventFields } from \"../nostr/event.js\";\nimport { inlineThrow } from \"../utils/inline-throw.js\";\n\nexport interface EventSigner {\n signEvent<K extends number>(\n params: Nostr.EventParameters<K>,\n ): Promise<Nostr.Event<K>>;\n getPublicKey(): Promise<string>;\n}\n\nexport interface EventSignerOptions {\n /** If set, the set tags is appended to the end of the given event's tags on signing. */\n tags?: Nostr.Tag.Any[];\n}\n\nexport function nip07Signer(options?: EventSignerOptions): EventSigner {\n return {\n async signEvent<K extends number>(\n params: Nostr.EventParameters<K>,\n ): Promise<Nostr.Event<K>> {\n const event = {\n ...params,\n pubkey:\n params.pubkey ??\n (await window?.nostr?.getPublicKey()) ??\n inlineThrow(\n new RxNostrEnvironmentError(\n \"window.nostr.getPublicKey() is not found\",\n ),\n ),\n tags: [...(params.tags ?? []), ...(options?.tags ?? [])],\n created_at: params.created_at ?? Math.floor(Date.now() / 1000),\n };\n\n if (ensureEventFields(event)) {\n return event;\n }\n\n return (\n (await window?.nostr?.signEvent(event)) ??\n inlineThrow(\n new RxNostrEnvironmentError(\"window.nostr.signEvent() is not found\"),\n )\n );\n },\n getPublicKey() {\n return (\n window?.nostr?.getPublicKey() ??\n inlineThrow(\n new RxNostrEnvironmentError(\n \"window.nostr.getPublicKey() is not found\",\n ),\n )\n );\n },\n };\n}\n\nexport function noopSigner(): EventSigner {\n return {\n async signEvent<K extends number>(params: Nostr.EventParameters<K>) {\n return params as Nostr.Event<K>;\n },\n async getPublicKey() {\n throw new RxNostrInvalidUsageError(\"noopSigner cannot calculate pubkey.\");\n },\n };\n}\n","import { fill } from \"../utils/config.js\";\nimport type { IWebSocketConstructor } from \"../websocket.js\";\nimport { AuthenticatorConfig } from \"./authenticator.js\";\nimport { EventSigner, nip07Signer } from \"./signer.js\";\nimport { EventVerifier } from \"./verifier.js\";\n\nexport const makeRxNostrConfig = (config: RxNostrConfig) =>\n fill(config, {\n signer: nip07Signer(),\n connectionStrategy: \"lazy\",\n retry: {\n strategy: \"exponential\",\n maxCount: 5,\n initialDelay: 1000,\n },\n disconnectTimeout: 10000,\n eoseTimeout: 30 * 1000,\n okTimeout: 30 * 1000,\n authTimeout: 30 * 1000,\n skipVerify: false,\n skipValidateFilterMatching: false,\n skipExpirationCheck: false,\n skipFetchNip11: false,\n });\nexport type FilledRxNostrConfig = ReturnType<typeof makeRxNostrConfig>;\n\n/**\n * Configuration object for a RxNostr instance.\n */\nexport interface RxNostrConfig {\n /**\n * Default signer, which is used to convert event parameters into signed event.\n */\n signer?: EventSigner;\n /**\n * Default verifier, which is used to verify event's signature.\n */\n verifier: EventVerifier;\n authenticator?:\n | AuthenticatorConfig\n | ((relay: string) => AuthenticatorConfig);\n\n /**\n * Connection strategy for default relays.\n */\n connectionStrategy?: ConnectionStrategy;\n\n /**\n * Auto reconnection strategy.\n */\n retry?: RetryConfig;\n\n /**\n * How long temporary relay connections should be held open when no longer used.\n * Applies to default relays when connectionStrategy is set to \"lazy\"\n * @default 10000\n */\n disconnectTimeout?: number;\n\n /**\n * Specify how long rx-nostr waits for EOSE messages in `use()` following backward strategy (milliseconds).\n *\n * If EOSE doesn't come after waiting for this amount of time,\n * rx-nostr is considered to get EOSE.\n */\n eoseTimeout?: number;\n /**\n * Specify how long rx-nostr waits for OK messages in `send()` (milliseconds).\n *\n * If OK doesn't come after waiting for this amount of time,\n * rx-nostr stops listening OK and the Observable come from `send()` finishes with TimeoutError.\n */\n okTimeout?: number;\n authTimeout?: number;\n /**\n * If true, skip filtering EVENTs based on signature verification.\n */\n skipVerify?: boolean;\n /**\n * If true, skip filtering EVENTs based on matching with REQ filter.\n */\n skipValidateFilterMatching?: boolean;\n /**\n * If true, skip automatic expiration check based on NIP-40.\n */\n skipExpirationCheck?: boolean;\n /**\n * If true, skip automatic fetching NIP-11 relay information.\n */\n skipFetchNip11?: boolean;\n /**\n * Optional. For environments where `WebSocket` doesn't exist in `globalThis` such as Node.js.\n */\n websocketCtor?: IWebSocketConstructor;\n}\n\n/**\n * Auto reconnection strategy.\n *\n * `strategy` can be one of the followings:\n *\n * - `\"exponential\"`: Exponential backoff and jitter strategy.\n * - `\"linear\"`: Retry at regular intervals.\n * - `\"immediately\"`: Retry immediately.\n * - `\"off\"`: Won't retry.\n *\n * Options:\n *\n * - `maxCount` specifies the maximum number of consecutive retry attempts.\n * - `polite` specifies whether to retry only if the relay is alive.\n * If true, rx-nostr doesn't try to retry against a relay doesn't respond to the first request.\n */\nexport type RetryConfig =\n | {\n strategy: \"exponential\";\n maxCount: number;\n initialDelay: number;\n polite?: boolean;\n }\n | {\n strategy: \"linear\";\n maxCount: number;\n interval: number;\n polite?: boolean;\n }\n | {\n strategy: \"immediately\";\n maxCount: number;\n polite?: boolean;\n }\n | {\n strategy: \"off\";\n };\n\n/**\n * Connection strategy for default relays.\n *\n * - `\"lazy\"`: Connect when needed, and disconnect when unneeded.\n * - `\"lazy-keep\"`: Connect when needed, when the relay gets to be non-default and it is unneeded.\n * - `\"aggressive\"`: Connect immediately, and disconnect when the relay gets to be non-default and it is unneeded.\n */\nexport type ConnectionStrategy = \"lazy\" | \"lazy-keep\" | \"aggressive\";\n","import * as Nostr from \"nostr-typedef\";\n\nexport interface EventVerifier {\n (params: Nostr.Event): Promise<boolean>;\n}\n\nexport const noopVerifier: EventVerifier = async () => true;\n\nexport const emptyVerifier: EventVerifier = async () => {\n throw new Error(\n \"You must give some verifier to createRxNostr(). In most cases, @rx-nostr/crypto packages will help you.\",\n );\n};\n","import * as Nostr from \"nostr-typedef\";\n\nimport { LazyFilter } from \"./packet.js\";\n\n/**\n * Evaluate one or more `LazyFilter`s and return `Nostr.Filter[]`.\n */\nexport function evalFilters(\n filters: LazyFilter | LazyFilter[],\n): Nostr.Filter[] {\n if (\"length\" in filters) {\n return filters.map(evalFilter);\n } else {\n return [evalFilter(filters)];\n }\n}\n\nfunction evalFilter(filter: LazyFilter): Nostr.Filter {\n return {\n ...filter,\n since: filter.since ? evalLazyNumber(filter.since) : undefined,\n until: filter.until ? evalLazyNumber(filter.until) : undefined,\n };\n}\n\nfunction evalLazyNumber(lazyNumber: number | (() => number)): number {\n return typeof lazyNumber === \"number\" ? lazyNumber : lazyNumber();\n}\n","import * as Nostr from \"nostr-typedef\";\n\n/**\n * Fetch relay's information based on [NIP-11](https://github.com/nostr-protocol/nips/blob/master/11.md).\n */\nexport async function fetchRelayInfo(\n url: string,\n): Promise<Nostr.Nip11.RelayInfo> {\n try {\n const u = new URL(url);\n u.protocol = u.protocol.replace(/^ws(s?):/, \"http$1:\");\n\n const res = await fetch(u.toString(), {\n headers: { Accept: \"application/nostr+json\" },\n });\n return await res.json();\n } catch {\n return {};\n }\n}\n","export function inlineTry<T, U>(\n f: () => T,\n g: U | ((err: unknown) => U),\n): T | U {\n try {\n return f();\n } catch (err) {\n if (g instanceof Function) {\n return g(err);\n } else {\n return g;\n }\n }\n}\n","import { inlineTry } from \"./inline-try.js\";\n\nexport function normalizeRelayUrl(url: string) {\n let o = \"\";\n\n try {\n o = url.trim();\n\n const u = new URL(o);\n\n u.hash = \"\";\n u.pathname = inlineTry(() => decodeURI(u.pathname), u.pathname);\n u.pathname = u.pathname.replace(/\\/$/, \"\");\n u.hostname = u.hostname.replace(/\\.$/, \"\");\n u.searchParams.sort();\n u.search = inlineTry(() => decodeURIComponent(u.search), u.search);\n\n let s = u.toString();\n if (!u.search) {\n s = s.replace(/\\/$/, \"\");\n }\n\n return s;\n } catch {\n return o;\n }\n}\n","import { normalizeRelayUrl } from \"./normalize-url.js\";\n\nexport class UrlMap<T> extends Map<string, T> {\n constructor(obj?: Record<string, T>) {\n super();\n\n if (!obj) {\n return;\n }\n\n for (const [url, v] of Object.entries(obj)) {\n this.set(normalizeRelayUrl(url), v);\n }\n }\n get(url: string) {\n return super.get(normalizeRelayUrl(url));\n }\n getMany(urls: string[]) {\n const vs: T[] = [];\n\n for (const url of new Set(urls.map(normalizeRelayUrl))) {\n const v = this.get(url);\n if (v !== undefined) {\n vs.push(v);\n }\n }\n\n return vs;\n }\n set(url: string, v: T) {\n return super.set(normalizeRelayUrl(url), v);\n }\n has(url: string): boolean {\n return super.has(normalizeRelayUrl(url));\n }\n delete(url: string) {\n return super.delete(normalizeRelayUrl(url));\n }\n toObject(): Record<string, T> {\n const obj: Record<string, T> = {};\n\n for (const [url, v] of this.entries()) {\n obj[url] = v;\n }\n\n return obj;\n }\n toKeys(): string[] {\n return [...super.keys()];\n }\n toValues(): T[] {\n return [...super.values()];\n }\n copy() {\n return new UrlMap(this.toObject());\n }\n}\n","import * as Nostr from \"nostr-typedef\";\n\nimport { fetchRelayInfo } from \"./nostr/nip11.js\";\nimport { UrlMap } from \"./utils/url-map.js\";\n\n/**\n * This is used by rx-nostr to access NIP-11 relay information.\n * rx-nostr works adaptively to the [`limitation`](https://github.com/nostr-protocol/nips/blob/master/11.md#server-limitations) defined by NIP-11.\n *\n * If you `set()` or `setDefault()` NIP-11 relay information in advance,\n * rx-nostr will use them instead of fetching even if `skipFetchNip11` is enabled.\n */\nexport class Nip11Registry {\n private static cache = new UrlMap<\n Promise<Nostr.Nip11.RelayInfo> | Nostr.Nip11.RelayInfo\n >();\n private static default: Nostr.Nip11.RelayInfo = {};\n\n static async getValue<T>(\n url: string,\n getter: (data: Nostr.Nip11.RelayInfo) => T,\n options?: {\n skipFetch?: boolean;\n skipCache?: boolean;\n },\n ): Promise<T> {\n if (!options?.skipCache) {\n const data = await this.cache.get(url);\n if (data) {\n return getter(data);\n }\n }\n if (!options?.skipFetch) {\n const data = await this.fetch(url);\n if (data) {\n return getter(data);\n }\n }\n\n return getter(this.default);\n }\n\n /**\n * Return cached or `set()`'ed NIP-11 information.\n */\n static get(url: string): Nostr.Nip11.RelayInfo | undefined {\n const v = this.cache.get(url);\n if (v && !(v instanceof Promise)) {\n return v;\n } else {\n return undefined;\n }\n }\n\n /**\n * Cache fetched information then return it.\n */\n static async fetch(url: string) {\n const promise = fetchRelayInfo(url);\n\n this.cache.set(url, promise);\n promise.then((v) => {\n this.cache.set(url, v);\n });\n\n return promise;\n }\n\n /**\n * Return cached or `set()`'ed NIP-11 information,\n * or cache fetched information then return it.\n */\n static async getOrFetch(url: string): Promise<Nostr.Nip11.RelayInfo> {\n return this.cache.get(url) ?? this.fetch(url);\n }\n\n /**\n * Set NIP-11 information manually for given relay URL.\n */\n static set(url: string, nip11: Nostr.Nip11.RelayInfo) {\n this.cache.set(url, nip11);\n }\n\n /**\n * Get NIP-11 information for fallback.\n */\n static getDefault(): Nostr.Nip11.RelayInfo {\n return this.default;\n }\n\n /**\n * Set NIP-11 information for fallback.\n */\n static setDefault(nip11: Nostr.Nip11.RelayInfo) {\n this.default = nip11;\n }\n\n /**\n * Forget cached NIP-11 information for given relay URL.\n */\n static forget(url: string) {\n this.cache.delete(url);\n }\n\n /**\n * Forget all cached NIP-11 information.\n *\n * This doesn't erase `setDefault()`'ed value.\n * If you want it, you can `setDefault({})` instead.\n */\n static forgetAll() {\n this.cache.clear();\n }\n}\n","function number(n) {\n if (!Number.isSafeInteger(n) || n < 0)\n throw new Error(`positive integer expected, not ${n}`);\n}\nfunction bool(b) {\n if (typeof b !== 'boolean')\n throw new Error(`boolean expected, not ${b}`);\n}\n// copied from utils\nexport function isBytes(a) {\n return (a instanceof Uint8Array ||\n (a != null && typeof a === 'object' && a.constructor.name === 'Uint8Array'));\n}\nfunction bytes(b, ...lengths) {\n if (!isBytes(b))\n throw new Error('Uint8Array expected');\n if (lengths.length > 0 && !lengths.includes(b.length))\n throw new Error(`Uint8Array expected of length ${lengths}, not of length=${b.length}`);\n}\nfunction hash(h) {\n if (typeof h !== 'function' || typeof h.create !== 'function')\n throw new Error('Hash should be wrapped by utils.wrapConstructor');\n number(h.outputLen);\n number(h.blockLen);\n}\nfunction exists(instance, checkFinished = true) {\n if (instance.destroyed)\n throw new Error('Hash instance has been destroyed');\n if (checkFinished && instance.finished)\n throw new Error('Hash#digest() has already been called');\n}\nfunction output(out, instance) {\n bytes(out);\n const min = instance.outputLen;\n if (out.length < min) {\n throw new Error(`digestInto() expects output buffer of length at least ${min}`);\n }\n}\nexport { number, bool, bytes, hash, exists, output };\nconst assert = { number, bool, bytes, hash, exists, output };\nexport default assert;\n//# sourceMappingURL=_assert.js.map","/*! noble-hashes - MIT License (c) 2022 Paul Miller (paulmillr.com) */\n// We use WebCrypto aka globalThis.crypto, which exists in browsers and node.js 16+.\n// node.js versions earlier than v19 don't declare it in global scope.\n// For node.js, package.json#exports field mapping rewrites import\n// from `crypto` to `cryptoNode`, which imports native module.\n// Makes the utils un-importable in browsers without a bundler.\n// Once node.js 18 is deprecated (2025-04-30), we can just drop the import.\nimport { crypto } from '@noble/hashes/crypto';\nimport { bytes as abytes } from './_assert.js';\n// export { isBytes } from './_assert.js';\n// We can't reuse isBytes from _assert, because somehow this causes huge perf issues\nexport function isBytes(a) {\n return (a instanceof Uint8Array ||\n (a != null && typeof a === 'object' && a.constructor.name === 'Uint8Array'));\n}\n// Cast array to different type\nexport const u8 = (arr) => new Uint8Array(arr.buffer, arr.byteOffset, arr.byteLength);\nexport const u32 = (arr) => new Uint32Array(arr.buffer, arr.byteOffset, Math.floor(arr.byteLength / 4));\n// Cast array to view\nexport const createView = (arr) => new DataView(arr.buffer, arr.byteOffset, arr.byteLength);\n// The rotate right (circular right shift) operation for uint32\nexport const rotr = (word, shift) => (word << (32 - shift)) | (word >>> shift);\n// The rotate left (circular left shift) operation for uint32\nexport const rotl = (word, shift) => (word << shift) | ((word >>> (32 - shift)) >>> 0);\nexport const isLE = new Uint8Array(new Uint32Array([0x11223344]).buffer)[0] === 0x44;\n// The byte swap operation for uint32\nexport const byteSwap = (word) => ((word << 24) & 0xff000000) |\n ((word << 8) & 0xff0000) |\n ((word >>> 8) & 0xff00) |\n ((word >>> 24) & 0xff);\n// Conditionally byte swap if on a big-endian platform\nexport const byteSwapIfBE = isLE ? (n) => n : (n) => byteSwap(n);\n// In place byte swap for Uint32Array\nexport function byteSwap32(arr) {\n for (let i = 0; i < arr.length; i++) {\n arr[i] = byteSwap(arr[i]);\n }\n}\n// Array where index 0xf0 (240) is mapped to string 'f0'\nconst hexes = /* @__PURE__ */ Array.from({ length: 256 }, (_, i) => i.toString(16).padStart(2, '0'));\n/**\n * @example bytesToHex(Uint8Array.from([0xca, 0xfe, 0x01, 0x23])) // 'cafe0123'\n */\nexport function bytesToHex(bytes) {\n abytes(bytes);\n // pre-caching improves the speed 6x\n let hex = '';\n for (let i = 0; i < bytes.length; i++) {\n hex += hexes[bytes[i]];\n }\n return hex;\n}\n// We use optimized technique to convert hex string to byte array\nconst asciis = { _0: 48, _9: 57, _A: 65, _F: 70, _a: 97, _f: 102 };\nfunction asciiToBase16(char) {\n if (char >= asciis._0 && char <= asciis._9)\n return char - asciis._0;\n if (char >= asciis._A && char <= asciis._F)\n return char - (asciis._A - 10);\n if (char >= asciis._a && char <= asciis._f)\n return char - (asciis._a - 10);\n return;\n}\n/**\n * @example hexToBytes('cafe0123') // Uint8Array.from([0xca, 0xfe, 0x01, 0x23])\n */\nexport function hexToBytes(hex) {\n if (typeof hex !== 'string')\n throw new Error('hex string expected, got ' + typeof hex);\n const hl = hex.length;\n const al = hl / 2;\n if (hl % 2)\n throw new Error('padded hex string expected, got unpadded hex of length ' + hl);\n const array = new Uint8Array(al);\n for (let ai = 0, hi = 0; ai < al; ai++, hi += 2) {\n const n1 = asciiToBase16(hex.charCodeAt(hi));\n const n2 = asciiToBase16(hex.charCodeAt(hi + 1));\n if (n1 === undefined || n2 === undefined) {\n const char = hex[hi] + hex[hi + 1];\n throw new Error('hex string expected, got non-hex character \"' + char + '\" at index ' + hi);\n }\n array[ai] = n1 * 16 + n2;\n }\n return array;\n}\n// There is no setImmediate in browser and setTimeout is slow.\n// call of async fn will return Promise, which will be fullfiled only on\n// next scheduler queue processing step and this is exactly what we need.\nexport const nextTick = async () => { };\n// Returns control to thread each 'tick' ms to avoid blocking\nexport async function asyncLoop(iters, tick, cb) {\n let ts = Date.now();\n for (let i = 0; i < iters; i++) {\n cb(i);\n // Date.now() is not monotonic, so in case if clock goes backwards we return return control too\n const diff = Date.now() - ts;\n if (diff >= 0 && diff < tick)\n continue;\n await nextTick();\n ts += diff;\n }\n}\n/**\n * @example utf8ToBytes('abc') // new Uint8Array([97, 98, 99])\n */\nexport function utf8ToBytes(str) {\n if (typeof str !== 'string')\n throw new Error(`utf8ToBytes expected string, got ${typeof str}`);\n return new Uint8Array(new TextEncoder().encode(str)); // https://bugzil.la/1681809\n}\n/**\n * Normalizes (non-hex) string or Uint8Array to Uint8Array.\n * Warning: when Uint8Array is passed, it would NOT get copied.\n * Keep in mind for future mutable operations.\n */\nexport function toBytes(data) {\n if (typeof data === 'string')\n data = utf8ToBytes(data);\n abytes(data);\n return data;\n}\n/**\n * Copies several Uint8Arrays into one.\n */\nexport function concatBytes(...arrays) {\n let sum = 0;\n for (let i = 0; i < arrays.length; i++) {\n const a = arrays[i];\n abytes(a);\n sum += a.length;\n }\n const res = new Uint8Array(sum);\n for (let i = 0, pad = 0; i < arrays.length; i++) {\n const a = arrays[i];\n res.set(a, pad);\n pad += a.length;\n }\n return res;\n}\n// For runtime check if class implements interface\nexport class Hash {\n // Safe version that clones internal state\n clone() {\n return this._cloneInto();\n }\n}\nconst toStr = {}.toString;\nexport function checkOpts(defaults, opts) {\n if (opts !== undefined && toStr.call(opts) !== '[object Object]')\n throw new Error('Options should be object or undefined');\n const merged = Object.assign(defaults, opts);\n return merged;\n}\nexport function wrapConstructor(hashCons) {\n const hashC = (msg) => hashCons().update(toBytes(msg)).digest();\n const tmp = hashCons();\n hashC.outputLen = tmp.outputLen;\n hashC.blockLen = tmp.blockLen;\n hashC.create = () => hashCons();\n return hashC;\n}\nexport function wrapConstructorWithOpts(hashCons) {\n const hashC = (msg, opts) => hashCons(opts).update(toBytes(msg)).digest();\n const tmp = hashCons({});\n hashC.outputLen = tmp.outputLen;\n hashC.blockLen = tmp.blockLen;\n hashC.create = (opts) => hashCons(opts);\n return hashC;\n}\nexport function wrapXOFConstructorWithOpts(hashCons) {\n const hashC = (msg, opts) => hashCons(opts).update(toBytes(msg)).digest();\n const tmp = hashCons({});\n hashC.outputLen = tmp.outputLen;\n hashC.blockLen = tmp.blockLen;\n hashC.create = (opts) => hashCons(opts);\n return hashC;\n}\n/**\n * Secure PRNG. Uses `crypto.getRandomValues`, which defers to OS.\n */\nexport function randomBytes(bytesLength = 32) {\n if (crypto && typeof crypto.getRandomValues === 'function') {\n return crypto.getRandomValues(new Uint8Array(bytesLength));\n }\n throw new Error('crypto.getRandomValues must be defined');\n}\n//# sourceMappingURL=utils.js.map","/*! scure-base - MIT License (c) 2022 Paul Miller (paulmillr.com) */\n// Utilities\n/**\n * @__NO_SIDE_EFFECTS__\n */\nexport function assertNumber(n) {\n if (!Number.isSafeInteger(n))\n throw new Error(`Wrong integer: ${n}`);\n}\nfunction isBytes(a) {\n return (a instanceof Uint8Array ||\n (a != null && typeof a === 'object' && a.constructor.name === 'Uint8Array'));\n}\n/**\n * @__NO_SIDE_EFFECTS__\n */\nfunction chain(...args) {\n const id = (a) => a;\n // Wrap call in closure so JIT can inline calls\n const wrap = (a, b) => (c) => a(b(c));\n // Construct chain of args[-1].encode(args[-2].encode([...]))\n const encode = args.map((x) => x.encode).reduceRight(wrap, id);\n // Construct chain of args[0].decode(args[1].decode(...))\n const decode = args.map((x) => x.decode).reduce(wrap, id);\n return { encode, decode };\n}\n/**\n * Encodes integer radix representation to array of strings using alphabet and back\n * @__NO_SIDE_EFFECTS__\n */\nfunction alphabet(alphabet) {\n return {\n encode: (digits) => {\n if (!Array.isArray(digits) || (digits.length && typeof digits[0] !== 'number'))\n throw new Error('alphabet.encode input should be an array of numbers');\n return digits.map((i) => {\n assertNumber(i);\n if (i < 0 || i >= alphabet.length)\n throw new Error(`Digit index outside alphabet: ${i} (alphabet: ${alphabet.length})`);\n return alphabet[i];\n });\n },\n decode: (input) => {\n if (!Array.isArray(input) || (input.length && typeof input[0] !== 'string'))\n throw new Error('alphabet.decode input should be array of strings');\n return input.map((letter) => {\n if (typeof letter !== 'string')\n throw new Error(`alphabet.decode: not string element=${letter}`);\n const index = alphabet.indexOf(letter);\n if (index === -1)\n throw new Error(`Unknown letter: \"${letter}\". Allowed: ${alphabet}`);\n return index;\n });\n },\n };\n}\n/**\n * @__NO_SIDE_EFFECTS__\n */\nfunction join(separator = '') {\n if (typeof separator !== 'string')\n throw new Error('join separator should be string');\n return {\n encode: (from) => {\n if (!Array.isArray(from) || (from.length && typeof from[0] !== 'string'))\n throw new Error('join.encode input should be array of strings');\n for (let i of from)\n if (typeof i !== 'string')\n throw new Error(`join.encode: non-string input=${i}`);\n return from.join(separator);\n },\n decode: (to) => {\n if (typeof to !== 'string')\n throw new Error('join.decode input should be string');\n return to.split(separator);\n },\n };\n}\n/**\n * Pad strings array so it has integer number of bits\n * @__NO_SIDE_EFFECTS__\n */\nfunction padding(bits, chr = '=') {\n assertNumber(bits);\n if (typeof chr !== 'string')\n throw new Error('padding chr should be string');\n return {\n encode(data) {\n if (!Array.isArray(data) || (data.length && typeof data[0] !== 'string'))\n throw new Error('padding.encode input should be array of strings');\n for (let i of data)\n if (typeof i !== 'string')\n throw new Error(`padding.encode: non-string input=${i}`);\n while ((data.length * bits) % 8)\n data.push(chr);\n return data;\n },\n decode(input) {\n if (!Array.isArray(input) || (input.length && typeof input[0] !== 'string'))\n throw new Error('padding.encode input should be array of strings');\n for (let i of input)\n if (typeof i !== 'string')\n throw new Error(`padding.decode: non-string input=${i}`);\n let end = input.length;\n if ((end * bits) % 8)\n throw new Error('Invalid padding: string should have whole number of bytes');\n for (; end > 0 && input[end - 1] === chr; end--) {\n if (!(((end - 1) * bits) % 8))\n throw new Error('Invalid padding: string has too much padding');\n }\n return input.slice(0, end);\n },\n };\n}\n/**\n * @__NO_SIDE_EFFECTS__\n */\nfunction normalize(fn) {\n if (typeof fn !== 'function')\n throw new Error('normalize fn should be function');\n return { encode: (from) => from, decode: (to) => fn(to) };\n}\n/**\n * Slow: O(n^2) time complexity\n * @__NO_SIDE_EFFECTS__\n */\nfunction convertRadix(data, from, to) {\n // base 1 is impossible\n if (from < 2)\n throw new Error(`convertRadix: wrong from=${from}, base cannot be less than 2`);\n if (to < 2)\n throw new Error(`convertRadix: wrong to=${to}, base cannot be less than 2`);\n if (!Array.isArray(data))\n throw new Error('convertRadix: data should be array');\n if (!data.length)\n return [];\n let pos = 0;\n const res = [];\n const digits = Array.from(data);\n digits.forEach((d) => {\n assertNumber(d);\n if (d < 0 || d >= from)\n throw new Error(`Wrong integer: ${d}`);\n });\n while (true) {\n let carry = 0;\n let done = true;\n for (let i = pos; i < digits.length; i++) {\n const digit = digits[i];\n const digitBase = from * carry + digit;\n if (!Number.isSafeInteger(digitBase) ||\n (from * carry) / from !== carry ||\n digitBase - digit !== from * carry) {\n throw new Error('convertRadix: carry overflow');\n }\n carry = digitBase % to;\n const rounded = Math.floor(digitBase / to);\n digits[i] = rounded;\n if (!Number.isSafeInteger(rounded) || rounded * to + carry !== digitBase)\n throw new Error('convertRadix: carry overflow');\n if (!done)\n continue;\n else if (!rounded)\n pos = i;\n else\n done = false;\n }\n res.push(carry);\n if (done)\n break;\n }\n for (let i = 0; i < data.length - 1 && data[i] === 0; i++)\n res.push(0);\n return res.reverse();\n}\nconst gcd = /* @__NO_SIDE_EFFECTS__ */ (a, b) => (!b ? a : gcd(b, a % b));\nconst radix2carry = /*@__NO_SIDE_EFFECTS__ */ (from, to) => from + (to - gcd(from, to));\n/**\n * Implemented with numbers, because BigInt is 5x slower\n * @__NO_SIDE_EFFECTS__\n */\nfunction convertRadix2(data, from, to, padding) {\n if (!Array.isArray(data))\n throw new Error('convertRadix2: data should be array');\n if (from <= 0 || from > 32)\n throw new Error(`convertRadix2: wrong from=${from}`);\n if (to <= 0 || to > 32)\n throw new Error(`convertRadix2: wrong to=${to}`);\n if (radix2carry(from, to) > 32) {\n throw new Error(`convertRadix2: carry overflow from=${from} to=${to} carryBits=${radix2carry(from, to)}`);\n }\n let carry = 0;\n let pos = 0; // bitwise position in current element\n const mask = 2 ** to - 1;\n const res = [];\n for (const n of data) {\n assertNumber(n);\n if (n >= 2 ** from)\n throw new Error(`convertRadix2: invalid data word=${n} from=${from}`);\n carry = (carry << from) | n;\n if (pos + from > 32)\n throw new Error(`convertRadix2: carry overflow pos=${pos} from=${from}`);\n pos += from;\n for (; pos >= to; pos -= to)\n res.push(((carry >> (pos - to)) & mask) >>> 0);\n carry &= 2 ** pos - 1; // clean carry, otherwise it will cause overflow\n }\n carry = (carry << (to - pos)) & mask;\n if (!padding && pos >= from)\n throw new Error('Excess padding');\n if (!padding && carry)\n throw new Error(`Non-zero padding: ${carry}`);\n if (padding && pos > 0)\n res.push(carry >>> 0);\n return res;\n}\n/**\n * @__NO_SIDE_EFFECTS__\n */\nfunction radix(num) {\n assertNumber(num);\n return {\n encode: (bytes) => {\n if (!isBytes(bytes))\n throw new Error('radix.encode input should be Uint8Array');\n return convertRadix(Array.from(bytes), 2 ** 8, num);\n },\n decode: (digits) => {\n if (!Array.isArray(digits) || (digits.length && typeof digits[0] !== 'number'))\n throw new Error('radix.decode input should be array of numbers');\n return Uint8Array.from(convertRadix(digits, num, 2 ** 8));\n },\n };\n}\n/**\n * If both bases are power of same number (like `2**8 <-> 2**64`),\n * there is a linear algorithm. For now we have implementation for power-of-two bases only.\n * @__NO_SIDE_EFFECTS__\n */\nfunction radix2(bits, revPadding = false) {\n assertNumber(bits);\n if (bits <= 0 || bits > 32)\n throw new Error('radix2: bits should be in (0..32]');\n if (radix2carry(8, bits) > 32 || radix2carry(bits, 8) > 32)\n throw new Error('radix2: carry overflow');\n return {\n encode: (bytes) => {\n if (!isBytes(bytes))\n throw new Error('radix2.encode input should be Uint8Array');\n return convertRadix2(Array.from(bytes), 8, bits, !revPadding);\n },\n decode: (digits) => {\n if (!Array.isArray(digits) || (digits.length && typeof digits[0] !== 'number'))\n throw new Error('radix2.decode input should be array of numbers');\n return Uint8Array.from(convertRadix2(digits, bits, 8, revPadding));\n },\n };\n}\n/**\n * @__NO_SIDE_EFFECTS__\n */\nfunction unsafeWrapper(fn) {\n if (typeof fn !== 'function')\n throw new Error('unsafeWrapper fn should be function');\n return function (...args) {\n try {\n return fn.apply(null, args);\n }\n catch (e) { }\n };\n}\n/**\n * @__NO_SIDE_EFFECTS__\n */\nfunction checksum(len, fn) {\n assertNumber(len);\n if (typeof fn !== 'function')\n throw new Error('checksum fn should be function');\n return {\n encode(data) {\n if (!isBytes(data))\n throw new Error('checksum.encode: input should be Uint8Array');\n const checksum = fn(data).slice(0, len);\n const res = new Uint8Array(data.length + len);\n res.set(data);\n res.set(checksum, data.length);\n return res;\n },\n decode(data) {\n if (!isBytes(data))\n throw new Error('checksum.decode: input should be Uint8Array');\n const payload = data.slice(0, -len);\n const newChecksum = fn(payload).slice(0, len);\n const oldChecksum = data.slice(-len);\n for (let i = 0; i < len; i++)\n if (newChecksum[i] !== oldChecksum[i])\n throw new Error('Invalid checksum');\n return payload;\n },\n };\n}\n// prettier-ignore\nexport const utils = {\n alphabet, chain, checksum, convertRadix, convertRadix2, radix, radix2, join, padding,\n};\n// RFC 4648 aka RFC 3548\n// ---------------------\nexport const base16 = /* @__PURE__ */ chain(radix2(4), alphabet('0123456789ABCDEF'), join(''));\nexport const base32 = /* @__PURE__ */ chain(radix2(5), alphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZ234567'), padding(5), join(''));\nexport const base32hex = /* @__PURE__ */ chain(radix2(5), alphabet('0123456789ABCDEFGHIJKLMNOPQRSTUV'), padding(5), join(''));\nexport const base32crockford = /* @__PURE__ */ chain(radix2(5), alphabet('0123456789ABCDEFGHJKMNPQRSTVWXYZ'), join(''), normalize((s) => s.toUpperCase().replace(/O/g, '0').replace(/[IL]/g, '1')));\nexport const base64 = /* @__PURE__ */ chain(radix2(6), alphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'), padding(6), join(''));\nexport const base64nopad = /* @__PURE__ */ chain(radix2(6), alphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'), join(''));\nexport const base64url = /* @__PURE__ */ chain(radix2(6), alphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'), padding(6), join(''));\nexport const base64urlnopad = /* @__PURE__ */ chain(radix2(6), alphabet('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_'), join(''));\n// base58 code\n// -----------\nconst genBase58 = (abc) => chain(radix(58), alphabet(abc), join(''));\nexport const base58 = /* @__PURE__ */ genBase58('123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz');\nexport const base58flickr = /* @__PURE__ */ genBase58('123456789abcdefghijkmnopqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ');\nexport const base58xrp = /* @__PURE__ */ genBase58('rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz');\n// xmr ver is done in 8-byte blocks (which equals 11 chars in decoding). Last (non-full) block padded with '1' to size in XMR_BLOCK_LEN.\n// Block encoding significantly reduces quadratic complexity of base58.\n// Data len (index) -> encoded block len\nconst XMR_BLOCK_LEN = [0, 2, 3, 5, 6, 7, 9, 10, 11];\nexport const base58xmr = {\n encode(data) {\n let res = '';\n for (let i = 0; i < data.length; i += 8) {\n const block = data.subarray(i, i + 8);\n res += base58.encode(block).padStart(XMR_BLOCK_LEN[block.length], '1');\n }\n return res;\n },\n decode(str) {\n let res = [];\n for (let i = 0; i < str.length; i += 11) {\n const slice = str.slice(i, i + 11);\n const blockLen = XMR_BLOCK_LEN.indexOf(slice.length);\n const block = base58.decode(slice);\n for (let j = 0; j < block.length - blockLen; j++) {\n if (block[j] !== 0)\n throw new Error('base58xmr: wrong padding');\n }\n res = res.concat(Array.from(block.slice(block.length - blockLen)));\n }\n return Uint8Array.from(res);\n },\n};\nexport const createBase58check = /* @__PURE__ */ (sha256) => chain(checksum(4, (data) => sha256(sha256(data))), base58);\n// legacy export, bad name\nexport const base58check = createBase58check;\nconst BECH_ALPHABET = /* @__PURE__ */ chain(alphabet('qpzry9x8gf2tvdw0s3jn54khce6mua7l'), join(''));\nconst POLYMOD_GENERATORS = [0x3b6a57b2, 0x26508e6d, 0x1ea119fa, 0x3d4233dd, 0x2a1462b3];\n/**\n * @__NO_SIDE_EFFECTS__\n */\nfunction bech32Polymod(pre) {\n const b = pre >> 25;\n let chk = (pre & 0x1ffffff) << 5;\n for (let i = 0; i < POLYMOD_GENERATORS.length; i++) {\n if (((b >> i) & 1) === 1)\n chk ^= POLYMOD_GENERATORS[i];\n }\n return chk;\n}\n/**\n * @__NO_SIDE_EFFECTS__\n */\nfunction bechChecksum(prefix, words, encodingConst = 1) {\n const len = prefix.length;\n let chk = 1;\n for (let i = 0; i < len; i++) {\n const c = prefix.charCodeAt(i);\n if (c < 33 || c > 126)\n throw new Error(`Invalid prefix (${prefix})`);\n chk = bech32Polymod(chk) ^ (c >> 5);\n }\n chk = bech32Polymod(chk);\n for (let i = 0; i < len; i++)\n chk = bech32Polymod(chk) ^ (prefix.charCodeAt(i) & 0x1f);\n for (let v of words)\n chk = bech32Polymod(chk) ^ v;\n for (let i = 0; i < 6; i++)\n chk = bech32Polymod(chk);\n chk ^= encodingConst;\n return BECH_ALPHABET.encode(convertRadix2([chk % 2 ** 30], 30, 5, false));\n}\n/**\n * @__NO_SIDE_EFFECTS__\n */\nfunction genBech32(encoding) {\n const ENCODING_CONST = encoding === 'bech32' ? 1 : 0x2bc830a3;\n const _words = radix2(5);\n const fromWords = _words.decode;\n const toWords = _words.encode;\n const fromWordsUnsafe = unsafeWrapper(fromWords);\n function encode(prefix, words, limit = 90) {\n if (typeof prefix !== 'string')\n throw new Error(`bech32.encode prefix should be string, not ${typeof prefix}`);\n if (!Array.isArray(words) || (words.length && typeof words[0] !== 'number'))\n throw new Error(`bech32.encode words should be array of numbers, not ${typeof words}`);\n if (prefix.length === 0)\n throw new TypeError(`Invalid prefix length ${prefix.length}`);\n const actualLength = prefix.length + 7 + words.length;\n if (limit !== false && actualLength > limit)\n throw n