@solana/transaction-confirmation 3.0.0 → 3.0.1
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.
- package/dist/index.browser.cjs +3 -1
- package/dist/index.browser.cjs.map +1 -1
- package/dist/index.browser.mjs +3 -1
- package/dist/index.browser.mjs.map +1 -1
- package/dist/index.native.mjs +3 -1
- package/dist/index.native.mjs.map +1 -1
- package/dist/index.node.cjs +3 -1
- package/dist/index.node.cjs.map +1 -1
- package/dist/index.node.mjs +3 -1
- package/dist/index.node.mjs.map +1 -1
- package/package.json +11 -11
package/dist/index.browser.cjs
CHANGED
|
@@ -166,8 +166,10 @@ function createRecentSignatureConfirmationPromiseFactory({
|
|
|
166
166
|
const signatureStatusLookupPromise = (async () => {
|
|
167
167
|
const { value: signatureStatusResults } = await rpc.getSignatureStatuses([signature]).send({ abortSignal: abortController.signal });
|
|
168
168
|
const signatureStatus = signatureStatusResults[0];
|
|
169
|
-
if (signatureStatus
|
|
169
|
+
if (signatureStatus?.confirmationStatus && rpcTypes.commitmentComparator(signatureStatus.confirmationStatus, commitment) >= 0) {
|
|
170
170
|
return;
|
|
171
|
+
} else if (signatureStatus?.err) {
|
|
172
|
+
throw errors.getSolanaErrorFromTransactionError(signatureStatus.err);
|
|
171
173
|
} else {
|
|
172
174
|
await new Promise(() => {
|
|
173
175
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../event-target-impl/src/index.browser.ts","../src/confirmation-strategy-blockheight.ts","../src/confirmation-strategy-nonce.ts","../src/confirmation-strategy-recent-signature.ts","../src/confirmation-strategy-timeout.ts","../src/confirmation-strategy-racer.ts","../src/waiters.ts"],"names":["AbortController","SolanaError","SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED","getBase58Decoder","getBase64Encoder","SOLANA_ERROR__INVALID_NONCE","SOLANA_ERROR__NONCE_ACCOUNT_NOT_FOUND","safeRace","getSolanaErrorFromTransactionError","commitmentComparator","getSignatureFromTransaction","getTimeoutPromise"],"mappings":"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","file":"index.browser.cjs","sourcesContent":["export const AbortController = globalThis.AbortController;\nexport const EventTarget = globalThis.EventTarget;\n","import { SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED, SolanaError } from '@solana/errors';\nimport { AbortController } from '@solana/event-target-impl';\nimport type { GetEpochInfoApi, Rpc } from '@solana/rpc';\nimport type { RpcSubscriptions, SlotNotificationsApi } from '@solana/rpc-subscriptions';\nimport type { Commitment } from '@solana/rpc-types';\n\ntype GetBlockHeightExceedencePromiseFn = (config: {\n abortSignal: AbortSignal;\n /**\n * Fetch the block height as of the highest slot that has reached this level of commitment.\n *\n * @defaultValue Whichever default is applied by the underlying {@link RpcApi} in use. For\n * example, when using an API created by a `createSolanaRpc*()` helper, the default commitment\n * is `\"confirmed\"` unless configured otherwise. Unmitigated by an API layer on the client, the\n * default commitment applied by the server is `\"finalized\"`.\n */\n commitment?: Commitment;\n /** The block height after which to reject the promise */\n lastValidBlockHeight: bigint;\n}) => Promise<void>;\n\ntype CreateBlockHeightExceedencePromiseFactoryConfig<TCluster> = {\n rpc: Rpc<GetEpochInfoApi> & { '~cluster'?: TCluster };\n rpcSubscriptions: RpcSubscriptions<SlotNotificationsApi> & { '~cluster'?: TCluster };\n};\n\n/**\n * Creates a promise that throws when the network progresses past the block height after which the\n * supplied blockhash is considered expired for use as a transaction lifetime specifier.\n *\n * When a transaction's lifetime is tied to a blockhash, that transaction can be landed on the\n * network until that blockhash expires. All blockhashes have a block height after which they are\n * considered to have expired.\n *\n * @param config\n *\n * @example\n * ```ts\n * import { isSolanaError, SolanaError } from '@solana/errors';\n * import { createBlockHeightExceedencePromiseFactory } from '@solana/transaction-confirmation';\n *\n * const getBlockHeightExceedencePromise = createBlockHeightExceedencePromiseFactory({\n * rpc,\n * rpcSubscriptions,\n * });\n * try {\n * await getBlockHeightExceedencePromise({ lastValidBlockHeight });\n * } catch (e) {\n * if (isSolanaError(e, SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED)) {\n * console.error(\n * `The block height of the network has exceeded ${e.context.lastValidBlockHeight}. ` +\n * `It is now ${e.context.currentBlockHeight}`,\n * );\n * // Re-sign and retry the transaction.\n * return;\n * }\n * throw e;\n * }\n * ```\n */\nexport function createBlockHeightExceedencePromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateBlockHeightExceedencePromiseFactoryConfig<'devnet'>): GetBlockHeightExceedencePromiseFn;\nexport function createBlockHeightExceedencePromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateBlockHeightExceedencePromiseFactoryConfig<'testnet'>): GetBlockHeightExceedencePromiseFn;\nexport function createBlockHeightExceedencePromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateBlockHeightExceedencePromiseFactoryConfig<'mainnet'>): GetBlockHeightExceedencePromiseFn;\nexport function createBlockHeightExceedencePromiseFactory<\n TCluster extends 'devnet' | 'mainnet' | 'testnet' | void = void,\n>({\n rpc,\n rpcSubscriptions,\n}: CreateBlockHeightExceedencePromiseFactoryConfig<TCluster>): GetBlockHeightExceedencePromiseFn {\n return async function getBlockHeightExceedencePromise({\n abortSignal: callerAbortSignal,\n commitment,\n lastValidBlockHeight,\n }): Promise<never> {\n callerAbortSignal.throwIfAborted();\n const abortController = new AbortController();\n const handleAbort = () => {\n abortController.abort();\n };\n callerAbortSignal.addEventListener('abort', handleAbort, { signal: abortController.signal });\n async function getBlockHeightAndDifferenceBetweenSlotHeightAndBlockHeight() {\n const { absoluteSlot, blockHeight } = await rpc\n .getEpochInfo({ commitment })\n .send({ abortSignal: abortController.signal });\n return {\n blockHeight,\n differenceBetweenSlotHeightAndBlockHeight: absoluteSlot - blockHeight,\n };\n }\n try {\n const [slotNotifications, { blockHeight: initialBlockHeight, differenceBetweenSlotHeightAndBlockHeight }] =\n await Promise.all([\n rpcSubscriptions.slotNotifications().subscribe({ abortSignal: abortController.signal }),\n getBlockHeightAndDifferenceBetweenSlotHeightAndBlockHeight(),\n ]);\n callerAbortSignal.throwIfAborted();\n let currentBlockHeight = initialBlockHeight;\n if (currentBlockHeight <= lastValidBlockHeight) {\n let lastKnownDifferenceBetweenSlotHeightAndBlockHeight = differenceBetweenSlotHeightAndBlockHeight;\n for await (const slotNotification of slotNotifications) {\n const { slot } = slotNotification;\n if (slot - lastKnownDifferenceBetweenSlotHeightAndBlockHeight > lastValidBlockHeight) {\n // Before making a final decision, recheck the actual block height.\n const {\n blockHeight: recheckedBlockHeight,\n differenceBetweenSlotHeightAndBlockHeight: currentDifferenceBetweenSlotHeightAndBlockHeight,\n } = await getBlockHeightAndDifferenceBetweenSlotHeightAndBlockHeight();\n currentBlockHeight = recheckedBlockHeight;\n if (currentBlockHeight > lastValidBlockHeight) {\n // Verified; the block height has been exceeded.\n break;\n } else {\n // The block height has not been exceeded, which implies that the\n // difference between the slot height and the block height has grown\n // (ie. some blocks have been skipped since we started). Recalibrate the\n // difference and keep waiting.\n lastKnownDifferenceBetweenSlotHeightAndBlockHeight =\n currentDifferenceBetweenSlotHeightAndBlockHeight;\n }\n }\n }\n }\n callerAbortSignal.throwIfAborted();\n throw new SolanaError(SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED, {\n currentBlockHeight,\n lastValidBlockHeight,\n });\n } finally {\n abortController.abort();\n }\n };\n}\n","import type { Address } from '@solana/addresses';\nimport { getBase58Decoder, getBase64Encoder } from '@solana/codecs-strings';\nimport { SOLANA_ERROR__INVALID_NONCE, SOLANA_ERROR__NONCE_ACCOUNT_NOT_FOUND, SolanaError } from '@solana/errors';\nimport { AbortController } from '@solana/event-target-impl';\nimport { safeRace } from '@solana/promises';\nimport type { GetAccountInfoApi, Rpc } from '@solana/rpc';\nimport type { AccountNotificationsApi, RpcSubscriptions } from '@solana/rpc-subscriptions';\nimport type { Base64EncodedDataResponse, Commitment } from '@solana/rpc-types';\nimport { Nonce } from '@solana/transaction-messages';\n\ntype GetNonceInvalidationPromiseFn = (config: {\n abortSignal: AbortSignal;\n /**\n * Fetch the nonce account details as of the highest slot that has reached this level of\n * commitment.\n */\n commitment: Commitment;\n /**\n * The value of the nonce that we would expect to see in the nonce account in order for any\n * transaction with that nonce-based lifetime to be considered valid.\n */\n currentNonceValue: Nonce;\n /** The address of the account in which the currently-valid nonce value is stored */\n nonceAccountAddress: Address;\n}) => Promise<void>;\n\ntype CreateNonceInvalidationPromiseFactoryConfig<TCluster> = {\n rpc: Rpc<GetAccountInfoApi> & { '~cluster'?: TCluster };\n rpcSubscriptions: RpcSubscriptions<AccountNotificationsApi> & { '~cluster'?: TCluster };\n};\n\nconst NONCE_VALUE_OFFSET =\n 4 + // version(u32)\n 4 + // state(u32)\n 32; // nonce authority(pubkey)\n// Then comes the nonce value.\n\n/**\n * Creates a promise that throws when the value stored in a nonce account is not the expected one.\n *\n * When a transaction's lifetime is tied to the value stored in a nonce account, that transaction\n * can be landed on the network until the nonce is advanced to a new value.\n *\n * @param config\n *\n * @example\n * ```ts\n * import { isSolanaError, SolanaError } from '@solana/errors';\n * import { createNonceInvalidationPromiseFactory } from '@solana/transaction-confirmation';\n *\n * const getNonceInvalidationPromise = createNonceInvalidationPromiseFactory({\n * rpc,\n * rpcSubscriptions,\n * });\n * try {\n * await getNonceInvalidationPromise({\n * currentNonceValue,\n * nonceAccountAddress,\n * });\n * } catch (e) {\n * if (isSolanaError(e, SOLANA_ERROR__NONCE_INVALID)) {\n * console.error(`The nonce has advanced to ${e.context.actualNonceValue}`);\n * // Re-sign and retry the transaction.\n * return;\n * } else if (isSolanaError(e, SOLANA_ERROR__NONCE_ACCOUNT_NOT_FOUND)) {\n * console.error(`No nonce account was found at ${nonceAccountAddress}`);\n * }\n * throw e;\n * }\n * ```\n */\nexport function createNonceInvalidationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateNonceInvalidationPromiseFactoryConfig<'devnet'>): GetNonceInvalidationPromiseFn;\nexport function createNonceInvalidationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateNonceInvalidationPromiseFactoryConfig<'testnet'>): GetNonceInvalidationPromiseFn;\nexport function createNonceInvalidationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateNonceInvalidationPromiseFactoryConfig<'mainnet'>): GetNonceInvalidationPromiseFn;\nexport function createNonceInvalidationPromiseFactory<TCluster extends 'devnet' | 'mainnet' | 'testnet' | void = void>({\n rpc,\n rpcSubscriptions,\n}: CreateNonceInvalidationPromiseFactoryConfig<TCluster>): GetNonceInvalidationPromiseFn {\n return async function getNonceInvalidationPromise({\n abortSignal: callerAbortSignal,\n commitment,\n currentNonceValue: expectedNonceValue,\n nonceAccountAddress,\n }) {\n const abortController = new AbortController();\n function handleAbort() {\n abortController.abort();\n }\n callerAbortSignal.addEventListener('abort', handleAbort, { signal: abortController.signal });\n /**\n * STEP 1: Set up a subscription for nonce account changes.\n */\n const accountNotifications = await rpcSubscriptions\n .accountNotifications(nonceAccountAddress, { commitment, encoding: 'base64' })\n .subscribe({ abortSignal: abortController.signal });\n const base58Decoder = getBase58Decoder();\n const base64Encoder = getBase64Encoder();\n function getNonceFromAccountData([base64EncodedBytes]: Base64EncodedDataResponse): Nonce {\n const data = base64Encoder.encode(base64EncodedBytes);\n const nonceValueBytes = data.slice(NONCE_VALUE_OFFSET, NONCE_VALUE_OFFSET + 32);\n return base58Decoder.decode(nonceValueBytes) as Nonce;\n }\n const nonceAccountDidAdvancePromise = (async () => {\n for await (const accountNotification of accountNotifications) {\n const nonceValue = getNonceFromAccountData(accountNotification.value.data);\n if (nonceValue !== expectedNonceValue) {\n throw new SolanaError(SOLANA_ERROR__INVALID_NONCE, {\n actualNonceValue: nonceValue,\n expectedNonceValue,\n });\n }\n }\n })();\n /**\n * STEP 2: Having subscribed for updates, make a one-shot request for the current nonce\n * value to check if it has already been advanced.\n */\n const nonceIsAlreadyInvalidPromise = (async () => {\n const { value: nonceAccount } = await rpc\n .getAccountInfo(nonceAccountAddress, {\n commitment,\n dataSlice: { length: 32, offset: NONCE_VALUE_OFFSET },\n encoding: 'base58',\n })\n .send({ abortSignal: abortController.signal });\n if (!nonceAccount) {\n throw new SolanaError(SOLANA_ERROR__NONCE_ACCOUNT_NOT_FOUND, {\n nonceAccountAddress,\n });\n }\n const nonceValue =\n // This works because we asked for the exact slice of data representing the nonce\n // value, and furthermore asked for it in `base58` encoding.\n nonceAccount.data[0] as unknown as Nonce;\n if (nonceValue !== expectedNonceValue) {\n throw new SolanaError(SOLANA_ERROR__INVALID_NONCE, {\n actualNonceValue: nonceValue,\n expectedNonceValue,\n });\n } else {\n await new Promise(() => {\n /* never resolve */\n });\n }\n })();\n try {\n return await safeRace([nonceAccountDidAdvancePromise, nonceIsAlreadyInvalidPromise]);\n } finally {\n abortController.abort();\n }\n };\n}\n","import { getSolanaErrorFromTransactionError } from '@solana/errors';\nimport { AbortController } from '@solana/event-target-impl';\nimport type { Signature } from '@solana/keys';\nimport { safeRace } from '@solana/promises';\nimport type { GetSignatureStatusesApi, Rpc } from '@solana/rpc';\nimport type { RpcSubscriptions, SignatureNotificationsApi } from '@solana/rpc-subscriptions';\nimport { type Commitment, commitmentComparator } from '@solana/rpc-types';\n\ntype GetRecentSignatureConfirmationPromiseFn = (config: {\n abortSignal: AbortSignal;\n /**\n * The level of commitment the transaction must have achieved in order for the promise to\n * resolve.\n */\n commitment: Commitment;\n /**\n * A 64 byte Ed25519 signature, encoded as a base-58 string, that uniquely identifies a\n * transaction by virtue of being the first or only signature in its list of signatures.\n */\n signature: Signature;\n}) => Promise<void>;\n\ntype CreateRecentSignatureConfirmationPromiseFactoryConfig<TCluster> = {\n rpc: Rpc<GetSignatureStatusesApi> & { '~cluster'?: TCluster };\n rpcSubscriptions: RpcSubscriptions<SignatureNotificationsApi> & { '~cluster'?: TCluster };\n};\n\n/**\n * Creates a promise that resolves when a recently-landed transaction achieves the target\n * confirmation commitment, and throws when the transaction fails with an error.\n *\n * The status of recently-landed transactions is available in the network's status cache. This\n * confirmation strategy will only yield a result if the signature is still in the status cache. To\n * fetch the status of transactions older than those available in the status cache, use the\n * {@link GetSignatureStatusesApi.getSignatureStatuses} method setting the\n * `searchTransactionHistory` configuration param to `true`.\n *\n * @param config\n *\n * @example\n * ```ts\n * import { createRecentSignatureConfirmationPromiseFactory } from '@solana/transaction-confirmation';\n *\n * const getRecentSignatureConfirmationPromise = createRecentSignatureConfirmationPromiseFactory({\n * rpc,\n * rpcSubscriptions,\n * });\n * try {\n * await getRecentSignatureConfirmationPromise({\n * commitment,\n * signature,\n * });\n * console.log(`The transaction with signature \\`${signature}\\` has achieved a commitment level of \\`${commitment}\\``);\n * } catch (e) {\n * console.error(`The transaction with signature \\`${signature}\\` failed`, e.cause);\n * throw e;\n * }\n * ```\n */\nexport function createRecentSignatureConfirmationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateRecentSignatureConfirmationPromiseFactoryConfig<'devnet'>): GetRecentSignatureConfirmationPromiseFn;\nexport function createRecentSignatureConfirmationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateRecentSignatureConfirmationPromiseFactoryConfig<'testnet'>): GetRecentSignatureConfirmationPromiseFn;\nexport function createRecentSignatureConfirmationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateRecentSignatureConfirmationPromiseFactoryConfig<'mainnet'>): GetRecentSignatureConfirmationPromiseFn;\nexport function createRecentSignatureConfirmationPromiseFactory<\n TCluster extends 'devnet' | 'mainnet' | 'testnet' | void = void,\n>({\n rpc,\n rpcSubscriptions,\n}: CreateRecentSignatureConfirmationPromiseFactoryConfig<TCluster>): GetRecentSignatureConfirmationPromiseFn {\n return async function getRecentSignatureConfirmationPromise({\n abortSignal: callerAbortSignal,\n commitment,\n signature,\n }) {\n const abortController = new AbortController();\n function handleAbort() {\n abortController.abort();\n }\n callerAbortSignal.addEventListener('abort', handleAbort, { signal: abortController.signal });\n /**\n * STEP 1: Set up a subscription for status changes to a signature.\n */\n const signatureStatusNotifications = await rpcSubscriptions\n .signatureNotifications(signature, { commitment })\n .subscribe({ abortSignal: abortController.signal });\n const signatureDidCommitPromise = (async () => {\n for await (const signatureStatusNotification of signatureStatusNotifications) {\n if (signatureStatusNotification.value.err) {\n throw getSolanaErrorFromTransactionError(signatureStatusNotification.value.err);\n } else {\n return;\n }\n }\n })();\n /**\n * STEP 2: Having subscribed for updates, make a one-shot request for the current status.\n * This will only yield a result if the signature is still in the status cache.\n */\n const signatureStatusLookupPromise = (async () => {\n const { value: signatureStatusResults } = await rpc\n .getSignatureStatuses([signature])\n .send({ abortSignal: abortController.signal });\n const signatureStatus = signatureStatusResults[0];\n if (\n signatureStatus &&\n signatureStatus.confirmationStatus &&\n commitmentComparator(signatureStatus.confirmationStatus, commitment) >= 0\n ) {\n return;\n } else {\n await new Promise(() => {\n /* never resolve */\n });\n }\n })();\n try {\n return await safeRace([signatureDidCommitPromise, signatureStatusLookupPromise]);\n } finally {\n abortController.abort();\n }\n };\n}\n","import type { Commitment } from '@solana/rpc-types';\n\ntype Config = Readonly<{\n abortSignal: AbortSignal;\n /**\n * The timeout promise will throw after 30 seconds when the commitment is `processed`, and 60\n * seconds otherwise.\n */\n commitment: Commitment;\n}>;\n\n/**\n * When no other heuristic exists to infer that a transaction has expired, you can use this promise\n * factory with a commitment level. It throws after 30 seconds when the commitment is `processed`,\n * and 60 seconds otherwise. You would typically race this with another confirmation strategy.\n *\n * @param config\n *\n * @example\n * ```ts\n * import { safeRace } from '@solana/promises';\n * import { getTimeoutPromise } from '@solana/transaction-confirmation';\n *\n * try {\n * await safeRace([getCustomTransactionConfirmationPromise(/* ... *\\/), getTimeoutPromise({ commitment })]);\n * } catch (e) {\n * if (e instanceof DOMException && e.name === 'TimeoutError') {\n * console.log('Could not confirm transaction after a timeout');\n * }\n * throw e;\n * }\n * ```\n */\nexport async function getTimeoutPromise({ abortSignal: callerAbortSignal, commitment }: Config) {\n return await new Promise((_, reject) => {\n const handleAbort = (e: AbortSignalEventMap['abort']) => {\n clearTimeout(timeoutId);\n const abortError = new DOMException((e.target as AbortSignal).reason, 'AbortError');\n reject(abortError);\n };\n callerAbortSignal.addEventListener('abort', handleAbort);\n const timeoutMs = commitment === 'processed' ? 30_000 : 60_000;\n const startMs = performance.now();\n const timeoutId =\n // We use `setTimeout` instead of `AbortSignal.timeout()` because we want to measure\n // elapsed time instead of active time.\n // See https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal/timeout_static\n setTimeout(() => {\n const elapsedMs = performance.now() - startMs;\n reject(new DOMException(`Timeout elapsed after ${elapsedMs} ms`, 'TimeoutError'));\n }, timeoutMs);\n });\n}\n","import { AbortController } from '@solana/event-target-impl';\nimport type { Signature } from '@solana/keys';\nimport { safeRace } from '@solana/promises';\nimport type { Commitment } from '@solana/rpc-types';\n\nimport { createRecentSignatureConfirmationPromiseFactory } from './confirmation-strategy-recent-signature';\n\nexport interface BaseTransactionConfirmationStrategyConfig {\n abortSignal?: AbortSignal;\n commitment: Commitment;\n getRecentSignatureConfirmationPromise: ReturnType<typeof createRecentSignatureConfirmationPromiseFactory>;\n}\n\ntype WithNonNullableAbortSignal<T> = Omit<T, 'abortSignal'> & Readonly<{ abortSignal: AbortSignal }>;\n\nexport async function raceStrategies<TConfig extends BaseTransactionConfirmationStrategyConfig>(\n signature: Signature,\n config: TConfig,\n getSpecificStrategiesForRace: (config: WithNonNullableAbortSignal<TConfig>) => readonly Promise<unknown>[],\n) {\n const { abortSignal: callerAbortSignal, commitment, getRecentSignatureConfirmationPromise } = config;\n callerAbortSignal?.throwIfAborted();\n const abortController = new AbortController();\n if (callerAbortSignal) {\n const handleAbort = () => {\n abortController.abort();\n };\n callerAbortSignal.addEventListener('abort', handleAbort, { signal: abortController.signal });\n }\n try {\n const specificStrategies = getSpecificStrategiesForRace({\n ...config,\n abortSignal: abortController.signal,\n });\n return await safeRace([\n getRecentSignatureConfirmationPromise({\n abortSignal: abortController.signal,\n commitment,\n signature,\n }),\n ...specificStrategies,\n ]);\n } finally {\n abortController.abort();\n }\n}\n","import { Signature } from '@solana/keys';\nimport {\n getSignatureFromTransaction,\n Transaction,\n TransactionWithBlockhashLifetime,\n TransactionWithDurableNonceLifetime,\n} from '@solana/transactions';\n\nimport { createBlockHeightExceedencePromiseFactory } from './confirmation-strategy-blockheight';\nimport { createNonceInvalidationPromiseFactory } from './confirmation-strategy-nonce';\nimport { BaseTransactionConfirmationStrategyConfig, raceStrategies } from './confirmation-strategy-racer';\nimport { getTimeoutPromise } from './confirmation-strategy-timeout';\n\nexport type TransactionWithLastValidBlockHeight = Omit<TransactionWithBlockhashLifetime, 'lifetimeConstraint'> & {\n lifetimeConstraint: Omit<TransactionWithBlockhashLifetime['lifetimeConstraint'], 'blockhash'>;\n};\n\ninterface WaitForDurableNonceTransactionConfirmationConfig extends BaseTransactionConfirmationStrategyConfig {\n getNonceInvalidationPromise: ReturnType<typeof createNonceInvalidationPromiseFactory>;\n transaction: Readonly<Transaction & TransactionWithDurableNonceLifetime>;\n}\n\ninterface WaitForRecentTransactionWithBlockhashLifetimeConfirmationConfig\n extends BaseTransactionConfirmationStrategyConfig {\n getBlockHeightExceedencePromise: ReturnType<typeof createBlockHeightExceedencePromiseFactory>;\n transaction: Readonly<Transaction & TransactionWithLastValidBlockHeight>;\n}\n\ninterface WaitForRecentTransactionWithTimeBasedLifetimeConfirmationConfig\n extends BaseTransactionConfirmationStrategyConfig {\n getTimeoutPromise: typeof getTimeoutPromise;\n /**\n * A 64 byte Ed25519 signature, encoded as a base-58 string, that uniquely identifies a\n * transaction by virtue of being the first or only signature in its list of signatures.\n */\n signature: Signature;\n}\n\n/**\n * Supply your own confirmation implementations to this function to create a custom nonce\n * transaction confirmation strategy.\n *\n * @example\n * ```ts\n * import { waitForDurableNonceTransactionConfirmation } from '@solana/transaction-confirmation';\n *\n * try {\n * await waitForDurableNonceTransactionConfirmation({\n * getNonceInvalidationPromise({ abortSignal, commitment, currentNonceValue, nonceAccountAddress }) {\n * // Return a promise that rejects when a nonce becomes invalid.\n * },\n * getRecentSignatureConfirmationPromise({ abortSignal, commitment, signature }) {\n * // Return a promise that resolves when a transaction achieves confirmation\n * },\n * });\n * } catch (e) {\n * // Handle errors.\n * }\n * ```\n */\nexport async function waitForDurableNonceTransactionConfirmation(\n config: WaitForDurableNonceTransactionConfirmationConfig,\n): Promise<void> {\n await raceStrategies(\n getSignatureFromTransaction(config.transaction),\n config,\n function getSpecificStrategiesForRace({ abortSignal, commitment, getNonceInvalidationPromise, transaction }) {\n return [\n getNonceInvalidationPromise({\n abortSignal,\n commitment,\n currentNonceValue: transaction.lifetimeConstraint.nonce,\n nonceAccountAddress: transaction.lifetimeConstraint.nonceAccountAddress,\n }),\n ];\n },\n );\n}\n\n/**\n * Supply your own confirmation implementations to this function to create a custom confirmation\n * strategy for recently-landed transactions.\n *\n * @example\n * ```ts\n * import { waitForRecentTransactionConfirmation } from '@solana/transaction-confirmation';\n *\n * try {\n * await waitForRecentTransactionConfirmation({\n * getBlockHeightExceedencePromise({ abortSignal, commitment, lastValidBlockHeight }) {\n * // Return a promise that rejects when the blockhash's block height has been exceeded\n * },\n * getRecentSignatureConfirmationPromise({ abortSignal, commitment, signature }) {\n * // Return a promise that resolves when a transaction achieves confirmation\n * },\n * });\n * } catch (e) {\n * // Handle errors.\n * }\n * ```\n */\nexport async function waitForRecentTransactionConfirmation(\n config: WaitForRecentTransactionWithBlockhashLifetimeConfirmationConfig,\n): Promise<void> {\n await raceStrategies(\n getSignatureFromTransaction(config.transaction),\n config,\n function getSpecificStrategiesForRace({\n abortSignal,\n commitment,\n getBlockHeightExceedencePromise,\n transaction,\n }) {\n return [\n getBlockHeightExceedencePromise({\n abortSignal,\n commitment,\n lastValidBlockHeight: transaction.lifetimeConstraint.lastValidBlockHeight,\n }),\n ];\n },\n );\n}\n\n/** @deprecated */\nexport async function waitForRecentTransactionConfirmationUntilTimeout(\n config: WaitForRecentTransactionWithTimeBasedLifetimeConfirmationConfig,\n): Promise<void> {\n await raceStrategies(\n config.signature,\n config,\n function getSpecificStrategiesForRace({ abortSignal, commitment, getTimeoutPromise }) {\n return [\n getTimeoutPromise({\n abortSignal,\n commitment,\n }),\n ];\n },\n );\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../event-target-impl/src/index.browser.ts","../src/confirmation-strategy-blockheight.ts","../src/confirmation-strategy-nonce.ts","../src/confirmation-strategy-recent-signature.ts","../src/confirmation-strategy-timeout.ts","../src/confirmation-strategy-racer.ts","../src/waiters.ts"],"names":["AbortController","SolanaError","SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED","getBase58Decoder","getBase64Encoder","SOLANA_ERROR__INVALID_NONCE","SOLANA_ERROR__NONCE_ACCOUNT_NOT_FOUND","safeRace","getSolanaErrorFromTransactionError","commitmentComparator","getSignatureFromTransaction","getTimeoutPromise"],"mappings":";;;;;;;;;;;AAAO,IAAMA,IAAkB,UAAW,CAAA,eAAA;;;ACwEnC,SAAS,yCAEd,CAAA;AAAA,EACE,GAAA;AAAA,EACA;AACJ,CAAiG,EAAA;AAC7F,EAAA,OAAO,eAAe,+BAAgC,CAAA;AAAA,IAClD,WAAa,EAAA,iBAAA;AAAA,IACb,UAAA;AAAA,IACA;AAAA,GACe,EAAA;AACf,IAAA,iBAAA,CAAkB,cAAe,EAAA;AACjC,IAAM,MAAA,eAAA,GAAkB,IAAI,CAAgB,EAAA;AAC5C,IAAA,MAAM,cAAc,MAAM;AACtB,MAAA,eAAA,CAAgB,KAAM,EAAA;AAAA,KAC1B;AACA,IAAA,iBAAA,CAAkB,iBAAiB,OAAS,EAAA,WAAA,EAAa,EAAE,MAAQ,EAAA,eAAA,CAAgB,QAAQ,CAAA;AAC3F,IAAA,eAAe,0DAA6D,GAAA;AACxE,MAAA,MAAM,EAAE,YAAc,EAAA,WAAA,EAAgB,GAAA,MAAM,IACvC,YAAa,CAAA,EAAE,UAAW,EAAC,EAC3B,IAAK,CAAA,EAAE,WAAa,EAAA,eAAA,CAAgB,QAAQ,CAAA;AACjD,MAAO,OAAA;AAAA,QACH,WAAA;AAAA,QACA,2CAA2C,YAAe,GAAA;AAAA,OAC9D;AAAA;AAEJ,IAAI,IAAA;AACA,MAAM,MAAA,CAAC,iBAAmB,EAAA,EAAE,WAAa,EAAA,kBAAA,EAAoB,2CAA2C,CAAA,GACpG,MAAM,OAAA,CAAQ,GAAI,CAAA;AAAA,QACd,gBAAA,CAAiB,mBAAoB,CAAA,SAAA,CAAU,EAAE,WAAa,EAAA,eAAA,CAAgB,QAAQ,CAAA;AAAA,QACtF,0DAA2D;AAAA,OAC9D,CAAA;AACL,MAAA,iBAAA,CAAkB,cAAe,EAAA;AACjC,MAAA,IAAI,kBAAqB,GAAA,kBAAA;AACzB,MAAA,IAAI,sBAAsB,oBAAsB,EAAA;AAC5C,QAAA,IAAI,kDAAqD,GAAA,yCAAA;AACzD,QAAA,WAAA,MAAiB,oBAAoB,iBAAmB,EAAA;AACpD,UAAM,MAAA,EAAE,MAAS,GAAA,gBAAA;AACjB,UAAI,IAAA,IAAA,GAAO,qDAAqD,oBAAsB,EAAA;AAElF,YAAM,MAAA;AAAA,cACF,WAAa,EAAA,oBAAA;AAAA,cACb,yCAA2C,EAAA;AAAA,aAC/C,GAAI,MAAM,0DAA2D,EAAA;AACrE,YAAqB,kBAAA,GAAA,oBAAA;AACrB,YAAA,IAAI,qBAAqB,oBAAsB,EAAA;AAE3C,cAAA;AAAA,aACG,MAAA;AAKH,cACI,kDAAA,GAAA,gDAAA;AAAA;AACR;AACJ;AACJ;AAEJ,MAAA,iBAAA,CAAkB,cAAe,EAAA;AACjC,MAAM,MAAA,IAAIC,mBAAYC,0CAAqC,EAAA;AAAA,QACvD,kBAAA;AAAA,QACA;AAAA,OACH,CAAA;AAAA,KACH,SAAA;AACE,MAAA,eAAA,CAAgB,KAAM,EAAA;AAAA;AAC1B,GACJ;AACJ;AC7GA,IAAM,kBACF,GAAA,CAAA;AACA,CAAA;AACA,EAAA;AAiDG,SAAS,qCAAuG,CAAA;AAAA,EACnH,GAAA;AAAA,EACA;AACJ,CAAyF,EAAA;AACrF,EAAA,OAAO,eAAe,2BAA4B,CAAA;AAAA,IAC9C,WAAa,EAAA,iBAAA;AAAA,IACb,UAAA;AAAA,IACA,iBAAmB,EAAA,kBAAA;AAAA,IACnB;AAAA,GACD,EAAA;AACC,IAAM,MAAA,eAAA,GAAkB,IAAI,CAAgB,EAAA;AAC5C,IAAA,SAAS,WAAc,GAAA;AACnB,MAAA,eAAA,CAAgB,KAAM,EAAA;AAAA;AAE1B,IAAA,iBAAA,CAAkB,iBAAiB,OAAS,EAAA,WAAA,EAAa,EAAE,MAAQ,EAAA,eAAA,CAAgB,QAAQ,CAAA;AAI3F,IAAA,MAAM,uBAAuB,MAAM,gBAAA,CAC9B,oBAAqB,CAAA,mBAAA,EAAqB,EAAE,UAAY,EAAA,QAAA,EAAU,QAAS,EAAC,EAC5E,SAAU,CAAA,EAAE,WAAa,EAAA,eAAA,CAAgB,QAAQ,CAAA;AACtD,IAAA,MAAM,gBAAgBC,8BAAiB,EAAA;AACvC,IAAA,MAAM,gBAAgBC,8BAAiB,EAAA;AACvC,IAAS,SAAA,uBAAA,CAAwB,CAAC,kBAAkB,CAAqC,EAAA;AACrF,MAAM,MAAA,IAAA,GAAO,aAAc,CAAA,MAAA,CAAO,kBAAkB,CAAA;AACpD,MAAA,MAAM,eAAkB,GAAA,IAAA,CAAK,KAAM,CAAA,kBAAA,EAAoB,qBAAqB,EAAE,CAAA;AAC9E,MAAO,OAAA,aAAA,CAAc,OAAO,eAAe,CAAA;AAAA;AAE/C,IAAA,MAAM,iCAAiC,YAAY;AAC/C,MAAA,WAAA,MAAiB,uBAAuB,oBAAsB,EAAA;AAC1D,QAAA,MAAM,UAAa,GAAA,uBAAA,CAAwB,mBAAoB,CAAA,KAAA,CAAM,IAAI,CAAA;AACzE,QAAA,IAAI,eAAe,kBAAoB,EAAA;AACnC,UAAM,MAAA,IAAIH,mBAAYI,kCAA6B,EAAA;AAAA,YAC/C,gBAAkB,EAAA,UAAA;AAAA,YAClB;AAAA,WACH,CAAA;AAAA;AACL;AACJ,KACD,GAAA;AAKH,IAAA,MAAM,gCAAgC,YAAY;AAC9C,MAAA,MAAM,EAAE,KAAO,EAAA,YAAA,KAAiB,MAAM,GAAA,CACjC,eAAe,mBAAqB,EAAA;AAAA,QACjC,UAAA;AAAA,QACA,SAAW,EAAA,EAAE,MAAQ,EAAA,EAAA,EAAI,QAAQ,kBAAmB,EAAA;AAAA,QACpD,QAAU,EAAA;AAAA,OACb,CACA,CAAA,IAAA,CAAK,EAAE,WAAa,EAAA,eAAA,CAAgB,QAAQ,CAAA;AACjD,MAAA,IAAI,CAAC,YAAc,EAAA;AACf,QAAM,MAAA,IAAIJ,mBAAYK,4CAAuC,EAAA;AAAA,UACzD;AAAA,SACH,CAAA;AAAA;AAEL,MAAM,MAAA,UAAA;AAAA;AAAA;AAAA,QAGF,YAAA,CAAa,KAAK,CAAC;AAAA,OAAA;AACvB,MAAA,IAAI,eAAe,kBAAoB,EAAA;AACnC,QAAM,MAAA,IAAIL,mBAAYI,kCAA6B,EAAA;AAAA,UAC/C,gBAAkB,EAAA,UAAA;AAAA,UAClB;AAAA,SACH,CAAA;AAAA,OACE,MAAA;AACH,QAAM,MAAA,IAAI,QAAQ,MAAM;AAAA,SAEvB,CAAA;AAAA;AACL,KACD,GAAA;AACH,IAAI,IAAA;AACA,MAAA,OAAO,MAAME,iBAAA,CAAS,CAAC,6BAAA,EAA+B,4BAA4B,CAAC,CAAA;AAAA,KACrF,SAAA;AACE,MAAA,eAAA,CAAgB,KAAM,EAAA;AAAA;AAC1B,GACJ;AACJ;ACzFO,SAAS,+CAEd,CAAA;AAAA,EACE,GAAA;AAAA,EACA;AACJ,CAA6G,EAAA;AACzG,EAAA,OAAO,eAAe,qCAAsC,CAAA;AAAA,IACxD,WAAa,EAAA,iBAAA;AAAA,IACb,UAAA;AAAA,IACA;AAAA,GACD,EAAA;AACC,IAAM,MAAA,eAAA,GAAkB,IAAI,CAAgB,EAAA;AAC5C,IAAA,SAAS,WAAc,GAAA;AACnB,MAAA,eAAA,CAAgB,KAAM,EAAA;AAAA;AAE1B,IAAA,iBAAA,CAAkB,iBAAiB,OAAS,EAAA,WAAA,EAAa,EAAE,MAAQ,EAAA,eAAA,CAAgB,QAAQ,CAAA;AAI3F,IAAA,MAAM,4BAA+B,GAAA,MAAM,gBACtC,CAAA,sBAAA,CAAuB,WAAW,EAAE,UAAA,EAAY,CAAA,CAChD,SAAU,CAAA,EAAE,WAAa,EAAA,eAAA,CAAgB,QAAQ,CAAA;AACtD,IAAA,MAAM,6BAA6B,YAAY;AAC3C,MAAA,WAAA,MAAiB,+BAA+B,4BAA8B,EAAA;AAC1E,QAAI,IAAA,2BAAA,CAA4B,MAAM,GAAK,EAAA;AACvC,UAAM,MAAAC,yCAAA,CAAmC,2BAA4B,CAAA,KAAA,CAAM,GAAG,CAAA;AAAA,SAC3E,MAAA;AACH,UAAA;AAAA;AACJ;AACJ,KACD,GAAA;AAKH,IAAA,MAAM,gCAAgC,YAAY;AAC9C,MAAA,MAAM,EAAE,KAAO,EAAA,sBAAA,EAA2B,GAAA,MAAM,IAC3C,oBAAqB,CAAA,CAAC,SAAS,CAAC,EAChC,IAAK,CAAA,EAAE,WAAa,EAAA,eAAA,CAAgB,QAAQ,CAAA;AACjD,MAAM,MAAA,eAAA,GAAkB,uBAAuB,CAAC,CAAA;AAChD,MAAA,IACI,iBAAiB,kBACjB,IAAAC,6BAAA,CAAqB,gBAAgB,kBAAoB,EAAA,UAAU,KAAK,CAC1E,EAAA;AACE,QAAA;AAAA,OACJ,MAAA,IAAW,iBAAiB,GAAK,EAAA;AAC7B,QAAM,MAAAD,yCAAA,CAAmC,gBAAgB,GAAG,CAAA;AAAA,OACzD,MAAA;AACH,QAAM,MAAA,IAAI,QAAQ,MAAM;AAAA,SAEvB,CAAA;AAAA;AACL,KACD,GAAA;AACH,IAAI,IAAA;AACA,MAAA,OAAO,MAAMD,iBAAAA,CAAS,CAAC,yBAAA,EAA2B,4BAA4B,CAAC,CAAA;AAAA,KACjF,SAAA;AACE,MAAA,eAAA,CAAgB,KAAM,EAAA;AAAA;AAC1B,GACJ;AACJ;;;ACjGA,eAAsB,iBAAkB,CAAA,EAAE,WAAa,EAAA,iBAAA,EAAmB,YAAsB,EAAA;AAC5F,EAAA,OAAO,MAAM,IAAI,OAAQ,CAAA,CAAC,GAAG,MAAW,KAAA;AACpC,IAAM,MAAA,WAAA,GAAc,CAAC,CAAoC,KAAA;AACrD,MAAA,YAAA,CAAa,SAAS,CAAA;AACtB,MAAA,MAAM,aAAa,IAAI,YAAA,CAAc,CAAE,CAAA,MAAA,CAAuB,QAAQ,YAAY,CAAA;AAClF,MAAA,MAAA,CAAO,UAAU,CAAA;AAAA,KACrB;AACA,IAAkB,iBAAA,CAAA,gBAAA,CAAiB,SAAS,WAAW,CAAA;AACvD,IAAM,MAAA,SAAA,GAAY,UAAe,KAAA,WAAA,GAAc,GAAS,GAAA,GAAA;AACxD,IAAM,MAAA,OAAA,GAAU,YAAY,GAAI,EAAA;AAChC,IAAM,MAAA,SAAA;AAAA;AAAA;AAAA;AAAA,MAIF,WAAW,MAAM;AACb,QAAM,MAAA,SAAA,GAAY,WAAY,CAAA,GAAA,EAAQ,GAAA,OAAA;AACtC,QAAA,MAAA,CAAO,IAAI,YAAa,CAAA,CAAA,sBAAA,EAAyB,SAAS,CAAA,GAAA,CAAA,EAAO,cAAc,CAAC,CAAA;AAAA,SACjF,SAAS;AAAA,KAAA;AAAA,GACnB,CAAA;AACL;ACrCA,eAAsB,cAAA,CAClB,SACA,EAAA,MAAA,EACA,4BACF,EAAA;AACE,EAAA,MAAM,EAAE,WAAA,EAAa,iBAAmB,EAAA,UAAA,EAAY,uCAA0C,GAAA,MAAA;AAC9F,EAAA,iBAAA,EAAmB,cAAe,EAAA;AAClC,EAAM,MAAA,eAAA,GAAkB,IAAI,CAAgB,EAAA;AAC5C,EAAA,IAAI,iBAAmB,EAAA;AACnB,IAAA,MAAM,cAAc,MAAM;AACtB,MAAA,eAAA,CAAgB,KAAM,EAAA;AAAA,KAC1B;AACA,IAAA,iBAAA,CAAkB,iBAAiB,OAAS,EAAA,WAAA,EAAa,EAAE,MAAQ,EAAA,eAAA,CAAgB,QAAQ,CAAA;AAAA;AAE/F,EAAI,IAAA;AACA,IAAA,MAAM,qBAAqB,4BAA6B,CAAA;AAAA,MACpD,GAAG,MAAA;AAAA,MACH,aAAa,eAAgB,CAAA;AAAA,KAChC,CAAA;AACD,IAAA,OAAO,MAAMA,iBAAS,CAAA;AAAA,MAClB,qCAAsC,CAAA;AAAA,QAClC,aAAa,eAAgB,CAAA,MAAA;AAAA,QAC7B,UAAA;AAAA,QACA;AAAA,OACH,CAAA;AAAA,MACD,GAAG;AAAA,KACN,CAAA;AAAA,GACH,SAAA;AACE,IAAA,eAAA,CAAgB,KAAM,EAAA;AAAA;AAE9B;;;ACeA,eAAsB,2CAClB,MACa,EAAA;AACb,EAAM,MAAA,cAAA;AAAA,IACFG,wCAAA,CAA4B,OAAO,WAAW,CAAA;AAAA,IAC9C,MAAA;AAAA,IACA,SAAS,4BAA6B,CAAA,EAAE,aAAa,UAAY,EAAA,2BAAA,EAA6B,aAAe,EAAA;AACzG,MAAO,OAAA;AAAA,QACH,2BAA4B,CAAA;AAAA,UACxB,WAAA;AAAA,UACA,UAAA;AAAA,UACA,iBAAA,EAAmB,YAAY,kBAAmB,CAAA,KAAA;AAAA,UAClD,mBAAA,EAAqB,YAAY,kBAAmB,CAAA;AAAA,SACvD;AAAA,OACL;AAAA;AACJ,GACJ;AACJ;AAwBA,eAAsB,qCAClB,MACa,EAAA;AACb,EAAM,MAAA,cAAA;AAAA,IACFA,wCAAA,CAA4B,OAAO,WAAW,CAAA;AAAA,IAC9C,MAAA;AAAA,IACA,SAAS,4BAA6B,CAAA;AAAA,MAClC,WAAA;AAAA,MACA,UAAA;AAAA,MACA,+BAAA;AAAA,MACA;AAAA,KACD,EAAA;AACC,MAAO,OAAA;AAAA,QACH,+BAAgC,CAAA;AAAA,UAC5B,WAAA;AAAA,UACA,UAAA;AAAA,UACA,oBAAA,EAAsB,YAAY,kBAAmB,CAAA;AAAA,SACxD;AAAA,OACL;AAAA;AACJ,GACJ;AACJ;AAGA,eAAsB,iDAClB,MACa,EAAA;AACb,EAAM,MAAA,cAAA;AAAA,IACF,MAAO,CAAA,SAAA;AAAA,IACP,MAAA;AAAA,IACA,SAAS,4BAA6B,CAAA,EAAE,aAAa,UAAY,EAAA,iBAAA,EAAAC,oBAAqB,EAAA;AAClF,MAAO,OAAA;AAAA,QACHA,kBAAkB,CAAA;AAAA,UACd,WAAA;AAAA,UACA;AAAA,SACH;AAAA,OACL;AAAA;AACJ,GACJ;AACJ","file":"index.browser.cjs","sourcesContent":["export const AbortController = globalThis.AbortController;\nexport const EventTarget = globalThis.EventTarget;\n","import { SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED, SolanaError } from '@solana/errors';\nimport { AbortController } from '@solana/event-target-impl';\nimport type { GetEpochInfoApi, Rpc } from '@solana/rpc';\nimport type { RpcSubscriptions, SlotNotificationsApi } from '@solana/rpc-subscriptions';\nimport type { Commitment } from '@solana/rpc-types';\n\ntype GetBlockHeightExceedencePromiseFn = (config: {\n abortSignal: AbortSignal;\n /**\n * Fetch the block height as of the highest slot that has reached this level of commitment.\n *\n * @defaultValue Whichever default is applied by the underlying {@link RpcApi} in use. For\n * example, when using an API created by a `createSolanaRpc*()` helper, the default commitment\n * is `\"confirmed\"` unless configured otherwise. Unmitigated by an API layer on the client, the\n * default commitment applied by the server is `\"finalized\"`.\n */\n commitment?: Commitment;\n /** The block height after which to reject the promise */\n lastValidBlockHeight: bigint;\n}) => Promise<void>;\n\ntype CreateBlockHeightExceedencePromiseFactoryConfig<TCluster> = {\n rpc: Rpc<GetEpochInfoApi> & { '~cluster'?: TCluster };\n rpcSubscriptions: RpcSubscriptions<SlotNotificationsApi> & { '~cluster'?: TCluster };\n};\n\n/**\n * Creates a promise that throws when the network progresses past the block height after which the\n * supplied blockhash is considered expired for use as a transaction lifetime specifier.\n *\n * When a transaction's lifetime is tied to a blockhash, that transaction can be landed on the\n * network until that blockhash expires. All blockhashes have a block height after which they are\n * considered to have expired.\n *\n * @param config\n *\n * @example\n * ```ts\n * import { isSolanaError, SolanaError } from '@solana/errors';\n * import { createBlockHeightExceedencePromiseFactory } from '@solana/transaction-confirmation';\n *\n * const getBlockHeightExceedencePromise = createBlockHeightExceedencePromiseFactory({\n * rpc,\n * rpcSubscriptions,\n * });\n * try {\n * await getBlockHeightExceedencePromise({ lastValidBlockHeight });\n * } catch (e) {\n * if (isSolanaError(e, SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED)) {\n * console.error(\n * `The block height of the network has exceeded ${e.context.lastValidBlockHeight}. ` +\n * `It is now ${e.context.currentBlockHeight}`,\n * );\n * // Re-sign and retry the transaction.\n * return;\n * }\n * throw e;\n * }\n * ```\n */\nexport function createBlockHeightExceedencePromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateBlockHeightExceedencePromiseFactoryConfig<'devnet'>): GetBlockHeightExceedencePromiseFn;\nexport function createBlockHeightExceedencePromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateBlockHeightExceedencePromiseFactoryConfig<'testnet'>): GetBlockHeightExceedencePromiseFn;\nexport function createBlockHeightExceedencePromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateBlockHeightExceedencePromiseFactoryConfig<'mainnet'>): GetBlockHeightExceedencePromiseFn;\nexport function createBlockHeightExceedencePromiseFactory<\n TCluster extends 'devnet' | 'mainnet' | 'testnet' | void = void,\n>({\n rpc,\n rpcSubscriptions,\n}: CreateBlockHeightExceedencePromiseFactoryConfig<TCluster>): GetBlockHeightExceedencePromiseFn {\n return async function getBlockHeightExceedencePromise({\n abortSignal: callerAbortSignal,\n commitment,\n lastValidBlockHeight,\n }): Promise<never> {\n callerAbortSignal.throwIfAborted();\n const abortController = new AbortController();\n const handleAbort = () => {\n abortController.abort();\n };\n callerAbortSignal.addEventListener('abort', handleAbort, { signal: abortController.signal });\n async function getBlockHeightAndDifferenceBetweenSlotHeightAndBlockHeight() {\n const { absoluteSlot, blockHeight } = await rpc\n .getEpochInfo({ commitment })\n .send({ abortSignal: abortController.signal });\n return {\n blockHeight,\n differenceBetweenSlotHeightAndBlockHeight: absoluteSlot - blockHeight,\n };\n }\n try {\n const [slotNotifications, { blockHeight: initialBlockHeight, differenceBetweenSlotHeightAndBlockHeight }] =\n await Promise.all([\n rpcSubscriptions.slotNotifications().subscribe({ abortSignal: abortController.signal }),\n getBlockHeightAndDifferenceBetweenSlotHeightAndBlockHeight(),\n ]);\n callerAbortSignal.throwIfAborted();\n let currentBlockHeight = initialBlockHeight;\n if (currentBlockHeight <= lastValidBlockHeight) {\n let lastKnownDifferenceBetweenSlotHeightAndBlockHeight = differenceBetweenSlotHeightAndBlockHeight;\n for await (const slotNotification of slotNotifications) {\n const { slot } = slotNotification;\n if (slot - lastKnownDifferenceBetweenSlotHeightAndBlockHeight > lastValidBlockHeight) {\n // Before making a final decision, recheck the actual block height.\n const {\n blockHeight: recheckedBlockHeight,\n differenceBetweenSlotHeightAndBlockHeight: currentDifferenceBetweenSlotHeightAndBlockHeight,\n } = await getBlockHeightAndDifferenceBetweenSlotHeightAndBlockHeight();\n currentBlockHeight = recheckedBlockHeight;\n if (currentBlockHeight > lastValidBlockHeight) {\n // Verified; the block height has been exceeded.\n break;\n } else {\n // The block height has not been exceeded, which implies that the\n // difference between the slot height and the block height has grown\n // (ie. some blocks have been skipped since we started). Recalibrate the\n // difference and keep waiting.\n lastKnownDifferenceBetweenSlotHeightAndBlockHeight =\n currentDifferenceBetweenSlotHeightAndBlockHeight;\n }\n }\n }\n }\n callerAbortSignal.throwIfAborted();\n throw new SolanaError(SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED, {\n currentBlockHeight,\n lastValidBlockHeight,\n });\n } finally {\n abortController.abort();\n }\n };\n}\n","import type { Address } from '@solana/addresses';\nimport { getBase58Decoder, getBase64Encoder } from '@solana/codecs-strings';\nimport { SOLANA_ERROR__INVALID_NONCE, SOLANA_ERROR__NONCE_ACCOUNT_NOT_FOUND, SolanaError } from '@solana/errors';\nimport { AbortController } from '@solana/event-target-impl';\nimport { safeRace } from '@solana/promises';\nimport type { GetAccountInfoApi, Rpc } from '@solana/rpc';\nimport type { AccountNotificationsApi, RpcSubscriptions } from '@solana/rpc-subscriptions';\nimport type { Base64EncodedDataResponse, Commitment } from '@solana/rpc-types';\nimport { Nonce } from '@solana/transaction-messages';\n\ntype GetNonceInvalidationPromiseFn = (config: {\n abortSignal: AbortSignal;\n /**\n * Fetch the nonce account details as of the highest slot that has reached this level of\n * commitment.\n */\n commitment: Commitment;\n /**\n * The value of the nonce that we would expect to see in the nonce account in order for any\n * transaction with that nonce-based lifetime to be considered valid.\n */\n currentNonceValue: Nonce;\n /** The address of the account in which the currently-valid nonce value is stored */\n nonceAccountAddress: Address;\n}) => Promise<void>;\n\ntype CreateNonceInvalidationPromiseFactoryConfig<TCluster> = {\n rpc: Rpc<GetAccountInfoApi> & { '~cluster'?: TCluster };\n rpcSubscriptions: RpcSubscriptions<AccountNotificationsApi> & { '~cluster'?: TCluster };\n};\n\nconst NONCE_VALUE_OFFSET =\n 4 + // version(u32)\n 4 + // state(u32)\n 32; // nonce authority(pubkey)\n// Then comes the nonce value.\n\n/**\n * Creates a promise that throws when the value stored in a nonce account is not the expected one.\n *\n * When a transaction's lifetime is tied to the value stored in a nonce account, that transaction\n * can be landed on the network until the nonce is advanced to a new value.\n *\n * @param config\n *\n * @example\n * ```ts\n * import { isSolanaError, SolanaError } from '@solana/errors';\n * import { createNonceInvalidationPromiseFactory } from '@solana/transaction-confirmation';\n *\n * const getNonceInvalidationPromise = createNonceInvalidationPromiseFactory({\n * rpc,\n * rpcSubscriptions,\n * });\n * try {\n * await getNonceInvalidationPromise({\n * currentNonceValue,\n * nonceAccountAddress,\n * });\n * } catch (e) {\n * if (isSolanaError(e, SOLANA_ERROR__NONCE_INVALID)) {\n * console.error(`The nonce has advanced to ${e.context.actualNonceValue}`);\n * // Re-sign and retry the transaction.\n * return;\n * } else if (isSolanaError(e, SOLANA_ERROR__NONCE_ACCOUNT_NOT_FOUND)) {\n * console.error(`No nonce account was found at ${nonceAccountAddress}`);\n * }\n * throw e;\n * }\n * ```\n */\nexport function createNonceInvalidationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateNonceInvalidationPromiseFactoryConfig<'devnet'>): GetNonceInvalidationPromiseFn;\nexport function createNonceInvalidationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateNonceInvalidationPromiseFactoryConfig<'testnet'>): GetNonceInvalidationPromiseFn;\nexport function createNonceInvalidationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateNonceInvalidationPromiseFactoryConfig<'mainnet'>): GetNonceInvalidationPromiseFn;\nexport function createNonceInvalidationPromiseFactory<TCluster extends 'devnet' | 'mainnet' | 'testnet' | void = void>({\n rpc,\n rpcSubscriptions,\n}: CreateNonceInvalidationPromiseFactoryConfig<TCluster>): GetNonceInvalidationPromiseFn {\n return async function getNonceInvalidationPromise({\n abortSignal: callerAbortSignal,\n commitment,\n currentNonceValue: expectedNonceValue,\n nonceAccountAddress,\n }) {\n const abortController = new AbortController();\n function handleAbort() {\n abortController.abort();\n }\n callerAbortSignal.addEventListener('abort', handleAbort, { signal: abortController.signal });\n /**\n * STEP 1: Set up a subscription for nonce account changes.\n */\n const accountNotifications = await rpcSubscriptions\n .accountNotifications(nonceAccountAddress, { commitment, encoding: 'base64' })\n .subscribe({ abortSignal: abortController.signal });\n const base58Decoder = getBase58Decoder();\n const base64Encoder = getBase64Encoder();\n function getNonceFromAccountData([base64EncodedBytes]: Base64EncodedDataResponse): Nonce {\n const data = base64Encoder.encode(base64EncodedBytes);\n const nonceValueBytes = data.slice(NONCE_VALUE_OFFSET, NONCE_VALUE_OFFSET + 32);\n return base58Decoder.decode(nonceValueBytes) as Nonce;\n }\n const nonceAccountDidAdvancePromise = (async () => {\n for await (const accountNotification of accountNotifications) {\n const nonceValue = getNonceFromAccountData(accountNotification.value.data);\n if (nonceValue !== expectedNonceValue) {\n throw new SolanaError(SOLANA_ERROR__INVALID_NONCE, {\n actualNonceValue: nonceValue,\n expectedNonceValue,\n });\n }\n }\n })();\n /**\n * STEP 2: Having subscribed for updates, make a one-shot request for the current nonce\n * value to check if it has already been advanced.\n */\n const nonceIsAlreadyInvalidPromise = (async () => {\n const { value: nonceAccount } = await rpc\n .getAccountInfo(nonceAccountAddress, {\n commitment,\n dataSlice: { length: 32, offset: NONCE_VALUE_OFFSET },\n encoding: 'base58',\n })\n .send({ abortSignal: abortController.signal });\n if (!nonceAccount) {\n throw new SolanaError(SOLANA_ERROR__NONCE_ACCOUNT_NOT_FOUND, {\n nonceAccountAddress,\n });\n }\n const nonceValue =\n // This works because we asked for the exact slice of data representing the nonce\n // value, and furthermore asked for it in `base58` encoding.\n nonceAccount.data[0] as unknown as Nonce;\n if (nonceValue !== expectedNonceValue) {\n throw new SolanaError(SOLANA_ERROR__INVALID_NONCE, {\n actualNonceValue: nonceValue,\n expectedNonceValue,\n });\n } else {\n await new Promise(() => {\n /* never resolve */\n });\n }\n })();\n try {\n return await safeRace([nonceAccountDidAdvancePromise, nonceIsAlreadyInvalidPromise]);\n } finally {\n abortController.abort();\n }\n };\n}\n","import { getSolanaErrorFromTransactionError } from '@solana/errors';\nimport { AbortController } from '@solana/event-target-impl';\nimport type { Signature } from '@solana/keys';\nimport { safeRace } from '@solana/promises';\nimport type { GetSignatureStatusesApi, Rpc } from '@solana/rpc';\nimport type { RpcSubscriptions, SignatureNotificationsApi } from '@solana/rpc-subscriptions';\nimport { type Commitment, commitmentComparator } from '@solana/rpc-types';\n\ntype GetRecentSignatureConfirmationPromiseFn = (config: {\n abortSignal: AbortSignal;\n /**\n * The level of commitment the transaction must have achieved in order for the promise to\n * resolve.\n */\n commitment: Commitment;\n /**\n * A 64 byte Ed25519 signature, encoded as a base-58 string, that uniquely identifies a\n * transaction by virtue of being the first or only signature in its list of signatures.\n */\n signature: Signature;\n}) => Promise<void>;\n\ntype CreateRecentSignatureConfirmationPromiseFactoryConfig<TCluster> = {\n rpc: Rpc<GetSignatureStatusesApi> & { '~cluster'?: TCluster };\n rpcSubscriptions: RpcSubscriptions<SignatureNotificationsApi> & { '~cluster'?: TCluster };\n};\n\n/**\n * Creates a promise that resolves when a recently-landed transaction achieves the target\n * confirmation commitment, and throws when the transaction fails with an error.\n *\n * The status of recently-landed transactions is available in the network's status cache. This\n * confirmation strategy will only yield a result if the signature is still in the status cache. To\n * fetch the status of transactions older than those available in the status cache, use the\n * {@link GetSignatureStatusesApi.getSignatureStatuses} method setting the\n * `searchTransactionHistory` configuration param to `true`.\n *\n * @param config\n *\n * @example\n * ```ts\n * import { createRecentSignatureConfirmationPromiseFactory } from '@solana/transaction-confirmation';\n *\n * const getRecentSignatureConfirmationPromise = createRecentSignatureConfirmationPromiseFactory({\n * rpc,\n * rpcSubscriptions,\n * });\n * try {\n * await getRecentSignatureConfirmationPromise({\n * commitment,\n * signature,\n * });\n * console.log(`The transaction with signature \\`${signature}\\` has achieved a commitment level of \\`${commitment}\\``);\n * } catch (e) {\n * console.error(`The transaction with signature \\`${signature}\\` failed`, e.cause);\n * throw e;\n * }\n * ```\n */\nexport function createRecentSignatureConfirmationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateRecentSignatureConfirmationPromiseFactoryConfig<'devnet'>): GetRecentSignatureConfirmationPromiseFn;\nexport function createRecentSignatureConfirmationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateRecentSignatureConfirmationPromiseFactoryConfig<'testnet'>): GetRecentSignatureConfirmationPromiseFn;\nexport function createRecentSignatureConfirmationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateRecentSignatureConfirmationPromiseFactoryConfig<'mainnet'>): GetRecentSignatureConfirmationPromiseFn;\nexport function createRecentSignatureConfirmationPromiseFactory<\n TCluster extends 'devnet' | 'mainnet' | 'testnet' | void = void,\n>({\n rpc,\n rpcSubscriptions,\n}: CreateRecentSignatureConfirmationPromiseFactoryConfig<TCluster>): GetRecentSignatureConfirmationPromiseFn {\n return async function getRecentSignatureConfirmationPromise({\n abortSignal: callerAbortSignal,\n commitment,\n signature,\n }) {\n const abortController = new AbortController();\n function handleAbort() {\n abortController.abort();\n }\n callerAbortSignal.addEventListener('abort', handleAbort, { signal: abortController.signal });\n /**\n * STEP 1: Set up a subscription for status changes to a signature.\n */\n const signatureStatusNotifications = await rpcSubscriptions\n .signatureNotifications(signature, { commitment })\n .subscribe({ abortSignal: abortController.signal });\n const signatureDidCommitPromise = (async () => {\n for await (const signatureStatusNotification of signatureStatusNotifications) {\n if (signatureStatusNotification.value.err) {\n throw getSolanaErrorFromTransactionError(signatureStatusNotification.value.err);\n } else {\n return;\n }\n }\n })();\n /**\n * STEP 2: Having subscribed for updates, make a one-shot request for the current status.\n * This will only yield a result if the signature is still in the status cache.\n */\n const signatureStatusLookupPromise = (async () => {\n const { value: signatureStatusResults } = await rpc\n .getSignatureStatuses([signature])\n .send({ abortSignal: abortController.signal });\n const signatureStatus = signatureStatusResults[0];\n if (\n signatureStatus?.confirmationStatus &&\n commitmentComparator(signatureStatus.confirmationStatus, commitment) >= 0\n ) {\n return;\n } else if (signatureStatus?.err) {\n throw getSolanaErrorFromTransactionError(signatureStatus.err);\n } else {\n await new Promise(() => {\n /* never resolve */\n });\n }\n })();\n try {\n return await safeRace([signatureDidCommitPromise, signatureStatusLookupPromise]);\n } finally {\n abortController.abort();\n }\n };\n}\n","import type { Commitment } from '@solana/rpc-types';\n\ntype Config = Readonly<{\n abortSignal: AbortSignal;\n /**\n * The timeout promise will throw after 30 seconds when the commitment is `processed`, and 60\n * seconds otherwise.\n */\n commitment: Commitment;\n}>;\n\n/**\n * When no other heuristic exists to infer that a transaction has expired, you can use this promise\n * factory with a commitment level. It throws after 30 seconds when the commitment is `processed`,\n * and 60 seconds otherwise. You would typically race this with another confirmation strategy.\n *\n * @param config\n *\n * @example\n * ```ts\n * import { safeRace } from '@solana/promises';\n * import { getTimeoutPromise } from '@solana/transaction-confirmation';\n *\n * try {\n * await safeRace([getCustomTransactionConfirmationPromise(/* ... *\\/), getTimeoutPromise({ commitment })]);\n * } catch (e) {\n * if (e instanceof DOMException && e.name === 'TimeoutError') {\n * console.log('Could not confirm transaction after a timeout');\n * }\n * throw e;\n * }\n * ```\n */\nexport async function getTimeoutPromise({ abortSignal: callerAbortSignal, commitment }: Config) {\n return await new Promise((_, reject) => {\n const handleAbort = (e: AbortSignalEventMap['abort']) => {\n clearTimeout(timeoutId);\n const abortError = new DOMException((e.target as AbortSignal).reason, 'AbortError');\n reject(abortError);\n };\n callerAbortSignal.addEventListener('abort', handleAbort);\n const timeoutMs = commitment === 'processed' ? 30_000 : 60_000;\n const startMs = performance.now();\n const timeoutId =\n // We use `setTimeout` instead of `AbortSignal.timeout()` because we want to measure\n // elapsed time instead of active time.\n // See https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal/timeout_static\n setTimeout(() => {\n const elapsedMs = performance.now() - startMs;\n reject(new DOMException(`Timeout elapsed after ${elapsedMs} ms`, 'TimeoutError'));\n }, timeoutMs);\n });\n}\n","import { AbortController } from '@solana/event-target-impl';\nimport type { Signature } from '@solana/keys';\nimport { safeRace } from '@solana/promises';\nimport type { Commitment } from '@solana/rpc-types';\n\nimport { createRecentSignatureConfirmationPromiseFactory } from './confirmation-strategy-recent-signature';\n\nexport interface BaseTransactionConfirmationStrategyConfig {\n abortSignal?: AbortSignal;\n commitment: Commitment;\n getRecentSignatureConfirmationPromise: ReturnType<typeof createRecentSignatureConfirmationPromiseFactory>;\n}\n\ntype WithNonNullableAbortSignal<T> = Omit<T, 'abortSignal'> & Readonly<{ abortSignal: AbortSignal }>;\n\nexport async function raceStrategies<TConfig extends BaseTransactionConfirmationStrategyConfig>(\n signature: Signature,\n config: TConfig,\n getSpecificStrategiesForRace: (config: WithNonNullableAbortSignal<TConfig>) => readonly Promise<unknown>[],\n) {\n const { abortSignal: callerAbortSignal, commitment, getRecentSignatureConfirmationPromise } = config;\n callerAbortSignal?.throwIfAborted();\n const abortController = new AbortController();\n if (callerAbortSignal) {\n const handleAbort = () => {\n abortController.abort();\n };\n callerAbortSignal.addEventListener('abort', handleAbort, { signal: abortController.signal });\n }\n try {\n const specificStrategies = getSpecificStrategiesForRace({\n ...config,\n abortSignal: abortController.signal,\n });\n return await safeRace([\n getRecentSignatureConfirmationPromise({\n abortSignal: abortController.signal,\n commitment,\n signature,\n }),\n ...specificStrategies,\n ]);\n } finally {\n abortController.abort();\n }\n}\n","import { Signature } from '@solana/keys';\nimport {\n getSignatureFromTransaction,\n Transaction,\n TransactionWithBlockhashLifetime,\n TransactionWithDurableNonceLifetime,\n} from '@solana/transactions';\n\nimport { createBlockHeightExceedencePromiseFactory } from './confirmation-strategy-blockheight';\nimport { createNonceInvalidationPromiseFactory } from './confirmation-strategy-nonce';\nimport { BaseTransactionConfirmationStrategyConfig, raceStrategies } from './confirmation-strategy-racer';\nimport { getTimeoutPromise } from './confirmation-strategy-timeout';\n\nexport type TransactionWithLastValidBlockHeight = Omit<TransactionWithBlockhashLifetime, 'lifetimeConstraint'> & {\n lifetimeConstraint: Omit<TransactionWithBlockhashLifetime['lifetimeConstraint'], 'blockhash'>;\n};\n\ninterface WaitForDurableNonceTransactionConfirmationConfig extends BaseTransactionConfirmationStrategyConfig {\n getNonceInvalidationPromise: ReturnType<typeof createNonceInvalidationPromiseFactory>;\n transaction: Readonly<Transaction & TransactionWithDurableNonceLifetime>;\n}\n\ninterface WaitForRecentTransactionWithBlockhashLifetimeConfirmationConfig\n extends BaseTransactionConfirmationStrategyConfig {\n getBlockHeightExceedencePromise: ReturnType<typeof createBlockHeightExceedencePromiseFactory>;\n transaction: Readonly<Transaction & TransactionWithLastValidBlockHeight>;\n}\n\ninterface WaitForRecentTransactionWithTimeBasedLifetimeConfirmationConfig\n extends BaseTransactionConfirmationStrategyConfig {\n getTimeoutPromise: typeof getTimeoutPromise;\n /**\n * A 64 byte Ed25519 signature, encoded as a base-58 string, that uniquely identifies a\n * transaction by virtue of being the first or only signature in its list of signatures.\n */\n signature: Signature;\n}\n\n/**\n * Supply your own confirmation implementations to this function to create a custom nonce\n * transaction confirmation strategy.\n *\n * @example\n * ```ts\n * import { waitForDurableNonceTransactionConfirmation } from '@solana/transaction-confirmation';\n *\n * try {\n * await waitForDurableNonceTransactionConfirmation({\n * getNonceInvalidationPromise({ abortSignal, commitment, currentNonceValue, nonceAccountAddress }) {\n * // Return a promise that rejects when a nonce becomes invalid.\n * },\n * getRecentSignatureConfirmationPromise({ abortSignal, commitment, signature }) {\n * // Return a promise that resolves when a transaction achieves confirmation\n * },\n * });\n * } catch (e) {\n * // Handle errors.\n * }\n * ```\n */\nexport async function waitForDurableNonceTransactionConfirmation(\n config: WaitForDurableNonceTransactionConfirmationConfig,\n): Promise<void> {\n await raceStrategies(\n getSignatureFromTransaction(config.transaction),\n config,\n function getSpecificStrategiesForRace({ abortSignal, commitment, getNonceInvalidationPromise, transaction }) {\n return [\n getNonceInvalidationPromise({\n abortSignal,\n commitment,\n currentNonceValue: transaction.lifetimeConstraint.nonce,\n nonceAccountAddress: transaction.lifetimeConstraint.nonceAccountAddress,\n }),\n ];\n },\n );\n}\n\n/**\n * Supply your own confirmation implementations to this function to create a custom confirmation\n * strategy for recently-landed transactions.\n *\n * @example\n * ```ts\n * import { waitForRecentTransactionConfirmation } from '@solana/transaction-confirmation';\n *\n * try {\n * await waitForRecentTransactionConfirmation({\n * getBlockHeightExceedencePromise({ abortSignal, commitment, lastValidBlockHeight }) {\n * // Return a promise that rejects when the blockhash's block height has been exceeded\n * },\n * getRecentSignatureConfirmationPromise({ abortSignal, commitment, signature }) {\n * // Return a promise that resolves when a transaction achieves confirmation\n * },\n * });\n * } catch (e) {\n * // Handle errors.\n * }\n * ```\n */\nexport async function waitForRecentTransactionConfirmation(\n config: WaitForRecentTransactionWithBlockhashLifetimeConfirmationConfig,\n): Promise<void> {\n await raceStrategies(\n getSignatureFromTransaction(config.transaction),\n config,\n function getSpecificStrategiesForRace({\n abortSignal,\n commitment,\n getBlockHeightExceedencePromise,\n transaction,\n }) {\n return [\n getBlockHeightExceedencePromise({\n abortSignal,\n commitment,\n lastValidBlockHeight: transaction.lifetimeConstraint.lastValidBlockHeight,\n }),\n ];\n },\n );\n}\n\n/** @deprecated */\nexport async function waitForRecentTransactionConfirmationUntilTimeout(\n config: WaitForRecentTransactionWithTimeBasedLifetimeConfirmationConfig,\n): Promise<void> {\n await raceStrategies(\n config.signature,\n config,\n function getSpecificStrategiesForRace({ abortSignal, commitment, getTimeoutPromise }) {\n return [\n getTimeoutPromise({\n abortSignal,\n commitment,\n }),\n ];\n },\n );\n}\n"]}
|
package/dist/index.browser.mjs
CHANGED
|
@@ -164,8 +164,10 @@ function createRecentSignatureConfirmationPromiseFactory({
|
|
|
164
164
|
const signatureStatusLookupPromise = (async () => {
|
|
165
165
|
const { value: signatureStatusResults } = await rpc.getSignatureStatuses([signature]).send({ abortSignal: abortController.signal });
|
|
166
166
|
const signatureStatus = signatureStatusResults[0];
|
|
167
|
-
if (signatureStatus
|
|
167
|
+
if (signatureStatus?.confirmationStatus && commitmentComparator(signatureStatus.confirmationStatus, commitment) >= 0) {
|
|
168
168
|
return;
|
|
169
|
+
} else if (signatureStatus?.err) {
|
|
170
|
+
throw getSolanaErrorFromTransactionError(signatureStatus.err);
|
|
169
171
|
} else {
|
|
170
172
|
await new Promise(() => {
|
|
171
173
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../event-target-impl/src/index.browser.ts","../src/confirmation-strategy-blockheight.ts","../src/confirmation-strategy-nonce.ts","../src/confirmation-strategy-recent-signature.ts","../src/confirmation-strategy-timeout.ts","../src/confirmation-strategy-racer.ts","../src/waiters.ts"],"names":["AbortController","SolanaError","safeRace","getTimeoutPromise"],"mappings":"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","file":"index.browser.mjs","sourcesContent":["export const AbortController = globalThis.AbortController;\nexport const EventTarget = globalThis.EventTarget;\n","import { SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED, SolanaError } from '@solana/errors';\nimport { AbortController } from '@solana/event-target-impl';\nimport type { GetEpochInfoApi, Rpc } from '@solana/rpc';\nimport type { RpcSubscriptions, SlotNotificationsApi } from '@solana/rpc-subscriptions';\nimport type { Commitment } from '@solana/rpc-types';\n\ntype GetBlockHeightExceedencePromiseFn = (config: {\n abortSignal: AbortSignal;\n /**\n * Fetch the block height as of the highest slot that has reached this level of commitment.\n *\n * @defaultValue Whichever default is applied by the underlying {@link RpcApi} in use. For\n * example, when using an API created by a `createSolanaRpc*()` helper, the default commitment\n * is `\"confirmed\"` unless configured otherwise. Unmitigated by an API layer on the client, the\n * default commitment applied by the server is `\"finalized\"`.\n */\n commitment?: Commitment;\n /** The block height after which to reject the promise */\n lastValidBlockHeight: bigint;\n}) => Promise<void>;\n\ntype CreateBlockHeightExceedencePromiseFactoryConfig<TCluster> = {\n rpc: Rpc<GetEpochInfoApi> & { '~cluster'?: TCluster };\n rpcSubscriptions: RpcSubscriptions<SlotNotificationsApi> & { '~cluster'?: TCluster };\n};\n\n/**\n * Creates a promise that throws when the network progresses past the block height after which the\n * supplied blockhash is considered expired for use as a transaction lifetime specifier.\n *\n * When a transaction's lifetime is tied to a blockhash, that transaction can be landed on the\n * network until that blockhash expires. All blockhashes have a block height after which they are\n * considered to have expired.\n *\n * @param config\n *\n * @example\n * ```ts\n * import { isSolanaError, SolanaError } from '@solana/errors';\n * import { createBlockHeightExceedencePromiseFactory } from '@solana/transaction-confirmation';\n *\n * const getBlockHeightExceedencePromise = createBlockHeightExceedencePromiseFactory({\n * rpc,\n * rpcSubscriptions,\n * });\n * try {\n * await getBlockHeightExceedencePromise({ lastValidBlockHeight });\n * } catch (e) {\n * if (isSolanaError(e, SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED)) {\n * console.error(\n * `The block height of the network has exceeded ${e.context.lastValidBlockHeight}. ` +\n * `It is now ${e.context.currentBlockHeight}`,\n * );\n * // Re-sign and retry the transaction.\n * return;\n * }\n * throw e;\n * }\n * ```\n */\nexport function createBlockHeightExceedencePromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateBlockHeightExceedencePromiseFactoryConfig<'devnet'>): GetBlockHeightExceedencePromiseFn;\nexport function createBlockHeightExceedencePromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateBlockHeightExceedencePromiseFactoryConfig<'testnet'>): GetBlockHeightExceedencePromiseFn;\nexport function createBlockHeightExceedencePromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateBlockHeightExceedencePromiseFactoryConfig<'mainnet'>): GetBlockHeightExceedencePromiseFn;\nexport function createBlockHeightExceedencePromiseFactory<\n TCluster extends 'devnet' | 'mainnet' | 'testnet' | void = void,\n>({\n rpc,\n rpcSubscriptions,\n}: CreateBlockHeightExceedencePromiseFactoryConfig<TCluster>): GetBlockHeightExceedencePromiseFn {\n return async function getBlockHeightExceedencePromise({\n abortSignal: callerAbortSignal,\n commitment,\n lastValidBlockHeight,\n }): Promise<never> {\n callerAbortSignal.throwIfAborted();\n const abortController = new AbortController();\n const handleAbort = () => {\n abortController.abort();\n };\n callerAbortSignal.addEventListener('abort', handleAbort, { signal: abortController.signal });\n async function getBlockHeightAndDifferenceBetweenSlotHeightAndBlockHeight() {\n const { absoluteSlot, blockHeight } = await rpc\n .getEpochInfo({ commitment })\n .send({ abortSignal: abortController.signal });\n return {\n blockHeight,\n differenceBetweenSlotHeightAndBlockHeight: absoluteSlot - blockHeight,\n };\n }\n try {\n const [slotNotifications, { blockHeight: initialBlockHeight, differenceBetweenSlotHeightAndBlockHeight }] =\n await Promise.all([\n rpcSubscriptions.slotNotifications().subscribe({ abortSignal: abortController.signal }),\n getBlockHeightAndDifferenceBetweenSlotHeightAndBlockHeight(),\n ]);\n callerAbortSignal.throwIfAborted();\n let currentBlockHeight = initialBlockHeight;\n if (currentBlockHeight <= lastValidBlockHeight) {\n let lastKnownDifferenceBetweenSlotHeightAndBlockHeight = differenceBetweenSlotHeightAndBlockHeight;\n for await (const slotNotification of slotNotifications) {\n const { slot } = slotNotification;\n if (slot - lastKnownDifferenceBetweenSlotHeightAndBlockHeight > lastValidBlockHeight) {\n // Before making a final decision, recheck the actual block height.\n const {\n blockHeight: recheckedBlockHeight,\n differenceBetweenSlotHeightAndBlockHeight: currentDifferenceBetweenSlotHeightAndBlockHeight,\n } = await getBlockHeightAndDifferenceBetweenSlotHeightAndBlockHeight();\n currentBlockHeight = recheckedBlockHeight;\n if (currentBlockHeight > lastValidBlockHeight) {\n // Verified; the block height has been exceeded.\n break;\n } else {\n // The block height has not been exceeded, which implies that the\n // difference between the slot height and the block height has grown\n // (ie. some blocks have been skipped since we started). Recalibrate the\n // difference and keep waiting.\n lastKnownDifferenceBetweenSlotHeightAndBlockHeight =\n currentDifferenceBetweenSlotHeightAndBlockHeight;\n }\n }\n }\n }\n callerAbortSignal.throwIfAborted();\n throw new SolanaError(SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED, {\n currentBlockHeight,\n lastValidBlockHeight,\n });\n } finally {\n abortController.abort();\n }\n };\n}\n","import type { Address } from '@solana/addresses';\nimport { getBase58Decoder, getBase64Encoder } from '@solana/codecs-strings';\nimport { SOLANA_ERROR__INVALID_NONCE, SOLANA_ERROR__NONCE_ACCOUNT_NOT_FOUND, SolanaError } from '@solana/errors';\nimport { AbortController } from '@solana/event-target-impl';\nimport { safeRace } from '@solana/promises';\nimport type { GetAccountInfoApi, Rpc } from '@solana/rpc';\nimport type { AccountNotificationsApi, RpcSubscriptions } from '@solana/rpc-subscriptions';\nimport type { Base64EncodedDataResponse, Commitment } from '@solana/rpc-types';\nimport { Nonce } from '@solana/transaction-messages';\n\ntype GetNonceInvalidationPromiseFn = (config: {\n abortSignal: AbortSignal;\n /**\n * Fetch the nonce account details as of the highest slot that has reached this level of\n * commitment.\n */\n commitment: Commitment;\n /**\n * The value of the nonce that we would expect to see in the nonce account in order for any\n * transaction with that nonce-based lifetime to be considered valid.\n */\n currentNonceValue: Nonce;\n /** The address of the account in which the currently-valid nonce value is stored */\n nonceAccountAddress: Address;\n}) => Promise<void>;\n\ntype CreateNonceInvalidationPromiseFactoryConfig<TCluster> = {\n rpc: Rpc<GetAccountInfoApi> & { '~cluster'?: TCluster };\n rpcSubscriptions: RpcSubscriptions<AccountNotificationsApi> & { '~cluster'?: TCluster };\n};\n\nconst NONCE_VALUE_OFFSET =\n 4 + // version(u32)\n 4 + // state(u32)\n 32; // nonce authority(pubkey)\n// Then comes the nonce value.\n\n/**\n * Creates a promise that throws when the value stored in a nonce account is not the expected one.\n *\n * When a transaction's lifetime is tied to the value stored in a nonce account, that transaction\n * can be landed on the network until the nonce is advanced to a new value.\n *\n * @param config\n *\n * @example\n * ```ts\n * import { isSolanaError, SolanaError } from '@solana/errors';\n * import { createNonceInvalidationPromiseFactory } from '@solana/transaction-confirmation';\n *\n * const getNonceInvalidationPromise = createNonceInvalidationPromiseFactory({\n * rpc,\n * rpcSubscriptions,\n * });\n * try {\n * await getNonceInvalidationPromise({\n * currentNonceValue,\n * nonceAccountAddress,\n * });\n * } catch (e) {\n * if (isSolanaError(e, SOLANA_ERROR__NONCE_INVALID)) {\n * console.error(`The nonce has advanced to ${e.context.actualNonceValue}`);\n * // Re-sign and retry the transaction.\n * return;\n * } else if (isSolanaError(e, SOLANA_ERROR__NONCE_ACCOUNT_NOT_FOUND)) {\n * console.error(`No nonce account was found at ${nonceAccountAddress}`);\n * }\n * throw e;\n * }\n * ```\n */\nexport function createNonceInvalidationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateNonceInvalidationPromiseFactoryConfig<'devnet'>): GetNonceInvalidationPromiseFn;\nexport function createNonceInvalidationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateNonceInvalidationPromiseFactoryConfig<'testnet'>): GetNonceInvalidationPromiseFn;\nexport function createNonceInvalidationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateNonceInvalidationPromiseFactoryConfig<'mainnet'>): GetNonceInvalidationPromiseFn;\nexport function createNonceInvalidationPromiseFactory<TCluster extends 'devnet' | 'mainnet' | 'testnet' | void = void>({\n rpc,\n rpcSubscriptions,\n}: CreateNonceInvalidationPromiseFactoryConfig<TCluster>): GetNonceInvalidationPromiseFn {\n return async function getNonceInvalidationPromise({\n abortSignal: callerAbortSignal,\n commitment,\n currentNonceValue: expectedNonceValue,\n nonceAccountAddress,\n }) {\n const abortController = new AbortController();\n function handleAbort() {\n abortController.abort();\n }\n callerAbortSignal.addEventListener('abort', handleAbort, { signal: abortController.signal });\n /**\n * STEP 1: Set up a subscription for nonce account changes.\n */\n const accountNotifications = await rpcSubscriptions\n .accountNotifications(nonceAccountAddress, { commitment, encoding: 'base64' })\n .subscribe({ abortSignal: abortController.signal });\n const base58Decoder = getBase58Decoder();\n const base64Encoder = getBase64Encoder();\n function getNonceFromAccountData([base64EncodedBytes]: Base64EncodedDataResponse): Nonce {\n const data = base64Encoder.encode(base64EncodedBytes);\n const nonceValueBytes = data.slice(NONCE_VALUE_OFFSET, NONCE_VALUE_OFFSET + 32);\n return base58Decoder.decode(nonceValueBytes) as Nonce;\n }\n const nonceAccountDidAdvancePromise = (async () => {\n for await (const accountNotification of accountNotifications) {\n const nonceValue = getNonceFromAccountData(accountNotification.value.data);\n if (nonceValue !== expectedNonceValue) {\n throw new SolanaError(SOLANA_ERROR__INVALID_NONCE, {\n actualNonceValue: nonceValue,\n expectedNonceValue,\n });\n }\n }\n })();\n /**\n * STEP 2: Having subscribed for updates, make a one-shot request for the current nonce\n * value to check if it has already been advanced.\n */\n const nonceIsAlreadyInvalidPromise = (async () => {\n const { value: nonceAccount } = await rpc\n .getAccountInfo(nonceAccountAddress, {\n commitment,\n dataSlice: { length: 32, offset: NONCE_VALUE_OFFSET },\n encoding: 'base58',\n })\n .send({ abortSignal: abortController.signal });\n if (!nonceAccount) {\n throw new SolanaError(SOLANA_ERROR__NONCE_ACCOUNT_NOT_FOUND, {\n nonceAccountAddress,\n });\n }\n const nonceValue =\n // This works because we asked for the exact slice of data representing the nonce\n // value, and furthermore asked for it in `base58` encoding.\n nonceAccount.data[0] as unknown as Nonce;\n if (nonceValue !== expectedNonceValue) {\n throw new SolanaError(SOLANA_ERROR__INVALID_NONCE, {\n actualNonceValue: nonceValue,\n expectedNonceValue,\n });\n } else {\n await new Promise(() => {\n /* never resolve */\n });\n }\n })();\n try {\n return await safeRace([nonceAccountDidAdvancePromise, nonceIsAlreadyInvalidPromise]);\n } finally {\n abortController.abort();\n }\n };\n}\n","import { getSolanaErrorFromTransactionError } from '@solana/errors';\nimport { AbortController } from '@solana/event-target-impl';\nimport type { Signature } from '@solana/keys';\nimport { safeRace } from '@solana/promises';\nimport type { GetSignatureStatusesApi, Rpc } from '@solana/rpc';\nimport type { RpcSubscriptions, SignatureNotificationsApi } from '@solana/rpc-subscriptions';\nimport { type Commitment, commitmentComparator } from '@solana/rpc-types';\n\ntype GetRecentSignatureConfirmationPromiseFn = (config: {\n abortSignal: AbortSignal;\n /**\n * The level of commitment the transaction must have achieved in order for the promise to\n * resolve.\n */\n commitment: Commitment;\n /**\n * A 64 byte Ed25519 signature, encoded as a base-58 string, that uniquely identifies a\n * transaction by virtue of being the first or only signature in its list of signatures.\n */\n signature: Signature;\n}) => Promise<void>;\n\ntype CreateRecentSignatureConfirmationPromiseFactoryConfig<TCluster> = {\n rpc: Rpc<GetSignatureStatusesApi> & { '~cluster'?: TCluster };\n rpcSubscriptions: RpcSubscriptions<SignatureNotificationsApi> & { '~cluster'?: TCluster };\n};\n\n/**\n * Creates a promise that resolves when a recently-landed transaction achieves the target\n * confirmation commitment, and throws when the transaction fails with an error.\n *\n * The status of recently-landed transactions is available in the network's status cache. This\n * confirmation strategy will only yield a result if the signature is still in the status cache. To\n * fetch the status of transactions older than those available in the status cache, use the\n * {@link GetSignatureStatusesApi.getSignatureStatuses} method setting the\n * `searchTransactionHistory` configuration param to `true`.\n *\n * @param config\n *\n * @example\n * ```ts\n * import { createRecentSignatureConfirmationPromiseFactory } from '@solana/transaction-confirmation';\n *\n * const getRecentSignatureConfirmationPromise = createRecentSignatureConfirmationPromiseFactory({\n * rpc,\n * rpcSubscriptions,\n * });\n * try {\n * await getRecentSignatureConfirmationPromise({\n * commitment,\n * signature,\n * });\n * console.log(`The transaction with signature \\`${signature}\\` has achieved a commitment level of \\`${commitment}\\``);\n * } catch (e) {\n * console.error(`The transaction with signature \\`${signature}\\` failed`, e.cause);\n * throw e;\n * }\n * ```\n */\nexport function createRecentSignatureConfirmationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateRecentSignatureConfirmationPromiseFactoryConfig<'devnet'>): GetRecentSignatureConfirmationPromiseFn;\nexport function createRecentSignatureConfirmationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateRecentSignatureConfirmationPromiseFactoryConfig<'testnet'>): GetRecentSignatureConfirmationPromiseFn;\nexport function createRecentSignatureConfirmationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateRecentSignatureConfirmationPromiseFactoryConfig<'mainnet'>): GetRecentSignatureConfirmationPromiseFn;\nexport function createRecentSignatureConfirmationPromiseFactory<\n TCluster extends 'devnet' | 'mainnet' | 'testnet' | void = void,\n>({\n rpc,\n rpcSubscriptions,\n}: CreateRecentSignatureConfirmationPromiseFactoryConfig<TCluster>): GetRecentSignatureConfirmationPromiseFn {\n return async function getRecentSignatureConfirmationPromise({\n abortSignal: callerAbortSignal,\n commitment,\n signature,\n }) {\n const abortController = new AbortController();\n function handleAbort() {\n abortController.abort();\n }\n callerAbortSignal.addEventListener('abort', handleAbort, { signal: abortController.signal });\n /**\n * STEP 1: Set up a subscription for status changes to a signature.\n */\n const signatureStatusNotifications = await rpcSubscriptions\n .signatureNotifications(signature, { commitment })\n .subscribe({ abortSignal: abortController.signal });\n const signatureDidCommitPromise = (async () => {\n for await (const signatureStatusNotification of signatureStatusNotifications) {\n if (signatureStatusNotification.value.err) {\n throw getSolanaErrorFromTransactionError(signatureStatusNotification.value.err);\n } else {\n return;\n }\n }\n })();\n /**\n * STEP 2: Having subscribed for updates, make a one-shot request for the current status.\n * This will only yield a result if the signature is still in the status cache.\n */\n const signatureStatusLookupPromise = (async () => {\n const { value: signatureStatusResults } = await rpc\n .getSignatureStatuses([signature])\n .send({ abortSignal: abortController.signal });\n const signatureStatus = signatureStatusResults[0];\n if (\n signatureStatus &&\n signatureStatus.confirmationStatus &&\n commitmentComparator(signatureStatus.confirmationStatus, commitment) >= 0\n ) {\n return;\n } else {\n await new Promise(() => {\n /* never resolve */\n });\n }\n })();\n try {\n return await safeRace([signatureDidCommitPromise, signatureStatusLookupPromise]);\n } finally {\n abortController.abort();\n }\n };\n}\n","import type { Commitment } from '@solana/rpc-types';\n\ntype Config = Readonly<{\n abortSignal: AbortSignal;\n /**\n * The timeout promise will throw after 30 seconds when the commitment is `processed`, and 60\n * seconds otherwise.\n */\n commitment: Commitment;\n}>;\n\n/**\n * When no other heuristic exists to infer that a transaction has expired, you can use this promise\n * factory with a commitment level. It throws after 30 seconds when the commitment is `processed`,\n * and 60 seconds otherwise. You would typically race this with another confirmation strategy.\n *\n * @param config\n *\n * @example\n * ```ts\n * import { safeRace } from '@solana/promises';\n * import { getTimeoutPromise } from '@solana/transaction-confirmation';\n *\n * try {\n * await safeRace([getCustomTransactionConfirmationPromise(/* ... *\\/), getTimeoutPromise({ commitment })]);\n * } catch (e) {\n * if (e instanceof DOMException && e.name === 'TimeoutError') {\n * console.log('Could not confirm transaction after a timeout');\n * }\n * throw e;\n * }\n * ```\n */\nexport async function getTimeoutPromise({ abortSignal: callerAbortSignal, commitment }: Config) {\n return await new Promise((_, reject) => {\n const handleAbort = (e: AbortSignalEventMap['abort']) => {\n clearTimeout(timeoutId);\n const abortError = new DOMException((e.target as AbortSignal).reason, 'AbortError');\n reject(abortError);\n };\n callerAbortSignal.addEventListener('abort', handleAbort);\n const timeoutMs = commitment === 'processed' ? 30_000 : 60_000;\n const startMs = performance.now();\n const timeoutId =\n // We use `setTimeout` instead of `AbortSignal.timeout()` because we want to measure\n // elapsed time instead of active time.\n // See https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal/timeout_static\n setTimeout(() => {\n const elapsedMs = performance.now() - startMs;\n reject(new DOMException(`Timeout elapsed after ${elapsedMs} ms`, 'TimeoutError'));\n }, timeoutMs);\n });\n}\n","import { AbortController } from '@solana/event-target-impl';\nimport type { Signature } from '@solana/keys';\nimport { safeRace } from '@solana/promises';\nimport type { Commitment } from '@solana/rpc-types';\n\nimport { createRecentSignatureConfirmationPromiseFactory } from './confirmation-strategy-recent-signature';\n\nexport interface BaseTransactionConfirmationStrategyConfig {\n abortSignal?: AbortSignal;\n commitment: Commitment;\n getRecentSignatureConfirmationPromise: ReturnType<typeof createRecentSignatureConfirmationPromiseFactory>;\n}\n\ntype WithNonNullableAbortSignal<T> = Omit<T, 'abortSignal'> & Readonly<{ abortSignal: AbortSignal }>;\n\nexport async function raceStrategies<TConfig extends BaseTransactionConfirmationStrategyConfig>(\n signature: Signature,\n config: TConfig,\n getSpecificStrategiesForRace: (config: WithNonNullableAbortSignal<TConfig>) => readonly Promise<unknown>[],\n) {\n const { abortSignal: callerAbortSignal, commitment, getRecentSignatureConfirmationPromise } = config;\n callerAbortSignal?.throwIfAborted();\n const abortController = new AbortController();\n if (callerAbortSignal) {\n const handleAbort = () => {\n abortController.abort();\n };\n callerAbortSignal.addEventListener('abort', handleAbort, { signal: abortController.signal });\n }\n try {\n const specificStrategies = getSpecificStrategiesForRace({\n ...config,\n abortSignal: abortController.signal,\n });\n return await safeRace([\n getRecentSignatureConfirmationPromise({\n abortSignal: abortController.signal,\n commitment,\n signature,\n }),\n ...specificStrategies,\n ]);\n } finally {\n abortController.abort();\n }\n}\n","import { Signature } from '@solana/keys';\nimport {\n getSignatureFromTransaction,\n Transaction,\n TransactionWithBlockhashLifetime,\n TransactionWithDurableNonceLifetime,\n} from '@solana/transactions';\n\nimport { createBlockHeightExceedencePromiseFactory } from './confirmation-strategy-blockheight';\nimport { createNonceInvalidationPromiseFactory } from './confirmation-strategy-nonce';\nimport { BaseTransactionConfirmationStrategyConfig, raceStrategies } from './confirmation-strategy-racer';\nimport { getTimeoutPromise } from './confirmation-strategy-timeout';\n\nexport type TransactionWithLastValidBlockHeight = Omit<TransactionWithBlockhashLifetime, 'lifetimeConstraint'> & {\n lifetimeConstraint: Omit<TransactionWithBlockhashLifetime['lifetimeConstraint'], 'blockhash'>;\n};\n\ninterface WaitForDurableNonceTransactionConfirmationConfig extends BaseTransactionConfirmationStrategyConfig {\n getNonceInvalidationPromise: ReturnType<typeof createNonceInvalidationPromiseFactory>;\n transaction: Readonly<Transaction & TransactionWithDurableNonceLifetime>;\n}\n\ninterface WaitForRecentTransactionWithBlockhashLifetimeConfirmationConfig\n extends BaseTransactionConfirmationStrategyConfig {\n getBlockHeightExceedencePromise: ReturnType<typeof createBlockHeightExceedencePromiseFactory>;\n transaction: Readonly<Transaction & TransactionWithLastValidBlockHeight>;\n}\n\ninterface WaitForRecentTransactionWithTimeBasedLifetimeConfirmationConfig\n extends BaseTransactionConfirmationStrategyConfig {\n getTimeoutPromise: typeof getTimeoutPromise;\n /**\n * A 64 byte Ed25519 signature, encoded as a base-58 string, that uniquely identifies a\n * transaction by virtue of being the first or only signature in its list of signatures.\n */\n signature: Signature;\n}\n\n/**\n * Supply your own confirmation implementations to this function to create a custom nonce\n * transaction confirmation strategy.\n *\n * @example\n * ```ts\n * import { waitForDurableNonceTransactionConfirmation } from '@solana/transaction-confirmation';\n *\n * try {\n * await waitForDurableNonceTransactionConfirmation({\n * getNonceInvalidationPromise({ abortSignal, commitment, currentNonceValue, nonceAccountAddress }) {\n * // Return a promise that rejects when a nonce becomes invalid.\n * },\n * getRecentSignatureConfirmationPromise({ abortSignal, commitment, signature }) {\n * // Return a promise that resolves when a transaction achieves confirmation\n * },\n * });\n * } catch (e) {\n * // Handle errors.\n * }\n * ```\n */\nexport async function waitForDurableNonceTransactionConfirmation(\n config: WaitForDurableNonceTransactionConfirmationConfig,\n): Promise<void> {\n await raceStrategies(\n getSignatureFromTransaction(config.transaction),\n config,\n function getSpecificStrategiesForRace({ abortSignal, commitment, getNonceInvalidationPromise, transaction }) {\n return [\n getNonceInvalidationPromise({\n abortSignal,\n commitment,\n currentNonceValue: transaction.lifetimeConstraint.nonce,\n nonceAccountAddress: transaction.lifetimeConstraint.nonceAccountAddress,\n }),\n ];\n },\n );\n}\n\n/**\n * Supply your own confirmation implementations to this function to create a custom confirmation\n * strategy for recently-landed transactions.\n *\n * @example\n * ```ts\n * import { waitForRecentTransactionConfirmation } from '@solana/transaction-confirmation';\n *\n * try {\n * await waitForRecentTransactionConfirmation({\n * getBlockHeightExceedencePromise({ abortSignal, commitment, lastValidBlockHeight }) {\n * // Return a promise that rejects when the blockhash's block height has been exceeded\n * },\n * getRecentSignatureConfirmationPromise({ abortSignal, commitment, signature }) {\n * // Return a promise that resolves when a transaction achieves confirmation\n * },\n * });\n * } catch (e) {\n * // Handle errors.\n * }\n * ```\n */\nexport async function waitForRecentTransactionConfirmation(\n config: WaitForRecentTransactionWithBlockhashLifetimeConfirmationConfig,\n): Promise<void> {\n await raceStrategies(\n getSignatureFromTransaction(config.transaction),\n config,\n function getSpecificStrategiesForRace({\n abortSignal,\n commitment,\n getBlockHeightExceedencePromise,\n transaction,\n }) {\n return [\n getBlockHeightExceedencePromise({\n abortSignal,\n commitment,\n lastValidBlockHeight: transaction.lifetimeConstraint.lastValidBlockHeight,\n }),\n ];\n },\n );\n}\n\n/** @deprecated */\nexport async function waitForRecentTransactionConfirmationUntilTimeout(\n config: WaitForRecentTransactionWithTimeBasedLifetimeConfirmationConfig,\n): Promise<void> {\n await raceStrategies(\n config.signature,\n config,\n function getSpecificStrategiesForRace({ abortSignal, commitment, getTimeoutPromise }) {\n return [\n getTimeoutPromise({\n abortSignal,\n commitment,\n }),\n ];\n },\n );\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../event-target-impl/src/index.browser.ts","../src/confirmation-strategy-blockheight.ts","../src/confirmation-strategy-nonce.ts","../src/confirmation-strategy-recent-signature.ts","../src/confirmation-strategy-timeout.ts","../src/confirmation-strategy-racer.ts","../src/waiters.ts"],"names":["AbortController","SolanaError","safeRace","getTimeoutPromise"],"mappings":"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","file":"index.browser.mjs","sourcesContent":["export const AbortController = globalThis.AbortController;\nexport const EventTarget = globalThis.EventTarget;\n","import { SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED, SolanaError } from '@solana/errors';\nimport { AbortController } from '@solana/event-target-impl';\nimport type { GetEpochInfoApi, Rpc } from '@solana/rpc';\nimport type { RpcSubscriptions, SlotNotificationsApi } from '@solana/rpc-subscriptions';\nimport type { Commitment } from '@solana/rpc-types';\n\ntype GetBlockHeightExceedencePromiseFn = (config: {\n abortSignal: AbortSignal;\n /**\n * Fetch the block height as of the highest slot that has reached this level of commitment.\n *\n * @defaultValue Whichever default is applied by the underlying {@link RpcApi} in use. For\n * example, when using an API created by a `createSolanaRpc*()` helper, the default commitment\n * is `\"confirmed\"` unless configured otherwise. Unmitigated by an API layer on the client, the\n * default commitment applied by the server is `\"finalized\"`.\n */\n commitment?: Commitment;\n /** The block height after which to reject the promise */\n lastValidBlockHeight: bigint;\n}) => Promise<void>;\n\ntype CreateBlockHeightExceedencePromiseFactoryConfig<TCluster> = {\n rpc: Rpc<GetEpochInfoApi> & { '~cluster'?: TCluster };\n rpcSubscriptions: RpcSubscriptions<SlotNotificationsApi> & { '~cluster'?: TCluster };\n};\n\n/**\n * Creates a promise that throws when the network progresses past the block height after which the\n * supplied blockhash is considered expired for use as a transaction lifetime specifier.\n *\n * When a transaction's lifetime is tied to a blockhash, that transaction can be landed on the\n * network until that blockhash expires. All blockhashes have a block height after which they are\n * considered to have expired.\n *\n * @param config\n *\n * @example\n * ```ts\n * import { isSolanaError, SolanaError } from '@solana/errors';\n * import { createBlockHeightExceedencePromiseFactory } from '@solana/transaction-confirmation';\n *\n * const getBlockHeightExceedencePromise = createBlockHeightExceedencePromiseFactory({\n * rpc,\n * rpcSubscriptions,\n * });\n * try {\n * await getBlockHeightExceedencePromise({ lastValidBlockHeight });\n * } catch (e) {\n * if (isSolanaError(e, SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED)) {\n * console.error(\n * `The block height of the network has exceeded ${e.context.lastValidBlockHeight}. ` +\n * `It is now ${e.context.currentBlockHeight}`,\n * );\n * // Re-sign and retry the transaction.\n * return;\n * }\n * throw e;\n * }\n * ```\n */\nexport function createBlockHeightExceedencePromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateBlockHeightExceedencePromiseFactoryConfig<'devnet'>): GetBlockHeightExceedencePromiseFn;\nexport function createBlockHeightExceedencePromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateBlockHeightExceedencePromiseFactoryConfig<'testnet'>): GetBlockHeightExceedencePromiseFn;\nexport function createBlockHeightExceedencePromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateBlockHeightExceedencePromiseFactoryConfig<'mainnet'>): GetBlockHeightExceedencePromiseFn;\nexport function createBlockHeightExceedencePromiseFactory<\n TCluster extends 'devnet' | 'mainnet' | 'testnet' | void = void,\n>({\n rpc,\n rpcSubscriptions,\n}: CreateBlockHeightExceedencePromiseFactoryConfig<TCluster>): GetBlockHeightExceedencePromiseFn {\n return async function getBlockHeightExceedencePromise({\n abortSignal: callerAbortSignal,\n commitment,\n lastValidBlockHeight,\n }): Promise<never> {\n callerAbortSignal.throwIfAborted();\n const abortController = new AbortController();\n const handleAbort = () => {\n abortController.abort();\n };\n callerAbortSignal.addEventListener('abort', handleAbort, { signal: abortController.signal });\n async function getBlockHeightAndDifferenceBetweenSlotHeightAndBlockHeight() {\n const { absoluteSlot, blockHeight } = await rpc\n .getEpochInfo({ commitment })\n .send({ abortSignal: abortController.signal });\n return {\n blockHeight,\n differenceBetweenSlotHeightAndBlockHeight: absoluteSlot - blockHeight,\n };\n }\n try {\n const [slotNotifications, { blockHeight: initialBlockHeight, differenceBetweenSlotHeightAndBlockHeight }] =\n await Promise.all([\n rpcSubscriptions.slotNotifications().subscribe({ abortSignal: abortController.signal }),\n getBlockHeightAndDifferenceBetweenSlotHeightAndBlockHeight(),\n ]);\n callerAbortSignal.throwIfAborted();\n let currentBlockHeight = initialBlockHeight;\n if (currentBlockHeight <= lastValidBlockHeight) {\n let lastKnownDifferenceBetweenSlotHeightAndBlockHeight = differenceBetweenSlotHeightAndBlockHeight;\n for await (const slotNotification of slotNotifications) {\n const { slot } = slotNotification;\n if (slot - lastKnownDifferenceBetweenSlotHeightAndBlockHeight > lastValidBlockHeight) {\n // Before making a final decision, recheck the actual block height.\n const {\n blockHeight: recheckedBlockHeight,\n differenceBetweenSlotHeightAndBlockHeight: currentDifferenceBetweenSlotHeightAndBlockHeight,\n } = await getBlockHeightAndDifferenceBetweenSlotHeightAndBlockHeight();\n currentBlockHeight = recheckedBlockHeight;\n if (currentBlockHeight > lastValidBlockHeight) {\n // Verified; the block height has been exceeded.\n break;\n } else {\n // The block height has not been exceeded, which implies that the\n // difference between the slot height and the block height has grown\n // (ie. some blocks have been skipped since we started). Recalibrate the\n // difference and keep waiting.\n lastKnownDifferenceBetweenSlotHeightAndBlockHeight =\n currentDifferenceBetweenSlotHeightAndBlockHeight;\n }\n }\n }\n }\n callerAbortSignal.throwIfAborted();\n throw new SolanaError(SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED, {\n currentBlockHeight,\n lastValidBlockHeight,\n });\n } finally {\n abortController.abort();\n }\n };\n}\n","import type { Address } from '@solana/addresses';\nimport { getBase58Decoder, getBase64Encoder } from '@solana/codecs-strings';\nimport { SOLANA_ERROR__INVALID_NONCE, SOLANA_ERROR__NONCE_ACCOUNT_NOT_FOUND, SolanaError } from '@solana/errors';\nimport { AbortController } from '@solana/event-target-impl';\nimport { safeRace } from '@solana/promises';\nimport type { GetAccountInfoApi, Rpc } from '@solana/rpc';\nimport type { AccountNotificationsApi, RpcSubscriptions } from '@solana/rpc-subscriptions';\nimport type { Base64EncodedDataResponse, Commitment } from '@solana/rpc-types';\nimport { Nonce } from '@solana/transaction-messages';\n\ntype GetNonceInvalidationPromiseFn = (config: {\n abortSignal: AbortSignal;\n /**\n * Fetch the nonce account details as of the highest slot that has reached this level of\n * commitment.\n */\n commitment: Commitment;\n /**\n * The value of the nonce that we would expect to see in the nonce account in order for any\n * transaction with that nonce-based lifetime to be considered valid.\n */\n currentNonceValue: Nonce;\n /** The address of the account in which the currently-valid nonce value is stored */\n nonceAccountAddress: Address;\n}) => Promise<void>;\n\ntype CreateNonceInvalidationPromiseFactoryConfig<TCluster> = {\n rpc: Rpc<GetAccountInfoApi> & { '~cluster'?: TCluster };\n rpcSubscriptions: RpcSubscriptions<AccountNotificationsApi> & { '~cluster'?: TCluster };\n};\n\nconst NONCE_VALUE_OFFSET =\n 4 + // version(u32)\n 4 + // state(u32)\n 32; // nonce authority(pubkey)\n// Then comes the nonce value.\n\n/**\n * Creates a promise that throws when the value stored in a nonce account is not the expected one.\n *\n * When a transaction's lifetime is tied to the value stored in a nonce account, that transaction\n * can be landed on the network until the nonce is advanced to a new value.\n *\n * @param config\n *\n * @example\n * ```ts\n * import { isSolanaError, SolanaError } from '@solana/errors';\n * import { createNonceInvalidationPromiseFactory } from '@solana/transaction-confirmation';\n *\n * const getNonceInvalidationPromise = createNonceInvalidationPromiseFactory({\n * rpc,\n * rpcSubscriptions,\n * });\n * try {\n * await getNonceInvalidationPromise({\n * currentNonceValue,\n * nonceAccountAddress,\n * });\n * } catch (e) {\n * if (isSolanaError(e, SOLANA_ERROR__NONCE_INVALID)) {\n * console.error(`The nonce has advanced to ${e.context.actualNonceValue}`);\n * // Re-sign and retry the transaction.\n * return;\n * } else if (isSolanaError(e, SOLANA_ERROR__NONCE_ACCOUNT_NOT_FOUND)) {\n * console.error(`No nonce account was found at ${nonceAccountAddress}`);\n * }\n * throw e;\n * }\n * ```\n */\nexport function createNonceInvalidationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateNonceInvalidationPromiseFactoryConfig<'devnet'>): GetNonceInvalidationPromiseFn;\nexport function createNonceInvalidationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateNonceInvalidationPromiseFactoryConfig<'testnet'>): GetNonceInvalidationPromiseFn;\nexport function createNonceInvalidationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateNonceInvalidationPromiseFactoryConfig<'mainnet'>): GetNonceInvalidationPromiseFn;\nexport function createNonceInvalidationPromiseFactory<TCluster extends 'devnet' | 'mainnet' | 'testnet' | void = void>({\n rpc,\n rpcSubscriptions,\n}: CreateNonceInvalidationPromiseFactoryConfig<TCluster>): GetNonceInvalidationPromiseFn {\n return async function getNonceInvalidationPromise({\n abortSignal: callerAbortSignal,\n commitment,\n currentNonceValue: expectedNonceValue,\n nonceAccountAddress,\n }) {\n const abortController = new AbortController();\n function handleAbort() {\n abortController.abort();\n }\n callerAbortSignal.addEventListener('abort', handleAbort, { signal: abortController.signal });\n /**\n * STEP 1: Set up a subscription for nonce account changes.\n */\n const accountNotifications = await rpcSubscriptions\n .accountNotifications(nonceAccountAddress, { commitment, encoding: 'base64' })\n .subscribe({ abortSignal: abortController.signal });\n const base58Decoder = getBase58Decoder();\n const base64Encoder = getBase64Encoder();\n function getNonceFromAccountData([base64EncodedBytes]: Base64EncodedDataResponse): Nonce {\n const data = base64Encoder.encode(base64EncodedBytes);\n const nonceValueBytes = data.slice(NONCE_VALUE_OFFSET, NONCE_VALUE_OFFSET + 32);\n return base58Decoder.decode(nonceValueBytes) as Nonce;\n }\n const nonceAccountDidAdvancePromise = (async () => {\n for await (const accountNotification of accountNotifications) {\n const nonceValue = getNonceFromAccountData(accountNotification.value.data);\n if (nonceValue !== expectedNonceValue) {\n throw new SolanaError(SOLANA_ERROR__INVALID_NONCE, {\n actualNonceValue: nonceValue,\n expectedNonceValue,\n });\n }\n }\n })();\n /**\n * STEP 2: Having subscribed for updates, make a one-shot request for the current nonce\n * value to check if it has already been advanced.\n */\n const nonceIsAlreadyInvalidPromise = (async () => {\n const { value: nonceAccount } = await rpc\n .getAccountInfo(nonceAccountAddress, {\n commitment,\n dataSlice: { length: 32, offset: NONCE_VALUE_OFFSET },\n encoding: 'base58',\n })\n .send({ abortSignal: abortController.signal });\n if (!nonceAccount) {\n throw new SolanaError(SOLANA_ERROR__NONCE_ACCOUNT_NOT_FOUND, {\n nonceAccountAddress,\n });\n }\n const nonceValue =\n // This works because we asked for the exact slice of data representing the nonce\n // value, and furthermore asked for it in `base58` encoding.\n nonceAccount.data[0] as unknown as Nonce;\n if (nonceValue !== expectedNonceValue) {\n throw new SolanaError(SOLANA_ERROR__INVALID_NONCE, {\n actualNonceValue: nonceValue,\n expectedNonceValue,\n });\n } else {\n await new Promise(() => {\n /* never resolve */\n });\n }\n })();\n try {\n return await safeRace([nonceAccountDidAdvancePromise, nonceIsAlreadyInvalidPromise]);\n } finally {\n abortController.abort();\n }\n };\n}\n","import { getSolanaErrorFromTransactionError } from '@solana/errors';\nimport { AbortController } from '@solana/event-target-impl';\nimport type { Signature } from '@solana/keys';\nimport { safeRace } from '@solana/promises';\nimport type { GetSignatureStatusesApi, Rpc } from '@solana/rpc';\nimport type { RpcSubscriptions, SignatureNotificationsApi } from '@solana/rpc-subscriptions';\nimport { type Commitment, commitmentComparator } from '@solana/rpc-types';\n\ntype GetRecentSignatureConfirmationPromiseFn = (config: {\n abortSignal: AbortSignal;\n /**\n * The level of commitment the transaction must have achieved in order for the promise to\n * resolve.\n */\n commitment: Commitment;\n /**\n * A 64 byte Ed25519 signature, encoded as a base-58 string, that uniquely identifies a\n * transaction by virtue of being the first or only signature in its list of signatures.\n */\n signature: Signature;\n}) => Promise<void>;\n\ntype CreateRecentSignatureConfirmationPromiseFactoryConfig<TCluster> = {\n rpc: Rpc<GetSignatureStatusesApi> & { '~cluster'?: TCluster };\n rpcSubscriptions: RpcSubscriptions<SignatureNotificationsApi> & { '~cluster'?: TCluster };\n};\n\n/**\n * Creates a promise that resolves when a recently-landed transaction achieves the target\n * confirmation commitment, and throws when the transaction fails with an error.\n *\n * The status of recently-landed transactions is available in the network's status cache. This\n * confirmation strategy will only yield a result if the signature is still in the status cache. To\n * fetch the status of transactions older than those available in the status cache, use the\n * {@link GetSignatureStatusesApi.getSignatureStatuses} method setting the\n * `searchTransactionHistory` configuration param to `true`.\n *\n * @param config\n *\n * @example\n * ```ts\n * import { createRecentSignatureConfirmationPromiseFactory } from '@solana/transaction-confirmation';\n *\n * const getRecentSignatureConfirmationPromise = createRecentSignatureConfirmationPromiseFactory({\n * rpc,\n * rpcSubscriptions,\n * });\n * try {\n * await getRecentSignatureConfirmationPromise({\n * commitment,\n * signature,\n * });\n * console.log(`The transaction with signature \\`${signature}\\` has achieved a commitment level of \\`${commitment}\\``);\n * } catch (e) {\n * console.error(`The transaction with signature \\`${signature}\\` failed`, e.cause);\n * throw e;\n * }\n * ```\n */\nexport function createRecentSignatureConfirmationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateRecentSignatureConfirmationPromiseFactoryConfig<'devnet'>): GetRecentSignatureConfirmationPromiseFn;\nexport function createRecentSignatureConfirmationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateRecentSignatureConfirmationPromiseFactoryConfig<'testnet'>): GetRecentSignatureConfirmationPromiseFn;\nexport function createRecentSignatureConfirmationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateRecentSignatureConfirmationPromiseFactoryConfig<'mainnet'>): GetRecentSignatureConfirmationPromiseFn;\nexport function createRecentSignatureConfirmationPromiseFactory<\n TCluster extends 'devnet' | 'mainnet' | 'testnet' | void = void,\n>({\n rpc,\n rpcSubscriptions,\n}: CreateRecentSignatureConfirmationPromiseFactoryConfig<TCluster>): GetRecentSignatureConfirmationPromiseFn {\n return async function getRecentSignatureConfirmationPromise({\n abortSignal: callerAbortSignal,\n commitment,\n signature,\n }) {\n const abortController = new AbortController();\n function handleAbort() {\n abortController.abort();\n }\n callerAbortSignal.addEventListener('abort', handleAbort, { signal: abortController.signal });\n /**\n * STEP 1: Set up a subscription for status changes to a signature.\n */\n const signatureStatusNotifications = await rpcSubscriptions\n .signatureNotifications(signature, { commitment })\n .subscribe({ abortSignal: abortController.signal });\n const signatureDidCommitPromise = (async () => {\n for await (const signatureStatusNotification of signatureStatusNotifications) {\n if (signatureStatusNotification.value.err) {\n throw getSolanaErrorFromTransactionError(signatureStatusNotification.value.err);\n } else {\n return;\n }\n }\n })();\n /**\n * STEP 2: Having subscribed for updates, make a one-shot request for the current status.\n * This will only yield a result if the signature is still in the status cache.\n */\n const signatureStatusLookupPromise = (async () => {\n const { value: signatureStatusResults } = await rpc\n .getSignatureStatuses([signature])\n .send({ abortSignal: abortController.signal });\n const signatureStatus = signatureStatusResults[0];\n if (\n signatureStatus?.confirmationStatus &&\n commitmentComparator(signatureStatus.confirmationStatus, commitment) >= 0\n ) {\n return;\n } else if (signatureStatus?.err) {\n throw getSolanaErrorFromTransactionError(signatureStatus.err);\n } else {\n await new Promise(() => {\n /* never resolve */\n });\n }\n })();\n try {\n return await safeRace([signatureDidCommitPromise, signatureStatusLookupPromise]);\n } finally {\n abortController.abort();\n }\n };\n}\n","import type { Commitment } from '@solana/rpc-types';\n\ntype Config = Readonly<{\n abortSignal: AbortSignal;\n /**\n * The timeout promise will throw after 30 seconds when the commitment is `processed`, and 60\n * seconds otherwise.\n */\n commitment: Commitment;\n}>;\n\n/**\n * When no other heuristic exists to infer that a transaction has expired, you can use this promise\n * factory with a commitment level. It throws after 30 seconds when the commitment is `processed`,\n * and 60 seconds otherwise. You would typically race this with another confirmation strategy.\n *\n * @param config\n *\n * @example\n * ```ts\n * import { safeRace } from '@solana/promises';\n * import { getTimeoutPromise } from '@solana/transaction-confirmation';\n *\n * try {\n * await safeRace([getCustomTransactionConfirmationPromise(/* ... *\\/), getTimeoutPromise({ commitment })]);\n * } catch (e) {\n * if (e instanceof DOMException && e.name === 'TimeoutError') {\n * console.log('Could not confirm transaction after a timeout');\n * }\n * throw e;\n * }\n * ```\n */\nexport async function getTimeoutPromise({ abortSignal: callerAbortSignal, commitment }: Config) {\n return await new Promise((_, reject) => {\n const handleAbort = (e: AbortSignalEventMap['abort']) => {\n clearTimeout(timeoutId);\n const abortError = new DOMException((e.target as AbortSignal).reason, 'AbortError');\n reject(abortError);\n };\n callerAbortSignal.addEventListener('abort', handleAbort);\n const timeoutMs = commitment === 'processed' ? 30_000 : 60_000;\n const startMs = performance.now();\n const timeoutId =\n // We use `setTimeout` instead of `AbortSignal.timeout()` because we want to measure\n // elapsed time instead of active time.\n // See https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal/timeout_static\n setTimeout(() => {\n const elapsedMs = performance.now() - startMs;\n reject(new DOMException(`Timeout elapsed after ${elapsedMs} ms`, 'TimeoutError'));\n }, timeoutMs);\n });\n}\n","import { AbortController } from '@solana/event-target-impl';\nimport type { Signature } from '@solana/keys';\nimport { safeRace } from '@solana/promises';\nimport type { Commitment } from '@solana/rpc-types';\n\nimport { createRecentSignatureConfirmationPromiseFactory } from './confirmation-strategy-recent-signature';\n\nexport interface BaseTransactionConfirmationStrategyConfig {\n abortSignal?: AbortSignal;\n commitment: Commitment;\n getRecentSignatureConfirmationPromise: ReturnType<typeof createRecentSignatureConfirmationPromiseFactory>;\n}\n\ntype WithNonNullableAbortSignal<T> = Omit<T, 'abortSignal'> & Readonly<{ abortSignal: AbortSignal }>;\n\nexport async function raceStrategies<TConfig extends BaseTransactionConfirmationStrategyConfig>(\n signature: Signature,\n config: TConfig,\n getSpecificStrategiesForRace: (config: WithNonNullableAbortSignal<TConfig>) => readonly Promise<unknown>[],\n) {\n const { abortSignal: callerAbortSignal, commitment, getRecentSignatureConfirmationPromise } = config;\n callerAbortSignal?.throwIfAborted();\n const abortController = new AbortController();\n if (callerAbortSignal) {\n const handleAbort = () => {\n abortController.abort();\n };\n callerAbortSignal.addEventListener('abort', handleAbort, { signal: abortController.signal });\n }\n try {\n const specificStrategies = getSpecificStrategiesForRace({\n ...config,\n abortSignal: abortController.signal,\n });\n return await safeRace([\n getRecentSignatureConfirmationPromise({\n abortSignal: abortController.signal,\n commitment,\n signature,\n }),\n ...specificStrategies,\n ]);\n } finally {\n abortController.abort();\n }\n}\n","import { Signature } from '@solana/keys';\nimport {\n getSignatureFromTransaction,\n Transaction,\n TransactionWithBlockhashLifetime,\n TransactionWithDurableNonceLifetime,\n} from '@solana/transactions';\n\nimport { createBlockHeightExceedencePromiseFactory } from './confirmation-strategy-blockheight';\nimport { createNonceInvalidationPromiseFactory } from './confirmation-strategy-nonce';\nimport { BaseTransactionConfirmationStrategyConfig, raceStrategies } from './confirmation-strategy-racer';\nimport { getTimeoutPromise } from './confirmation-strategy-timeout';\n\nexport type TransactionWithLastValidBlockHeight = Omit<TransactionWithBlockhashLifetime, 'lifetimeConstraint'> & {\n lifetimeConstraint: Omit<TransactionWithBlockhashLifetime['lifetimeConstraint'], 'blockhash'>;\n};\n\ninterface WaitForDurableNonceTransactionConfirmationConfig extends BaseTransactionConfirmationStrategyConfig {\n getNonceInvalidationPromise: ReturnType<typeof createNonceInvalidationPromiseFactory>;\n transaction: Readonly<Transaction & TransactionWithDurableNonceLifetime>;\n}\n\ninterface WaitForRecentTransactionWithBlockhashLifetimeConfirmationConfig\n extends BaseTransactionConfirmationStrategyConfig {\n getBlockHeightExceedencePromise: ReturnType<typeof createBlockHeightExceedencePromiseFactory>;\n transaction: Readonly<Transaction & TransactionWithLastValidBlockHeight>;\n}\n\ninterface WaitForRecentTransactionWithTimeBasedLifetimeConfirmationConfig\n extends BaseTransactionConfirmationStrategyConfig {\n getTimeoutPromise: typeof getTimeoutPromise;\n /**\n * A 64 byte Ed25519 signature, encoded as a base-58 string, that uniquely identifies a\n * transaction by virtue of being the first or only signature in its list of signatures.\n */\n signature: Signature;\n}\n\n/**\n * Supply your own confirmation implementations to this function to create a custom nonce\n * transaction confirmation strategy.\n *\n * @example\n * ```ts\n * import { waitForDurableNonceTransactionConfirmation } from '@solana/transaction-confirmation';\n *\n * try {\n * await waitForDurableNonceTransactionConfirmation({\n * getNonceInvalidationPromise({ abortSignal, commitment, currentNonceValue, nonceAccountAddress }) {\n * // Return a promise that rejects when a nonce becomes invalid.\n * },\n * getRecentSignatureConfirmationPromise({ abortSignal, commitment, signature }) {\n * // Return a promise that resolves when a transaction achieves confirmation\n * },\n * });\n * } catch (e) {\n * // Handle errors.\n * }\n * ```\n */\nexport async function waitForDurableNonceTransactionConfirmation(\n config: WaitForDurableNonceTransactionConfirmationConfig,\n): Promise<void> {\n await raceStrategies(\n getSignatureFromTransaction(config.transaction),\n config,\n function getSpecificStrategiesForRace({ abortSignal, commitment, getNonceInvalidationPromise, transaction }) {\n return [\n getNonceInvalidationPromise({\n abortSignal,\n commitment,\n currentNonceValue: transaction.lifetimeConstraint.nonce,\n nonceAccountAddress: transaction.lifetimeConstraint.nonceAccountAddress,\n }),\n ];\n },\n );\n}\n\n/**\n * Supply your own confirmation implementations to this function to create a custom confirmation\n * strategy for recently-landed transactions.\n *\n * @example\n * ```ts\n * import { waitForRecentTransactionConfirmation } from '@solana/transaction-confirmation';\n *\n * try {\n * await waitForRecentTransactionConfirmation({\n * getBlockHeightExceedencePromise({ abortSignal, commitment, lastValidBlockHeight }) {\n * // Return a promise that rejects when the blockhash's block height has been exceeded\n * },\n * getRecentSignatureConfirmationPromise({ abortSignal, commitment, signature }) {\n * // Return a promise that resolves when a transaction achieves confirmation\n * },\n * });\n * } catch (e) {\n * // Handle errors.\n * }\n * ```\n */\nexport async function waitForRecentTransactionConfirmation(\n config: WaitForRecentTransactionWithBlockhashLifetimeConfirmationConfig,\n): Promise<void> {\n await raceStrategies(\n getSignatureFromTransaction(config.transaction),\n config,\n function getSpecificStrategiesForRace({\n abortSignal,\n commitment,\n getBlockHeightExceedencePromise,\n transaction,\n }) {\n return [\n getBlockHeightExceedencePromise({\n abortSignal,\n commitment,\n lastValidBlockHeight: transaction.lifetimeConstraint.lastValidBlockHeight,\n }),\n ];\n },\n );\n}\n\n/** @deprecated */\nexport async function waitForRecentTransactionConfirmationUntilTimeout(\n config: WaitForRecentTransactionWithTimeBasedLifetimeConfirmationConfig,\n): Promise<void> {\n await raceStrategies(\n config.signature,\n config,\n function getSpecificStrategiesForRace({ abortSignal, commitment, getTimeoutPromise }) {\n return [\n getTimeoutPromise({\n abortSignal,\n commitment,\n }),\n ];\n },\n );\n}\n"]}
|
package/dist/index.native.mjs
CHANGED
|
@@ -164,8 +164,10 @@ function createRecentSignatureConfirmationPromiseFactory({
|
|
|
164
164
|
const signatureStatusLookupPromise = (async () => {
|
|
165
165
|
const { value: signatureStatusResults } = await rpc.getSignatureStatuses([signature]).send({ abortSignal: abortController.signal });
|
|
166
166
|
const signatureStatus = signatureStatusResults[0];
|
|
167
|
-
if (signatureStatus
|
|
167
|
+
if (signatureStatus?.confirmationStatus && commitmentComparator(signatureStatus.confirmationStatus, commitment) >= 0) {
|
|
168
168
|
return;
|
|
169
|
+
} else if (signatureStatus?.err) {
|
|
170
|
+
throw getSolanaErrorFromTransactionError(signatureStatus.err);
|
|
169
171
|
} else {
|
|
170
172
|
await new Promise(() => {
|
|
171
173
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../event-target-impl/src/index.browser.ts","../src/confirmation-strategy-blockheight.ts","../src/confirmation-strategy-nonce.ts","../src/confirmation-strategy-recent-signature.ts","../src/confirmation-strategy-timeout.ts","../src/confirmation-strategy-racer.ts","../src/waiters.ts"],"names":["AbortController","SolanaError","safeRace","getTimeoutPromise"],"mappings":";;;;;;;;;AAAO,IAAMA,IAAkB,UAAW,CAAA,eAAA;;;ACwEnC,SAAS,yCAEd,CAAA;AAAA,EACE,GAAA;AAAA,EACA;AACJ,CAAiG,EAAA;AAC7F,EAAA,OAAO,eAAe,+BAAgC,CAAA;AAAA,IAClD,WAAa,EAAA,iBAAA;AAAA,IACb,UAAA;AAAA,IACA;AAAA,GACe,EAAA;AACf,IAAA,iBAAA,CAAkB,cAAe,EAAA;AACjC,IAAM,MAAA,eAAA,GAAkB,IAAI,CAAgB,EAAA;AAC5C,IAAA,MAAM,cAAc,MAAM;AACtB,MAAA,eAAA,CAAgB,KAAM,EAAA;AAAA,KAC1B;AACA,IAAA,iBAAA,CAAkB,iBAAiB,OAAS,EAAA,WAAA,EAAa,EAAE,MAAQ,EAAA,eAAA,CAAgB,QAAQ,CAAA;AAC3F,IAAA,eAAe,0DAA6D,GAAA;AACxE,MAAA,MAAM,EAAE,YAAc,EAAA,WAAA,EAAgB,GAAA,MAAM,IACvC,YAAa,CAAA,EAAE,UAAW,EAAC,EAC3B,IAAK,CAAA,EAAE,WAAa,EAAA,eAAA,CAAgB,QAAQ,CAAA;AACjD,MAAO,OAAA;AAAA,QACH,WAAA;AAAA,QACA,2CAA2C,YAAe,GAAA;AAAA,OAC9D;AAAA;AAEJ,IAAI,IAAA;AACA,MAAM,MAAA,CAAC,iBAAmB,EAAA,EAAE,WAAa,EAAA,kBAAA,EAAoB,2CAA2C,CAAA,GACpG,MAAM,OAAA,CAAQ,GAAI,CAAA;AAAA,QACd,gBAAA,CAAiB,mBAAoB,CAAA,SAAA,CAAU,EAAE,WAAa,EAAA,eAAA,CAAgB,QAAQ,CAAA;AAAA,QACtF,0DAA2D;AAAA,OAC9D,CAAA;AACL,MAAA,iBAAA,CAAkB,cAAe,EAAA;AACjC,MAAA,IAAI,kBAAqB,GAAA,kBAAA;AACzB,MAAA,IAAI,sBAAsB,oBAAsB,EAAA;AAC5C,QAAA,IAAI,kDAAqD,GAAA,yCAAA;AACzD,QAAA,WAAA,MAAiB,oBAAoB,iBAAmB,EAAA;AACpD,UAAM,MAAA,EAAE,MAAS,GAAA,gBAAA;AACjB,UAAI,IAAA,IAAA,GAAO,qDAAqD,oBAAsB,EAAA;AAElF,YAAM,MAAA;AAAA,cACF,WAAa,EAAA,oBAAA;AAAA,cACb,yCAA2C,EAAA;AAAA,aAC/C,GAAI,MAAM,0DAA2D,EAAA;AACrE,YAAqB,kBAAA,GAAA,oBAAA;AACrB,YAAA,IAAI,qBAAqB,oBAAsB,EAAA;AAE3C,cAAA;AAAA,aACG,MAAA;AAKH,cACI,kDAAA,GAAA,gDAAA;AAAA;AACR;AACJ;AACJ;AAEJ,MAAA,iBAAA,CAAkB,cAAe,EAAA;AACjC,MAAM,MAAA,IAAI,YAAY,mCAAqC,EAAA;AAAA,QACvD,kBAAA;AAAA,QACA;AAAA,OACH,CAAA;AAAA,KACH,SAAA;AACE,MAAA,eAAA,CAAgB,KAAM,EAAA;AAAA;AAC1B,GACJ;AACJ;AC7GA,IAAM,kBACF,GAAA,CAAA;AACA,CAAA;AACA,EAAA;AAiDG,SAAS,qCAAuG,CAAA;AAAA,EACnH,GAAA;AAAA,EACA;AACJ,CAAyF,EAAA;AACrF,EAAA,OAAO,eAAe,2BAA4B,CAAA;AAAA,IAC9C,WAAa,EAAA,iBAAA;AAAA,IACb,UAAA;AAAA,IACA,iBAAmB,EAAA,kBAAA;AAAA,IACnB;AAAA,GACD,EAAA;AACC,IAAM,MAAA,eAAA,GAAkB,IAAI,CAAgB,EAAA;AAC5C,IAAA,SAAS,WAAc,GAAA;AACnB,MAAA,eAAA,CAAgB,KAAM,EAAA;AAAA;AAE1B,IAAA,iBAAA,CAAkB,iBAAiB,OAAS,EAAA,WAAA,EAAa,EAAE,MAAQ,EAAA,eAAA,CAAgB,QAAQ,CAAA;AAI3F,IAAA,MAAM,uBAAuB,MAAM,gBAAA,CAC9B,oBAAqB,CAAA,mBAAA,EAAqB,EAAE,UAAY,EAAA,QAAA,EAAU,QAAS,EAAC,EAC5E,SAAU,CAAA,EAAE,WAAa,EAAA,eAAA,CAAgB,QAAQ,CAAA;AACtD,IAAA,MAAM,gBAAgB,gBAAiB,EAAA;AACvC,IAAA,MAAM,gBAAgB,gBAAiB,EAAA;AACvC,IAAS,SAAA,uBAAA,CAAwB,CAAC,kBAAkB,CAAqC,EAAA;AACrF,MAAM,MAAA,IAAA,GAAO,aAAc,CAAA,MAAA,CAAO,kBAAkB,CAAA;AACpD,MAAA,MAAM,eAAkB,GAAA,IAAA,CAAK,KAAM,CAAA,kBAAA,EAAoB,qBAAqB,EAAE,CAAA;AAC9E,MAAO,OAAA,aAAA,CAAc,OAAO,eAAe,CAAA;AAAA;AAE/C,IAAA,MAAM,iCAAiC,YAAY;AAC/C,MAAA,WAAA,MAAiB,uBAAuB,oBAAsB,EAAA;AAC1D,QAAA,MAAM,UAAa,GAAA,uBAAA,CAAwB,mBAAoB,CAAA,KAAA,CAAM,IAAI,CAAA;AACzE,QAAA,IAAI,eAAe,kBAAoB,EAAA;AACnC,UAAM,MAAA,IAAIC,YAAY,2BAA6B,EAAA;AAAA,YAC/C,gBAAkB,EAAA,UAAA;AAAA,YAClB;AAAA,WACH,CAAA;AAAA;AACL;AACJ,KACD,GAAA;AAKH,IAAA,MAAM,gCAAgC,YAAY;AAC9C,MAAA,MAAM,EAAE,KAAO,EAAA,YAAA,KAAiB,MAAM,GAAA,CACjC,eAAe,mBAAqB,EAAA;AAAA,QACjC,UAAA;AAAA,QACA,SAAW,EAAA,EAAE,MAAQ,EAAA,EAAA,EAAI,QAAQ,kBAAmB,EAAA;AAAA,QACpD,QAAU,EAAA;AAAA,OACb,CACA,CAAA,IAAA,CAAK,EAAE,WAAa,EAAA,eAAA,CAAgB,QAAQ,CAAA;AACjD,MAAA,IAAI,CAAC,YAAc,EAAA;AACf,QAAM,MAAA,IAAIA,YAAY,qCAAuC,EAAA;AAAA,UACzD;AAAA,SACH,CAAA;AAAA;AAEL,MAAM,MAAA,UAAA;AAAA;AAAA;AAAA,QAGF,YAAA,CAAa,KAAK,CAAC;AAAA,OAAA;AACvB,MAAA,IAAI,eAAe,kBAAoB,EAAA;AACnC,QAAM,MAAA,IAAIA,YAAY,2BAA6B,EAAA;AAAA,UAC/C,gBAAkB,EAAA,UAAA;AAAA,UAClB;AAAA,SACH,CAAA;AAAA,OACE,MAAA;AACH,QAAM,MAAA,IAAI,QAAQ,MAAM;AAAA,SAEvB,CAAA;AAAA;AACL,KACD,GAAA;AACH,IAAI,IAAA;AACA,MAAA,OAAO,MAAM,QAAA,CAAS,CAAC,6BAAA,EAA+B,4BAA4B,CAAC,CAAA;AAAA,KACrF,SAAA;AACE,MAAA,eAAA,CAAgB,KAAM,EAAA;AAAA;AAC1B,GACJ;AACJ;ACzFO,SAAS,+CAEd,CAAA;AAAA,EACE,GAAA;AAAA,EACA;AACJ,CAA6G,EAAA;AACzG,EAAA,OAAO,eAAe,qCAAsC,CAAA;AAAA,IACxD,WAAa,EAAA,iBAAA;AAAA,IACb,UAAA;AAAA,IACA;AAAA,GACD,EAAA;AACC,IAAM,MAAA,eAAA,GAAkB,IAAI,CAAgB,EAAA;AAC5C,IAAA,SAAS,WAAc,GAAA;AACnB,MAAA,eAAA,CAAgB,KAAM,EAAA;AAAA;AAE1B,IAAA,iBAAA,CAAkB,iBAAiB,OAAS,EAAA,WAAA,EAAa,EAAE,MAAQ,EAAA,eAAA,CAAgB,QAAQ,CAAA;AAI3F,IAAA,MAAM,4BAA+B,GAAA,MAAM,gBACtC,CAAA,sBAAA,CAAuB,WAAW,EAAE,UAAA,EAAY,CAAA,CAChD,SAAU,CAAA,EAAE,WAAa,EAAA,eAAA,CAAgB,QAAQ,CAAA;AACtD,IAAA,MAAM,6BAA6B,YAAY;AAC3C,MAAA,WAAA,MAAiB,+BAA+B,4BAA8B,EAAA;AAC1E,QAAI,IAAA,2BAAA,CAA4B,MAAM,GAAK,EAAA;AACvC,UAAM,MAAA,kCAAA,CAAmC,2BAA4B,CAAA,KAAA,CAAM,GAAG,CAAA;AAAA,SAC3E,MAAA;AACH,UAAA;AAAA;AACJ;AACJ,KACD,GAAA;AAKH,IAAA,MAAM,gCAAgC,YAAY;AAC9C,MAAA,MAAM,EAAE,KAAO,EAAA,sBAAA,EAA2B,GAAA,MAAM,IAC3C,oBAAqB,CAAA,CAAC,SAAS,CAAC,EAChC,IAAK,CAAA,EAAE,WAAa,EAAA,eAAA,CAAgB,QAAQ,CAAA;AACjD,MAAM,MAAA,eAAA,GAAkB,uBAAuB,CAAC,CAAA;AAChD,MACI,IAAA,eAAA,IACA,gBAAgB,kBAChB,IAAA,oBAAA,CAAqB,gBAAgB,kBAAoB,EAAA,UAAU,KAAK,CAC1E,EAAA;AACE,QAAA;AAAA,OACG,MAAA;AACH,QAAM,MAAA,IAAI,QAAQ,MAAM;AAAA,SAEvB,CAAA;AAAA;AACL,KACD,GAAA;AACH,IAAI,IAAA;AACA,MAAA,OAAO,MAAMC,QAAAA,CAAS,CAAC,yBAAA,EAA2B,4BAA4B,CAAC,CAAA;AAAA,KACjF,SAAA;AACE,MAAA,eAAA,CAAgB,KAAM,EAAA;AAAA;AAC1B,GACJ;AACJ;;;AChGA,eAAsB,iBAAkB,CAAA,EAAE,WAAa,EAAA,iBAAA,EAAmB,YAAsB,EAAA;AAC5F,EAAA,OAAO,MAAM,IAAI,OAAQ,CAAA,CAAC,GAAG,MAAW,KAAA;AACpC,IAAM,MAAA,WAAA,GAAc,CAAC,CAAoC,KAAA;AACrD,MAAA,YAAA,CAAa,SAAS,CAAA;AACtB,MAAA,MAAM,aAAa,IAAI,YAAA,CAAc,CAAE,CAAA,MAAA,CAAuB,QAAQ,YAAY,CAAA;AAClF,MAAA,MAAA,CAAO,UAAU,CAAA;AAAA,KACrB;AACA,IAAkB,iBAAA,CAAA,gBAAA,CAAiB,SAAS,WAAW,CAAA;AACvD,IAAM,MAAA,SAAA,GAAY,UAAe,KAAA,WAAA,GAAc,GAAS,GAAA,GAAA;AACxD,IAAM,MAAA,OAAA,GAAU,YAAY,GAAI,EAAA;AAChC,IAAM,MAAA,SAAA;AAAA;AAAA;AAAA;AAAA,MAIF,WAAW,MAAM;AACb,QAAM,MAAA,SAAA,GAAY,WAAY,CAAA,GAAA,EAAQ,GAAA,OAAA;AACtC,QAAA,MAAA,CAAO,IAAI,YAAa,CAAA,CAAA,sBAAA,EAAyB,SAAS,CAAA,GAAA,CAAA,EAAO,cAAc,CAAC,CAAA;AAAA,SACjF,SAAS;AAAA,KAAA;AAAA,GACnB,CAAA;AACL;ACrCA,eAAsB,cAAA,CAClB,SACA,EAAA,MAAA,EACA,4BACF,EAAA;AACE,EAAA,MAAM,EAAE,WAAA,EAAa,iBAAmB,EAAA,UAAA,EAAY,uCAA0C,GAAA,MAAA;AAC9F,EAAA,iBAAA,EAAmB,cAAe,EAAA;AAClC,EAAM,MAAA,eAAA,GAAkB,IAAI,CAAgB,EAAA;AAC5C,EAAA,IAAI,iBAAmB,EAAA;AACnB,IAAA,MAAM,cAAc,MAAM;AACtB,MAAA,eAAA,CAAgB,KAAM,EAAA;AAAA,KAC1B;AACA,IAAA,iBAAA,CAAkB,iBAAiB,OAAS,EAAA,WAAA,EAAa,EAAE,MAAQ,EAAA,eAAA,CAAgB,QAAQ,CAAA;AAAA;AAE/F,EAAI,IAAA;AACA,IAAA,MAAM,qBAAqB,4BAA6B,CAAA;AAAA,MACpD,GAAG,MAAA;AAAA,MACH,aAAa,eAAgB,CAAA;AAAA,KAChC,CAAA;AACD,IAAA,OAAO,MAAMA,QAAS,CAAA;AAAA,MAClB,qCAAsC,CAAA;AAAA,QAClC,aAAa,eAAgB,CAAA,MAAA;AAAA,QAC7B,UAAA;AAAA,QACA;AAAA,OACH,CAAA;AAAA,MACD,GAAG;AAAA,KACN,CAAA;AAAA,GACH,SAAA;AACE,IAAA,eAAA,CAAgB,KAAM,EAAA;AAAA;AAE9B;;;ACeA,eAAsB,2CAClB,MACa,EAAA;AACb,EAAM,MAAA,cAAA;AAAA,IACF,2BAAA,CAA4B,OAAO,WAAW,CAAA;AAAA,IAC9C,MAAA;AAAA,IACA,SAAS,4BAA6B,CAAA,EAAE,aAAa,UAAY,EAAA,2BAAA,EAA6B,aAAe,EAAA;AACzG,MAAO,OAAA;AAAA,QACH,2BAA4B,CAAA;AAAA,UACxB,WAAA;AAAA,UACA,UAAA;AAAA,UACA,iBAAA,EAAmB,YAAY,kBAAmB,CAAA,KAAA;AAAA,UAClD,mBAAA,EAAqB,YAAY,kBAAmB,CAAA;AAAA,SACvD;AAAA,OACL;AAAA;AACJ,GACJ;AACJ;AAwBA,eAAsB,qCAClB,MACa,EAAA;AACb,EAAM,MAAA,cAAA;AAAA,IACF,2BAAA,CAA4B,OAAO,WAAW,CAAA;AAAA,IAC9C,MAAA;AAAA,IACA,SAAS,4BAA6B,CAAA;AAAA,MAClC,WAAA;AAAA,MACA,UAAA;AAAA,MACA,+BAAA;AAAA,MACA;AAAA,KACD,EAAA;AACC,MAAO,OAAA;AAAA,QACH,+BAAgC,CAAA;AAAA,UAC5B,WAAA;AAAA,UACA,UAAA;AAAA,UACA,oBAAA,EAAsB,YAAY,kBAAmB,CAAA;AAAA,SACxD;AAAA,OACL;AAAA;AACJ,GACJ;AACJ;AAGA,eAAsB,iDAClB,MACa,EAAA;AACb,EAAM,MAAA,cAAA;AAAA,IACF,MAAO,CAAA,SAAA;AAAA,IACP,MAAA;AAAA,IACA,SAAS,4BAA6B,CAAA,EAAE,aAAa,UAAY,EAAA,iBAAA,EAAAC,oBAAqB,EAAA;AAClF,MAAO,OAAA;AAAA,QACHA,kBAAkB,CAAA;AAAA,UACd,WAAA;AAAA,UACA;AAAA,SACH;AAAA,OACL;AAAA;AACJ,GACJ;AACJ","file":"index.native.mjs","sourcesContent":["export const AbortController = globalThis.AbortController;\nexport const EventTarget = globalThis.EventTarget;\n","import { SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED, SolanaError } from '@solana/errors';\nimport { AbortController } from '@solana/event-target-impl';\nimport type { GetEpochInfoApi, Rpc } from '@solana/rpc';\nimport type { RpcSubscriptions, SlotNotificationsApi } from '@solana/rpc-subscriptions';\nimport type { Commitment } from '@solana/rpc-types';\n\ntype GetBlockHeightExceedencePromiseFn = (config: {\n abortSignal: AbortSignal;\n /**\n * Fetch the block height as of the highest slot that has reached this level of commitment.\n *\n * @defaultValue Whichever default is applied by the underlying {@link RpcApi} in use. For\n * example, when using an API created by a `createSolanaRpc*()` helper, the default commitment\n * is `\"confirmed\"` unless configured otherwise. Unmitigated by an API layer on the client, the\n * default commitment applied by the server is `\"finalized\"`.\n */\n commitment?: Commitment;\n /** The block height after which to reject the promise */\n lastValidBlockHeight: bigint;\n}) => Promise<void>;\n\ntype CreateBlockHeightExceedencePromiseFactoryConfig<TCluster> = {\n rpc: Rpc<GetEpochInfoApi> & { '~cluster'?: TCluster };\n rpcSubscriptions: RpcSubscriptions<SlotNotificationsApi> & { '~cluster'?: TCluster };\n};\n\n/**\n * Creates a promise that throws when the network progresses past the block height after which the\n * supplied blockhash is considered expired for use as a transaction lifetime specifier.\n *\n * When a transaction's lifetime is tied to a blockhash, that transaction can be landed on the\n * network until that blockhash expires. All blockhashes have a block height after which they are\n * considered to have expired.\n *\n * @param config\n *\n * @example\n * ```ts\n * import { isSolanaError, SolanaError } from '@solana/errors';\n * import { createBlockHeightExceedencePromiseFactory } from '@solana/transaction-confirmation';\n *\n * const getBlockHeightExceedencePromise = createBlockHeightExceedencePromiseFactory({\n * rpc,\n * rpcSubscriptions,\n * });\n * try {\n * await getBlockHeightExceedencePromise({ lastValidBlockHeight });\n * } catch (e) {\n * if (isSolanaError(e, SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED)) {\n * console.error(\n * `The block height of the network has exceeded ${e.context.lastValidBlockHeight}. ` +\n * `It is now ${e.context.currentBlockHeight}`,\n * );\n * // Re-sign and retry the transaction.\n * return;\n * }\n * throw e;\n * }\n * ```\n */\nexport function createBlockHeightExceedencePromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateBlockHeightExceedencePromiseFactoryConfig<'devnet'>): GetBlockHeightExceedencePromiseFn;\nexport function createBlockHeightExceedencePromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateBlockHeightExceedencePromiseFactoryConfig<'testnet'>): GetBlockHeightExceedencePromiseFn;\nexport function createBlockHeightExceedencePromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateBlockHeightExceedencePromiseFactoryConfig<'mainnet'>): GetBlockHeightExceedencePromiseFn;\nexport function createBlockHeightExceedencePromiseFactory<\n TCluster extends 'devnet' | 'mainnet' | 'testnet' | void = void,\n>({\n rpc,\n rpcSubscriptions,\n}: CreateBlockHeightExceedencePromiseFactoryConfig<TCluster>): GetBlockHeightExceedencePromiseFn {\n return async function getBlockHeightExceedencePromise({\n abortSignal: callerAbortSignal,\n commitment,\n lastValidBlockHeight,\n }): Promise<never> {\n callerAbortSignal.throwIfAborted();\n const abortController = new AbortController();\n const handleAbort = () => {\n abortController.abort();\n };\n callerAbortSignal.addEventListener('abort', handleAbort, { signal: abortController.signal });\n async function getBlockHeightAndDifferenceBetweenSlotHeightAndBlockHeight() {\n const { absoluteSlot, blockHeight } = await rpc\n .getEpochInfo({ commitment })\n .send({ abortSignal: abortController.signal });\n return {\n blockHeight,\n differenceBetweenSlotHeightAndBlockHeight: absoluteSlot - blockHeight,\n };\n }\n try {\n const [slotNotifications, { blockHeight: initialBlockHeight, differenceBetweenSlotHeightAndBlockHeight }] =\n await Promise.all([\n rpcSubscriptions.slotNotifications().subscribe({ abortSignal: abortController.signal }),\n getBlockHeightAndDifferenceBetweenSlotHeightAndBlockHeight(),\n ]);\n callerAbortSignal.throwIfAborted();\n let currentBlockHeight = initialBlockHeight;\n if (currentBlockHeight <= lastValidBlockHeight) {\n let lastKnownDifferenceBetweenSlotHeightAndBlockHeight = differenceBetweenSlotHeightAndBlockHeight;\n for await (const slotNotification of slotNotifications) {\n const { slot } = slotNotification;\n if (slot - lastKnownDifferenceBetweenSlotHeightAndBlockHeight > lastValidBlockHeight) {\n // Before making a final decision, recheck the actual block height.\n const {\n blockHeight: recheckedBlockHeight,\n differenceBetweenSlotHeightAndBlockHeight: currentDifferenceBetweenSlotHeightAndBlockHeight,\n } = await getBlockHeightAndDifferenceBetweenSlotHeightAndBlockHeight();\n currentBlockHeight = recheckedBlockHeight;\n if (currentBlockHeight > lastValidBlockHeight) {\n // Verified; the block height has been exceeded.\n break;\n } else {\n // The block height has not been exceeded, which implies that the\n // difference between the slot height and the block height has grown\n // (ie. some blocks have been skipped since we started). Recalibrate the\n // difference and keep waiting.\n lastKnownDifferenceBetweenSlotHeightAndBlockHeight =\n currentDifferenceBetweenSlotHeightAndBlockHeight;\n }\n }\n }\n }\n callerAbortSignal.throwIfAborted();\n throw new SolanaError(SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED, {\n currentBlockHeight,\n lastValidBlockHeight,\n });\n } finally {\n abortController.abort();\n }\n };\n}\n","import type { Address } from '@solana/addresses';\nimport { getBase58Decoder, getBase64Encoder } from '@solana/codecs-strings';\nimport { SOLANA_ERROR__INVALID_NONCE, SOLANA_ERROR__NONCE_ACCOUNT_NOT_FOUND, SolanaError } from '@solana/errors';\nimport { AbortController } from '@solana/event-target-impl';\nimport { safeRace } from '@solana/promises';\nimport type { GetAccountInfoApi, Rpc } from '@solana/rpc';\nimport type { AccountNotificationsApi, RpcSubscriptions } from '@solana/rpc-subscriptions';\nimport type { Base64EncodedDataResponse, Commitment } from '@solana/rpc-types';\nimport { Nonce } from '@solana/transaction-messages';\n\ntype GetNonceInvalidationPromiseFn = (config: {\n abortSignal: AbortSignal;\n /**\n * Fetch the nonce account details as of the highest slot that has reached this level of\n * commitment.\n */\n commitment: Commitment;\n /**\n * The value of the nonce that we would expect to see in the nonce account in order for any\n * transaction with that nonce-based lifetime to be considered valid.\n */\n currentNonceValue: Nonce;\n /** The address of the account in which the currently-valid nonce value is stored */\n nonceAccountAddress: Address;\n}) => Promise<void>;\n\ntype CreateNonceInvalidationPromiseFactoryConfig<TCluster> = {\n rpc: Rpc<GetAccountInfoApi> & { '~cluster'?: TCluster };\n rpcSubscriptions: RpcSubscriptions<AccountNotificationsApi> & { '~cluster'?: TCluster };\n};\n\nconst NONCE_VALUE_OFFSET =\n 4 + // version(u32)\n 4 + // state(u32)\n 32; // nonce authority(pubkey)\n// Then comes the nonce value.\n\n/**\n * Creates a promise that throws when the value stored in a nonce account is not the expected one.\n *\n * When a transaction's lifetime is tied to the value stored in a nonce account, that transaction\n * can be landed on the network until the nonce is advanced to a new value.\n *\n * @param config\n *\n * @example\n * ```ts\n * import { isSolanaError, SolanaError } from '@solana/errors';\n * import { createNonceInvalidationPromiseFactory } from '@solana/transaction-confirmation';\n *\n * const getNonceInvalidationPromise = createNonceInvalidationPromiseFactory({\n * rpc,\n * rpcSubscriptions,\n * });\n * try {\n * await getNonceInvalidationPromise({\n * currentNonceValue,\n * nonceAccountAddress,\n * });\n * } catch (e) {\n * if (isSolanaError(e, SOLANA_ERROR__NONCE_INVALID)) {\n * console.error(`The nonce has advanced to ${e.context.actualNonceValue}`);\n * // Re-sign and retry the transaction.\n * return;\n * } else if (isSolanaError(e, SOLANA_ERROR__NONCE_ACCOUNT_NOT_FOUND)) {\n * console.error(`No nonce account was found at ${nonceAccountAddress}`);\n * }\n * throw e;\n * }\n * ```\n */\nexport function createNonceInvalidationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateNonceInvalidationPromiseFactoryConfig<'devnet'>): GetNonceInvalidationPromiseFn;\nexport function createNonceInvalidationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateNonceInvalidationPromiseFactoryConfig<'testnet'>): GetNonceInvalidationPromiseFn;\nexport function createNonceInvalidationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateNonceInvalidationPromiseFactoryConfig<'mainnet'>): GetNonceInvalidationPromiseFn;\nexport function createNonceInvalidationPromiseFactory<TCluster extends 'devnet' | 'mainnet' | 'testnet' | void = void>({\n rpc,\n rpcSubscriptions,\n}: CreateNonceInvalidationPromiseFactoryConfig<TCluster>): GetNonceInvalidationPromiseFn {\n return async function getNonceInvalidationPromise({\n abortSignal: callerAbortSignal,\n commitment,\n currentNonceValue: expectedNonceValue,\n nonceAccountAddress,\n }) {\n const abortController = new AbortController();\n function handleAbort() {\n abortController.abort();\n }\n callerAbortSignal.addEventListener('abort', handleAbort, { signal: abortController.signal });\n /**\n * STEP 1: Set up a subscription for nonce account changes.\n */\n const accountNotifications = await rpcSubscriptions\n .accountNotifications(nonceAccountAddress, { commitment, encoding: 'base64' })\n .subscribe({ abortSignal: abortController.signal });\n const base58Decoder = getBase58Decoder();\n const base64Encoder = getBase64Encoder();\n function getNonceFromAccountData([base64EncodedBytes]: Base64EncodedDataResponse): Nonce {\n const data = base64Encoder.encode(base64EncodedBytes);\n const nonceValueBytes = data.slice(NONCE_VALUE_OFFSET, NONCE_VALUE_OFFSET + 32);\n return base58Decoder.decode(nonceValueBytes) as Nonce;\n }\n const nonceAccountDidAdvancePromise = (async () => {\n for await (const accountNotification of accountNotifications) {\n const nonceValue = getNonceFromAccountData(accountNotification.value.data);\n if (nonceValue !== expectedNonceValue) {\n throw new SolanaError(SOLANA_ERROR__INVALID_NONCE, {\n actualNonceValue: nonceValue,\n expectedNonceValue,\n });\n }\n }\n })();\n /**\n * STEP 2: Having subscribed for updates, make a one-shot request for the current nonce\n * value to check if it has already been advanced.\n */\n const nonceIsAlreadyInvalidPromise = (async () => {\n const { value: nonceAccount } = await rpc\n .getAccountInfo(nonceAccountAddress, {\n commitment,\n dataSlice: { length: 32, offset: NONCE_VALUE_OFFSET },\n encoding: 'base58',\n })\n .send({ abortSignal: abortController.signal });\n if (!nonceAccount) {\n throw new SolanaError(SOLANA_ERROR__NONCE_ACCOUNT_NOT_FOUND, {\n nonceAccountAddress,\n });\n }\n const nonceValue =\n // This works because we asked for the exact slice of data representing the nonce\n // value, and furthermore asked for it in `base58` encoding.\n nonceAccount.data[0] as unknown as Nonce;\n if (nonceValue !== expectedNonceValue) {\n throw new SolanaError(SOLANA_ERROR__INVALID_NONCE, {\n actualNonceValue: nonceValue,\n expectedNonceValue,\n });\n } else {\n await new Promise(() => {\n /* never resolve */\n });\n }\n })();\n try {\n return await safeRace([nonceAccountDidAdvancePromise, nonceIsAlreadyInvalidPromise]);\n } finally {\n abortController.abort();\n }\n };\n}\n","import { getSolanaErrorFromTransactionError } from '@solana/errors';\nimport { AbortController } from '@solana/event-target-impl';\nimport type { Signature } from '@solana/keys';\nimport { safeRace } from '@solana/promises';\nimport type { GetSignatureStatusesApi, Rpc } from '@solana/rpc';\nimport type { RpcSubscriptions, SignatureNotificationsApi } from '@solana/rpc-subscriptions';\nimport { type Commitment, commitmentComparator } from '@solana/rpc-types';\n\ntype GetRecentSignatureConfirmationPromiseFn = (config: {\n abortSignal: AbortSignal;\n /**\n * The level of commitment the transaction must have achieved in order for the promise to\n * resolve.\n */\n commitment: Commitment;\n /**\n * A 64 byte Ed25519 signature, encoded as a base-58 string, that uniquely identifies a\n * transaction by virtue of being the first or only signature in its list of signatures.\n */\n signature: Signature;\n}) => Promise<void>;\n\ntype CreateRecentSignatureConfirmationPromiseFactoryConfig<TCluster> = {\n rpc: Rpc<GetSignatureStatusesApi> & { '~cluster'?: TCluster };\n rpcSubscriptions: RpcSubscriptions<SignatureNotificationsApi> & { '~cluster'?: TCluster };\n};\n\n/**\n * Creates a promise that resolves when a recently-landed transaction achieves the target\n * confirmation commitment, and throws when the transaction fails with an error.\n *\n * The status of recently-landed transactions is available in the network's status cache. This\n * confirmation strategy will only yield a result if the signature is still in the status cache. To\n * fetch the status of transactions older than those available in the status cache, use the\n * {@link GetSignatureStatusesApi.getSignatureStatuses} method setting the\n * `searchTransactionHistory` configuration param to `true`.\n *\n * @param config\n *\n * @example\n * ```ts\n * import { createRecentSignatureConfirmationPromiseFactory } from '@solana/transaction-confirmation';\n *\n * const getRecentSignatureConfirmationPromise = createRecentSignatureConfirmationPromiseFactory({\n * rpc,\n * rpcSubscriptions,\n * });\n * try {\n * await getRecentSignatureConfirmationPromise({\n * commitment,\n * signature,\n * });\n * console.log(`The transaction with signature \\`${signature}\\` has achieved a commitment level of \\`${commitment}\\``);\n * } catch (e) {\n * console.error(`The transaction with signature \\`${signature}\\` failed`, e.cause);\n * throw e;\n * }\n * ```\n */\nexport function createRecentSignatureConfirmationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateRecentSignatureConfirmationPromiseFactoryConfig<'devnet'>): GetRecentSignatureConfirmationPromiseFn;\nexport function createRecentSignatureConfirmationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateRecentSignatureConfirmationPromiseFactoryConfig<'testnet'>): GetRecentSignatureConfirmationPromiseFn;\nexport function createRecentSignatureConfirmationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateRecentSignatureConfirmationPromiseFactoryConfig<'mainnet'>): GetRecentSignatureConfirmationPromiseFn;\nexport function createRecentSignatureConfirmationPromiseFactory<\n TCluster extends 'devnet' | 'mainnet' | 'testnet' | void = void,\n>({\n rpc,\n rpcSubscriptions,\n}: CreateRecentSignatureConfirmationPromiseFactoryConfig<TCluster>): GetRecentSignatureConfirmationPromiseFn {\n return async function getRecentSignatureConfirmationPromise({\n abortSignal: callerAbortSignal,\n commitment,\n signature,\n }) {\n const abortController = new AbortController();\n function handleAbort() {\n abortController.abort();\n }\n callerAbortSignal.addEventListener('abort', handleAbort, { signal: abortController.signal });\n /**\n * STEP 1: Set up a subscription for status changes to a signature.\n */\n const signatureStatusNotifications = await rpcSubscriptions\n .signatureNotifications(signature, { commitment })\n .subscribe({ abortSignal: abortController.signal });\n const signatureDidCommitPromise = (async () => {\n for await (const signatureStatusNotification of signatureStatusNotifications) {\n if (signatureStatusNotification.value.err) {\n throw getSolanaErrorFromTransactionError(signatureStatusNotification.value.err);\n } else {\n return;\n }\n }\n })();\n /**\n * STEP 2: Having subscribed for updates, make a one-shot request for the current status.\n * This will only yield a result if the signature is still in the status cache.\n */\n const signatureStatusLookupPromise = (async () => {\n const { value: signatureStatusResults } = await rpc\n .getSignatureStatuses([signature])\n .send({ abortSignal: abortController.signal });\n const signatureStatus = signatureStatusResults[0];\n if (\n signatureStatus &&\n signatureStatus.confirmationStatus &&\n commitmentComparator(signatureStatus.confirmationStatus, commitment) >= 0\n ) {\n return;\n } else {\n await new Promise(() => {\n /* never resolve */\n });\n }\n })();\n try {\n return await safeRace([signatureDidCommitPromise, signatureStatusLookupPromise]);\n } finally {\n abortController.abort();\n }\n };\n}\n","import type { Commitment } from '@solana/rpc-types';\n\ntype Config = Readonly<{\n abortSignal: AbortSignal;\n /**\n * The timeout promise will throw after 30 seconds when the commitment is `processed`, and 60\n * seconds otherwise.\n */\n commitment: Commitment;\n}>;\n\n/**\n * When no other heuristic exists to infer that a transaction has expired, you can use this promise\n * factory with a commitment level. It throws after 30 seconds when the commitment is `processed`,\n * and 60 seconds otherwise. You would typically race this with another confirmation strategy.\n *\n * @param config\n *\n * @example\n * ```ts\n * import { safeRace } from '@solana/promises';\n * import { getTimeoutPromise } from '@solana/transaction-confirmation';\n *\n * try {\n * await safeRace([getCustomTransactionConfirmationPromise(/* ... *\\/), getTimeoutPromise({ commitment })]);\n * } catch (e) {\n * if (e instanceof DOMException && e.name === 'TimeoutError') {\n * console.log('Could not confirm transaction after a timeout');\n * }\n * throw e;\n * }\n * ```\n */\nexport async function getTimeoutPromise({ abortSignal: callerAbortSignal, commitment }: Config) {\n return await new Promise((_, reject) => {\n const handleAbort = (e: AbortSignalEventMap['abort']) => {\n clearTimeout(timeoutId);\n const abortError = new DOMException((e.target as AbortSignal).reason, 'AbortError');\n reject(abortError);\n };\n callerAbortSignal.addEventListener('abort', handleAbort);\n const timeoutMs = commitment === 'processed' ? 30_000 : 60_000;\n const startMs = performance.now();\n const timeoutId =\n // We use `setTimeout` instead of `AbortSignal.timeout()` because we want to measure\n // elapsed time instead of active time.\n // See https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal/timeout_static\n setTimeout(() => {\n const elapsedMs = performance.now() - startMs;\n reject(new DOMException(`Timeout elapsed after ${elapsedMs} ms`, 'TimeoutError'));\n }, timeoutMs);\n });\n}\n","import { AbortController } from '@solana/event-target-impl';\nimport type { Signature } from '@solana/keys';\nimport { safeRace } from '@solana/promises';\nimport type { Commitment } from '@solana/rpc-types';\n\nimport { createRecentSignatureConfirmationPromiseFactory } from './confirmation-strategy-recent-signature';\n\nexport interface BaseTransactionConfirmationStrategyConfig {\n abortSignal?: AbortSignal;\n commitment: Commitment;\n getRecentSignatureConfirmationPromise: ReturnType<typeof createRecentSignatureConfirmationPromiseFactory>;\n}\n\ntype WithNonNullableAbortSignal<T> = Omit<T, 'abortSignal'> & Readonly<{ abortSignal: AbortSignal }>;\n\nexport async function raceStrategies<TConfig extends BaseTransactionConfirmationStrategyConfig>(\n signature: Signature,\n config: TConfig,\n getSpecificStrategiesForRace: (config: WithNonNullableAbortSignal<TConfig>) => readonly Promise<unknown>[],\n) {\n const { abortSignal: callerAbortSignal, commitment, getRecentSignatureConfirmationPromise } = config;\n callerAbortSignal?.throwIfAborted();\n const abortController = new AbortController();\n if (callerAbortSignal) {\n const handleAbort = () => {\n abortController.abort();\n };\n callerAbortSignal.addEventListener('abort', handleAbort, { signal: abortController.signal });\n }\n try {\n const specificStrategies = getSpecificStrategiesForRace({\n ...config,\n abortSignal: abortController.signal,\n });\n return await safeRace([\n getRecentSignatureConfirmationPromise({\n abortSignal: abortController.signal,\n commitment,\n signature,\n }),\n ...specificStrategies,\n ]);\n } finally {\n abortController.abort();\n }\n}\n","import { Signature } from '@solana/keys';\nimport {\n getSignatureFromTransaction,\n Transaction,\n TransactionWithBlockhashLifetime,\n TransactionWithDurableNonceLifetime,\n} from '@solana/transactions';\n\nimport { createBlockHeightExceedencePromiseFactory } from './confirmation-strategy-blockheight';\nimport { createNonceInvalidationPromiseFactory } from './confirmation-strategy-nonce';\nimport { BaseTransactionConfirmationStrategyConfig, raceStrategies } from './confirmation-strategy-racer';\nimport { getTimeoutPromise } from './confirmation-strategy-timeout';\n\nexport type TransactionWithLastValidBlockHeight = Omit<TransactionWithBlockhashLifetime, 'lifetimeConstraint'> & {\n lifetimeConstraint: Omit<TransactionWithBlockhashLifetime['lifetimeConstraint'], 'blockhash'>;\n};\n\ninterface WaitForDurableNonceTransactionConfirmationConfig extends BaseTransactionConfirmationStrategyConfig {\n getNonceInvalidationPromise: ReturnType<typeof createNonceInvalidationPromiseFactory>;\n transaction: Readonly<Transaction & TransactionWithDurableNonceLifetime>;\n}\n\ninterface WaitForRecentTransactionWithBlockhashLifetimeConfirmationConfig\n extends BaseTransactionConfirmationStrategyConfig {\n getBlockHeightExceedencePromise: ReturnType<typeof createBlockHeightExceedencePromiseFactory>;\n transaction: Readonly<Transaction & TransactionWithLastValidBlockHeight>;\n}\n\ninterface WaitForRecentTransactionWithTimeBasedLifetimeConfirmationConfig\n extends BaseTransactionConfirmationStrategyConfig {\n getTimeoutPromise: typeof getTimeoutPromise;\n /**\n * A 64 byte Ed25519 signature, encoded as a base-58 string, that uniquely identifies a\n * transaction by virtue of being the first or only signature in its list of signatures.\n */\n signature: Signature;\n}\n\n/**\n * Supply your own confirmation implementations to this function to create a custom nonce\n * transaction confirmation strategy.\n *\n * @example\n * ```ts\n * import { waitForDurableNonceTransactionConfirmation } from '@solana/transaction-confirmation';\n *\n * try {\n * await waitForDurableNonceTransactionConfirmation({\n * getNonceInvalidationPromise({ abortSignal, commitment, currentNonceValue, nonceAccountAddress }) {\n * // Return a promise that rejects when a nonce becomes invalid.\n * },\n * getRecentSignatureConfirmationPromise({ abortSignal, commitment, signature }) {\n * // Return a promise that resolves when a transaction achieves confirmation\n * },\n * });\n * } catch (e) {\n * // Handle errors.\n * }\n * ```\n */\nexport async function waitForDurableNonceTransactionConfirmation(\n config: WaitForDurableNonceTransactionConfirmationConfig,\n): Promise<void> {\n await raceStrategies(\n getSignatureFromTransaction(config.transaction),\n config,\n function getSpecificStrategiesForRace({ abortSignal, commitment, getNonceInvalidationPromise, transaction }) {\n return [\n getNonceInvalidationPromise({\n abortSignal,\n commitment,\n currentNonceValue: transaction.lifetimeConstraint.nonce,\n nonceAccountAddress: transaction.lifetimeConstraint.nonceAccountAddress,\n }),\n ];\n },\n );\n}\n\n/**\n * Supply your own confirmation implementations to this function to create a custom confirmation\n * strategy for recently-landed transactions.\n *\n * @example\n * ```ts\n * import { waitForRecentTransactionConfirmation } from '@solana/transaction-confirmation';\n *\n * try {\n * await waitForRecentTransactionConfirmation({\n * getBlockHeightExceedencePromise({ abortSignal, commitment, lastValidBlockHeight }) {\n * // Return a promise that rejects when the blockhash's block height has been exceeded\n * },\n * getRecentSignatureConfirmationPromise({ abortSignal, commitment, signature }) {\n * // Return a promise that resolves when a transaction achieves confirmation\n * },\n * });\n * } catch (e) {\n * // Handle errors.\n * }\n * ```\n */\nexport async function waitForRecentTransactionConfirmation(\n config: WaitForRecentTransactionWithBlockhashLifetimeConfirmationConfig,\n): Promise<void> {\n await raceStrategies(\n getSignatureFromTransaction(config.transaction),\n config,\n function getSpecificStrategiesForRace({\n abortSignal,\n commitment,\n getBlockHeightExceedencePromise,\n transaction,\n }) {\n return [\n getBlockHeightExceedencePromise({\n abortSignal,\n commitment,\n lastValidBlockHeight: transaction.lifetimeConstraint.lastValidBlockHeight,\n }),\n ];\n },\n );\n}\n\n/** @deprecated */\nexport async function waitForRecentTransactionConfirmationUntilTimeout(\n config: WaitForRecentTransactionWithTimeBasedLifetimeConfirmationConfig,\n): Promise<void> {\n await raceStrategies(\n config.signature,\n config,\n function getSpecificStrategiesForRace({ abortSignal, commitment, getTimeoutPromise }) {\n return [\n getTimeoutPromise({\n abortSignal,\n commitment,\n }),\n ];\n },\n );\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../event-target-impl/src/index.browser.ts","../src/confirmation-strategy-blockheight.ts","../src/confirmation-strategy-nonce.ts","../src/confirmation-strategy-recent-signature.ts","../src/confirmation-strategy-timeout.ts","../src/confirmation-strategy-racer.ts","../src/waiters.ts"],"names":["AbortController","SolanaError","safeRace","getTimeoutPromise"],"mappings":"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","file":"index.native.mjs","sourcesContent":["export const AbortController = globalThis.AbortController;\nexport const EventTarget = globalThis.EventTarget;\n","import { SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED, SolanaError } from '@solana/errors';\nimport { AbortController } from '@solana/event-target-impl';\nimport type { GetEpochInfoApi, Rpc } from '@solana/rpc';\nimport type { RpcSubscriptions, SlotNotificationsApi } from '@solana/rpc-subscriptions';\nimport type { Commitment } from '@solana/rpc-types';\n\ntype GetBlockHeightExceedencePromiseFn = (config: {\n abortSignal: AbortSignal;\n /**\n * Fetch the block height as of the highest slot that has reached this level of commitment.\n *\n * @defaultValue Whichever default is applied by the underlying {@link RpcApi} in use. For\n * example, when using an API created by a `createSolanaRpc*()` helper, the default commitment\n * is `\"confirmed\"` unless configured otherwise. Unmitigated by an API layer on the client, the\n * default commitment applied by the server is `\"finalized\"`.\n */\n commitment?: Commitment;\n /** The block height after which to reject the promise */\n lastValidBlockHeight: bigint;\n}) => Promise<void>;\n\ntype CreateBlockHeightExceedencePromiseFactoryConfig<TCluster> = {\n rpc: Rpc<GetEpochInfoApi> & { '~cluster'?: TCluster };\n rpcSubscriptions: RpcSubscriptions<SlotNotificationsApi> & { '~cluster'?: TCluster };\n};\n\n/**\n * Creates a promise that throws when the network progresses past the block height after which the\n * supplied blockhash is considered expired for use as a transaction lifetime specifier.\n *\n * When a transaction's lifetime is tied to a blockhash, that transaction can be landed on the\n * network until that blockhash expires. All blockhashes have a block height after which they are\n * considered to have expired.\n *\n * @param config\n *\n * @example\n * ```ts\n * import { isSolanaError, SolanaError } from '@solana/errors';\n * import { createBlockHeightExceedencePromiseFactory } from '@solana/transaction-confirmation';\n *\n * const getBlockHeightExceedencePromise = createBlockHeightExceedencePromiseFactory({\n * rpc,\n * rpcSubscriptions,\n * });\n * try {\n * await getBlockHeightExceedencePromise({ lastValidBlockHeight });\n * } catch (e) {\n * if (isSolanaError(e, SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED)) {\n * console.error(\n * `The block height of the network has exceeded ${e.context.lastValidBlockHeight}. ` +\n * `It is now ${e.context.currentBlockHeight}`,\n * );\n * // Re-sign and retry the transaction.\n * return;\n * }\n * throw e;\n * }\n * ```\n */\nexport function createBlockHeightExceedencePromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateBlockHeightExceedencePromiseFactoryConfig<'devnet'>): GetBlockHeightExceedencePromiseFn;\nexport function createBlockHeightExceedencePromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateBlockHeightExceedencePromiseFactoryConfig<'testnet'>): GetBlockHeightExceedencePromiseFn;\nexport function createBlockHeightExceedencePromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateBlockHeightExceedencePromiseFactoryConfig<'mainnet'>): GetBlockHeightExceedencePromiseFn;\nexport function createBlockHeightExceedencePromiseFactory<\n TCluster extends 'devnet' | 'mainnet' | 'testnet' | void = void,\n>({\n rpc,\n rpcSubscriptions,\n}: CreateBlockHeightExceedencePromiseFactoryConfig<TCluster>): GetBlockHeightExceedencePromiseFn {\n return async function getBlockHeightExceedencePromise({\n abortSignal: callerAbortSignal,\n commitment,\n lastValidBlockHeight,\n }): Promise<never> {\n callerAbortSignal.throwIfAborted();\n const abortController = new AbortController();\n const handleAbort = () => {\n abortController.abort();\n };\n callerAbortSignal.addEventListener('abort', handleAbort, { signal: abortController.signal });\n async function getBlockHeightAndDifferenceBetweenSlotHeightAndBlockHeight() {\n const { absoluteSlot, blockHeight } = await rpc\n .getEpochInfo({ commitment })\n .send({ abortSignal: abortController.signal });\n return {\n blockHeight,\n differenceBetweenSlotHeightAndBlockHeight: absoluteSlot - blockHeight,\n };\n }\n try {\n const [slotNotifications, { blockHeight: initialBlockHeight, differenceBetweenSlotHeightAndBlockHeight }] =\n await Promise.all([\n rpcSubscriptions.slotNotifications().subscribe({ abortSignal: abortController.signal }),\n getBlockHeightAndDifferenceBetweenSlotHeightAndBlockHeight(),\n ]);\n callerAbortSignal.throwIfAborted();\n let currentBlockHeight = initialBlockHeight;\n if (currentBlockHeight <= lastValidBlockHeight) {\n let lastKnownDifferenceBetweenSlotHeightAndBlockHeight = differenceBetweenSlotHeightAndBlockHeight;\n for await (const slotNotification of slotNotifications) {\n const { slot } = slotNotification;\n if (slot - lastKnownDifferenceBetweenSlotHeightAndBlockHeight > lastValidBlockHeight) {\n // Before making a final decision, recheck the actual block height.\n const {\n blockHeight: recheckedBlockHeight,\n differenceBetweenSlotHeightAndBlockHeight: currentDifferenceBetweenSlotHeightAndBlockHeight,\n } = await getBlockHeightAndDifferenceBetweenSlotHeightAndBlockHeight();\n currentBlockHeight = recheckedBlockHeight;\n if (currentBlockHeight > lastValidBlockHeight) {\n // Verified; the block height has been exceeded.\n break;\n } else {\n // The block height has not been exceeded, which implies that the\n // difference between the slot height and the block height has grown\n // (ie. some blocks have been skipped since we started). Recalibrate the\n // difference and keep waiting.\n lastKnownDifferenceBetweenSlotHeightAndBlockHeight =\n currentDifferenceBetweenSlotHeightAndBlockHeight;\n }\n }\n }\n }\n callerAbortSignal.throwIfAborted();\n throw new SolanaError(SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED, {\n currentBlockHeight,\n lastValidBlockHeight,\n });\n } finally {\n abortController.abort();\n }\n };\n}\n","import type { Address } from '@solana/addresses';\nimport { getBase58Decoder, getBase64Encoder } from '@solana/codecs-strings';\nimport { SOLANA_ERROR__INVALID_NONCE, SOLANA_ERROR__NONCE_ACCOUNT_NOT_FOUND, SolanaError } from '@solana/errors';\nimport { AbortController } from '@solana/event-target-impl';\nimport { safeRace } from '@solana/promises';\nimport type { GetAccountInfoApi, Rpc } from '@solana/rpc';\nimport type { AccountNotificationsApi, RpcSubscriptions } from '@solana/rpc-subscriptions';\nimport type { Base64EncodedDataResponse, Commitment } from '@solana/rpc-types';\nimport { Nonce } from '@solana/transaction-messages';\n\ntype GetNonceInvalidationPromiseFn = (config: {\n abortSignal: AbortSignal;\n /**\n * Fetch the nonce account details as of the highest slot that has reached this level of\n * commitment.\n */\n commitment: Commitment;\n /**\n * The value of the nonce that we would expect to see in the nonce account in order for any\n * transaction with that nonce-based lifetime to be considered valid.\n */\n currentNonceValue: Nonce;\n /** The address of the account in which the currently-valid nonce value is stored */\n nonceAccountAddress: Address;\n}) => Promise<void>;\n\ntype CreateNonceInvalidationPromiseFactoryConfig<TCluster> = {\n rpc: Rpc<GetAccountInfoApi> & { '~cluster'?: TCluster };\n rpcSubscriptions: RpcSubscriptions<AccountNotificationsApi> & { '~cluster'?: TCluster };\n};\n\nconst NONCE_VALUE_OFFSET =\n 4 + // version(u32)\n 4 + // state(u32)\n 32; // nonce authority(pubkey)\n// Then comes the nonce value.\n\n/**\n * Creates a promise that throws when the value stored in a nonce account is not the expected one.\n *\n * When a transaction's lifetime is tied to the value stored in a nonce account, that transaction\n * can be landed on the network until the nonce is advanced to a new value.\n *\n * @param config\n *\n * @example\n * ```ts\n * import { isSolanaError, SolanaError } from '@solana/errors';\n * import { createNonceInvalidationPromiseFactory } from '@solana/transaction-confirmation';\n *\n * const getNonceInvalidationPromise = createNonceInvalidationPromiseFactory({\n * rpc,\n * rpcSubscriptions,\n * });\n * try {\n * await getNonceInvalidationPromise({\n * currentNonceValue,\n * nonceAccountAddress,\n * });\n * } catch (e) {\n * if (isSolanaError(e, SOLANA_ERROR__NONCE_INVALID)) {\n * console.error(`The nonce has advanced to ${e.context.actualNonceValue}`);\n * // Re-sign and retry the transaction.\n * return;\n * } else if (isSolanaError(e, SOLANA_ERROR__NONCE_ACCOUNT_NOT_FOUND)) {\n * console.error(`No nonce account was found at ${nonceAccountAddress}`);\n * }\n * throw e;\n * }\n * ```\n */\nexport function createNonceInvalidationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateNonceInvalidationPromiseFactoryConfig<'devnet'>): GetNonceInvalidationPromiseFn;\nexport function createNonceInvalidationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateNonceInvalidationPromiseFactoryConfig<'testnet'>): GetNonceInvalidationPromiseFn;\nexport function createNonceInvalidationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateNonceInvalidationPromiseFactoryConfig<'mainnet'>): GetNonceInvalidationPromiseFn;\nexport function createNonceInvalidationPromiseFactory<TCluster extends 'devnet' | 'mainnet' | 'testnet' | void = void>({\n rpc,\n rpcSubscriptions,\n}: CreateNonceInvalidationPromiseFactoryConfig<TCluster>): GetNonceInvalidationPromiseFn {\n return async function getNonceInvalidationPromise({\n abortSignal: callerAbortSignal,\n commitment,\n currentNonceValue: expectedNonceValue,\n nonceAccountAddress,\n }) {\n const abortController = new AbortController();\n function handleAbort() {\n abortController.abort();\n }\n callerAbortSignal.addEventListener('abort', handleAbort, { signal: abortController.signal });\n /**\n * STEP 1: Set up a subscription for nonce account changes.\n */\n const accountNotifications = await rpcSubscriptions\n .accountNotifications(nonceAccountAddress, { commitment, encoding: 'base64' })\n .subscribe({ abortSignal: abortController.signal });\n const base58Decoder = getBase58Decoder();\n const base64Encoder = getBase64Encoder();\n function getNonceFromAccountData([base64EncodedBytes]: Base64EncodedDataResponse): Nonce {\n const data = base64Encoder.encode(base64EncodedBytes);\n const nonceValueBytes = data.slice(NONCE_VALUE_OFFSET, NONCE_VALUE_OFFSET + 32);\n return base58Decoder.decode(nonceValueBytes) as Nonce;\n }\n const nonceAccountDidAdvancePromise = (async () => {\n for await (const accountNotification of accountNotifications) {\n const nonceValue = getNonceFromAccountData(accountNotification.value.data);\n if (nonceValue !== expectedNonceValue) {\n throw new SolanaError(SOLANA_ERROR__INVALID_NONCE, {\n actualNonceValue: nonceValue,\n expectedNonceValue,\n });\n }\n }\n })();\n /**\n * STEP 2: Having subscribed for updates, make a one-shot request for the current nonce\n * value to check if it has already been advanced.\n */\n const nonceIsAlreadyInvalidPromise = (async () => {\n const { value: nonceAccount } = await rpc\n .getAccountInfo(nonceAccountAddress, {\n commitment,\n dataSlice: { length: 32, offset: NONCE_VALUE_OFFSET },\n encoding: 'base58',\n })\n .send({ abortSignal: abortController.signal });\n if (!nonceAccount) {\n throw new SolanaError(SOLANA_ERROR__NONCE_ACCOUNT_NOT_FOUND, {\n nonceAccountAddress,\n });\n }\n const nonceValue =\n // This works because we asked for the exact slice of data representing the nonce\n // value, and furthermore asked for it in `base58` encoding.\n nonceAccount.data[0] as unknown as Nonce;\n if (nonceValue !== expectedNonceValue) {\n throw new SolanaError(SOLANA_ERROR__INVALID_NONCE, {\n actualNonceValue: nonceValue,\n expectedNonceValue,\n });\n } else {\n await new Promise(() => {\n /* never resolve */\n });\n }\n })();\n try {\n return await safeRace([nonceAccountDidAdvancePromise, nonceIsAlreadyInvalidPromise]);\n } finally {\n abortController.abort();\n }\n };\n}\n","import { getSolanaErrorFromTransactionError } from '@solana/errors';\nimport { AbortController } from '@solana/event-target-impl';\nimport type { Signature } from '@solana/keys';\nimport { safeRace } from '@solana/promises';\nimport type { GetSignatureStatusesApi, Rpc } from '@solana/rpc';\nimport type { RpcSubscriptions, SignatureNotificationsApi } from '@solana/rpc-subscriptions';\nimport { type Commitment, commitmentComparator } from '@solana/rpc-types';\n\ntype GetRecentSignatureConfirmationPromiseFn = (config: {\n abortSignal: AbortSignal;\n /**\n * The level of commitment the transaction must have achieved in order for the promise to\n * resolve.\n */\n commitment: Commitment;\n /**\n * A 64 byte Ed25519 signature, encoded as a base-58 string, that uniquely identifies a\n * transaction by virtue of being the first or only signature in its list of signatures.\n */\n signature: Signature;\n}) => Promise<void>;\n\ntype CreateRecentSignatureConfirmationPromiseFactoryConfig<TCluster> = {\n rpc: Rpc<GetSignatureStatusesApi> & { '~cluster'?: TCluster };\n rpcSubscriptions: RpcSubscriptions<SignatureNotificationsApi> & { '~cluster'?: TCluster };\n};\n\n/**\n * Creates a promise that resolves when a recently-landed transaction achieves the target\n * confirmation commitment, and throws when the transaction fails with an error.\n *\n * The status of recently-landed transactions is available in the network's status cache. This\n * confirmation strategy will only yield a result if the signature is still in the status cache. To\n * fetch the status of transactions older than those available in the status cache, use the\n * {@link GetSignatureStatusesApi.getSignatureStatuses} method setting the\n * `searchTransactionHistory` configuration param to `true`.\n *\n * @param config\n *\n * @example\n * ```ts\n * import { createRecentSignatureConfirmationPromiseFactory } from '@solana/transaction-confirmation';\n *\n * const getRecentSignatureConfirmationPromise = createRecentSignatureConfirmationPromiseFactory({\n * rpc,\n * rpcSubscriptions,\n * });\n * try {\n * await getRecentSignatureConfirmationPromise({\n * commitment,\n * signature,\n * });\n * console.log(`The transaction with signature \\`${signature}\\` has achieved a commitment level of \\`${commitment}\\``);\n * } catch (e) {\n * console.error(`The transaction with signature \\`${signature}\\` failed`, e.cause);\n * throw e;\n * }\n * ```\n */\nexport function createRecentSignatureConfirmationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateRecentSignatureConfirmationPromiseFactoryConfig<'devnet'>): GetRecentSignatureConfirmationPromiseFn;\nexport function createRecentSignatureConfirmationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateRecentSignatureConfirmationPromiseFactoryConfig<'testnet'>): GetRecentSignatureConfirmationPromiseFn;\nexport function createRecentSignatureConfirmationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateRecentSignatureConfirmationPromiseFactoryConfig<'mainnet'>): GetRecentSignatureConfirmationPromiseFn;\nexport function createRecentSignatureConfirmationPromiseFactory<\n TCluster extends 'devnet' | 'mainnet' | 'testnet' | void = void,\n>({\n rpc,\n rpcSubscriptions,\n}: CreateRecentSignatureConfirmationPromiseFactoryConfig<TCluster>): GetRecentSignatureConfirmationPromiseFn {\n return async function getRecentSignatureConfirmationPromise({\n abortSignal: callerAbortSignal,\n commitment,\n signature,\n }) {\n const abortController = new AbortController();\n function handleAbort() {\n abortController.abort();\n }\n callerAbortSignal.addEventListener('abort', handleAbort, { signal: abortController.signal });\n /**\n * STEP 1: Set up a subscription for status changes to a signature.\n */\n const signatureStatusNotifications = await rpcSubscriptions\n .signatureNotifications(signature, { commitment })\n .subscribe({ abortSignal: abortController.signal });\n const signatureDidCommitPromise = (async () => {\n for await (const signatureStatusNotification of signatureStatusNotifications) {\n if (signatureStatusNotification.value.err) {\n throw getSolanaErrorFromTransactionError(signatureStatusNotification.value.err);\n } else {\n return;\n }\n }\n })();\n /**\n * STEP 2: Having subscribed for updates, make a one-shot request for the current status.\n * This will only yield a result if the signature is still in the status cache.\n */\n const signatureStatusLookupPromise = (async () => {\n const { value: signatureStatusResults } = await rpc\n .getSignatureStatuses([signature])\n .send({ abortSignal: abortController.signal });\n const signatureStatus = signatureStatusResults[0];\n if (\n signatureStatus?.confirmationStatus &&\n commitmentComparator(signatureStatus.confirmationStatus, commitment) >= 0\n ) {\n return;\n } else if (signatureStatus?.err) {\n throw getSolanaErrorFromTransactionError(signatureStatus.err);\n } else {\n await new Promise(() => {\n /* never resolve */\n });\n }\n })();\n try {\n return await safeRace([signatureDidCommitPromise, signatureStatusLookupPromise]);\n } finally {\n abortController.abort();\n }\n };\n}\n","import type { Commitment } from '@solana/rpc-types';\n\ntype Config = Readonly<{\n abortSignal: AbortSignal;\n /**\n * The timeout promise will throw after 30 seconds when the commitment is `processed`, and 60\n * seconds otherwise.\n */\n commitment: Commitment;\n}>;\n\n/**\n * When no other heuristic exists to infer that a transaction has expired, you can use this promise\n * factory with a commitment level. It throws after 30 seconds when the commitment is `processed`,\n * and 60 seconds otherwise. You would typically race this with another confirmation strategy.\n *\n * @param config\n *\n * @example\n * ```ts\n * import { safeRace } from '@solana/promises';\n * import { getTimeoutPromise } from '@solana/transaction-confirmation';\n *\n * try {\n * await safeRace([getCustomTransactionConfirmationPromise(/* ... *\\/), getTimeoutPromise({ commitment })]);\n * } catch (e) {\n * if (e instanceof DOMException && e.name === 'TimeoutError') {\n * console.log('Could not confirm transaction after a timeout');\n * }\n * throw e;\n * }\n * ```\n */\nexport async function getTimeoutPromise({ abortSignal: callerAbortSignal, commitment }: Config) {\n return await new Promise((_, reject) => {\n const handleAbort = (e: AbortSignalEventMap['abort']) => {\n clearTimeout(timeoutId);\n const abortError = new DOMException((e.target as AbortSignal).reason, 'AbortError');\n reject(abortError);\n };\n callerAbortSignal.addEventListener('abort', handleAbort);\n const timeoutMs = commitment === 'processed' ? 30_000 : 60_000;\n const startMs = performance.now();\n const timeoutId =\n // We use `setTimeout` instead of `AbortSignal.timeout()` because we want to measure\n // elapsed time instead of active time.\n // See https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal/timeout_static\n setTimeout(() => {\n const elapsedMs = performance.now() - startMs;\n reject(new DOMException(`Timeout elapsed after ${elapsedMs} ms`, 'TimeoutError'));\n }, timeoutMs);\n });\n}\n","import { AbortController } from '@solana/event-target-impl';\nimport type { Signature } from '@solana/keys';\nimport { safeRace } from '@solana/promises';\nimport type { Commitment } from '@solana/rpc-types';\n\nimport { createRecentSignatureConfirmationPromiseFactory } from './confirmation-strategy-recent-signature';\n\nexport interface BaseTransactionConfirmationStrategyConfig {\n abortSignal?: AbortSignal;\n commitment: Commitment;\n getRecentSignatureConfirmationPromise: ReturnType<typeof createRecentSignatureConfirmationPromiseFactory>;\n}\n\ntype WithNonNullableAbortSignal<T> = Omit<T, 'abortSignal'> & Readonly<{ abortSignal: AbortSignal }>;\n\nexport async function raceStrategies<TConfig extends BaseTransactionConfirmationStrategyConfig>(\n signature: Signature,\n config: TConfig,\n getSpecificStrategiesForRace: (config: WithNonNullableAbortSignal<TConfig>) => readonly Promise<unknown>[],\n) {\n const { abortSignal: callerAbortSignal, commitment, getRecentSignatureConfirmationPromise } = config;\n callerAbortSignal?.throwIfAborted();\n const abortController = new AbortController();\n if (callerAbortSignal) {\n const handleAbort = () => {\n abortController.abort();\n };\n callerAbortSignal.addEventListener('abort', handleAbort, { signal: abortController.signal });\n }\n try {\n const specificStrategies = getSpecificStrategiesForRace({\n ...config,\n abortSignal: abortController.signal,\n });\n return await safeRace([\n getRecentSignatureConfirmationPromise({\n abortSignal: abortController.signal,\n commitment,\n signature,\n }),\n ...specificStrategies,\n ]);\n } finally {\n abortController.abort();\n }\n}\n","import { Signature } from '@solana/keys';\nimport {\n getSignatureFromTransaction,\n Transaction,\n TransactionWithBlockhashLifetime,\n TransactionWithDurableNonceLifetime,\n} from '@solana/transactions';\n\nimport { createBlockHeightExceedencePromiseFactory } from './confirmation-strategy-blockheight';\nimport { createNonceInvalidationPromiseFactory } from './confirmation-strategy-nonce';\nimport { BaseTransactionConfirmationStrategyConfig, raceStrategies } from './confirmation-strategy-racer';\nimport { getTimeoutPromise } from './confirmation-strategy-timeout';\n\nexport type TransactionWithLastValidBlockHeight = Omit<TransactionWithBlockhashLifetime, 'lifetimeConstraint'> & {\n lifetimeConstraint: Omit<TransactionWithBlockhashLifetime['lifetimeConstraint'], 'blockhash'>;\n};\n\ninterface WaitForDurableNonceTransactionConfirmationConfig extends BaseTransactionConfirmationStrategyConfig {\n getNonceInvalidationPromise: ReturnType<typeof createNonceInvalidationPromiseFactory>;\n transaction: Readonly<Transaction & TransactionWithDurableNonceLifetime>;\n}\n\ninterface WaitForRecentTransactionWithBlockhashLifetimeConfirmationConfig\n extends BaseTransactionConfirmationStrategyConfig {\n getBlockHeightExceedencePromise: ReturnType<typeof createBlockHeightExceedencePromiseFactory>;\n transaction: Readonly<Transaction & TransactionWithLastValidBlockHeight>;\n}\n\ninterface WaitForRecentTransactionWithTimeBasedLifetimeConfirmationConfig\n extends BaseTransactionConfirmationStrategyConfig {\n getTimeoutPromise: typeof getTimeoutPromise;\n /**\n * A 64 byte Ed25519 signature, encoded as a base-58 string, that uniquely identifies a\n * transaction by virtue of being the first or only signature in its list of signatures.\n */\n signature: Signature;\n}\n\n/**\n * Supply your own confirmation implementations to this function to create a custom nonce\n * transaction confirmation strategy.\n *\n * @example\n * ```ts\n * import { waitForDurableNonceTransactionConfirmation } from '@solana/transaction-confirmation';\n *\n * try {\n * await waitForDurableNonceTransactionConfirmation({\n * getNonceInvalidationPromise({ abortSignal, commitment, currentNonceValue, nonceAccountAddress }) {\n * // Return a promise that rejects when a nonce becomes invalid.\n * },\n * getRecentSignatureConfirmationPromise({ abortSignal, commitment, signature }) {\n * // Return a promise that resolves when a transaction achieves confirmation\n * },\n * });\n * } catch (e) {\n * // Handle errors.\n * }\n * ```\n */\nexport async function waitForDurableNonceTransactionConfirmation(\n config: WaitForDurableNonceTransactionConfirmationConfig,\n): Promise<void> {\n await raceStrategies(\n getSignatureFromTransaction(config.transaction),\n config,\n function getSpecificStrategiesForRace({ abortSignal, commitment, getNonceInvalidationPromise, transaction }) {\n return [\n getNonceInvalidationPromise({\n abortSignal,\n commitment,\n currentNonceValue: transaction.lifetimeConstraint.nonce,\n nonceAccountAddress: transaction.lifetimeConstraint.nonceAccountAddress,\n }),\n ];\n },\n );\n}\n\n/**\n * Supply your own confirmation implementations to this function to create a custom confirmation\n * strategy for recently-landed transactions.\n *\n * @example\n * ```ts\n * import { waitForRecentTransactionConfirmation } from '@solana/transaction-confirmation';\n *\n * try {\n * await waitForRecentTransactionConfirmation({\n * getBlockHeightExceedencePromise({ abortSignal, commitment, lastValidBlockHeight }) {\n * // Return a promise that rejects when the blockhash's block height has been exceeded\n * },\n * getRecentSignatureConfirmationPromise({ abortSignal, commitment, signature }) {\n * // Return a promise that resolves when a transaction achieves confirmation\n * },\n * });\n * } catch (e) {\n * // Handle errors.\n * }\n * ```\n */\nexport async function waitForRecentTransactionConfirmation(\n config: WaitForRecentTransactionWithBlockhashLifetimeConfirmationConfig,\n): Promise<void> {\n await raceStrategies(\n getSignatureFromTransaction(config.transaction),\n config,\n function getSpecificStrategiesForRace({\n abortSignal,\n commitment,\n getBlockHeightExceedencePromise,\n transaction,\n }) {\n return [\n getBlockHeightExceedencePromise({\n abortSignal,\n commitment,\n lastValidBlockHeight: transaction.lifetimeConstraint.lastValidBlockHeight,\n }),\n ];\n },\n );\n}\n\n/** @deprecated */\nexport async function waitForRecentTransactionConfirmationUntilTimeout(\n config: WaitForRecentTransactionWithTimeBasedLifetimeConfirmationConfig,\n): Promise<void> {\n await raceStrategies(\n config.signature,\n config,\n function getSpecificStrategiesForRace({ abortSignal, commitment, getTimeoutPromise }) {\n return [\n getTimeoutPromise({\n abortSignal,\n commitment,\n }),\n ];\n },\n );\n}\n"]}
|
package/dist/index.node.cjs
CHANGED
|
@@ -169,8 +169,10 @@ function createRecentSignatureConfirmationPromiseFactory({
|
|
|
169
169
|
const signatureStatusLookupPromise = (async () => {
|
|
170
170
|
const { value: signatureStatusResults } = await rpc.getSignatureStatuses([signature]).send({ abortSignal: abortController.signal });
|
|
171
171
|
const signatureStatus = signatureStatusResults[0];
|
|
172
|
-
if (signatureStatus
|
|
172
|
+
if (signatureStatus?.confirmationStatus && rpcTypes.commitmentComparator(signatureStatus.confirmationStatus, commitment) >= 0) {
|
|
173
173
|
return;
|
|
174
|
+
} else if (signatureStatus?.err) {
|
|
175
|
+
throw errors.getSolanaErrorFromTransactionError(signatureStatus.err);
|
|
174
176
|
} else {
|
|
175
177
|
await new Promise(() => {
|
|
176
178
|
});
|
package/dist/index.node.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../event-target-impl/src/index.node.ts","../src/confirmation-strategy-blockheight.ts","../src/confirmation-strategy-nonce.ts","../src/confirmation-strategy-recent-signature.ts","../src/confirmation-strategy-timeout.ts","../src/confirmation-strategy-racer.ts","../src/waiters.ts"],"names":["AbortController","args","setMaxListeners","SolanaError","SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED","getBase58Decoder","getBase64Encoder","SOLANA_ERROR__INVALID_NONCE","SOLANA_ERROR__NONCE_ACCOUNT_NOT_FOUND","safeRace","getSolanaErrorFromTransactionError","commitmentComparator","e","getSignatureFromTransaction","getTimeoutPromise"],"mappings":"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","file":"index.node.cjs","sourcesContent":["import { setMaxListeners } from 'node:events';\n\nexport const AbortController = class extends globalThis.AbortController {\n constructor(...args: ConstructorParameters<typeof globalThis.AbortController>) {\n super(...args);\n setMaxListeners(Number.MAX_SAFE_INTEGER, this.signal);\n }\n};\n\nexport const EventTarget = class extends globalThis.EventTarget {\n constructor(...args: ConstructorParameters<typeof globalThis.EventTarget>) {\n super(...args);\n setMaxListeners(Number.MAX_SAFE_INTEGER, this);\n }\n};\n","import { SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED, SolanaError } from '@solana/errors';\nimport { AbortController } from '@solana/event-target-impl';\nimport type { GetEpochInfoApi, Rpc } from '@solana/rpc';\nimport type { RpcSubscriptions, SlotNotificationsApi } from '@solana/rpc-subscriptions';\nimport type { Commitment } from '@solana/rpc-types';\n\ntype GetBlockHeightExceedencePromiseFn = (config: {\n abortSignal: AbortSignal;\n /**\n * Fetch the block height as of the highest slot that has reached this level of commitment.\n *\n * @defaultValue Whichever default is applied by the underlying {@link RpcApi} in use. For\n * example, when using an API created by a `createSolanaRpc*()` helper, the default commitment\n * is `\"confirmed\"` unless configured otherwise. Unmitigated by an API layer on the client, the\n * default commitment applied by the server is `\"finalized\"`.\n */\n commitment?: Commitment;\n /** The block height after which to reject the promise */\n lastValidBlockHeight: bigint;\n}) => Promise<void>;\n\ntype CreateBlockHeightExceedencePromiseFactoryConfig<TCluster> = {\n rpc: Rpc<GetEpochInfoApi> & { '~cluster'?: TCluster };\n rpcSubscriptions: RpcSubscriptions<SlotNotificationsApi> & { '~cluster'?: TCluster };\n};\n\n/**\n * Creates a promise that throws when the network progresses past the block height after which the\n * supplied blockhash is considered expired for use as a transaction lifetime specifier.\n *\n * When a transaction's lifetime is tied to a blockhash, that transaction can be landed on the\n * network until that blockhash expires. All blockhashes have a block height after which they are\n * considered to have expired.\n *\n * @param config\n *\n * @example\n * ```ts\n * import { isSolanaError, SolanaError } from '@solana/errors';\n * import { createBlockHeightExceedencePromiseFactory } from '@solana/transaction-confirmation';\n *\n * const getBlockHeightExceedencePromise = createBlockHeightExceedencePromiseFactory({\n * rpc,\n * rpcSubscriptions,\n * });\n * try {\n * await getBlockHeightExceedencePromise({ lastValidBlockHeight });\n * } catch (e) {\n * if (isSolanaError(e, SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED)) {\n * console.error(\n * `The block height of the network has exceeded ${e.context.lastValidBlockHeight}. ` +\n * `It is now ${e.context.currentBlockHeight}`,\n * );\n * // Re-sign and retry the transaction.\n * return;\n * }\n * throw e;\n * }\n * ```\n */\nexport function createBlockHeightExceedencePromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateBlockHeightExceedencePromiseFactoryConfig<'devnet'>): GetBlockHeightExceedencePromiseFn;\nexport function createBlockHeightExceedencePromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateBlockHeightExceedencePromiseFactoryConfig<'testnet'>): GetBlockHeightExceedencePromiseFn;\nexport function createBlockHeightExceedencePromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateBlockHeightExceedencePromiseFactoryConfig<'mainnet'>): GetBlockHeightExceedencePromiseFn;\nexport function createBlockHeightExceedencePromiseFactory<\n TCluster extends 'devnet' | 'mainnet' | 'testnet' | void = void,\n>({\n rpc,\n rpcSubscriptions,\n}: CreateBlockHeightExceedencePromiseFactoryConfig<TCluster>): GetBlockHeightExceedencePromiseFn {\n return async function getBlockHeightExceedencePromise({\n abortSignal: callerAbortSignal,\n commitment,\n lastValidBlockHeight,\n }): Promise<never> {\n callerAbortSignal.throwIfAborted();\n const abortController = new AbortController();\n const handleAbort = () => {\n abortController.abort();\n };\n callerAbortSignal.addEventListener('abort', handleAbort, { signal: abortController.signal });\n async function getBlockHeightAndDifferenceBetweenSlotHeightAndBlockHeight() {\n const { absoluteSlot, blockHeight } = await rpc\n .getEpochInfo({ commitment })\n .send({ abortSignal: abortController.signal });\n return {\n blockHeight,\n differenceBetweenSlotHeightAndBlockHeight: absoluteSlot - blockHeight,\n };\n }\n try {\n const [slotNotifications, { blockHeight: initialBlockHeight, differenceBetweenSlotHeightAndBlockHeight }] =\n await Promise.all([\n rpcSubscriptions.slotNotifications().subscribe({ abortSignal: abortController.signal }),\n getBlockHeightAndDifferenceBetweenSlotHeightAndBlockHeight(),\n ]);\n callerAbortSignal.throwIfAborted();\n let currentBlockHeight = initialBlockHeight;\n if (currentBlockHeight <= lastValidBlockHeight) {\n let lastKnownDifferenceBetweenSlotHeightAndBlockHeight = differenceBetweenSlotHeightAndBlockHeight;\n for await (const slotNotification of slotNotifications) {\n const { slot } = slotNotification;\n if (slot - lastKnownDifferenceBetweenSlotHeightAndBlockHeight > lastValidBlockHeight) {\n // Before making a final decision, recheck the actual block height.\n const {\n blockHeight: recheckedBlockHeight,\n differenceBetweenSlotHeightAndBlockHeight: currentDifferenceBetweenSlotHeightAndBlockHeight,\n } = await getBlockHeightAndDifferenceBetweenSlotHeightAndBlockHeight();\n currentBlockHeight = recheckedBlockHeight;\n if (currentBlockHeight > lastValidBlockHeight) {\n // Verified; the block height has been exceeded.\n break;\n } else {\n // The block height has not been exceeded, which implies that the\n // difference between the slot height and the block height has grown\n // (ie. some blocks have been skipped since we started). Recalibrate the\n // difference and keep waiting.\n lastKnownDifferenceBetweenSlotHeightAndBlockHeight =\n currentDifferenceBetweenSlotHeightAndBlockHeight;\n }\n }\n }\n }\n callerAbortSignal.throwIfAborted();\n throw new SolanaError(SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED, {\n currentBlockHeight,\n lastValidBlockHeight,\n });\n } finally {\n abortController.abort();\n }\n };\n}\n","import type { Address } from '@solana/addresses';\nimport { getBase58Decoder, getBase64Encoder } from '@solana/codecs-strings';\nimport { SOLANA_ERROR__INVALID_NONCE, SOLANA_ERROR__NONCE_ACCOUNT_NOT_FOUND, SolanaError } from '@solana/errors';\nimport { AbortController } from '@solana/event-target-impl';\nimport { safeRace } from '@solana/promises';\nimport type { GetAccountInfoApi, Rpc } from '@solana/rpc';\nimport type { AccountNotificationsApi, RpcSubscriptions } from '@solana/rpc-subscriptions';\nimport type { Base64EncodedDataResponse, Commitment } from '@solana/rpc-types';\nimport { Nonce } from '@solana/transaction-messages';\n\ntype GetNonceInvalidationPromiseFn = (config: {\n abortSignal: AbortSignal;\n /**\n * Fetch the nonce account details as of the highest slot that has reached this level of\n * commitment.\n */\n commitment: Commitment;\n /**\n * The value of the nonce that we would expect to see in the nonce account in order for any\n * transaction with that nonce-based lifetime to be considered valid.\n */\n currentNonceValue: Nonce;\n /** The address of the account in which the currently-valid nonce value is stored */\n nonceAccountAddress: Address;\n}) => Promise<void>;\n\ntype CreateNonceInvalidationPromiseFactoryConfig<TCluster> = {\n rpc: Rpc<GetAccountInfoApi> & { '~cluster'?: TCluster };\n rpcSubscriptions: RpcSubscriptions<AccountNotificationsApi> & { '~cluster'?: TCluster };\n};\n\nconst NONCE_VALUE_OFFSET =\n 4 + // version(u32)\n 4 + // state(u32)\n 32; // nonce authority(pubkey)\n// Then comes the nonce value.\n\n/**\n * Creates a promise that throws when the value stored in a nonce account is not the expected one.\n *\n * When a transaction's lifetime is tied to the value stored in a nonce account, that transaction\n * can be landed on the network until the nonce is advanced to a new value.\n *\n * @param config\n *\n * @example\n * ```ts\n * import { isSolanaError, SolanaError } from '@solana/errors';\n * import { createNonceInvalidationPromiseFactory } from '@solana/transaction-confirmation';\n *\n * const getNonceInvalidationPromise = createNonceInvalidationPromiseFactory({\n * rpc,\n * rpcSubscriptions,\n * });\n * try {\n * await getNonceInvalidationPromise({\n * currentNonceValue,\n * nonceAccountAddress,\n * });\n * } catch (e) {\n * if (isSolanaError(e, SOLANA_ERROR__NONCE_INVALID)) {\n * console.error(`The nonce has advanced to ${e.context.actualNonceValue}`);\n * // Re-sign and retry the transaction.\n * return;\n * } else if (isSolanaError(e, SOLANA_ERROR__NONCE_ACCOUNT_NOT_FOUND)) {\n * console.error(`No nonce account was found at ${nonceAccountAddress}`);\n * }\n * throw e;\n * }\n * ```\n */\nexport function createNonceInvalidationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateNonceInvalidationPromiseFactoryConfig<'devnet'>): GetNonceInvalidationPromiseFn;\nexport function createNonceInvalidationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateNonceInvalidationPromiseFactoryConfig<'testnet'>): GetNonceInvalidationPromiseFn;\nexport function createNonceInvalidationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateNonceInvalidationPromiseFactoryConfig<'mainnet'>): GetNonceInvalidationPromiseFn;\nexport function createNonceInvalidationPromiseFactory<TCluster extends 'devnet' | 'mainnet' | 'testnet' | void = void>({\n rpc,\n rpcSubscriptions,\n}: CreateNonceInvalidationPromiseFactoryConfig<TCluster>): GetNonceInvalidationPromiseFn {\n return async function getNonceInvalidationPromise({\n abortSignal: callerAbortSignal,\n commitment,\n currentNonceValue: expectedNonceValue,\n nonceAccountAddress,\n }) {\n const abortController = new AbortController();\n function handleAbort() {\n abortController.abort();\n }\n callerAbortSignal.addEventListener('abort', handleAbort, { signal: abortController.signal });\n /**\n * STEP 1: Set up a subscription for nonce account changes.\n */\n const accountNotifications = await rpcSubscriptions\n .accountNotifications(nonceAccountAddress, { commitment, encoding: 'base64' })\n .subscribe({ abortSignal: abortController.signal });\n const base58Decoder = getBase58Decoder();\n const base64Encoder = getBase64Encoder();\n function getNonceFromAccountData([base64EncodedBytes]: Base64EncodedDataResponse): Nonce {\n const data = base64Encoder.encode(base64EncodedBytes);\n const nonceValueBytes = data.slice(NONCE_VALUE_OFFSET, NONCE_VALUE_OFFSET + 32);\n return base58Decoder.decode(nonceValueBytes) as Nonce;\n }\n const nonceAccountDidAdvancePromise = (async () => {\n for await (const accountNotification of accountNotifications) {\n const nonceValue = getNonceFromAccountData(accountNotification.value.data);\n if (nonceValue !== expectedNonceValue) {\n throw new SolanaError(SOLANA_ERROR__INVALID_NONCE, {\n actualNonceValue: nonceValue,\n expectedNonceValue,\n });\n }\n }\n })();\n /**\n * STEP 2: Having subscribed for updates, make a one-shot request for the current nonce\n * value to check if it has already been advanced.\n */\n const nonceIsAlreadyInvalidPromise = (async () => {\n const { value: nonceAccount } = await rpc\n .getAccountInfo(nonceAccountAddress, {\n commitment,\n dataSlice: { length: 32, offset: NONCE_VALUE_OFFSET },\n encoding: 'base58',\n })\n .send({ abortSignal: abortController.signal });\n if (!nonceAccount) {\n throw new SolanaError(SOLANA_ERROR__NONCE_ACCOUNT_NOT_FOUND, {\n nonceAccountAddress,\n });\n }\n const nonceValue =\n // This works because we asked for the exact slice of data representing the nonce\n // value, and furthermore asked for it in `base58` encoding.\n nonceAccount.data[0] as unknown as Nonce;\n if (nonceValue !== expectedNonceValue) {\n throw new SolanaError(SOLANA_ERROR__INVALID_NONCE, {\n actualNonceValue: nonceValue,\n expectedNonceValue,\n });\n } else {\n await new Promise(() => {\n /* never resolve */\n });\n }\n })();\n try {\n return await safeRace([nonceAccountDidAdvancePromise, nonceIsAlreadyInvalidPromise]);\n } finally {\n abortController.abort();\n }\n };\n}\n","import { getSolanaErrorFromTransactionError } from '@solana/errors';\nimport { AbortController } from '@solana/event-target-impl';\nimport type { Signature } from '@solana/keys';\nimport { safeRace } from '@solana/promises';\nimport type { GetSignatureStatusesApi, Rpc } from '@solana/rpc';\nimport type { RpcSubscriptions, SignatureNotificationsApi } from '@solana/rpc-subscriptions';\nimport { type Commitment, commitmentComparator } from '@solana/rpc-types';\n\ntype GetRecentSignatureConfirmationPromiseFn = (config: {\n abortSignal: AbortSignal;\n /**\n * The level of commitment the transaction must have achieved in order for the promise to\n * resolve.\n */\n commitment: Commitment;\n /**\n * A 64 byte Ed25519 signature, encoded as a base-58 string, that uniquely identifies a\n * transaction by virtue of being the first or only signature in its list of signatures.\n */\n signature: Signature;\n}) => Promise<void>;\n\ntype CreateRecentSignatureConfirmationPromiseFactoryConfig<TCluster> = {\n rpc: Rpc<GetSignatureStatusesApi> & { '~cluster'?: TCluster };\n rpcSubscriptions: RpcSubscriptions<SignatureNotificationsApi> & { '~cluster'?: TCluster };\n};\n\n/**\n * Creates a promise that resolves when a recently-landed transaction achieves the target\n * confirmation commitment, and throws when the transaction fails with an error.\n *\n * The status of recently-landed transactions is available in the network's status cache. This\n * confirmation strategy will only yield a result if the signature is still in the status cache. To\n * fetch the status of transactions older than those available in the status cache, use the\n * {@link GetSignatureStatusesApi.getSignatureStatuses} method setting the\n * `searchTransactionHistory` configuration param to `true`.\n *\n * @param config\n *\n * @example\n * ```ts\n * import { createRecentSignatureConfirmationPromiseFactory } from '@solana/transaction-confirmation';\n *\n * const getRecentSignatureConfirmationPromise = createRecentSignatureConfirmationPromiseFactory({\n * rpc,\n * rpcSubscriptions,\n * });\n * try {\n * await getRecentSignatureConfirmationPromise({\n * commitment,\n * signature,\n * });\n * console.log(`The transaction with signature \\`${signature}\\` has achieved a commitment level of \\`${commitment}\\``);\n * } catch (e) {\n * console.error(`The transaction with signature \\`${signature}\\` failed`, e.cause);\n * throw e;\n * }\n * ```\n */\nexport function createRecentSignatureConfirmationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateRecentSignatureConfirmationPromiseFactoryConfig<'devnet'>): GetRecentSignatureConfirmationPromiseFn;\nexport function createRecentSignatureConfirmationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateRecentSignatureConfirmationPromiseFactoryConfig<'testnet'>): GetRecentSignatureConfirmationPromiseFn;\nexport function createRecentSignatureConfirmationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateRecentSignatureConfirmationPromiseFactoryConfig<'mainnet'>): GetRecentSignatureConfirmationPromiseFn;\nexport function createRecentSignatureConfirmationPromiseFactory<\n TCluster extends 'devnet' | 'mainnet' | 'testnet' | void = void,\n>({\n rpc,\n rpcSubscriptions,\n}: CreateRecentSignatureConfirmationPromiseFactoryConfig<TCluster>): GetRecentSignatureConfirmationPromiseFn {\n return async function getRecentSignatureConfirmationPromise({\n abortSignal: callerAbortSignal,\n commitment,\n signature,\n }) {\n const abortController = new AbortController();\n function handleAbort() {\n abortController.abort();\n }\n callerAbortSignal.addEventListener('abort', handleAbort, { signal: abortController.signal });\n /**\n * STEP 1: Set up a subscription for status changes to a signature.\n */\n const signatureStatusNotifications = await rpcSubscriptions\n .signatureNotifications(signature, { commitment })\n .subscribe({ abortSignal: abortController.signal });\n const signatureDidCommitPromise = (async () => {\n for await (const signatureStatusNotification of signatureStatusNotifications) {\n if (signatureStatusNotification.value.err) {\n throw getSolanaErrorFromTransactionError(signatureStatusNotification.value.err);\n } else {\n return;\n }\n }\n })();\n /**\n * STEP 2: Having subscribed for updates, make a one-shot request for the current status.\n * This will only yield a result if the signature is still in the status cache.\n */\n const signatureStatusLookupPromise = (async () => {\n const { value: signatureStatusResults } = await rpc\n .getSignatureStatuses([signature])\n .send({ abortSignal: abortController.signal });\n const signatureStatus = signatureStatusResults[0];\n if (\n signatureStatus &&\n signatureStatus.confirmationStatus &&\n commitmentComparator(signatureStatus.confirmationStatus, commitment) >= 0\n ) {\n return;\n } else {\n await new Promise(() => {\n /* never resolve */\n });\n }\n })();\n try {\n return await safeRace([signatureDidCommitPromise, signatureStatusLookupPromise]);\n } finally {\n abortController.abort();\n }\n };\n}\n","import type { Commitment } from '@solana/rpc-types';\n\ntype Config = Readonly<{\n abortSignal: AbortSignal;\n /**\n * The timeout promise will throw after 30 seconds when the commitment is `processed`, and 60\n * seconds otherwise.\n */\n commitment: Commitment;\n}>;\n\n/**\n * When no other heuristic exists to infer that a transaction has expired, you can use this promise\n * factory with a commitment level. It throws after 30 seconds when the commitment is `processed`,\n * and 60 seconds otherwise. You would typically race this with another confirmation strategy.\n *\n * @param config\n *\n * @example\n * ```ts\n * import { safeRace } from '@solana/promises';\n * import { getTimeoutPromise } from '@solana/transaction-confirmation';\n *\n * try {\n * await safeRace([getCustomTransactionConfirmationPromise(/* ... *\\/), getTimeoutPromise({ commitment })]);\n * } catch (e) {\n * if (e instanceof DOMException && e.name === 'TimeoutError') {\n * console.log('Could not confirm transaction after a timeout');\n * }\n * throw e;\n * }\n * ```\n */\nexport async function getTimeoutPromise({ abortSignal: callerAbortSignal, commitment }: Config) {\n return await new Promise((_, reject) => {\n const handleAbort = (e: AbortSignalEventMap['abort']) => {\n clearTimeout(timeoutId);\n const abortError = new DOMException((e.target as AbortSignal).reason, 'AbortError');\n reject(abortError);\n };\n callerAbortSignal.addEventListener('abort', handleAbort);\n const timeoutMs = commitment === 'processed' ? 30_000 : 60_000;\n const startMs = performance.now();\n const timeoutId =\n // We use `setTimeout` instead of `AbortSignal.timeout()` because we want to measure\n // elapsed time instead of active time.\n // See https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal/timeout_static\n setTimeout(() => {\n const elapsedMs = performance.now() - startMs;\n reject(new DOMException(`Timeout elapsed after ${elapsedMs} ms`, 'TimeoutError'));\n }, timeoutMs);\n });\n}\n","import { AbortController } from '@solana/event-target-impl';\nimport type { Signature } from '@solana/keys';\nimport { safeRace } from '@solana/promises';\nimport type { Commitment } from '@solana/rpc-types';\n\nimport { createRecentSignatureConfirmationPromiseFactory } from './confirmation-strategy-recent-signature';\n\nexport interface BaseTransactionConfirmationStrategyConfig {\n abortSignal?: AbortSignal;\n commitment: Commitment;\n getRecentSignatureConfirmationPromise: ReturnType<typeof createRecentSignatureConfirmationPromiseFactory>;\n}\n\ntype WithNonNullableAbortSignal<T> = Omit<T, 'abortSignal'> & Readonly<{ abortSignal: AbortSignal }>;\n\nexport async function raceStrategies<TConfig extends BaseTransactionConfirmationStrategyConfig>(\n signature: Signature,\n config: TConfig,\n getSpecificStrategiesForRace: (config: WithNonNullableAbortSignal<TConfig>) => readonly Promise<unknown>[],\n) {\n const { abortSignal: callerAbortSignal, commitment, getRecentSignatureConfirmationPromise } = config;\n callerAbortSignal?.throwIfAborted();\n const abortController = new AbortController();\n if (callerAbortSignal) {\n const handleAbort = () => {\n abortController.abort();\n };\n callerAbortSignal.addEventListener('abort', handleAbort, { signal: abortController.signal });\n }\n try {\n const specificStrategies = getSpecificStrategiesForRace({\n ...config,\n abortSignal: abortController.signal,\n });\n return await safeRace([\n getRecentSignatureConfirmationPromise({\n abortSignal: abortController.signal,\n commitment,\n signature,\n }),\n ...specificStrategies,\n ]);\n } finally {\n abortController.abort();\n }\n}\n","import { Signature } from '@solana/keys';\nimport {\n getSignatureFromTransaction,\n Transaction,\n TransactionWithBlockhashLifetime,\n TransactionWithDurableNonceLifetime,\n} from '@solana/transactions';\n\nimport { createBlockHeightExceedencePromiseFactory } from './confirmation-strategy-blockheight';\nimport { createNonceInvalidationPromiseFactory } from './confirmation-strategy-nonce';\nimport { BaseTransactionConfirmationStrategyConfig, raceStrategies } from './confirmation-strategy-racer';\nimport { getTimeoutPromise } from './confirmation-strategy-timeout';\n\nexport type TransactionWithLastValidBlockHeight = Omit<TransactionWithBlockhashLifetime, 'lifetimeConstraint'> & {\n lifetimeConstraint: Omit<TransactionWithBlockhashLifetime['lifetimeConstraint'], 'blockhash'>;\n};\n\ninterface WaitForDurableNonceTransactionConfirmationConfig extends BaseTransactionConfirmationStrategyConfig {\n getNonceInvalidationPromise: ReturnType<typeof createNonceInvalidationPromiseFactory>;\n transaction: Readonly<Transaction & TransactionWithDurableNonceLifetime>;\n}\n\ninterface WaitForRecentTransactionWithBlockhashLifetimeConfirmationConfig\n extends BaseTransactionConfirmationStrategyConfig {\n getBlockHeightExceedencePromise: ReturnType<typeof createBlockHeightExceedencePromiseFactory>;\n transaction: Readonly<Transaction & TransactionWithLastValidBlockHeight>;\n}\n\ninterface WaitForRecentTransactionWithTimeBasedLifetimeConfirmationConfig\n extends BaseTransactionConfirmationStrategyConfig {\n getTimeoutPromise: typeof getTimeoutPromise;\n /**\n * A 64 byte Ed25519 signature, encoded as a base-58 string, that uniquely identifies a\n * transaction by virtue of being the first or only signature in its list of signatures.\n */\n signature: Signature;\n}\n\n/**\n * Supply your own confirmation implementations to this function to create a custom nonce\n * transaction confirmation strategy.\n *\n * @example\n * ```ts\n * import { waitForDurableNonceTransactionConfirmation } from '@solana/transaction-confirmation';\n *\n * try {\n * await waitForDurableNonceTransactionConfirmation({\n * getNonceInvalidationPromise({ abortSignal, commitment, currentNonceValue, nonceAccountAddress }) {\n * // Return a promise that rejects when a nonce becomes invalid.\n * },\n * getRecentSignatureConfirmationPromise({ abortSignal, commitment, signature }) {\n * // Return a promise that resolves when a transaction achieves confirmation\n * },\n * });\n * } catch (e) {\n * // Handle errors.\n * }\n * ```\n */\nexport async function waitForDurableNonceTransactionConfirmation(\n config: WaitForDurableNonceTransactionConfirmationConfig,\n): Promise<void> {\n await raceStrategies(\n getSignatureFromTransaction(config.transaction),\n config,\n function getSpecificStrategiesForRace({ abortSignal, commitment, getNonceInvalidationPromise, transaction }) {\n return [\n getNonceInvalidationPromise({\n abortSignal,\n commitment,\n currentNonceValue: transaction.lifetimeConstraint.nonce,\n nonceAccountAddress: transaction.lifetimeConstraint.nonceAccountAddress,\n }),\n ];\n },\n );\n}\n\n/**\n * Supply your own confirmation implementations to this function to create a custom confirmation\n * strategy for recently-landed transactions.\n *\n * @example\n * ```ts\n * import { waitForRecentTransactionConfirmation } from '@solana/transaction-confirmation';\n *\n * try {\n * await waitForRecentTransactionConfirmation({\n * getBlockHeightExceedencePromise({ abortSignal, commitment, lastValidBlockHeight }) {\n * // Return a promise that rejects when the blockhash's block height has been exceeded\n * },\n * getRecentSignatureConfirmationPromise({ abortSignal, commitment, signature }) {\n * // Return a promise that resolves when a transaction achieves confirmation\n * },\n * });\n * } catch (e) {\n * // Handle errors.\n * }\n * ```\n */\nexport async function waitForRecentTransactionConfirmation(\n config: WaitForRecentTransactionWithBlockhashLifetimeConfirmationConfig,\n): Promise<void> {\n await raceStrategies(\n getSignatureFromTransaction(config.transaction),\n config,\n function getSpecificStrategiesForRace({\n abortSignal,\n commitment,\n getBlockHeightExceedencePromise,\n transaction,\n }) {\n return [\n getBlockHeightExceedencePromise({\n abortSignal,\n commitment,\n lastValidBlockHeight: transaction.lifetimeConstraint.lastValidBlockHeight,\n }),\n ];\n },\n );\n}\n\n/** @deprecated */\nexport async function waitForRecentTransactionConfirmationUntilTimeout(\n config: WaitForRecentTransactionWithTimeBasedLifetimeConfirmationConfig,\n): Promise<void> {\n await raceStrategies(\n config.signature,\n config,\n function getSpecificStrategiesForRace({ abortSignal, commitment, getTimeoutPromise }) {\n return [\n getTimeoutPromise({\n abortSignal,\n commitment,\n }),\n ];\n },\n );\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../event-target-impl/src/index.node.ts","../src/confirmation-strategy-blockheight.ts","../src/confirmation-strategy-nonce.ts","../src/confirmation-strategy-recent-signature.ts","../src/confirmation-strategy-timeout.ts","../src/confirmation-strategy-racer.ts","../src/waiters.ts"],"names":["AbortController","args","setMaxListeners","SolanaError","SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED","getBase58Decoder","getBase64Encoder","SOLANA_ERROR__INVALID_NONCE","SOLANA_ERROR__NONCE_ACCOUNT_NOT_FOUND","safeRace","getSolanaErrorFromTransactionError","commitmentComparator","e","getSignatureFromTransaction","getTimeoutPromise"],"mappings":"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","file":"index.node.cjs","sourcesContent":["import { setMaxListeners } from 'node:events';\n\nexport const AbortController = class extends globalThis.AbortController {\n constructor(...args: ConstructorParameters<typeof globalThis.AbortController>) {\n super(...args);\n setMaxListeners(Number.MAX_SAFE_INTEGER, this.signal);\n }\n};\n\nexport const EventTarget = class extends globalThis.EventTarget {\n constructor(...args: ConstructorParameters<typeof globalThis.EventTarget>) {\n super(...args);\n setMaxListeners(Number.MAX_SAFE_INTEGER, this);\n }\n};\n","import { SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED, SolanaError } from '@solana/errors';\nimport { AbortController } from '@solana/event-target-impl';\nimport type { GetEpochInfoApi, Rpc } from '@solana/rpc';\nimport type { RpcSubscriptions, SlotNotificationsApi } from '@solana/rpc-subscriptions';\nimport type { Commitment } from '@solana/rpc-types';\n\ntype GetBlockHeightExceedencePromiseFn = (config: {\n abortSignal: AbortSignal;\n /**\n * Fetch the block height as of the highest slot that has reached this level of commitment.\n *\n * @defaultValue Whichever default is applied by the underlying {@link RpcApi} in use. For\n * example, when using an API created by a `createSolanaRpc*()` helper, the default commitment\n * is `\"confirmed\"` unless configured otherwise. Unmitigated by an API layer on the client, the\n * default commitment applied by the server is `\"finalized\"`.\n */\n commitment?: Commitment;\n /** The block height after which to reject the promise */\n lastValidBlockHeight: bigint;\n}) => Promise<void>;\n\ntype CreateBlockHeightExceedencePromiseFactoryConfig<TCluster> = {\n rpc: Rpc<GetEpochInfoApi> & { '~cluster'?: TCluster };\n rpcSubscriptions: RpcSubscriptions<SlotNotificationsApi> & { '~cluster'?: TCluster };\n};\n\n/**\n * Creates a promise that throws when the network progresses past the block height after which the\n * supplied blockhash is considered expired for use as a transaction lifetime specifier.\n *\n * When a transaction's lifetime is tied to a blockhash, that transaction can be landed on the\n * network until that blockhash expires. All blockhashes have a block height after which they are\n * considered to have expired.\n *\n * @param config\n *\n * @example\n * ```ts\n * import { isSolanaError, SolanaError } from '@solana/errors';\n * import { createBlockHeightExceedencePromiseFactory } from '@solana/transaction-confirmation';\n *\n * const getBlockHeightExceedencePromise = createBlockHeightExceedencePromiseFactory({\n * rpc,\n * rpcSubscriptions,\n * });\n * try {\n * await getBlockHeightExceedencePromise({ lastValidBlockHeight });\n * } catch (e) {\n * if (isSolanaError(e, SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED)) {\n * console.error(\n * `The block height of the network has exceeded ${e.context.lastValidBlockHeight}. ` +\n * `It is now ${e.context.currentBlockHeight}`,\n * );\n * // Re-sign and retry the transaction.\n * return;\n * }\n * throw e;\n * }\n * ```\n */\nexport function createBlockHeightExceedencePromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateBlockHeightExceedencePromiseFactoryConfig<'devnet'>): GetBlockHeightExceedencePromiseFn;\nexport function createBlockHeightExceedencePromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateBlockHeightExceedencePromiseFactoryConfig<'testnet'>): GetBlockHeightExceedencePromiseFn;\nexport function createBlockHeightExceedencePromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateBlockHeightExceedencePromiseFactoryConfig<'mainnet'>): GetBlockHeightExceedencePromiseFn;\nexport function createBlockHeightExceedencePromiseFactory<\n TCluster extends 'devnet' | 'mainnet' | 'testnet' | void = void,\n>({\n rpc,\n rpcSubscriptions,\n}: CreateBlockHeightExceedencePromiseFactoryConfig<TCluster>): GetBlockHeightExceedencePromiseFn {\n return async function getBlockHeightExceedencePromise({\n abortSignal: callerAbortSignal,\n commitment,\n lastValidBlockHeight,\n }): Promise<never> {\n callerAbortSignal.throwIfAborted();\n const abortController = new AbortController();\n const handleAbort = () => {\n abortController.abort();\n };\n callerAbortSignal.addEventListener('abort', handleAbort, { signal: abortController.signal });\n async function getBlockHeightAndDifferenceBetweenSlotHeightAndBlockHeight() {\n const { absoluteSlot, blockHeight } = await rpc\n .getEpochInfo({ commitment })\n .send({ abortSignal: abortController.signal });\n return {\n blockHeight,\n differenceBetweenSlotHeightAndBlockHeight: absoluteSlot - blockHeight,\n };\n }\n try {\n const [slotNotifications, { blockHeight: initialBlockHeight, differenceBetweenSlotHeightAndBlockHeight }] =\n await Promise.all([\n rpcSubscriptions.slotNotifications().subscribe({ abortSignal: abortController.signal }),\n getBlockHeightAndDifferenceBetweenSlotHeightAndBlockHeight(),\n ]);\n callerAbortSignal.throwIfAborted();\n let currentBlockHeight = initialBlockHeight;\n if (currentBlockHeight <= lastValidBlockHeight) {\n let lastKnownDifferenceBetweenSlotHeightAndBlockHeight = differenceBetweenSlotHeightAndBlockHeight;\n for await (const slotNotification of slotNotifications) {\n const { slot } = slotNotification;\n if (slot - lastKnownDifferenceBetweenSlotHeightAndBlockHeight > lastValidBlockHeight) {\n // Before making a final decision, recheck the actual block height.\n const {\n blockHeight: recheckedBlockHeight,\n differenceBetweenSlotHeightAndBlockHeight: currentDifferenceBetweenSlotHeightAndBlockHeight,\n } = await getBlockHeightAndDifferenceBetweenSlotHeightAndBlockHeight();\n currentBlockHeight = recheckedBlockHeight;\n if (currentBlockHeight > lastValidBlockHeight) {\n // Verified; the block height has been exceeded.\n break;\n } else {\n // The block height has not been exceeded, which implies that the\n // difference between the slot height and the block height has grown\n // (ie. some blocks have been skipped since we started). Recalibrate the\n // difference and keep waiting.\n lastKnownDifferenceBetweenSlotHeightAndBlockHeight =\n currentDifferenceBetweenSlotHeightAndBlockHeight;\n }\n }\n }\n }\n callerAbortSignal.throwIfAborted();\n throw new SolanaError(SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED, {\n currentBlockHeight,\n lastValidBlockHeight,\n });\n } finally {\n abortController.abort();\n }\n };\n}\n","import type { Address } from '@solana/addresses';\nimport { getBase58Decoder, getBase64Encoder } from '@solana/codecs-strings';\nimport { SOLANA_ERROR__INVALID_NONCE, SOLANA_ERROR__NONCE_ACCOUNT_NOT_FOUND, SolanaError } from '@solana/errors';\nimport { AbortController } from '@solana/event-target-impl';\nimport { safeRace } from '@solana/promises';\nimport type { GetAccountInfoApi, Rpc } from '@solana/rpc';\nimport type { AccountNotificationsApi, RpcSubscriptions } from '@solana/rpc-subscriptions';\nimport type { Base64EncodedDataResponse, Commitment } from '@solana/rpc-types';\nimport { Nonce } from '@solana/transaction-messages';\n\ntype GetNonceInvalidationPromiseFn = (config: {\n abortSignal: AbortSignal;\n /**\n * Fetch the nonce account details as of the highest slot that has reached this level of\n * commitment.\n */\n commitment: Commitment;\n /**\n * The value of the nonce that we would expect to see in the nonce account in order for any\n * transaction with that nonce-based lifetime to be considered valid.\n */\n currentNonceValue: Nonce;\n /** The address of the account in which the currently-valid nonce value is stored */\n nonceAccountAddress: Address;\n}) => Promise<void>;\n\ntype CreateNonceInvalidationPromiseFactoryConfig<TCluster> = {\n rpc: Rpc<GetAccountInfoApi> & { '~cluster'?: TCluster };\n rpcSubscriptions: RpcSubscriptions<AccountNotificationsApi> & { '~cluster'?: TCluster };\n};\n\nconst NONCE_VALUE_OFFSET =\n 4 + // version(u32)\n 4 + // state(u32)\n 32; // nonce authority(pubkey)\n// Then comes the nonce value.\n\n/**\n * Creates a promise that throws when the value stored in a nonce account is not the expected one.\n *\n * When a transaction's lifetime is tied to the value stored in a nonce account, that transaction\n * can be landed on the network until the nonce is advanced to a new value.\n *\n * @param config\n *\n * @example\n * ```ts\n * import { isSolanaError, SolanaError } from '@solana/errors';\n * import { createNonceInvalidationPromiseFactory } from '@solana/transaction-confirmation';\n *\n * const getNonceInvalidationPromise = createNonceInvalidationPromiseFactory({\n * rpc,\n * rpcSubscriptions,\n * });\n * try {\n * await getNonceInvalidationPromise({\n * currentNonceValue,\n * nonceAccountAddress,\n * });\n * } catch (e) {\n * if (isSolanaError(e, SOLANA_ERROR__NONCE_INVALID)) {\n * console.error(`The nonce has advanced to ${e.context.actualNonceValue}`);\n * // Re-sign and retry the transaction.\n * return;\n * } else if (isSolanaError(e, SOLANA_ERROR__NONCE_ACCOUNT_NOT_FOUND)) {\n * console.error(`No nonce account was found at ${nonceAccountAddress}`);\n * }\n * throw e;\n * }\n * ```\n */\nexport function createNonceInvalidationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateNonceInvalidationPromiseFactoryConfig<'devnet'>): GetNonceInvalidationPromiseFn;\nexport function createNonceInvalidationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateNonceInvalidationPromiseFactoryConfig<'testnet'>): GetNonceInvalidationPromiseFn;\nexport function createNonceInvalidationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateNonceInvalidationPromiseFactoryConfig<'mainnet'>): GetNonceInvalidationPromiseFn;\nexport function createNonceInvalidationPromiseFactory<TCluster extends 'devnet' | 'mainnet' | 'testnet' | void = void>({\n rpc,\n rpcSubscriptions,\n}: CreateNonceInvalidationPromiseFactoryConfig<TCluster>): GetNonceInvalidationPromiseFn {\n return async function getNonceInvalidationPromise({\n abortSignal: callerAbortSignal,\n commitment,\n currentNonceValue: expectedNonceValue,\n nonceAccountAddress,\n }) {\n const abortController = new AbortController();\n function handleAbort() {\n abortController.abort();\n }\n callerAbortSignal.addEventListener('abort', handleAbort, { signal: abortController.signal });\n /**\n * STEP 1: Set up a subscription for nonce account changes.\n */\n const accountNotifications = await rpcSubscriptions\n .accountNotifications(nonceAccountAddress, { commitment, encoding: 'base64' })\n .subscribe({ abortSignal: abortController.signal });\n const base58Decoder = getBase58Decoder();\n const base64Encoder = getBase64Encoder();\n function getNonceFromAccountData([base64EncodedBytes]: Base64EncodedDataResponse): Nonce {\n const data = base64Encoder.encode(base64EncodedBytes);\n const nonceValueBytes = data.slice(NONCE_VALUE_OFFSET, NONCE_VALUE_OFFSET + 32);\n return base58Decoder.decode(nonceValueBytes) as Nonce;\n }\n const nonceAccountDidAdvancePromise = (async () => {\n for await (const accountNotification of accountNotifications) {\n const nonceValue = getNonceFromAccountData(accountNotification.value.data);\n if (nonceValue !== expectedNonceValue) {\n throw new SolanaError(SOLANA_ERROR__INVALID_NONCE, {\n actualNonceValue: nonceValue,\n expectedNonceValue,\n });\n }\n }\n })();\n /**\n * STEP 2: Having subscribed for updates, make a one-shot request for the current nonce\n * value to check if it has already been advanced.\n */\n const nonceIsAlreadyInvalidPromise = (async () => {\n const { value: nonceAccount } = await rpc\n .getAccountInfo(nonceAccountAddress, {\n commitment,\n dataSlice: { length: 32, offset: NONCE_VALUE_OFFSET },\n encoding: 'base58',\n })\n .send({ abortSignal: abortController.signal });\n if (!nonceAccount) {\n throw new SolanaError(SOLANA_ERROR__NONCE_ACCOUNT_NOT_FOUND, {\n nonceAccountAddress,\n });\n }\n const nonceValue =\n // This works because we asked for the exact slice of data representing the nonce\n // value, and furthermore asked for it in `base58` encoding.\n nonceAccount.data[0] as unknown as Nonce;\n if (nonceValue !== expectedNonceValue) {\n throw new SolanaError(SOLANA_ERROR__INVALID_NONCE, {\n actualNonceValue: nonceValue,\n expectedNonceValue,\n });\n } else {\n await new Promise(() => {\n /* never resolve */\n });\n }\n })();\n try {\n return await safeRace([nonceAccountDidAdvancePromise, nonceIsAlreadyInvalidPromise]);\n } finally {\n abortController.abort();\n }\n };\n}\n","import { getSolanaErrorFromTransactionError } from '@solana/errors';\nimport { AbortController } from '@solana/event-target-impl';\nimport type { Signature } from '@solana/keys';\nimport { safeRace } from '@solana/promises';\nimport type { GetSignatureStatusesApi, Rpc } from '@solana/rpc';\nimport type { RpcSubscriptions, SignatureNotificationsApi } from '@solana/rpc-subscriptions';\nimport { type Commitment, commitmentComparator } from '@solana/rpc-types';\n\ntype GetRecentSignatureConfirmationPromiseFn = (config: {\n abortSignal: AbortSignal;\n /**\n * The level of commitment the transaction must have achieved in order for the promise to\n * resolve.\n */\n commitment: Commitment;\n /**\n * A 64 byte Ed25519 signature, encoded as a base-58 string, that uniquely identifies a\n * transaction by virtue of being the first or only signature in its list of signatures.\n */\n signature: Signature;\n}) => Promise<void>;\n\ntype CreateRecentSignatureConfirmationPromiseFactoryConfig<TCluster> = {\n rpc: Rpc<GetSignatureStatusesApi> & { '~cluster'?: TCluster };\n rpcSubscriptions: RpcSubscriptions<SignatureNotificationsApi> & { '~cluster'?: TCluster };\n};\n\n/**\n * Creates a promise that resolves when a recently-landed transaction achieves the target\n * confirmation commitment, and throws when the transaction fails with an error.\n *\n * The status of recently-landed transactions is available in the network's status cache. This\n * confirmation strategy will only yield a result if the signature is still in the status cache. To\n * fetch the status of transactions older than those available in the status cache, use the\n * {@link GetSignatureStatusesApi.getSignatureStatuses} method setting the\n * `searchTransactionHistory` configuration param to `true`.\n *\n * @param config\n *\n * @example\n * ```ts\n * import { createRecentSignatureConfirmationPromiseFactory } from '@solana/transaction-confirmation';\n *\n * const getRecentSignatureConfirmationPromise = createRecentSignatureConfirmationPromiseFactory({\n * rpc,\n * rpcSubscriptions,\n * });\n * try {\n * await getRecentSignatureConfirmationPromise({\n * commitment,\n * signature,\n * });\n * console.log(`The transaction with signature \\`${signature}\\` has achieved a commitment level of \\`${commitment}\\``);\n * } catch (e) {\n * console.error(`The transaction with signature \\`${signature}\\` failed`, e.cause);\n * throw e;\n * }\n * ```\n */\nexport function createRecentSignatureConfirmationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateRecentSignatureConfirmationPromiseFactoryConfig<'devnet'>): GetRecentSignatureConfirmationPromiseFn;\nexport function createRecentSignatureConfirmationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateRecentSignatureConfirmationPromiseFactoryConfig<'testnet'>): GetRecentSignatureConfirmationPromiseFn;\nexport function createRecentSignatureConfirmationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateRecentSignatureConfirmationPromiseFactoryConfig<'mainnet'>): GetRecentSignatureConfirmationPromiseFn;\nexport function createRecentSignatureConfirmationPromiseFactory<\n TCluster extends 'devnet' | 'mainnet' | 'testnet' | void = void,\n>({\n rpc,\n rpcSubscriptions,\n}: CreateRecentSignatureConfirmationPromiseFactoryConfig<TCluster>): GetRecentSignatureConfirmationPromiseFn {\n return async function getRecentSignatureConfirmationPromise({\n abortSignal: callerAbortSignal,\n commitment,\n signature,\n }) {\n const abortController = new AbortController();\n function handleAbort() {\n abortController.abort();\n }\n callerAbortSignal.addEventListener('abort', handleAbort, { signal: abortController.signal });\n /**\n * STEP 1: Set up a subscription for status changes to a signature.\n */\n const signatureStatusNotifications = await rpcSubscriptions\n .signatureNotifications(signature, { commitment })\n .subscribe({ abortSignal: abortController.signal });\n const signatureDidCommitPromise = (async () => {\n for await (const signatureStatusNotification of signatureStatusNotifications) {\n if (signatureStatusNotification.value.err) {\n throw getSolanaErrorFromTransactionError(signatureStatusNotification.value.err);\n } else {\n return;\n }\n }\n })();\n /**\n * STEP 2: Having subscribed for updates, make a one-shot request for the current status.\n * This will only yield a result if the signature is still in the status cache.\n */\n const signatureStatusLookupPromise = (async () => {\n const { value: signatureStatusResults } = await rpc\n .getSignatureStatuses([signature])\n .send({ abortSignal: abortController.signal });\n const signatureStatus = signatureStatusResults[0];\n if (\n signatureStatus?.confirmationStatus &&\n commitmentComparator(signatureStatus.confirmationStatus, commitment) >= 0\n ) {\n return;\n } else if (signatureStatus?.err) {\n throw getSolanaErrorFromTransactionError(signatureStatus.err);\n } else {\n await new Promise(() => {\n /* never resolve */\n });\n }\n })();\n try {\n return await safeRace([signatureDidCommitPromise, signatureStatusLookupPromise]);\n } finally {\n abortController.abort();\n }\n };\n}\n","import type { Commitment } from '@solana/rpc-types';\n\ntype Config = Readonly<{\n abortSignal: AbortSignal;\n /**\n * The timeout promise will throw after 30 seconds when the commitment is `processed`, and 60\n * seconds otherwise.\n */\n commitment: Commitment;\n}>;\n\n/**\n * When no other heuristic exists to infer that a transaction has expired, you can use this promise\n * factory with a commitment level. It throws after 30 seconds when the commitment is `processed`,\n * and 60 seconds otherwise. You would typically race this with another confirmation strategy.\n *\n * @param config\n *\n * @example\n * ```ts\n * import { safeRace } from '@solana/promises';\n * import { getTimeoutPromise } from '@solana/transaction-confirmation';\n *\n * try {\n * await safeRace([getCustomTransactionConfirmationPromise(/* ... *\\/), getTimeoutPromise({ commitment })]);\n * } catch (e) {\n * if (e instanceof DOMException && e.name === 'TimeoutError') {\n * console.log('Could not confirm transaction after a timeout');\n * }\n * throw e;\n * }\n * ```\n */\nexport async function getTimeoutPromise({ abortSignal: callerAbortSignal, commitment }: Config) {\n return await new Promise((_, reject) => {\n const handleAbort = (e: AbortSignalEventMap['abort']) => {\n clearTimeout(timeoutId);\n const abortError = new DOMException((e.target as AbortSignal).reason, 'AbortError');\n reject(abortError);\n };\n callerAbortSignal.addEventListener('abort', handleAbort);\n const timeoutMs = commitment === 'processed' ? 30_000 : 60_000;\n const startMs = performance.now();\n const timeoutId =\n // We use `setTimeout` instead of `AbortSignal.timeout()` because we want to measure\n // elapsed time instead of active time.\n // See https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal/timeout_static\n setTimeout(() => {\n const elapsedMs = performance.now() - startMs;\n reject(new DOMException(`Timeout elapsed after ${elapsedMs} ms`, 'TimeoutError'));\n }, timeoutMs);\n });\n}\n","import { AbortController } from '@solana/event-target-impl';\nimport type { Signature } from '@solana/keys';\nimport { safeRace } from '@solana/promises';\nimport type { Commitment } from '@solana/rpc-types';\n\nimport { createRecentSignatureConfirmationPromiseFactory } from './confirmation-strategy-recent-signature';\n\nexport interface BaseTransactionConfirmationStrategyConfig {\n abortSignal?: AbortSignal;\n commitment: Commitment;\n getRecentSignatureConfirmationPromise: ReturnType<typeof createRecentSignatureConfirmationPromiseFactory>;\n}\n\ntype WithNonNullableAbortSignal<T> = Omit<T, 'abortSignal'> & Readonly<{ abortSignal: AbortSignal }>;\n\nexport async function raceStrategies<TConfig extends BaseTransactionConfirmationStrategyConfig>(\n signature: Signature,\n config: TConfig,\n getSpecificStrategiesForRace: (config: WithNonNullableAbortSignal<TConfig>) => readonly Promise<unknown>[],\n) {\n const { abortSignal: callerAbortSignal, commitment, getRecentSignatureConfirmationPromise } = config;\n callerAbortSignal?.throwIfAborted();\n const abortController = new AbortController();\n if (callerAbortSignal) {\n const handleAbort = () => {\n abortController.abort();\n };\n callerAbortSignal.addEventListener('abort', handleAbort, { signal: abortController.signal });\n }\n try {\n const specificStrategies = getSpecificStrategiesForRace({\n ...config,\n abortSignal: abortController.signal,\n });\n return await safeRace([\n getRecentSignatureConfirmationPromise({\n abortSignal: abortController.signal,\n commitment,\n signature,\n }),\n ...specificStrategies,\n ]);\n } finally {\n abortController.abort();\n }\n}\n","import { Signature } from '@solana/keys';\nimport {\n getSignatureFromTransaction,\n Transaction,\n TransactionWithBlockhashLifetime,\n TransactionWithDurableNonceLifetime,\n} from '@solana/transactions';\n\nimport { createBlockHeightExceedencePromiseFactory } from './confirmation-strategy-blockheight';\nimport { createNonceInvalidationPromiseFactory } from './confirmation-strategy-nonce';\nimport { BaseTransactionConfirmationStrategyConfig, raceStrategies } from './confirmation-strategy-racer';\nimport { getTimeoutPromise } from './confirmation-strategy-timeout';\n\nexport type TransactionWithLastValidBlockHeight = Omit<TransactionWithBlockhashLifetime, 'lifetimeConstraint'> & {\n lifetimeConstraint: Omit<TransactionWithBlockhashLifetime['lifetimeConstraint'], 'blockhash'>;\n};\n\ninterface WaitForDurableNonceTransactionConfirmationConfig extends BaseTransactionConfirmationStrategyConfig {\n getNonceInvalidationPromise: ReturnType<typeof createNonceInvalidationPromiseFactory>;\n transaction: Readonly<Transaction & TransactionWithDurableNonceLifetime>;\n}\n\ninterface WaitForRecentTransactionWithBlockhashLifetimeConfirmationConfig\n extends BaseTransactionConfirmationStrategyConfig {\n getBlockHeightExceedencePromise: ReturnType<typeof createBlockHeightExceedencePromiseFactory>;\n transaction: Readonly<Transaction & TransactionWithLastValidBlockHeight>;\n}\n\ninterface WaitForRecentTransactionWithTimeBasedLifetimeConfirmationConfig\n extends BaseTransactionConfirmationStrategyConfig {\n getTimeoutPromise: typeof getTimeoutPromise;\n /**\n * A 64 byte Ed25519 signature, encoded as a base-58 string, that uniquely identifies a\n * transaction by virtue of being the first or only signature in its list of signatures.\n */\n signature: Signature;\n}\n\n/**\n * Supply your own confirmation implementations to this function to create a custom nonce\n * transaction confirmation strategy.\n *\n * @example\n * ```ts\n * import { waitForDurableNonceTransactionConfirmation } from '@solana/transaction-confirmation';\n *\n * try {\n * await waitForDurableNonceTransactionConfirmation({\n * getNonceInvalidationPromise({ abortSignal, commitment, currentNonceValue, nonceAccountAddress }) {\n * // Return a promise that rejects when a nonce becomes invalid.\n * },\n * getRecentSignatureConfirmationPromise({ abortSignal, commitment, signature }) {\n * // Return a promise that resolves when a transaction achieves confirmation\n * },\n * });\n * } catch (e) {\n * // Handle errors.\n * }\n * ```\n */\nexport async function waitForDurableNonceTransactionConfirmation(\n config: WaitForDurableNonceTransactionConfirmationConfig,\n): Promise<void> {\n await raceStrategies(\n getSignatureFromTransaction(config.transaction),\n config,\n function getSpecificStrategiesForRace({ abortSignal, commitment, getNonceInvalidationPromise, transaction }) {\n return [\n getNonceInvalidationPromise({\n abortSignal,\n commitment,\n currentNonceValue: transaction.lifetimeConstraint.nonce,\n nonceAccountAddress: transaction.lifetimeConstraint.nonceAccountAddress,\n }),\n ];\n },\n );\n}\n\n/**\n * Supply your own confirmation implementations to this function to create a custom confirmation\n * strategy for recently-landed transactions.\n *\n * @example\n * ```ts\n * import { waitForRecentTransactionConfirmation } from '@solana/transaction-confirmation';\n *\n * try {\n * await waitForRecentTransactionConfirmation({\n * getBlockHeightExceedencePromise({ abortSignal, commitment, lastValidBlockHeight }) {\n * // Return a promise that rejects when the blockhash's block height has been exceeded\n * },\n * getRecentSignatureConfirmationPromise({ abortSignal, commitment, signature }) {\n * // Return a promise that resolves when a transaction achieves confirmation\n * },\n * });\n * } catch (e) {\n * // Handle errors.\n * }\n * ```\n */\nexport async function waitForRecentTransactionConfirmation(\n config: WaitForRecentTransactionWithBlockhashLifetimeConfirmationConfig,\n): Promise<void> {\n await raceStrategies(\n getSignatureFromTransaction(config.transaction),\n config,\n function getSpecificStrategiesForRace({\n abortSignal,\n commitment,\n getBlockHeightExceedencePromise,\n transaction,\n }) {\n return [\n getBlockHeightExceedencePromise({\n abortSignal,\n commitment,\n lastValidBlockHeight: transaction.lifetimeConstraint.lastValidBlockHeight,\n }),\n ];\n },\n );\n}\n\n/** @deprecated */\nexport async function waitForRecentTransactionConfirmationUntilTimeout(\n config: WaitForRecentTransactionWithTimeBasedLifetimeConfirmationConfig,\n): Promise<void> {\n await raceStrategies(\n config.signature,\n config,\n function getSpecificStrategiesForRace({ abortSignal, commitment, getTimeoutPromise }) {\n return [\n getTimeoutPromise({\n abortSignal,\n commitment,\n }),\n ];\n },\n );\n}\n"]}
|
package/dist/index.node.mjs
CHANGED
|
@@ -167,8 +167,10 @@ function createRecentSignatureConfirmationPromiseFactory({
|
|
|
167
167
|
const signatureStatusLookupPromise = (async () => {
|
|
168
168
|
const { value: signatureStatusResults } = await rpc.getSignatureStatuses([signature]).send({ abortSignal: abortController.signal });
|
|
169
169
|
const signatureStatus = signatureStatusResults[0];
|
|
170
|
-
if (signatureStatus
|
|
170
|
+
if (signatureStatus?.confirmationStatus && commitmentComparator(signatureStatus.confirmationStatus, commitment) >= 0) {
|
|
171
171
|
return;
|
|
172
|
+
} else if (signatureStatus?.err) {
|
|
173
|
+
throw getSolanaErrorFromTransactionError(signatureStatus.err);
|
|
172
174
|
} else {
|
|
173
175
|
await new Promise(() => {
|
|
174
176
|
});
|
package/dist/index.node.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../event-target-impl/src/index.node.ts","../src/confirmation-strategy-blockheight.ts","../src/confirmation-strategy-nonce.ts","../src/confirmation-strategy-recent-signature.ts","../src/confirmation-strategy-timeout.ts","../src/confirmation-strategy-racer.ts","../src/waiters.ts"],"names":["AbortController","args","setMaxListeners","SolanaError","safeRace","e","getTimeoutPromise"],"mappings":"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","file":"index.node.mjs","sourcesContent":["import { setMaxListeners } from 'node:events';\n\nexport const AbortController = class extends globalThis.AbortController {\n constructor(...args: ConstructorParameters<typeof globalThis.AbortController>) {\n super(...args);\n setMaxListeners(Number.MAX_SAFE_INTEGER, this.signal);\n }\n};\n\nexport const EventTarget = class extends globalThis.EventTarget {\n constructor(...args: ConstructorParameters<typeof globalThis.EventTarget>) {\n super(...args);\n setMaxListeners(Number.MAX_SAFE_INTEGER, this);\n }\n};\n","import { SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED, SolanaError } from '@solana/errors';\nimport { AbortController } from '@solana/event-target-impl';\nimport type { GetEpochInfoApi, Rpc } from '@solana/rpc';\nimport type { RpcSubscriptions, SlotNotificationsApi } from '@solana/rpc-subscriptions';\nimport type { Commitment } from '@solana/rpc-types';\n\ntype GetBlockHeightExceedencePromiseFn = (config: {\n abortSignal: AbortSignal;\n /**\n * Fetch the block height as of the highest slot that has reached this level of commitment.\n *\n * @defaultValue Whichever default is applied by the underlying {@link RpcApi} in use. For\n * example, when using an API created by a `createSolanaRpc*()` helper, the default commitment\n * is `\"confirmed\"` unless configured otherwise. Unmitigated by an API layer on the client, the\n * default commitment applied by the server is `\"finalized\"`.\n */\n commitment?: Commitment;\n /** The block height after which to reject the promise */\n lastValidBlockHeight: bigint;\n}) => Promise<void>;\n\ntype CreateBlockHeightExceedencePromiseFactoryConfig<TCluster> = {\n rpc: Rpc<GetEpochInfoApi> & { '~cluster'?: TCluster };\n rpcSubscriptions: RpcSubscriptions<SlotNotificationsApi> & { '~cluster'?: TCluster };\n};\n\n/**\n * Creates a promise that throws when the network progresses past the block height after which the\n * supplied blockhash is considered expired for use as a transaction lifetime specifier.\n *\n * When a transaction's lifetime is tied to a blockhash, that transaction can be landed on the\n * network until that blockhash expires. All blockhashes have a block height after which they are\n * considered to have expired.\n *\n * @param config\n *\n * @example\n * ```ts\n * import { isSolanaError, SolanaError } from '@solana/errors';\n * import { createBlockHeightExceedencePromiseFactory } from '@solana/transaction-confirmation';\n *\n * const getBlockHeightExceedencePromise = createBlockHeightExceedencePromiseFactory({\n * rpc,\n * rpcSubscriptions,\n * });\n * try {\n * await getBlockHeightExceedencePromise({ lastValidBlockHeight });\n * } catch (e) {\n * if (isSolanaError(e, SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED)) {\n * console.error(\n * `The block height of the network has exceeded ${e.context.lastValidBlockHeight}. ` +\n * `It is now ${e.context.currentBlockHeight}`,\n * );\n * // Re-sign and retry the transaction.\n * return;\n * }\n * throw e;\n * }\n * ```\n */\nexport function createBlockHeightExceedencePromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateBlockHeightExceedencePromiseFactoryConfig<'devnet'>): GetBlockHeightExceedencePromiseFn;\nexport function createBlockHeightExceedencePromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateBlockHeightExceedencePromiseFactoryConfig<'testnet'>): GetBlockHeightExceedencePromiseFn;\nexport function createBlockHeightExceedencePromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateBlockHeightExceedencePromiseFactoryConfig<'mainnet'>): GetBlockHeightExceedencePromiseFn;\nexport function createBlockHeightExceedencePromiseFactory<\n TCluster extends 'devnet' | 'mainnet' | 'testnet' | void = void,\n>({\n rpc,\n rpcSubscriptions,\n}: CreateBlockHeightExceedencePromiseFactoryConfig<TCluster>): GetBlockHeightExceedencePromiseFn {\n return async function getBlockHeightExceedencePromise({\n abortSignal: callerAbortSignal,\n commitment,\n lastValidBlockHeight,\n }): Promise<never> {\n callerAbortSignal.throwIfAborted();\n const abortController = new AbortController();\n const handleAbort = () => {\n abortController.abort();\n };\n callerAbortSignal.addEventListener('abort', handleAbort, { signal: abortController.signal });\n async function getBlockHeightAndDifferenceBetweenSlotHeightAndBlockHeight() {\n const { absoluteSlot, blockHeight } = await rpc\n .getEpochInfo({ commitment })\n .send({ abortSignal: abortController.signal });\n return {\n blockHeight,\n differenceBetweenSlotHeightAndBlockHeight: absoluteSlot - blockHeight,\n };\n }\n try {\n const [slotNotifications, { blockHeight: initialBlockHeight, differenceBetweenSlotHeightAndBlockHeight }] =\n await Promise.all([\n rpcSubscriptions.slotNotifications().subscribe({ abortSignal: abortController.signal }),\n getBlockHeightAndDifferenceBetweenSlotHeightAndBlockHeight(),\n ]);\n callerAbortSignal.throwIfAborted();\n let currentBlockHeight = initialBlockHeight;\n if (currentBlockHeight <= lastValidBlockHeight) {\n let lastKnownDifferenceBetweenSlotHeightAndBlockHeight = differenceBetweenSlotHeightAndBlockHeight;\n for await (const slotNotification of slotNotifications) {\n const { slot } = slotNotification;\n if (slot - lastKnownDifferenceBetweenSlotHeightAndBlockHeight > lastValidBlockHeight) {\n // Before making a final decision, recheck the actual block height.\n const {\n blockHeight: recheckedBlockHeight,\n differenceBetweenSlotHeightAndBlockHeight: currentDifferenceBetweenSlotHeightAndBlockHeight,\n } = await getBlockHeightAndDifferenceBetweenSlotHeightAndBlockHeight();\n currentBlockHeight = recheckedBlockHeight;\n if (currentBlockHeight > lastValidBlockHeight) {\n // Verified; the block height has been exceeded.\n break;\n } else {\n // The block height has not been exceeded, which implies that the\n // difference between the slot height and the block height has grown\n // (ie. some blocks have been skipped since we started). Recalibrate the\n // difference and keep waiting.\n lastKnownDifferenceBetweenSlotHeightAndBlockHeight =\n currentDifferenceBetweenSlotHeightAndBlockHeight;\n }\n }\n }\n }\n callerAbortSignal.throwIfAborted();\n throw new SolanaError(SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED, {\n currentBlockHeight,\n lastValidBlockHeight,\n });\n } finally {\n abortController.abort();\n }\n };\n}\n","import type { Address } from '@solana/addresses';\nimport { getBase58Decoder, getBase64Encoder } from '@solana/codecs-strings';\nimport { SOLANA_ERROR__INVALID_NONCE, SOLANA_ERROR__NONCE_ACCOUNT_NOT_FOUND, SolanaError } from '@solana/errors';\nimport { AbortController } from '@solana/event-target-impl';\nimport { safeRace } from '@solana/promises';\nimport type { GetAccountInfoApi, Rpc } from '@solana/rpc';\nimport type { AccountNotificationsApi, RpcSubscriptions } from '@solana/rpc-subscriptions';\nimport type { Base64EncodedDataResponse, Commitment } from '@solana/rpc-types';\nimport { Nonce } from '@solana/transaction-messages';\n\ntype GetNonceInvalidationPromiseFn = (config: {\n abortSignal: AbortSignal;\n /**\n * Fetch the nonce account details as of the highest slot that has reached this level of\n * commitment.\n */\n commitment: Commitment;\n /**\n * The value of the nonce that we would expect to see in the nonce account in order for any\n * transaction with that nonce-based lifetime to be considered valid.\n */\n currentNonceValue: Nonce;\n /** The address of the account in which the currently-valid nonce value is stored */\n nonceAccountAddress: Address;\n}) => Promise<void>;\n\ntype CreateNonceInvalidationPromiseFactoryConfig<TCluster> = {\n rpc: Rpc<GetAccountInfoApi> & { '~cluster'?: TCluster };\n rpcSubscriptions: RpcSubscriptions<AccountNotificationsApi> & { '~cluster'?: TCluster };\n};\n\nconst NONCE_VALUE_OFFSET =\n 4 + // version(u32)\n 4 + // state(u32)\n 32; // nonce authority(pubkey)\n// Then comes the nonce value.\n\n/**\n * Creates a promise that throws when the value stored in a nonce account is not the expected one.\n *\n * When a transaction's lifetime is tied to the value stored in a nonce account, that transaction\n * can be landed on the network until the nonce is advanced to a new value.\n *\n * @param config\n *\n * @example\n * ```ts\n * import { isSolanaError, SolanaError } from '@solana/errors';\n * import { createNonceInvalidationPromiseFactory } from '@solana/transaction-confirmation';\n *\n * const getNonceInvalidationPromise = createNonceInvalidationPromiseFactory({\n * rpc,\n * rpcSubscriptions,\n * });\n * try {\n * await getNonceInvalidationPromise({\n * currentNonceValue,\n * nonceAccountAddress,\n * });\n * } catch (e) {\n * if (isSolanaError(e, SOLANA_ERROR__NONCE_INVALID)) {\n * console.error(`The nonce has advanced to ${e.context.actualNonceValue}`);\n * // Re-sign and retry the transaction.\n * return;\n * } else if (isSolanaError(e, SOLANA_ERROR__NONCE_ACCOUNT_NOT_FOUND)) {\n * console.error(`No nonce account was found at ${nonceAccountAddress}`);\n * }\n * throw e;\n * }\n * ```\n */\nexport function createNonceInvalidationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateNonceInvalidationPromiseFactoryConfig<'devnet'>): GetNonceInvalidationPromiseFn;\nexport function createNonceInvalidationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateNonceInvalidationPromiseFactoryConfig<'testnet'>): GetNonceInvalidationPromiseFn;\nexport function createNonceInvalidationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateNonceInvalidationPromiseFactoryConfig<'mainnet'>): GetNonceInvalidationPromiseFn;\nexport function createNonceInvalidationPromiseFactory<TCluster extends 'devnet' | 'mainnet' | 'testnet' | void = void>({\n rpc,\n rpcSubscriptions,\n}: CreateNonceInvalidationPromiseFactoryConfig<TCluster>): GetNonceInvalidationPromiseFn {\n return async function getNonceInvalidationPromise({\n abortSignal: callerAbortSignal,\n commitment,\n currentNonceValue: expectedNonceValue,\n nonceAccountAddress,\n }) {\n const abortController = new AbortController();\n function handleAbort() {\n abortController.abort();\n }\n callerAbortSignal.addEventListener('abort', handleAbort, { signal: abortController.signal });\n /**\n * STEP 1: Set up a subscription for nonce account changes.\n */\n const accountNotifications = await rpcSubscriptions\n .accountNotifications(nonceAccountAddress, { commitment, encoding: 'base64' })\n .subscribe({ abortSignal: abortController.signal });\n const base58Decoder = getBase58Decoder();\n const base64Encoder = getBase64Encoder();\n function getNonceFromAccountData([base64EncodedBytes]: Base64EncodedDataResponse): Nonce {\n const data = base64Encoder.encode(base64EncodedBytes);\n const nonceValueBytes = data.slice(NONCE_VALUE_OFFSET, NONCE_VALUE_OFFSET + 32);\n return base58Decoder.decode(nonceValueBytes) as Nonce;\n }\n const nonceAccountDidAdvancePromise = (async () => {\n for await (const accountNotification of accountNotifications) {\n const nonceValue = getNonceFromAccountData(accountNotification.value.data);\n if (nonceValue !== expectedNonceValue) {\n throw new SolanaError(SOLANA_ERROR__INVALID_NONCE, {\n actualNonceValue: nonceValue,\n expectedNonceValue,\n });\n }\n }\n })();\n /**\n * STEP 2: Having subscribed for updates, make a one-shot request for the current nonce\n * value to check if it has already been advanced.\n */\n const nonceIsAlreadyInvalidPromise = (async () => {\n const { value: nonceAccount } = await rpc\n .getAccountInfo(nonceAccountAddress, {\n commitment,\n dataSlice: { length: 32, offset: NONCE_VALUE_OFFSET },\n encoding: 'base58',\n })\n .send({ abortSignal: abortController.signal });\n if (!nonceAccount) {\n throw new SolanaError(SOLANA_ERROR__NONCE_ACCOUNT_NOT_FOUND, {\n nonceAccountAddress,\n });\n }\n const nonceValue =\n // This works because we asked for the exact slice of data representing the nonce\n // value, and furthermore asked for it in `base58` encoding.\n nonceAccount.data[0] as unknown as Nonce;\n if (nonceValue !== expectedNonceValue) {\n throw new SolanaError(SOLANA_ERROR__INVALID_NONCE, {\n actualNonceValue: nonceValue,\n expectedNonceValue,\n });\n } else {\n await new Promise(() => {\n /* never resolve */\n });\n }\n })();\n try {\n return await safeRace([nonceAccountDidAdvancePromise, nonceIsAlreadyInvalidPromise]);\n } finally {\n abortController.abort();\n }\n };\n}\n","import { getSolanaErrorFromTransactionError } from '@solana/errors';\nimport { AbortController } from '@solana/event-target-impl';\nimport type { Signature } from '@solana/keys';\nimport { safeRace } from '@solana/promises';\nimport type { GetSignatureStatusesApi, Rpc } from '@solana/rpc';\nimport type { RpcSubscriptions, SignatureNotificationsApi } from '@solana/rpc-subscriptions';\nimport { type Commitment, commitmentComparator } from '@solana/rpc-types';\n\ntype GetRecentSignatureConfirmationPromiseFn = (config: {\n abortSignal: AbortSignal;\n /**\n * The level of commitment the transaction must have achieved in order for the promise to\n * resolve.\n */\n commitment: Commitment;\n /**\n * A 64 byte Ed25519 signature, encoded as a base-58 string, that uniquely identifies a\n * transaction by virtue of being the first or only signature in its list of signatures.\n */\n signature: Signature;\n}) => Promise<void>;\n\ntype CreateRecentSignatureConfirmationPromiseFactoryConfig<TCluster> = {\n rpc: Rpc<GetSignatureStatusesApi> & { '~cluster'?: TCluster };\n rpcSubscriptions: RpcSubscriptions<SignatureNotificationsApi> & { '~cluster'?: TCluster };\n};\n\n/**\n * Creates a promise that resolves when a recently-landed transaction achieves the target\n * confirmation commitment, and throws when the transaction fails with an error.\n *\n * The status of recently-landed transactions is available in the network's status cache. This\n * confirmation strategy will only yield a result if the signature is still in the status cache. To\n * fetch the status of transactions older than those available in the status cache, use the\n * {@link GetSignatureStatusesApi.getSignatureStatuses} method setting the\n * `searchTransactionHistory` configuration param to `true`.\n *\n * @param config\n *\n * @example\n * ```ts\n * import { createRecentSignatureConfirmationPromiseFactory } from '@solana/transaction-confirmation';\n *\n * const getRecentSignatureConfirmationPromise = createRecentSignatureConfirmationPromiseFactory({\n * rpc,\n * rpcSubscriptions,\n * });\n * try {\n * await getRecentSignatureConfirmationPromise({\n * commitment,\n * signature,\n * });\n * console.log(`The transaction with signature \\`${signature}\\` has achieved a commitment level of \\`${commitment}\\``);\n * } catch (e) {\n * console.error(`The transaction with signature \\`${signature}\\` failed`, e.cause);\n * throw e;\n * }\n * ```\n */\nexport function createRecentSignatureConfirmationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateRecentSignatureConfirmationPromiseFactoryConfig<'devnet'>): GetRecentSignatureConfirmationPromiseFn;\nexport function createRecentSignatureConfirmationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateRecentSignatureConfirmationPromiseFactoryConfig<'testnet'>): GetRecentSignatureConfirmationPromiseFn;\nexport function createRecentSignatureConfirmationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateRecentSignatureConfirmationPromiseFactoryConfig<'mainnet'>): GetRecentSignatureConfirmationPromiseFn;\nexport function createRecentSignatureConfirmationPromiseFactory<\n TCluster extends 'devnet' | 'mainnet' | 'testnet' | void = void,\n>({\n rpc,\n rpcSubscriptions,\n}: CreateRecentSignatureConfirmationPromiseFactoryConfig<TCluster>): GetRecentSignatureConfirmationPromiseFn {\n return async function getRecentSignatureConfirmationPromise({\n abortSignal: callerAbortSignal,\n commitment,\n signature,\n }) {\n const abortController = new AbortController();\n function handleAbort() {\n abortController.abort();\n }\n callerAbortSignal.addEventListener('abort', handleAbort, { signal: abortController.signal });\n /**\n * STEP 1: Set up a subscription for status changes to a signature.\n */\n const signatureStatusNotifications = await rpcSubscriptions\n .signatureNotifications(signature, { commitment })\n .subscribe({ abortSignal: abortController.signal });\n const signatureDidCommitPromise = (async () => {\n for await (const signatureStatusNotification of signatureStatusNotifications) {\n if (signatureStatusNotification.value.err) {\n throw getSolanaErrorFromTransactionError(signatureStatusNotification.value.err);\n } else {\n return;\n }\n }\n })();\n /**\n * STEP 2: Having subscribed for updates, make a one-shot request for the current status.\n * This will only yield a result if the signature is still in the status cache.\n */\n const signatureStatusLookupPromise = (async () => {\n const { value: signatureStatusResults } = await rpc\n .getSignatureStatuses([signature])\n .send({ abortSignal: abortController.signal });\n const signatureStatus = signatureStatusResults[0];\n if (\n signatureStatus &&\n signatureStatus.confirmationStatus &&\n commitmentComparator(signatureStatus.confirmationStatus, commitment) >= 0\n ) {\n return;\n } else {\n await new Promise(() => {\n /* never resolve */\n });\n }\n })();\n try {\n return await safeRace([signatureDidCommitPromise, signatureStatusLookupPromise]);\n } finally {\n abortController.abort();\n }\n };\n}\n","import type { Commitment } from '@solana/rpc-types';\n\ntype Config = Readonly<{\n abortSignal: AbortSignal;\n /**\n * The timeout promise will throw after 30 seconds when the commitment is `processed`, and 60\n * seconds otherwise.\n */\n commitment: Commitment;\n}>;\n\n/**\n * When no other heuristic exists to infer that a transaction has expired, you can use this promise\n * factory with a commitment level. It throws after 30 seconds when the commitment is `processed`,\n * and 60 seconds otherwise. You would typically race this with another confirmation strategy.\n *\n * @param config\n *\n * @example\n * ```ts\n * import { safeRace } from '@solana/promises';\n * import { getTimeoutPromise } from '@solana/transaction-confirmation';\n *\n * try {\n * await safeRace([getCustomTransactionConfirmationPromise(/* ... *\\/), getTimeoutPromise({ commitment })]);\n * } catch (e) {\n * if (e instanceof DOMException && e.name === 'TimeoutError') {\n * console.log('Could not confirm transaction after a timeout');\n * }\n * throw e;\n * }\n * ```\n */\nexport async function getTimeoutPromise({ abortSignal: callerAbortSignal, commitment }: Config) {\n return await new Promise((_, reject) => {\n const handleAbort = (e: AbortSignalEventMap['abort']) => {\n clearTimeout(timeoutId);\n const abortError = new DOMException((e.target as AbortSignal).reason, 'AbortError');\n reject(abortError);\n };\n callerAbortSignal.addEventListener('abort', handleAbort);\n const timeoutMs = commitment === 'processed' ? 30_000 : 60_000;\n const startMs = performance.now();\n const timeoutId =\n // We use `setTimeout` instead of `AbortSignal.timeout()` because we want to measure\n // elapsed time instead of active time.\n // See https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal/timeout_static\n setTimeout(() => {\n const elapsedMs = performance.now() - startMs;\n reject(new DOMException(`Timeout elapsed after ${elapsedMs} ms`, 'TimeoutError'));\n }, timeoutMs);\n });\n}\n","import { AbortController } from '@solana/event-target-impl';\nimport type { Signature } from '@solana/keys';\nimport { safeRace } from '@solana/promises';\nimport type { Commitment } from '@solana/rpc-types';\n\nimport { createRecentSignatureConfirmationPromiseFactory } from './confirmation-strategy-recent-signature';\n\nexport interface BaseTransactionConfirmationStrategyConfig {\n abortSignal?: AbortSignal;\n commitment: Commitment;\n getRecentSignatureConfirmationPromise: ReturnType<typeof createRecentSignatureConfirmationPromiseFactory>;\n}\n\ntype WithNonNullableAbortSignal<T> = Omit<T, 'abortSignal'> & Readonly<{ abortSignal: AbortSignal }>;\n\nexport async function raceStrategies<TConfig extends BaseTransactionConfirmationStrategyConfig>(\n signature: Signature,\n config: TConfig,\n getSpecificStrategiesForRace: (config: WithNonNullableAbortSignal<TConfig>) => readonly Promise<unknown>[],\n) {\n const { abortSignal: callerAbortSignal, commitment, getRecentSignatureConfirmationPromise } = config;\n callerAbortSignal?.throwIfAborted();\n const abortController = new AbortController();\n if (callerAbortSignal) {\n const handleAbort = () => {\n abortController.abort();\n };\n callerAbortSignal.addEventListener('abort', handleAbort, { signal: abortController.signal });\n }\n try {\n const specificStrategies = getSpecificStrategiesForRace({\n ...config,\n abortSignal: abortController.signal,\n });\n return await safeRace([\n getRecentSignatureConfirmationPromise({\n abortSignal: abortController.signal,\n commitment,\n signature,\n }),\n ...specificStrategies,\n ]);\n } finally {\n abortController.abort();\n }\n}\n","import { Signature } from '@solana/keys';\nimport {\n getSignatureFromTransaction,\n Transaction,\n TransactionWithBlockhashLifetime,\n TransactionWithDurableNonceLifetime,\n} from '@solana/transactions';\n\nimport { createBlockHeightExceedencePromiseFactory } from './confirmation-strategy-blockheight';\nimport { createNonceInvalidationPromiseFactory } from './confirmation-strategy-nonce';\nimport { BaseTransactionConfirmationStrategyConfig, raceStrategies } from './confirmation-strategy-racer';\nimport { getTimeoutPromise } from './confirmation-strategy-timeout';\n\nexport type TransactionWithLastValidBlockHeight = Omit<TransactionWithBlockhashLifetime, 'lifetimeConstraint'> & {\n lifetimeConstraint: Omit<TransactionWithBlockhashLifetime['lifetimeConstraint'], 'blockhash'>;\n};\n\ninterface WaitForDurableNonceTransactionConfirmationConfig extends BaseTransactionConfirmationStrategyConfig {\n getNonceInvalidationPromise: ReturnType<typeof createNonceInvalidationPromiseFactory>;\n transaction: Readonly<Transaction & TransactionWithDurableNonceLifetime>;\n}\n\ninterface WaitForRecentTransactionWithBlockhashLifetimeConfirmationConfig\n extends BaseTransactionConfirmationStrategyConfig {\n getBlockHeightExceedencePromise: ReturnType<typeof createBlockHeightExceedencePromiseFactory>;\n transaction: Readonly<Transaction & TransactionWithLastValidBlockHeight>;\n}\n\ninterface WaitForRecentTransactionWithTimeBasedLifetimeConfirmationConfig\n extends BaseTransactionConfirmationStrategyConfig {\n getTimeoutPromise: typeof getTimeoutPromise;\n /**\n * A 64 byte Ed25519 signature, encoded as a base-58 string, that uniquely identifies a\n * transaction by virtue of being the first or only signature in its list of signatures.\n */\n signature: Signature;\n}\n\n/**\n * Supply your own confirmation implementations to this function to create a custom nonce\n * transaction confirmation strategy.\n *\n * @example\n * ```ts\n * import { waitForDurableNonceTransactionConfirmation } from '@solana/transaction-confirmation';\n *\n * try {\n * await waitForDurableNonceTransactionConfirmation({\n * getNonceInvalidationPromise({ abortSignal, commitment, currentNonceValue, nonceAccountAddress }) {\n * // Return a promise that rejects when a nonce becomes invalid.\n * },\n * getRecentSignatureConfirmationPromise({ abortSignal, commitment, signature }) {\n * // Return a promise that resolves when a transaction achieves confirmation\n * },\n * });\n * } catch (e) {\n * // Handle errors.\n * }\n * ```\n */\nexport async function waitForDurableNonceTransactionConfirmation(\n config: WaitForDurableNonceTransactionConfirmationConfig,\n): Promise<void> {\n await raceStrategies(\n getSignatureFromTransaction(config.transaction),\n config,\n function getSpecificStrategiesForRace({ abortSignal, commitment, getNonceInvalidationPromise, transaction }) {\n return [\n getNonceInvalidationPromise({\n abortSignal,\n commitment,\n currentNonceValue: transaction.lifetimeConstraint.nonce,\n nonceAccountAddress: transaction.lifetimeConstraint.nonceAccountAddress,\n }),\n ];\n },\n );\n}\n\n/**\n * Supply your own confirmation implementations to this function to create a custom confirmation\n * strategy for recently-landed transactions.\n *\n * @example\n * ```ts\n * import { waitForRecentTransactionConfirmation } from '@solana/transaction-confirmation';\n *\n * try {\n * await waitForRecentTransactionConfirmation({\n * getBlockHeightExceedencePromise({ abortSignal, commitment, lastValidBlockHeight }) {\n * // Return a promise that rejects when the blockhash's block height has been exceeded\n * },\n * getRecentSignatureConfirmationPromise({ abortSignal, commitment, signature }) {\n * // Return a promise that resolves when a transaction achieves confirmation\n * },\n * });\n * } catch (e) {\n * // Handle errors.\n * }\n * ```\n */\nexport async function waitForRecentTransactionConfirmation(\n config: WaitForRecentTransactionWithBlockhashLifetimeConfirmationConfig,\n): Promise<void> {\n await raceStrategies(\n getSignatureFromTransaction(config.transaction),\n config,\n function getSpecificStrategiesForRace({\n abortSignal,\n commitment,\n getBlockHeightExceedencePromise,\n transaction,\n }) {\n return [\n getBlockHeightExceedencePromise({\n abortSignal,\n commitment,\n lastValidBlockHeight: transaction.lifetimeConstraint.lastValidBlockHeight,\n }),\n ];\n },\n );\n}\n\n/** @deprecated */\nexport async function waitForRecentTransactionConfirmationUntilTimeout(\n config: WaitForRecentTransactionWithTimeBasedLifetimeConfirmationConfig,\n): Promise<void> {\n await raceStrategies(\n config.signature,\n config,\n function getSpecificStrategiesForRace({ abortSignal, commitment, getTimeoutPromise }) {\n return [\n getTimeoutPromise({\n abortSignal,\n commitment,\n }),\n ];\n },\n );\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../event-target-impl/src/index.node.ts","../src/confirmation-strategy-blockheight.ts","../src/confirmation-strategy-nonce.ts","../src/confirmation-strategy-recent-signature.ts","../src/confirmation-strategy-timeout.ts","../src/confirmation-strategy-racer.ts","../src/waiters.ts"],"names":["AbortController","args","setMaxListeners","SolanaError","safeRace","e","getTimeoutPromise"],"mappings":"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","file":"index.node.mjs","sourcesContent":["import { setMaxListeners } from 'node:events';\n\nexport const AbortController = class extends globalThis.AbortController {\n constructor(...args: ConstructorParameters<typeof globalThis.AbortController>) {\n super(...args);\n setMaxListeners(Number.MAX_SAFE_INTEGER, this.signal);\n }\n};\n\nexport const EventTarget = class extends globalThis.EventTarget {\n constructor(...args: ConstructorParameters<typeof globalThis.EventTarget>) {\n super(...args);\n setMaxListeners(Number.MAX_SAFE_INTEGER, this);\n }\n};\n","import { SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED, SolanaError } from '@solana/errors';\nimport { AbortController } from '@solana/event-target-impl';\nimport type { GetEpochInfoApi, Rpc } from '@solana/rpc';\nimport type { RpcSubscriptions, SlotNotificationsApi } from '@solana/rpc-subscriptions';\nimport type { Commitment } from '@solana/rpc-types';\n\ntype GetBlockHeightExceedencePromiseFn = (config: {\n abortSignal: AbortSignal;\n /**\n * Fetch the block height as of the highest slot that has reached this level of commitment.\n *\n * @defaultValue Whichever default is applied by the underlying {@link RpcApi} in use. For\n * example, when using an API created by a `createSolanaRpc*()` helper, the default commitment\n * is `\"confirmed\"` unless configured otherwise. Unmitigated by an API layer on the client, the\n * default commitment applied by the server is `\"finalized\"`.\n */\n commitment?: Commitment;\n /** The block height after which to reject the promise */\n lastValidBlockHeight: bigint;\n}) => Promise<void>;\n\ntype CreateBlockHeightExceedencePromiseFactoryConfig<TCluster> = {\n rpc: Rpc<GetEpochInfoApi> & { '~cluster'?: TCluster };\n rpcSubscriptions: RpcSubscriptions<SlotNotificationsApi> & { '~cluster'?: TCluster };\n};\n\n/**\n * Creates a promise that throws when the network progresses past the block height after which the\n * supplied blockhash is considered expired for use as a transaction lifetime specifier.\n *\n * When a transaction's lifetime is tied to a blockhash, that transaction can be landed on the\n * network until that blockhash expires. All blockhashes have a block height after which they are\n * considered to have expired.\n *\n * @param config\n *\n * @example\n * ```ts\n * import { isSolanaError, SolanaError } from '@solana/errors';\n * import { createBlockHeightExceedencePromiseFactory } from '@solana/transaction-confirmation';\n *\n * const getBlockHeightExceedencePromise = createBlockHeightExceedencePromiseFactory({\n * rpc,\n * rpcSubscriptions,\n * });\n * try {\n * await getBlockHeightExceedencePromise({ lastValidBlockHeight });\n * } catch (e) {\n * if (isSolanaError(e, SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED)) {\n * console.error(\n * `The block height of the network has exceeded ${e.context.lastValidBlockHeight}. ` +\n * `It is now ${e.context.currentBlockHeight}`,\n * );\n * // Re-sign and retry the transaction.\n * return;\n * }\n * throw e;\n * }\n * ```\n */\nexport function createBlockHeightExceedencePromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateBlockHeightExceedencePromiseFactoryConfig<'devnet'>): GetBlockHeightExceedencePromiseFn;\nexport function createBlockHeightExceedencePromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateBlockHeightExceedencePromiseFactoryConfig<'testnet'>): GetBlockHeightExceedencePromiseFn;\nexport function createBlockHeightExceedencePromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateBlockHeightExceedencePromiseFactoryConfig<'mainnet'>): GetBlockHeightExceedencePromiseFn;\nexport function createBlockHeightExceedencePromiseFactory<\n TCluster extends 'devnet' | 'mainnet' | 'testnet' | void = void,\n>({\n rpc,\n rpcSubscriptions,\n}: CreateBlockHeightExceedencePromiseFactoryConfig<TCluster>): GetBlockHeightExceedencePromiseFn {\n return async function getBlockHeightExceedencePromise({\n abortSignal: callerAbortSignal,\n commitment,\n lastValidBlockHeight,\n }): Promise<never> {\n callerAbortSignal.throwIfAborted();\n const abortController = new AbortController();\n const handleAbort = () => {\n abortController.abort();\n };\n callerAbortSignal.addEventListener('abort', handleAbort, { signal: abortController.signal });\n async function getBlockHeightAndDifferenceBetweenSlotHeightAndBlockHeight() {\n const { absoluteSlot, blockHeight } = await rpc\n .getEpochInfo({ commitment })\n .send({ abortSignal: abortController.signal });\n return {\n blockHeight,\n differenceBetweenSlotHeightAndBlockHeight: absoluteSlot - blockHeight,\n };\n }\n try {\n const [slotNotifications, { blockHeight: initialBlockHeight, differenceBetweenSlotHeightAndBlockHeight }] =\n await Promise.all([\n rpcSubscriptions.slotNotifications().subscribe({ abortSignal: abortController.signal }),\n getBlockHeightAndDifferenceBetweenSlotHeightAndBlockHeight(),\n ]);\n callerAbortSignal.throwIfAborted();\n let currentBlockHeight = initialBlockHeight;\n if (currentBlockHeight <= lastValidBlockHeight) {\n let lastKnownDifferenceBetweenSlotHeightAndBlockHeight = differenceBetweenSlotHeightAndBlockHeight;\n for await (const slotNotification of slotNotifications) {\n const { slot } = slotNotification;\n if (slot - lastKnownDifferenceBetweenSlotHeightAndBlockHeight > lastValidBlockHeight) {\n // Before making a final decision, recheck the actual block height.\n const {\n blockHeight: recheckedBlockHeight,\n differenceBetweenSlotHeightAndBlockHeight: currentDifferenceBetweenSlotHeightAndBlockHeight,\n } = await getBlockHeightAndDifferenceBetweenSlotHeightAndBlockHeight();\n currentBlockHeight = recheckedBlockHeight;\n if (currentBlockHeight > lastValidBlockHeight) {\n // Verified; the block height has been exceeded.\n break;\n } else {\n // The block height has not been exceeded, which implies that the\n // difference between the slot height and the block height has grown\n // (ie. some blocks have been skipped since we started). Recalibrate the\n // difference and keep waiting.\n lastKnownDifferenceBetweenSlotHeightAndBlockHeight =\n currentDifferenceBetweenSlotHeightAndBlockHeight;\n }\n }\n }\n }\n callerAbortSignal.throwIfAborted();\n throw new SolanaError(SOLANA_ERROR__BLOCK_HEIGHT_EXCEEDED, {\n currentBlockHeight,\n lastValidBlockHeight,\n });\n } finally {\n abortController.abort();\n }\n };\n}\n","import type { Address } from '@solana/addresses';\nimport { getBase58Decoder, getBase64Encoder } from '@solana/codecs-strings';\nimport { SOLANA_ERROR__INVALID_NONCE, SOLANA_ERROR__NONCE_ACCOUNT_NOT_FOUND, SolanaError } from '@solana/errors';\nimport { AbortController } from '@solana/event-target-impl';\nimport { safeRace } from '@solana/promises';\nimport type { GetAccountInfoApi, Rpc } from '@solana/rpc';\nimport type { AccountNotificationsApi, RpcSubscriptions } from '@solana/rpc-subscriptions';\nimport type { Base64EncodedDataResponse, Commitment } from '@solana/rpc-types';\nimport { Nonce } from '@solana/transaction-messages';\n\ntype GetNonceInvalidationPromiseFn = (config: {\n abortSignal: AbortSignal;\n /**\n * Fetch the nonce account details as of the highest slot that has reached this level of\n * commitment.\n */\n commitment: Commitment;\n /**\n * The value of the nonce that we would expect to see in the nonce account in order for any\n * transaction with that nonce-based lifetime to be considered valid.\n */\n currentNonceValue: Nonce;\n /** The address of the account in which the currently-valid nonce value is stored */\n nonceAccountAddress: Address;\n}) => Promise<void>;\n\ntype CreateNonceInvalidationPromiseFactoryConfig<TCluster> = {\n rpc: Rpc<GetAccountInfoApi> & { '~cluster'?: TCluster };\n rpcSubscriptions: RpcSubscriptions<AccountNotificationsApi> & { '~cluster'?: TCluster };\n};\n\nconst NONCE_VALUE_OFFSET =\n 4 + // version(u32)\n 4 + // state(u32)\n 32; // nonce authority(pubkey)\n// Then comes the nonce value.\n\n/**\n * Creates a promise that throws when the value stored in a nonce account is not the expected one.\n *\n * When a transaction's lifetime is tied to the value stored in a nonce account, that transaction\n * can be landed on the network until the nonce is advanced to a new value.\n *\n * @param config\n *\n * @example\n * ```ts\n * import { isSolanaError, SolanaError } from '@solana/errors';\n * import { createNonceInvalidationPromiseFactory } from '@solana/transaction-confirmation';\n *\n * const getNonceInvalidationPromise = createNonceInvalidationPromiseFactory({\n * rpc,\n * rpcSubscriptions,\n * });\n * try {\n * await getNonceInvalidationPromise({\n * currentNonceValue,\n * nonceAccountAddress,\n * });\n * } catch (e) {\n * if (isSolanaError(e, SOLANA_ERROR__NONCE_INVALID)) {\n * console.error(`The nonce has advanced to ${e.context.actualNonceValue}`);\n * // Re-sign and retry the transaction.\n * return;\n * } else if (isSolanaError(e, SOLANA_ERROR__NONCE_ACCOUNT_NOT_FOUND)) {\n * console.error(`No nonce account was found at ${nonceAccountAddress}`);\n * }\n * throw e;\n * }\n * ```\n */\nexport function createNonceInvalidationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateNonceInvalidationPromiseFactoryConfig<'devnet'>): GetNonceInvalidationPromiseFn;\nexport function createNonceInvalidationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateNonceInvalidationPromiseFactoryConfig<'testnet'>): GetNonceInvalidationPromiseFn;\nexport function createNonceInvalidationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateNonceInvalidationPromiseFactoryConfig<'mainnet'>): GetNonceInvalidationPromiseFn;\nexport function createNonceInvalidationPromiseFactory<TCluster extends 'devnet' | 'mainnet' | 'testnet' | void = void>({\n rpc,\n rpcSubscriptions,\n}: CreateNonceInvalidationPromiseFactoryConfig<TCluster>): GetNonceInvalidationPromiseFn {\n return async function getNonceInvalidationPromise({\n abortSignal: callerAbortSignal,\n commitment,\n currentNonceValue: expectedNonceValue,\n nonceAccountAddress,\n }) {\n const abortController = new AbortController();\n function handleAbort() {\n abortController.abort();\n }\n callerAbortSignal.addEventListener('abort', handleAbort, { signal: abortController.signal });\n /**\n * STEP 1: Set up a subscription for nonce account changes.\n */\n const accountNotifications = await rpcSubscriptions\n .accountNotifications(nonceAccountAddress, { commitment, encoding: 'base64' })\n .subscribe({ abortSignal: abortController.signal });\n const base58Decoder = getBase58Decoder();\n const base64Encoder = getBase64Encoder();\n function getNonceFromAccountData([base64EncodedBytes]: Base64EncodedDataResponse): Nonce {\n const data = base64Encoder.encode(base64EncodedBytes);\n const nonceValueBytes = data.slice(NONCE_VALUE_OFFSET, NONCE_VALUE_OFFSET + 32);\n return base58Decoder.decode(nonceValueBytes) as Nonce;\n }\n const nonceAccountDidAdvancePromise = (async () => {\n for await (const accountNotification of accountNotifications) {\n const nonceValue = getNonceFromAccountData(accountNotification.value.data);\n if (nonceValue !== expectedNonceValue) {\n throw new SolanaError(SOLANA_ERROR__INVALID_NONCE, {\n actualNonceValue: nonceValue,\n expectedNonceValue,\n });\n }\n }\n })();\n /**\n * STEP 2: Having subscribed for updates, make a one-shot request for the current nonce\n * value to check if it has already been advanced.\n */\n const nonceIsAlreadyInvalidPromise = (async () => {\n const { value: nonceAccount } = await rpc\n .getAccountInfo(nonceAccountAddress, {\n commitment,\n dataSlice: { length: 32, offset: NONCE_VALUE_OFFSET },\n encoding: 'base58',\n })\n .send({ abortSignal: abortController.signal });\n if (!nonceAccount) {\n throw new SolanaError(SOLANA_ERROR__NONCE_ACCOUNT_NOT_FOUND, {\n nonceAccountAddress,\n });\n }\n const nonceValue =\n // This works because we asked for the exact slice of data representing the nonce\n // value, and furthermore asked for it in `base58` encoding.\n nonceAccount.data[0] as unknown as Nonce;\n if (nonceValue !== expectedNonceValue) {\n throw new SolanaError(SOLANA_ERROR__INVALID_NONCE, {\n actualNonceValue: nonceValue,\n expectedNonceValue,\n });\n } else {\n await new Promise(() => {\n /* never resolve */\n });\n }\n })();\n try {\n return await safeRace([nonceAccountDidAdvancePromise, nonceIsAlreadyInvalidPromise]);\n } finally {\n abortController.abort();\n }\n };\n}\n","import { getSolanaErrorFromTransactionError } from '@solana/errors';\nimport { AbortController } from '@solana/event-target-impl';\nimport type { Signature } from '@solana/keys';\nimport { safeRace } from '@solana/promises';\nimport type { GetSignatureStatusesApi, Rpc } from '@solana/rpc';\nimport type { RpcSubscriptions, SignatureNotificationsApi } from '@solana/rpc-subscriptions';\nimport { type Commitment, commitmentComparator } from '@solana/rpc-types';\n\ntype GetRecentSignatureConfirmationPromiseFn = (config: {\n abortSignal: AbortSignal;\n /**\n * The level of commitment the transaction must have achieved in order for the promise to\n * resolve.\n */\n commitment: Commitment;\n /**\n * A 64 byte Ed25519 signature, encoded as a base-58 string, that uniquely identifies a\n * transaction by virtue of being the first or only signature in its list of signatures.\n */\n signature: Signature;\n}) => Promise<void>;\n\ntype CreateRecentSignatureConfirmationPromiseFactoryConfig<TCluster> = {\n rpc: Rpc<GetSignatureStatusesApi> & { '~cluster'?: TCluster };\n rpcSubscriptions: RpcSubscriptions<SignatureNotificationsApi> & { '~cluster'?: TCluster };\n};\n\n/**\n * Creates a promise that resolves when a recently-landed transaction achieves the target\n * confirmation commitment, and throws when the transaction fails with an error.\n *\n * The status of recently-landed transactions is available in the network's status cache. This\n * confirmation strategy will only yield a result if the signature is still in the status cache. To\n * fetch the status of transactions older than those available in the status cache, use the\n * {@link GetSignatureStatusesApi.getSignatureStatuses} method setting the\n * `searchTransactionHistory` configuration param to `true`.\n *\n * @param config\n *\n * @example\n * ```ts\n * import { createRecentSignatureConfirmationPromiseFactory } from '@solana/transaction-confirmation';\n *\n * const getRecentSignatureConfirmationPromise = createRecentSignatureConfirmationPromiseFactory({\n * rpc,\n * rpcSubscriptions,\n * });\n * try {\n * await getRecentSignatureConfirmationPromise({\n * commitment,\n * signature,\n * });\n * console.log(`The transaction with signature \\`${signature}\\` has achieved a commitment level of \\`${commitment}\\``);\n * } catch (e) {\n * console.error(`The transaction with signature \\`${signature}\\` failed`, e.cause);\n * throw e;\n * }\n * ```\n */\nexport function createRecentSignatureConfirmationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateRecentSignatureConfirmationPromiseFactoryConfig<'devnet'>): GetRecentSignatureConfirmationPromiseFn;\nexport function createRecentSignatureConfirmationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateRecentSignatureConfirmationPromiseFactoryConfig<'testnet'>): GetRecentSignatureConfirmationPromiseFn;\nexport function createRecentSignatureConfirmationPromiseFactory({\n rpc,\n rpcSubscriptions,\n}: CreateRecentSignatureConfirmationPromiseFactoryConfig<'mainnet'>): GetRecentSignatureConfirmationPromiseFn;\nexport function createRecentSignatureConfirmationPromiseFactory<\n TCluster extends 'devnet' | 'mainnet' | 'testnet' | void = void,\n>({\n rpc,\n rpcSubscriptions,\n}: CreateRecentSignatureConfirmationPromiseFactoryConfig<TCluster>): GetRecentSignatureConfirmationPromiseFn {\n return async function getRecentSignatureConfirmationPromise({\n abortSignal: callerAbortSignal,\n commitment,\n signature,\n }) {\n const abortController = new AbortController();\n function handleAbort() {\n abortController.abort();\n }\n callerAbortSignal.addEventListener('abort', handleAbort, { signal: abortController.signal });\n /**\n * STEP 1: Set up a subscription for status changes to a signature.\n */\n const signatureStatusNotifications = await rpcSubscriptions\n .signatureNotifications(signature, { commitment })\n .subscribe({ abortSignal: abortController.signal });\n const signatureDidCommitPromise = (async () => {\n for await (const signatureStatusNotification of signatureStatusNotifications) {\n if (signatureStatusNotification.value.err) {\n throw getSolanaErrorFromTransactionError(signatureStatusNotification.value.err);\n } else {\n return;\n }\n }\n })();\n /**\n * STEP 2: Having subscribed for updates, make a one-shot request for the current status.\n * This will only yield a result if the signature is still in the status cache.\n */\n const signatureStatusLookupPromise = (async () => {\n const { value: signatureStatusResults } = await rpc\n .getSignatureStatuses([signature])\n .send({ abortSignal: abortController.signal });\n const signatureStatus = signatureStatusResults[0];\n if (\n signatureStatus?.confirmationStatus &&\n commitmentComparator(signatureStatus.confirmationStatus, commitment) >= 0\n ) {\n return;\n } else if (signatureStatus?.err) {\n throw getSolanaErrorFromTransactionError(signatureStatus.err);\n } else {\n await new Promise(() => {\n /* never resolve */\n });\n }\n })();\n try {\n return await safeRace([signatureDidCommitPromise, signatureStatusLookupPromise]);\n } finally {\n abortController.abort();\n }\n };\n}\n","import type { Commitment } from '@solana/rpc-types';\n\ntype Config = Readonly<{\n abortSignal: AbortSignal;\n /**\n * The timeout promise will throw after 30 seconds when the commitment is `processed`, and 60\n * seconds otherwise.\n */\n commitment: Commitment;\n}>;\n\n/**\n * When no other heuristic exists to infer that a transaction has expired, you can use this promise\n * factory with a commitment level. It throws after 30 seconds when the commitment is `processed`,\n * and 60 seconds otherwise. You would typically race this with another confirmation strategy.\n *\n * @param config\n *\n * @example\n * ```ts\n * import { safeRace } from '@solana/promises';\n * import { getTimeoutPromise } from '@solana/transaction-confirmation';\n *\n * try {\n * await safeRace([getCustomTransactionConfirmationPromise(/* ... *\\/), getTimeoutPromise({ commitment })]);\n * } catch (e) {\n * if (e instanceof DOMException && e.name === 'TimeoutError') {\n * console.log('Could not confirm transaction after a timeout');\n * }\n * throw e;\n * }\n * ```\n */\nexport async function getTimeoutPromise({ abortSignal: callerAbortSignal, commitment }: Config) {\n return await new Promise((_, reject) => {\n const handleAbort = (e: AbortSignalEventMap['abort']) => {\n clearTimeout(timeoutId);\n const abortError = new DOMException((e.target as AbortSignal).reason, 'AbortError');\n reject(abortError);\n };\n callerAbortSignal.addEventListener('abort', handleAbort);\n const timeoutMs = commitment === 'processed' ? 30_000 : 60_000;\n const startMs = performance.now();\n const timeoutId =\n // We use `setTimeout` instead of `AbortSignal.timeout()` because we want to measure\n // elapsed time instead of active time.\n // See https://developer.mozilla.org/en-US/docs/Web/API/AbortSignal/timeout_static\n setTimeout(() => {\n const elapsedMs = performance.now() - startMs;\n reject(new DOMException(`Timeout elapsed after ${elapsedMs} ms`, 'TimeoutError'));\n }, timeoutMs);\n });\n}\n","import { AbortController } from '@solana/event-target-impl';\nimport type { Signature } from '@solana/keys';\nimport { safeRace } from '@solana/promises';\nimport type { Commitment } from '@solana/rpc-types';\n\nimport { createRecentSignatureConfirmationPromiseFactory } from './confirmation-strategy-recent-signature';\n\nexport interface BaseTransactionConfirmationStrategyConfig {\n abortSignal?: AbortSignal;\n commitment: Commitment;\n getRecentSignatureConfirmationPromise: ReturnType<typeof createRecentSignatureConfirmationPromiseFactory>;\n}\n\ntype WithNonNullableAbortSignal<T> = Omit<T, 'abortSignal'> & Readonly<{ abortSignal: AbortSignal }>;\n\nexport async function raceStrategies<TConfig extends BaseTransactionConfirmationStrategyConfig>(\n signature: Signature,\n config: TConfig,\n getSpecificStrategiesForRace: (config: WithNonNullableAbortSignal<TConfig>) => readonly Promise<unknown>[],\n) {\n const { abortSignal: callerAbortSignal, commitment, getRecentSignatureConfirmationPromise } = config;\n callerAbortSignal?.throwIfAborted();\n const abortController = new AbortController();\n if (callerAbortSignal) {\n const handleAbort = () => {\n abortController.abort();\n };\n callerAbortSignal.addEventListener('abort', handleAbort, { signal: abortController.signal });\n }\n try {\n const specificStrategies = getSpecificStrategiesForRace({\n ...config,\n abortSignal: abortController.signal,\n });\n return await safeRace([\n getRecentSignatureConfirmationPromise({\n abortSignal: abortController.signal,\n commitment,\n signature,\n }),\n ...specificStrategies,\n ]);\n } finally {\n abortController.abort();\n }\n}\n","import { Signature } from '@solana/keys';\nimport {\n getSignatureFromTransaction,\n Transaction,\n TransactionWithBlockhashLifetime,\n TransactionWithDurableNonceLifetime,\n} from '@solana/transactions';\n\nimport { createBlockHeightExceedencePromiseFactory } from './confirmation-strategy-blockheight';\nimport { createNonceInvalidationPromiseFactory } from './confirmation-strategy-nonce';\nimport { BaseTransactionConfirmationStrategyConfig, raceStrategies } from './confirmation-strategy-racer';\nimport { getTimeoutPromise } from './confirmation-strategy-timeout';\n\nexport type TransactionWithLastValidBlockHeight = Omit<TransactionWithBlockhashLifetime, 'lifetimeConstraint'> & {\n lifetimeConstraint: Omit<TransactionWithBlockhashLifetime['lifetimeConstraint'], 'blockhash'>;\n};\n\ninterface WaitForDurableNonceTransactionConfirmationConfig extends BaseTransactionConfirmationStrategyConfig {\n getNonceInvalidationPromise: ReturnType<typeof createNonceInvalidationPromiseFactory>;\n transaction: Readonly<Transaction & TransactionWithDurableNonceLifetime>;\n}\n\ninterface WaitForRecentTransactionWithBlockhashLifetimeConfirmationConfig\n extends BaseTransactionConfirmationStrategyConfig {\n getBlockHeightExceedencePromise: ReturnType<typeof createBlockHeightExceedencePromiseFactory>;\n transaction: Readonly<Transaction & TransactionWithLastValidBlockHeight>;\n}\n\ninterface WaitForRecentTransactionWithTimeBasedLifetimeConfirmationConfig\n extends BaseTransactionConfirmationStrategyConfig {\n getTimeoutPromise: typeof getTimeoutPromise;\n /**\n * A 64 byte Ed25519 signature, encoded as a base-58 string, that uniquely identifies a\n * transaction by virtue of being the first or only signature in its list of signatures.\n */\n signature: Signature;\n}\n\n/**\n * Supply your own confirmation implementations to this function to create a custom nonce\n * transaction confirmation strategy.\n *\n * @example\n * ```ts\n * import { waitForDurableNonceTransactionConfirmation } from '@solana/transaction-confirmation';\n *\n * try {\n * await waitForDurableNonceTransactionConfirmation({\n * getNonceInvalidationPromise({ abortSignal, commitment, currentNonceValue, nonceAccountAddress }) {\n * // Return a promise that rejects when a nonce becomes invalid.\n * },\n * getRecentSignatureConfirmationPromise({ abortSignal, commitment, signature }) {\n * // Return a promise that resolves when a transaction achieves confirmation\n * },\n * });\n * } catch (e) {\n * // Handle errors.\n * }\n * ```\n */\nexport async function waitForDurableNonceTransactionConfirmation(\n config: WaitForDurableNonceTransactionConfirmationConfig,\n): Promise<void> {\n await raceStrategies(\n getSignatureFromTransaction(config.transaction),\n config,\n function getSpecificStrategiesForRace({ abortSignal, commitment, getNonceInvalidationPromise, transaction }) {\n return [\n getNonceInvalidationPromise({\n abortSignal,\n commitment,\n currentNonceValue: transaction.lifetimeConstraint.nonce,\n nonceAccountAddress: transaction.lifetimeConstraint.nonceAccountAddress,\n }),\n ];\n },\n );\n}\n\n/**\n * Supply your own confirmation implementations to this function to create a custom confirmation\n * strategy for recently-landed transactions.\n *\n * @example\n * ```ts\n * import { waitForRecentTransactionConfirmation } from '@solana/transaction-confirmation';\n *\n * try {\n * await waitForRecentTransactionConfirmation({\n * getBlockHeightExceedencePromise({ abortSignal, commitment, lastValidBlockHeight }) {\n * // Return a promise that rejects when the blockhash's block height has been exceeded\n * },\n * getRecentSignatureConfirmationPromise({ abortSignal, commitment, signature }) {\n * // Return a promise that resolves when a transaction achieves confirmation\n * },\n * });\n * } catch (e) {\n * // Handle errors.\n * }\n * ```\n */\nexport async function waitForRecentTransactionConfirmation(\n config: WaitForRecentTransactionWithBlockhashLifetimeConfirmationConfig,\n): Promise<void> {\n await raceStrategies(\n getSignatureFromTransaction(config.transaction),\n config,\n function getSpecificStrategiesForRace({\n abortSignal,\n commitment,\n getBlockHeightExceedencePromise,\n transaction,\n }) {\n return [\n getBlockHeightExceedencePromise({\n abortSignal,\n commitment,\n lastValidBlockHeight: transaction.lifetimeConstraint.lastValidBlockHeight,\n }),\n ];\n },\n );\n}\n\n/** @deprecated */\nexport async function waitForRecentTransactionConfirmationUntilTimeout(\n config: WaitForRecentTransactionWithTimeBasedLifetimeConfirmationConfig,\n): Promise<void> {\n await raceStrategies(\n config.signature,\n config,\n function getSpecificStrategiesForRace({ abortSignal, commitment, getTimeoutPromise }) {\n return [\n getTimeoutPromise({\n abortSignal,\n commitment,\n }),\n ];\n },\n );\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solana/transaction-confirmation",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.1",
|
|
4
4
|
"description": "Helpers for confirming Solana transactions",
|
|
5
5
|
"exports": {
|
|
6
6
|
"edge-light": {
|
|
@@ -54,16 +54,16 @@
|
|
|
54
54
|
"maintained node versions"
|
|
55
55
|
],
|
|
56
56
|
"dependencies": {
|
|
57
|
-
"@solana/
|
|
58
|
-
"@solana/
|
|
59
|
-
"@solana/errors": "3.0.
|
|
60
|
-
"@solana/promises": "3.0.
|
|
61
|
-
"@solana/keys": "3.0.
|
|
62
|
-
"@solana/rpc": "3.0.
|
|
63
|
-
"@solana/rpc-subscriptions": "3.0.
|
|
64
|
-
"@solana/
|
|
65
|
-
"@solana/transactions": "3.0.
|
|
66
|
-
"@solana/
|
|
57
|
+
"@solana/codecs-strings": "3.0.1",
|
|
58
|
+
"@solana/addresses": "3.0.1",
|
|
59
|
+
"@solana/errors": "3.0.1",
|
|
60
|
+
"@solana/promises": "3.0.1",
|
|
61
|
+
"@solana/keys": "3.0.1",
|
|
62
|
+
"@solana/rpc": "3.0.1",
|
|
63
|
+
"@solana/rpc-subscriptions": "3.0.1",
|
|
64
|
+
"@solana/rpc-types": "3.0.1",
|
|
65
|
+
"@solana/transactions": "3.0.1",
|
|
66
|
+
"@solana/transaction-messages": "3.0.1"
|
|
67
67
|
},
|
|
68
68
|
"peerDependencies": {
|
|
69
69
|
"typescript": ">=5.3.3"
|