{"version":3,"sources":["../../src/internal/transaction.ts"],"sourcesContent":["// Copyright © Aptos Foundation\n// SPDX-License-Identifier: Apache-2.0\n\n/**\n * This file contains the underlying implementations for exposed API surface in\n * the {@link api/transaction}. By moving the methods out into a separate file,\n * other namespaces and processes can access these methods without depending on the entire\n * transaction namespace and without having a dependency cycle error.\n */\n\nimport { AptosConfig } from \"../api/aptosConfig\";\nimport { AptosApiError, getAptosFullNode, paginateWithCursor } from \"../client\";\nimport {\n  TransactionResponseType,\n  type AnyNumber,\n  type GasEstimation,\n  type HexInput,\n  type PaginationArgs,\n  type TransactionResponse,\n  WaitForTransactionOptions,\n  CommittedTransactionResponse,\n} from \"../types\";\nimport { DEFAULT_TXN_TIMEOUT_SEC, ProcessorType } from \"../utils/const\";\nimport { sleep } from \"../utils/helpers\";\nimport { memoizeAsync } from \"../utils/memoize\";\nimport { getIndexerLastSuccessVersion, getProcessorStatus } from \"./general\";\n\nexport async function getTransactions(args: {\n  aptosConfig: AptosConfig;\n  options?: PaginationArgs;\n}): Promise<TransactionResponse[]> {\n  const { aptosConfig, options } = args;\n  return paginateWithCursor<{}, TransactionResponse[]>({\n    aptosConfig,\n    originMethod: \"getTransactions\",\n    path: \"transactions\",\n    params: { start: options?.offset, limit: options?.limit },\n  });\n}\n\nexport async function getGasPriceEstimation(args: { aptosConfig: AptosConfig }) {\n  const { aptosConfig } = args;\n\n  return memoizeAsync(\n    async () => {\n      const { data } = await getAptosFullNode<{}, GasEstimation>({\n        aptosConfig,\n        originMethod: \"getGasPriceEstimation\",\n        path: \"estimate_gas_price\",\n      });\n      return data;\n    },\n    `gas-price-${aptosConfig.network}`,\n    1000 * 60 * 5, // 5 minutes\n  )();\n}\n\nexport async function getTransactionByVersion(args: {\n  aptosConfig: AptosConfig;\n  ledgerVersion: AnyNumber;\n}): Promise<TransactionResponse> {\n  const { aptosConfig, ledgerVersion } = args;\n  const { data } = await getAptosFullNode<{}, TransactionResponse>({\n    aptosConfig,\n    originMethod: \"getTransactionByVersion\",\n    path: `transactions/by_version/${ledgerVersion}`,\n  });\n  return data;\n}\n\nexport async function getTransactionByHash(args: {\n  aptosConfig: AptosConfig;\n  transactionHash: HexInput;\n}): Promise<TransactionResponse> {\n  const { aptosConfig, transactionHash } = args;\n  const { data } = await getAptosFullNode<{}, TransactionResponse>({\n    aptosConfig,\n    path: `transactions/by_hash/${transactionHash}`,\n    originMethod: \"getTransactionByHash\",\n  });\n  return data;\n}\n\nexport async function isTransactionPending(args: {\n  aptosConfig: AptosConfig;\n  transactionHash: HexInput;\n}): Promise<boolean> {\n  const { aptosConfig, transactionHash } = args;\n  try {\n    const transaction = await getTransactionByHash({ aptosConfig, transactionHash });\n    return transaction.type === TransactionResponseType.Pending;\n  } catch (e: any) {\n    if (e?.status === 404) {\n      return true;\n    }\n    throw e;\n  }\n}\n\nexport async function longWaitForTransaction(args: {\n  aptosConfig: AptosConfig;\n  transactionHash: HexInput;\n}): Promise<TransactionResponse> {\n  const { aptosConfig, transactionHash } = args;\n  const { data } = await getAptosFullNode<{}, TransactionResponse>({\n    aptosConfig,\n    path: `transactions/wait_by_hash/${transactionHash}`,\n    originMethod: \"longWaitForTransaction\",\n  });\n  return data;\n}\n\nexport async function waitForTransaction(args: {\n  aptosConfig: AptosConfig;\n  transactionHash: HexInput;\n  options?: WaitForTransactionOptions;\n}): Promise<CommittedTransactionResponse> {\n  const { aptosConfig, transactionHash, options } = args;\n  const timeoutSecs = options?.timeoutSecs ?? DEFAULT_TXN_TIMEOUT_SEC;\n  const checkSuccess = options?.checkSuccess ?? true;\n\n  let isPending = true;\n  let timeElapsed = 0;\n  let lastTxn: TransactionResponse | undefined;\n  let lastError: AptosApiError | undefined;\n  let backoffIntervalMs = 200;\n  const backoffMultiplier = 1.5;\n\n  function handleAPIError(e: any) {\n    // In short, this means we will retry if it was an AptosApiError and the code was 404 or 5xx.\n    const isAptosApiError = e instanceof AptosApiError;\n    if (!isAptosApiError) {\n      throw e; // This would be unexpected\n    }\n    lastError = e;\n    const isRequestError = e.status !== 404 && e.status >= 400 && e.status < 500;\n    if (isRequestError) {\n      throw e;\n    }\n  }\n\n  // check to see if the txn is already on the blockchain\n  try {\n    lastTxn = await getTransactionByHash({ aptosConfig, transactionHash });\n    isPending = lastTxn.type === TransactionResponseType.Pending;\n  } catch (e) {\n    handleAPIError(e);\n  }\n\n  // If the transaction is pending, we do a long wait once to avoid polling\n  if (isPending) {\n    const startTime = Date.now();\n    try {\n      lastTxn = await longWaitForTransaction({ aptosConfig, transactionHash });\n      isPending = lastTxn.type === TransactionResponseType.Pending;\n    } catch (e) {\n      handleAPIError(e);\n    }\n    timeElapsed = (Date.now() - startTime) / 1000;\n  }\n\n  // Now we do polling to see if the transaction is still pending\n  while (isPending) {\n    if (timeElapsed >= timeoutSecs) {\n      break;\n    }\n    try {\n      // eslint-disable-next-line no-await-in-loop\n      lastTxn = await getTransactionByHash({ aptosConfig, transactionHash });\n\n      isPending = lastTxn.type === TransactionResponseType.Pending;\n\n      if (!isPending) {\n        break;\n      }\n    } catch (e) {\n      handleAPIError(e);\n    }\n    // eslint-disable-next-line no-await-in-loop\n    await sleep(backoffIntervalMs);\n    timeElapsed += backoffIntervalMs / 1000; // Convert to seconds\n    backoffIntervalMs *= backoffMultiplier;\n  }\n\n  // There is a chance that lastTxn is still undefined. Let's throw the last error otherwise a WaitForTransactionError\n  if (lastTxn === undefined) {\n    if (lastError) {\n      throw lastError;\n    } else {\n      throw new WaitForTransactionError(\n        `Fetching transaction ${transactionHash} failed and timed out after ${timeoutSecs} seconds`,\n        lastTxn,\n      );\n    }\n  }\n\n  if (lastTxn.type === TransactionResponseType.Pending) {\n    throw new WaitForTransactionError(\n      `Transaction ${transactionHash} timed out in pending state after ${timeoutSecs} seconds`,\n      lastTxn,\n    );\n  }\n  if (!checkSuccess) {\n    return lastTxn;\n  }\n  if (!lastTxn.success) {\n    throw new FailedTransactionError(\n      `Transaction ${transactionHash} failed with an error: ${lastTxn.vm_status}`,\n      lastTxn,\n    );\n  }\n\n  return lastTxn;\n}\n\n/**\n * Waits for the indexer to sync up to the ledgerVersion. Timeout is 3 seconds.\n */\nexport async function waitForIndexer(args: {\n  aptosConfig: AptosConfig;\n  minimumLedgerVersion: AnyNumber;\n  processorType?: ProcessorType;\n}): Promise<void> {\n  const { aptosConfig, processorType } = args;\n  const minimumLedgerVersion = BigInt(args.minimumLedgerVersion);\n  const timeoutMilliseconds = 3000; // 3 seconds\n  const startTime = new Date().getTime();\n  let indexerVersion = BigInt(-1);\n\n  while (indexerVersion < minimumLedgerVersion) {\n    // check for timeout\n    if (new Date().getTime() - startTime > timeoutMilliseconds) {\n      throw new Error(\"waitForLastSuccessIndexerVersionSync timeout\");\n    }\n\n    if (processorType === undefined) {\n      // Get the last success version from all processor\n      // eslint-disable-next-line no-await-in-loop\n      indexerVersion = await getIndexerLastSuccessVersion({ aptosConfig });\n    } else {\n      // Get the last success version from the specific processor\n      // eslint-disable-next-line no-await-in-loop\n      const processor = await getProcessorStatus({ aptosConfig, processorType });\n      indexerVersion = processor.last_success_version;\n    }\n\n    if (indexerVersion >= minimumLedgerVersion) {\n      // break out immediately if we are synced\n      break;\n    }\n\n    // eslint-disable-next-line no-await-in-loop\n    await sleep(200);\n  }\n}\n\n/**\n * This error is used by `waitForTransaction` when waiting for a\n * transaction to time out or when the transaction response is undefined\n */\nexport class WaitForTransactionError extends Error {\n  public readonly lastSubmittedTransaction: TransactionResponse | undefined;\n\n  constructor(message: string, lastSubmittedTransaction: TransactionResponse | undefined) {\n    super(message);\n    this.lastSubmittedTransaction = lastSubmittedTransaction;\n  }\n}\n\n/**\n * This error is used by `waitForTransaction` if `checkSuccess` is true.\n * See that function for more information.\n */\nexport class FailedTransactionError extends Error {\n  public readonly transaction: TransactionResponse;\n\n  constructor(message: string, transaction: TransactionResponse) {\n    super(message);\n    this.transaction = transaction;\n  }\n}\n"],"mappings":"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","names":["getTransactions","args","aptosConfig","options","paginateWithCursor","getGasPriceEstimation","memoizeAsync","data","getAptosFullNode","getTransactionByVersion","ledgerVersion","getTransactionByHash","transactionHash","isTransactionPending","e","longWaitForTransaction","waitForTransaction","timeoutSecs","checkSuccess","isPending","timeElapsed","lastTxn","lastError","backoffIntervalMs","backoffMultiplier","handleAPIError","AptosApiError","startTime","sleep","WaitForTransactionError","FailedTransactionError","waitForIndexer","processorType","minimumLedgerVersion","timeoutMilliseconds","indexerVersion","getIndexerLastSuccessVersion","getProcessorStatus","message","lastSubmittedTransaction","transaction"]}