@xo-cash/utils 0.0.7 → 0.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["#listeners","#options","#calculateDelay","#abortController","#exponentialBackoff","#stream","#controller","#closed","#textDecoder","#messageBuffer"],"sources":["../source/errors.ts","../source/event-emitter.ts","../source/exponential-backoff/errors.ts","../source/misc.ts","../source/exponential-backoff/exponential-backoff.ts","../source/exponential-backoff/exponential-backoff-externally-aborted.ts","../source/extended-json.ts","../source/script.ts","../source/sse-session/async-push-iterator.ts","../source/sse-session/constants.ts","../source/sse-session/sse-event-parser.ts","../source/template/errors.ts","../source/template/serialization.ts","../source/template/identifier.ts","../source/template/schemas.ts","../source/template/parser.ts","../source/cash-assembly/errors.ts","../source/cash-assembly/collect-evaluations.ts","../source/cash-assembly/bytes.ts","../source/cash-assembly/defaults.ts","../source/cash-assembly/primitive-evaluations.ts","../source/cash-assembly/identifier-collisions.ts","../source/cash-assembly/scan-evaluations.ts","../source/cash-assembly/evaluations.ts"],"sourcesContent":["/**\n * Error thrown when a waitFor timeout is reached\n */\nexport class WaitForTimeoutError extends Error {\n constructor(type: string) {\n super(`Timeout waiting for event \"${type}\"`);\n this.name = 'WaitForTimeoutError';\n }\n}\n","import type { DeeplyReadonly } from './types.ts';\nimport type { deepFreeze } from './misc.ts';\n\nimport { WaitForTimeoutError } from './errors.ts';\n\nexport type EventMap = Record<string, unknown>;\n\ntype Listener<T> = (detail: T) => void;\n\n/**\n * Internally permits listeners for individual event payloads to be stored\n * in a collection typed with the union of all event payloads.\n */\ntype StoredListener<T> = {\n bivarianceHack(detail: T): void;\n}['bivarianceHack'];\n\n/**\n * A listener entry.\n * @template T - The event payload type.\n */\ninterface ListenerEntry<T> {\n listener: StoredListener<T>;\n wrappedListener: StoredListener<T>;\n cancel: () => void;\n}\n\n/**\n * Callback returned by {@link on} and {@link once} for removing a listener.\n */\nexport type OffCallback = () => void;\n\n/**\n * A simple event emitter implementation.\n * @template T - The event map type.\n */\nexport class EventEmitter<T extends EventMap> {\n /**\n * The listeners map.\n * @private\n */\n #listeners: Map<keyof T, Set<ListenerEntry<T[keyof T]>>> = new Map();\n\n /**\n * Add a listener for an event.\n * @param type - The event type.\n * @param listener - The listener function.\n * @param debounceMilliseconds - The debounce time in milliseconds.\n * @returns An off callback that can be called to stop listening for events.\n */\n on<K extends keyof T>(type: K, listener: Listener<T[K]>, debounceMilliseconds: number = 0): OffCallback {\n const { cancel, listener: cancellableListener } = this.cancellable(listener);\n\n // Create a wrapped listener so that the debounce can be applied.\n const wrappedListener = debounceMilliseconds > 0 ? this.debounce(cancellableListener, debounceMilliseconds) : cancellableListener;\n\n // If the listeners map does not have the event type, create a new set.\n if (!this.#listeners.has(type)) {\n this.#listeners.set(type, new Set());\n }\n\n // Create a listener entry.\n const listenerEntry: ListenerEntry<T[K]> = {\n listener,\n wrappedListener,\n cancel,\n };\n\n // Add the listener entry to the listeners map.\n this.#listeners.get(type)?.add(listenerEntry);\n\n // Return an \"off\" callback that can be called to stop listening for events.\n return () => this.off(type, listener);\n }\n\n /**\n * Add a one-time listener for an event.\n * @param type - The event type.\n * @param listener - The listener function.\n * @param debounceMilliseconds - The debounce time in milliseconds.\n * @returns An off callback that can be called to stop listening for events.\n */\n once<K extends keyof T>(type: K, listener: Listener<T[K]>, debounceMilliseconds: number = 0): OffCallback {\n const wrappedListener: Listener<T[K]> = (detail: T[K]) => {\n this.off(type, listener);\n listener(detail);\n };\n\n // Create a cancellable listener.\n const { cancel, listener: cancellableListener } = this.cancellable(wrappedListener);\n\n // Create a debounced listener.\n const debouncedListener = debounceMilliseconds > 0 ? this.debounce(cancellableListener, debounceMilliseconds) : cancellableListener;\n\n // If the listeners map does not have the event type, create a new set.\n if (!this.#listeners.has(type)) {\n this.#listeners.set(type, new Set());\n }\n\n // Create a listener entry.\n const listenerEntry: ListenerEntry<T[K]> = {\n listener,\n wrappedListener: debouncedListener,\n cancel,\n };\n\n // Add the listener entry to the listeners map.\n this.#listeners.get(type)?.add(listenerEntry);\n\n // Return an \"off\" callback that can be called to stop listening for events.\n return () => this.off(type, listener);\n }\n\n /**\n * Remove a listener for an event.\n * @param type - The event type.\n * @param listener - The listener function.\n */\n off<K extends keyof T>(type: K, listener?: Listener<T[K]>): void {\n // Get the listeners for the event type.\n const listeners = this.#listeners.get(type);\n if (!listeners) return;\n\n // Find the listener entries (If a listener was provided, only 1 entry will be returned. Otherwise, all entries will be returned).\n const listenerEntries = Array.from(listeners).filter((entry) => !listener || entry.listener === listener || entry.wrappedListener === listener);\n\n // Remove the listener entries from the listeners set.\n listenerEntries.forEach((entry) => {\n // Set the wrapped listener to a no-op function to prevent it from being called by debounced events after it's been removed.\n entry.cancel();\n\n // Remove the listener entry from the listeners set.\n listeners.delete(entry);\n });\n\n // If no listener was provided and no listeners are left for the event type, remove the listeners set from the listeners map.\n if (!listener || this.#listeners.get(type)?.size === 0) {\n this.#listeners.delete(type);\n }\n }\n\n /**\n * Emit an event.\n *\n * @remarks The caller is responsible for ensuring the payload suits the intended mutability requirements.\n * By default, the payload will be mutable, so listeners may mutate the payload, effecting both\n * the original object and the other listeners.\n * To prevent this, the caller can use the {@link Object.freeze} or {@link deepFreeze} function to freeze the payload.\n * This will need to be defined in the EventMap using the built-in {@link Readonly} type or the provided {@link DeeplyReadonly} type.\n *\n * @param type - The event type.\n * @param payload - The event payload.\n * @returns True if there are listeners for the event, false otherwise.\n */\n emit<K extends keyof T>(type: K, payload: T[K]): boolean {\n // Get the listeners for the event type.\n const listeners = this.#listeners.get(type);\n if (!listeners) return false;\n\n // Emit the event to all listeners.\n listeners.forEach((entry) => {\n try {\n entry.wrappedListener(payload);\n } catch (error) {\n console.error(error);\n }\n });\n\n // Return true if there are listeners for the event, false otherwise.\n return listeners.size > 0;\n }\n\n /**\n * Remove all listeners.\n */\n removeAllListeners(): void {\n for (const [ type, listeners ] of this.#listeners.entries()) {\n listeners.forEach((entry) => {\n this.off(type, entry.listener);\n });\n }\n }\n\n /**\n * Wait for an event to be emitted that matches the provided predicate function's criteria.\n * @param type - The event type.\n * @param predicate - Predicate function to filter for whether the event payload matches the criteria.\n * @param timeoutMs - The timeout in milliseconds.\n * @returns The event payload.\n */\n async waitFor<K extends keyof T>(type: K, predicate: (payload: T[K]) => boolean, timeoutMs?: number): Promise<T[K]> {\n // Create a promise to wait for the event to be emitted.\n return new Promise((resolve, reject) => {\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n\n // Create a cleanup function to remove the listener and clear the timeout if it is still pending.\n const cleanup = (listener: Listener<T[K]>): void => {\n // Remove the listener from the listeners map.\n this.off(type, listener);\n\n // Clear the timeout if it is still pending.\n if (timeoutId !== undefined) {\n clearTimeout(timeoutId);\n }\n };\n\n // Create a listener function.\n const listener = (payload: T[K]): void => {\n try {\n // If the event payload does not match the predicate condition, return.\n if (!predicate(payload)) {\n return;\n }\n\n cleanup(listener);\n resolve(payload);\n } catch (error) {\n cleanup(listener);\n reject(error);\n }\n };\n\n // Set up timeout if specified\n if (timeoutMs !== undefined) {\n timeoutId = setTimeout(() => {\n this.off(type, listener);\n reject(new WaitForTimeoutError(String(type)));\n }, timeoutMs);\n }\n\n // Add the listener to the listeners map.\n this.on(type, listener);\n });\n }\n\n /**\n * Debounce a function.\n *\n * @remarks If {@link off} is called on a listener while it is debounced, the timeout is not cleared with clearTimeout.\n * Instead, the function is no-oped.\n *\n * @param func - The function to debounce.\n * @param wait - The wait time in milliseconds.\n * @returns The debounced function.\n */\n private debounce<K extends keyof T>(func: Listener<T[K]>, wait: number): Listener<T[K]> {\n // Create a timeout variable.\n let timeout: ReturnType<typeof setTimeout>;\n\n return (detail: T[K]) => {\n // If a debounce timer is already pending, clear it before scheduling the next one.\n if (timeout !== undefined) {\n clearTimeout(timeout);\n }\n\n timeout = setTimeout(() => {\n func(detail);\n }, wait);\n };\n }\n\n /**\n * Make a function cancellable.\n * @param func - The function to make cancelable.\n * @returns The cancellable function with a cancel method.\n */\n private cancellable<K extends keyof T>(func: Listener<T[K]>): { cancel: () => void; listener: Listener<T[K]> } {\n let cancelled = false;\n\n return {\n cancel: (): boolean => (cancelled = true),\n listener: (detail: T[K]): void => {\n if (cancelled) return;\n func(detail);\n },\n };\n }\n}\n","/* eslint-disable max-classes-per-file */\n\n/**\n * Error thrown when the maximum number of retries is hit in an exponential backoff\n */\nexport class ExponentialBackoffMaxRetriesHitError extends Error {\n constructor(errors: Array<Error>) {\n super('Exponential backoff: Max retries hit', { cause: errors });\n this.name = 'ExponentialBackoffMaxRetriesHitError';\n }\n}\n\n/**\n * Error thrown when the exponential backoff retries are stopped\n */\nexport class ExponentialBackoffStoppedRetriesError extends Error {\n constructor(reason: unknown) {\n // Convert the reason to an error if it is not an error\n const reasonError = reason instanceof Error ? reason : new Error(`${reason}`);\n\n super(`Exponential backoff was aborted: \"${reasonError.message}\"`, { cause: reasonError });\n this.name = 'ExponentialBackoffStoppedRetriesError';\n }\n}\n\n/**\n * Error thrown when an exponential backoff option is too small\n */\nexport class ExponentialBackoffNumberTooSmallError extends Error {\n constructor(option: string, value: number, min: number) {\n super(`Exponential backoff option \"${option}\" is too small. Must be at least ${min}. Received value: ${value}`);\n this.name = 'ExponentialBackoffNumberTooSmallError';\n }\n}\n\n/**\n * Error thrown when an exponential backoff option is out of bounds\n */\nexport class ExponentialBackoffNumberOutOfBoundsError extends Error {\n constructor(option: string, value: number, min: number, max: number) {\n super(`Exponential backoff option \"${option}\" is out of bounds. Must be between ${min} and ${max}. Received value: ${value}`);\n this.name = 'ExponentialBackoffNumberOutOfBoundsError';\n }\n}\n\n/**\n * Error thrown when an exponential backoff option is an invalid infinite integer\n */\nexport class ExponentialBackoffNumberNotFiniteError extends Error {\n constructor(option: string, value: number) {\n super(`Exponential backoff option \"${option}\" is invalid. Must be a finite number. Received value: ${value}`);\n this.name = 'ExponentialBackoffNumberNotFiniteError';\n }\n}\n\n/**\n * Error thrown when an exponential backoff option is not an integer\n */\nexport class ExponentialBackoffNonIntegerError extends Error {\n constructor(option: string, value: number) {\n super(`Exponential backoff option \"${option}\" is invalid. Must be an integer. Received value: ${value}`);\n this.name = 'ExponentialBackoffNonIntegerError';\n }\n}\n\n/**\n * Error thrown when an externally aborted exponential backoff is aborted\n * due to the external abort signal that was passed in to the constructor being aborted by an upstream consumer\n */\nexport class ExternallyAbortedExponentialBackoffExternalSignalAbortedError extends Error {\n constructor(reason: unknown) {\n // Convert the reason to an error if it is not an error\n const reasonError = reason instanceof Error ? reason : new Error(`${reason}`);\n\n super(`Externally aborted exponential backoff: \"${reasonError.message}\"`, { cause: reasonError });\n this.name = 'ExternallyAbortedExponentialBackoffExternalSignalAbortedError';\n }\n}\n\n/**\n * Error thrown when an externally aborted exponential backoff is aborted\n * due to the internal abort signal being aborted using the .abort() method\n */\nexport class ExternallyAbortedExponentialBackoffInternalSignalAbortedError extends Error {\n constructor(reason: unknown) {\n // Convert the reason to an error if it is not an error\n const reasonError = reason instanceof Error ? reason : new Error(`${reason}`);\n\n super(`Externally aborted exponential backoff: \"${reasonError.message}\"`, { cause: reasonError });\n this.name = 'ExternallyAbortedExponentialBackoffInternalSignalAbortedError';\n }\n}\n","import type { DeeplyReadonly } from './types';\n\n/**\n * Recursively freezes an object by iterating over all properties and freezing them.\n * @param obj - The object to freeze.\n * @returns The frozen object.\n */\nexport const deepFreeze = <T>(value: T): DeeplyReadonly<T> => {\n if (value !== null && (typeof value === 'object' || typeof value === 'function')) {\n for (const key of Reflect.ownKeys(value)) {\n const descriptor = Reflect.getOwnPropertyDescriptor(value, key);\n\n if (descriptor && 'value' in descriptor) {\n deepFreeze(descriptor.value);\n }\n }\n\n Object.freeze(value);\n }\n\n return value;\n};\n\n/**\n * Validate the value is within the bounds, returning true if it is within the bounds, false otherwise\n *\n * @param value - The value to validate\n * @param min - The minimum value\n * @param max - The maximum value\n *\n * @returns True if the value is within the bounds, false otherwise\n */\nexport const isWithinBounds = (value: number, min: number, max: number): boolean => {\n if (value < min || value > max) {\n return false;\n }\n\n return true;\n};\n","import {\n ExponentialBackoffStoppedRetriesError,\n ExponentialBackoffMaxRetriesHitError,\n ExponentialBackoffNonIntegerError,\n ExponentialBackoffNumberTooSmallError,\n ExponentialBackoffNumberOutOfBoundsError,\n ExponentialBackoffNumberNotFiniteError,\n} from './errors.ts';\nimport { isWithinBounds } from '../misc.ts';\n\nexport type ExponentialBackoffOptions = {\n\n /**\n * The maximum delay between attempts in milliseconds\n */\n maxDelay: number;\n\n /**\n * The maximum number of attempts. Passing 0 will result in infinite attempts.\n */\n maxAttempts: number;\n\n /**\n * The base delay between attempts in milliseconds\n */\n baseDelay: number;\n\n /**\n * The growth rate of the delay\n */\n growthRate: number;\n\n /**\n * The jitter of the delay as a percentage of growthRate. The jitter is subtracted from the delay.\n */\n jitter: number;\n};\n\n/**\n * The function to call to stop the retries.\n * This mimics the AbortSignal.abort function by taking in a reason for stopping\n *\n * @param reason - The reason for stopping the retries.\n */\nexport type ExponentialBackoffStopRetriesFunction = (reason: unknown) => void;\n\n/**\n * The parameters for the task function\n *\n * @param stopRetries - The function to call to stop the retries\n */\nexport type ExponentialBackoffCallbackParameters = {\n stopRetries: ExponentialBackoffStopRetriesFunction;\n};\n\n/**\n * Options that control a single exponential-backoff run.\n */\nexport type ExponentialBackoffRunOptions = {\n\n /**\n * Called after each failed task attempt.\n */\n onError?: ((error: Error) => void) | undefined;\n\n /**\n * Stops pending delays and prevents future attempts when aborted.\n */\n signal?: AbortSignal | undefined;\n};\n\n/**\n * Options accepted by the static exponential-backoff run helper.\n */\nexport type ExponentialBackoffStaticRunOptions = Partial<ExponentialBackoffOptions> & ExponentialBackoffRunOptions;\n\n/**\n * Exponential backoff is a technique used to retry a function after a delay.\n *\n * The delay increases exponentially with each attempt, up to a maximum delay.\n *\n * The jitter is a random amount of time subtracted from the delay to prevent thundering herd problems.\n *\n * The growth rate is the factor by which the delay increases with each attempt.\n */\nexport class ExponentialBackoff {\n readonly #options: ExponentialBackoffOptions;\n\n /**\n * Creates a new exponential-backoff instance.\n *\n * Unspecified options use the defaults listed below.\n *\n * @param options - Exponential-backoff configuration overrides.\n * @param options.maxDelay - Maximum delay between retries. Default: `10_000` ms.\n * @param options.maxAttempts - Maximum number of attempts; `0` retries indefinitely. Default: `10`.\n * @param options.baseDelay - Delay used as the basis for the first retry. Default: `1_000` ms.\n * @param options.growthRate - Multiplier applied to the delay after each attempt. Default: `2`.\n * @param options.jitter - Maximum proportional reduction subtracted from each delay (0–1). Default: `0.1`.\n *\n * @throws An {@link ExponentialBackoffNumberNotFiniteError} if a provided option is not a finite number\n * @throws An {@link ExponentialBackoffNumberOutOfBoundsError} if a provided option is out of bounds\n * @throws An {@link ExponentialBackoffNumberTooSmallError} if a provided option is too small\n * @throws An {@link ExponentialBackoffNonIntegerError} if a provided option is not an integer\n */\n constructor(options: Partial<ExponentialBackoffOptions> = {}) {\n this.#options = {\n maxDelay: 10_000,\n maxAttempts: 10,\n baseDelay: 1_000,\n growthRate: 2,\n jitter: 0.1,\n ...options,\n };\n\n ExponentialBackoff.validateOptions(this.#options);\n }\n\n /**\n * Create a new ExponentialBackoff instance\n *\n * @param config - The configuration for the exponential backoff\n *\n * @throws An {@link ExponentialBackoffNumberNotFiniteError} if a provided option is not a finite number\n * @throws An {@link ExponentialBackoffNumberOutOfBoundsError} if a provided option is out of bounds\n * @throws An {@link ExponentialBackoffNumberTooSmallError} if a provided option is too small\n * @throws An {@link ExponentialBackoffNonIntegerError} if a provided option is not an integer\n *\n * @returns The ExponentialBackoff instance\n */\n public static from(config?: Partial<ExponentialBackoffOptions>): ExponentialBackoff {\n const backoff = new ExponentialBackoff(config);\n\n return backoff;\n }\n\n /**\n * Run the function with exponential backoff\n *\n * @param taskFn - The function to run\n * @param options - Backoff configuration and options for this run\n *\n * @throws An {@link ExponentialBackoffMaxRetriesHitError} with all the errors that were thrown by the task function\n * @throws An {@link ExponentialBackoffStoppedRetriesError} if the abort signal is activated\n *\n * @returns The result of the function\n */\n public static run<T>(\n taskFn: (callbackParameters: ExponentialBackoffCallbackParameters) => Promise<T>,\n options: Partial<ExponentialBackoffStaticRunOptions> = {},\n ): Promise<T> {\n // Grab onError and signal from the options\n const { onError, signal, ...backoffOptions } = options;\n const backoff = ExponentialBackoff.from(backoffOptions);\n\n return backoff.run(taskFn, { onError, signal });\n }\n\n /**\n * Validate the options for the exponential backoff\n *\n * @param options - The options to validate\n *\n * @throws {@link ExponentialBackoffNumberNotFiniteError} if a provided option is not a finite number\n * @throws {@link ExponentialBackoffNonIntegerError} if a provided option is not an integer\n * @throws {@link ExponentialBackoffNumberOutOfBoundsError} if a provided option is out of bounds\n * @throws {@link ExponentialBackoffNumberTooSmallError} if a provided option is too small\n */\n public static validateOptions(options: ExponentialBackoffOptions): void {\n /** Validate the value is finite, throwing an {@link ExponentialBackoffInvalidInfiniteIntegerError} if the value is infinite */\n const assertIsFinite = (key: string, value: number): void => {\n if (!Number.isFinite(value)) {\n throw new ExponentialBackoffNumberNotFiniteError(key, value);\n }\n };\n\n /** Validate the value is an integer, throwing a {@link ExponentialBackoffNonIntegerError} if it is not an integer */\n const assertIsInteger = (key: string, value: number): void => {\n if (!Number.isInteger(value)) {\n throw new ExponentialBackoffNonIntegerError(key, value);\n }\n };\n\n /** Validate the value is greater than the minimum, throwing a {@link ExponentialBackoffNumberTooSmallError} if it is not */\n const assertIsHigherThan = (key: string, value: number, min: number): void => {\n if (value < min) {\n throw new ExponentialBackoffNumberTooSmallError(key, value, min);\n }\n };\n\n /** Validate the value is within the bounds, throwing a {@link ExponentialBackoffNumberOutOfBoundsError} if it is not within the bounds */\n const assertIsWithinBounds = (key: string, value: number, min: number, max: number): void => {\n if (!isWithinBounds(value, min, max)) {\n throw new ExponentialBackoffNumberOutOfBoundsError(key, value, min, max);\n }\n };\n\n // Validate the max delay\n assertIsFinite('maxDelay', options.maxDelay);\n assertIsHigherThan('maxDelay', options.maxDelay, 0);\n\n // Validate the max attempts\n assertIsFinite('maxAttempts', options.maxAttempts);\n assertIsInteger('maxAttempts', options.maxAttempts);\n assertIsHigherThan('maxAttempts', options.maxAttempts, 0);\n\n // Validate the base delay\n assertIsFinite('baseDelay', options.baseDelay);\n assertIsHigherThan('baseDelay', options.baseDelay, 0);\n\n // Validate the growth rate\n assertIsFinite('growthRate', options.growthRate);\n assertIsHigherThan('growthRate', options.growthRate, 0);\n\n // Validate the jitter\n assertIsFinite('jitter', options.jitter);\n assertIsWithinBounds('jitter', options.jitter, 0, 1);\n }\n\n /**\n * Run the function with exponential backoff\n *\n * If the function fails but we have not hit the max attempts, the error will be passed to the onError callback\n * and the function will be retried with an exponential delay\n *\n * If every attempt fails, an ExponentialBackoffMaxRetriesHitError will be thrown\n * with all errors from the task function.\n *\n * @param taskFn - The function to run\n * @param options - Options that control this run\n *\n * @throws An {@link ExponentialBackoffMaxRetriesHitError} with all the errors that were thrown by the task function\n * @throws An {@link ExponentialBackoffStoppedRetriesError} if the abort signal is activated\n *\n * @returns The result of the function\n */\n public async run<T>(\n taskFn: (callbackParameters: ExponentialBackoffCallbackParameters) => Promise<T>,\n options: ExponentialBackoffRunOptions = {},\n ): Promise<T> {\n const { onError, signal: suppliedSignal } = options;\n\n // The task can stop its own retries without owning the signal supplied by the caller.\n const abortController = new AbortController();\n const stopRetries = abortController.abort.bind(abortController);\n\n // Start with the abort controller signal\n const signals = [ abortController.signal ];\n\n // If we received a signal from the caller, add it to the signals array\n if (suppliedSignal !== undefined) {\n signals.push(suppliedSignal);\n }\n\n // Compose the signals together\n const signal = AbortSignal.any(signals);\n\n // If the composed signal is already aborted, throw an error\n if (signal.aborted) {\n throw new ExponentialBackoffStoppedRetriesError(signal.reason);\n }\n\n // Initialize an empty array to store the errors\n const errors: Error[] = [];\n\n // Initialize the attempt counter\n let attempt = 0;\n\n // If the max attempts is 0, we should continue indefinitely.\n const unlimitedAttempts = this.#options.maxAttempts === 0;\n\n // Loop until we succeed, hit the max attempts, or the abort signal is activated\n while (true) {\n try {\n // Await the promise before returning so its execution context remains in the try-catch\n // If we didn't await, this `run` function would successfully return and any errors would not be caught here.\n return await taskFn({ stopRetries });\n } catch (error) {\n // Store the error in case we fail every attempt\n const errorInstance = error instanceof Error ? error : new Error(`${error}`);\n onError?.(errorInstance);\n\n // If we have unlimited attempts, don't append this to the errors array to prevent a memory leak.\n if (!unlimitedAttempts) {\n errors.push(errorInstance);\n }\n }\n\n // Check if the abort signal has been activated\n if (signal.aborted) {\n // Throw an error if the abort signal has been activated\n throw new ExponentialBackoffStoppedRetriesError(signal.reason);\n }\n\n // Calculate the count for next attempt. Do this now so we can exit before waiting and before running the next attempt.\n const nextAttemptCount = attempt + 1;\n const nextAttemptExceedsMaxAttempts = nextAttemptCount >= this.#options.maxAttempts;\n\n // If the next attempt exceeds the max attempts, break out of the loop\n if (!unlimitedAttempts && nextAttemptExceedsMaxAttempts) {\n break;\n }\n\n // Wait before going to the next attempt\n const delay = this.#calculateDelay(this.#options, attempt);\n\n // Wait for the delay or the abort signal\n await new Promise<void>((resolve, reject) => {\n // eslint-disable-next-line prefer-const\n let timeout: ReturnType<typeof setTimeout>;\n\n // Handle the abort signal\n const abortHandler = (): void => {\n clearTimeout(timeout);\n reject(new ExponentialBackoffStoppedRetriesError(signal.reason));\n };\n\n // Handle the timeout\n const timeoutHandler = (): void => {\n signal.removeEventListener('abort', abortHandler);\n resolve(undefined);\n };\n\n // Set the timeout\n timeout = setTimeout(timeoutHandler, delay);\n\n // Add the abort handler to the abort signal\n signal.addEventListener('abort', abortHandler, { once: true });\n });\n\n attempt++;\n }\n\n // We completed the loop without ever succeeding. Throw an ExponentialBackoffMaxRetriesHitError with all the errors we got\n throw new ExponentialBackoffMaxRetriesHitError(errors);\n }\n\n /**\n * Calculate the delay before we should attempt to retry\n *\n * @param options - The configuration for the exponential backoff\n * @param attempt - The current attempt number\n * @returns The time in milliseconds before another attempt should be made\n */\n #calculateDelay(options: ExponentialBackoffOptions, attempt: number): number {\n // Get the power of the growth rate\n const power = options.growthRate ** attempt;\n\n // Get the delay before jitter or limit\n const rawDelay = options.baseDelay * power;\n\n // Cap the delay to the maximum. Do this before the jitter so jitter does not become larger than delay\n const cappedDelay = Math.min(rawDelay, options.maxDelay);\n\n // Get a random number for the amount to \"jitter\" the delay by\n const jitterAmount = Math.random();\n\n // Calculate the jitter\n const jitter = jitterAmount * options.jitter * cappedDelay;\n\n // Subtract the jitter from the delay\n return cappedDelay - jitter;\n }\n}\n","import {\n ExternallyAbortedExponentialBackoffExternalSignalAbortedError,\n ExternallyAbortedExponentialBackoffInternalSignalAbortedError,\n} from './errors.ts';\nimport { ExponentialBackoff } from './exponential-backoff.ts';\nimport type { ExponentialBackoffCallbackParameters, ExponentialBackoffOptions, ExponentialBackoffRunOptions } from './exponential-backoff.ts';\n\n/**\n * Options for the ExponentialBackoffExternallyAbortable class\n *\n * @extends Partial<ExponentialBackoffOptions>\n * @property abortSignal - The abort signal to use for this instance\n */\nexport type ExponentialBackoffExternallyAbortableOptions = Partial<ExponentialBackoffOptions> & {\n abortSignal: AbortSignal;\n};\n\n/**\n * An exponential backoff that can be stopped by calling `.abort()` or by passing an\n * `abortSignal` to the constructor.\n *\n * @remarks One instance can run many tasks. Aborting it stops retries for every run.\n */\nexport class ExponentialBackoffExternallyAbortable {\n readonly #abortController = new AbortController();\n readonly #exponentialBackoff: ExponentialBackoff;\n\n constructor(options: Partial<ExponentialBackoffExternallyAbortableOptions> = {}) {\n const { abortSignal, ...backoffOptions } = options;\n\n this.#exponentialBackoff = new ExponentialBackoff(backoffOptions);\n\n // Listen for the provided abort signal to be aborted\n abortSignal?.addEventListener(\n 'abort',\n () => {\n this.#abortController.abort(new ExternallyAbortedExponentialBackoffExternalSignalAbortedError(abortSignal.reason));\n },\n {\n once: true,\n // Clean up this listener if the internal abort controller is aborted\n signal: this.#abortController.signal,\n },\n );\n\n // If the abort signal is already aborted, immediately abort the internal abort controller\n if (abortSignal?.aborted) {\n this.#abortController.abort(new ExternallyAbortedExponentialBackoffExternalSignalAbortedError(abortSignal.reason));\n }\n }\n\n /**\n * Run the function with exponential backoff\n *\n * If the function fails but we have not hit the max attempts, the error will be passed to the onError callback\n * and the function will be retried with an exponential delay\n *\n * If every attempt fails, an ExponentialBackoffMaxRetriesHitError will be thrown\n * with all errors from the task function.\n *\n * @param taskFn - The function to run\n * @param options - Options that control this run\n *\n * @throws An {@link ExponentialBackoffMaxRetriesHitError} with all the errors that were thrown by the task function\n * @throws An {@link ExponentialBackoffStoppedRetriesError} if the abort signal is activated\n * @throws An {@link ExternallyAbortedExponentialBackoffExternalSignalAbortedError}\n * if the abort signal that was provided during construction is activated\n * @throws An {@link ExternallyAbortedExponentialBackoffInternalSignalAbortedError}\n * if {@link ExponentialBackoffExternallyAbortable.abort} is called on this class\n *\n * @returns The result of the function\n */\n public run<T>(\n taskFn: (callbackParameters: ExponentialBackoffCallbackParameters) => Promise<T>,\n options: Partial<ExponentialBackoffRunOptions> = {},\n ): Promise<T> {\n let signal = this.#abortController.signal;\n\n // If a signal was provided for this run, compose it with the instance-wide signal\n if (options.signal !== undefined) {\n signal = AbortSignal.any([ signal, options.signal ]);\n }\n\n // Call the exponential backoff run method with the composed signal\n return this.#exponentialBackoff.run(taskFn, { ...options, signal });\n }\n\n /**\n * Stops retries for all current and future runs.\n *\n * @param reason - The reason for stopping retries\n */\n public abort(reason: unknown): void {\n this.#abortController.abort(new ExternallyAbortedExponentialBackoffInternalSignalAbortedError(reason));\n }\n}\n","import { binToHex, hexToBin } from '@bitauth/libauth';\n\n/**\n * Matches a bigint encoded in Extended JSON format: `<bigint: 123n>`.\n */\nconst EXTENDED_JSON_BIGINT_PATTERN = /^<bigint: (?<bigint>[+-]?[0-9]+)n>$/u;\n\n/**\n * Matches a Uint8Array encoded in Extended JSON format: `<uint8array: abcd>`.\n */\nconst EXTENDED_JSON_UINT8ARRAY_PATTERN = /^<uint8array: (?<hex>[0-9a-f]*)>$/u;\n\n/**\n * The JSON replacer that encodes `bigint` and `Uint8Array` values in Extended JSON format,\n * compatible with the format expected by `extendedJsonReviver`.\n *\n * - BigInts are encoded as `<bigint: 123n>`.\n * - Uint8Arrays are encoded as `<uint8array: abcd>`.\n * All other values pass through unchanged and if any incompatible type is encountered, an error is thrown.\n *\n * Note: To use this function, pass it as the second argument to `JSON.stringify` when serializing data.\n *\n * Note to developers: Libauth's `stringify` is the replacer. It also serializes functions and symbols,\n * which we do not support. Passing it would let templates include those values, but revival would then fail.\n * This module provides a dedicated replacer and reviver so serialization and deserialization stay aligned.\n *\n * @param _propertyKey The property key being serialized, required by the `JSON.stringify` replacer but not used here.\n * @param value The value to encode or pass through unchanged.\n * @returns The encoded string\n */\nexport const extendedJsonReplacer = (_propertyKey: string, value: unknown): unknown => {\n if (value instanceof Uint8Array) {\n return `<uint8array: ${binToHex(value)}>`;\n }\n\n if (typeof value === 'bigint') {\n return `<bigint: ${value.toString()}n>`;\n }\n\n return value;\n};\n\n/**\n * The JSON reviver that reconstructs `bigint` and `Uint8Array` values encoded by `extendedJsonReplacer`.\n *\n * Note: To use this function, pass it as the second argument to `JSON.parse` when deserializing data.\n *\n * @param _propertyKey The property key being deserialized, required by the `JSON.parse` reviver but not used here.\n * @param value The value to reconstruct or pass through unchanged.\n * @returns The reconstructed value\n */\nexport const extendedJsonReviver = (_propertyKey: string, value: unknown): unknown => {\n // If the value is not a string, return the original value\n if (typeof value !== 'string') {\n return value;\n }\n\n // Match the bigint pattern\n const bigintPatternMatch = value.match(EXTENDED_JSON_BIGINT_PATTERN);\n\n // If the value matches the bigint pattern, return the reconstructed bigint\n if (bigintPatternMatch) {\n return BigInt(bigintPatternMatch.groups!.bigint);\n }\n\n // Match the Uint8Array pattern\n const uint8arrayPatternMatch = value.match(EXTENDED_JSON_UINT8ARRAY_PATTERN);\n\n // If the value matches the Uint8Array pattern, return the reconstructed Uint8Array\n if (uint8arrayPatternMatch) {\n return hexToBin(uint8arrayPatternMatch.groups!.hex);\n }\n\n // If the value does not match either pattern, return the original value\n return value;\n};\n\n/**\n * Serializes an object to a string using the {@link extendedJsonReplacer}.\n *\n * @param object The object to serialize.\n * @returns The string representation of the object in Extended JSON format.\n */\nexport const toExtendedJson = (object: unknown): string => {\n return JSON.stringify(object, extendedJsonReplacer);\n};\n\n/**\n * Deserializes a string to an object using the {@link extendedJsonReviver}.\n *\n * @param serializedObject The string to deserialize.\n * @returns The object reconstructed from the string.\n */\nexport const fromExtendedJson = (serializedObject: string): unknown => {\n return JSON.parse(serializedObject, extendedJsonReviver);\n};\n","import { binToHex, sha256 } from '@bitauth/libauth';\n\n/**\n * Converts a script to a scriptHash.\n * @param {Uint8Array} script - The script to convert.\n * @returns {string} The scriptHash as a reversed hex string.\n */\nexport const scriptToScriptHash = (script: Uint8Array): string => {\n // Hash the script.\n const hash = sha256.hash(script);\n\n // Reverse the hash. (Electrum style, reverse switches to little endian representation)\n const reversed = hash.reverse();\n\n // Convert the reversed hash to hex.\n return binToHex(reversed);\n};\n","/**\n * An async iterable queue that bridges push-based producers and pull-based consumers.\n *\n * Composes an internal {@link ReadableStream} instead of extending it, so producers\n * call {@link push} while consumers use standard async iteration (`for await...of`).\n *\n * ```ts\n * const messages = new AsyncPushIterator<SSEvent>();\n *\n * // Producer (elsewhere)\n * messages.push(event);\n *\n * // Consumer\n * for await (const event of messages) {\n * handle(event);\n * }\n * ```\n *\n * {@link Symbol.asyncIterator} returns `stream.values({ preventCancel: true })` so\n * breaking out of `for await...of` does not cancel the underlying stream. That\n * matters for long-lived sessions where the producer keeps pushing after a consumer\n * stops reading early (for example, test helpers that only collect a fixed count).\n */\nexport class AsyncPushIterator<T> {\n /** ReadableStream backing the async iterator returned from {@link Symbol.asyncIterator}. */\n #stream: ReadableStream<T>;\n\n /** Controller used to enqueue values and close the stream from {@link push} and {@link close}. */\n #controller: ReadableStreamDefaultController<T> | undefined;\n\n /** When true, no more values are accepted and iteration eventually completes. */\n #closed = false;\n\n public constructor() {\n // `start`'s `this` is the underlying source object when using a plain method.\n // An arrow function captures the class instance so the controller is stored here.\n this.#stream = new ReadableStream({\n start: (controller: ReadableStreamDefaultController<T>): void => {\n this.#controller = controller;\n },\n });\n }\n\n /**\n * Flag indicating if the iterator is closed.\n */\n public get closed(): boolean {\n return this.#closed;\n }\n\n /**\n * Enqueues a value for the consumer.\n *\n * After {@link close}, pushes are silently dropped.\n *\n * @param value - The next value to yield from the iterator.\n */\n push(value: T): void {\n if (this.#closed) return;\n\n this.#controller?.enqueue(value);\n }\n\n /**\n * Causes any future interactions with the associated stream to error with {@link error}.\n * Calling this will also clear the pending values immediately, so iterators that were listening will not receive them.\n *\n * @param error - The error to throw from the stream.\n */\n error(error: Error): void {\n if (this.#closed) return;\n\n this.#closed = true;\n this.#controller?.error(error);\n }\n\n /**\n * Ends the stream.\n *\n * Marks the iterator closed so future {@link push} calls are ignored.\n * Buffered values are still yielded before iteration completes.\n */\n close(): void {\n this.#closed = true;\n\n try {\n this.#controller?.close();\n } catch {\n // The reader may already have released or cancelled the stream.\n }\n }\n\n /**\n * Returns an async iterator over the composed stream.\n *\n * Uses `preventCancel: true` so early `break` from `for await...of` does not\n * close the stream and block later pushes.\n *\n * Because values are discarded after being read, only a single consumer is supported.\n * Additional consumers will receive a stream lock error. Unread values will be preserved until {@link close} is called.\n */\n [Symbol.asyncIterator](): AsyncIterableIterator<T> {\n return this.#stream.values({ preventCancel: true });\n }\n}\n","/**\n * Regex that splits decoded SSE text into lines.\n *\n * The SSE wire format is line-oriented (`field: value` per line). Servers may\n * send `\\r\\n` (HTTP default), `\\n` (Unix), or `\\r` (legacy Mac). Matching all\n * three keeps parsing correct regardless of platform or server implementation.\n */\nexport const SSE_LINE_ENDINGS = /\\r\\n|\\r|\\n/;\n\n/**\n * Regex that matches the single optional leading space in an SSE field value.\n *\n * Per the SSE spec, `field: value` may include one space immediately after the\n * colon; that space is not part of the value. Used with `.replace()` to strip\n * it when parsing lines such as `data: hello` → `hello`.\n */\nexport const SSE_FIELD_VALUE_REGEX = /^ /;\n\n/**\n * Regex that matches a trailing newline at the end of a string.\n *\n * Multiple `data:` lines in one event are joined with `\\n`. When the event is\n * completed, this removes any stray trailing newline so callers receive the\n * payload without an extra line break at the end.\n */\nexport const SSE_TRAILING_NEWLINE_REGEX = /\\n$/;\n\n/**\n * The newline character used when normalizing SSE text internally.\n *\n * Used to join consecutive `data:` lines into one payload and to reassemble\n * buffered partial lines between streamed chunks before the next parse call.\n */\nexport const NEW_LINE = '\\n';\n","import type { SSEvent } from './types.ts';\nimport { NEW_LINE, SSE_FIELD_VALUE_REGEX, SSE_LINE_ENDINGS, SSE_TRAILING_NEWLINE_REGEX } from './constants.ts';\n\n/**\n * Optional encoders used when decoding incoming SSE bytes and re-encoding\n * any buffered remainder between chunks.\n */\nexport interface SSEEventParserOptions {\n\n /** Decodes raw stream bytes into text. Defaults to a new `TextDecoder`. */\n textDecoder: TextDecoder;\n}\n\n/**\n * Incrementally parses Server-Sent Events (SSE) from streamed byte chunks.\n *\n * SSE payloads are line-oriented: each event is a sequence of `field: value`\n * lines terminated by a blank line. This parser accepts arbitrary chunk\n * boundaries from a live HTTP response body and emits only complete events.\n *\n * Typical usage is one parser instance per connection, calling {@link parseEvents}\n * for each chunk received from the stream:\n *\n * ```ts\n * const parser = new SSEEventParser();\n *\n * for await (const chunk of response.body) {\n * for (const event of parser.parseEvents(chunk)) {\n * // handle event.data, event.event, event.id, event.retry\n * }\n * }\n * ```\n *\n * Supported fields follow the SSE spec: `data`, `event`, `id`, and `retry`.\n * Multiple `data:` lines in one event are joined with `\\n`. An event is only\n * emitted once a blank line is seen and at least one `data` field was collected.\n */\nexport class SSEEventParser {\n readonly #textDecoder: TextDecoder;\n\n /** Bytes from a partial line or incomplete event, carried over to the next chunk. */\n #messageBuffer: string = '';\n\n /**\n * Creates a parser for one SSE stream.\n *\n * Inject custom encoders in tests or when a non-default character encoding\n * is required; production callers can rely on the defaults.\n *\n * @param options - Optional text encoders for decode/encode of stream bytes.\n */\n constructor(options: Partial<SSEEventParserOptions> = {}) {\n this.#textDecoder = options.textDecoder ?? new TextDecoder();\n }\n\n /**\n * Clears any buffered bytes from a partial line or incomplete event.\n *\n * Call when abandoning a transport so the next connection does not prepend\n * stale bytes to incoming chunks.\n */\n public reset(): void {\n // Clear the message buffer\n this.#messageBuffer = '';\n\n // Reset the decoder to clear any buffered bytes\n this.#textDecoder.decode();\n }\n\n /**\n * Parses all complete SSE events contained in a newly received chunk.\n *\n * The chunk is appended to any bytes buffered from earlier calls. Complete\n * events (blank-line delimited blocks with at least one `data` field) are\n * returned immediately; any trailing partial line or in-progress event stays\n * in the internal buffer until a later chunk completes it.\n *\n * @param chunk - Newly received SSE stream bytes.\n * @returns Zero or more complete parsed SSE events from this chunk.\n */\n public parseEvents(chunk: Uint8Array): SSEvent[] {\n const lines = this.getBufferedLines(chunk);\n\n const eventLines = lines.slice(0, -1);\n\n const events: SSEvent[] = [];\n let event: Partial<SSEvent> = {};\n let processedLineCount = 0;\n\n for (const [ index, line ] of eventLines.entries()) {\n // A blank line indicates the end of an event. If we have received data, we can complete the event\n if (line === '') {\n if (event.data !== undefined) {\n events.push(this.completeEvent(event));\n event = {};\n processedLineCount = index + 1;\n }\n\n continue;\n }\n\n this.parseLine(line, event);\n }\n\n this.storeRemainingLines(lines, processedLineCount);\n\n return events;\n }\n\n /**\n * Appends a new chunk to the buffered bytes and splits the combined payload\n * into lines.\n *\n * Accepts `\\r\\n`, `\\r`, and `\\n` line endings so events parse correctly\n * regardless of server or platform conventions.\n */\n private getBufferedLines(chunk: Uint8Array): string[] {\n this.#messageBuffer += this.#textDecoder.decode(chunk, { stream: true });\n\n return this.#messageBuffer.split(SSE_LINE_ENDINGS);\n }\n\n /**\n * Parses one SSE field line into an in-progress event.\n *\n * Lines without a colon are ignored. A single optional space after the colon\n * is stripped from the field value, per the SSE spec.\n */\n private parseLine(line: string, event: Partial<SSEvent>): void {\n const colonIndex = line.indexOf(':');\n if (colonIndex === -1) return;\n\n const field = line.slice(0, colonIndex);\n const value = line.slice(colonIndex + 1).replace(SSE_FIELD_VALUE_REGEX, '');\n\n switch (field) {\n case 'data':\n event.data = event.data ? `${event.data}${NEW_LINE}${value}` : value;\n\n return;\n\n case 'event':\n event.event = value;\n\n return;\n\n case 'id':\n event.id = value;\n\n return;\n\n case 'retry':\n this.parseRetry(value, event);\n\n return;\n }\n }\n\n /**\n * Applies a numeric `retry:` field to an in-progress event.\n *\n * Non-numeric values are ignored rather than failing the parse.\n */\n private parseRetry(value: string, event: Partial<SSEvent>): void {\n const retry = parseInt(value, 10);\n\n if (!isNaN(retry)) {\n event.retry = retry;\n }\n }\n\n /**\n * Constructs a completed SSE event from accumulated fields.\n *\n * Trims a trailing newline from multi-line `data` values so callers receive\n * the payload without an extra line break at the end.\n */\n private completeEvent(event: Partial<SSEvent>): SSEvent {\n return {\n ...event,\n data: event.data?.replace(SSE_TRAILING_NEWLINE_REGEX, ''),\n } as SSEvent;\n }\n\n /**\n * Preserves incomplete trailing lines for the next received chunk.\n *\n * Only lines that were fully processed (through a completed event boundary)\n * are discarded; the remainder is re-encoded into {@link messageBuffer}.\n */\n private storeRemainingLines(lines: string[], processedLineCount: number): void {\n this.#messageBuffer = lines.slice(processedLineCount).join(NEW_LINE);\n }\n}\n","/* eslint-disable max-classes-per-file */\n\nimport type { $ZodIssue } from 'zod/v4/core';\n\n/**\n * Formats the Zod validation failures into a single string with one line each: \"- <field>: <message>\" and top level failures\n * with no field path show as \"(root)\" for better readability.\n *\n * @param issues The Zod validation failures to format.\n * @returns A human readable error string for better debugging.\n */\nexport const buildErrorDescription = (issues: $ZodIssue[]): string => {\n // Initialize an empty array to store the formatted lines.\n const lines: string[] = [];\n\n // Iterate over the issues and format them into a string.\n for (const issue of issues) {\n // Get the issue path.\n const issuePath = issue.path.length > 0 ? issue.path.join('.') : '(root)';\n\n // The prefix that Zod adds to messages.\n const messagePrefix = 'Invalid input: ';\n\n // Remove the prefix for better readability.\n const issueMessage = issue.message.startsWith(messagePrefix) ? issue.message.slice(messagePrefix.length) : issue.message;\n\n // Add the formatted line to the array.\n lines.push(`- ${issuePath}: ${issueMessage}`);\n }\n\n // Return the formatted string.\n return `\\n${lines.join('\\n')}`;\n};\n\n/**\n * Thrown when the provided template does not satisfy the XOTemplate schema.\n */\nexport class TemplateInvalidError extends Error {\n constructor(details: string) {\n const message = `Template invalid: ${details}`;\n super(message);\n this.name = 'TemplateInvalidError';\n }\n}\n\n/**\n * Thrown when a string passed to `deserializeTemplate` cannot be parsed as JSON.\n */\nexport class TemplateJsonMalformedError extends Error {\n constructor(reason: string) {\n super(`Template JSON malformed, expected a valid JSON string: ${reason}`);\n this.name = 'TemplateJsonMalformedError';\n }\n}\n\n/**\n * Thrown when `serializeTemplate` fails to produce a JSON string from the template.\n */\nexport class TemplateSerializationFailedError extends Error {\n constructor(reason: string) {\n super(`Template serialization failed: ${reason}`);\n this.name = 'TemplateSerializationFailedError';\n }\n}\n","import type { XOTemplate } from '@xo-cash/types';\nimport { extendedJsonReplacer, extendedJsonReviver } from '../extended-json.ts';\nimport { TemplateJsonMalformedError, TemplateSerializationFailedError } from './errors.ts';\n\n/**\n * Serializes an XOTemplate to a JSON string. Encodes `bigint` and `Uint8Array` fields in\n * Extended JSON format so they can be reconstructed by `deserializeTemplate`.\n *\n * @param template The template to serialize.\n * @returns A JSON string representation of the template.\n * @throws {TemplateSerializationFailedError} If the template cannot be serialized to JSON.\n */\nexport const serializeTemplate = (template: XOTemplate): string => {\n try {\n // Serialize the template to a JSON string.\n return JSON.stringify(template, extendedJsonReplacer);\n } catch (serializationError) {\n const reason = serializationError instanceof Error ? serializationError.message : 'unknown error while serializing template';\n\n throw new TemplateSerializationFailedError(reason);\n }\n};\n\n/**\n * Deserializes a JSON string back into an XOTemplate object. Restores `bigint` and\n * `Uint8Array` fields encoded in Extended JSON format by `serializeTemplate`.\n *\n * @param serializedTemplate - A JSON string of an XOTemplate object.\n * @returns The reconstructed XOTemplate object.\n * @throws {TemplateJsonMalformedError} If the serialized template is not valid JSON.\n */\nexport const deserializeTemplate = (serializedTemplate: string): XOTemplate => {\n try {\n // Parse the serialized template using the extended JSON reviver.\n return JSON.parse(serializedTemplate, extendedJsonReviver);\n } catch (parsingError) {\n const reason = parsingError instanceof Error ? parsingError.message : 'unknown error while deserializing template';\n\n throw new TemplateJsonMalformedError(reason);\n }\n};\n","import { binToHex, sha256, utf8ToBin } from '@bitauth/libauth';\nimport type { XOTemplate } from '@xo-cash/types';\nimport { serializeTemplate } from './serialization.ts';\n\n/**\n * Generates a deterministic template identifier by hashing the template.\n *\n * Note: This expects a template that has been validated by `parseTemplate`.\n *\n * @param template - The template to generate an identifier for.\n * @returns The sha256 hex identifier for the template.\n */\nexport const generateTemplateIdentifier = (template: XOTemplate): string => {\n // Serialize the template.\n const serializedTemplate = serializeTemplate(template);\n\n // Hash the serialized template.\n const hash = sha256.hash(utf8ToBin(serializedTemplate));\n\n // Convert the hash to hex and return it.\n return binToHex(hash);\n};\n","/* eslint-disable @stylistic/newline-per-chained-call */\nimport { BchVmVersions, XOTemplatePrimitiveTypes, XOTemplateLockingTypes, XOTemplateNftCapabilities } from '@xo-cash/types';\nimport { z } from 'zod';\n\n// ============================================================\n// Enums\n// ============================================================\n\n/**\n * Validation schema for a BCH VM version identifier. Defines the set of known BCH VM versions\n * that XO templates declare support for.\n *\n * Uses `BchVmVersions` from `@xo-cash/types` so template validation stays aligned with the\n * `BchVmVersion` type.\n *\n * ```\n * {\n * \"supported\": [ \"BCH_2025_05\" ] ← each value\n * }\n * ```\n */\nexport const bchVmVersionSchema = z.enum(BchVmVersions);\n\n/**\n * Validation schema for the capability of a non-fungible token. Defines the three capability\n * types supported on BCH: minting tokens can create new NFTs, mutable tokens can update their\n * commitment, and none tokens cannot be changed after creation.\n *\n * ```\n * {\n * \"inputs|outputs\": {\n * \"[id]\": {\n * \"token\": {\n * \"nft\": {\n * \"capability\": \"minting\" ← this schema\n * }\n * }\n * }\n * }\n * }\n * ```\n */\nexport const xoTemplateNftCapabilitySchema = z.enum(XOTemplateNftCapabilities);\n\n/**\n * Validation schema for a BCH locking script type. Defines the standard locking script types\n * supported on BCH.\n *\n * ```\n * {\n * \"lockingScripts\": {\n * \"[id]\": {\n * \"lockingType\": \"p2pkh\" ← this schema\n * }\n * }\n * }\n * ```\n */\nexport const xoTemplateLockingTypeSchema = z.enum(XOTemplateLockingTypes);\n\n/**\n * Validation schema for a primitive type identifier.\n * Accepts values from XOTemplatePrimitiveTypes for the `hint` field on constants, variables, and data.\n */\nexport const xoTemplatePrimitiveTypeSchema = z.enum(XOTemplatePrimitiveTypes);\n\n// ============================================================\n// Primitives\n// ============================================================\n\n/**\n * Validation schema for byte array fields i.e. Uint8Array instance.\n */\nexport const uint8ArraySchema = z.instanceof(Uint8Array).describe('A sequence of unsigned 8-bit integers expressed as a Uint8Array.');\n\n/**\n * Validation schema for the Satoshis type i.e. bigint.\n */\nexport const satoshisSchema = z.bigint().describe('A satoshi amount expressed as a bigint.');\n\n// ============================================================\n// Shared\n// ============================================================\n\n/** Maximum character length for name fields on view properties. */\nexport const VIEW_PROPERTIES_NAME_MAX_LENGTH = 1000;\n\n/** Maximum character length for description fields on view properties. */\nexport const VIEW_PROPERTIES_DESCRIPTION_MAX_LENGTH = 5000;\n\n/** Maximum character length for icon fields on view properties. */\nexport const VIEW_PROPERTIES_ICON_MAX_LENGTH = 1000;\n\n/**\n * Validation schema for view properties shared across many template elements i.e. name, description, icon.\n * Extended by most other schemas in this file.\n */\nexport const xoTemplateViewPropertiesSchema = z\n .object({\n name: z.string().max(VIEW_PROPERTIES_NAME_MAX_LENGTH).describe('A short human-readable label for this element.'),\n description: z\n .string()\n .max(VIEW_PROPERTIES_DESCRIPTION_MAX_LENGTH)\n .describe('A human-readable explanation of what this element does and when it is relevant.'),\n icon: z.string().max(VIEW_PROPERTIES_ICON_MAX_LENGTH).optional().describe('An optional icon identifier or URL for this element.'),\n })\n .strict();\n\n// ============================================================\n// Intents\n// ============================================================\n\n/**\n * Validation schema for the base intent structure. Describes the common data parameters shared\n * by all intent types regardless of what they target.\n *\n * An optional templateIdentifier allows the intent to reference a target defined in a different\n * template, enabling cross-template interaction.\n *\n * Extended by: xoTemplateActionIntentSchema, xoTemplateOutputIntentSchema,\n * xoTemplateLockingScriptIntentSchema.\n */\nexport const xoTemplateIntentSchema = z\n .object({\n templateIdentifier: z\n .string()\n .optional()\n .describe('Optional identifier for the template used in this intent. If not provided, uses the current template.'),\n role: z.string().optional().describe('Optional identifier for the role used in this intent.'),\n generate: z.array(z.string()).optional().describe('Identifiers for items to generate when this intent is resolved, e.g. keys or secrets.'),\n variables: z.array(z.record(z.string(), z.unknown())).optional().describe('Variable values to apply when this intent is resolved.'),\n constants: z.array(z.record(z.string(), z.unknown())).optional().describe('Constant values to apply when this intent is resolved.'),\n secrets: z.array(z.record(z.string(), z.unknown())).optional().describe('Secret values to apply when this intent is resolved.'),\n })\n .strict();\n\n/**\n * Validation schema for an action intent. Extends the base intent structure with an action\n * identifier. Used in locking script action lists and in the template's start array.\n *\n * ```\n * {\n * \"start\": [\n * { \"action\": \"...\" } ← this schema\n * ],\n * \"lockingScripts\": {\n * \"[id]\": {\n * \"actions\": [\n * { \"action\": \"...\" } ← this schema\n * ],\n * \"roles\": {\n * \"[roleId]\": {\n * \"actions\": [\n * { \"action\": \"...\" } ← this schema\n * ]\n * }\n * }\n * }\n * }\n * }\n * ```\n */\nexport const xoTemplateActionIntentSchema = xoTemplateIntentSchema\n .extend({\n action: z.string().describe('The identifier for the intended action.'),\n })\n .strict();\n\n/**\n * Validation schema for an output intent. Extends the base intent structure with an output\n * identifier. Used in the template's defaults block.\n *\n * ```\n * {\n * \"defaults\": {\n * \"change\": { \"output\": \"...\" } ← this schema\n * }\n * }\n * ```\n */\nexport const xoTemplateOutputIntentSchema = xoTemplateIntentSchema\n .extend({\n output: z.string().describe('The identifier for the intended output.'),\n })\n .strict();\n\n/**\n * Validation schema for a locking script intent. Extends the base intent structure with\n * a locking script identifier.\n *\n * @todo The location of this schema in the template JSON is not yet determined.\n */\nexport const xoTemplateLockingScriptIntentSchema = xoTemplateIntentSchema\n .extend({\n lockingScript: z.string().describe('The identifier for the intended locking script.'),\n })\n .strict();\n\n// ============================================================\n// Actions\n// ============================================================\n\n/**\n * Validation schema for the slot count configuration on a role requirement. Declares how many\n * participants of a given role are needed. min sets the lower bound and max sets the upper bound.\n * When max is absent, there is no upper limit.\n *\n * ```\n * {\n * \"actions\": {\n * \"[id]\": {\n * \"requirements\": {\n * \"participants\": [\n * { \"slots\": { \"min\": 1, \"max\": 1 } } ← this schema\n * ]\n * }\n * }\n * }\n * }\n * ```\n */\nexport const xoTemplateRoleSlotsRequirementsSchema = z\n .object({\n min: z.number().describe('Minimum number of participants required for this role.'),\n max: z.number().optional().describe('Maximum number of participants allowed for this role. Undefined means unlimited.'),\n })\n .strict();\n\n/**\n * Validation schema for the capability requirements declared on a role within an action.\n * Describes what data, secrets, or state the role is responsible for providing when participating in an action.\n *\n * ```\n * {\n * \"actions\": {\n * \"[id]\": {\n * \"roles\": {\n * \"[roleId]\": {\n * \"requirements\": { \"variables\": [], \"secrets\": [] } ← this schema\n * }\n * }\n * }\n * }\n * }\n * ```\n */\nexport const xoTemplateActionRoleRequirementsSchema = z\n .object({\n variables: z.array(z.string()).optional().describe('List of variable identifiers required for this role.'),\n secrets: z.array(z.string()).optional().describe('List of secret identifiers required for this role.'),\n })\n .strict();\n\n/**\n * Validation schema for a role-specific definition within an action.\n * All view properties are optional.\n *\n * ```\n * {\n * \"actions\": {\n * \"[id]\": {\n * \"roles\": {\n * \"[roleId]\": { } ← this schema\n * }\n * }\n * }\n * }\n * ```\n */\nexport const xoTemplateActionRoleSchema = xoTemplateViewPropertiesSchema\n .partial()\n .extend({\n generate: z\n .array(z.string())\n .optional()\n .describe('Identifiers for data items that should be generated for this role when participating in the action.'),\n\n // Describes under what conditions this role can proceed with the action. All values listed\n // under requirements must be populated for the action to work. This is a developer and\n // author concern. It is not present on intents because intents are used to populate the\n // action rather than to define it, and their fields are flattened accordingly.\n requirements: xoTemplateActionRoleRequirementsSchema.optional().describe('The requirements for this role within this action.'),\n })\n .strict();\n\n/**\n * Validation schema for a role participation requirement in an action's requirements block.\n *\n * ```\n * {\n * \"actions\": {\n * \"[id]\": {\n * \"requirements\": {\n * \"participants\": [\n * { \"role\": \"...\", \"slots\": { } } ← this schema\n * ]\n * }\n * }\n * }\n * }\n * ```\n */\nexport const xoTemplateRoleSlotSchema = z\n .object({\n role: z.string().describe('The role identifier that this requirement applies to.'),\n slots: xoTemplateRoleSlotsRequirementsSchema.describe('Slot configuration specifying how many participants of this role are required.'),\n })\n .strict();\n\n/**\n * Validation schema for the requirements of an action.\n *\n * ```\n * {\n * \"actions\": {\n * \"[id]\": {\n * \"requirements\": { \"variables\": [], \"participants\": [], \"secrets\": [] } ← this schema\n * }\n * }\n * }\n * ```\n */\nexport const xoTemplateActionRequirementsSchema = z\n .object({\n variables: z.array(z.string()).optional().describe('List of variable identifiers required for this action.'),\n participants: z.array(xoTemplateRoleSlotSchema).optional().describe('The participants required for this action.'),\n secrets: z.array(z.string()).optional().describe('The secrets required for this action.'),\n })\n .strict();\n\n/**\n * Validation schema for an action definition.\n *\n * ```\n * {\n * \"actions\": {\n * \"[id]\": { } ← this schema\n * }\n * }\n * ```\n */\nexport const xoTemplateActionSchema = xoTemplateViewPropertiesSchema\n .extend({\n roles: z.record(z.string(), xoTemplateActionRoleSchema).optional().describe('Specific context for each role participating in this action.'),\n requirements: xoTemplateActionRequirementsSchema.optional().describe('The requirements for this action.'),\n\n // This is a list of conditions that can influence how the action behaves.\n // This needs more work to be done.\n conditions: z.array(z.string()).optional().describe('Conditions that must be met for this action to be available.'),\n\n // A single transaction produced by the action.\n // In future this might be moved to a results block that can have multiple transactions.\n transaction: z\n .string()\n .optional()\n .describe(\"The identifier of the transaction this action produces, referencing an entry in the template's transactions.\"),\n\n // The data that is produced by the action.\n // In future this might be moved to a results block that can have multiple data fields.\n data: z.string().optional().describe(\"The identifier of the data field this action produces, referencing an entry in the template's data.\"),\n })\n .strict();\n\n// ============================================================\n// Tokens & Amounts\n// ============================================================\n\n/**\n * Validation schema for the non-fungible token configuration within a token field.\n *\n * ```\n * {\n * \"inputs|outputs\": {\n * \"[id]\": {\n * \"token\": {\n * \"nft\": { } ← this schema\n * }\n * }\n * }\n * }\n * ```\n */\nexport const xoTemplateNonFungibleTokenDetailsSchema = z\n .object({\n capability: z\n .union([ xoTemplateNftCapabilitySchema, z.string() ])\n .optional()\n .describe('The capability of the NFT. May be a known capability value or a CashASM expression resolving to a capability.'),\n commitment: z.string().optional().describe('The commitment data for the NFT, as a string or CashASM expression resolving to a commitment.'),\n })\n .strict();\n\n/**\n * Validation schema for the token configuration on inputs and outputs.\n *\n * ```\n * {\n * \"inputs|outputs\": {\n * \"[id]\": {\n * \"token\": { } ← this schema\n * }\n * }\n * }\n * ```\n */\nexport const xoTemplateTokenSchema = z\n .object({\n category: z.string().optional().describe('The category of the token, as a string or CashASM expression resolving to a category.'),\n amount: z\n .union([ z.bigint(), z.string(), z.null() ])\n .optional()\n .describe('The amount of fungible tokens as a bigint, a CashASM expression resolving to a bigint, or null indicating no FT is present.'),\n nft: xoTemplateNonFungibleTokenDetailsSchema\n .nullable()\n .optional()\n .describe('Non-fungible token configuration. Null indicates no NFT is present.'),\n })\n .strict();\n\n/**\n * Validation schema for the asset amounts configuration. Used by omitChangeAmounts on inputs\n * and by balance on locking scripts, outputs, and their roles.\n */\nexport const xoTemplateAssetAmountsSchema = z\n .object({\n\n /**\n * The satoshi amount.\n * - `Satoshis`: A specific bigint amount.\n * - `string`: A CashASM expression that resolves to the amount.\n * - `true`: all, i.e. the entire amount\n */\n satoshis: z\n .union([ satoshisSchema, z.string(), z.literal(true) ])\n .optional()\n .describe('The satoshi amount. Accepts a bigint for a specific value, a CashASM expression, or true for the entire amount.'),\n\n /**\n * The fungible token amount.\n * - `FungibleTokenAmount`: A specific bigint amount.\n * - `string`: A CashASM expression that resolves to the amount.\n * - `true`: all, i.e. the entire amount\n */\n fungibleTokens: z\n .union([ z.bigint(), z.string(), z.literal(true) ])\n .optional()\n .describe('The fungible token amount. Accepts a bigint for a specific value, a CashASM expression, or true for the entire amount.'),\n\n /**\n * Whether a non-fungible token is present (0 for absent, 1 for present),\n * or a CashASM expression that evaluates to 0 or 1.\n * - `true`: resolves to 1 if an NFT is present, or 0 if none is present. Use this when\n * the NFT is optional, to express that the NFT is estimated to be part of the balance\n * if present, or absent from it if not.\n * - `0`: None, i.e. nothing is expected to be included\n * - `1`: present and complete, as value > 1 does not make sense for non-fungible tokens\n * - `string`: A CashASM expression that evaluates to 0 or 1.\n */\n nonfungibleTokens: z\n .union([ z.literal(0), z.literal(1), z.string(), z.literal(true) ])\n .optional()\n .describe('Whether an NFT is present: 0 for absent, 1 for present, a CashASM expression evaluating to 0 or 1, or true to estimate the NFT as part of the balance if present, or absent from it if not.'),\n })\n .strict();\n\n// ============================================================\n// Locking Scripts\n// ============================================================\n\n/**\n * Validation schema for the state configuration shared by a locking script and its individual roles.\n * Declares which variables and secrets are tracked in the on-chain state for a given participant.\n *\n * ```\n * {\n * \"lockingScripts\": {\n * \"[id]\": {\n * \"state\": { \"variables\": [], \"secrets\": [] } ← this schema\n * \"roles\": {\n * \"[roleId]\": {\n * \"state\": { \"variables\": [], \"secrets\": [] } ← this schema\n * }\n * }\n * }\n * }\n * }\n * ```\n */\nexport const xoTemplateStateSchema = z\n .object({\n variables: z.array(z.string()).optional().describe('List of variable identifiers to track in state.'),\n secrets: z.array(z.string()).optional().describe('List of secret identifiers to track in state.'),\n })\n .strict();\n\n/**\n * Validation schema for a role definition for a locking script.\n *\n * ```\n * {\n * \"lockingScripts\": {\n * \"[id]\": {\n * \"roles\": {\n * \"[roleId]\": { } ← this schema\n * }\n * }\n * }\n * }\n * ```\n */\nexport const xoTemplateLockingScriptRoleSchema = xoTemplateViewPropertiesSchema\n .partial()\n .extend({\n state: xoTemplateStateSchema.optional().describe('List of items to track as state for this role.'),\n actions: z.array(xoTemplateActionIntentSchema).optional().describe('List of action references available to this role.'),\n balance: xoTemplateAssetAmountsSchema.partial().optional().describe('Estimated ownership in the optional set of asset amounts specified.'),\n selectable: z.boolean().optional().describe('Whether outputs locked to this script should be available for coin selection.'),\n relevant: z\n .union([ z.boolean(), z.string() ])\n .optional()\n .describe('Whether this output or locking script should be tracked by the engine, When omitted, the engine treats this field as true.'\n + 'Accepts true, false, or a CashASM expression that evaluates to a boolean relevance value.'),\n privacy: z\n .union([ z.number(), z.string() ])\n .optional()\n .describe('Privacy level for outputs locked to this script. A numeric level or a CashASM expression that evaluates to a privacy level.'),\n })\n .strict();\n\n/**\n * Validation schema for a locking script definition.\n *\n * ```\n * {\n * \"lockingScripts\": {\n * \"[id]\": { } ← this schema\n * }\n * }\n * ```\n */\nexport const xoTemplateLockingScriptSchema = xoTemplateViewPropertiesSchema\n .extend({\n lockingType: xoTemplateLockingTypeSchema.optional().describe('The type of locking mechanism. Defaults to p2s if not specified.'),\n lockingBytecode: z.string().describe('The locking script bytecode.'),\n unlockingBytecode: z.string().optional().describe('Optional default unlocking bytecode when used in automatic coin selection.'),\n actions: z.array(xoTemplateActionIntentSchema).optional().describe('The actions available for this locking script.'),\n state: xoTemplateStateSchema.optional().describe('List of items to track as state for all participants.'),\n balance: xoTemplateAssetAmountsSchema.partial().optional().describe('Estimated ownership in the optional set of asset amounts specified.'),\n selectable: z.boolean().optional().describe('Whether outputs locked to this script should be available for coin selection.'),\n // Might be levels or tags\n privacy: z\n .union([ z.number(), z.string() ])\n .optional()\n .describe('Privacy level for outputs locked to this script. A numeric level or a CashASM expression that evaluates to a privacy level.'),\n roles: z\n .record(z.string(), xoTemplateLockingScriptRoleSchema)\n .optional()\n .describe('Specific context for each role participating in this locking script.'),\n })\n .strict();\n\n// ============================================================\n// Inputs\n// ============================================================\n\n/**\n * Validation schema for an input definition in the template. Extends view properties with optional\n * satoshi value, token configuration, and other transaction level fields.\n *\n * ```\n * {\n * \"inputs\": {\n * \"[id]\": { } ← this schema\n * }\n * }\n * ```\n */\nexport const xoTemplateInputSchema = xoTemplateViewPropertiesSchema\n .extend({\n valueSatoshis: z\n .union([ satoshisSchema, z.string() ])\n .optional()\n .describe('The amount of satoshis for this input as a bigint or a CashASM expression resolving to the amount.'),\n token: xoTemplateTokenSchema.nullable().optional().describe('Token configuration for this input.'),\n sequenceNumber: z\n .union([ z.number(), z.string() ])\n .optional()\n .describe('The sequence number of this input as a specific number or a CashASM expression.'),\n unlockingScript: z.string().optional().describe('Identifier of the unlocking script to use for the UTXO provided for this input.'),\n omitChangeAmounts: xoTemplateAssetAmountsSchema\n .optional()\n .describe('Amount of change that should be omitted from the automatic change handling. WARNING: Setting this can result in loss of funds!'),\n })\n .strict();\n\n// ============================================================\n// Outputs\n// ============================================================\n\n/**\n * Validation schema for an output definition. Extends the locking script schema so that\n * every output inherits the same locking script fields and adds output-specific fields.\n *\n * ```\n * {\n * \"outputs\": {\n * \"[id]\": { } ← this schema\n * }\n * }\n * ```\n */\nexport const xoTemplateOutputSchema = xoTemplateLockingScriptSchema\n .omit({ lockingType: true, lockingBytecode: true, unlockingBytecode: true })\n .extend({\n lockingScript: z.string().describe('Identifier of the locking script to use for this output.'),\n valueSatoshis: z\n .union([ satoshisSchema, z.string() ])\n .optional()\n .describe('The amount of satoshis for this output as a bigint or a CashASM expression resolving to the amount.'),\n token: xoTemplateTokenSchema.nullable().optional().describe('Token configuration for this output.'),\n })\n .strict();\n\n// ============================================================\n// Transactions\n// ============================================================\n\n/**\n * Validation schema for a transaction input reference for a transaction definition.\n *\n * ```\n * {\n * \"transactions\": {\n * \"[id]\": {\n * \"inputs\": [\n * { \"input\": \"...\" } ← this schema\n * ]\n * }\n * }\n * }\n * ```\n */\nexport const xoTemplateTransactionInputSchema = z\n .object({\n input: z.string().describe('The input definition identifier.'),\n inputIndex: z.number().optional().describe('Optional index of this input in the transaction.'),\n })\n .strict();\n\n/**\n * Validation schema for a transaction output reference for a transaction definition.\n *\n * ```\n * {\n * \"transactions\": {\n * \"[id]\": {\n * \"outputs\": [\n * { \"output\": \"...\" } ← this schema\n * ]\n * }\n * }\n * }\n * ```\n */\nexport const xoTemplateTransactionOutputSchema = z\n .object({\n output: z.string().describe('The output definition identifier.'),\n outputIndex: z.number().optional().describe('Optional index of this output in the transaction.'),\n })\n .strict();\n\n/**\n * Validation schema for role-specific data for a transaction definition.\n *\n * ```\n * {\n * \"transactions\": {\n * \"[id]\": {\n * \"roles\": {\n * \"[roleId]\": { } ← this schema\n * }\n * }\n * }\n * }\n * ```\n */\nexport const xoTemplateTransactionRoleDataSchema = xoTemplateViewPropertiesSchema\n .partial()\n .extend({\n inputs: z.array(xoTemplateTransactionInputSchema).optional().describe('The inputs required for this role.'),\n outputs: z.array(xoTemplateTransactionOutputSchema).optional().describe('The outputs required for this role.'),\n })\n .strict();\n\n/**\n * Validation schema for a transaction template definition.\n *\n * ```\n * {\n * \"transactions\": {\n * \"[id]\": { } ← this schema\n * }\n * }\n * ```\n */\nexport const xoTemplateTransactionSchema = xoTemplateViewPropertiesSchema\n .extend({\n version: z.number().optional().describe('The version of the transaction.'),\n locktime: z\n .union([ z.number(), z.string() ])\n .optional()\n .describe('The locktime for this transaction as a specific number or a CashASM expression.'),\n inputs: z.array(xoTemplateTransactionInputSchema).describe('The inputs for this transaction.'),\n outputs: z.array(xoTemplateTransactionOutputSchema).describe('The outputs for this transaction.'),\n roles: z\n .record(z.string(), xoTemplateTransactionRoleDataSchema)\n .optional()\n .describe('Specific context for each role participating in this transaction.'),\n composable: z.boolean().optional().describe('Whether this transaction can be composed with other transactions.'),\n })\n .strict();\n\n// ============================================================\n// Template Data\n// ============================================================\n\n/**\n * Validation schema for a constant value definition.\n *\n * ```\n * {\n * \"constants\": {\n * \"[id]\": { } ← this schema\n * }\n * }\n * ```\n */\nexport const xoTemplateConstantSchema = xoTemplateViewPropertiesSchema\n .extend({\n type: xoTemplatePrimitiveTypeSchema.describe('The data type of this constant.'),\n value: z.unknown().describe('The value of this constant.'),\n hint: z.unknown().optional().describe('An optional hint to help apps and users understand what this constant represents.'),\n })\n .strict();\n\n/**\n * Validation schema for a data field definition.\n *\n * ```\n * {\n * \"data\": {\n * \"[id]\": { } ← this schema\n * }\n * }\n * ```\n */\nexport const xoTemplateDataSchema = z\n .object({\n type: xoTemplatePrimitiveTypeSchema.describe('The data type of this data field.'),\n value: z.unknown().describe('The value for this data field.'),\n hint: z.unknown().optional().describe('An optional hint to help apps and users understand this data field.'),\n })\n .strict();\n\n/**\n * Validation schema for an import default value intent. Extends the base intent with optional\n * view properties that the engine evaluates at runtime to produce human-readable output.\n *\n * ```\n * {\n * \"variables\": {\n * \"[id]\": {\n * \"importDefaultValue\": { } ← this schema\n * }\n * }\n * }\n * ```\n */\nexport const xoTemplateImportDefaultValueSchema = xoTemplateIntentSchema\n // .shape unwraps the ZodObject to the raw field map { name, description, icon } with each field made optional\n .extend(xoTemplateViewPropertiesSchema.partial().shape)\n .strict();\n\n/**\n * Validation schema for a variable definition.\n *\n * ```\n * {\n * \"variables\": {\n * \"[id]\": { } ← this schema\n * }\n * }\n * ```\n */\nexport const xoTemplateVariableSchema = xoTemplateViewPropertiesSchema\n .extend({\n type: xoTemplatePrimitiveTypeSchema.optional().describe('The data type of this variable.'),\n hint: z.unknown().optional().describe('A hint to help users understand what value to provide.'),\n\n // A neutral intent that the engine uses to populate the default value for this variable.\n // View properties (name, description, icon) may contain CashASM expressions that the\n // engine evaluates at runtime to produce human-readable output. The engine overrides\n // whatever values are set here when resolving the variable for a participant.\n importDefaultValue: xoTemplateImportDefaultValueSchema\n .optional()\n .describe('A neutral intent that the engine uses to populate the default value for this variable.'),\n })\n .strict();\n\n// ============================================================\n// Template Resources\n// ============================================================\n\n/**\n * Validation schema for a resource reference attached to a template element. Extends view\n * properties with a URL pointing to external documentation or tooling.\n *\n * ```\n * {\n * \"resources\": [\n * { \"name\": \"...\", \"description\": \"...\", \"url\": \"...\" } ← this schema\n * ]\n * }\n * ```\n */\nexport const xoTemplateResourceSchema = xoTemplateViewPropertiesSchema\n .extend({\n url: z.string().describe('The URL for this resource.'),\n })\n .strict();\n\n/**\n * Validation schema for an icon reference.\n *\n * ```\n * {\n * \"icons\": [\n * { \"name\": \"...\", \"hash\": \"...\" } ← this schema\n * ]\n * }\n * ```\n */\nexport const xoTemplateIconSchema = xoTemplateViewPropertiesSchema\n .pick({ name: true })\n .extend({\n hash: z.string().describe('The identifier of the icon.'),\n })\n .strict();\n\n// ============================================================\n// Defaults\n// ============================================================\n\n/**\n * Validation schema for the defaults block of a template.\n *\n * ```\n * {\n * \"defaults\": { } ← this schema\n * }\n * ```\n */\nexport const xoTemplateDefaultsSchema = z\n .object({\n change: xoTemplateOutputIntentSchema.optional().describe('Instructions for how to construct automated change output.'),\n })\n .strict();\n\n// ============================================================\n// Template\n// ============================================================\n\n/**\n * Validation schema for the full XOTemplate type.\n */\nexport const xoTemplateSchema = xoTemplateViewPropertiesSchema\n .extend({\n $schema: z\n .string()\n .describe('The URI that identifies the JSON Schema used by this template. This enables documentation, autocompletion, and validation in JSON documents.'),\n version: z.string().optional().describe('A string identifying the version of this template.'),\n supported: z.array(bchVmVersionSchema).min(1).describe('The BCH VM versions that this template supports. At least one version is required.'),\n defaults: xoTemplateDefaultsSchema.optional().describe('Optional default settings used in this template.'),\n roles: z.record(z.string(), xoTemplateViewPropertiesSchema).describe('The roles defined in this template.'),\n start: z.array(xoTemplateActionIntentSchema).describe('A list of entry points defining which actions are available at the start.'),\n actions: z.record(z.string(), xoTemplateActionSchema).describe('The actions defined in this template.'),\n data: z.record(z.string(), xoTemplateDataSchema).optional().describe('The data fields defined in this template.'),\n transactions: z.record(z.string(), xoTemplateTransactionSchema).optional().describe('The transaction templates defined in this template.'),\n inputs: z.record(z.string(), xoTemplateInputSchema).describe('The inputs defined in this template.'),\n outputs: z.record(z.string(), xoTemplateOutputSchema).describe('The outputs defined in this template.'),\n lockingScripts: z.record(z.string(), xoTemplateLockingScriptSchema).describe('The locking script templates defined in this template.'),\n scripts: z\n .record(z.string(), z.string())\n .describe('Scripts used in this template. Keys are script identifiers, values are bytecode or CashASM expressions.'),\n constants: z.record(z.string(), xoTemplateConstantSchema).optional().describe('The constants defined in this template.'),\n variables: z\n .record(z.string(), xoTemplateVariableSchema)\n .optional()\n .describe(\"The variables that must be provided for use in the template's scripts.\"),\n resources: z.array(xoTemplateResourceSchema).optional().describe('Resource references providing external documentation or tooling links.'),\n icons: z.array(xoTemplateIconSchema).optional().describe('The icons available for use throughout the template.'),\n scenarios: z.unknown().optional().describe('The scenarios defined in this template.'),\n })\n .strict();\n","import type { XOTemplate } from '@xo-cash/types';\nimport { xoTemplateSchema } from './schemas.ts';\nimport { TemplateInvalidError, buildErrorDescription } from './errors.ts';\nimport { deserializeTemplate, serializeTemplate } from './serialization.ts';\n\n/**\n * Accepts a template value and returns a validated XOTemplate object. The input may be\n * either an Extended JSON string or a pre-parsed object. Both are validated\n * against the XOTemplate schema.\n *\n * @param inputTemplate - The value to validate. May be an Extended JSON string or a pre-parsed object.\n * @returns The validated template object\n * @throws {TemplateSerializationFailedError} If a pre-parsed object input cannot be serialized to JSON for normalization.\n * @throws {TemplateJsonMalformedError} If the string input is not valid JSON.\n * @throws {TemplateInvalidError} If the value does not conform to the XOTemplate schema.\n */\nexport const parseTemplate = (inputTemplate: string | XOTemplate): XOTemplate => {\n // Regardless of whether the inputTemplate is a string, an imported template or an in-memory object, serialize and then\n // deserialize it to ensure the output shape is consistent. For example, optional fields explicitly set to 'undefined' would be passed through\n // and then dropped on the string path, resulting in structurally different results for the same template.\n const serializedTemplate = typeof inputTemplate === 'string' ? inputTemplate : serializeTemplate(inputTemplate);\n const templateObject = deserializeTemplate(serializedTemplate);\n\n // Validate the template against the schema.\n const parseResult = xoTemplateSchema.safeParse(templateObject);\n\n if (parseResult.success) {\n // Return the validated template object\n return parseResult.data as XOTemplate;\n }\n\n // Build a human-readable description of every validation failure\n const errorDescription = buildErrorDescription(parseResult.error.issues);\n\n // Throw a typed error with the description\n throw new TemplateInvalidError(errorDescription);\n};\n","/* eslint-disable max-classes-per-file */\nimport type { IdentifierResolutionType } from '@bitauth/libauth';\n\n/**\n * Error thrown when a required variable is missing.\n */\nexport class CashAssemblyRequiredVariableMissingError extends Error {\n /**\n * Variable names that were required but absent from the variables map.\n */\n readonly variableNames: string[];\n\n constructor(variableNames: string[] = []) {\n const defaultMessage = 'Missing required variable';\n if (variableNames.length > 0) {\n super(`${defaultMessage}: variableNames [${variableNames.join(', ')}]`);\n } else {\n super(defaultMessage);\n }\n\n this.variableNames = variableNames;\n }\n}\n\n/**\n * Error thrown when cash assembly compilation fails.\n */\nexport class CashAssemblyCompilationFailedError extends Error {\n constructor(message?: string) {\n const defaultMessage = 'Cash assembly compilation failed';\n super(message ? `${defaultMessage}: ${message}` : defaultMessage);\n }\n}\n\n/**\n * Error thrown when a quoted string inside `$()` never closes.\n */\nexport class CashAssemblyQuotedLiteralUnclosedError extends Error {\n /**\n * Index of the opening quote that never found a closer.\n */\n readonly openingQuoteIndex: number;\n\n /**\n * Quote character that opened the literal.\n */\n readonly quoteCharacter: string;\n\n /**\n * Text from the opening quote through the end of the scanned string.\n */\n readonly unclosedText: string;\n\n constructor(openingQuoteIndex: number, quoteCharacter: string, cashAssemblyText: string) {\n const unclosedText = cashAssemblyText.slice(openingQuoteIndex);\n const defaultMessage = 'Quoted literal in a CashAssembly evaluation is unclosed';\n const details = [\n `quoteCharacter ${JSON.stringify(quoteCharacter)}`,\n `openingQuoteIndex ${String(openingQuoteIndex)}`,\n `unclosedText ${JSON.stringify(unclosedText)}`,\n ].join(', ');\n\n super(`${defaultMessage}: ${details}`);\n\n this.openingQuoteIndex = openingQuoteIndex;\n this.quoteCharacter = quoteCharacter;\n this.unclosedText = unclosedText;\n }\n}\n\n/**\n * Error thrown when a block comment inside `$()` never closes.\n */\nexport class CashAssemblyBlockCommentUnclosedError extends Error {\n /**\n * Index of the first slash of the block comment opener.\n */\n readonly commentStartIndex: number;\n\n /**\n * Text from the block comment opener through the end of the scanned string.\n */\n readonly unclosedText: string;\n\n constructor(commentStartIndex: number, cashAssemblyText: string) {\n const unclosedText = cashAssemblyText.slice(commentStartIndex);\n const defaultMessage = 'Block comment in a CashAssembly evaluation is unclosed';\n const details = [ `commentStartIndex ${String(commentStartIndex)}`, `unclosedText ${JSON.stringify(unclosedText)}` ].join(', ');\n\n super(`${defaultMessage}: ${details}`);\n\n this.commentStartIndex = commentStartIndex;\n this.unclosedText = unclosedText;\n }\n}\n\n/**\n * Error thrown when a `$()` evaluation never finds its matching closer.\n */\nexport class CashAssemblyEvaluationUnclosedError extends Error {\n /**\n * Index of the `$` that opened the evaluation.\n */\n readonly evaluationStartIndex: number;\n\n /**\n * How many `$()` remain open at the end of the string, including nested evaluations.\n */\n readonly remainingOpenEvaluations: number;\n\n /**\n * Text from the opening `$` through the end of the scanned string.\n */\n readonly unclosedText: string;\n\n constructor(evaluationStartIndex: number, remainingOpenEvaluations: number, cashAssemblyText: string) {\n const unclosedText = cashAssemblyText.slice(evaluationStartIndex);\n const defaultMessage = 'CashAssembly evaluation is unclosed';\n const details = [\n `evaluationStartIndex ${String(evaluationStartIndex)}`,\n `remainingOpenEvaluations ${String(remainingOpenEvaluations)}`,\n `unclosedText ${JSON.stringify(unclosedText)}`,\n ].join(', ');\n\n super(`${defaultMessage}: ${details}`);\n\n this.evaluationStartIndex = evaluationStartIndex;\n this.remainingOpenEvaluations = remainingOpenEvaluations;\n this.unclosedText = unclosedText;\n }\n}\n\n/**\n * Error thrown when a variable's runtime type does not match the type required for compilation.\n */\nexport class CashAssemblyVariableTypeMismatchError extends Error {\n constructor(variableKey: string, expectedType: string, actualType: string) {\n const defaultMessage = 'Variable type mismatch';\n super(`${defaultMessage}: variableKey \"${variableKey}\", expected ${expectedType}, got ${actualType}`);\n }\n}\n\n/**\n * Error thrown when a method resolvable primitive type does not expose the requested method.\n */\nexport class CashAssemblyPrimitiveMethodMissingError extends Error {\n constructor(identifier: string, methodName: string, type: string) {\n const defaultMessage = 'CashAssembly primitive method does not exist';\n super(`${defaultMessage}: identifier \"${identifier}\", methodName \"${methodName}\", type \"${type}\"`);\n }\n}\n\n/**\n * Error thrown when a value cannot be resolved as bytes.\n */\nexport class CashAssemblyUnsupportedValueTypeError extends Error {\n constructor(identifier: string, returnedType: string) {\n const defaultMessage = 'CashAssembly value type is unsupported for byte resolution';\n super(`${defaultMessage}: identifier \"${identifier}\", returnedType \"${returnedType}\"`);\n }\n}\n\n/**\n * Error thrown when a number cannot be safely encoded as a CashAssembly VM number.\n */\nexport class CashAssemblyNumberNotSafeIntegerError extends Error {\n constructor(identifier: string, value: number) {\n const defaultMessage = 'CashAssembly number is not a safe integer';\n super(`${defaultMessage}: identifier \"${identifier}\", got ${String(value)}`);\n }\n}\n\n/**\n * Error thrown when a method resolvable primitive is selected but its value is missing from the variables map.\n */\nexport class CashAssemblyPrimitiveVariableMissingError extends Error {\n constructor(identifier: string, variableName: string) {\n const defaultMessage = 'CashAssembly primitive variable is missing from the variables map';\n super(`${defaultMessage}: identifier \"${identifier}\", variableName \"${variableName}\"`);\n }\n}\n\n/**\n * Error thrown when one identifier would resolve as more than one {@link IdentifierResolutionType}.\n */\nexport class CashAssemblyIdentifierCollisionError extends Error {\n /**\n * Identifier that more than one resolution type would match.\n */\n readonly identifier: string;\n\n /**\n * The list of resolution types that the identifier matches.\n */\n readonly resolutionTypes: IdentifierResolutionType[];\n\n constructor(identifier: string, resolutionTypes: IdentifierResolutionType[]) {\n const defaultMessage = 'CashAssembly identifier exists for more than one resolution type';\n\n super(`${defaultMessage}: identifier \"${identifier}\", resolutionTypes [${resolutionTypes.join(', ')}]`);\n\n this.identifier = identifier;\n this.resolutionTypes = resolutionTypes;\n }\n}\n\n/**\n * Error thrown when compiled evaluation bytes cannot be decoded as a VM number.\n */\nexport class CashAssemblyVmNumberDecodeError extends Error {\n constructor(reason: string) {\n const defaultMessage = 'CashAssembly evaluation could not be decoded as a VM number';\n super(`${defaultMessage}: ${reason}`);\n }\n}\n","import { describeExpectedInput, parseScript } from '@bitauth/libauth';\nimport type { CashAssemblyScriptSegment } from '@bitauth/libauth';\nimport { CashAssemblyCompilationFailedError } from './errors.ts';\nimport type { CashAssemblyTemplateScripts } from './types.ts';\n\n/**\n * Shared state while scanning a parse tree and visiting nested template scripts.\n */\ntype CollectFromParseTreeContext = {\n\n /**\n * Script ids present in the template scripts map.\n */\n knownScriptIdentifiers: ReadonlySet<string>;\n\n /**\n * Script ids whose sources were already visited.\n */\n visitedScriptIdentifiers: ReadonlySet<string>;\n\n /**\n * Pending script ids queued to visit.\n */\n scriptIdentifiersToVisit: string[];\n\n /**\n * WalletData variable names.\n */\n variableNames: Set<string>;\n};\n\n/**\n * Parameters for scanning one parsed Script node.\n */\ntype CollectFromParsedScriptParameters = CollectFromParseTreeContext & {\n\n /**\n * Parsed Script whose children are Push, Evaluation, Identifier, or literals.\n */\n scriptSegment: CashAssemblyScriptSegment;\n\n /**\n * True when this Script is the value of a Push.\n * Direct Identifier children are WalletData unless they are template script ids.\n */\n isDirectPushContent: boolean;\n};\n\n/**\n * Parameters for handling one Identifier node.\n */\ntype CollectFromParsedIdentifierParameters = CollectFromParseTreeContext & {\n\n /**\n * Identifier text from parseScript, which may include `.` and `_`.\n */\n identifier: string;\n\n /**\n * True when this Identifier is a direct child of a Push Script.\n */\n isDirectPushContent: boolean;\n};\n\n/**\n * Enqueues a template script id so its source can be visited when it exists in the scripts map.\n *\n * @param {string} scriptIdentifier - Script id from an evaluation or nested script source.\n * @param {ReadonlySet<string>} knownScriptIdentifiers - Script ids present in the template scripts map.\n * @param {ReadonlySet<string>} visitedScriptIdentifiers - Script ids whose sources were already visited.\n * @param {string[]} scriptIdentifiersToVisit - Pending script ids queued to visit.\n */\nconst enqueueReachableTemplateScriptIdentifier = (\n scriptIdentifier: string,\n knownScriptIdentifiers: ReadonlySet<string>,\n visitedScriptIdentifiers: ReadonlySet<string>,\n scriptIdentifiersToVisit: string[],\n): void => {\n // Return when this id is not a template script.\n if (knownScriptIdentifiers.has(scriptIdentifier) === false) {\n return;\n }\n\n // Skip ids whose sources were already visited.\n if (visitedScriptIdentifiers.has(scriptIdentifier) === true) {\n return;\n }\n\n // Avoid duplicate queue entries when the same id is referenced more than once.\n if (scriptIdentifiersToVisit.includes(scriptIdentifier) === true) {\n return;\n }\n\n // Queue this id so its source is parsed after the current scan finishes.\n scriptIdentifiersToVisit.push(scriptIdentifier);\n};\n\n/**\n * Parses CashAssembly source with parseScript and throws when the parse fails.\n *\n * @param {string} cashAssemblyText - Evaluation or script source to parse.\n * @returns {CashAssemblyScriptSegment} - Parsed Script root.\n * @throws {@link CashAssemblyCompilationFailedError} - When parseScript rejects the source.\n */\nconst parseCashAssemblySource = (cashAssemblyText: string): CashAssemblyScriptSegment => {\n // Parse so Push and Identifier nodes are available for collection.\n const parseResult = parseScript(cashAssemblyText);\n\n // parseScript returns a union. status false is the failure arm and must not be read as a Script.\n if (parseResult.status === false) {\n // describeExpectedInput turns the expected input list into readable text for the typed error.\n const expectedInputDescription = describeExpectedInput(parseResult.expected);\n\n throw new CashAssemblyCompilationFailedError(`${expectedInputDescription} Line ${String(parseResult.index.line)}, column ${String(parseResult.index.column)}.`);\n }\n\n return parseResult.value;\n};\n\n/**\n * Identifier visitor for the parseScript tree.\n * Records WalletData or queues a nested script from one Identifier node.\n *\n * @param {CollectFromParsedIdentifierParameters} parameters - Identifier text and the parse tree context.\n */\nconst collectFromParsedIdentifier = (parameters: CollectFromParsedIdentifierParameters): void => {\n const { identifier, isDirectPushContent, knownScriptIdentifiers, visitedScriptIdentifiers, scriptIdentifiersToVisit, variableNames } = parameters;\n\n // Script ids are visited whether they appear in a Push or beside opcodes.\n if (knownScriptIdentifiers.has(identifier) === true) {\n enqueueReachableTemplateScriptIdentifier(identifier, knownScriptIdentifiers, visitedScriptIdentifiers, scriptIdentifiersToVisit);\n\n return;\n }\n\n // Direct Push names that are not script ids are WalletData, including dotted names.\n if (isDirectPushContent === true) {\n variableNames.add(identifier);\n }\n};\n\n/**\n * Visitor for one Script node in the parseScript tree.\n * Recurses into Push and Evaluation children and dispatches Identifier nodes.\n *\n * @param {CollectFromParsedScriptParameters} parameters - Parsed Script, Push depth flag, and parse tree context.\n */\nconst collectFromParsedScript = (parameters: CollectFromParsedScriptParameters): void => {\n const { scriptSegment, isDirectPushContent, knownScriptIdentifiers, visitedScriptIdentifiers, scriptIdentifiersToVisit, variableNames } =\n parameters;\n\n for (const child of scriptSegment.value) {\n if (child.name === 'Push') {\n // Inner Script of a Push is where `<name>` WalletData lives, including nested angle brackets.\n collectFromParsedScript({\n scriptSegment: child.value,\n isDirectPushContent: true,\n knownScriptIdentifiers,\n visitedScriptIdentifiers,\n scriptIdentifiersToVisit,\n variableNames,\n });\n\n continue;\n }\n\n if (child.name === 'Evaluation') {\n // Evaluation contents are opcodes and nested Pushes, not WalletData by themselves.\n collectFromParsedScript({\n scriptSegment: child.value,\n isDirectPushContent: false,\n knownScriptIdentifiers,\n visitedScriptIdentifiers,\n scriptIdentifiersToVisit,\n variableNames,\n });\n\n continue;\n }\n\n if (child.name === 'Identifier') {\n collectFromParsedIdentifier({\n identifier: child.value,\n isDirectPushContent,\n knownScriptIdentifiers,\n visitedScriptIdentifiers,\n scriptIdentifiersToVisit,\n variableNames,\n });\n }\n }\n};\n\n/**\n * Collects WalletData names from the parseScript tree using the visitor pattern.\n *\n * parseScript returns a tree of Script, Push, Evaluation, and Identifier nodes. Nested Push and\n * Evaluation nodes are entered immediately. A template script id is queued whether it appears inside a Push or next to\n * opcodes. Queued script sources are visited after the current tree finishes, in the order they were\n * first seen.\n * A visited id is skipped on later encounters. Opcodes and literals are ignored. Unrelated scripts\n * in the map are not visited. An Identifier inside a nested Push is collected from that inner Push,\n * for example `<$(<ownerKey.public_key> OP_HASH160)>` collects `ownerKey.public_key`.\n *\n * @param {string} evaluation - CashAssembly evaluation or script id text to scan.\n * @param {CashAssemblyTemplateScripts} [templateScripts] - Optional template scripts map used to visit nested script ids.\n * @returns {string[]} - WalletData names from reachable Pushes. Script ids are omitted when\n * `templateScripts` is provided.\n * @throws {@link CashAssemblyCompilationFailedError} - When parseScript rejects the starting text or a visited script source.\n */\nexport const collectVariablesUsingParseScript = (evaluation: string, templateScripts: CashAssemblyTemplateScripts = {}): string[] => {\n // Create a set of the script identifiers from the template scripts map.\n const knownScriptIdentifiers = new Set(Object.keys(templateScripts));\n\n const visitedScriptIdentifiers = new Set<string>();\n const scriptIdentifiersToVisit: string[] = [];\n const variableNames = new Set<string>();\n\n // Share by reference context.\n const parseTreeContext: CollectFromParseTreeContext = {\n knownScriptIdentifiers,\n visitedScriptIdentifiers,\n scriptIdentifiersToVisit,\n variableNames,\n };\n\n // Parse the starting text so nested Pushes are visible before visiting nested script sources.\n const startingScriptSegment = parseCashAssemblySource(evaluation);\n\n // Scan the starting parse tree before visiting nested script sources.\n collectFromParsedScript({\n ...parseTreeContext,\n scriptSegment: startingScriptSegment,\n isDirectPushContent: false,\n });\n\n for (const scriptIdentifier of scriptIdentifiersToVisit) {\n if (visitedScriptIdentifiers.has(scriptIdentifier) === true) {\n continue;\n }\n\n visitedScriptIdentifiers.add(scriptIdentifier);\n\n // Get the script definition from the template scripts map.\n const scriptDefinition = templateScripts[scriptIdentifier];\n\n const nestedScriptSegment = parseCashAssemblySource(scriptDefinition);\n\n collectFromParsedScript({\n ...parseTreeContext,\n scriptSegment: nestedScriptSegment,\n isDirectPushContent: false,\n });\n }\n\n return [ ...variableNames ];\n};\n","import { bigIntToVmNumber, utf8ToBin } from '@bitauth/libauth';\nimport { CashAssemblyNumberNotSafeIntegerError, CashAssemblyUnsupportedValueTypeError } from './errors.ts';\n\n/**\n * Converts a value into bytes representation.\n *\n * @param {unknown} value - Value to encode, should be one of: Uint8Array, bigint, boolean, string, or a safe integer number.\n * @param {string} valueIdentifier - Identifier used in error messages.\n * @returns {Uint8Array} - Bytes representation of the value.\n * @throws {@link CashAssemblyNumberNotSafeIntegerError} - When a number is not a safe integer.\n * @throws {@link CashAssemblyUnsupportedValueTypeError} - When the value type cannot be resolved.\n */\nexport const convertValueToBytes = (value: unknown, valueIdentifier: string): Uint8Array => {\n if (value instanceof Uint8Array) {\n return value;\n }\n\n if (typeof value === 'bigint') {\n return bigIntToVmNumber(value);\n }\n\n if (typeof value === 'boolean') {\n // The BCH VM treats an empty byte array as false and any nonempty byte array as true.\n return new Uint8Array(value ? [ 1 ] : []);\n }\n\n if (typeof value === 'string') {\n return utf8ToBin(value);\n }\n\n if (typeof value === 'number') {\n if (Number.isSafeInteger(value) === true) {\n return bigIntToVmNumber(BigInt(value));\n }\n\n throw new CashAssemblyNumberNotSafeIntegerError(valueIdentifier, value);\n }\n\n throw new CashAssemblyUnsupportedValueTypeError(valueIdentifier, typeof value);\n};\n","/**\n * Matches a single dot variable method reference inside an angle bracket identifier.\n *\n * Used to detect primitive method references such as `expiry.toIso8601`.\n *\n * For example `expiry.toIso8601` matches with base expiry and method toIso8601.\n * `requestedSatoshis` does not match because it has no method.\n * `key.schnorr_signature.all_outputs` does not match because it has more than one dot.\n */\nexport const CASHASSEMBLY_VARIABLE_METHOD_REFERENCE_PATTERN = /^([^.]+)\\.([^.]+)$/;\n\n/**\n * Character count of the `$(` evaluation opener, which is two characters long.\n *\n * Adding this length moves the read position to the first character after that sequence so scanning\n * starts on the evaluation contents rather than on the opening parenthesis.\n */\nexport const CASHASSEMBLY_EVALUATION_START_LENGTH = 2;\n\n/**\n * Character count of the `//` and `/*` comment openers, which are both two characters long.\n *\n * Adding this length moves the read position to the first character after that sequence so the '*'\n * of a block comment opener cannot be reused as the '*' of its closer.\n */\nexport const CASHASSEMBLY_COMMENT_START_LENGTH = 2;\n\n/**\n * Character count of the block comment closer, which is two characters long.\n *\n * Adding this length moves the read position to the first character after that sequence so the\n * closing slash cannot pair with the next character and open another comment.\n */\nexport const CASHASSEMBLY_BLOCK_COMMENT_END_LENGTH = 2;\n\n/**\n * `$()` with nothing between the parentheses.\n *\n * Callers use this to detect an evaluation that has no contents to compile.\n */\nexport const EMPTY_CASHASSEMBLY_EVALUATION = '$()';\n","import {\n FungibleTokenAmount,\n NFTCommitment,\n PublicKey,\n Satoshis,\n SchnorrSignature,\n TemplateIdentifier,\n Timestamp,\n TokenCategory,\n TransactionHash,\n} from '@xo-cash/primitives';\nimport { XOTemplatePrimitiveTypes } from '@xo-cash/types';\nimport type { XOTemplate, XOTemplatePrimitiveType } from '@xo-cash/types';\nimport { CashAssemblyPrimitiveMethodMissingError, CashAssemblyPrimitiveVariableMissingError } from './errors.ts';\nimport { CASHASSEMBLY_VARIABLE_METHOD_REFERENCE_PATTERN } from './defaults.ts';\nimport { convertValueToBytes } from './bytes.ts';\n\n/**\n * Maps method resolvable template types to `@xo-cash/primitives` classes for `base.method` resolution.\n * Keys are a subset of {@link XOTemplatePrimitiveTypes}.\n */\nconst RESOLVABLE_PRIMITIVE_CLASS_BY_TYPE = {\n [XOTemplatePrimitiveTypes.FUNGIBLE_TOKEN_AMOUNT]: FungibleTokenAmount,\n [XOTemplatePrimitiveTypes.NFT_COMMITMENT]: NFTCommitment,\n [XOTemplatePrimitiveTypes.PUBLIC_KEY]: PublicKey,\n [XOTemplatePrimitiveTypes.SATOSHIS]: Satoshis,\n [XOTemplatePrimitiveTypes.SCHNORR_SIGNATURE]: SchnorrSignature,\n [XOTemplatePrimitiveTypes.TEMPLATE_IDENTIFIER]: TemplateIdentifier,\n [XOTemplatePrimitiveTypes.TIMESTAMP]: Timestamp,\n [XOTemplatePrimitiveTypes.TOKEN_CATEGORY]: TokenCategory,\n [XOTemplatePrimitiveTypes.TRANSACTION_HASH]: TransactionHash,\n} as const;\n\n/**\n * Template primitive types that map to an `@xo-cash/primitives` class for `base.method` resolution.\n * This is a subset of {@link XOTemplatePrimitiveType}, not every declared template type.\n */\ntype ResolvablePrimitiveType = keyof typeof RESOLVABLE_PRIMITIVE_CLASS_BY_TYPE;\n\n/**\n * Inputs needed to call a primitive method for a `name.method` push.\n */\ntype CallPrimitiveMethodParameters = {\n\n /**\n * Full push identifier from the evaluation, for example `amount.toSatoshis`.\n */\n identifier: string;\n\n /**\n * Method name to call on the constructed primitive, for example `toIso8601`.\n */\n methodName: string;\n\n /**\n * Value for the variable.\n */\n value: unknown;\n\n /**\n * Method resolvable template type that selects the primitive class.\n */\n type: ResolvablePrimitiveType;\n};\n\n/**\n * Inputs needed to resolve primitive method pushes from collected CashAssembly variable names.\n */\nexport type ResolvePrimitiveMethodBytesParameters = {\n\n /**\n * Variable names from {@link collectVariablesUsingParseScript}, for example\n * `['amount.toSatoshis', 'fee.toSatoshis']`.\n */\n variableNames: string[];\n\n /**\n * Variable names and values object.\n */\n variables: Record<string, unknown>;\n\n /**\n * Template variable definitions. When omitted, no primitive methods are resolved.\n * The `type` on each entry selects the primitive class.\n */\n templateVariables?: XOTemplate['variables'];\n};\n\n/**\n * Returns true when `type` maps to a primitive class in `RESOLVABLE_PRIMITIVE_CLASS_BY_TYPE` for method resolution.\n *\n * @param {XOTemplatePrimitiveType | undefined} type - Template variable type.\n * @returns {boolean} True when the type can resolve `base.method` through a primitive class.\n */\nconst isResolvablePrimitiveType = (type: XOTemplatePrimitiveType | undefined): type is ResolvablePrimitiveType => {\n return type !== undefined && Object.hasOwn(RESOLVABLE_PRIMITIVE_CLASS_BY_TYPE, type) === true;\n};\n\n/**\n * Returns true when `methodName` is an own function on the primitive class for `type`.\n *\n * @param {ResolvablePrimitiveType} type - Method resolvable template type.\n * @param {string} methodName - Method name from the evaluation text, for example `toSatoshis`.\n * @returns {boolean} - True when that class exposes the named method.\n */\nconst canResolvePrimitiveMethod = (type: ResolvablePrimitiveType, methodName: string): boolean => {\n const PrimitiveClass = RESOLVABLE_PRIMITIVE_CLASS_BY_TYPE[type];\n\n // Check own properties only so inherited Object.prototype names are rejected without needing a value.\n if (Object.hasOwn(PrimitiveClass.prototype, methodName) === false) {\n return false;\n }\n\n return typeof Reflect.get(PrimitiveClass.prototype, methodName) === 'function';\n};\n\n/**\n * Constructs a primitive from a raw value and calls one instance method on it.\n *\n * Call only after `canResolvePrimitiveMethod` is true for the same type and method.\n *\n * @param {CallPrimitiveMethodParameters} parameters - Identifier, method, value, and resolvable type.\n * @returns {unknown} Method return value, later encoded as CashAssembly push bytes.\n * @throws {@link CashAssemblyPrimitiveMethodMissingError} When the prototype member is not a function.\n * @throws When the primitive constructor rejects the raw value (validation errors from `@xo-cash/primitives`).\n */\nconst callPrimitiveMethod = (parameters: CallPrimitiveMethodParameters): unknown => {\n const { identifier, methodName, value, type } = parameters;\n\n const PrimitiveClass = RESOLVABLE_PRIMITIVE_CLASS_BY_TYPE[type];\n\n // Constructing runs each primitive's own input validation (range checks, hex length, etc).\n // `as never` satisfies TypeScript across constructors that accept different input shapes.\n const primitiveInstance = new PrimitiveClass(value as never);\n\n // Same prototype member canResolvePrimitiveMethod already verified as an own function.\n const primitiveMethod = Reflect.get(PrimitiveClass.prototype, methodName);\n\n if (typeof primitiveMethod !== 'function') {\n throw new CashAssemblyPrimitiveMethodMissingError(identifier, methodName, type);\n }\n\n return primitiveMethod.call(primitiveInstance);\n};\n\n/**\n * Resolves method resolvable `base.method` identifiers to CashAssembly variable bytes.\n *\n * Each single dot identifier whose `type` is in `RESOLVABLE_PRIMITIVE_CLASS_BY_TYPE` is resolved and stored under\n * the full identifier (`base.method`). Other template types or multi dot identifiers are left for CashAssembly.\n *\n * When `templateVariables` is omitted, returns an empty map.\n *\n * @param {ResolvePrimitiveMethodBytesParameters} parameters - Identifiers, values, and optional template metadata.\n * @returns {Record<string, Uint8Array>} Resolved method identifiers mapped to bytes for CashAssembly pushes.\n * @throws {@link CashAssemblyPrimitiveMethodMissingError} When the type is method resolvable but the method is missing.\n * @throws {@link CashAssemblyPrimitiveVariableMissingError} When the runtime value is missing from the variables map.\n * @throws {@link CashAssemblyUnsupportedValueTypeError} When the method return type cannot be embedded.\n * @throws {@link CashAssemblyNumberNotSafeIntegerError} When a method return value is a number that is not a safe integer.\n */\nexport const resolvePrimitiveMethodBytes = (parameters: ResolvePrimitiveMethodBytesParameters): Record<string, Uint8Array> => {\n const { variableNames, templateVariables, variables } = parameters;\n\n // Without template metadata there is no type to select a primitive class.\n if (templateVariables === undefined) {\n return {};\n }\n\n const resolvedBytes: Record<string, Uint8Array> = {};\n\n for (const variableName of variableNames) {\n // The same name can appear more than once. Resolve it only once.\n if (Object.hasOwn(resolvedBytes, variableName) === true) {\n continue;\n }\n\n // Find the primitive method reference in the name.\n const methodReferenceMatch = variableName.match(CASHASSEMBLY_VARIABLE_METHOD_REFERENCE_PATTERN);\n\n if (methodReferenceMatch === null) {\n continue;\n }\n\n const [ , baseName, methodName ] = methodReferenceMatch;\n\n // Unknown names and CashAssembly native operations such as someKey.schnorr_signature.all_outputs\n // must be left for CashAssembly rather than treated as primitive failures.\n if (Object.hasOwn(templateVariables, baseName) === false) {\n continue;\n }\n\n const type = templateVariables[baseName].type;\n\n // Template types without a mapped primitive class are left for CashAssembly.\n if (isResolvablePrimitiveType(type) === false) {\n continue;\n }\n\n // Method resolvable type with an unknown method should throw.\n if (canResolvePrimitiveMethod(type, methodName) === false) {\n throw new CashAssemblyPrimitiveMethodMissingError(variableName, methodName, type);\n }\n\n // If the method is known but the runtime value is missing, throw an error.\n if (Object.hasOwn(variables, baseName) === false) {\n throw new CashAssemblyPrimitiveVariableMissingError(variableName, baseName);\n }\n\n const methodResult = callPrimitiveMethod({\n identifier: variableName,\n methodName,\n value: variables[baseName],\n type,\n });\n\n // CashAssembly looks up the full `base.method` name as WalletData bytes.\n resolvedBytes[variableName] = convertValueToBytes(methodResult, variableName);\n }\n\n return resolvedBytes;\n};\n","import { generateBytecodeMap, IdentifierResolutionType, OpcodesBchSpec } from '@bitauth/libauth';\nimport { CashAssemblyIdentifierCollisionError } from './errors.ts';\nimport type { CompileCashAssemblyContext } from './types.ts';\n\n/**\n * Set of opcode names that the compiler recognizes.\n */\nconst COMPILER_OPCODE_NAMES: ReadonlySet<string> = new Set(Object.keys(generateBytecodeMap(OpcodesBchSpec)));\n\n/**\n * Parameters for {@link assertNoIdentifierCollisions} function.\n */\nexport type AssertNoIdentifierCollisionsParameters = Pick<CompileCashAssemblyContext, 'variables' | 'templateScripts'>;\n\n/**\n * Libauth resolves opcodes, then variables, then scripts, and the first match silently hides the\n * rest, leading to unexpected compilation results and no errors. This function throws when one identifier matches more than one resolution type.\n *\n * @param {AssertNoIdentifierCollisionsParameters} parameters - Provided variables and optional template scripts.\n * @throws {@link CashAssemblyIdentifierCollisionError} - When one identifier matches more than one resolution type.\n */\nexport const assertNoIdentifierCollisions = (parameters: AssertNoIdentifierCollisionsParameters): void => {\n const { variables, templateScripts } = parameters;\n\n // Create a set of the script identifiers from the template scripts map.\n const scriptIdentifiers = new Set(Object.keys(templateScripts ?? {}));\n\n const variableNames = new Set(Object.keys(variables));\n\n // Combine both, the variableNames and the scriptIdentifiers, to get a set of all identifiers.\n const declaredIdentifiers = new Set([ ...variableNames, ...scriptIdentifiers ]);\n\n // This loop will check for more than one occurrence of an identifier in OP_CODES, variables, and scripts\n for (const identifier of declaredIdentifiers) {\n // Resolution types is a native construct from libauth.\n const resolutionTypes: IdentifierResolutionType[] = [];\n\n // If the identifier is an opcode, then push it to the resolution types array, this will also be\n // detected by either or both of the variableNames and scriptIdentifiers checks.\n if (COMPILER_OPCODE_NAMES.has(identifier) === true) {\n resolutionTypes.push(IdentifierResolutionType.opcode);\n }\n\n // If the identifier is in variables, then push it to the resolution types array.\n if (variableNames.has(identifier) === true) {\n resolutionTypes.push(IdentifierResolutionType.variable);\n }\n\n // If the identifier is a script identifier, then push it to the resolution types array.\n if (scriptIdentifiers.has(identifier) === true) {\n resolutionTypes.push(IdentifierResolutionType.script);\n }\n\n // If there are more than one resolution types, then throw an error.\n if (resolutionTypes.length > 1) {\n throw new CashAssemblyIdentifierCollisionError(identifier, resolutionTypes);\n }\n }\n};\n","import {\n CASHASSEMBLY_BLOCK_COMMENT_END_LENGTH,\n CASHASSEMBLY_COMMENT_START_LENGTH,\n CASHASSEMBLY_EVALUATION_START_LENGTH,\n EMPTY_CASHASSEMBLY_EVALUATION,\n} from './defaults.ts';\nimport { CashAssemblyBlockCommentUnclosedError, CashAssemblyEvaluationUnclosedError, CashAssemblyQuotedLiteralUnclosedError } from './errors.ts';\n\n/**\n * Skips a quoted CashAssembly string so a `)` inside it cannot end `$()`.\n *\n * CashAssembly UTF8 literals use `\"...\"` or `'...'`. Everything between the quotes is payload,\n * including parentheses.\n * For example `$(<\"hello)world\">)` must close after the literal, not at the `)` inside the quotes.\n *\n * @param {string} cashAssemblyText - Text that contains the quoted literal.\n * @param {number} openingQuoteIndex - Index of the opening `\"` or `'`.\n * @returns {number} - Index of the character after the closing quote.\n * @throws {@link CashAssemblyQuotedLiteralUnclosedError} - When the quoted literal never closes.\n */\nconst skipQuotedCashAssemblyLiteral = (cashAssemblyText: string, openingQuoteIndex: number): number => {\n const quoteCharacter = cashAssemblyText[openingQuoteIndex];\n let currentIndex = openingQuoteIndex + 1;\n\n // CashAssembly puts payload `)` inside the quotes. Stop only at the matching quote.\n while (currentIndex < cashAssemblyText.length) {\n if (cashAssemblyText[currentIndex] === quoteCharacter) {\n return currentIndex + 1;\n }\n\n currentIndex += 1;\n }\n\n throw new CashAssemblyQuotedLiteralUnclosedError(openingQuoteIndex, quoteCharacter, cashAssemblyText);\n};\n\n/**\n * This function skips a `//` comment so a `)` written in the comment cannot end `$()`.\n * A line comment runs from `//` to the newline, or to the end of the string when there is no newline.\n * A `)` in that span is comment text, not the closer of `$()`.\n *\n * @param {string} cashAssemblyText - Text that contains the line comment.\n * @param {number} commentStartIndex - Index of the first `/` of `//`.\n * @returns {number} - Index after the newline that ends the comment, or the end of the string if there is no newline.\n */\nconst skipSingleLineCashAssemblyComment = (cashAssemblyText: string, commentStartIndex: number): number => {\n let currentIndex = commentStartIndex + CASHASSEMBLY_COMMENT_START_LENGTH;\n\n // CashAssembly line comments hide `)` until the newline. End of string also ends them.\n while (currentIndex < cashAssemblyText.length) {\n if (cashAssemblyText[currentIndex] === '\\n') {\n return currentIndex + 1;\n }\n\n currentIndex += 1;\n }\n\n return currentIndex;\n};\n\n/**\n * This function skips a block comment so a `)` written in the comment cannot end `$()`.\n * A `)` inside a block comment is comment text, not the closer of `$()`.\n *\n * @param {string} cashAssemblyText - Text that contains the block comment.\n * @param {number} commentStartIndex - Index of the first slash of the block comment opener.\n * @returns {number} - Index of the character after the comment closer.\n * @throws {@link CashAssemblyBlockCommentUnclosedError} - When the block comment never closes.\n */\nconst skipBlockCashAssemblyComment = (cashAssemblyText: string, commentStartIndex: number): number => {\n let currentIndex = commentStartIndex + CASHASSEMBLY_COMMENT_START_LENGTH;\n\n // CashAssembly block comments hide `)` until the closer is found.\n while (currentIndex + 1 < cashAssemblyText.length) {\n if (cashAssemblyText[currentIndex] === '*' && cashAssemblyText[currentIndex + 1] === '/') {\n return currentIndex + CASHASSEMBLY_BLOCK_COMMENT_END_LENGTH;\n }\n\n currentIndex += 1;\n }\n\n throw new CashAssemblyBlockCommentUnclosedError(commentStartIndex, cashAssemblyText);\n};\n\n/**\n * Parenthesis matching with a depth count.\n *\n * Returns the index of the `)` that closes the `$()` starting at `evaluationStartIndex`.\n * Nested `$()` raise the depth so an inner closer cannot finish the outer evaluation.\n *\n * @param {string} cashAssemblyText - Text that contains the evaluation.\n * @param {number} evaluationStartIndex - Index of the `$` that opens this evaluation.\n * @returns {number} - Index of the matching closing parenthesis.\n * @throws {@link CashAssemblyEvaluationUnclosedError} - When the evaluation never closes.\n * @throws {@link CashAssemblyQuotedLiteralUnclosedError} - When a quoted literal inside the evaluation never closes.\n * @throws {@link CashAssemblyBlockCommentUnclosedError} - When a block comment inside the evaluation never closes.\n */\nconst findCashAssemblyEvaluationCloseIndex = (cashAssemblyText: string, evaluationStartIndex: number): number => {\n let currentIndex = evaluationStartIndex + CASHASSEMBLY_EVALUATION_START_LENGTH;\n let remainingOpenEvaluations = 1;\n\n // Scan the evaluation contents until the matching closer at depth zero.\n while (currentIndex < cashAssemblyText.length) {\n const currentCharacter = cashAssemblyText[currentIndex];\n const nextCharacter = cashAssemblyText[currentIndex + 1];\n\n // CashAssembly allows `)` inside `\"...\"` and `'...'`. Skip the literal so that closer is not structural.\n if (currentCharacter === '\"' || currentCharacter === \"'\") {\n currentIndex = skipQuotedCashAssemblyLiteral(cashAssemblyText, currentIndex);\n\n continue;\n }\n\n // CashAssembly `//` comments may mention `)`. Skip them so that `)` is not treated as a closer.\n if (currentCharacter === '/' && nextCharacter === '/') {\n currentIndex = skipSingleLineCashAssemblyComment(cashAssemblyText, currentIndex);\n\n continue;\n }\n\n // CashAssembly block comments may mention `)`. Skip them so that `)` is not treated as a closer.\n if (currentCharacter === '/' && nextCharacter === '*') {\n currentIndex = skipBlockCashAssemblyComment(cashAssemblyText, currentIndex);\n\n continue;\n }\n\n // Nested `$()` must close before this evaluation can close.\n if (currentCharacter === '$' && nextCharacter === '(') {\n // Since all previous checks have passed then it means this is start of another evaluation, it we must\n // increment the remainingOpenEvaluations counter and move the currentIndex to the next character.\n remainingOpenEvaluations += 1;\n currentIndex += CASHASSEMBLY_EVALUATION_START_LENGTH;\n\n continue;\n }\n\n // A closer at depth one ends this evaluation. Inner closers only reduce nested depth.\n if (currentCharacter === ')') {\n // Since all previous checks have passed then it means this is a closer for the current evaluation, we must\n // decrement the remainingOpenEvaluations counter and check if it is now zero. If it is then we have found the\n // matching closer and we can return the currentIndex.\n remainingOpenEvaluations -= 1;\n\n if (remainingOpenEvaluations === 0) {\n return currentIndex;\n }\n }\n\n // Move the currentIndex to the next character.\n currentIndex += 1;\n }\n\n // The matching closer was never found.\n throw new CashAssemblyEvaluationUnclosedError(evaluationStartIndex, remainingOpenEvaluations, cashAssemblyText);\n};\n\n/**\n * One `$()` found in text that is not nested inside another `$()`.\n */\ntype CashAssemblyEvaluationScanMatch = {\n\n /**\n * Complete `$()` text including the opening `$` and the matching closer.\n */\n evaluationText: string;\n\n /**\n * Index of the `$` that opens this evaluation.\n */\n startIndex: number;\n\n /**\n * Index of the matching closing parenthesis.\n */\n closeIndex: number;\n};\n\n/**\n * Scans text and returns every `$()` that starts in this string, including empty `$()`.\n *\n * Nested `$()` stay inside the outer evaluation.\n *\n * @param {string} cashAssemblyText - Text that may contain `$()`.\n * @returns {CashAssemblyEvaluationScanMatch[]} - Evaluations in left to right order.\n * @throws {@link CashAssemblyEvaluationUnclosedError} - When an evaluation never closes.\n * @throws {@link CashAssemblyQuotedLiteralUnclosedError} - When a quoted literal never closes.\n * @throws {@link CashAssemblyBlockCommentUnclosedError} - When a block comment never closes.\n */\nexport const scanCashAssemblyEvaluations = (cashAssemblyText: string): CashAssemblyEvaluationScanMatch[] => {\n const scannedEvaluations: CashAssemblyEvaluationScanMatch[] = [];\n let currentIndex = 0;\n\n // Find `$()` that starts in this string. Nested evaluations stay inside the outer evaluation.\n while (currentIndex < cashAssemblyText.length) {\n const currentCharacter = cashAssemblyText[currentIndex];\n const nextCharacter = cashAssemblyText[currentIndex + 1];\n\n // A `$` that is followed by `(`.\n if (currentCharacter === '$' && nextCharacter === '(') {\n // Count parentheses so quotes, comments, and nested `$()` cannot close this evaluation early.\n const closeIndex = findCashAssemblyEvaluationCloseIndex(cashAssemblyText, currentIndex);\n // Slice the complete `$()` so later steps do not re-scan these characters.\n const evaluationText = cashAssemblyText.slice(currentIndex, closeIndex + 1);\n\n // Store the outer `$()`. Nested evaluations are already inside evaluationText.\n scannedEvaluations.push({\n closeIndex,\n evaluationText,\n startIndex: currentIndex,\n });\n\n // Skip to after this `$()` so nested evaluations are not scanned as their own matches.\n currentIndex = closeIndex + 1;\n\n continue;\n }\n\n currentIndex += 1;\n }\n\n return scannedEvaluations;\n};\n\n/**\n * This function returns each `$()` that starts in this string.\n * Empty `$()` is omitted.\n *\n * @param {string} cashAssemblyText - Text that may contain `$()`.\n * @returns {string[]} - Complete non empty evaluation strings in left to right order.\n * @throws {@link CashAssemblyEvaluationUnclosedError} - When an evaluation never closes.\n * @throws {@link CashAssemblyQuotedLiteralUnclosedError} - When a quoted literal never closes.\n * @throws {@link CashAssemblyBlockCommentUnclosedError} - When a block comment never closes.\n */\nexport const extractCashAssemblyEvaluations = (cashAssemblyText: string): string[] => {\n const scannedEvaluations = scanCashAssemblyEvaluations(cashAssemblyText);\n const evaluations: string[] = [];\n\n // Omit empty `$()` so callers that compile extracted text do not treat it as an evaluation.\n for (const scannedEvaluation of scannedEvaluations) {\n if (scannedEvaluation.evaluationText !== EMPTY_CASHASSEMBLY_EVALUATION) {\n evaluations.push(scannedEvaluation.evaluationText);\n }\n }\n\n return evaluations;\n};\n\n/**\n * This function returns true when the value is exactly one CashAssembly `$()`.\n * Text with characters outside `$()`, empty `$()`, or a failed scan returns false.\n *\n * @param {unknown} expression - Value to test.\n * @returns {boolean} - True when the value is a string that is one complete evaluation and nothing else.\n */\nexport const isCashAssemblyExpression = (expression: unknown): boolean => {\n // Numbers and other types are never CashAssembly evaluations.\n if (typeof expression !== 'string') {\n return false;\n }\n\n try {\n const evaluations = extractCashAssemblyEvaluations(expression);\n\n // If there is only one evaluation extracted and the returned value matches to that of the expression passed in the parameter,\n // then return true.\n return evaluations.length === 1 && evaluations[0] === expression;\n } catch {\n // A failed scan is not a complete evaluation.\n return false;\n }\n};\n","/**\n * Utilities for parsing, extracting, and compiling CashAssembly expressions.\n *\n * CashAssembly is the scripting language used by Bitauth templates to describe Bitcoin Cash\n * locking and unlocking scripts.\n *\n * ## Syntax (CashAssembly)\n *\n * `<expression>` is a push statement. Compiles the contents and pushes the result onto the VM stack.\n * For example `<someKey.public_key>` pushes the 33 byte compressed public key and `<1>` pushes the integer 1.\n *\n * `$(<expression>)` is an evaluation. Runs the inner script in the VM and inserts the top stack\n * item as VM bytecode.\n * For example `$(<someKey.public_key> OP_HASH160)` inserts the HASH160 of the public key.\n *\n * `<$(<expression>)>` is a push of an evaluation result. It evaluates first then pushes.\n * For example a P2PKH locking script looks like\n * `OP_DUP OP_HASH160 <$(<someKey.public_key> OP_HASH160)> OP_EQUALVERIFY OP_CHECKSIG`.\n *\n * `variableId.operation` is a variable with a compiler resolved operation.\n * For example `someKey.public_key` produces the public key bytes and\n * `someKey.schnorr_signature.all_outputs` produces a Schnorr signature.\n *\n * Opcodes (`OP_DUP`, `OP_HASH160`, and similar) are inserted as their bytecode equivalent directly.\n *\n * ## Name resolution priority (CashAssembly)\n *\n * When the compiler encounters an identifier it resolves it in this order.\n * 1. Opcode always wins. For example naming a variable or script `OP_ADD` will not shadow it.\n * 2. Variable shadows scripts of the same name.\n * 3. Script is the script's bytecode.\n *\n * ## Resolution Order (CashAssembly + Primitive Method Resolution)\n *\n * Supported `<base.method>` pushes are resolved to bytes before CashAssembly compiles.\n * Inside CashAssembly the order is Opcode then Variable then Script.\n *\n * ## This compile path\n *\n * This file is a layer on CashAssembly. Text outside `$()` is kept. Only `$()` is compiled.\n * For example `Paid $(scriptA) of $(scriptB)` keeps the words Paid and of.\n *\n * `$()` is found by scanning left to right with parenthesis matching by depth count. Quoted strings\n * and comments are skipped so a `)` there cannot end `$()`. Nested `$()` stay inside the outer\n * evaluation. That text is never passed to parseScript.\n *\n * Empty `$()` still uses this mixed path. When the string contains no `$()` at all, the entire\n * string is compiled as CashAssembly so push opcodes remain.\n */\nimport type { CompilerBch } from '@bitauth/libauth';\nimport { binToHex, binToUtf8, createCompilerBch, vmNumberToBigInt } from '@bitauth/libauth';\nimport { convertValueToBytes } from './bytes.ts';\nimport {\n CashAssemblyCompilationFailedError,\n CashAssemblyRequiredVariableMissingError,\n CashAssemblyVariableTypeMismatchError,\n CashAssemblyVmNumberDecodeError,\n} from './errors.ts';\nimport { resolvePrimitiveMethodBytes } from './primitive-evaluations.ts';\nimport { assertNoIdentifierCollisions } from './identifier-collisions.ts';\nimport { collectVariablesUsingParseScript } from './collect-evaluations.ts';\nimport { EMPTY_CASHASSEMBLY_EVALUATION } from './defaults.ts';\nimport { scanCashAssemblyEvaluations } from './scan-evaluations.ts';\nimport type {\n CompileCashAssemblyEvaluationsParameters,\n CompileCashAssemblySourceToBytesParameters,\n CompileCashAssemblySourceToDecodedTextParameters,\n CompileCashAssemblyStringParameters,\n CompiledCashAssemblyDecodeMode,\n} from './types.ts';\n\n/**\n * Returns the segment of `identifier` before the first `.`.\n *\n * When there is no `.`, returns `identifier` unchanged.\n * Multi segment identifiers such as `foo.bar.baz` resolve to `foo`.\n *\n * @param {string} identifier - Identifier that may contain a dot.\n * @returns {string} - The base name before the first `.`.\n */\nconst resolveIdentifierBaseName = (identifier: string): string => {\n const firstDotIndex = identifier.indexOf('.');\n\n if (firstDotIndex === -1) {\n return identifier;\n }\n\n return identifier.slice(0, firstDotIndex);\n};\n\n/**\n * Decodes compiled CashAssembly evaluation bytes into a string representation.\n *\n * 'evaluationDecodeMode' determines how the evaluation bytes are interpreted and presented.\n * Use `bigint` for numeric values like satoshis, `utf8` for text labels, `hex` for binary data\n * such as hashes, and `boolean` to represent boolean values.\n *\n * @param {Uint8Array} compiledResult - The compiled evaluation bytecode.\n * @param {CompiledCashAssemblyDecodeMode} evaluationDecodeMode - The decode mode used to convert bytes to text.\n * @returns {string} - The decoded value as a string suitable for inline replacement.\n * @throws {@link CashAssemblyVmNumberDecodeError} - When `evaluationDecodeMode` is `bigint` and the bytes are not a VM number.\n */\nexport const decodeCompiledCashAssemblyEvaluation = (\n compiledResult: Uint8Array,\n evaluationDecodeMode: CompiledCashAssemblyDecodeMode = 'utf8',\n): string => {\n // Converts the byte array to a string.\n if (evaluationDecodeMode === 'uint8array') {\n return String(compiledResult);\n }\n\n // Converts the byte array to a boolean string, converting the evaluation result into a true or a false.\n if (evaluationDecodeMode === 'boolean') {\n return compiledResult.length === 0 ? 'false' : 'true';\n }\n\n // Converts the byte array to a hex string.\n if (evaluationDecodeMode === 'hex') {\n return binToHex(compiledResult);\n }\n\n // Converts the byte array to a bigint string.\n if (evaluationDecodeMode === 'bigint') {\n const vmNumberResult = vmNumberToBigInt(compiledResult);\n\n if (typeof vmNumberResult === 'bigint') {\n return vmNumberResult.toString();\n }\n\n throw new CashAssemblyVmNumberDecodeError(vmNumberResult);\n }\n\n // Converts the byte array to a utf8 string.\n return binToUtf8(compiledResult);\n};\n\n/**\n * Generates bytecode for a specific CashAssembly evaluation using given variable values and a prepared compiler.\n *\n * @param {CompilerBch} compiler - The libauth compiler from {@link compileCashAssemblyEvaluations}.\n * @param {string} evaluation - The specific evaluation string to compile.\n * @param {Record<string, Uint8Array>} variables - A record mapping variable names to their values.\n * @param {string[]} requiredVariableNames - WalletData names from {@link collectVariablesUsingParseScript} that must be present.\n * @returns {Uint8Array} - The compiled bytecode.\n * @throws {@link CashAssemblyRequiredVariableMissingError} - If a required variable is not present.\n * @throws {@link CashAssemblyVariableTypeMismatchError} - If a variable value is not a Uint8Array.\n * @throws {@link CashAssemblyCompilationFailedError} - If libauth compilation fails.\n */\nexport const generateCashAssemblyBytecode = (\n compiler: CompilerBch,\n evaluation: string,\n variables: Record<string, Uint8Array>,\n requiredVariableNames: string[],\n): Uint8Array => {\n // Missing WalletData must fail here. Libauth would otherwise compile as if the value were empty bytes.\n const missingVariables = requiredVariableNames.filter((name: string) => Object.hasOwn(variables, name) === false);\n\n // Refuse invented defaults so a missing value cannot compile into incorrect bytecode.\n if (missingVariables.length > 0) {\n throw new CashAssemblyRequiredVariableMissingError(missingVariables);\n }\n\n const bytecode: Record<string, Uint8Array> = {};\n\n // Pass only required names so extra keys in `variables` are not sent to Libauth.\n for (const variableName of requiredVariableNames) {\n const value = variables[variableName];\n\n // Libauth WalletData is always bytes. A number would compile incorrectly if we trusted TypeScript alone.\n if (value instanceof Uint8Array === false) {\n throw new CashAssemblyVariableTypeMismatchError(variableName, 'Uint8Array', typeof value);\n }\n\n bytecode[variableName] = value;\n }\n\n // `scriptId` is the source string registered in compileCashAssemblyEvaluations.\n const compiledBytecode = compiler.generateBytecode({\n data: { bytecode },\n scriptId: evaluation,\n });\n\n // A failed compile must not return partial bytecode.\n if (compiledBytecode.success === false) {\n // CashAssemblyCompilationFailedError carries one message. Libauth may report several errors.\n let compilationFailureMessage = 'unknown compilation failure';\n\n // Prefer Libauth's own error text when the failure object includes an errors list.\n if ('errors' in compiledBytecode && compiledBytecode.errors.length > 0) {\n compilationFailureMessage = compiledBytecode.errors.map((compilationError) => compilationError.error).join('; ');\n }\n\n throw new CashAssemblyCompilationFailedError(compilationFailureMessage);\n }\n\n return compiledBytecode.bytecode;\n};\n\n/**\n * Prepares a compiler for the provided CashAssembly source strings, setting required variables as 'WalletData'.\n *\n * Each evaluation string is registered as a script whose id and source are that string. Template\n * scripts are then copied onto the same table. If a source is a template id such as `scriptA`, that\n * id must compile the template source. Leaving the id as its own source would compile the text\n * `scriptA` and include itself.\n *\n * @param {CompileCashAssemblyEvaluationsParameters} parameters - Source strings, optional template scripts, and already collected WalletData names.\n * @returns {CompilerBch} - A Libauth compiler instance for use with these source strings.\n */\nexport const compileCashAssemblyEvaluations = (parameters: CompileCashAssemblyEvaluationsParameters): CompilerBch => {\n const { evaluations, templateScripts, variableNames } = parameters;\n const scripts: Record<string, string> = {};\n\n // Libauth looks up scripts by id. Using the source string as the id lets generateBytecode request that exact source.\n for (const evaluation of evaluations) {\n scripts[evaluation] = evaluation;\n }\n\n const knownScriptIdentifiers = new Set<string>();\n\n if (templateScripts !== undefined) {\n for (const [ scriptIdentifier, scriptDefinition ] of Object.entries(templateScripts)) {\n // Compiling `scriptA` must run the template source. Otherwise the id compiles as the text `scriptA` and includes itself.\n scripts[scriptIdentifier] = scriptDefinition;\n\n // Template ids compile as scripts. They must not also be registered as WalletData.\n knownScriptIdentifiers.add(scriptIdentifier);\n }\n }\n\n const variables: Record<string, { type: 'WalletData' }> = {};\n\n // Register caller collected names. This function does not parse or collect again.\n for (const variableName of variableNames) {\n // A name that is a template script id is already a compiler script, not WalletData.\n if (knownScriptIdentifiers.has(variableName) === true) {\n continue;\n }\n\n // Libauth WalletData is the name before the first `.`. `ownerKey.public_key` registers as `ownerKey`.\n variables[resolveIdentifierBaseName(variableName)] = { type: 'WalletData' as const };\n }\n\n const compiler = createCompilerBch({\n scripts,\n variables,\n });\n\n return compiler;\n};\n\n/**\n * Compiles one CashAssembly source string to bytecode.\n *\n * The source may be an evaluation such as `$(scriptA)` or CashAssembly such as\n * `scriptA`. WalletData names come from {@link collectVariablesUsingParseScript}.\n *\n * @param {CompileCashAssemblySourceToBytesParameters} parameters - Source text and compilation context.\n * @returns {Uint8Array} - Compiled bytecode for that source.\n * @throws {@link CashAssemblyRequiredVariableMissingError} - When a required variable is not present in the variables map.\n * @throws {@link CashAssemblyPrimitiveMethodMissingError} - When a supported primitive hint has an unknown method.\n * @throws {@link CashAssemblyPrimitiveVariableMissingError} - When a supported primitive method is missing its runtime value.\n * @throws {@link CashAssemblyUnsupportedValueTypeError} - When a primitive method return type cannot be embedded as bytes.\n * @throws {@link CashAssemblyNumberNotSafeIntegerError} - When a number variable is not a safe integer.\n * @throws {@link CashAssemblyIdentifierCollisionError} - When one identifier matches two resolution types.\n * @throws {@link CashAssemblyCompilationFailedError} - When Libauth compilation fails.\n */\nexport const compileCashAssemblySourceToBytes = (parameters: CompileCashAssemblySourceToBytesParameters): Uint8Array => {\n const { cashAssemblySource, variables, templateVariables, templateScripts } = parameters;\n\n // Throw if there is a identifier collision between opcodes, variable, or template script.\n assertNoIdentifierCollisions({ variables, templateScripts });\n\n // Collect WalletData names from the source and every reachable nested script source.\n const variableNames = collectVariablesUsingParseScript(cashAssemblySource, templateScripts);\n\n // Resolve supported primitive methods to bytes before treating remaining names as WalletData.\n const primitiveMethodBytes = resolvePrimitiveMethodBytes({\n variableNames,\n templateVariables,\n variables,\n });\n\n // Collect names that still need a caller supplied value after primitive resolution.\n const missingVariables: string[] = [];\n for (const variableName of variableNames) {\n // Primitive methods already produced bytes under the full name.\n if (Object.hasOwn(primitiveMethodBytes, variableName) === true) {\n continue;\n }\n\n // A present runtime value will be converted to bytes below.\n if (Object.hasOwn(variables, variableName) === true) {\n continue;\n }\n\n missingVariables.push(variableName);\n }\n\n // Refuse invented defaults so a missing value cannot compile into incorrect bytecode.\n if (missingVariables.length > 0) {\n throw new CashAssemblyRequiredVariableMissingError(missingVariables);\n }\n\n // Convert each variable to its bytes before compilation.\n const variableBytes: Record<string, Uint8Array> = {};\n for (const variableName of variableNames) {\n // Prefer the primitive method result so CashAssembly sees bytes under `base.method`.\n if (Object.hasOwn(primitiveMethodBytes, variableName) === true) {\n variableBytes[variableName] = primitiveMethodBytes[variableName];\n continue;\n }\n\n // Remaining names are caller WalletData that still needs a byte encoding.\n variableBytes[variableName] = convertValueToBytes(variables[variableName], variableName);\n }\n\n // Reuse the names collected above so this compiler is not built from a second parse.\n const compiler = compileCashAssemblyEvaluations({\n evaluations: [ cashAssemblySource ],\n templateScripts,\n variableNames,\n });\n\n return generateCashAssemblyBytecode(compiler, cashAssemblySource, variableBytes, variableNames);\n};\n\n/**\n * Compiles one CashAssembly source to bytes and decodes those bytes to text.\n *\n * @param {CompileCashAssemblySourceToDecodedTextParameters} parameters - Source text, WalletData, optional template context, and decode mode.\n * @returns {string} - Decoded compilation result for that source.\n * @throws {@link CashAssemblyRequiredVariableMissingError} - When a required variable is not present in the variables map.\n * @throws {@link CashAssemblyPrimitiveMethodMissingError} - When a supported primitive hint has an unknown method.\n * @throws {@link CashAssemblyPrimitiveVariableMissingError} - When a supported primitive method is missing its runtime value.\n * @throws {@link CashAssemblyUnsupportedValueTypeError} - When a primitive method return type cannot be embedded as bytes.\n * @throws {@link CashAssemblyNumberNotSafeIntegerError} - When a number variable is not a safe integer.\n * @throws {@link CashAssemblyVmNumberDecodeError} - When `evaluationDecodeMode` is `bigint` and compiled bytes are not a VM number.\n * @throws {@link CashAssemblyIdentifierCollisionError} - When one identifier matches two resolution types.\n * @throws {@link CashAssemblyCompilationFailedError} - When Libauth compilation fails.\n */\nconst compileCashAssemblySourceToDecodedText = (parameters: CompileCashAssemblySourceToDecodedTextParameters): string => {\n const { cashAssemblySource, variables, templateVariables, templateScripts, evaluationDecodeMode } = parameters;\n\n const compilationResult = compileCashAssemblySourceToBytes({\n cashAssemblySource,\n variables,\n templateVariables,\n templateScripts,\n });\n\n return decodeCompiledCashAssemblyEvaluation(compilationResult, evaluationDecodeMode);\n};\n\n/**\n * Compiles CashAssembly text. WalletData names come from parseScript. `$()` evaluations in text\n * are found by scanning the string and matching parentheses.\n *\n * When `cashAssemblyText` contains `$()`, each non empty evaluation is compiled and\n * replaced in place. Empty `$()` is copied through. Surrounding text is kept. Evaluation drops\n * push opcodes and keeps the stack payload.\n *\n * When `cashAssemblyText` contains no `$()` at all, the entire string is compiled as CashAssembly.\n * Push opcodes from `<...>` remain. Pass a template script id such as `scriptA` or\n * concatenated ids such as `scriptA scriptB`.\n *\n * Required WalletData names come from {@link collectVariablesUsingParseScript}.\n *\n * @param {CompileCashAssemblyStringParameters} parameters - Parameters for compiling the CashAssembly string.\n * @returns {string} - Compiled text with evaluations replaced, or decoded bytecode when the whole string is compiled as CashAssembly.\n * @throws {@link CashAssemblyRequiredVariableMissingError} - When a required variable is not present in the variables map.\n * @throws {@link CashAssemblyPrimitiveMethodMissingError} - When a supported primitive hint has an unknown method.\n * @throws {@link CashAssemblyPrimitiveVariableMissingError} - When a supported primitive method is missing its runtime value.\n * @throws {@link CashAssemblyUnsupportedValueTypeError} - When a primitive method return type cannot be embedded as bytes.\n * @throws {@link CashAssemblyNumberNotSafeIntegerError} - When a number variable is not a safe integer.\n * @throws {@link CashAssemblyVmNumberDecodeError} - When `evaluationDecodeMode` is `bigint` and compiled bytes are not a VM number.\n * @throws {@link CashAssemblyIdentifierCollisionError} - When one identifier matches two resolution types.\n * @throws {@link CashAssemblyCompilationFailedError} - When Libauth compilation fails.\n * @throws {@link CashAssemblyEvaluationUnclosedError} - When an evaluation never closes.\n * @throws {@link CashAssemblyQuotedLiteralUnclosedError} - When a quoted literal never closes.\n * @throws {@link CashAssemblyBlockCommentUnclosedError} - When a block comment never closes.\n */\nexport const compileCashAssemblyString = (parameters: CompileCashAssemblyStringParameters): string => {\n const { cashAssemblyText, variables, evaluationDecodeMode = 'utf8', templateVariables, templateScripts } = parameters;\n\n // Scan once so empty `$()` still copies text around `$()` instead of compiling as CashAssembly.\n const scannedEvaluations = scanCashAssemblyEvaluations(cashAssemblyText);\n\n if (scannedEvaluations.length === 0) {\n return compileCashAssemblySourceToDecodedText({\n cashAssemblySource: cashAssemblyText,\n variables,\n templateVariables,\n templateScripts,\n evaluationDecodeMode,\n });\n }\n\n // Copy text outside `$()` and compile each `$()`.\n let textWithCompiledEvaluations = '';\n\n // Start of the next original text slice in cashAssemblyText. Gaps between evaluations must stay intact.\n let nextTextStartIndex = 0;\n\n // When every `$()` is empty, return cashAssemblyText so the original text is unchanged.\n let hasCompiledNonEmptyEvaluation = false;\n\n for (const scannedEvaluation of scannedEvaluations) {\n textWithCompiledEvaluations += cashAssemblyText.slice(nextTextStartIndex, scannedEvaluation.startIndex);\n\n // Empty `$()` has no contents to compile.\n if (scannedEvaluation.evaluationText === EMPTY_CASHASSEMBLY_EVALUATION) {\n textWithCompiledEvaluations += scannedEvaluation.evaluationText;\n } else {\n hasCompiledNonEmptyEvaluation = true;\n textWithCompiledEvaluations += compileCashAssemblySourceToDecodedText({\n cashAssemblySource: scannedEvaluation.evaluationText,\n variables,\n templateVariables,\n templateScripts,\n evaluationDecodeMode,\n });\n }\n\n // Advance past this `$()` so nested evaluations inside it are not copied again.\n nextTextStartIndex = scannedEvaluation.closeIndex + 1;\n }\n\n // Copy text after the last `$()` so the suffix is kept.\n textWithCompiledEvaluations += cashAssemblyText.slice(nextTextStartIndex);\n\n if (hasCompiledNonEmptyEvaluation === false) {\n return cashAssemblyText;\n }\n\n return textWithCompiledEvaluations;\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.mjs","names":["#listeners","#options","#calculateDelay","#abortController","#exponentialBackoff","#stream","#controller","#closed","#textDecoder","#messageBuffer","#url","#connectionController","#resetEventParser","#ensureMessageStreamOpen","#createReader","#closeMessageStream","#readStream","#retryInterval"],"sources":["../source/errors.ts","../source/event-emitter.ts","../source/exponential-backoff/errors.ts","../source/misc.ts","../source/exponential-backoff/exponential-backoff.ts","../source/exponential-backoff/exponential-backoff-externally-aborted.ts","../source/extended-json.ts","../source/script.ts","../source/sse-session/async-push-iterator.ts","../source/sse-session/constants.ts","../source/sse-session/sse-event-parser.ts","../source/sse-session/errors.ts","../source/sse-session/sse-session.ts","../source/template/errors.ts","../source/template/serialization.ts","../source/template/identifier.ts","../source/template/schemas.ts","../source/template/parser.ts","../source/cash-assembly/errors.ts","../source/cash-assembly/collect-evaluations.ts","../source/cash-assembly/bytes.ts","../source/cash-assembly/defaults.ts","../source/cash-assembly/primitive-evaluations.ts","../source/cash-assembly/identifier-collisions.ts","../source/cash-assembly/scan-evaluations.ts","../source/cash-assembly/evaluations.ts"],"sourcesContent":["/**\n * Error thrown when a waitFor timeout is reached\n */\nexport class WaitForTimeoutError extends Error {\n constructor(type: string) {\n super(`Timeout waiting for event \"${type}\"`);\n this.name = 'WaitForTimeoutError';\n }\n}\n","import type { DeeplyReadonly } from './types.ts';\nimport type { deepFreeze } from './misc.ts';\n\nimport { WaitForTimeoutError } from './errors.ts';\n\nexport type EventMap = Record<string, unknown>;\n\ntype Listener<T> = (detail: T) => void;\n\n/**\n * Internally permits listeners for individual event payloads to be stored\n * in a collection typed with the union of all event payloads.\n */\ntype StoredListener<T> = {\n bivarianceHack(detail: T): void;\n}['bivarianceHack'];\n\n/**\n * A listener entry.\n * @template T - The event payload type.\n */\ninterface ListenerEntry<T> {\n listener: StoredListener<T>;\n wrappedListener: StoredListener<T>;\n cancel: () => void;\n}\n\n/**\n * Callback returned by {@link on} and {@link once} for removing a listener.\n */\nexport type OffCallback = () => void;\n\n/**\n * A simple event emitter implementation.\n * @template T - The event map type.\n */\nexport class EventEmitter<T extends EventMap> {\n /**\n * The listeners map.\n * @private\n */\n #listeners: Map<keyof T, Set<ListenerEntry<T[keyof T]>>> = new Map();\n\n /**\n * Add a listener for an event.\n * @param type - The event type.\n * @param listener - The listener function.\n * @param debounceMilliseconds - The debounce time in milliseconds.\n * @returns An off callback that can be called to stop listening for events.\n */\n on<K extends keyof T>(type: K, listener: Listener<T[K]>, debounceMilliseconds: number = 0): OffCallback {\n const { cancel, listener: cancellableListener } = this.cancellable(listener);\n\n // Create a wrapped listener so that the debounce can be applied.\n const wrappedListener = debounceMilliseconds > 0 ? this.debounce(cancellableListener, debounceMilliseconds) : cancellableListener;\n\n // If the listeners map does not have the event type, create a new set.\n if (!this.#listeners.has(type)) {\n this.#listeners.set(type, new Set());\n }\n\n // Create a listener entry.\n const listenerEntry: ListenerEntry<T[K]> = {\n listener,\n wrappedListener,\n cancel,\n };\n\n // Add the listener entry to the listeners map.\n this.#listeners.get(type)?.add(listenerEntry);\n\n // Return an \"off\" callback that can be called to stop listening for events.\n return () => this.off(type, listener);\n }\n\n /**\n * Add a one-time listener for an event.\n * @param type - The event type.\n * @param listener - The listener function.\n * @param debounceMilliseconds - The debounce time in milliseconds.\n * @returns An off callback that can be called to stop listening for events.\n */\n once<K extends keyof T>(type: K, listener: Listener<T[K]>, debounceMilliseconds: number = 0): OffCallback {\n const wrappedListener: Listener<T[K]> = (detail: T[K]) => {\n this.off(type, listener);\n listener(detail);\n };\n\n // Create a cancellable listener.\n const { cancel, listener: cancellableListener } = this.cancellable(wrappedListener);\n\n // Create a debounced listener.\n const debouncedListener = debounceMilliseconds > 0 ? this.debounce(cancellableListener, debounceMilliseconds) : cancellableListener;\n\n // If the listeners map does not have the event type, create a new set.\n if (!this.#listeners.has(type)) {\n this.#listeners.set(type, new Set());\n }\n\n // Create a listener entry.\n const listenerEntry: ListenerEntry<T[K]> = {\n listener,\n wrappedListener: debouncedListener,\n cancel,\n };\n\n // Add the listener entry to the listeners map.\n this.#listeners.get(type)?.add(listenerEntry);\n\n // Return an \"off\" callback that can be called to stop listening for events.\n return () => this.off(type, listener);\n }\n\n /**\n * Remove a listener for an event.\n * @param type - The event type.\n * @param listener - The listener function.\n */\n off<K extends keyof T>(type: K, listener?: Listener<T[K]>): void {\n // Get the listeners for the event type.\n const listeners = this.#listeners.get(type);\n if (!listeners) return;\n\n // Find the listener entries (If a listener was provided, only 1 entry will be returned. Otherwise, all entries will be returned).\n const listenerEntries = Array.from(listeners).filter((entry) => !listener || entry.listener === listener || entry.wrappedListener === listener);\n\n // Remove the listener entries from the listeners set.\n listenerEntries.forEach((entry) => {\n // Set the wrapped listener to a no-op function to prevent it from being called by debounced events after it's been removed.\n entry.cancel();\n\n // Remove the listener entry from the listeners set.\n listeners.delete(entry);\n });\n\n // If no listener was provided and no listeners are left for the event type, remove the listeners set from the listeners map.\n if (!listener || this.#listeners.get(type)?.size === 0) {\n this.#listeners.delete(type);\n }\n }\n\n /**\n * Emit an event.\n *\n * @remarks The caller is responsible for ensuring the payload suits the intended mutability requirements.\n * By default, the payload will be mutable, so listeners may mutate the payload, effecting both\n * the original object and the other listeners.\n * To prevent this, the caller can use the {@link Object.freeze} or {@link deepFreeze} function to freeze the payload.\n * This will need to be defined in the EventMap using the built-in {@link Readonly} type or the provided {@link DeeplyReadonly} type.\n *\n * @param type - The event type.\n * @param payload - The event payload.\n * @returns True if there are listeners for the event, false otherwise.\n */\n emit<K extends keyof T>(type: K, payload: T[K]): boolean {\n // Get the listeners for the event type.\n const listeners = this.#listeners.get(type);\n if (!listeners) return false;\n\n // Emit the event to all listeners.\n listeners.forEach((entry) => {\n try {\n entry.wrappedListener(payload);\n } catch (error) {\n console.error(error);\n }\n });\n\n // Return true if there are listeners for the event, false otherwise.\n return listeners.size > 0;\n }\n\n /**\n * Remove all listeners.\n */\n removeAllListeners(): void {\n for (const [ type, listeners ] of this.#listeners.entries()) {\n listeners.forEach((entry) => {\n this.off(type, entry.listener);\n });\n }\n }\n\n /**\n * Wait for an event to be emitted that matches the provided predicate function's criteria.\n * @param type - The event type.\n * @param predicate - Predicate function to filter for whether the event payload matches the criteria.\n * @param timeoutMs - The timeout in milliseconds.\n * @returns The event payload.\n */\n async waitFor<K extends keyof T>(type: K, predicate: (payload: T[K]) => boolean, timeoutMs?: number): Promise<T[K]> {\n // Create a promise to wait for the event to be emitted.\n return new Promise((resolve, reject) => {\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n\n // Create a cleanup function to remove the listener and clear the timeout if it is still pending.\n const cleanup = (listener: Listener<T[K]>): void => {\n // Remove the listener from the listeners map.\n this.off(type, listener);\n\n // Clear the timeout if it is still pending.\n if (timeoutId !== undefined) {\n clearTimeout(timeoutId);\n }\n };\n\n // Create a listener function.\n const listener = (payload: T[K]): void => {\n try {\n // If the event payload does not match the predicate condition, return.\n if (!predicate(payload)) {\n return;\n }\n\n cleanup(listener);\n resolve(payload);\n } catch (error) {\n cleanup(listener);\n reject(error);\n }\n };\n\n // Set up timeout if specified\n if (timeoutMs !== undefined) {\n timeoutId = setTimeout(() => {\n this.off(type, listener);\n reject(new WaitForTimeoutError(String(type)));\n }, timeoutMs);\n }\n\n // Add the listener to the listeners map.\n this.on(type, listener);\n });\n }\n\n /**\n * Debounce a function.\n *\n * @remarks If {@link off} is called on a listener while it is debounced, the timeout is not cleared with clearTimeout.\n * Instead, the function is no-oped.\n *\n * @param func - The function to debounce.\n * @param wait - The wait time in milliseconds.\n * @returns The debounced function.\n */\n private debounce<K extends keyof T>(func: Listener<T[K]>, wait: number): Listener<T[K]> {\n // Create a timeout variable.\n let timeout: ReturnType<typeof setTimeout>;\n\n return (detail: T[K]) => {\n // If a debounce timer is already pending, clear it before scheduling the next one.\n if (timeout !== undefined) {\n clearTimeout(timeout);\n }\n\n timeout = setTimeout(() => {\n func(detail);\n }, wait);\n };\n }\n\n /**\n * Make a function cancellable.\n * @param func - The function to make cancelable.\n * @returns The cancellable function with a cancel method.\n */\n private cancellable<K extends keyof T>(func: Listener<T[K]>): { cancel: () => void; listener: Listener<T[K]> } {\n let cancelled = false;\n\n return {\n cancel: (): boolean => (cancelled = true),\n listener: (detail: T[K]): void => {\n if (cancelled) return;\n func(detail);\n },\n };\n }\n}\n","/* eslint-disable max-classes-per-file */\n\n/**\n * Error thrown when the maximum number of retries is hit in an exponential backoff\n */\nexport class ExponentialBackoffMaxRetriesHitError extends Error {\n constructor(errors: Array<Error>) {\n super('Exponential backoff: Max retries hit', { cause: errors });\n this.name = 'ExponentialBackoffMaxRetriesHitError';\n }\n}\n\n/**\n * Error thrown when the exponential backoff retries are stopped\n */\nexport class ExponentialBackoffStoppedRetriesError extends Error {\n constructor(reason: unknown) {\n // Convert the reason to an error if it is not an error\n const reasonError = reason instanceof Error ? reason : new Error(`${reason}`);\n\n super(`Exponential backoff was aborted: \"${reasonError.message}\"`, { cause: reasonError });\n this.name = 'ExponentialBackoffStoppedRetriesError';\n }\n}\n\n/**\n * Error thrown when an exponential backoff option is too small\n */\nexport class ExponentialBackoffNumberTooSmallError extends Error {\n constructor(option: string, value: number, min: number) {\n super(`Exponential backoff option \"${option}\" is too small. Must be at least ${min}. Received value: ${value}`);\n this.name = 'ExponentialBackoffNumberTooSmallError';\n }\n}\n\n/**\n * Error thrown when an exponential backoff option is out of bounds\n */\nexport class ExponentialBackoffNumberOutOfBoundsError extends Error {\n constructor(option: string, value: number, min: number, max: number) {\n super(`Exponential backoff option \"${option}\" is out of bounds. Must be between ${min} and ${max}. Received value: ${value}`);\n this.name = 'ExponentialBackoffNumberOutOfBoundsError';\n }\n}\n\n/**\n * Error thrown when an exponential backoff option is an invalid infinite integer\n */\nexport class ExponentialBackoffNumberNotFiniteError extends Error {\n constructor(option: string, value: number) {\n super(`Exponential backoff option \"${option}\" is invalid. Must be a finite number. Received value: ${value}`);\n this.name = 'ExponentialBackoffNumberNotFiniteError';\n }\n}\n\n/**\n * Error thrown when an exponential backoff option is not an integer\n */\nexport class ExponentialBackoffNonIntegerError extends Error {\n constructor(option: string, value: number) {\n super(`Exponential backoff option \"${option}\" is invalid. Must be an integer. Received value: ${value}`);\n this.name = 'ExponentialBackoffNonIntegerError';\n }\n}\n\n/**\n * Error thrown when an externally aborted exponential backoff is aborted\n * due to the external abort signal that was passed in to the constructor being aborted by an upstream consumer\n */\nexport class ExternallyAbortedExponentialBackoffExternalSignalAbortedError extends Error {\n constructor(reason: unknown) {\n // Convert the reason to an error if it is not an error\n const reasonError = reason instanceof Error ? reason : new Error(`${reason}`);\n\n super(`Externally aborted exponential backoff: \"${reasonError.message}\"`, { cause: reasonError });\n this.name = 'ExternallyAbortedExponentialBackoffExternalSignalAbortedError';\n }\n}\n\n/**\n * Error thrown when an externally aborted exponential backoff is aborted\n * due to the internal abort signal being aborted using the .abort() method\n */\nexport class ExternallyAbortedExponentialBackoffInternalSignalAbortedError extends Error {\n constructor(reason: unknown) {\n // Convert the reason to an error if it is not an error\n const reasonError = reason instanceof Error ? reason : new Error(`${reason}`);\n\n super(`Externally aborted exponential backoff: \"${reasonError.message}\"`, { cause: reasonError });\n this.name = 'ExternallyAbortedExponentialBackoffInternalSignalAbortedError';\n }\n}\n","import type { DeeplyReadonly } from './types';\n\n/**\n * Recursively freezes an object by iterating over all properties and freezing them.\n * @param obj - The object to freeze.\n * @returns The frozen object.\n */\nexport const deepFreeze = <T>(value: T): DeeplyReadonly<T> => {\n if (value !== null && (typeof value === 'object' || typeof value === 'function')) {\n for (const key of Reflect.ownKeys(value)) {\n const descriptor = Reflect.getOwnPropertyDescriptor(value, key);\n\n if (descriptor && 'value' in descriptor) {\n deepFreeze(descriptor.value);\n }\n }\n\n Object.freeze(value);\n }\n\n return value;\n};\n\n/**\n * Validate the value is within the bounds, returning true if it is within the bounds, false otherwise\n *\n * @param value - The value to validate\n * @param min - The minimum value\n * @param max - The maximum value\n *\n * @returns True if the value is within the bounds, false otherwise\n */\nexport const isWithinBounds = (value: number, min: number, max: number): boolean => {\n if (value < min || value > max) {\n return false;\n }\n\n return true;\n};\n\n/**\n * Converts a non-error to an error\n * @param error - The error to convert\n * @returns The error\n */\nexport const normalizeError = (error: unknown): Error => {\n // Convert the error to an error if it is not already an error\n const errorInstance = error instanceof Error ? error : new Error(`${error}`);\n\n return errorInstance;\n};\n","import {\n ExponentialBackoffStoppedRetriesError,\n ExponentialBackoffMaxRetriesHitError,\n ExponentialBackoffNonIntegerError,\n ExponentialBackoffNumberTooSmallError,\n ExponentialBackoffNumberOutOfBoundsError,\n ExponentialBackoffNumberNotFiniteError,\n} from './errors.ts';\nimport { isWithinBounds } from '../misc.ts';\n\nexport type ExponentialBackoffOptions = {\n\n /**\n * The maximum delay between attempts in milliseconds\n */\n maxDelay: number;\n\n /**\n * The maximum number of attempts. Passing 0 will result in infinite attempts.\n */\n maxAttempts: number;\n\n /**\n * The base delay between attempts in milliseconds\n */\n baseDelay: number;\n\n /**\n * The growth rate of the delay\n */\n growthRate: number;\n\n /**\n * The jitter of the delay as a percentage of growthRate. The jitter is subtracted from the delay.\n */\n jitter: number;\n};\n\n/**\n * The function to call to stop the retries.\n * This mimics the AbortSignal.abort function by taking in a reason for stopping\n *\n * @param reason - The reason for stopping the retries.\n */\nexport type ExponentialBackoffStopRetriesFunction = (reason: unknown) => void;\n\n/**\n * The parameters for the task function\n *\n * @param stopRetries - The function to call to stop the retries\n */\nexport type ExponentialBackoffCallbackParameters = {\n stopRetries: ExponentialBackoffStopRetriesFunction;\n};\n\n/**\n * Options that control a single exponential-backoff run.\n */\nexport type ExponentialBackoffRunOptions = {\n\n /**\n * Called after each failed task attempt.\n */\n onError?: ((error: Error) => void) | undefined;\n\n /**\n * Stops pending delays and prevents future attempts when aborted.\n */\n signal?: AbortSignal | undefined;\n};\n\n/**\n * Options accepted by the static exponential-backoff run helper.\n */\nexport type ExponentialBackoffStaticRunOptions = Partial<ExponentialBackoffOptions> & ExponentialBackoffRunOptions;\n\n/**\n * Exponential backoff is a technique used to retry a function after a delay.\n *\n * The delay increases exponentially with each attempt, up to a maximum delay.\n *\n * The jitter is a random amount of time subtracted from the delay to prevent thundering herd problems.\n *\n * The growth rate is the factor by which the delay increases with each attempt.\n */\nexport class ExponentialBackoff {\n readonly #options: ExponentialBackoffOptions;\n\n /**\n * Creates a new exponential-backoff instance.\n *\n * Unspecified options use the defaults listed below.\n *\n * @param options - Exponential-backoff configuration overrides.\n * @param options.maxDelay - Maximum delay between retries. Default: `10_000` ms.\n * @param options.maxAttempts - Maximum number of attempts; `0` retries indefinitely. Default: `10`.\n * @param options.baseDelay - Delay used as the basis for the first retry. Default: `1_000` ms.\n * @param options.growthRate - Multiplier applied to the delay after each attempt. Default: `2`.\n * @param options.jitter - Maximum proportional reduction subtracted from each delay (0–1). Default: `0.1`.\n *\n * @throws An {@link ExponentialBackoffNumberNotFiniteError} if a provided option is not a finite number\n * @throws An {@link ExponentialBackoffNumberOutOfBoundsError} if a provided option is out of bounds\n * @throws An {@link ExponentialBackoffNumberTooSmallError} if a provided option is too small\n * @throws An {@link ExponentialBackoffNonIntegerError} if a provided option is not an integer\n */\n constructor(options: Partial<ExponentialBackoffOptions> = {}) {\n this.#options = {\n maxDelay: 10_000,\n maxAttempts: 10,\n baseDelay: 1_000,\n growthRate: 2,\n jitter: 0.1,\n ...options,\n };\n\n ExponentialBackoff.validateOptions(this.#options);\n }\n\n /**\n * Create a new ExponentialBackoff instance\n *\n * @param config - The configuration for the exponential backoff\n *\n * @throws An {@link ExponentialBackoffNumberNotFiniteError} if a provided option is not a finite number\n * @throws An {@link ExponentialBackoffNumberOutOfBoundsError} if a provided option is out of bounds\n * @throws An {@link ExponentialBackoffNumberTooSmallError} if a provided option is too small\n * @throws An {@link ExponentialBackoffNonIntegerError} if a provided option is not an integer\n *\n * @returns The ExponentialBackoff instance\n */\n public static from(config?: Partial<ExponentialBackoffOptions>): ExponentialBackoff {\n const backoff = new ExponentialBackoff(config);\n\n return backoff;\n }\n\n /**\n * Run the function with exponential backoff\n *\n * @param taskFn - The function to run\n * @param options - Backoff configuration and options for this run\n *\n * @throws An {@link ExponentialBackoffMaxRetriesHitError} with all the errors that were thrown by the task function\n * @throws An {@link ExponentialBackoffStoppedRetriesError} if the abort signal is activated\n *\n * @returns The result of the function\n */\n public static run<T>(\n taskFn: (callbackParameters: ExponentialBackoffCallbackParameters) => Promise<T>,\n options: Partial<ExponentialBackoffStaticRunOptions> = {},\n ): Promise<T> {\n // Grab onError and signal from the options\n const { onError, signal, ...backoffOptions } = options;\n const backoff = ExponentialBackoff.from(backoffOptions);\n\n return backoff.run(taskFn, { onError, signal });\n }\n\n /**\n * Validate the options for the exponential backoff\n *\n * @param options - The options to validate\n *\n * @throws {@link ExponentialBackoffNumberNotFiniteError} if a provided option is not a finite number\n * @throws {@link ExponentialBackoffNonIntegerError} if a provided option is not an integer\n * @throws {@link ExponentialBackoffNumberOutOfBoundsError} if a provided option is out of bounds\n * @throws {@link ExponentialBackoffNumberTooSmallError} if a provided option is too small\n */\n public static validateOptions(options: ExponentialBackoffOptions): void {\n /** Validate the value is finite, throwing an {@link ExponentialBackoffInvalidInfiniteIntegerError} if the value is infinite */\n const assertIsFinite = (key: string, value: number): void => {\n if (!Number.isFinite(value)) {\n throw new ExponentialBackoffNumberNotFiniteError(key, value);\n }\n };\n\n /** Validate the value is an integer, throwing a {@link ExponentialBackoffNonIntegerError} if it is not an integer */\n const assertIsInteger = (key: string, value: number): void => {\n if (!Number.isInteger(value)) {\n throw new ExponentialBackoffNonIntegerError(key, value);\n }\n };\n\n /** Validate the value is greater than the minimum, throwing a {@link ExponentialBackoffNumberTooSmallError} if it is not */\n const assertIsHigherThan = (key: string, value: number, min: number): void => {\n if (value < min) {\n throw new ExponentialBackoffNumberTooSmallError(key, value, min);\n }\n };\n\n /** Validate the value is within the bounds, throwing a {@link ExponentialBackoffNumberOutOfBoundsError} if it is not within the bounds */\n const assertIsWithinBounds = (key: string, value: number, min: number, max: number): void => {\n if (!isWithinBounds(value, min, max)) {\n throw new ExponentialBackoffNumberOutOfBoundsError(key, value, min, max);\n }\n };\n\n // Validate the max delay\n assertIsFinite('maxDelay', options.maxDelay);\n assertIsHigherThan('maxDelay', options.maxDelay, 0);\n\n // Validate the max attempts\n assertIsFinite('maxAttempts', options.maxAttempts);\n assertIsInteger('maxAttempts', options.maxAttempts);\n assertIsHigherThan('maxAttempts', options.maxAttempts, 0);\n\n // Validate the base delay\n assertIsFinite('baseDelay', options.baseDelay);\n assertIsHigherThan('baseDelay', options.baseDelay, 0);\n\n // Validate the growth rate\n assertIsFinite('growthRate', options.growthRate);\n assertIsHigherThan('growthRate', options.growthRate, 0);\n\n // Validate the jitter\n assertIsFinite('jitter', options.jitter);\n assertIsWithinBounds('jitter', options.jitter, 0, 1);\n }\n\n /**\n * Run the function with exponential backoff\n *\n * If the function fails but we have not hit the max attempts, the error will be passed to the onError callback\n * and the function will be retried with an exponential delay\n *\n * If every attempt fails, an ExponentialBackoffMaxRetriesHitError will be thrown\n * with all errors from the task function.\n *\n * @param taskFn - The function to run\n * @param options - Options that control this run\n *\n * @throws An {@link ExponentialBackoffMaxRetriesHitError} with all the errors that were thrown by the task function\n * @throws An {@link ExponentialBackoffStoppedRetriesError} if the abort signal is activated\n *\n * @returns The result of the function\n */\n public async run<T>(\n taskFn: (callbackParameters: ExponentialBackoffCallbackParameters) => Promise<T>,\n options: ExponentialBackoffRunOptions = {},\n ): Promise<T> {\n const { onError, signal: suppliedSignal } = options;\n\n // The task can stop its own retries without owning the signal supplied by the caller.\n const abortController = new AbortController();\n const stopRetries = abortController.abort.bind(abortController);\n\n // Start with the abort controller signal\n const signals = [ abortController.signal ];\n\n // If we received a signal from the caller, add it to the signals array\n if (suppliedSignal !== undefined) {\n signals.push(suppliedSignal);\n }\n\n // Compose the signals together\n const signal = AbortSignal.any(signals);\n\n // If the composed signal is already aborted, throw an error\n if (signal.aborted) {\n throw new ExponentialBackoffStoppedRetriesError(signal.reason);\n }\n\n // Initialize an empty array to store the errors\n const errors: Error[] = [];\n\n // Initialize the attempt counter\n let attempt = 0;\n\n // If the max attempts is 0, we should continue indefinitely.\n const unlimitedAttempts = this.#options.maxAttempts === 0;\n\n // Loop until we succeed, hit the max attempts, or the abort signal is activated\n while (true) {\n try {\n // Await the promise before returning so its execution context remains in the try-catch\n // If we didn't await, this `run` function would successfully return and any errors would not be caught here.\n return await taskFn({ stopRetries });\n } catch (error) {\n // Store the error in case we fail every attempt\n const errorInstance = error instanceof Error ? error : new Error(`${error}`);\n onError?.(errorInstance);\n\n // If we have unlimited attempts, don't append this to the errors array to prevent a memory leak.\n if (!unlimitedAttempts) {\n errors.push(errorInstance);\n }\n }\n\n // Check if the abort signal has been activated\n if (signal.aborted) {\n // Throw an error if the abort signal has been activated\n throw new ExponentialBackoffStoppedRetriesError(signal.reason);\n }\n\n // Calculate the count for next attempt. Do this now so we can exit before waiting and before running the next attempt.\n const nextAttemptCount = attempt + 1;\n const nextAttemptExceedsMaxAttempts = nextAttemptCount >= this.#options.maxAttempts;\n\n // If the next attempt exceeds the max attempts, break out of the loop\n if (!unlimitedAttempts && nextAttemptExceedsMaxAttempts) {\n break;\n }\n\n // Wait before going to the next attempt\n const delay = this.#calculateDelay(this.#options, attempt);\n\n // Wait for the delay or the abort signal\n await new Promise<void>((resolve, reject) => {\n // eslint-disable-next-line prefer-const\n let timeout: ReturnType<typeof setTimeout>;\n\n // Handle the abort signal\n const abortHandler = (): void => {\n clearTimeout(timeout);\n reject(new ExponentialBackoffStoppedRetriesError(signal.reason));\n };\n\n // Handle the timeout\n const timeoutHandler = (): void => {\n signal.removeEventListener('abort', abortHandler);\n resolve(undefined);\n };\n\n // Set the timeout\n timeout = setTimeout(timeoutHandler, delay);\n\n // Add the abort handler to the abort signal\n signal.addEventListener('abort', abortHandler, { once: true });\n });\n\n attempt++;\n }\n\n // We completed the loop without ever succeeding. Throw an ExponentialBackoffMaxRetriesHitError with all the errors we got\n throw new ExponentialBackoffMaxRetriesHitError(errors);\n }\n\n /**\n * Calculate the delay before we should attempt to retry\n *\n * @param options - The configuration for the exponential backoff\n * @param attempt - The current attempt number\n * @returns The time in milliseconds before another attempt should be made\n */\n #calculateDelay(options: ExponentialBackoffOptions, attempt: number): number {\n // Get the power of the growth rate\n const power = options.growthRate ** attempt;\n\n // Get the delay before jitter or limit\n const rawDelay = options.baseDelay * power;\n\n // Cap the delay to the maximum. Do this before the jitter so jitter does not become larger than delay\n const cappedDelay = Math.min(rawDelay, options.maxDelay);\n\n // Get a random number for the amount to \"jitter\" the delay by\n const jitterAmount = Math.random();\n\n // Calculate the jitter\n const jitter = jitterAmount * options.jitter * cappedDelay;\n\n // Subtract the jitter from the delay\n return cappedDelay - jitter;\n }\n}\n","import {\n ExternallyAbortedExponentialBackoffExternalSignalAbortedError,\n ExternallyAbortedExponentialBackoffInternalSignalAbortedError,\n} from './errors.ts';\nimport { ExponentialBackoff } from './exponential-backoff.ts';\nimport type { ExponentialBackoffCallbackParameters, ExponentialBackoffOptions, ExponentialBackoffRunOptions } from './exponential-backoff.ts';\n\n/**\n * Options for the ExponentialBackoffExternallyAbortable class\n *\n * @extends Partial<ExponentialBackoffOptions>\n * @property abortSignal - The abort signal to use for this instance\n */\nexport type ExponentialBackoffExternallyAbortableOptions = Partial<ExponentialBackoffOptions> & {\n abortSignal: AbortSignal;\n};\n\n/**\n * An exponential backoff that can be stopped by calling `.abort()` or by passing an\n * `abortSignal` to the constructor.\n *\n * @remarks One instance can run many tasks. Aborting it stops retries for every run.\n */\nexport class ExponentialBackoffExternallyAbortable {\n readonly #abortController = new AbortController();\n readonly #exponentialBackoff: ExponentialBackoff;\n\n constructor(options: Partial<ExponentialBackoffExternallyAbortableOptions> = {}) {\n const { abortSignal, ...backoffOptions } = options;\n\n this.#exponentialBackoff = new ExponentialBackoff(backoffOptions);\n\n // Listen for the provided abort signal to be aborted\n abortSignal?.addEventListener(\n 'abort',\n () => {\n this.#abortController.abort(new ExternallyAbortedExponentialBackoffExternalSignalAbortedError(abortSignal.reason));\n },\n {\n once: true,\n // Clean up this listener if the internal abort controller is aborted\n signal: this.#abortController.signal,\n },\n );\n\n // If the abort signal is already aborted, immediately abort the internal abort controller\n if (abortSignal?.aborted) {\n this.#abortController.abort(new ExternallyAbortedExponentialBackoffExternalSignalAbortedError(abortSignal.reason));\n }\n }\n\n /**\n * Run the function with exponential backoff\n *\n * If the function fails but we have not hit the max attempts, the error will be passed to the onError callback\n * and the function will be retried with an exponential delay\n *\n * If every attempt fails, an ExponentialBackoffMaxRetriesHitError will be thrown\n * with all errors from the task function.\n *\n * @param taskFn - The function to run\n * @param options - Options that control this run\n *\n * @throws An {@link ExponentialBackoffMaxRetriesHitError} with all the errors that were thrown by the task function\n * @throws An {@link ExponentialBackoffStoppedRetriesError} if the abort signal is activated\n * @throws An {@link ExternallyAbortedExponentialBackoffExternalSignalAbortedError}\n * if the abort signal that was provided during construction is activated\n * @throws An {@link ExternallyAbortedExponentialBackoffInternalSignalAbortedError}\n * if {@link ExponentialBackoffExternallyAbortable.abort} is called on this class\n *\n * @returns The result of the function\n */\n public run<T>(\n taskFn: (callbackParameters: ExponentialBackoffCallbackParameters) => Promise<T>,\n options: Partial<ExponentialBackoffRunOptions> = {},\n ): Promise<T> {\n let signal = this.#abortController.signal;\n\n // If a signal was provided for this run, compose it with the instance-wide signal\n if (options.signal !== undefined) {\n signal = AbortSignal.any([ signal, options.signal ]);\n }\n\n // Call the exponential backoff run method with the composed signal\n return this.#exponentialBackoff.run(taskFn, { ...options, signal });\n }\n\n /**\n * Stops retries for all current and future runs.\n *\n * @param reason - The reason for stopping retries\n */\n public abort(reason: unknown): void {\n this.#abortController.abort(new ExternallyAbortedExponentialBackoffInternalSignalAbortedError(reason));\n }\n}\n","import { binToHex, hexToBin } from '@bitauth/libauth';\n\n/**\n * Matches a bigint encoded in Extended JSON format: `<bigint: 123n>`.\n */\nconst EXTENDED_JSON_BIGINT_PATTERN = /^<bigint: (?<bigint>[+-]?[0-9]+)n>$/u;\n\n/**\n * Matches a Uint8Array encoded in Extended JSON format: `<uint8array: abcd>`.\n */\nconst EXTENDED_JSON_UINT8ARRAY_PATTERN = /^<uint8array: (?<hex>[0-9a-f]*)>$/u;\n\n/**\n * The JSON replacer that encodes `bigint` and `Uint8Array` values in Extended JSON format,\n * compatible with the format expected by `extendedJsonReviver`.\n *\n * - BigInts are encoded as `<bigint: 123n>`.\n * - Uint8Arrays are encoded as `<uint8array: abcd>`.\n * All other values pass through unchanged and if any incompatible type is encountered, an error is thrown.\n *\n * Note: To use this function, pass it as the second argument to `JSON.stringify` when serializing data.\n *\n * Note to developers: Libauth's `stringify` is the replacer. It also serializes functions and symbols,\n * which we do not support. Passing it would let templates include those values, but revival would then fail.\n * This module provides a dedicated replacer and reviver so serialization and deserialization stay aligned.\n *\n * @param _propertyKey The property key being serialized, required by the `JSON.stringify` replacer but not used here.\n * @param value The value to encode or pass through unchanged.\n * @returns The encoded string\n */\nexport const extendedJsonReplacer = (_propertyKey: string, value: unknown): unknown => {\n if (value instanceof Uint8Array) {\n return `<uint8array: ${binToHex(value)}>`;\n }\n\n if (typeof value === 'bigint') {\n return `<bigint: ${value.toString()}n>`;\n }\n\n return value;\n};\n\n/**\n * The JSON reviver that reconstructs `bigint` and `Uint8Array` values encoded by `extendedJsonReplacer`.\n *\n * Note: To use this function, pass it as the second argument to `JSON.parse` when deserializing data.\n *\n * @param _propertyKey The property key being deserialized, required by the `JSON.parse` reviver but not used here.\n * @param value The value to reconstruct or pass through unchanged.\n * @returns The reconstructed value\n */\nexport const extendedJsonReviver = (_propertyKey: string, value: unknown): unknown => {\n // If the value is not a string, return the original value\n if (typeof value !== 'string') {\n return value;\n }\n\n // Match the bigint pattern\n const bigintPatternMatch = value.match(EXTENDED_JSON_BIGINT_PATTERN);\n\n // If the value matches the bigint pattern, return the reconstructed bigint\n if (bigintPatternMatch) {\n return BigInt(bigintPatternMatch.groups!.bigint);\n }\n\n // Match the Uint8Array pattern\n const uint8arrayPatternMatch = value.match(EXTENDED_JSON_UINT8ARRAY_PATTERN);\n\n // If the value matches the Uint8Array pattern, return the reconstructed Uint8Array\n if (uint8arrayPatternMatch) {\n return hexToBin(uint8arrayPatternMatch.groups!.hex);\n }\n\n // If the value does not match either pattern, return the original value\n return value;\n};\n\n/**\n * Serializes an object to a string using the {@link extendedJsonReplacer}.\n *\n * @param object The object to serialize.\n * @returns The string representation of the object in Extended JSON format.\n */\nexport const toExtendedJson = (object: unknown): string => {\n return JSON.stringify(object, extendedJsonReplacer);\n};\n\n/**\n * Deserializes a string to an object using the {@link extendedJsonReviver}.\n *\n * @param serializedObject The string to deserialize.\n * @returns The object reconstructed from the string.\n */\nexport const fromExtendedJson = (serializedObject: string): unknown => {\n return JSON.parse(serializedObject, extendedJsonReviver);\n};\n","import { binToHex, sha256 } from '@bitauth/libauth';\n\n/**\n * Converts a script to a scriptHash.\n * @param {Uint8Array} script - The script to convert.\n * @returns {string} The scriptHash as a reversed hex string.\n */\nexport const scriptToScriptHash = (script: Uint8Array): string => {\n // Hash the script.\n const hash = sha256.hash(script);\n\n // Reverse the hash. (Electrum style, reverse switches to little endian representation)\n const reversed = hash.reverse();\n\n // Convert the reversed hash to hex.\n return binToHex(reversed);\n};\n","/**\n * An async iterable queue that bridges push-based producers and pull-based consumers.\n *\n * Composes an internal {@link ReadableStream} instead of extending it, so producers\n * call {@link push} while consumers use standard async iteration (`for await...of`).\n *\n * ```ts\n * const messages = new AsyncPushIterator<SSEvent>();\n *\n * // Producer (elsewhere)\n * messages.push(event);\n *\n * // Consumer\n * for await (const event of messages) {\n * handle(event);\n * }\n * ```\n *\n * {@link Symbol.asyncIterator} returns `stream.values({ preventCancel: true })` so\n * breaking out of `for await...of` does not cancel the underlying stream. That\n * matters for long-lived sessions where the producer keeps pushing after a consumer\n * stops reading early (for example, test helpers that only collect a fixed count).\n */\nexport class AsyncPushIterator<T> {\n /** ReadableStream backing the async iterator returned from {@link Symbol.asyncIterator}. */\n #stream: ReadableStream<T>;\n\n /** Controller used to enqueue values and close the stream from {@link push} and {@link close}. */\n #controller: ReadableStreamDefaultController<T> | undefined;\n\n /** When true, no more values are accepted and iteration eventually completes. */\n #closed = false;\n\n public constructor() {\n // `start`'s `this` is the underlying source object when using a plain method.\n // An arrow function captures the class instance so the controller is stored here.\n this.#stream = new ReadableStream({\n start: (controller: ReadableStreamDefaultController<T>): void => {\n this.#controller = controller;\n },\n });\n }\n\n /**\n * Flag indicating if the iterator is closed.\n */\n public get closed(): boolean {\n return this.#closed;\n }\n\n /**\n * Enqueues a value for the consumer.\n *\n * After {@link close}, pushes are silently dropped.\n *\n * @param value - The next value to yield from the iterator.\n */\n push(value: T): void {\n if (this.#closed) return;\n\n this.#controller?.enqueue(value);\n }\n\n /**\n * Causes any future interactions with the associated stream to error with {@link error}.\n * Calling this will also clear the pending values immediately, so iterators that were listening will not receive them.\n *\n * @param error - The error to throw from the stream.\n */\n error(error: Error): void {\n if (this.#closed) return;\n\n this.#closed = true;\n this.#controller?.error(error);\n }\n\n /**\n * Ends the stream.\n *\n * Marks the iterator closed so future {@link push} calls are ignored.\n * Buffered values are still yielded before iteration completes.\n */\n close(): void {\n this.#closed = true;\n\n try {\n this.#controller?.close();\n } catch {\n // The reader may already have released or cancelled the stream.\n }\n }\n\n /**\n * Returns an async iterator over the composed stream.\n *\n * Uses `preventCancel: true` so early `break` from `for await...of` does not\n * close the stream and block later pushes.\n *\n * Because values are discarded after being read, only a single consumer is supported.\n * Additional consumers will receive a stream lock error. Unread values will be preserved until {@link close} is called.\n */\n [Symbol.asyncIterator](): AsyncIterableIterator<T> {\n return this.#stream.values({ preventCancel: true });\n }\n}\n","/**\n * Regex that splits decoded SSE text into lines.\n *\n * The SSE wire format is line-oriented (`field: value` per line). Servers may\n * send `\\r\\n` (HTTP default), `\\n` (Unix), or `\\r` (legacy Mac). Matching all\n * three keeps parsing correct regardless of platform or server implementation.\n */\nexport const SSE_LINE_ENDINGS = /\\r\\n|\\r|\\n/;\n\n/**\n * Regex that matches the single optional leading space in an SSE field value.\n *\n * Per the SSE spec, `field: value` may include one space immediately after the\n * colon; that space is not part of the value. Used with `.replace()` to strip\n * it when parsing lines such as `data: hello` → `hello`.\n */\nexport const SSE_FIELD_VALUE_REGEX = /^ /;\n\n/**\n * Regex that matches a trailing newline at the end of a string.\n *\n * Multiple `data:` lines in one event are joined with `\\n`. When the event is\n * completed, this removes any stray trailing newline so callers receive the\n * payload without an extra line break at the end.\n */\nexport const SSE_TRAILING_NEWLINE_REGEX = /\\n$/;\n\n/**\n * The newline character used when normalizing SSE text internally.\n *\n * Used to join consecutive `data:` lines into one payload and to reassemble\n * buffered partial lines between streamed chunks before the next parse call.\n */\nexport const NEW_LINE = '\\n';\n\n/**\n * Default exponential backoff options for the SSE session.\n */\nexport const SSE_SESSION_EXPONENTIAL_BACKOFF_DEFAULTS = {\n baseDelay: 250,\n maxDelay: 10000,\n maxAttempts: 0,\n growthRate: 1.3,\n jitter: 0.3,\n} as const;\n\n/**\n * Default attempt reconnect flag for the SSE session.\n * @default true\n */\nexport const SSE_SESSION_ATTEMPT_RECONNECT_DEFAULT = true;\n\n/**\n * Default persistent flag for the SSE session.\n * @default false\n */\nexport const SSE_SESSION_PERSISTENT_DEFAULT = false;\n","import type { SSEvent } from './types.ts';\nimport { NEW_LINE, SSE_FIELD_VALUE_REGEX, SSE_LINE_ENDINGS, SSE_TRAILING_NEWLINE_REGEX } from './constants.ts';\n\n/**\n * Optional encoders used when decoding incoming SSE bytes and re-encoding\n * any buffered remainder between chunks.\n */\nexport interface SSEEventParserOptions {\n\n /** Decodes raw stream bytes into text. Defaults to a new `TextDecoder`. */\n textDecoder: TextDecoder;\n}\n\n/**\n * Incrementally parses Server-Sent Events (SSE) from streamed byte chunks.\n *\n * SSE payloads are line-oriented: each event is a sequence of `field: value`\n * lines terminated by a blank line. This parser accepts arbitrary chunk\n * boundaries from a live HTTP response body and emits only complete events.\n *\n * Typical usage is one parser instance per connection, calling {@link parseEvents}\n * for each chunk received from the stream:\n *\n * ```ts\n * const parser = new SSEEventParser();\n *\n * for await (const chunk of response.body) {\n * for (const event of parser.parseEvents(chunk)) {\n * // handle event.data, event.event, event.id, event.retry\n * }\n * }\n * ```\n *\n * Supported fields follow the SSE spec: `data`, `event`, `id`, and `retry`.\n * Multiple `data:` lines in one event are joined with `\\n`. An event is only\n * emitted once a blank line is seen and at least one `data` field was collected.\n */\nexport class SSEEventParser {\n readonly #textDecoder: TextDecoder;\n\n /** Bytes from a partial line or incomplete event, carried over to the next chunk. */\n #messageBuffer: string = '';\n\n /**\n * Creates a parser for one SSE stream.\n *\n * Inject custom encoders in tests or when a non-default character encoding\n * is required; production callers can rely on the defaults.\n *\n * @param options - Optional text encoders for decode/encode of stream bytes.\n */\n constructor(options: Partial<SSEEventParserOptions> = {}) {\n this.#textDecoder = options.textDecoder ?? new TextDecoder();\n }\n\n /**\n * Clears any buffered bytes from a partial line or incomplete event.\n *\n * Call when abandoning a transport so the next connection does not prepend\n * stale bytes to incoming chunks.\n */\n public reset(): void {\n // Clear the message buffer\n this.#messageBuffer = '';\n\n // Reset the decoder to clear any buffered bytes\n this.#textDecoder.decode();\n }\n\n /**\n * Parses all complete SSE events contained in a newly received chunk.\n *\n * The chunk is appended to any bytes buffered from earlier calls. Complete\n * events (blank-line delimited blocks with at least one `data` field) are\n * returned immediately; any trailing partial line or in-progress event stays\n * in the internal buffer until a later chunk completes it.\n *\n * @param chunk - Newly received SSE stream bytes.\n * @returns Zero or more complete parsed SSE events from this chunk.\n */\n public parseEvents(chunk: Uint8Array): SSEvent[] {\n const lines = this.getBufferedLines(chunk);\n\n const eventLines = lines.slice(0, -1);\n\n const events: SSEvent[] = [];\n let event: Partial<SSEvent> = {};\n let processedLineCount = 0;\n\n for (const [ index, line ] of eventLines.entries()) {\n // A blank line indicates the end of an event. If we have received data, we can complete the event\n if (line === '') {\n if (event.data !== undefined) {\n events.push(this.completeEvent(event));\n event = {};\n processedLineCount = index + 1;\n }\n\n continue;\n }\n\n this.parseLine(line, event);\n }\n\n this.storeRemainingLines(lines, processedLineCount);\n\n return events;\n }\n\n /**\n * Appends a new chunk to the buffered bytes and splits the combined payload\n * into lines.\n *\n * Accepts `\\r\\n`, `\\r`, and `\\n` line endings so events parse correctly\n * regardless of server or platform conventions.\n */\n private getBufferedLines(chunk: Uint8Array): string[] {\n this.#messageBuffer += this.#textDecoder.decode(chunk, { stream: true });\n\n return this.#messageBuffer.split(SSE_LINE_ENDINGS);\n }\n\n /**\n * Parses one SSE field line into an in-progress event.\n *\n * Lines without a colon are ignored. A single optional space after the colon\n * is stripped from the field value, per the SSE spec.\n */\n private parseLine(line: string, event: Partial<SSEvent>): void {\n const colonIndex = line.indexOf(':');\n if (colonIndex === -1) return;\n\n const field = line.slice(0, colonIndex);\n const value = line.slice(colonIndex + 1).replace(SSE_FIELD_VALUE_REGEX, '');\n\n switch (field) {\n case 'data':\n event.data = event.data ? `${event.data}${NEW_LINE}${value}` : value;\n\n return;\n\n case 'event':\n event.event = value;\n\n return;\n\n case 'id':\n event.id = value;\n\n return;\n\n case 'retry':\n this.parseRetry(value, event);\n\n return;\n }\n }\n\n /**\n * Applies a numeric `retry:` field to an in-progress event.\n *\n * Non-numeric values are ignored rather than failing the parse.\n */\n private parseRetry(value: string, event: Partial<SSEvent>): void {\n const retry = parseInt(value, 10);\n\n if (!isNaN(retry)) {\n event.retry = retry;\n }\n }\n\n /**\n * Constructs a completed SSE event from accumulated fields.\n *\n * Trims a trailing newline from multi-line `data` values so callers receive\n * the payload without an extra line break at the end.\n */\n private completeEvent(event: Partial<SSEvent>): SSEvent {\n return {\n ...event,\n data: event.data?.replace(SSE_TRAILING_NEWLINE_REGEX, ''),\n } as SSEvent;\n }\n\n /**\n * Preserves incomplete trailing lines for the next received chunk.\n *\n * Only lines that were fully processed (through a completed event boundary)\n * are discarded; the remainder is re-encoded into {@link messageBuffer}.\n */\n private storeRemainingLines(lines: string[], processedLineCount: number): void {\n this.#messageBuffer = lines.slice(processedLineCount).join(NEW_LINE);\n }\n}\n","/* eslint-disable max-classes-per-file */\n\n/**\n * Error thrown when a response body is null\n */\nexport class ResponseBodyNullError extends Error {\n constructor() {\n super('Response body is null');\n this.name = 'ResponseBodyNullError';\n }\n}\n\n/**\n * Error thrown when an HTTP error occurs\n */\nexport class HTTPError extends Error {\n constructor(status: number, message: string) {\n super(`HTTP error! Status: ${status} - ${message}`);\n this.name = 'HTTPError';\n }\n}\n\n/**\n * Error thrown when a plugin's unsubscribe function is not a function\n */\nexport class SSESessionUnsubscribePluginNotAFunctionError extends Error {\n constructor(pluginName: string) {\n super(`${pluginName}'s unsubscribe function is not a function`);\n this.name = 'SSESessionUnsubscribePluginNotAFunctionError';\n }\n}\n","import type { SSESessionOptions, SSESessionEventMap, SSEvent, SSESessionEventCallbacks, SSESessionOperationContext } from './types.ts';\nimport { SSE_SESSION_EXPONENTIAL_BACKOFF_DEFAULTS, SSE_SESSION_ATTEMPT_RECONNECT_DEFAULT, SSE_SESSION_PERSISTENT_DEFAULT } from './constants.ts';\n\nimport { EventEmitter, type OffCallback } from '../event-emitter.ts';\nimport { ExponentialBackoff } from '../exponential-backoff/index.ts';\nimport { normalizeError } from '../misc.ts';\n\nimport { SSEEventParser } from './sse-event-parser.ts';\nimport { AsyncPushIterator } from './async-push-iterator.ts';\nimport { HTTPError, ResponseBodyNullError, SSESessionUnsubscribePluginNotAFunctionError } from './errors.ts';\n\n/**\n * A fetch-based Server-Sent Events (SSE) client with reconnect and optional\n * browser tab visibility handling.\n *\n * Each session maintains one HTTP streaming connection at a time. Incoming\n * bytes are parsed into {@link SSEvent} objects and delivered through two\n * surfaces:\n *\n * - **Events** — `\"connected\"`, `\"message\"`, `\"disconnected\"`, `\"error\"`,\n * and `\"closed\"` on the session itself (extends {@link EventEmitter}).\n * - **Messages** — {@link messages}, an async iterable for `for await...of`\n * consumers.\n *\n * Typical usage:\n *\n * ```ts\n * const session = await SSESession.create(\"/events\");\n *\n * session.on(\"message\", (event) => console.log(event.data));\n *\n * for await (const event of session.messages) {\n * handle(event);\n * }\n * ```\n *\n * ## Lifecycle\n *\n * - {@link connect} opens (or reopens) the transport. It resolves once the\n * HTTP stream is established; reading continues in the background.\n * - {@link disconnect} stops the in-flight fetch without ending the session.\n * Used internally for tab visibility. The {@link messages} iterator stays\n * open so an existing consumer resumes when the tab becomes visible again.\n * - {@link close} aborts the transport, closes {@link messages}, and emits\n * `\"closed\"`.\n *\n * Automatic reconnect is controlled by {@link SSESessionOptions.persistent}\n * (server closed the stream) and\n * {@link SSESessionOptions.attemptReconnect} (transport error).\n *\n * ## Connection supersession\n *\n * Each {@link connect} will create a new controller if one does not exist. Otherwise,\n * it will return immediately.\n */\nexport class SSESession extends EventEmitter<SSESessionEventMap> {\n /**\n * Creates a session and waits until the first connection is established.\n *\n * @param url - The SSE endpoint URL.\n * @param options - Configuration merged with instance defaults.\n * @returns A connected session.\n * @throws When the initial connection cannot be established.\n */\n static async create(url: string, options: Partial<SSESessionOptions & SSESessionEventCallbacks> = {}): Promise<SSESession> {\n const session = new SSESession(url, options);\n await session.connect();\n\n return session;\n }\n\n /**\n * Enables SSE resume semantics by sending `Last-Event-ID` on reconnect.\n *\n * Listens for incoming `\"message\"` events and remembers the most recent\n * {@link SSEvent.id}. On every subsequent connect or reconnect, the session's\n * {@link onRequest} hook is wrapped so that header is attached when an id is\n * known, allowing the server to replay only events the client has not yet\n * received.\n *\n * The existing {@link onRequest} callback is preserved and runs after the\n * header is applied, so auth or other header mutations continue to work.\n *\n * Since this relies on listening to the `\"message\"` event, this should ideally\n * be called before \"{@link connect} is called so no messages (and no ids) are missed.\n *\n * ```ts\n * const session = new SSESession(url);\n * SSESession.addLastEventIdReconnect(session);\n * await session.connect();\n * // Reconnects send Last-Event-ID once an event with an id is received.\n * ```\n *\n * @param session - The session to instrument.\n * @returns The same session, for chaining.\n */\n static addLastEventIdReconnect(session: SSESession): { session: SSESession; removeListener?: OffCallback } {\n // If the plugin is already installed, we return the session and the remove listener function.\n if (session.plugins.has(SSESession.addLastEventIdReconnect)) {\n // Get the remove listener function from the session.\n const removeListener = session.plugins.get(SSESession.addLastEventIdReconnect) as OffCallback;\n\n // If the plugin was added with a non-function listener, we throw an error.\n if (typeof removeListener !== 'function') {\n throw new SSESessionUnsubscribePluginNotAFunctionError('addLastEventIdReconnect');\n }\n\n // If the plugin is already installed, we return the session and the remove listener function.\n return { session, removeListener };\n }\n\n // Store the last event id so we can send it on reconnect.\n let lastEventId: string | undefined;\n\n // Define the message listener that will store the last event id and begin listening for 'message' events.\n const messageListener = (event: SSEvent): void => {\n // If the event has no id, we should not update the lastEventId and instead keep the old one.\n lastEventId = event.id ?? lastEventId;\n };\n\n session.on('message', messageListener);\n\n // Store the original onRequest callback so we can extend its behavior to write the reconnect header.\n const originalOnRequest = session.options.onRequest;\n\n // Whether we actively send the Last-Event-ID header on reconnect.\n // Because the `onRequest` callback may be extended further by other code, we can't just roll-back to the `originalOnRequest`\n // Instead, we just use this flag to determine if we should write the Last-Event-ID header.\n let enabled = true;\n\n // Extend the onRequest callback to write the Last-Event-ID header if it is enabled.\n session.options.onRequest = async (request: RequestInit): Promise<RequestInit> => {\n if (lastEventId && enabled) {\n request.headers = { ...request.headers, 'Last-Event-ID': lastEventId };\n }\n\n return originalOnRequest(request);\n };\n\n // Define the remove listener function that will disable the Last-Event-ID header on reconnect.\n const removeListener = (): void => {\n enabled = false;\n session.off('message', messageListener);\n\n // If the remove listener function is the same as the existing remove listener function, we remove the plugin from the session.\n // This protects against the `removeListener` function being called onto after a new instance of this plugin is added\n const existingRemoveListener = session.plugins.get(SSESession.addLastEventIdReconnect) as OffCallback;\n if (existingRemoveListener === removeListener) {\n session.plugins.delete(SSESession.addLastEventIdReconnect);\n }\n };\n\n // Store the plugin in the session.\n session.plugins.set(SSESession.addLastEventIdReconnect, removeListener);\n\n return { session, removeListener };\n }\n\n /**\n * Pauses and resumes a session based on browser tab visibility.\n *\n * Uses the Page Visibility API (`document.visibilitychange`):\n *\n * - **hidden** — {@link disconnect} stops the active fetch. {@link messages}\n * stays open; `\"disconnected\"` fires but `\"closed\"` does not.\n * - **visible** — {@link connect} re-establishes the stream if needed.\n *\n * This controller will not re-connect if the session was disconnected by something else.\n *\n * No-op in non-browser environments where `document` is undefined.\n *\n * @param session - The session to manage.\n */\n static addBrowserVisibilityHandler(session: SSESession): { session: SSESession; removeListener?: OffCallback } {\n if (typeof document === 'undefined') return { session };\n\n // If the plugin is already installed, we return the session and the remove listener function.\n if (session.plugins.has(SSESession.addBrowserVisibilityHandler)) {\n // Get the remove listener function from the session.\n const removeListener = session.plugins.get(SSESession.addBrowserVisibilityHandler) as OffCallback;\n\n // If the plugin was added with a non-function listener, we throw an error.\n if (typeof removeListener !== 'function') {\n throw new SSESessionUnsubscribePluginNotAFunctionError('addBrowserVisibilityHandler');\n }\n\n // If the plugin is already installed, we return the session and the remove listener function.\n return { session, removeListener };\n }\n\n // Create a listener that will reconnect the session\n // This listener is added when the hidden->disconnect listener disconnects the session, but will not be added\n // if the session was disconnected by something else, like a manual disconnect, server-disconnect, or another plugin.\n const reconnectOnVisible = async (): Promise<void> => {\n if (document.visibilityState === 'visible') {\n // Remove this listener\n document.removeEventListener('visibilitychange', reconnectOnVisible);\n\n // Reconnect the session\n await session.connect();\n }\n };\n\n // Create a listener that will disable the reconnect listener if the session is disconnected by something else.\n const disableOnExternalDisconnect = ({ source }: SSESessionOperationContext): void => {\n // If the source is not the browser visibility handler, we remove the listener.\n if (source !== SSESession.addBrowserVisibilityHandler) {\n document.removeEventListener('visibilitychange', reconnectOnVisible);\n }\n };\n\n // Create a listener that will live as-long as this session is not closed\n // This listener will create a new 'on visible' listener that will reconnect the session when it disconnects the session.\n // This prevents it from trying to reconnect the session if the session was disconnected by something else\n const handleVisibilityChange = async (): Promise<void> => {\n // If the session is not connected, we do nothing.\n if (!session.active) {\n return;\n }\n\n // If the session is connected and the visibility is hidden, we disconnect it.\n if (document.visibilityState === 'hidden') {\n // Add the listener for connected event to reconnect the session.\n document.addEventListener('visibilitychange', reconnectOnVisible);\n\n // Disconnect the session.\n session.disconnect({ source: SSESession.addBrowserVisibilityHandler });\n }\n };\n\n // Add the listener for visibility change.\n document.addEventListener('visibilitychange', handleVisibilityChange);\n\n // Add a listener for `beforeDisconnect` event to disable the reconnect listener if the session is disconnected by something else.\n session.on('beforeDisconnect', disableOnExternalDisconnect);\n\n // Remove the listener for visibility change.\n const removeListener = (): void => {\n document.removeEventListener('visibilitychange', handleVisibilityChange);\n document.removeEventListener('visibilitychange', reconnectOnVisible);\n\n session.off('beforeDisconnect', disableOnExternalDisconnect);\n\n // If the remove listener function is the same as the existing remove listener function, we remove the plugin from the session.\n // This protects against the `removeListener` function being called onto after a new instance of this plugin is added\n const existingRemoveListener = session.plugins.get(SSESession.addBrowserVisibilityHandler) as OffCallback;\n if (existingRemoveListener === removeListener) {\n session.plugins.delete(SSESession.addBrowserVisibilityHandler);\n }\n };\n\n // Store the plugin in the session.\n session.plugins.set(SSESession.addBrowserVisibilityHandler, removeListener);\n\n // Return the session and the remove listener function.\n return { session, removeListener };\n }\n\n /** SSE endpoint URL for this session. */\n readonly #url: string;\n\n /**\n * Per-instance configuration.\n *\n * Defaults live on the instance field (not a shared static) so each session\n * gets its own {@link SSEEventParser} and {@link ExponentialBackoff}.\n */\n public options: SSESessionOptions = {\n // Fetch options\n fetch: (...args) => fetch(...args),\n method: 'GET',\n headers: {\n Accept: 'text/event-stream',\n 'Cache-Control': 'no-cache',\n },\n body: new FormData(),\n\n // callback to mutate the fetch options before the fetch is made.\n onRequest: (request) => Promise.resolve(request),\n\n // Retry the initial fetch.\n // Use the spread operator so it's impossible for us to override the default options. (default is exponential backoff)\n retry: new ExponentialBackoff({\n ...SSE_SESSION_EXPONENTIAL_BACKOFF_DEFAULTS,\n }),\n\n // Reconnection options\n attemptReconnect: SSE_SESSION_ATTEMPT_RECONNECT_DEFAULT,\n persistent: SSE_SESSION_PERSISTENT_DEFAULT,\n\n // Event parser options\n eventParser: new SSEEventParser(),\n };\n\n /**\n * Registered plugins for the session.\n * This can be used to prevent duplicate plugins from being added to the session.\n * The value for a plugin is arbitrary, for example a function that removes the plugin.\n */\n public readonly plugins: Map<unknown, unknown> = new Map();\n\n /** AbortController for the currently active fetch, if any. */\n #connectionController: AbortController | null = null;\n\n /** The server's requested retry interval in milliseconds (per SSE spec) if any */\n #retryInterval: number | null = null;\n\n /**\n * Asynchronous stream of parsed SSE events for the active connection.\n *\n * Stays open across {@link disconnect} and automatic reconnects so an existing\n * `for await` consumer keeps receiving events after visibility resumes.\n *\n * Closes when:\n * - the server ends the stream and {@link SSESessionOptions.persistent}\n * is false,\n * - {@link close} is called, or\n * - a transport error occurs with\n * {@link SSESessionOptions.attemptReconnect} disabled.\n *\n * A later {@link connect} replaces this with a new iterator when the\n * previous one was closed. Consumers should read from `session.messages`\n * rather than caching a reference across terminal disconnects.\n */\n public messages: AsyncPushIterator<SSEvent> = new AsyncPushIterator<SSEvent>();\n\n public constructor(url: string, options: Partial<SSESessionOptions & SSESessionEventCallbacks> = {}) {\n super();\n\n const { onConnected, onDisconnected, onError, ...restOptions } = options;\n\n this.#url = url;\n this.options = {\n ...this.options,\n ...restOptions,\n // Shallow merge would drop default headers when options.headers is set.\n headers: { ...this.options.headers, ...options.headers },\n };\n\n // Add the onConnected, onDisconnected, and onError as event listeners to the session.\n // We accept these as options to the constructor so that we can both instantiate the session and add the event listeners at the same time,\n // avoiding any potential race-conditions or async/await issues.\n if (onConnected) {\n this.on('connected', onConnected);\n }\n\n if (onDisconnected) {\n this.on('disconnected', onDisconnected);\n }\n\n if (onError) {\n this.on('error', onError);\n }\n }\n\n /**\n * Returns true if the session is active by checking if the controller is not null.\n */\n public get active(): boolean {\n return this.#connectionController !== null;\n }\n\n /**\n * Connects or reconnects to the SSE endpoint.\n *\n * Resolves once the HTTP stream is established and `\"connected\"` has been\n * emitted. Body reading continues asynchronously in the background via the\n * internal `#readStream` method.\n *\n * @throws When the fetch retry policy exhausts attempts or the connection\n * is superseded before the reader is handed off (in the latter case the\n * promise resolves without throwing).\n */\n public async connect(): Promise<void> {\n // If there is already a controller present, we are already connected.\n if (this.#connectionController) return;\n\n // Prepare for a fresh transport. Parser state from an abandoned connection\n // must not bleed into the next one; reopen messages if a prior terminal\n // close ended the consumer's iteration loop.\n this.#resetEventParser();\n this.#ensureMessageStreamOpen();\n\n const connectionController = new AbortController();\n this.#connectionController = connectionController;\n\n const { method, headers, body } = this.options;\n\n // Create the fetch options.\n const fetchOptions: RequestInit = {\n method,\n headers: headers || {},\n signal: connectionController.signal,\n cache: 'no-store',\n };\n\n // If the method is POST, we will set the body of the fetch options.\n // NOTE: RequestInit doesn't allow body to be `undefined`, so if its false-y we will set it to null.\n if (method === 'POST') {\n fetchOptions.body = body || null;\n }\n\n // Create a reader for the response body.\n let reader: ReadableStreamDefaultReader<Uint8Array>;\n\n try {\n // Retry the fetch using the provided retry policy. (default is exponential backoff)\n reader = await this.options.retry.run(() => this.#createReader(fetchOptions), {\n signal: connectionController.signal,\n });\n } catch (error) {\n // A newer `connect()` superseded this attempt — leave state to the winner.\n if (this.#connectionController !== connectionController) return;\n\n // Reset the controller to null to allow for reconnection if needed.\n this.#connectionController = null;\n\n // Normalize the error so it can be passed to the event listeners.\n const normalizedError = normalizeError(error);\n\n // Emit the disconnected and error events.\n this.emit('disconnected', { reason: 'error', error: normalizedError });\n this.emit('error', normalizedError);\n\n // Close the message stream so `for await...of` consumers resolve.\n this.#closeMessageStream();\n\n // Throw the error so the caller can handle it.\n throw error;\n }\n\n // Connection succeeded but was already replaced (for example disconnect during fetch).\n if (this.#connectionController !== connectionController) {\n await reader.cancel();\n\n return;\n }\n\n this.emit('connected', undefined);\n\n // Fire-and-forget: connect() resolves while the stream is consumed.\n // Data is emitted as a `message` event and from the `messages` iterator.\n this.#readStream(reader, connectionController).catch((error) => {\n this.emit('error', error);\n });\n }\n\n /**\n * Disconnects only the currently active transport.\n *\n * `beforeDisconnect` is emitted on every invocation, even when no\n * transport is currently active. This allows observers to react to\n * an explicit disconnect operation.\n *\n * @param context - Context describing the operation initiator.\n * @emits `beforeDisconnect` with the supplied operation context.\n * @emits `disconnected` with reason `\"disconnect\"` when an active\n * transport is actually disconnected.\n */\n public disconnect(context: SSESessionOperationContext = {}): void {\n this.emit('beforeDisconnect', context);\n\n if (this.#connectionController) {\n // Grab the current controller to ensure we are aborting the correct one.\n const connectionController = this.#connectionController;\n this.#connectionController = null;\n\n // Invalidate any in-flight read loop and fetch for this transport.\n connectionController.abort();\n\n // Emit the disconnected event.\n this.emit('disconnected', {\n reason: 'disconnect',\n source: context.source,\n });\n }\n\n // Reset the event parser buffer so data is not carried through resulting in malformed events.\n this.#resetEventParser();\n }\n\n /**\n * Terminates the session and disables attached visibility handling until\n * the same instance is manually {@link connect connected} again.\n *\n * Closes {@link messages} and emits `\"closed\"`.\n */\n public close(): void {\n // Disconnect the session.\n this.disconnect();\n\n // Close the message stream so `for await...of` consumers resolve.\n this.#closeMessageStream();\n\n // Emit the closed event.\n this.emit('closed', undefined);\n }\n\n /**\n * Performs the HTTP request and returns a reader for the response body.\n *\n * {@link SSESessionOptions.onRequest} may mutate headers (for example auth\n * tokens or `Last-Event-ID`) before the fetch runs.\n */\n async #createReader(fetchOptions: RequestInit): Promise<ReadableStreamDefaultReader<Uint8Array>> {\n const requestOptions = await this.options.onRequest(fetchOptions);\n const response = await this.options.fetch(this.#url, requestOptions);\n\n // Handle a bad response from the server\n if (!response.ok) {\n // Get the response code and text.\n const responseCode = response.status;\n const responseText = await response.text();\n\n // Create a new error and emit it.\n const error = new HTTPError(responseCode, responseText);\n this.emit('error', error);\n\n // Throw the error so the caller can handle it.\n throw error;\n }\n\n // Handle a response with no body (SSE still uses the response body)\n if (!response.body) {\n const error = new ResponseBodyNullError();\n this.emit('error', error);\n throw error;\n }\n\n // Return the reader for the response body.\n return response.body.getReader();\n }\n\n /**\n * Reads bytes from an established stream until it ends, errors, or is\n * superseded by a newer connection.\n */\n async #readStream(reader: ReadableStreamDefaultReader<Uint8Array>, connectionController: AbortController): Promise<void> {\n try {\n while (this.#connectionController === connectionController) {\n const { done, value } = await reader.read();\n\n // `disconnect()` or a newer connect() may have landed while we were awaiting.\n if (this.#connectionController !== connectionController) return;\n\n // If the stream is done, we've been disconnected.\n // We need to clean up and either complete or reconnect the session.\n if (done) {\n // Reset the controller to null to allow for reconnection if needed.\n this.#connectionController = null;\n\n // Emit the disconnected event.\n this.emit('disconnected', { reason: 'remote' });\n\n // If the session is persistent, we will attempt to reconnect.\n // NOTE: in very rare cases, a malfunctioning server can make this code turn into an infinite loop.\n if (this.options.persistent) {\n // Server closed gracefully — reopen unless the consumer opted out.\n await this.connect();\n } else {\n // Close the message stream so `for await...of` consumers resolve.\n this.#closeMessageStream();\n }\n\n return;\n }\n\n // Some environments yield `{ done: false, value: undefined }`.\n if (!value) continue;\n\n // Emit the parsed events to the event listeners and the messages iterator.\n for (const event of this.options.eventParser.parseEvents(value)) {\n // If the event has a retry interval, we will store it.\n if (event.retry) {\n this.#retryInterval = event.retry;\n }\n\n this.emit('message', event);\n this.messages.push(event);\n }\n }\n } catch (error) {\n // If the controller is different, we already started a new connection and it would be confusing to handle this error.\n // The controller can also be null here if the session was disconnected.\n if (connectionController !== this.#connectionController) return;\n\n // Invalidate the current controller to allow for reconnection if needed\n this.#connectionController = null;\n\n const normalizedError = normalizeError(error);\n this.emit('disconnected', { reason: 'error', error: normalizedError });\n\n // Expected path for `disconnect()` — do not treat as an error or reconnect.\n if (connectionController.signal.aborted) return;\n\n this.emit('error', normalizedError);\n\n // If the session is configured to attempt reconnect, we will attempt to reconnect.\n if (this.options.attemptReconnect) {\n // If the server has requested a retry interval, we will wait for it before attempting to reconnect.\n if (this.#retryInterval) {\n await new Promise((resolve) => setTimeout(resolve, this.#retryInterval!));\n }\n\n // Attempt to reconnect.\n await this.connect();\n } else {\n // Close the message stream so `for await...of` consumers resolve.\n this.#closeMessageStream();\n }\n }\n }\n\n /** Clears partial SSE frames left over from an abandoned transport. */\n #resetEventParser(): void {\n this.options.eventParser.reset();\n }\n\n /**\n * Creates a new {@link messages} iterator when the previous one was closed\n * by a terminal disconnect or server stream end.\n */\n #ensureMessageStreamOpen(): void {\n if (!this.messages.closed) return;\n\n this.messages = new AsyncPushIterator<SSEvent>();\n }\n\n /** Ends the message iteration loop for the current connection span. */\n #closeMessageStream(): void {\n if (this.messages.closed) return;\n\n this.messages.close();\n }\n}\n","/* eslint-disable max-classes-per-file */\n\nimport type { $ZodIssue } from 'zod/v4/core';\n\n/**\n * Formats the Zod validation failures into a single string with one line each: \"- <field>: <message>\" and top level failures\n * with no field path show as \"(root)\" for better readability.\n *\n * @param issues The Zod validation failures to format.\n * @returns A human readable error string for better debugging.\n */\nexport const buildErrorDescription = (issues: $ZodIssue[]): string => {\n // Initialize an empty array to store the formatted lines.\n const lines: string[] = [];\n\n // Iterate over the issues and format them into a string.\n for (const issue of issues) {\n // Get the issue path.\n const issuePath = issue.path.length > 0 ? issue.path.join('.') : '(root)';\n\n // The prefix that Zod adds to messages.\n const messagePrefix = 'Invalid input: ';\n\n // Remove the prefix for better readability.\n const issueMessage = issue.message.startsWith(messagePrefix) ? issue.message.slice(messagePrefix.length) : issue.message;\n\n // Add the formatted line to the array.\n lines.push(`- ${issuePath}: ${issueMessage}`);\n }\n\n // Return the formatted string.\n return `\\n${lines.join('\\n')}`;\n};\n\n/**\n * Thrown when the provided template does not satisfy the XOTemplate schema.\n */\nexport class TemplateInvalidError extends Error {\n constructor(details: string) {\n const message = `Template invalid: ${details}`;\n super(message);\n this.name = 'TemplateInvalidError';\n }\n}\n\n/**\n * Thrown when a string passed to `deserializeTemplate` cannot be parsed as JSON.\n */\nexport class TemplateJsonMalformedError extends Error {\n constructor(reason: string) {\n super(`Template JSON malformed, expected a valid JSON string: ${reason}`);\n this.name = 'TemplateJsonMalformedError';\n }\n}\n\n/**\n * Thrown when `serializeTemplate` fails to produce a JSON string from the template.\n */\nexport class TemplateSerializationFailedError extends Error {\n constructor(reason: string) {\n super(`Template serialization failed: ${reason}`);\n this.name = 'TemplateSerializationFailedError';\n }\n}\n","import type { XOTemplate } from '@xo-cash/types';\nimport { extendedJsonReplacer, extendedJsonReviver } from '../extended-json.ts';\nimport { TemplateJsonMalformedError, TemplateSerializationFailedError } from './errors.ts';\n\n/**\n * Serializes an XOTemplate to a JSON string. Encodes `bigint` and `Uint8Array` fields in\n * Extended JSON format so they can be reconstructed by `deserializeTemplate`.\n *\n * @param template The template to serialize.\n * @returns A JSON string representation of the template.\n * @throws {TemplateSerializationFailedError} If the template cannot be serialized to JSON.\n */\nexport const serializeTemplate = (template: XOTemplate): string => {\n try {\n // Serialize the template to a JSON string.\n return JSON.stringify(template, extendedJsonReplacer);\n } catch (serializationError) {\n const reason = serializationError instanceof Error ? serializationError.message : 'unknown error while serializing template';\n\n throw new TemplateSerializationFailedError(reason);\n }\n};\n\n/**\n * Deserializes a JSON string back into an XOTemplate object. Restores `bigint` and\n * `Uint8Array` fields encoded in Extended JSON format by `serializeTemplate`.\n *\n * @param serializedTemplate - A JSON string of an XOTemplate object.\n * @returns The reconstructed XOTemplate object.\n * @throws {TemplateJsonMalformedError} If the serialized template is not valid JSON.\n */\nexport const deserializeTemplate = (serializedTemplate: string): XOTemplate => {\n try {\n // Parse the serialized template using the extended JSON reviver.\n return JSON.parse(serializedTemplate, extendedJsonReviver);\n } catch (parsingError) {\n const reason = parsingError instanceof Error ? parsingError.message : 'unknown error while deserializing template';\n\n throw new TemplateJsonMalformedError(reason);\n }\n};\n","import { binToHex, sha256, utf8ToBin } from '@bitauth/libauth';\nimport type { XOTemplate } from '@xo-cash/types';\nimport { serializeTemplate } from './serialization.ts';\n\n/**\n * Generates a deterministic template identifier by hashing the template.\n *\n * Note: This expects a template that has been validated by `parseTemplate`.\n *\n * @param template - The template to generate an identifier for.\n * @returns The sha256 hex identifier for the template.\n */\nexport const generateTemplateIdentifier = (template: XOTemplate): string => {\n // Serialize the template.\n const serializedTemplate = serializeTemplate(template);\n\n // Hash the serialized template.\n const hash = sha256.hash(utf8ToBin(serializedTemplate));\n\n // Convert the hash to hex and return it.\n return binToHex(hash);\n};\n","/* eslint-disable @stylistic/newline-per-chained-call */\nimport { BchVmVersions, XOTemplatePrimitiveTypes, XOTemplateLockingTypes, XOTemplateNftCapabilities } from '@xo-cash/types';\nimport { z } from 'zod';\n\n// ============================================================\n// Enums\n// ============================================================\n\n/**\n * Validation schema for a BCH VM version identifier. Defines the set of known BCH VM versions\n * that XO templates declare support for.\n *\n * Uses `BchVmVersions` from `@xo-cash/types` so template validation stays aligned with the\n * `BchVmVersion` type.\n *\n * ```\n * {\n * \"supported\": [ \"BCH_2025_05\" ] ← each value\n * }\n * ```\n */\nexport const bchVmVersionSchema = z.enum(BchVmVersions);\n\n/**\n * Validation schema for the capability of a non-fungible token. Defines the three capability\n * types supported on BCH: minting tokens can create new NFTs, mutable tokens can update their\n * commitment, and none tokens cannot be changed after creation.\n *\n * ```\n * {\n * \"inputs|outputs\": {\n * \"[id]\": {\n * \"token\": {\n * \"nft\": {\n * \"capability\": \"minting\" ← this schema\n * }\n * }\n * }\n * }\n * }\n * ```\n */\nexport const xoTemplateNftCapabilitySchema = z.enum(XOTemplateNftCapabilities);\n\n/**\n * Validation schema for a BCH locking script type. Defines the standard locking script types\n * supported on BCH.\n *\n * ```\n * {\n * \"lockingScripts\": {\n * \"[id]\": {\n * \"lockingType\": \"p2pkh\" ← this schema\n * }\n * }\n * }\n * ```\n */\nexport const xoTemplateLockingTypeSchema = z.enum(XOTemplateLockingTypes);\n\n/**\n * Validation schema for a primitive type identifier.\n * Accepts values from XOTemplatePrimitiveTypes for the `hint` field on constants, variables, and data.\n */\nexport const xoTemplatePrimitiveTypeSchema = z.enum(XOTemplatePrimitiveTypes);\n\n// ============================================================\n// Primitives\n// ============================================================\n\n/**\n * Validation schema for byte array fields i.e. Uint8Array instance.\n */\nexport const uint8ArraySchema = z.instanceof(Uint8Array).describe('A sequence of unsigned 8-bit integers expressed as a Uint8Array.');\n\n/**\n * Validation schema for the Satoshis type i.e. bigint.\n */\nexport const satoshisSchema = z.bigint().describe('A satoshi amount expressed as a bigint.');\n\n// ============================================================\n// Shared\n// ============================================================\n\n/** Maximum character length for name fields on view properties. */\nexport const VIEW_PROPERTIES_NAME_MAX_LENGTH = 1000;\n\n/** Maximum character length for description fields on view properties. */\nexport const VIEW_PROPERTIES_DESCRIPTION_MAX_LENGTH = 5000;\n\n/** Maximum character length for icon fields on view properties. */\nexport const VIEW_PROPERTIES_ICON_MAX_LENGTH = 1000;\n\n/**\n * Validation schema for view properties shared across many template elements i.e. name, description, icon.\n * Extended by most other schemas in this file.\n */\nexport const xoTemplateViewPropertiesSchema = z\n .object({\n name: z.string().max(VIEW_PROPERTIES_NAME_MAX_LENGTH).describe('A short human-readable label for this element.'),\n description: z\n .string()\n .max(VIEW_PROPERTIES_DESCRIPTION_MAX_LENGTH)\n .describe('A human-readable explanation of what this element does and when it is relevant.'),\n icon: z.string().max(VIEW_PROPERTIES_ICON_MAX_LENGTH).optional().describe('An optional icon identifier or URL for this element.'),\n })\n .strict();\n\n// ============================================================\n// Intents\n// ============================================================\n\n/**\n * Validation schema for the base intent structure. Describes the common data parameters shared\n * by all intent types regardless of what they target.\n *\n * An optional templateIdentifier allows the intent to reference a target defined in a different\n * template, enabling cross-template interaction.\n *\n * Extended by: xoTemplateActionIntentSchema, xoTemplateOutputIntentSchema,\n * xoTemplateLockingScriptIntentSchema.\n */\nexport const xoTemplateIntentSchema = z\n .object({\n templateIdentifier: z\n .string()\n .optional()\n .describe('Optional identifier for the template used in this intent. If not provided, uses the current template.'),\n role: z.string().optional().describe('Optional identifier for the role used in this intent.'),\n generate: z.array(z.string()).optional().describe('Identifiers for items to generate when this intent is resolved, e.g. keys or secrets.'),\n variables: z.array(z.record(z.string(), z.unknown())).optional().describe('Variable values to apply when this intent is resolved.'),\n constants: z.array(z.record(z.string(), z.unknown())).optional().describe('Constant values to apply when this intent is resolved.'),\n secrets: z.array(z.record(z.string(), z.unknown())).optional().describe('Secret values to apply when this intent is resolved.'),\n })\n .strict();\n\n/**\n * Validation schema for an action intent. Extends the base intent structure with an action\n * identifier. Used in locking script action lists and in the template's start array.\n *\n * ```\n * {\n * \"start\": [\n * { \"action\": \"...\" } ← this schema\n * ],\n * \"lockingScripts\": {\n * \"[id]\": {\n * \"actions\": [\n * { \"action\": \"...\" } ← this schema\n * ],\n * \"roles\": {\n * \"[roleId]\": {\n * \"actions\": [\n * { \"action\": \"...\" } ← this schema\n * ]\n * }\n * }\n * }\n * }\n * }\n * ```\n */\nexport const xoTemplateActionIntentSchema = xoTemplateIntentSchema\n .extend({\n action: z.string().describe('The identifier for the intended action.'),\n })\n .strict();\n\n/**\n * Validation schema for an output intent. Extends the base intent structure with an output\n * identifier. Used in the template's defaults block.\n *\n * ```\n * {\n * \"defaults\": {\n * \"change\": { \"output\": \"...\" } ← this schema\n * }\n * }\n * ```\n */\nexport const xoTemplateOutputIntentSchema = xoTemplateIntentSchema\n .extend({\n output: z.string().describe('The identifier for the intended output.'),\n })\n .strict();\n\n/**\n * Validation schema for a locking script intent. Extends the base intent structure with\n * a locking script identifier.\n *\n * @todo The location of this schema in the template JSON is not yet determined.\n */\nexport const xoTemplateLockingScriptIntentSchema = xoTemplateIntentSchema\n .extend({\n lockingScript: z.string().describe('The identifier for the intended locking script.'),\n })\n .strict();\n\n// ============================================================\n// Actions\n// ============================================================\n\n/**\n * Validation schema for the slot count configuration on a role requirement. Declares how many\n * participants of a given role are needed. min sets the lower bound and max sets the upper bound.\n * When max is absent, there is no upper limit.\n *\n * ```\n * {\n * \"actions\": {\n * \"[id]\": {\n * \"requirements\": {\n * \"participants\": [\n * { \"slots\": { \"min\": 1, \"max\": 1 } } ← this schema\n * ]\n * }\n * }\n * }\n * }\n * ```\n */\nexport const xoTemplateRoleSlotsRequirementsSchema = z\n .object({\n min: z.number().describe('Minimum number of participants required for this role.'),\n max: z.number().optional().describe('Maximum number of participants allowed for this role. Undefined means unlimited.'),\n })\n .strict();\n\n/**\n * Validation schema for the capability requirements declared on a role within an action.\n * Describes what data, secrets, or state the role is responsible for providing when participating in an action.\n *\n * ```\n * {\n * \"actions\": {\n * \"[id]\": {\n * \"roles\": {\n * \"[roleId]\": {\n * \"requirements\": { \"variables\": [], \"secrets\": [] } ← this schema\n * }\n * }\n * }\n * }\n * }\n * ```\n */\nexport const xoTemplateActionRoleRequirementsSchema = z\n .object({\n variables: z.array(z.string()).optional().describe('List of variable identifiers required for this role.'),\n secrets: z.array(z.string()).optional().describe('List of secret identifiers required for this role.'),\n })\n .strict();\n\n/**\n * Validation schema for a role-specific definition within an action.\n * All view properties are optional.\n *\n * ```\n * {\n * \"actions\": {\n * \"[id]\": {\n * \"roles\": {\n * \"[roleId]\": { } ← this schema\n * }\n * }\n * }\n * }\n * ```\n */\nexport const xoTemplateActionRoleSchema = xoTemplateViewPropertiesSchema\n .partial()\n .extend({\n generate: z\n .array(z.string())\n .optional()\n .describe('Identifiers for data items that should be generated for this role when participating in the action.'),\n\n // Describes under what conditions this role can proceed with the action. All values listed\n // under requirements must be populated for the action to work. This is a developer and\n // author concern. It is not present on intents because intents are used to populate the\n // action rather than to define it, and their fields are flattened accordingly.\n requirements: xoTemplateActionRoleRequirementsSchema.optional().describe('The requirements for this role within this action.'),\n })\n .strict();\n\n/**\n * Validation schema for a role participation requirement in an action's requirements block.\n *\n * ```\n * {\n * \"actions\": {\n * \"[id]\": {\n * \"requirements\": {\n * \"participants\": [\n * { \"role\": \"...\", \"slots\": { } } ← this schema\n * ]\n * }\n * }\n * }\n * }\n * ```\n */\nexport const xoTemplateRoleSlotSchema = z\n .object({\n role: z.string().describe('The role identifier that this requirement applies to.'),\n slots: xoTemplateRoleSlotsRequirementsSchema.describe('Slot configuration specifying how many participants of this role are required.'),\n })\n .strict();\n\n/**\n * Validation schema for the requirements of an action.\n *\n * ```\n * {\n * \"actions\": {\n * \"[id]\": {\n * \"requirements\": { \"variables\": [], \"participants\": [], \"secrets\": [] } ← this schema\n * }\n * }\n * }\n * ```\n */\nexport const xoTemplateActionRequirementsSchema = z\n .object({\n variables: z.array(z.string()).optional().describe('List of variable identifiers required for this action.'),\n participants: z.array(xoTemplateRoleSlotSchema).optional().describe('The participants required for this action.'),\n secrets: z.array(z.string()).optional().describe('The secrets required for this action.'),\n })\n .strict();\n\n/**\n * Validation schema for an action definition.\n *\n * ```\n * {\n * \"actions\": {\n * \"[id]\": { } ← this schema\n * }\n * }\n * ```\n */\nexport const xoTemplateActionSchema = xoTemplateViewPropertiesSchema\n .extend({\n roles: z.record(z.string(), xoTemplateActionRoleSchema).optional().describe('Specific context for each role participating in this action.'),\n requirements: xoTemplateActionRequirementsSchema.optional().describe('The requirements for this action.'),\n\n // This is a list of conditions that can influence how the action behaves.\n // This needs more work to be done.\n conditions: z.array(z.string()).optional().describe('Conditions that must be met for this action to be available.'),\n\n // A single transaction produced by the action.\n // In future this might be moved to a results block that can have multiple transactions.\n transaction: z\n .string()\n .optional()\n .describe(\"The identifier of the transaction this action produces, referencing an entry in the template's transactions.\"),\n\n // The data that is produced by the action.\n // In future this might be moved to a results block that can have multiple data fields.\n data: z.string().optional().describe(\"The identifier of the data field this action produces, referencing an entry in the template's data.\"),\n })\n .strict();\n\n// ============================================================\n// Tokens & Amounts\n// ============================================================\n\n/**\n * Validation schema for the non-fungible token configuration within a token field.\n *\n * ```\n * {\n * \"inputs|outputs\": {\n * \"[id]\": {\n * \"token\": {\n * \"nft\": { } ← this schema\n * }\n * }\n * }\n * }\n * ```\n */\nexport const xoTemplateNonFungibleTokenDetailsSchema = z\n .object({\n capability: z\n .union([ xoTemplateNftCapabilitySchema, z.string() ])\n .optional()\n .describe('The capability of the NFT. May be a known capability value or a CashASM expression resolving to a capability.'),\n commitment: z.string().optional().describe('The commitment data for the NFT, as a string or CashASM expression resolving to a commitment.'),\n })\n .strict();\n\n/**\n * Validation schema for the token configuration on inputs and outputs.\n *\n * ```\n * {\n * \"inputs|outputs\": {\n * \"[id]\": {\n * \"token\": { } ← this schema\n * }\n * }\n * }\n * ```\n */\nexport const xoTemplateTokenSchema = z\n .object({\n category: z.string().optional().describe('The category of the token, as a string or CashASM expression resolving to a category.'),\n amount: z\n .union([ z.bigint(), z.string(), z.null() ])\n .optional()\n .describe('The amount of fungible tokens as a bigint, a CashASM expression resolving to a bigint, or null indicating no FT is present.'),\n nft: xoTemplateNonFungibleTokenDetailsSchema\n .nullable()\n .optional()\n .describe('Non-fungible token configuration. Null indicates no NFT is present.'),\n })\n .strict();\n\n/**\n * Validation schema for the asset amounts configuration. Used by omitChangeAmounts on inputs\n * and by balance on locking scripts, outputs, and their roles.\n */\nexport const xoTemplateAssetAmountsSchema = z\n .object({\n\n /**\n * The satoshi amount.\n * - `Satoshis`: A specific bigint amount.\n * - `string`: A CashASM expression that resolves to the amount.\n * - `true`: all, i.e. the entire amount\n */\n satoshis: z\n .union([ satoshisSchema, z.string(), z.literal(true) ])\n .optional()\n .describe('The satoshi amount. Accepts a bigint for a specific value, a CashASM expression, or true for the entire amount.'),\n\n /**\n * The fungible token amount.\n * - `FungibleTokenAmount`: A specific bigint amount.\n * - `string`: A CashASM expression that resolves to the amount.\n * - `true`: all, i.e. the entire amount\n */\n fungibleTokens: z\n .union([ z.bigint(), z.string(), z.literal(true) ])\n .optional()\n .describe('The fungible token amount. Accepts a bigint for a specific value, a CashASM expression, or true for the entire amount.'),\n\n /**\n * Whether a non-fungible token is present (0 for absent, 1 for present),\n * or a CashASM expression that evaluates to 0 or 1.\n * - `true`: resolves to 1 if an NFT is present, or 0 if none is present. Use this when\n * the NFT is optional, to express that the NFT is estimated to be part of the balance\n * if present, or absent from it if not.\n * - `0`: None, i.e. nothing is expected to be included\n * - `1`: present and complete, as value > 1 does not make sense for non-fungible tokens\n * - `string`: A CashASM expression that evaluates to 0 or 1.\n */\n nonfungibleTokens: z\n .union([ z.literal(0), z.literal(1), z.string(), z.literal(true) ])\n .optional()\n .describe('Whether an NFT is present: 0 for absent, 1 for present, a CashASM expression evaluating to 0 or 1, or true to estimate the NFT as part of the balance if present, or absent from it if not.'),\n })\n .strict();\n\n// ============================================================\n// Locking Scripts\n// ============================================================\n\n/**\n * Validation schema for the state configuration shared by a locking script and its individual roles.\n * Declares which variables and secrets are tracked in the on-chain state for a given participant.\n *\n * ```\n * {\n * \"lockingScripts\": {\n * \"[id]\": {\n * \"state\": { \"variables\": [], \"secrets\": [] } ← this schema\n * \"roles\": {\n * \"[roleId]\": {\n * \"state\": { \"variables\": [], \"secrets\": [] } ← this schema\n * }\n * }\n * }\n * }\n * }\n * ```\n */\nexport const xoTemplateStateSchema = z\n .object({\n variables: z.array(z.string()).optional().describe('List of variable identifiers to track in state.'),\n secrets: z.array(z.string()).optional().describe('List of secret identifiers to track in state.'),\n })\n .strict();\n\n/**\n * Validation schema for a role definition for a locking script.\n *\n * ```\n * {\n * \"lockingScripts\": {\n * \"[id]\": {\n * \"roles\": {\n * \"[roleId]\": { } ← this schema\n * }\n * }\n * }\n * }\n * ```\n */\nexport const xoTemplateLockingScriptRoleSchema = xoTemplateViewPropertiesSchema\n .partial()\n .extend({\n state: xoTemplateStateSchema.optional().describe('List of items to track as state for this role.'),\n actions: z.array(xoTemplateActionIntentSchema).optional().describe('List of action references available to this role.'),\n balance: xoTemplateAssetAmountsSchema.partial().optional().describe('Estimated ownership in the optional set of asset amounts specified.'),\n selectable: z.boolean().optional().describe('Whether outputs locked to this script should be available for coin selection.'),\n relevant: z\n .union([ z.boolean(), z.string() ])\n .optional()\n .describe('Whether this output or locking script should be tracked by the engine, When omitted, the engine treats this field as true.'\n + 'Accepts true, false, or a CashASM expression that evaluates to a boolean relevance value.'),\n privacy: z\n .union([ z.number(), z.string() ])\n .optional()\n .describe('Privacy level for outputs locked to this script. A numeric level or a CashASM expression that evaluates to a privacy level.'),\n })\n .strict();\n\n/**\n * Validation schema for a locking script definition.\n *\n * ```\n * {\n * \"lockingScripts\": {\n * \"[id]\": { } ← this schema\n * }\n * }\n * ```\n */\nexport const xoTemplateLockingScriptSchema = xoTemplateViewPropertiesSchema\n .extend({\n lockingType: xoTemplateLockingTypeSchema.optional().describe('The type of locking mechanism. Defaults to p2s if not specified.'),\n lockingBytecode: z.string().describe('The locking script bytecode.'),\n unlockingBytecode: z.string().optional().describe('Optional default unlocking bytecode when used in automatic coin selection.'),\n actions: z.array(xoTemplateActionIntentSchema).optional().describe('The actions available for this locking script.'),\n state: xoTemplateStateSchema.optional().describe('List of items to track as state for all participants.'),\n balance: xoTemplateAssetAmountsSchema.partial().optional().describe('Estimated ownership in the optional set of asset amounts specified.'),\n selectable: z.boolean().optional().describe('Whether outputs locked to this script should be available for coin selection.'),\n // Might be levels or tags\n privacy: z\n .union([ z.number(), z.string() ])\n .optional()\n .describe('Privacy level for outputs locked to this script. A numeric level or a CashASM expression that evaluates to a privacy level.'),\n roles: z\n .record(z.string(), xoTemplateLockingScriptRoleSchema)\n .optional()\n .describe('Specific context for each role participating in this locking script.'),\n })\n .strict();\n\n// ============================================================\n// Inputs\n// ============================================================\n\n/**\n * Validation schema for an input definition in the template. Extends view properties with optional\n * satoshi value, token configuration, and other transaction level fields.\n *\n * ```\n * {\n * \"inputs\": {\n * \"[id]\": { } ← this schema\n * }\n * }\n * ```\n */\nexport const xoTemplateInputSchema = xoTemplateViewPropertiesSchema\n .extend({\n valueSatoshis: z\n .union([ satoshisSchema, z.string() ])\n .optional()\n .describe('The amount of satoshis for this input as a bigint or a CashASM expression resolving to the amount.'),\n token: xoTemplateTokenSchema.nullable().optional().describe('Token configuration for this input.'),\n sequenceNumber: z\n .union([ z.number(), z.string() ])\n .optional()\n .describe('The sequence number of this input as a specific number or a CashASM expression.'),\n unlockingScript: z.string().optional().describe('Identifier of the unlocking script to use for the UTXO provided for this input.'),\n omitChangeAmounts: xoTemplateAssetAmountsSchema\n .optional()\n .describe('Amount of change that should be omitted from the automatic change handling. WARNING: Setting this can result in loss of funds!'),\n })\n .strict();\n\n// ============================================================\n// Outputs\n// ============================================================\n\n/**\n * Validation schema for an output definition. Extends the locking script schema so that\n * every output inherits the same locking script fields and adds output-specific fields.\n *\n * ```\n * {\n * \"outputs\": {\n * \"[id]\": { } ← this schema\n * }\n * }\n * ```\n */\nexport const xoTemplateOutputSchema = xoTemplateLockingScriptSchema\n .omit({ lockingType: true, lockingBytecode: true, unlockingBytecode: true })\n .extend({\n lockingScript: z.string().describe('Identifier of the locking script to use for this output.'),\n valueSatoshis: z\n .union([ satoshisSchema, z.string() ])\n .optional()\n .describe('The amount of satoshis for this output as a bigint or a CashASM expression resolving to the amount.'),\n token: xoTemplateTokenSchema.nullable().optional().describe('Token configuration for this output.'),\n })\n .strict();\n\n// ============================================================\n// Transactions\n// ============================================================\n\n/**\n * Validation schema for a transaction input reference for a transaction definition.\n *\n * ```\n * {\n * \"transactions\": {\n * \"[id]\": {\n * \"inputs\": [\n * { \"input\": \"...\" } ← this schema\n * ]\n * }\n * }\n * }\n * ```\n */\nexport const xoTemplateTransactionInputSchema = z\n .object({\n input: z.string().describe('The input definition identifier.'),\n inputIndex: z.number().optional().describe('Optional index of this input in the transaction.'),\n })\n .strict();\n\n/**\n * Validation schema for a transaction output reference for a transaction definition.\n *\n * ```\n * {\n * \"transactions\": {\n * \"[id]\": {\n * \"outputs\": [\n * { \"output\": \"...\" } ← this schema\n * ]\n * }\n * }\n * }\n * ```\n */\nexport const xoTemplateTransactionOutputSchema = z\n .object({\n output: z.string().describe('The output definition identifier.'),\n outputIndex: z.number().optional().describe('Optional index of this output in the transaction.'),\n })\n .strict();\n\n/**\n * Validation schema for role-specific data for a transaction definition.\n *\n * ```\n * {\n * \"transactions\": {\n * \"[id]\": {\n * \"roles\": {\n * \"[roleId]\": { } ← this schema\n * }\n * }\n * }\n * }\n * ```\n */\nexport const xoTemplateTransactionRoleDataSchema = xoTemplateViewPropertiesSchema\n .partial()\n .extend({\n inputs: z.array(xoTemplateTransactionInputSchema).optional().describe('The inputs required for this role.'),\n outputs: z.array(xoTemplateTransactionOutputSchema).optional().describe('The outputs required for this role.'),\n })\n .strict();\n\n/**\n * Validation schema for a transaction template definition.\n *\n * ```\n * {\n * \"transactions\": {\n * \"[id]\": { } ← this schema\n * }\n * }\n * ```\n */\nexport const xoTemplateTransactionSchema = xoTemplateViewPropertiesSchema\n .extend({\n version: z.number().optional().describe('The version of the transaction.'),\n locktime: z\n .union([ z.number(), z.string() ])\n .optional()\n .describe('The locktime for this transaction as a specific number or a CashASM expression.'),\n inputs: z.array(xoTemplateTransactionInputSchema).describe('The inputs for this transaction.'),\n outputs: z.array(xoTemplateTransactionOutputSchema).describe('The outputs for this transaction.'),\n roles: z\n .record(z.string(), xoTemplateTransactionRoleDataSchema)\n .optional()\n .describe('Specific context for each role participating in this transaction.'),\n composable: z.boolean().optional().describe('Whether this transaction can be composed with other transactions.'),\n })\n .strict();\n\n// ============================================================\n// Template Data\n// ============================================================\n\n/**\n * Validation schema for a constant value definition.\n *\n * ```\n * {\n * \"constants\": {\n * \"[id]\": { } ← this schema\n * }\n * }\n * ```\n */\nexport const xoTemplateConstantSchema = xoTemplateViewPropertiesSchema\n .extend({\n type: xoTemplatePrimitiveTypeSchema.describe('The data type of this constant.'),\n value: z.unknown().describe('The value of this constant.'),\n hint: z.unknown().optional().describe('An optional hint to help apps and users understand what this constant represents.'),\n })\n .strict();\n\n/**\n * Validation schema for a data field definition.\n *\n * ```\n * {\n * \"data\": {\n * \"[id]\": { } ← this schema\n * }\n * }\n * ```\n */\nexport const xoTemplateDataSchema = z\n .object({\n type: xoTemplatePrimitiveTypeSchema.describe('The data type of this data field.'),\n value: z.unknown().describe('The value for this data field.'),\n hint: z.unknown().optional().describe('An optional hint to help apps and users understand this data field.'),\n })\n .strict();\n\n/**\n * Validation schema for an import default value intent. Extends the base intent with optional\n * view properties that the engine evaluates at runtime to produce human-readable output.\n *\n * ```\n * {\n * \"variables\": {\n * \"[id]\": {\n * \"importDefaultValue\": { } ← this schema\n * }\n * }\n * }\n * ```\n */\nexport const xoTemplateImportDefaultValueSchema = xoTemplateIntentSchema\n // .shape unwraps the ZodObject to the raw field map { name, description, icon } with each field made optional\n .extend(xoTemplateViewPropertiesSchema.partial().shape)\n .strict();\n\n/**\n * Validation schema for a variable definition.\n *\n * ```\n * {\n * \"variables\": {\n * \"[id]\": { } ← this schema\n * }\n * }\n * ```\n */\nexport const xoTemplateVariableSchema = xoTemplateViewPropertiesSchema\n .extend({\n type: xoTemplatePrimitiveTypeSchema.optional().describe('The data type of this variable.'),\n hint: z.unknown().optional().describe('A hint to help users understand what value to provide.'),\n\n // A neutral intent that the engine uses to populate the default value for this variable.\n // View properties (name, description, icon) may contain CashASM expressions that the\n // engine evaluates at runtime to produce human-readable output. The engine overrides\n // whatever values are set here when resolving the variable for a participant.\n importDefaultValue: xoTemplateImportDefaultValueSchema\n .optional()\n .describe('A neutral intent that the engine uses to populate the default value for this variable.'),\n })\n .strict();\n\n// ============================================================\n// Template Resources\n// ============================================================\n\n/**\n * Validation schema for a resource reference attached to a template element. Extends view\n * properties with a URL pointing to external documentation or tooling.\n *\n * ```\n * {\n * \"resources\": [\n * { \"name\": \"...\", \"description\": \"...\", \"url\": \"...\" } ← this schema\n * ]\n * }\n * ```\n */\nexport const xoTemplateResourceSchema = xoTemplateViewPropertiesSchema\n .extend({\n url: z.string().describe('The URL for this resource.'),\n })\n .strict();\n\n/**\n * Validation schema for an icon reference.\n *\n * ```\n * {\n * \"icons\": [\n * { \"name\": \"...\", \"hash\": \"...\" } ← this schema\n * ]\n * }\n * ```\n */\nexport const xoTemplateIconSchema = xoTemplateViewPropertiesSchema\n .pick({ name: true })\n .extend({\n hash: z.string().describe('The identifier of the icon.'),\n })\n .strict();\n\n// ============================================================\n// Defaults\n// ============================================================\n\n/**\n * Validation schema for the defaults block of a template.\n *\n * ```\n * {\n * \"defaults\": { } ← this schema\n * }\n * ```\n */\nexport const xoTemplateDefaultsSchema = z\n .object({\n change: xoTemplateOutputIntentSchema.optional().describe('Instructions for how to construct automated change output.'),\n })\n .strict();\n\n// ============================================================\n// Template\n// ============================================================\n\n/**\n * Validation schema for the full XOTemplate type.\n */\nexport const xoTemplateSchema = xoTemplateViewPropertiesSchema\n .extend({\n $schema: z\n .string()\n .describe('The URI that identifies the JSON Schema used by this template. This enables documentation, autocompletion, and validation in JSON documents.'),\n version: z.string().optional().describe('A string identifying the version of this template.'),\n supported: z.array(bchVmVersionSchema).min(1).describe('The BCH VM versions that this template supports. At least one version is required.'),\n defaults: xoTemplateDefaultsSchema.optional().describe('Optional default settings used in this template.'),\n roles: z.record(z.string(), xoTemplateViewPropertiesSchema).describe('The roles defined in this template.'),\n start: z.array(xoTemplateActionIntentSchema).describe('A list of entry points defining which actions are available at the start.'),\n actions: z.record(z.string(), xoTemplateActionSchema).describe('The actions defined in this template.'),\n data: z.record(z.string(), xoTemplateDataSchema).optional().describe('The data fields defined in this template.'),\n transactions: z.record(z.string(), xoTemplateTransactionSchema).optional().describe('The transaction templates defined in this template.'),\n inputs: z.record(z.string(), xoTemplateInputSchema).describe('The inputs defined in this template.'),\n outputs: z.record(z.string(), xoTemplateOutputSchema).describe('The outputs defined in this template.'),\n lockingScripts: z.record(z.string(), xoTemplateLockingScriptSchema).describe('The locking script templates defined in this template.'),\n scripts: z\n .record(z.string(), z.string())\n .describe('Scripts used in this template. Keys are script identifiers, values are bytecode or CashASM expressions.'),\n constants: z.record(z.string(), xoTemplateConstantSchema).optional().describe('The constants defined in this template.'),\n variables: z\n .record(z.string(), xoTemplateVariableSchema)\n .optional()\n .describe(\"The variables that must be provided for use in the template's scripts.\"),\n resources: z.array(xoTemplateResourceSchema).optional().describe('Resource references providing external documentation or tooling links.'),\n icons: z.array(xoTemplateIconSchema).optional().describe('The icons available for use throughout the template.'),\n scenarios: z.unknown().optional().describe('The scenarios defined in this template.'),\n })\n .strict();\n","import type { XOTemplate } from '@xo-cash/types';\nimport { xoTemplateSchema } from './schemas.ts';\nimport { TemplateInvalidError, buildErrorDescription } from './errors.ts';\nimport { deserializeTemplate, serializeTemplate } from './serialization.ts';\n\n/**\n * Accepts a template value and returns a validated XOTemplate object. The input may be\n * either an Extended JSON string or a pre-parsed object. Both are validated\n * against the XOTemplate schema.\n *\n * @param inputTemplate - The value to validate. May be an Extended JSON string or a pre-parsed object.\n * @returns The validated template object\n * @throws {TemplateSerializationFailedError} If a pre-parsed object input cannot be serialized to JSON for normalization.\n * @throws {TemplateJsonMalformedError} If the string input is not valid JSON.\n * @throws {TemplateInvalidError} If the value does not conform to the XOTemplate schema.\n */\nexport const parseTemplate = (inputTemplate: string | XOTemplate): XOTemplate => {\n // Regardless of whether the inputTemplate is a string, an imported template or an in-memory object, serialize and then\n // deserialize it to ensure the output shape is consistent. For example, optional fields explicitly set to 'undefined' would be passed through\n // and then dropped on the string path, resulting in structurally different results for the same template.\n const serializedTemplate = typeof inputTemplate === 'string' ? inputTemplate : serializeTemplate(inputTemplate);\n const templateObject = deserializeTemplate(serializedTemplate);\n\n // Validate the template against the schema.\n const parseResult = xoTemplateSchema.safeParse(templateObject);\n\n if (parseResult.success) {\n // Return the validated template object\n return parseResult.data as XOTemplate;\n }\n\n // Build a human-readable description of every validation failure\n const errorDescription = buildErrorDescription(parseResult.error.issues);\n\n // Throw a typed error with the description\n throw new TemplateInvalidError(errorDescription);\n};\n","/* eslint-disable max-classes-per-file */\nimport type { IdentifierResolutionType } from '@bitauth/libauth';\n\n/**\n * Error thrown when a required variable is missing.\n */\nexport class CashAssemblyRequiredVariableMissingError extends Error {\n /**\n * Variable names that were required but absent from the variables map.\n */\n readonly variableNames: string[];\n\n constructor(variableNames: string[] = []) {\n const defaultMessage = 'Missing required variable';\n if (variableNames.length > 0) {\n super(`${defaultMessage}: variableNames [${variableNames.join(', ')}]`);\n } else {\n super(defaultMessage);\n }\n\n this.variableNames = variableNames;\n }\n}\n\n/**\n * Error thrown when cash assembly compilation fails.\n */\nexport class CashAssemblyCompilationFailedError extends Error {\n constructor(message?: string) {\n const defaultMessage = 'Cash assembly compilation failed';\n super(message ? `${defaultMessage}: ${message}` : defaultMessage);\n }\n}\n\n/**\n * Error thrown when a quoted string inside `$()` never closes.\n */\nexport class CashAssemblyQuotedLiteralUnclosedError extends Error {\n /**\n * Index of the opening quote that never found a closer.\n */\n readonly openingQuoteIndex: number;\n\n /**\n * Quote character that opened the literal.\n */\n readonly quoteCharacter: string;\n\n /**\n * Text from the opening quote through the end of the scanned string.\n */\n readonly unclosedText: string;\n\n constructor(openingQuoteIndex: number, quoteCharacter: string, cashAssemblyText: string) {\n const unclosedText = cashAssemblyText.slice(openingQuoteIndex);\n const defaultMessage = 'Quoted literal in a CashAssembly evaluation is unclosed';\n const details = [\n `quoteCharacter ${JSON.stringify(quoteCharacter)}`,\n `openingQuoteIndex ${String(openingQuoteIndex)}`,\n `unclosedText ${JSON.stringify(unclosedText)}`,\n ].join(', ');\n\n super(`${defaultMessage}: ${details}`);\n\n this.openingQuoteIndex = openingQuoteIndex;\n this.quoteCharacter = quoteCharacter;\n this.unclosedText = unclosedText;\n }\n}\n\n/**\n * Error thrown when a block comment inside `$()` never closes.\n */\nexport class CashAssemblyBlockCommentUnclosedError extends Error {\n /**\n * Index of the first slash of the block comment opener.\n */\n readonly commentStartIndex: number;\n\n /**\n * Text from the block comment opener through the end of the scanned string.\n */\n readonly unclosedText: string;\n\n constructor(commentStartIndex: number, cashAssemblyText: string) {\n const unclosedText = cashAssemblyText.slice(commentStartIndex);\n const defaultMessage = 'Block comment in a CashAssembly evaluation is unclosed';\n const details = [ `commentStartIndex ${String(commentStartIndex)}`, `unclosedText ${JSON.stringify(unclosedText)}` ].join(', ');\n\n super(`${defaultMessage}: ${details}`);\n\n this.commentStartIndex = commentStartIndex;\n this.unclosedText = unclosedText;\n }\n}\n\n/**\n * Error thrown when a `$()` evaluation never finds its matching closer.\n */\nexport class CashAssemblyEvaluationUnclosedError extends Error {\n /**\n * Index of the `$` that opened the evaluation.\n */\n readonly evaluationStartIndex: number;\n\n /**\n * How many `$()` remain open at the end of the string, including nested evaluations.\n */\n readonly remainingOpenEvaluations: number;\n\n /**\n * Text from the opening `$` through the end of the scanned string.\n */\n readonly unclosedText: string;\n\n constructor(evaluationStartIndex: number, remainingOpenEvaluations: number, cashAssemblyText: string) {\n const unclosedText = cashAssemblyText.slice(evaluationStartIndex);\n const defaultMessage = 'CashAssembly evaluation is unclosed';\n const details = [\n `evaluationStartIndex ${String(evaluationStartIndex)}`,\n `remainingOpenEvaluations ${String(remainingOpenEvaluations)}`,\n `unclosedText ${JSON.stringify(unclosedText)}`,\n ].join(', ');\n\n super(`${defaultMessage}: ${details}`);\n\n this.evaluationStartIndex = evaluationStartIndex;\n this.remainingOpenEvaluations = remainingOpenEvaluations;\n this.unclosedText = unclosedText;\n }\n}\n\n/**\n * Error thrown when a variable's runtime type does not match the type required for compilation.\n */\nexport class CashAssemblyVariableTypeMismatchError extends Error {\n constructor(variableKey: string, expectedType: string, actualType: string) {\n const defaultMessage = 'Variable type mismatch';\n super(`${defaultMessage}: variableKey \"${variableKey}\", expected ${expectedType}, got ${actualType}`);\n }\n}\n\n/**\n * Error thrown when a method resolvable primitive type does not expose the requested method.\n */\nexport class CashAssemblyPrimitiveMethodMissingError extends Error {\n constructor(identifier: string, methodName: string, type: string) {\n const defaultMessage = 'CashAssembly primitive method does not exist';\n super(`${defaultMessage}: identifier \"${identifier}\", methodName \"${methodName}\", type \"${type}\"`);\n }\n}\n\n/**\n * Error thrown when a value cannot be resolved as bytes.\n */\nexport class CashAssemblyUnsupportedValueTypeError extends Error {\n constructor(identifier: string, returnedType: string) {\n const defaultMessage = 'CashAssembly value type is unsupported for byte resolution';\n super(`${defaultMessage}: identifier \"${identifier}\", returnedType \"${returnedType}\"`);\n }\n}\n\n/**\n * Error thrown when a number cannot be safely encoded as a CashAssembly VM number.\n */\nexport class CashAssemblyNumberNotSafeIntegerError extends Error {\n constructor(identifier: string, value: number) {\n const defaultMessage = 'CashAssembly number is not a safe integer';\n super(`${defaultMessage}: identifier \"${identifier}\", got ${String(value)}`);\n }\n}\n\n/**\n * Error thrown when a method resolvable primitive is selected but its value is missing from the variables map.\n */\nexport class CashAssemblyPrimitiveVariableMissingError extends Error {\n constructor(identifier: string, variableName: string) {\n const defaultMessage = 'CashAssembly primitive variable is missing from the variables map';\n super(`${defaultMessage}: identifier \"${identifier}\", variableName \"${variableName}\"`);\n }\n}\n\n/**\n * Error thrown when one identifier would resolve as more than one {@link IdentifierResolutionType}.\n */\nexport class CashAssemblyIdentifierCollisionError extends Error {\n /**\n * Identifier that more than one resolution type would match.\n */\n readonly identifier: string;\n\n /**\n * The list of resolution types that the identifier matches.\n */\n readonly resolutionTypes: IdentifierResolutionType[];\n\n constructor(identifier: string, resolutionTypes: IdentifierResolutionType[]) {\n const defaultMessage = 'CashAssembly identifier exists for more than one resolution type';\n\n super(`${defaultMessage}: identifier \"${identifier}\", resolutionTypes [${resolutionTypes.join(', ')}]`);\n\n this.identifier = identifier;\n this.resolutionTypes = resolutionTypes;\n }\n}\n\n/**\n * Error thrown when compiled evaluation bytes cannot be decoded as a VM number.\n */\nexport class CashAssemblyVmNumberDecodeError extends Error {\n constructor(reason: string) {\n const defaultMessage = 'CashAssembly evaluation could not be decoded as a VM number';\n super(`${defaultMessage}: ${reason}`);\n }\n}\n","import { describeExpectedInput, parseScript } from '@bitauth/libauth';\nimport type { CashAssemblyScriptSegment } from '@bitauth/libauth';\nimport { CashAssemblyCompilationFailedError } from './errors.ts';\nimport type { CashAssemblyTemplateScripts } from './types.ts';\n\n/**\n * Shared state while scanning a parse tree and visiting nested template scripts.\n */\ntype CollectFromParseTreeContext = {\n\n /**\n * Script ids present in the template scripts map.\n */\n knownScriptIdentifiers: ReadonlySet<string>;\n\n /**\n * Script ids whose sources were already visited.\n */\n visitedScriptIdentifiers: ReadonlySet<string>;\n\n /**\n * Pending script ids queued to visit.\n */\n scriptIdentifiersToVisit: string[];\n\n /**\n * WalletData variable names.\n */\n variableNames: Set<string>;\n};\n\n/**\n * Parameters for scanning one parsed Script node.\n */\ntype CollectFromParsedScriptParameters = CollectFromParseTreeContext & {\n\n /**\n * Parsed Script whose children are Push, Evaluation, Identifier, or literals.\n */\n scriptSegment: CashAssemblyScriptSegment;\n\n /**\n * True when this Script is the value of a Push.\n * Direct Identifier children are WalletData unless they are template script ids.\n */\n isDirectPushContent: boolean;\n};\n\n/**\n * Parameters for handling one Identifier node.\n */\ntype CollectFromParsedIdentifierParameters = CollectFromParseTreeContext & {\n\n /**\n * Identifier text from parseScript, which may include `.` and `_`.\n */\n identifier: string;\n\n /**\n * True when this Identifier is a direct child of a Push Script.\n */\n isDirectPushContent: boolean;\n};\n\n/**\n * Enqueues a template script id so its source can be visited when it exists in the scripts map.\n *\n * @param {string} scriptIdentifier - Script id from an evaluation or nested script source.\n * @param {ReadonlySet<string>} knownScriptIdentifiers - Script ids present in the template scripts map.\n * @param {ReadonlySet<string>} visitedScriptIdentifiers - Script ids whose sources were already visited.\n * @param {string[]} scriptIdentifiersToVisit - Pending script ids queued to visit.\n */\nconst enqueueReachableTemplateScriptIdentifier = (\n scriptIdentifier: string,\n knownScriptIdentifiers: ReadonlySet<string>,\n visitedScriptIdentifiers: ReadonlySet<string>,\n scriptIdentifiersToVisit: string[],\n): void => {\n // Return when this id is not a template script.\n if (knownScriptIdentifiers.has(scriptIdentifier) === false) {\n return;\n }\n\n // Skip ids whose sources were already visited.\n if (visitedScriptIdentifiers.has(scriptIdentifier) === true) {\n return;\n }\n\n // Avoid duplicate queue entries when the same id is referenced more than once.\n if (scriptIdentifiersToVisit.includes(scriptIdentifier) === true) {\n return;\n }\n\n // Queue this id so its source is parsed after the current scan finishes.\n scriptIdentifiersToVisit.push(scriptIdentifier);\n};\n\n/**\n * Parses CashAssembly source with parseScript and throws when the parse fails.\n *\n * @param {string} cashAssemblyText - Evaluation or script source to parse.\n * @returns {CashAssemblyScriptSegment} - Parsed Script root.\n * @throws {@link CashAssemblyCompilationFailedError} - When parseScript rejects the source.\n */\nconst parseCashAssemblySource = (cashAssemblyText: string): CashAssemblyScriptSegment => {\n // Parse so Push and Identifier nodes are available for collection.\n const parseResult = parseScript(cashAssemblyText);\n\n // parseScript returns a union. status false is the failure arm and must not be read as a Script.\n if (parseResult.status === false) {\n // describeExpectedInput turns the expected input list into readable text for the typed error.\n const expectedInputDescription = describeExpectedInput(parseResult.expected);\n\n throw new CashAssemblyCompilationFailedError(`${expectedInputDescription} Line ${String(parseResult.index.line)}, column ${String(parseResult.index.column)}.`);\n }\n\n return parseResult.value;\n};\n\n/**\n * Identifier visitor for the parseScript tree.\n * Records WalletData or queues a nested script from one Identifier node.\n *\n * @param {CollectFromParsedIdentifierParameters} parameters - Identifier text and the parse tree context.\n */\nconst collectFromParsedIdentifier = (parameters: CollectFromParsedIdentifierParameters): void => {\n const { identifier, isDirectPushContent, knownScriptIdentifiers, visitedScriptIdentifiers, scriptIdentifiersToVisit, variableNames } = parameters;\n\n // Script ids are visited whether they appear in a Push or beside opcodes.\n if (knownScriptIdentifiers.has(identifier) === true) {\n enqueueReachableTemplateScriptIdentifier(identifier, knownScriptIdentifiers, visitedScriptIdentifiers, scriptIdentifiersToVisit);\n\n return;\n }\n\n // Direct Push names that are not script ids are WalletData, including dotted names.\n if (isDirectPushContent === true) {\n variableNames.add(identifier);\n }\n};\n\n/**\n * Visitor for one Script node in the parseScript tree.\n * Recurses into Push and Evaluation children and dispatches Identifier nodes.\n *\n * @param {CollectFromParsedScriptParameters} parameters - Parsed Script, Push depth flag, and parse tree context.\n */\nconst collectFromParsedScript = (parameters: CollectFromParsedScriptParameters): void => {\n const { scriptSegment, isDirectPushContent, knownScriptIdentifiers, visitedScriptIdentifiers, scriptIdentifiersToVisit, variableNames } =\n parameters;\n\n for (const child of scriptSegment.value) {\n if (child.name === 'Push') {\n // Inner Script of a Push is where `<name>` WalletData lives, including nested angle brackets.\n collectFromParsedScript({\n scriptSegment: child.value,\n isDirectPushContent: true,\n knownScriptIdentifiers,\n visitedScriptIdentifiers,\n scriptIdentifiersToVisit,\n variableNames,\n });\n\n continue;\n }\n\n if (child.name === 'Evaluation') {\n // Evaluation contents are opcodes and nested Pushes, not WalletData by themselves.\n collectFromParsedScript({\n scriptSegment: child.value,\n isDirectPushContent: false,\n knownScriptIdentifiers,\n visitedScriptIdentifiers,\n scriptIdentifiersToVisit,\n variableNames,\n });\n\n continue;\n }\n\n if (child.name === 'Identifier') {\n collectFromParsedIdentifier({\n identifier: child.value,\n isDirectPushContent,\n knownScriptIdentifiers,\n visitedScriptIdentifiers,\n scriptIdentifiersToVisit,\n variableNames,\n });\n }\n }\n};\n\n/**\n * Collects WalletData names from the parseScript tree using the visitor pattern.\n *\n * parseScript returns a tree of Script, Push, Evaluation, and Identifier nodes. Nested Push and\n * Evaluation nodes are entered immediately. A template script id is queued whether it appears inside a Push or next to\n * opcodes. Queued script sources are visited after the current tree finishes, in the order they were\n * first seen.\n * A visited id is skipped on later encounters. Opcodes and literals are ignored. Unrelated scripts\n * in the map are not visited. An Identifier inside a nested Push is collected from that inner Push,\n * for example `<$(<ownerKey.public_key> OP_HASH160)>` collects `ownerKey.public_key`.\n *\n * @param {string} evaluation - CashAssembly evaluation or script id text to scan.\n * @param {CashAssemblyTemplateScripts} [templateScripts] - Optional template scripts map used to visit nested script ids.\n * @returns {string[]} - WalletData names from reachable Pushes. Script ids are omitted when\n * `templateScripts` is provided.\n * @throws {@link CashAssemblyCompilationFailedError} - When parseScript rejects the starting text or a visited script source.\n */\nexport const collectVariablesUsingParseScript = (evaluation: string, templateScripts: CashAssemblyTemplateScripts = {}): string[] => {\n // Create a set of the script identifiers from the template scripts map.\n const knownScriptIdentifiers = new Set(Object.keys(templateScripts));\n\n const visitedScriptIdentifiers = new Set<string>();\n const scriptIdentifiersToVisit: string[] = [];\n const variableNames = new Set<string>();\n\n // Share by reference context.\n const parseTreeContext: CollectFromParseTreeContext = {\n knownScriptIdentifiers,\n visitedScriptIdentifiers,\n scriptIdentifiersToVisit,\n variableNames,\n };\n\n // Parse the starting text so nested Pushes are visible before visiting nested script sources.\n const startingScriptSegment = parseCashAssemblySource(evaluation);\n\n // Scan the starting parse tree before visiting nested script sources.\n collectFromParsedScript({\n ...parseTreeContext,\n scriptSegment: startingScriptSegment,\n isDirectPushContent: false,\n });\n\n for (const scriptIdentifier of scriptIdentifiersToVisit) {\n if (visitedScriptIdentifiers.has(scriptIdentifier) === true) {\n continue;\n }\n\n visitedScriptIdentifiers.add(scriptIdentifier);\n\n // Get the script definition from the template scripts map.\n const scriptDefinition = templateScripts[scriptIdentifier];\n\n const nestedScriptSegment = parseCashAssemblySource(scriptDefinition);\n\n collectFromParsedScript({\n ...parseTreeContext,\n scriptSegment: nestedScriptSegment,\n isDirectPushContent: false,\n });\n }\n\n return [ ...variableNames ];\n};\n","import { bigIntToVmNumber, utf8ToBin } from '@bitauth/libauth';\nimport { CashAssemblyNumberNotSafeIntegerError, CashAssemblyUnsupportedValueTypeError } from './errors.ts';\n\n/**\n * Converts a value into bytes representation.\n *\n * @param {unknown} value - Value to encode, should be one of: Uint8Array, bigint, boolean, string, or a safe integer number.\n * @param {string} valueIdentifier - Identifier used in error messages.\n * @returns {Uint8Array} - Bytes representation of the value.\n * @throws {@link CashAssemblyNumberNotSafeIntegerError} - When a number is not a safe integer.\n * @throws {@link CashAssemblyUnsupportedValueTypeError} - When the value type cannot be resolved.\n */\nexport const convertValueToBytes = (value: unknown, valueIdentifier: string): Uint8Array => {\n if (value instanceof Uint8Array) {\n return value;\n }\n\n if (typeof value === 'bigint') {\n return bigIntToVmNumber(value);\n }\n\n if (typeof value === 'boolean') {\n // The BCH VM treats an empty byte array as false and any nonempty byte array as true.\n return new Uint8Array(value ? [ 1 ] : []);\n }\n\n if (typeof value === 'string') {\n return utf8ToBin(value);\n }\n\n if (typeof value === 'number') {\n if (Number.isSafeInteger(value) === true) {\n return bigIntToVmNumber(BigInt(value));\n }\n\n throw new CashAssemblyNumberNotSafeIntegerError(valueIdentifier, value);\n }\n\n throw new CashAssemblyUnsupportedValueTypeError(valueIdentifier, typeof value);\n};\n","/**\n * Matches a single dot variable method reference inside an angle bracket identifier.\n *\n * Used to detect primitive method references such as `expiry.toIso8601`.\n *\n * For example `expiry.toIso8601` matches with base expiry and method toIso8601.\n * `requestedSatoshis` does not match because it has no method.\n * `key.schnorr_signature.all_outputs` does not match because it has more than one dot.\n */\nexport const CASHASSEMBLY_VARIABLE_METHOD_REFERENCE_PATTERN = /^([^.]+)\\.([^.]+)$/;\n\n/**\n * Character count of the `$(` evaluation opener, which is two characters long.\n *\n * Adding this length moves the read position to the first character after that sequence so scanning\n * starts on the evaluation contents rather than on the opening parenthesis.\n */\nexport const CASHASSEMBLY_EVALUATION_START_LENGTH = 2;\n\n/**\n * Character count of the `//` and `/*` comment openers, which are both two characters long.\n *\n * Adding this length moves the read position to the first character after that sequence so the '*'\n * of a block comment opener cannot be reused as the '*' of its closer.\n */\nexport const CASHASSEMBLY_COMMENT_START_LENGTH = 2;\n\n/**\n * Character count of the block comment closer, which is two characters long.\n *\n * Adding this length moves the read position to the first character after that sequence so the\n * closing slash cannot pair with the next character and open another comment.\n */\nexport const CASHASSEMBLY_BLOCK_COMMENT_END_LENGTH = 2;\n\n/**\n * `$()` with nothing between the parentheses.\n *\n * Callers use this to detect an evaluation that has no contents to compile.\n */\nexport const EMPTY_CASHASSEMBLY_EVALUATION = '$()';\n","import {\n FungibleTokenAmount,\n NFTCommitment,\n PublicKey,\n Satoshis,\n SchnorrSignature,\n TemplateIdentifier,\n Timestamp,\n TokenCategory,\n TransactionHash,\n} from '@xo-cash/primitives';\nimport { XOTemplatePrimitiveTypes } from '@xo-cash/types';\nimport type { XOTemplate, XOTemplatePrimitiveType } from '@xo-cash/types';\nimport { CashAssemblyPrimitiveMethodMissingError, CashAssemblyPrimitiveVariableMissingError } from './errors.ts';\nimport { CASHASSEMBLY_VARIABLE_METHOD_REFERENCE_PATTERN } from './defaults.ts';\nimport { convertValueToBytes } from './bytes.ts';\n\n/**\n * Maps method resolvable template types to `@xo-cash/primitives` classes for `base.method` resolution.\n * Keys are a subset of {@link XOTemplatePrimitiveTypes}.\n */\nconst RESOLVABLE_PRIMITIVE_CLASS_BY_TYPE = {\n [XOTemplatePrimitiveTypes.FUNGIBLE_TOKEN_AMOUNT]: FungibleTokenAmount,\n [XOTemplatePrimitiveTypes.NFT_COMMITMENT]: NFTCommitment,\n [XOTemplatePrimitiveTypes.PUBLIC_KEY]: PublicKey,\n [XOTemplatePrimitiveTypes.SATOSHIS]: Satoshis,\n [XOTemplatePrimitiveTypes.SCHNORR_SIGNATURE]: SchnorrSignature,\n [XOTemplatePrimitiveTypes.TEMPLATE_IDENTIFIER]: TemplateIdentifier,\n [XOTemplatePrimitiveTypes.TIMESTAMP]: Timestamp,\n [XOTemplatePrimitiveTypes.TOKEN_CATEGORY]: TokenCategory,\n [XOTemplatePrimitiveTypes.TRANSACTION_HASH]: TransactionHash,\n} as const;\n\n/**\n * Template primitive types that map to an `@xo-cash/primitives` class for `base.method` resolution.\n * This is a subset of {@link XOTemplatePrimitiveType}, not every declared template type.\n */\ntype ResolvablePrimitiveType = keyof typeof RESOLVABLE_PRIMITIVE_CLASS_BY_TYPE;\n\n/**\n * Inputs needed to call a primitive method for a `name.method` push.\n */\ntype CallPrimitiveMethodParameters = {\n\n /**\n * Full push identifier from the evaluation, for example `amount.toSatoshis`.\n */\n identifier: string;\n\n /**\n * Method name to call on the constructed primitive, for example `toIso8601`.\n */\n methodName: string;\n\n /**\n * Value for the variable.\n */\n value: unknown;\n\n /**\n * Method resolvable template type that selects the primitive class.\n */\n type: ResolvablePrimitiveType;\n};\n\n/**\n * Inputs needed to resolve primitive method pushes from collected CashAssembly variable names.\n */\nexport type ResolvePrimitiveMethodBytesParameters = {\n\n /**\n * Variable names from {@link collectVariablesUsingParseScript}, for example\n * `['amount.toSatoshis', 'fee.toSatoshis']`.\n */\n variableNames: string[];\n\n /**\n * Variable names and values object.\n */\n variables: Record<string, unknown>;\n\n /**\n * Template variable definitions. When omitted, no primitive methods are resolved.\n * The `type` on each entry selects the primitive class.\n */\n templateVariables?: XOTemplate['variables'];\n};\n\n/**\n * Returns true when `type` maps to a primitive class in `RESOLVABLE_PRIMITIVE_CLASS_BY_TYPE` for method resolution.\n *\n * @param {XOTemplatePrimitiveType | undefined} type - Template variable type.\n * @returns {boolean} True when the type can resolve `base.method` through a primitive class.\n */\nconst isResolvablePrimitiveType = (type: XOTemplatePrimitiveType | undefined): type is ResolvablePrimitiveType => {\n return type !== undefined && Object.hasOwn(RESOLVABLE_PRIMITIVE_CLASS_BY_TYPE, type) === true;\n};\n\n/**\n * Returns true when `methodName` is an own function on the primitive class for `type`.\n *\n * @param {ResolvablePrimitiveType} type - Method resolvable template type.\n * @param {string} methodName - Method name from the evaluation text, for example `toSatoshis`.\n * @returns {boolean} - True when that class exposes the named method.\n */\nconst canResolvePrimitiveMethod = (type: ResolvablePrimitiveType, methodName: string): boolean => {\n const PrimitiveClass = RESOLVABLE_PRIMITIVE_CLASS_BY_TYPE[type];\n\n // Check own properties only so inherited Object.prototype names are rejected without needing a value.\n if (Object.hasOwn(PrimitiveClass.prototype, methodName) === false) {\n return false;\n }\n\n return typeof Reflect.get(PrimitiveClass.prototype, methodName) === 'function';\n};\n\n/**\n * Constructs a primitive from a raw value and calls one instance method on it.\n *\n * Call only after `canResolvePrimitiveMethod` is true for the same type and method.\n *\n * @param {CallPrimitiveMethodParameters} parameters - Identifier, method, value, and resolvable type.\n * @returns {unknown} Method return value, later encoded as CashAssembly push bytes.\n * @throws {@link CashAssemblyPrimitiveMethodMissingError} When the prototype member is not a function.\n * @throws When the primitive constructor rejects the raw value (validation errors from `@xo-cash/primitives`).\n */\nconst callPrimitiveMethod = (parameters: CallPrimitiveMethodParameters): unknown => {\n const { identifier, methodName, value, type } = parameters;\n\n const PrimitiveClass = RESOLVABLE_PRIMITIVE_CLASS_BY_TYPE[type];\n\n // Constructing runs each primitive's own input validation (range checks, hex length, etc).\n // `as never` satisfies TypeScript across constructors that accept different input shapes.\n const primitiveInstance = new PrimitiveClass(value as never);\n\n // Same prototype member canResolvePrimitiveMethod already verified as an own function.\n const primitiveMethod = Reflect.get(PrimitiveClass.prototype, methodName);\n\n if (typeof primitiveMethod !== 'function') {\n throw new CashAssemblyPrimitiveMethodMissingError(identifier, methodName, type);\n }\n\n return primitiveMethod.call(primitiveInstance);\n};\n\n/**\n * Resolves method resolvable `base.method` identifiers to CashAssembly variable bytes.\n *\n * Each single dot identifier whose `type` is in `RESOLVABLE_PRIMITIVE_CLASS_BY_TYPE` is resolved and stored under\n * the full identifier (`base.method`). Other template types or multi dot identifiers are left for CashAssembly.\n *\n * When `templateVariables` is omitted, returns an empty map.\n *\n * @param {ResolvePrimitiveMethodBytesParameters} parameters - Identifiers, values, and optional template metadata.\n * @returns {Record<string, Uint8Array>} Resolved method identifiers mapped to bytes for CashAssembly pushes.\n * @throws {@link CashAssemblyPrimitiveMethodMissingError} When the type is method resolvable but the method is missing.\n * @throws {@link CashAssemblyPrimitiveVariableMissingError} When the runtime value is missing from the variables map.\n * @throws {@link CashAssemblyUnsupportedValueTypeError} When the method return type cannot be embedded.\n * @throws {@link CashAssemblyNumberNotSafeIntegerError} When a method return value is a number that is not a safe integer.\n */\nexport const resolvePrimitiveMethodBytes = (parameters: ResolvePrimitiveMethodBytesParameters): Record<string, Uint8Array> => {\n const { variableNames, templateVariables, variables } = parameters;\n\n // Without template metadata there is no type to select a primitive class.\n if (templateVariables === undefined) {\n return {};\n }\n\n const resolvedBytes: Record<string, Uint8Array> = {};\n\n for (const variableName of variableNames) {\n // The same name can appear more than once. Resolve it only once.\n if (Object.hasOwn(resolvedBytes, variableName) === true) {\n continue;\n }\n\n // Find the primitive method reference in the name.\n const methodReferenceMatch = variableName.match(CASHASSEMBLY_VARIABLE_METHOD_REFERENCE_PATTERN);\n\n if (methodReferenceMatch === null) {\n continue;\n }\n\n const [ , baseName, methodName ] = methodReferenceMatch;\n\n // Unknown names and CashAssembly native operations such as someKey.schnorr_signature.all_outputs\n // must be left for CashAssembly rather than treated as primitive failures.\n if (Object.hasOwn(templateVariables, baseName) === false) {\n continue;\n }\n\n const type = templateVariables[baseName].type;\n\n // Template types without a mapped primitive class are left for CashAssembly.\n if (isResolvablePrimitiveType(type) === false) {\n continue;\n }\n\n // Method resolvable type with an unknown method should throw.\n if (canResolvePrimitiveMethod(type, methodName) === false) {\n throw new CashAssemblyPrimitiveMethodMissingError(variableName, methodName, type);\n }\n\n // If the method is known but the runtime value is missing, throw an error.\n if (Object.hasOwn(variables, baseName) === false) {\n throw new CashAssemblyPrimitiveVariableMissingError(variableName, baseName);\n }\n\n const methodResult = callPrimitiveMethod({\n identifier: variableName,\n methodName,\n value: variables[baseName],\n type,\n });\n\n // CashAssembly looks up the full `base.method` name as WalletData bytes.\n resolvedBytes[variableName] = convertValueToBytes(methodResult, variableName);\n }\n\n return resolvedBytes;\n};\n","import { generateBytecodeMap, IdentifierResolutionType, OpcodesBchSpec } from '@bitauth/libauth';\nimport { CashAssemblyIdentifierCollisionError } from './errors.ts';\nimport type { CompileCashAssemblyContext } from './types.ts';\n\n/**\n * Set of opcode names that the compiler recognizes.\n */\nconst COMPILER_OPCODE_NAMES: ReadonlySet<string> = new Set(Object.keys(generateBytecodeMap(OpcodesBchSpec)));\n\n/**\n * Parameters for {@link assertNoIdentifierCollisions} function.\n */\nexport type AssertNoIdentifierCollisionsParameters = Pick<CompileCashAssemblyContext, 'variables' | 'templateScripts'>;\n\n/**\n * Libauth resolves opcodes, then variables, then scripts, and the first match silently hides the\n * rest, leading to unexpected compilation results and no errors. This function throws when one identifier matches more than one resolution type.\n *\n * @param {AssertNoIdentifierCollisionsParameters} parameters - Provided variables and optional template scripts.\n * @throws {@link CashAssemblyIdentifierCollisionError} - When one identifier matches more than one resolution type.\n */\nexport const assertNoIdentifierCollisions = (parameters: AssertNoIdentifierCollisionsParameters): void => {\n const { variables, templateScripts } = parameters;\n\n // Create a set of the script identifiers from the template scripts map.\n const scriptIdentifiers = new Set(Object.keys(templateScripts ?? {}));\n\n const variableNames = new Set(Object.keys(variables));\n\n // Combine both, the variableNames and the scriptIdentifiers, to get a set of all identifiers.\n const declaredIdentifiers = new Set([ ...variableNames, ...scriptIdentifiers ]);\n\n // This loop will check for more than one occurrence of an identifier in OP_CODES, variables, and scripts\n for (const identifier of declaredIdentifiers) {\n // Resolution types is a native construct from libauth.\n const resolutionTypes: IdentifierResolutionType[] = [];\n\n // If the identifier is an opcode, then push it to the resolution types array, this will also be\n // detected by either or both of the variableNames and scriptIdentifiers checks.\n if (COMPILER_OPCODE_NAMES.has(identifier) === true) {\n resolutionTypes.push(IdentifierResolutionType.opcode);\n }\n\n // If the identifier is in variables, then push it to the resolution types array.\n if (variableNames.has(identifier) === true) {\n resolutionTypes.push(IdentifierResolutionType.variable);\n }\n\n // If the identifier is a script identifier, then push it to the resolution types array.\n if (scriptIdentifiers.has(identifier) === true) {\n resolutionTypes.push(IdentifierResolutionType.script);\n }\n\n // If there are more than one resolution types, then throw an error.\n if (resolutionTypes.length > 1) {\n throw new CashAssemblyIdentifierCollisionError(identifier, resolutionTypes);\n }\n }\n};\n","import {\n CASHASSEMBLY_BLOCK_COMMENT_END_LENGTH,\n CASHASSEMBLY_COMMENT_START_LENGTH,\n CASHASSEMBLY_EVALUATION_START_LENGTH,\n EMPTY_CASHASSEMBLY_EVALUATION,\n} from './defaults.ts';\nimport { CashAssemblyBlockCommentUnclosedError, CashAssemblyEvaluationUnclosedError, CashAssemblyQuotedLiteralUnclosedError } from './errors.ts';\n\n/**\n * Skips a quoted CashAssembly string so a `)` inside it cannot end `$()`.\n *\n * CashAssembly UTF8 literals use `\"...\"` or `'...'`. Everything between the quotes is payload,\n * including parentheses.\n * For example `$(<\"hello)world\">)` must close after the literal, not at the `)` inside the quotes.\n *\n * @param {string} cashAssemblyText - Text that contains the quoted literal.\n * @param {number} openingQuoteIndex - Index of the opening `\"` or `'`.\n * @returns {number} - Index of the character after the closing quote.\n * @throws {@link CashAssemblyQuotedLiteralUnclosedError} - When the quoted literal never closes.\n */\nconst skipQuotedCashAssemblyLiteral = (cashAssemblyText: string, openingQuoteIndex: number): number => {\n const quoteCharacter = cashAssemblyText[openingQuoteIndex];\n let currentIndex = openingQuoteIndex + 1;\n\n // CashAssembly puts payload `)` inside the quotes. Stop only at the matching quote.\n while (currentIndex < cashAssemblyText.length) {\n if (cashAssemblyText[currentIndex] === quoteCharacter) {\n return currentIndex + 1;\n }\n\n currentIndex += 1;\n }\n\n throw new CashAssemblyQuotedLiteralUnclosedError(openingQuoteIndex, quoteCharacter, cashAssemblyText);\n};\n\n/**\n * This function skips a `//` comment so a `)` written in the comment cannot end `$()`.\n * A line comment runs from `//` to the newline, or to the end of the string when there is no newline.\n * A `)` in that span is comment text, not the closer of `$()`.\n *\n * @param {string} cashAssemblyText - Text that contains the line comment.\n * @param {number} commentStartIndex - Index of the first `/` of `//`.\n * @returns {number} - Index after the newline that ends the comment, or the end of the string if there is no newline.\n */\nconst skipSingleLineCashAssemblyComment = (cashAssemblyText: string, commentStartIndex: number): number => {\n let currentIndex = commentStartIndex + CASHASSEMBLY_COMMENT_START_LENGTH;\n\n // CashAssembly line comments hide `)` until the newline. End of string also ends them.\n while (currentIndex < cashAssemblyText.length) {\n if (cashAssemblyText[currentIndex] === '\\n') {\n return currentIndex + 1;\n }\n\n currentIndex += 1;\n }\n\n return currentIndex;\n};\n\n/**\n * This function skips a block comment so a `)` written in the comment cannot end `$()`.\n * A `)` inside a block comment is comment text, not the closer of `$()`.\n *\n * @param {string} cashAssemblyText - Text that contains the block comment.\n * @param {number} commentStartIndex - Index of the first slash of the block comment opener.\n * @returns {number} - Index of the character after the comment closer.\n * @throws {@link CashAssemblyBlockCommentUnclosedError} - When the block comment never closes.\n */\nconst skipBlockCashAssemblyComment = (cashAssemblyText: string, commentStartIndex: number): number => {\n let currentIndex = commentStartIndex + CASHASSEMBLY_COMMENT_START_LENGTH;\n\n // CashAssembly block comments hide `)` until the closer is found.\n while (currentIndex + 1 < cashAssemblyText.length) {\n if (cashAssemblyText[currentIndex] === '*' && cashAssemblyText[currentIndex + 1] === '/') {\n return currentIndex + CASHASSEMBLY_BLOCK_COMMENT_END_LENGTH;\n }\n\n currentIndex += 1;\n }\n\n throw new CashAssemblyBlockCommentUnclosedError(commentStartIndex, cashAssemblyText);\n};\n\n/**\n * Parenthesis matching with a depth count.\n *\n * Returns the index of the `)` that closes the `$()` starting at `evaluationStartIndex`.\n * Nested `$()` raise the depth so an inner closer cannot finish the outer evaluation.\n *\n * @param {string} cashAssemblyText - Text that contains the evaluation.\n * @param {number} evaluationStartIndex - Index of the `$` that opens this evaluation.\n * @returns {number} - Index of the matching closing parenthesis.\n * @throws {@link CashAssemblyEvaluationUnclosedError} - When the evaluation never closes.\n * @throws {@link CashAssemblyQuotedLiteralUnclosedError} - When a quoted literal inside the evaluation never closes.\n * @throws {@link CashAssemblyBlockCommentUnclosedError} - When a block comment inside the evaluation never closes.\n */\nconst findCashAssemblyEvaluationCloseIndex = (cashAssemblyText: string, evaluationStartIndex: number): number => {\n let currentIndex = evaluationStartIndex + CASHASSEMBLY_EVALUATION_START_LENGTH;\n let remainingOpenEvaluations = 1;\n\n // Scan the evaluation contents until the matching closer at depth zero.\n while (currentIndex < cashAssemblyText.length) {\n const currentCharacter = cashAssemblyText[currentIndex];\n const nextCharacter = cashAssemblyText[currentIndex + 1];\n\n // CashAssembly allows `)` inside `\"...\"` and `'...'`. Skip the literal so that closer is not structural.\n if (currentCharacter === '\"' || currentCharacter === \"'\") {\n currentIndex = skipQuotedCashAssemblyLiteral(cashAssemblyText, currentIndex);\n\n continue;\n }\n\n // CashAssembly `//` comments may mention `)`. Skip them so that `)` is not treated as a closer.\n if (currentCharacter === '/' && nextCharacter === '/') {\n currentIndex = skipSingleLineCashAssemblyComment(cashAssemblyText, currentIndex);\n\n continue;\n }\n\n // CashAssembly block comments may mention `)`. Skip them so that `)` is not treated as a closer.\n if (currentCharacter === '/' && nextCharacter === '*') {\n currentIndex = skipBlockCashAssemblyComment(cashAssemblyText, currentIndex);\n\n continue;\n }\n\n // Nested `$()` must close before this evaluation can close.\n if (currentCharacter === '$' && nextCharacter === '(') {\n // Since all previous checks have passed then it means this is start of another evaluation, it we must\n // increment the remainingOpenEvaluations counter and move the currentIndex to the next character.\n remainingOpenEvaluations += 1;\n currentIndex += CASHASSEMBLY_EVALUATION_START_LENGTH;\n\n continue;\n }\n\n // A closer at depth one ends this evaluation. Inner closers only reduce nested depth.\n if (currentCharacter === ')') {\n // Since all previous checks have passed then it means this is a closer for the current evaluation, we must\n // decrement the remainingOpenEvaluations counter and check if it is now zero. If it is then we have found the\n // matching closer and we can return the currentIndex.\n remainingOpenEvaluations -= 1;\n\n if (remainingOpenEvaluations === 0) {\n return currentIndex;\n }\n }\n\n // Move the currentIndex to the next character.\n currentIndex += 1;\n }\n\n // The matching closer was never found.\n throw new CashAssemblyEvaluationUnclosedError(evaluationStartIndex, remainingOpenEvaluations, cashAssemblyText);\n};\n\n/**\n * One `$()` found in text that is not nested inside another `$()`.\n */\ntype CashAssemblyEvaluationScanMatch = {\n\n /**\n * Complete `$()` text including the opening `$` and the matching closer.\n */\n evaluationText: string;\n\n /**\n * Index of the `$` that opens this evaluation.\n */\n startIndex: number;\n\n /**\n * Index of the matching closing parenthesis.\n */\n closeIndex: number;\n};\n\n/**\n * Scans text and returns every `$()` that starts in this string, including empty `$()`.\n *\n * Nested `$()` stay inside the outer evaluation.\n *\n * @param {string} cashAssemblyText - Text that may contain `$()`.\n * @returns {CashAssemblyEvaluationScanMatch[]} - Evaluations in left to right order.\n * @throws {@link CashAssemblyEvaluationUnclosedError} - When an evaluation never closes.\n * @throws {@link CashAssemblyQuotedLiteralUnclosedError} - When a quoted literal never closes.\n * @throws {@link CashAssemblyBlockCommentUnclosedError} - When a block comment never closes.\n */\nexport const scanCashAssemblyEvaluations = (cashAssemblyText: string): CashAssemblyEvaluationScanMatch[] => {\n const scannedEvaluations: CashAssemblyEvaluationScanMatch[] = [];\n let currentIndex = 0;\n\n // Find `$()` that starts in this string. Nested evaluations stay inside the outer evaluation.\n while (currentIndex < cashAssemblyText.length) {\n const currentCharacter = cashAssemblyText[currentIndex];\n const nextCharacter = cashAssemblyText[currentIndex + 1];\n\n // A `$` that is followed by `(`.\n if (currentCharacter === '$' && nextCharacter === '(') {\n // Count parentheses so quotes, comments, and nested `$()` cannot close this evaluation early.\n const closeIndex = findCashAssemblyEvaluationCloseIndex(cashAssemblyText, currentIndex);\n // Slice the complete `$()` so later steps do not re-scan these characters.\n const evaluationText = cashAssemblyText.slice(currentIndex, closeIndex + 1);\n\n // Store the outer `$()`. Nested evaluations are already inside evaluationText.\n scannedEvaluations.push({\n closeIndex,\n evaluationText,\n startIndex: currentIndex,\n });\n\n // Skip to after this `$()` so nested evaluations are not scanned as their own matches.\n currentIndex = closeIndex + 1;\n\n continue;\n }\n\n currentIndex += 1;\n }\n\n return scannedEvaluations;\n};\n\n/**\n * This function returns each `$()` that starts in this string.\n * Empty `$()` is omitted.\n *\n * @param {string} cashAssemblyText - Text that may contain `$()`.\n * @returns {string[]} - Complete non empty evaluation strings in left to right order.\n * @throws {@link CashAssemblyEvaluationUnclosedError} - When an evaluation never closes.\n * @throws {@link CashAssemblyQuotedLiteralUnclosedError} - When a quoted literal never closes.\n * @throws {@link CashAssemblyBlockCommentUnclosedError} - When a block comment never closes.\n */\nexport const extractCashAssemblyEvaluations = (cashAssemblyText: string): string[] => {\n const scannedEvaluations = scanCashAssemblyEvaluations(cashAssemblyText);\n const evaluations: string[] = [];\n\n // Omit empty `$()` so callers that compile extracted text do not treat it as an evaluation.\n for (const scannedEvaluation of scannedEvaluations) {\n if (scannedEvaluation.evaluationText !== EMPTY_CASHASSEMBLY_EVALUATION) {\n evaluations.push(scannedEvaluation.evaluationText);\n }\n }\n\n return evaluations;\n};\n\n/**\n * This function returns true when the value is exactly one CashAssembly `$()`.\n * Text with characters outside `$()`, empty `$()`, or a failed scan returns false.\n *\n * @param {unknown} expression - Value to test.\n * @returns {boolean} - True when the value is a string that is one complete evaluation and nothing else.\n */\nexport const isCashAssemblyExpression = (expression: unknown): boolean => {\n // Numbers and other types are never CashAssembly evaluations.\n if (typeof expression !== 'string') {\n return false;\n }\n\n try {\n const evaluations = extractCashAssemblyEvaluations(expression);\n\n // If there is only one evaluation extracted and the returned value matches to that of the expression passed in the parameter,\n // then return true.\n return evaluations.length === 1 && evaluations[0] === expression;\n } catch {\n // A failed scan is not a complete evaluation.\n return false;\n }\n};\n","/**\n * Utilities for parsing, extracting, and compiling CashAssembly expressions.\n *\n * CashAssembly is the scripting language used by Bitauth templates to describe Bitcoin Cash\n * locking and unlocking scripts.\n *\n * ## Syntax (CashAssembly)\n *\n * `<expression>` is a push statement. Compiles the contents and pushes the result onto the VM stack.\n * For example `<someKey.public_key>` pushes the 33 byte compressed public key and `<1>` pushes the integer 1.\n *\n * `$(<expression>)` is an evaluation. Runs the inner script in the VM and inserts the top stack\n * item as VM bytecode.\n * For example `$(<someKey.public_key> OP_HASH160)` inserts the HASH160 of the public key.\n *\n * `<$(<expression>)>` is a push of an evaluation result. It evaluates first then pushes.\n * For example a P2PKH locking script looks like\n * `OP_DUP OP_HASH160 <$(<someKey.public_key> OP_HASH160)> OP_EQUALVERIFY OP_CHECKSIG`.\n *\n * `variableId.operation` is a variable with a compiler resolved operation.\n * For example `someKey.public_key` produces the public key bytes and\n * `someKey.schnorr_signature.all_outputs` produces a Schnorr signature.\n *\n * Opcodes (`OP_DUP`, `OP_HASH160`, and similar) are inserted as their bytecode equivalent directly.\n *\n * ## Name resolution priority (CashAssembly)\n *\n * When the compiler encounters an identifier it resolves it in this order.\n * 1. Opcode always wins. For example naming a variable or script `OP_ADD` will not shadow it.\n * 2. Variable shadows scripts of the same name.\n * 3. Script is the script's bytecode.\n *\n * ## Resolution Order (CashAssembly + Primitive Method Resolution)\n *\n * Supported `<base.method>` pushes are resolved to bytes before CashAssembly compiles.\n * Inside CashAssembly the order is Opcode then Variable then Script.\n *\n * ## This compile path\n *\n * This file is a layer on CashAssembly. Text outside `$()` is kept. Only `$()` is compiled.\n * For example `Paid $(scriptA) of $(scriptB)` keeps the words Paid and of.\n *\n * `$()` is found by scanning left to right with parenthesis matching by depth count. Quoted strings\n * and comments are skipped so a `)` there cannot end `$()`. Nested `$()` stay inside the outer\n * evaluation. That text is never passed to parseScript.\n *\n * Empty `$()` still uses this mixed path. When the string contains no `$()` at all, the entire\n * string is compiled as CashAssembly so push opcodes remain.\n */\nimport type { CompilerBch } from '@bitauth/libauth';\nimport { binToHex, binToUtf8, createCompilerBch, vmNumberToBigInt } from '@bitauth/libauth';\nimport { convertValueToBytes } from './bytes.ts';\nimport {\n CashAssemblyCompilationFailedError,\n CashAssemblyRequiredVariableMissingError,\n CashAssemblyVariableTypeMismatchError,\n CashAssemblyVmNumberDecodeError,\n} from './errors.ts';\nimport { resolvePrimitiveMethodBytes } from './primitive-evaluations.ts';\nimport { assertNoIdentifierCollisions } from './identifier-collisions.ts';\nimport { collectVariablesUsingParseScript } from './collect-evaluations.ts';\nimport { EMPTY_CASHASSEMBLY_EVALUATION } from './defaults.ts';\nimport { scanCashAssemblyEvaluations } from './scan-evaluations.ts';\nimport type {\n CompileCashAssemblyEvaluationsParameters,\n CompileCashAssemblySourceToBytesParameters,\n CompileCashAssemblySourceToDecodedTextParameters,\n CompileCashAssemblyStringParameters,\n CompiledCashAssemblyDecodeMode,\n} from './types.ts';\n\n/**\n * Returns the segment of `identifier` before the first `.`.\n *\n * When there is no `.`, returns `identifier` unchanged.\n * Multi segment identifiers such as `foo.bar.baz` resolve to `foo`.\n *\n * @param {string} identifier - Identifier that may contain a dot.\n * @returns {string} - The base name before the first `.`.\n */\nconst resolveIdentifierBaseName = (identifier: string): string => {\n const firstDotIndex = identifier.indexOf('.');\n\n if (firstDotIndex === -1) {\n return identifier;\n }\n\n return identifier.slice(0, firstDotIndex);\n};\n\n/**\n * Decodes compiled CashAssembly evaluation bytes into a string representation.\n *\n * 'evaluationDecodeMode' determines how the evaluation bytes are interpreted and presented.\n * Use `bigint` for numeric values like satoshis, `utf8` for text labels, `hex` for binary data\n * such as hashes, and `boolean` to represent boolean values.\n *\n * @param {Uint8Array} compiledResult - The compiled evaluation bytecode.\n * @param {CompiledCashAssemblyDecodeMode} evaluationDecodeMode - The decode mode used to convert bytes to text.\n * @returns {string} - The decoded value as a string suitable for inline replacement.\n * @throws {@link CashAssemblyVmNumberDecodeError} - When `evaluationDecodeMode` is `bigint` and the bytes are not a VM number.\n */\nexport const decodeCompiledCashAssemblyEvaluation = (\n compiledResult: Uint8Array,\n evaluationDecodeMode: CompiledCashAssemblyDecodeMode = 'utf8',\n): string => {\n // Converts the byte array to a string.\n if (evaluationDecodeMode === 'uint8array') {\n return String(compiledResult);\n }\n\n // Converts the byte array to a boolean string, converting the evaluation result into a true or a false.\n if (evaluationDecodeMode === 'boolean') {\n return compiledResult.length === 0 ? 'false' : 'true';\n }\n\n // Converts the byte array to a hex string.\n if (evaluationDecodeMode === 'hex') {\n return binToHex(compiledResult);\n }\n\n // Converts the byte array to a bigint string.\n if (evaluationDecodeMode === 'bigint') {\n const vmNumberResult = vmNumberToBigInt(compiledResult);\n\n if (typeof vmNumberResult === 'bigint') {\n return vmNumberResult.toString();\n }\n\n throw new CashAssemblyVmNumberDecodeError(vmNumberResult);\n }\n\n // Converts the byte array to a utf8 string.\n return binToUtf8(compiledResult);\n};\n\n/**\n * Generates bytecode for a specific CashAssembly evaluation using given variable values and a prepared compiler.\n *\n * @param {CompilerBch} compiler - The libauth compiler from {@link compileCashAssemblyEvaluations}.\n * @param {string} evaluation - The specific evaluation string to compile.\n * @param {Record<string, Uint8Array>} variables - A record mapping variable names to their values.\n * @param {string[]} requiredVariableNames - WalletData names from {@link collectVariablesUsingParseScript} that must be present.\n * @returns {Uint8Array} - The compiled bytecode.\n * @throws {@link CashAssemblyRequiredVariableMissingError} - If a required variable is not present.\n * @throws {@link CashAssemblyVariableTypeMismatchError} - If a variable value is not a Uint8Array.\n * @throws {@link CashAssemblyCompilationFailedError} - If libauth compilation fails.\n */\nexport const generateCashAssemblyBytecode = (\n compiler: CompilerBch,\n evaluation: string,\n variables: Record<string, Uint8Array>,\n requiredVariableNames: string[],\n): Uint8Array => {\n // Missing WalletData must fail here. Libauth would otherwise compile as if the value were empty bytes.\n const missingVariables = requiredVariableNames.filter((name: string) => Object.hasOwn(variables, name) === false);\n\n // Refuse invented defaults so a missing value cannot compile into incorrect bytecode.\n if (missingVariables.length > 0) {\n throw new CashAssemblyRequiredVariableMissingError(missingVariables);\n }\n\n const bytecode: Record<string, Uint8Array> = {};\n\n // Pass only required names so extra keys in `variables` are not sent to Libauth.\n for (const variableName of requiredVariableNames) {\n const value = variables[variableName];\n\n // Libauth WalletData is always bytes. A number would compile incorrectly if we trusted TypeScript alone.\n if (value instanceof Uint8Array === false) {\n throw new CashAssemblyVariableTypeMismatchError(variableName, 'Uint8Array', typeof value);\n }\n\n bytecode[variableName] = value;\n }\n\n // `scriptId` is the source string registered in compileCashAssemblyEvaluations.\n const compiledBytecode = compiler.generateBytecode({\n data: { bytecode },\n scriptId: evaluation,\n });\n\n // A failed compile must not return partial bytecode.\n if (compiledBytecode.success === false) {\n // CashAssemblyCompilationFailedError carries one message. Libauth may report several errors.\n let compilationFailureMessage = 'unknown compilation failure';\n\n // Prefer Libauth's own error text when the failure object includes an errors list.\n if ('errors' in compiledBytecode && compiledBytecode.errors.length > 0) {\n compilationFailureMessage = compiledBytecode.errors.map((compilationError) => compilationError.error).join('; ');\n }\n\n throw new CashAssemblyCompilationFailedError(compilationFailureMessage);\n }\n\n return compiledBytecode.bytecode;\n};\n\n/**\n * Prepares a compiler for the provided CashAssembly source strings, setting required variables as 'WalletData'.\n *\n * Each evaluation string is registered as a script whose id and source are that string. Template\n * scripts are then copied onto the same table. If a source is a template id such as `scriptA`, that\n * id must compile the template source. Leaving the id as its own source would compile the text\n * `scriptA` and include itself.\n *\n * @param {CompileCashAssemblyEvaluationsParameters} parameters - Source strings, optional template scripts, and already collected WalletData names.\n * @returns {CompilerBch} - A Libauth compiler instance for use with these source strings.\n */\nexport const compileCashAssemblyEvaluations = (parameters: CompileCashAssemblyEvaluationsParameters): CompilerBch => {\n const { evaluations, templateScripts, variableNames } = parameters;\n const scripts: Record<string, string> = {};\n\n // Libauth looks up scripts by id. Using the source string as the id lets generateBytecode request that exact source.\n for (const evaluation of evaluations) {\n scripts[evaluation] = evaluation;\n }\n\n const knownScriptIdentifiers = new Set<string>();\n\n if (templateScripts !== undefined) {\n for (const [ scriptIdentifier, scriptDefinition ] of Object.entries(templateScripts)) {\n // Compiling `scriptA` must run the template source. Otherwise the id compiles as the text `scriptA` and includes itself.\n scripts[scriptIdentifier] = scriptDefinition;\n\n // Template ids compile as scripts. They must not also be registered as WalletData.\n knownScriptIdentifiers.add(scriptIdentifier);\n }\n }\n\n const variables: Record<string, { type: 'WalletData' }> = {};\n\n // Register caller collected names. This function does not parse or collect again.\n for (const variableName of variableNames) {\n // A name that is a template script id is already a compiler script, not WalletData.\n if (knownScriptIdentifiers.has(variableName) === true) {\n continue;\n }\n\n // Libauth WalletData is the name before the first `.`. `ownerKey.public_key` registers as `ownerKey`.\n variables[resolveIdentifierBaseName(variableName)] = { type: 'WalletData' as const };\n }\n\n const compiler = createCompilerBch({\n scripts,\n variables,\n });\n\n return compiler;\n};\n\n/**\n * Compiles one CashAssembly source string to bytecode.\n *\n * The source may be an evaluation such as `$(scriptA)` or CashAssembly such as\n * `scriptA`. WalletData names come from {@link collectVariablesUsingParseScript}.\n *\n * @param {CompileCashAssemblySourceToBytesParameters} parameters - Source text and compilation context.\n * @returns {Uint8Array} - Compiled bytecode for that source.\n * @throws {@link CashAssemblyRequiredVariableMissingError} - When a required variable is not present in the variables map.\n * @throws {@link CashAssemblyPrimitiveMethodMissingError} - When a supported primitive hint has an unknown method.\n * @throws {@link CashAssemblyPrimitiveVariableMissingError} - When a supported primitive method is missing its runtime value.\n * @throws {@link CashAssemblyUnsupportedValueTypeError} - When a primitive method return type cannot be embedded as bytes.\n * @throws {@link CashAssemblyNumberNotSafeIntegerError} - When a number variable is not a safe integer.\n * @throws {@link CashAssemblyIdentifierCollisionError} - When one identifier matches two resolution types.\n * @throws {@link CashAssemblyCompilationFailedError} - When Libauth compilation fails.\n */\nexport const compileCashAssemblySourceToBytes = (parameters: CompileCashAssemblySourceToBytesParameters): Uint8Array => {\n const { cashAssemblySource, variables, templateVariables, templateScripts } = parameters;\n\n // Throw if there is a identifier collision between opcodes, variable, or template script.\n assertNoIdentifierCollisions({ variables, templateScripts });\n\n // Collect WalletData names from the source and every reachable nested script source.\n const variableNames = collectVariablesUsingParseScript(cashAssemblySource, templateScripts);\n\n // Resolve supported primitive methods to bytes before treating remaining names as WalletData.\n const primitiveMethodBytes = resolvePrimitiveMethodBytes({\n variableNames,\n templateVariables,\n variables,\n });\n\n // Collect names that still need a caller supplied value after primitive resolution.\n const missingVariables: string[] = [];\n for (const variableName of variableNames) {\n // Primitive methods already produced bytes under the full name.\n if (Object.hasOwn(primitiveMethodBytes, variableName) === true) {\n continue;\n }\n\n // A present runtime value will be converted to bytes below.\n if (Object.hasOwn(variables, variableName) === true) {\n continue;\n }\n\n missingVariables.push(variableName);\n }\n\n // Refuse invented defaults so a missing value cannot compile into incorrect bytecode.\n if (missingVariables.length > 0) {\n throw new CashAssemblyRequiredVariableMissingError(missingVariables);\n }\n\n // Convert each variable to its bytes before compilation.\n const variableBytes: Record<string, Uint8Array> = {};\n for (const variableName of variableNames) {\n // Prefer the primitive method result so CashAssembly sees bytes under `base.method`.\n if (Object.hasOwn(primitiveMethodBytes, variableName) === true) {\n variableBytes[variableName] = primitiveMethodBytes[variableName];\n continue;\n }\n\n // Remaining names are caller WalletData that still needs a byte encoding.\n variableBytes[variableName] = convertValueToBytes(variables[variableName], variableName);\n }\n\n // Reuse the names collected above so this compiler is not built from a second parse.\n const compiler = compileCashAssemblyEvaluations({\n evaluations: [ cashAssemblySource ],\n templateScripts,\n variableNames,\n });\n\n return generateCashAssemblyBytecode(compiler, cashAssemblySource, variableBytes, variableNames);\n};\n\n/**\n * Compiles one CashAssembly source to bytes and decodes those bytes to text.\n *\n * @param {CompileCashAssemblySourceToDecodedTextParameters} parameters - Source text, WalletData, optional template context, and decode mode.\n * @returns {string} - Decoded compilation result for that source.\n * @throws {@link CashAssemblyRequiredVariableMissingError} - When a required variable is not present in the variables map.\n * @throws {@link CashAssemblyPrimitiveMethodMissingError} - When a supported primitive hint has an unknown method.\n * @throws {@link CashAssemblyPrimitiveVariableMissingError} - When a supported primitive method is missing its runtime value.\n * @throws {@link CashAssemblyUnsupportedValueTypeError} - When a primitive method return type cannot be embedded as bytes.\n * @throws {@link CashAssemblyNumberNotSafeIntegerError} - When a number variable is not a safe integer.\n * @throws {@link CashAssemblyVmNumberDecodeError} - When `evaluationDecodeMode` is `bigint` and compiled bytes are not a VM number.\n * @throws {@link CashAssemblyIdentifierCollisionError} - When one identifier matches two resolution types.\n * @throws {@link CashAssemblyCompilationFailedError} - When Libauth compilation fails.\n */\nconst compileCashAssemblySourceToDecodedText = (parameters: CompileCashAssemblySourceToDecodedTextParameters): string => {\n const { cashAssemblySource, variables, templateVariables, templateScripts, evaluationDecodeMode } = parameters;\n\n const compilationResult = compileCashAssemblySourceToBytes({\n cashAssemblySource,\n variables,\n templateVariables,\n templateScripts,\n });\n\n return decodeCompiledCashAssemblyEvaluation(compilationResult, evaluationDecodeMode);\n};\n\n/**\n * Compiles CashAssembly text. WalletData names come from parseScript. `$()` evaluations in text\n * are found by scanning the string and matching parentheses.\n *\n * When `cashAssemblyText` contains `$()`, each non empty evaluation is compiled and\n * replaced in place. Empty `$()` is copied through. Surrounding text is kept. Evaluation drops\n * push opcodes and keeps the stack payload.\n *\n * When `cashAssemblyText` contains no `$()` at all, the entire string is compiled as CashAssembly.\n * Push opcodes from `<...>` remain. Pass a template script id such as `scriptA` or\n * concatenated ids such as `scriptA scriptB`.\n *\n * Required WalletData names come from {@link collectVariablesUsingParseScript}.\n *\n * @param {CompileCashAssemblyStringParameters} parameters - Parameters for compiling the CashAssembly string.\n * @returns {string} - Compiled text with evaluations replaced, or decoded bytecode when the whole string is compiled as CashAssembly.\n * @throws {@link CashAssemblyRequiredVariableMissingError} - When a required variable is not present in the variables map.\n * @throws {@link CashAssemblyPrimitiveMethodMissingError} - When a supported primitive hint has an unknown method.\n * @throws {@link CashAssemblyPrimitiveVariableMissingError} - When a supported primitive method is missing its runtime value.\n * @throws {@link CashAssemblyUnsupportedValueTypeError} - When a primitive method return type cannot be embedded as bytes.\n * @throws {@link CashAssemblyNumberNotSafeIntegerError} - When a number variable is not a safe integer.\n * @throws {@link CashAssemblyVmNumberDecodeError} - When `evaluationDecodeMode` is `bigint` and compiled bytes are not a VM number.\n * @throws {@link CashAssemblyIdentifierCollisionError} - When one identifier matches two resolution types.\n * @throws {@link CashAssemblyCompilationFailedError} - When Libauth compilation fails.\n * @throws {@link CashAssemblyEvaluationUnclosedError} - When an evaluation never closes.\n * @throws {@link CashAssemblyQuotedLiteralUnclosedError} - When a quoted literal never closes.\n * @throws {@link CashAssemblyBlockCommentUnclosedError} - When a block comment never closes.\n */\nexport const compileCashAssemblyString = (parameters: CompileCashAssemblyStringParameters): string => {\n const { cashAssemblyText, variables, evaluationDecodeMode = 'utf8', templateVariables, templateScripts } = parameters;\n\n // Scan once so empty `$()` still copies text around `$()` instead of compiling as CashAssembly.\n const scannedEvaluations = scanCashAssemblyEvaluations(cashAssemblyText);\n\n if (scannedEvaluations.length === 0) {\n return compileCashAssemblySourceToDecodedText({\n cashAssemblySource: cashAssemblyText,\n variables,\n templateVariables,\n templateScripts,\n evaluationDecodeMode,\n });\n }\n\n // Copy text outside `$()` and compile each `$()`.\n let textWithCompiledEvaluations = '';\n\n // Start of the next original text slice in cashAssemblyText. Gaps between evaluations must stay intact.\n let nextTextStartIndex = 0;\n\n // When every `$()` is empty, return cashAssemblyText so the original text is unchanged.\n let hasCompiledNonEmptyEvaluation = false;\n\n for (const scannedEvaluation of scannedEvaluations) {\n textWithCompiledEvaluations += cashAssemblyText.slice(nextTextStartIndex, scannedEvaluation.startIndex);\n\n // Empty `$()` has no contents to compile.\n if (scannedEvaluation.evaluationText === EMPTY_CASHASSEMBLY_EVALUATION) {\n textWithCompiledEvaluations += scannedEvaluation.evaluationText;\n } else {\n hasCompiledNonEmptyEvaluation = true;\n textWithCompiledEvaluations += compileCashAssemblySourceToDecodedText({\n cashAssemblySource: scannedEvaluation.evaluationText,\n variables,\n templateVariables,\n templateScripts,\n evaluationDecodeMode,\n });\n }\n\n // Advance past this `$()` so nested evaluations inside it are not copied again.\n nextTextStartIndex = scannedEvaluation.closeIndex + 1;\n }\n\n // Copy text after the last `$()` so the suffix is kept.\n textWithCompiledEvaluations += cashAssemblyText.slice(nextTextStartIndex);\n\n if (hasCompiledNonEmptyEvaluation === false) {\n return cashAssemblyText;\n }\n\n return textWithCompiledEvaluations;\n};\n"],"mappings":"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"}