Background
JavaScript numbers are IEEE-754 doubles, so integers above 2^53 - 1 (Number.MAX_SAFE_INTEGER) cannot be represented exactly. The java-tron HTTP API serializes protobuf int64 / uint64 fields as JSON numbers, which means large values (balances, TRC10 amounts, vote counts, ...) are silently corrupted by JSON.parse before user code ever sees them.
java-tron #6699 added an int64_as_string=true query flag (honored on GET requests) that makes the node serialize int64/uint64 fields as JSON strings, so exact values reach JavaScript intact.
What's added
A new read-only namespace tronWeb.trx.raw that mirrors the chain-reading methods of trx (getBalance, getAccount, getBlock, getTransaction, getTransactionInfo, getAccountResources, token / proposal / exchange / witness queries, ...) but issues them as GET requests with int64_as_string=true.
const tronWeb = new TronWeb({ fullHost: 'https://nile.trongrid.io' });
const balance = await tronWeb.trx.raw.getBalance(address);
// "9007199254740993" — string, exact
const block = await tronWeb.trx.raw.getCurrentBlock();
block.block_header.raw_data.number; // string (proto int64)
block.block_header.raw_data.version; // number (proto int32 — not affected by the flag)
Compile-time typing
Return types reflect the wire change via two new exported mapped types:
Types.Int64AsString<T> — maps exactly the int64 fields of a regular response type to string, leaving proto int32 / enum fields (id, type, Permission_id, version, trx_num, precision, num, vote_score) as number. The field mapping was verified against Nile testnet.
Types.Precise64<T, P> — resolves to Int64AsString<T> when P is true, to T otherwise.
Internally, the method logic is shared: Trx and RawTrx both extend AbstractTrx<P extends boolean>, and only the HTTP routing differs (readRequest re-issues raw reads as GET with the flag).
Routing details
getCurrentBlock / getConfirmedCurrentBlock are rerouted in raw mode to wallet/getblock?detail=true / walletsolidity/getblock?detail=true, because getnowblock does not honor the flag.
- Reads that cannot take the flag are pinned to the regular number path in both modes:
getNodeInfo — the node does not honor the flag there, and the response carries doubles that must stay numbers;
listNodes, getBandwidthPrices, getEnergyPrices, getDelegatedResourceAccountIndexV2, getBrokerage / getUnconfirmedBrokerage — no int64 in the response;
getTransactionsToAddress / getTransactionsFromAddress / getTransactionsRelated — deprecated walletextension APIs;
getSignWeight / getApprovedList — consume a transaction object via POST body;
getCurrentRefBlockParams — feeds local transaction building and must stay on the number path.
trx.raw is read-only: no signing / broadcasting methods are exposed on it.
- The plugin system cannot override the
raw sub-module (pluginNoOverride).
Requirements & caveats
- The connected node must run a java-tron build that includes #6699. Older nodes ignore the flag and keep returning (possibly precision-lossy) numbers without any error — there is no runtime detection.
- Responses read via
trx.raw must not be fed back into transaction-consuming endpoints (sendRawTransaction, getSignWeight, ...): the node rejects string-encoded int64 fields in request bodies.
- proto3 omits fields holding their default value, so declared-required fields can still be absent at runtime (a fresh account is
{}).
Tests
test/lib/rawTrx.test.ts — integration suite against a local TRE node covering the string/number field split, the getblock rerouting, the read-only surface, and the plugin-override protection.
Background
JavaScript numbers are IEEE-754 doubles, so integers above
2^53 - 1(Number.MAX_SAFE_INTEGER) cannot be represented exactly. The java-tron HTTP API serializes protobufint64/uint64fields as JSON numbers, which means large values (balances, TRC10 amounts, vote counts, ...) are silently corrupted byJSON.parsebefore user code ever sees them.java-tron #6699 added an
int64_as_string=truequery flag (honored on GET requests) that makes the node serialize int64/uint64 fields as JSON strings, so exact values reach JavaScript intact.What's added
A new read-only namespace
tronWeb.trx.rawthat mirrors the chain-reading methods oftrx(getBalance,getAccount,getBlock,getTransaction,getTransactionInfo,getAccountResources, token / proposal / exchange / witness queries, ...) but issues them as GET requests withint64_as_string=true.Compile-time typing
Return types reflect the wire change via two new exported mapped types:
Types.Int64AsString<T>— maps exactly the int64 fields of a regular response type tostring, leaving proto int32 / enum fields (id,type,Permission_id,version,trx_num,precision,num,vote_score) asnumber. The field mapping was verified against Nile testnet.Types.Precise64<T, P>— resolves toInt64AsString<T>whenPistrue, toTotherwise.Internally, the method logic is shared:
TrxandRawTrxboth extendAbstractTrx<P extends boolean>, and only the HTTP routing differs (readRequestre-issues raw reads as GET with the flag).Routing details
getCurrentBlock/getConfirmedCurrentBlockare rerouted in raw mode towallet/getblock?detail=true/walletsolidity/getblock?detail=true, becausegetnowblockdoes not honor the flag.getNodeInfo— the node does not honor the flag there, and the response carries doubles that must stay numbers;listNodes,getBandwidthPrices,getEnergyPrices,getDelegatedResourceAccountIndexV2,getBrokerage/getUnconfirmedBrokerage— no int64 in the response;getTransactionsToAddress/getTransactionsFromAddress/getTransactionsRelated— deprecated walletextension APIs;getSignWeight/getApprovedList— consume a transaction object via POST body;getCurrentRefBlockParams— feeds local transaction building and must stay on the number path.trx.rawis read-only: no signing / broadcasting methods are exposed on it.rawsub-module (pluginNoOverride).Requirements & caveats
trx.rawmust not be fed back into transaction-consuming endpoints (sendRawTransaction,getSignWeight, ...): the node rejects string-encoded int64 fields in request bodies.{}).Tests
test/lib/rawTrx.test.ts— integration suite against a local TRE node covering the string/number field split, thegetblockrerouting, the read-only surface, and the plugin-override protection.