{"version":3,"file":"arweave.mjs","names":[],"sources":["../../src/providers/arweave.ts"],"sourcesContent":["import { z } from \"zod\";\nimport { Provider } from \"../core/provider.js\";\nimport { ARWEAVE_GATEWAY_URL } from \"../core/endpoints.js\";\nimport { normalizeBaseUrl } from \"../core/client.js\";\nimport { ExplorerError, NotFoundError, UnsupportedChainError } from \"../core/errors.js\";\nimport { formatWei, toTimestamp } from \"../core/types.js\";\nimport type {\n  Balance,\n  BlockInfo,\n  ChainKey,\n  ProviderCapabilities,\n  ProviderConfig,\n  Transaction,\n  TxHistoryOptions,\n} from \"../core/types.js\";\n\nconst TX_FIELDS = `id owner { address } recipient quantity { winston } fee { winston }\n  block { height timestamp } bundledIn { id } data { size type } tags { name value }`;\nconst MAX_WINDOW = 1000;\n\nfunction transactionSchema() {\n  const amount = z.object({ winston: z.string().regex(/^\\d+$/) });\n  return z.object({\n    id: z.string().min(1),\n    owner: z.object({ address: z.string() }),\n    recipient: z.string(),\n    quantity: amount,\n    fee: amount,\n    block: z\n      .object({\n        height: z.number().int().nonnegative(),\n        timestamp: z.number().int().nonnegative().max(8_640_000_000_000),\n      })\n      .nullable(),\n    bundledIn: z.object({ id: z.string() }).nullable(),\n    data: z.object({ size: z.string(), type: z.string().nullable() }),\n    tags: z.array(z.object({ name: z.string(), value: z.string() })),\n  });\n}\n\ntype IndexedTransaction = z.infer<ReturnType<typeof transactionSchema>>;\n\nfunction assertChain(chain: ChainKey): void {\n  if (chain !== \"arweave\") throw new UnsupportedChainError(chain, Arweave.key);\n}\n\nfunction assertIdentifier(value: string): void {\n  if (!/^[A-Za-z0-9_-]{43}$/.test(value)) {\n    throw new ExplorerError(\n      \"Expected an Arweave address or transaction ID with 43 characters\",\n      Arweave.key,\n    );\n  }\n}\n\n/* oxlint-disable-next-line typescript/prefer-readonly-parameter-types */\nfunction mapTransaction(tx: IndexedTransaction): Transaction {\n  return {\n    hash: tx.id,\n    from: tx.owner.address,\n    to: tx.recipient,\n    value: tx.quantity.winston,\n    valueFormatted: formatWei(tx.quantity.winston, 12),\n    ...(tx.bundledIn === null ? { fee: tx.fee.winston } : {}),\n    blockNumber: tx.block?.height ?? 0,\n    ...(tx.block === null ? {} : { timestamp: toTimestamp(tx.block.timestamp) }),\n    status: tx.block === null ? \"pending\" : \"success\",\n    isContractInteraction: false,\n    tokenTransfers: [],\n    raw: { ...tx },\n  };\n}\n\nfunction validInteger(value: number, min: number, max: number): boolean {\n  return Number.isSafeInteger(value) && value >= min && value <= max;\n}\n\nfunction historyWindow(options: Readonly<TxHistoryOptions>) {\n  const limit = options.limit ?? 100;\n  const page = options.page ?? 1;\n  if (!validInteger(limit, 1, 100) || !validInteger(page, 1, Math.floor(MAX_WINDOW / limit))) {\n    throw new ExplorerError(\n      \"Arweave history requires limit from 1 to 100 and page * limit <= 1000\",\n      Arweave.key,\n    );\n  }\n  assertBlockBounds(options);\n  return { limit, count: page * limit, offset: (page - 1) * limit };\n}\n\nfunction assertBlockBounds(options: Readonly<TxHistoryOptions>): void {\n  for (const height of [options.startBlock, options.endBlock]) {\n    if (height !== undefined && !validInteger(height, 0, 2_147_483_647)) {\n      throw new ExplorerError(\n        \"Arweave block bounds must be nonnegative GraphQL Int values\",\n        Arweave.key,\n      );\n    }\n  }\n  if (\n    options.startBlock !== undefined &&\n    options.endBlock !== undefined &&\n    options.startBlock > options.endBlock\n  ) {\n    throw new ExplorerError(\"Arweave startBlock must not exceed endBlock\", Arweave.key);\n  }\n}\n\n/** Arweave balances and blocks from gateway REST, transactions from its GraphQL index. */\nexport class Arweave extends Provider {\n  static readonly key = \"arweave\";\n  private readonly base: string;\n  private readonly endpoint: string;\n\n  constructor(config: Readonly<ProviderConfig> = {}) {\n    super(config);\n    this.base = normalizeBaseUrl(config.baseUrl ?? ARWEAVE_GATEWAY_URL);\n    this.endpoint = `${this.base}/graphql`;\n  }\n\n  get capabilities(): ProviderCapabilities {\n    return {\n      balances: true,\n      txHistory: true,\n      txDetail: true,\n      utxos: false,\n      contractInfo: false,\n      tokenBalances: false,\n      tokenTransfers: false,\n      gasData: false,\n      blockInfo: true,\n    };\n  }\n\n  async getBalance(address: string, chain: ChainKey = \"arweave\"): Promise<Balance> {\n    assertChain(chain);\n    assertIdentifier(address);\n    const raw = await this.getJSON<unknown>(`${this.base}/wallet/${address}/balance`);\n    /** Integers served as text pass through the shared lossless JSON parser. */\n    const parsed = z\n      .union([z.string().regex(/^\\d+$/), z.number().int().nonnegative().safe()])\n      .safeParse(raw);\n    if (!parsed.success) throw new ExplorerError(\"Invalid Arweave balance response\", this.name);\n    const balance = String(parsed.data);\n    return {\n      address,\n      chain,\n      fetchedAt: new Date().toISOString(),\n      blockNumber: null,\n      blockHash: null,\n      balance,\n      balanceFormatted: formatWei(balance, 12),\n      symbol: \"AR\",\n    };\n  }\n\n  override async getBlockInfo(\n    blockNumber: number,\n    chain: ChainKey = \"arweave\",\n  ): Promise<BlockInfo> {\n    assertChain(chain);\n    if (!validInteger(blockNumber, 0, Number.MAX_SAFE_INTEGER))\n      throw new ExplorerError(\"Arweave block number must be a nonnegative safe integer\", this.name);\n    const raw = await this.getJSON<unknown>(`${this.base}/block/height/${blockNumber}`);\n    const parsed = z\n      .object({\n        height: z.literal(blockNumber),\n        indep_hash: z.string().min(1),\n        previous_block: z.string(),\n        timestamp: z.number().int().nonnegative().max(8_640_000_000_000),\n        reward_addr: z.string().min(1),\n        txs: z.array(z.string()),\n      })\n      .safeParse(raw);\n    if (!parsed.success) throw new ExplorerError(\"Invalid Arweave block response\", this.name);\n    const block = parsed.data;\n    return {\n      number: block.height,\n      hash: block.indep_hash,\n      parentHash: block.previous_block,\n      timestamp: new Date(block.timestamp * 1000).toISOString(),\n      miner: block.reward_addr,\n      /** Arweave has no gas; retain the existing non-EVM BlockInfo convention. */\n      gasUsed: \"0\",\n      gasLimit: \"0\",\n      txCount: block.txs.length,\n    };\n  }\n\n  private async query<T>(\n    query: string,\n    variables: Readonly<Record<string, unknown>>,\n    /* oxlint-disable-next-line typescript/prefer-readonly-parameter-types */\n    schema: z.ZodType<T>,\n  ): Promise<T> {\n    const raw = await this.postJSON<unknown>(this.endpoint, { query, variables });\n    const parsed = z\n      .object({\n        data: schema.nullish(),\n        errors: z.array(z.object({ message: z.string() })).optional(),\n      })\n      .safeParse(raw);\n    if (!parsed.success) throw new ExplorerError(\"Invalid Arweave GraphQL response\", this.name);\n    if (parsed.data.errors?.length) {\n      throw new ExplorerError(\n        `Arweave GraphQL: ${parsed.data.errors.map((error) => error.message).join(\"; \")}`,\n        this.name,\n      );\n    }\n    if (parsed.data.data === null || parsed.data.data === undefined)\n      throw new ExplorerError(\"Missing Arweave GraphQL data\", this.name);\n    return parsed.data.data;\n  }\n\n  override async getTxDetail(hash: string, chain: ChainKey = \"arweave\"): Promise<Transaction> {\n    assertChain(chain);\n    assertIdentifier(hash);\n    const { transaction } = await this.query(\n      `query ($id: ID!) { transaction(id: $id) { ${TX_FIELDS} } }`,\n      { id: hash },\n      z.object({ transaction: transactionSchema().nullable() }),\n    );\n    if (transaction === null) throw new NotFoundError(`transaction ${hash}`, this.name);\n    return mapTransaction(transaction);\n  }\n\n  /**\n   * GraphQL combines owners and recipients with AND, so read each direction separately.\n   * @param {string} address - Address to match.\n   * @param {\"owners\" | \"recipients\"} direction - Indexed address field.\n   * @param {number} count - Number of rows needed before merging.\n   * @param {Readonly<TxHistoryOptions>} options - Order and block bounds.\n   * @returns {Promise<IndexedTransaction[]>} Rows from one direction.\n   */\n  private async historyDirection(\n    address: string,\n    direction: \"owners\" | \"recipients\",\n    count: number,\n    options: Readonly<TxHistoryOptions>,\n  ): Promise<IndexedTransaction[]> {\n    const result: IndexedTransaction[] = [];\n    const seen = new Set<string>();\n    let after: string | undefined;\n    while (result.length < count) {\n      const { transactions } = await this.query(\n        `query ($addresses: [String!]!, $first: Int!, $after: String, $sort: SortOrder!, $block: RangeFilter) {\n          transactions(${direction}: $addresses, first: $first, after: $after, sort: $sort, block: $block) {\n            pageInfo { hasNextPage } edges { cursor node { ${TX_FIELDS} } }\n          }\n        }`,\n        {\n          addresses: [address],\n          first: Math.min(100, count - result.length),\n          after,\n          sort: options.sort === \"asc\" ? \"HEIGHT_ASC\" : \"HEIGHT_DESC\",\n          block: { min: options.startBlock, max: options.endBlock },\n        },\n        z.object({\n          transactions: z.object({\n            pageInfo: z.object({ hasNextPage: z.boolean() }),\n            edges: z\n              .array(z.object({ cursor: z.string().min(1), node: transactionSchema() }))\n              .max(100),\n          }),\n        }),\n      );\n      result.push(...transactions.edges.map((edge) => edge.node));\n      if (!transactions.pageInfo.hasNextPage) break;\n      const cursor = transactions.edges.at(-1)?.cursor;\n      if (!cursor || seen.has(cursor))\n        throw new ExplorerError(\"Arweave history cursor did not advance\", this.name);\n      seen.add(cursor);\n      after = cursor;\n    }\n    return result.slice(0, count);\n  }\n\n  async getTxHistory(\n    address: string,\n    chain: ChainKey = \"arweave\",\n    options: Readonly<TxHistoryOptions> = {},\n  ): Promise<Transaction[]> {\n    assertChain(chain);\n    assertIdentifier(address);\n    const { count, offset, limit } = historyWindow(options);\n    const [sent, received] = await Promise.all([\n      this.historyDirection(address, \"owners\", count, options),\n      this.historyDirection(address, \"recipients\", count, options),\n    ]);\n    const unique = new Map([...sent, ...received].map((tx) => [tx.id, tx]));\n    const order = options.sort === \"asc\" ? 1 : -1;\n    return [...unique.values()]\n      .sort(\n        (a, b) =>\n          order *\n          ((a.block?.height ?? Number.MAX_SAFE_INTEGER) -\n            (b.block?.height ?? Number.MAX_SAFE_INTEGER)),\n      )\n      .slice(offset, offset + limit)\n      .map(mapTransaction);\n  }\n}\n"],"mappings":"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"}