{"version":3,"file":"tronscan.mjs","names":[],"sources":["../../src/providers/tronscan.ts"],"sourcesContent":["/**\n * TRONSCAN provider — indexed TRON explorer API.\n *\n * https://docs.tronscan.org/en/api\n */\n\nimport type {\n  Balance,\n  BlockInfo,\n  ChainKey,\n  ProviderCapabilities,\n  ProviderConfig,\n  Transaction,\n  TxHistoryOptions,\n  TxStatus,\n} from \"../core/types.js\";\nimport { Provider } from \"../core/provider.js\";\nimport { normalizeBaseUrl, buildQuery } from \"../core/client.js\";\nimport { AuthError, NotFoundError, UnsupportedChainError } from \"../core/errors.js\";\nimport { assertSafePathSegment } from \"../core/path-safety.js\";\nimport { clampMaxResults, formatWei } from \"../core/types.js\";\n\nconst DEFAULT_BASE = \"https://apilist.tronscanapi.com\";\n\ninterface TronscanAccount {\n  readonly address: string;\n  readonly balance?: string | number;\n  readonly balanceStr?: string;\n}\n\ninterface TronscanTransaction {\n  readonly hash: string;\n  readonly timestamp: number;\n  readonly block: number;\n  readonly ownerAddress?: string;\n  readonly toAddress?: string;\n  readonly contractType?: number;\n  readonly confirmed?: boolean;\n  readonly revert?: boolean;\n  readonly contractRet?: string;\n  readonly amount?: string | number;\n  readonly cost?: {\n    readonly fee?: string | number;\n    readonly net_fee?: string | number;\n  };\n}\n\ninterface TronscanBlock {\n  readonly number: number;\n  readonly hash: string;\n  readonly timestamp: number;\n  readonly nrOfTrx: number;\n  readonly witnessAddress?: string;\n}\n\nfunction transactionStatus(raw: Readonly<TronscanTransaction>): TxStatus {\n  if (raw.confirmed === false) return \"pending\";\n  return raw.contractRet === \"SUCCESS\" && raw.revert !== true ? \"success\" : \"failed\";\n}\n\nfunction transactionFee(raw: Readonly<TronscanTransaction>): string | undefined {\n  const fee = raw.cost?.fee ?? raw.cost?.net_fee;\n  return fee === undefined ? undefined : String(fee);\n}\n\nfunction mapTransaction(raw: Readonly<TronscanTransaction>): Transaction {\n  const value = String(raw.amount ?? 0);\n  return {\n    hash: raw.hash,\n    blockNumber: raw.block,\n    timestamp: new Date(raw.timestamp).toISOString(),\n    from: raw.ownerAddress ?? \"\",\n    to: raw.toAddress ?? null,\n    value,\n    valueFormatted: formatWei(value, 6),\n    fee: transactionFee(raw),\n    status: transactionStatus(raw),\n    isContractInteraction: raw.contractType !== undefined && raw.contractType !== 1,\n    tokenTransfers: [],\n    raw: raw as unknown as Record<string, unknown>,\n  };\n}\n\nexport class Tronscan extends Provider {\n  static readonly key = \"tronscan\";\n\n  private readonly apiKey: string;\n  private readonly baseUrl: string;\n\n  constructor(config: Readonly<ProviderConfig>) {\n    super(config);\n    const apiKey = config.apiKey ?? process.env.TRONSCAN_API_KEY ?? \"\";\n    if (!apiKey) {\n      throw new AuthError(\"tronscan\", \"Set TRONSCAN_API_KEY or pass apiKey in config\");\n    }\n    this.apiKey = apiKey;\n    this.baseUrl = normalizeBaseUrl(config.baseUrl ?? DEFAULT_BASE);\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  private api<T>(\n    path: string,\n    params: Readonly<Record<string, string | number | undefined>>,\n  ): Promise<T> {\n    return this.getJSON<T>(`${this.baseUrl}${path}${buildQuery(params)}`, {\n      headers: { \"TRON-PRO-API-KEY\": this.apiKey },\n    });\n  }\n\n  async getBalance(address: string, chain?: ChainKey): Promise<Balance> {\n    const c = chain ?? \"tron\";\n    if (c !== \"tron\") throw new UnsupportedChainError(c, this.name);\n    assertSafePathSegment(address, \"address\");\n\n    const account = await this.api<TronscanAccount>(\"/api/accountv2\", { address });\n    const balance = account.balanceStr ?? String(account.balance ?? 0);\n    return this.snapshotBalance({\n      address,\n      chain: \"tron\",\n      balance,\n      balanceFormatted: formatWei(balance, 6),\n      symbol: \"TRX\",\n    });\n  }\n\n  async getTxHistory(\n    address: string,\n    chain?: ChainKey,\n    options?: Readonly<TxHistoryOptions>,\n  ): Promise<Transaction[]> {\n    const c = chain ?? \"tron\";\n    if (c !== \"tron\") throw new UnsupportedChainError(c, this.name);\n    assertSafePathSegment(address, \"address\");\n\n    const response = await this.api<{ data: TronscanTransaction[] }>(\"/api/transaction\", {\n      address,\n      limit: clampMaxResults(options?.limit, 50),\n      start: 0,\n      sort: options?.sort === \"asc\" ? \"timestamp\" : \"-timestamp\",\n    });\n    return response.data.map(mapTransaction);\n  }\n\n  override async getTxDetail(hash: string, chain?: ChainKey): Promise<Transaction> {\n    const c = chain ?? \"tron\";\n    if (c !== \"tron\") throw new UnsupportedChainError(c, this.name);\n    assertSafePathSegment(hash, \"tx hash\");\n\n    const transaction = await this.api<TronscanTransaction>(\"/api/transaction-info\", { hash });\n    if (!transaction.hash) throw new NotFoundError(`Transaction ${hash}`, this.name);\n    return mapTransaction(transaction);\n  }\n\n  override async getBlockInfo(blockNumber: number, chain?: ChainKey): Promise<BlockInfo> {\n    const c = chain ?? \"tron\";\n    if (c !== \"tron\") throw new UnsupportedChainError(c, this.name);\n    assertSafePathSegment(String(blockNumber), \"block number\");\n\n    const response = await this.api<{ data: TronscanBlock[] }>(\"/api/block\", {\n      number: blockNumber,\n    });\n    const block = response.data[0];\n    if (!block) throw new NotFoundError(`Block ${blockNumber}`, this.name);\n    return {\n      number: block.number,\n      hash: block.hash,\n      parentHash: \"\",\n      timestamp: new Date(block.timestamp).toISOString(),\n      miner: block.witnessAddress ?? \"\",\n      gasUsed: \"0\",\n      gasLimit: \"0\",\n      txCount: block.nrOfTrx,\n    };\n  }\n}\n"],"mappings":"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"}