import type { TronWeb } from '../../tron-discovery' import type { TronNativeTransferRequest, TronTRC20TransferRequest } from '@meshconnect/uwc-types' import { parseError } from '../../utils/error-utils' /** * Builder for Tron transactions. * Uses the injected tronWeb instance to create unsigned transactions. */ export class TronTransactionBuilder { /** * Build a native TRX transfer transaction */ async buildNativeTransfer( tronWeb: TronWeb, request: TronNativeTransferRequest // eslint-disable-next-line @typescript-eslint/no-explicit-any ): Promise { try { // sendTrx takes a JS number, so the SUN amount must be a non-negative // safe integer. The public type allows bigint; guard before narrowing so // an out-of-range value fails loudly instead of silently losing precision // (mirrors the new connector's assertValidAmount). const { amount } = request const valid = typeof amount === 'bigint' ? amount >= 0n && amount <= BigInt(Number.MAX_SAFE_INTEGER) : Number.isSafeInteger(amount) && amount >= 0 if (!valid) { throw new Error( `TronTransactionBuilder: native amount must be a non-negative integer within the safe range, got ${amount}` ) } const transaction = await tronWeb.transactionBuilder.sendTrx( request.to, Number(amount), request.from ) return transaction } catch (error) { parseError(error) } } /** * Build a TRC20 token transfer transaction */ async buildTRC20Transfer( tronWeb: TronWeb, request: TronTRC20TransferRequest // eslint-disable-next-line @typescript-eslint/no-explicit-any ): Promise { try { // The uint256 amount must be a non-negative integer; a fractional or // precision-lost number would stringify to a wrong/invalid value. (A // bigint is exact at any magnitude, so only the sign is checked here.) const { amount } = request const valid = typeof amount === 'bigint' ? amount >= 0n : Number.isSafeInteger(amount) && amount >= 0 if (!valid) { throw new Error( `TronTransactionBuilder: TRC20 amount must be a non-negative integer, got ${amount}` ) } const functionSelector = 'transfer(address,uint256)' const parameter = [ { type: 'address', value: request.to }, // Pass uint256 as a string so a large bigint amount keeps full // precision through tronWeb's ABI encoding. { type: 'uint256', value: amount.toString() } ] const { transaction, result } = await tronWeb.transactionBuilder.triggerSmartContract( request.contractAddress, functionSelector, {}, parameter, request.from ) if (!result?.result) { throw new Error('Failed to build TRC20 transfer transaction') } return transaction } catch (error) { parseError(error) } } }