Repository navigation
Releases
wallet-cli-4.16.0
Notice
Non-mandatory upgrade
This release makes the TypeScript CLI safer for scripts and agents: commands now wait for
confirmation and finish within one time limit, and signing refuses payloads meant for another
network. Several options, error codes and JSON fields change, so check scripts that parse the
output before you upgrade. The Java REPL only carries the version bump, with no behavior change.
New Features
Change
-
Commands wait for confirmation by default. A send, a broadcast or a GasFree transfer now returns when the transaction is confirmed or failed, not when it is submitted. Pass
--no-waitto return right after submission.--wait-timeoutand thewaitTimeoutMsconfig key are removed, and the flag now fails withinvalid_option. (#1046) -
One time limit for the whole command.
--timeout <ms>(default 90 seconds,0for no limit) now covers the whole command, including Ledger approval and waiting for confirmation, but not your typing at a prompt. If time runs out after the transaction was accepted, the command still exits0withstage: "submitted", the txId and a warning. (#1046) -
Safer signing and credentials. Signing now refuses a transaction or typed data that names a different chain from the selected network (
chain_id_mismatch), and every Ledger signature is checked against the account before it is used. TronLink, GasFree, B.AI and network API keys are set only withconfig <key> --api-key-stdin; passing them as arguments fails. (#1046) -
Clear signal when a transaction may have gone through. When a request may have acted although the command failed, the error carries
error.details.outcome: "unknown"and the txId. Check it withtx statusbefore sending again. Rebroadcasting a signed TRON transaction the node already holds returnsalreadyKnown: trueinstead of an error. (#1046) -
sunswap swap: set the minimum you receive.--min-out <base-units>sets the floor directly instead of--slippage. If the route already quotes less, the command stops withslippage_exceededbefore anything is approved, signed or sent. A route quoted at zero output is no longer offered. (#1046)
Bug Fixes
Change
-
tx statusreports TRON results correctly. A mined transaction whose receipt saysDEFAULTis nowconfirmedinstead offailed, and a transaction the node marksFAILEDisfailed. (#1046) -
Errors name the real cause. A wrong combination of options now fails with
invalid_optioninstead ofinvalid_value. Malformed data from a node or a service fails withinvalid_node_responseorprovider_errorinstead of showing zero or empty values, and HTTP 429 from any service isprovider_rate_limited. (#1046) -
Failing transfers stop before they cost a fee.
stake undelegateabove the delegated amount fails withinsufficient_stake, and a TRC20 or ERC20tx sendabove the token balance fails withinsufficient_token_balance. Both checks run before signing, in every mode including--dry-run. (#1046) -
Ambiguous token symbols stop before signing. If
--token USDTmatches no token or more than one token in the book, the command stops and lists the candidates. On EVM,--tokentogether with--contractfails withinvalid_option. (#1046) -
A blocked command says how to unblock it. When another wallet-cli process holds a lock, the error names the lock file and the process that holds it. If no wallet-cli command is running, delete the file. (#1046)
-
Updated dependencies. TronWeb is updated to 6.5.1, which verifies the node's copy of a transaction before multi-signing and checks inputs from a single snapshot. Other dependencies with published advisories are updated as well. (#1046, #1049)
Integrity Check
All jar files available in this release are signed via this GPG key:
- PUB: 1254 F859 D2B1 BD9F 66E7 107D F859 BCB4 4A28 290B
- UID: build@tron.network
From the download listings below you should see links to the downloadable jar files as well as sig signature files. To verify the authenticity of any jar file, grab the jar and sig files with the same prefix name and then execute the verification process: GPG signature verification
wallet-cli-4.15.1
Notice
Non-mandatory upgrade
This release fixes interactive prompts in the TypeScript CLI, mainly on Windows, tightens how
x402 pay applies a raw payment limit, and requires a Node.js release that carries the October
2026 security fixes. The Java REPL only carries the version bump, with no behavior change.
Bug Fixes
Change
-
Interactive prompts now work on Windows. You can now type passwords, recovery phrases and private keys at the terminal prompt on Windows. Before, commands such as
import,change-passwordanddeletefailed withtty_requiredinstead of asking. On Windows, a prompt needs the command to run directly in the console; in scripts, pipe the password with--password-stdininstead. (#1034) -
config baiApiKey --api-key-stdinreads from slow pipes. Piping the key from a tool that takes a moment to answer, such as a password manager CLI, no longer fails with "no data available on stdin". (#1034) -
Ctrl-C no longer hangs at a typed prompt. Pressing Ctrl-C at the
deleteconfirmation, or when the CLI asks for a missing argument, now ends the command with exit code130, as it already did at password prompts. (#1034) -
x402 pay --max-raw-amountnow needs--tokenor--asset. A raw limit counts smallest units without naming a token, so a paid endpoint could ask for a different, more valuable token and still stay under it. The CLI now refuses a raw limit that is not pinned to a token, before anything is signed; scripts that pass--max-raw-amountalone fail withinvalid_optionuntil they add--tokenor--asset, or switch to--max-amount. After a payment, the result also shows which token and how much was paid (data.paymentin JSON). (#1040) -
x402 roundtripno longer fails on a busy machine. When signing took more than a few seconds, the paid request could fail withECONNRESETand report an unknown payment status, although nothing had been paid.x402 servenow closes the connection after its payment challenge, so the paid request always starts on a fresh one, forx402 roundtripand for any other payer. (#1042) -
The TypeScript CLI now needs Node.js 22.23.4, 24.22.1 or 26.12.1 or later. These releases fix the Node.js October 2026 security issues, including one in Brotli decompression that responses from RPC nodes and paid endpoints can reach. Node.js 20 is end-of-life and gets no fix. On an older Node.js,
npm installprints anEBADENGINEwarning, or fails withengine-strict, so upgrade Node.js first. (#1042)
Integrity Check
All jar files available in this release are signed via this GPG key:
- PUB: 1254 F859 D2B1 BD9F 66E7 107D F859 BCB4 4A28 290B
- UID: build@tron.network
From the download listings below you should see links to the downloadable jar files as well as sig signature files. To verify the authenticity of any jar file, grab the jar and sig files with the same prefix name and then execute the verification process: GPG signature verification
wallet-cli-4.15.0
Notice
Non-mandatory upgrade
This release adds SunSwap and SunPump support to the TypeScript CLI. The Java REPL only carries
the version bump and a documentation correction, with no behavior change.
New Features
Change
-
sunswap— trade and provide liquidity on SunSwap from the CLI. Swap tokens, add or remove liquidity on V2, V3 and V4 pools, and collect fees from your positions. You can also look up pools, positions, tokens and prices without a wallet. Every transaction can be previewed with--dry-runfirst, and any token approvals it needs are sent and confirmed for you before the trade. The swap and market queries run on mainnet; the liquidity commands also run on Nile. (#1025) -
sunpump— buy, sell and launch tokens on SunPump. Buy and sell tokens on their bonding curve, launch a new token, and browse or search the launchpad.--quoteshows the price of a trade without an account or a transaction, and the platform fee is shown separately from the network fee. Once a token has launched,sunswap swaptrades it instead. Available on mainnet. (#1025) -
Clearer network errors and price display. When a command is not available on the selected network, the error now tells you which networks support it. Very small USD prices are shown with their significant digits instead of
0.0000. Ledger users need Custom contracts and Sign by Hash enabled in the TRON app to usesunswapandsunpump. (#1025)
Bug Fixes
Change
-
x402 paynow handles binary content correctly. Request bodies from--body-fileare sent exactly as they are, instead of being altered when they are not plain text. A binary response, such as an image or a PDF, now requires--outto save it, instead of being printed as corrupted text. In addition,bai usage-summaryno longer rounds large values. (#1029) -
A failed
importno longer leaves files behind. Whenimportrejected the label, it could still leave an encrypted key file in the wallet directory, or set a master password. The label is now checked before anything is saved. Error messages in text mode also no longer let a file name or label break the output across lines. (#1029) -
Ledger errors are clearer, and cancelling no longer hangs. Cancelling a Ledger operation or letting it time out now ends the command right away. When the device cannot be used, the error now tells you whether it is not connected, busy in another application such as Ledger Live, or disconnected during the operation. On TRON, broadcasting an expired transaction now reports
tx_expired, so you know to rebuild and sign it again. (#1025)
Integrity Check
All jar files available in this release are signed via this GPG key:
- PUB: 1254 F859 D2B1 BD9F 66E7 107D F859 BCB4 4A28 290B
- UID: build@tron.network
From the download listings below you should see links to the downloadable jar files as well as sig signature files. To verify the authenticity of any jar file, grab the jar and sig files with the same prefix name and then execute the verification process: GPG signature verification
wallet-cli-4.14.0
Notice
Non-mandatory upgrade
This release is TypeScript-only in substance: the Java REPL carries the version bump and
documentation touch-ups and no behavior change. If you are upgrading the TypeScript CLI from 4.13.0
or earlier, the legacy_derivation guidance in the
4.13.1 release note
still applies.
New Features
Change
-
x402— pay x402-protected HTTP endpoints from the wallet. A new command family lets an agent call an endpoint that answers402 Payment Required, pick a payment route the endpoint offers on the selected network, sign the authorization with the active account and repeat the request with it; a facilitator settles on chain, so there is no--wait.x402 pay <url>takes the usual HTTP shape (--method,--header,--body/--body-file -) plus spend controls that are enforced before anything is signed:--max-amount/--max-raw-amount,--token/--asset,--scheme exact|exact_gasfree, and--max-gasfree-feefor a payment drawn from the account's GasFree balance instead of its token balance.--dry-runreports the route that would be paid;--outwrites the paid response to a new file, refusing an existing one before the first request.x402 serveruns a local paywall (with--daemonfor a background server),x402 roundtripstarts one, pays it once and exits, andprovider-list/provider-show/endpoint-list/update-catalogbrowse a cached provider catalog. Every failure says whether money may have moved —error.details.phase,paymentStatus(not_sent/unknown/settled),retryPayment,candidateTxHash, and on TRON the one-time Permit2approvalthat was signed — so a script never pays twice on a rumor; the SDK's own spend refusal surfaces asamount_exceeds_limit/no_matching_requirementat exit1, and a rate-limited facilitator asprovider_rate_limitedwithretryAfterSeconds. Permit2, EIP-3009 and GasFree deadlines are checked before and after the signer returns, and the TRON approve the bridge signs is pinned toapprove(Permit2, MaxUint256)on the named token with zero call value, so a substituted transaction is refused before the device prompt. (#1002, #1007, #1008, #1010, #1011, #1013, #1021, #1022) -
bai— check and recharge a B.AI account with stablecoins.bai usage-summary,bai usage-records(cursor-paged:meta.pagination.hasMore/nextCursor, passed back with--cursor) andbai recharge-ordersread the account;bai recharge <amount> [--token] [--to <email|address>] [--network tron|bsc|base]pays a recharge order with an x402 payment from the active account and reports the transaction to B.AI. The paying address must be bound to the B.AI account:rechargechecks the binding on every run and, when it is missing, signs B.AI's binding message and binds it first, stopping with no order and no payment on any failure;--dry-runreportsbindingRequiredand what would be paid without binding, ordering or signing. When B.AI cannot confirm the credit in time the command still succeeds withcreditStatus: "unconfirmed"and the transaction hash — the payment went through — andbai report-recharge <txHash>reports it again without paying. The personal API key is a new secret config key:config baiApiKey --api-key-stdinreads it from stdin only (config baiApiKey <key>on argv isinvalid_option), saves it locally without contacting B.AI, and everybaicommand without one stops withbai_credentials_missingat exit2; a wrong key isbai_auth_failed. (#1002, #1017, #1018, #1020) -
8004— read and manage ERC-8004 Agent identities. Eight commands work against the Identity Registry ontron,nile,shasta,bsc,bsc-testnet,baseandbase-sepolia(Ethereum and Sepolia fail withunsupported_network_capability):showandoperator-checkread without a wallet, andregister <uri>,update,transfer,approve,add-operatorandremove-operatorsign with the active account under the usual transaction options (--wait,--sign-only,--build-only, and on TRON--fee-limit,--permission-id,--expiration). Agent ids may carry their canonical network (tron:3448148188:172,eip155:97:42) and are checked against the selected network withchain_id_mismatch. Authorization is decided during fee estimation, before signing: the registry's revert is decoded intonot_authorizedoragent_not_found, and any other revert isexecution_revertedwitherror.details.revertData— TRON constant-call revert data, which TronWeb used to discard, is now preserved at the transport boundary for this. Receipts group the Agent fields underdata.identity, with chain-read values (agentId,newURI,newOwner,approved) present only with--wait. (#1002, #1008) -
Machine-interface and packaging refinements around the new families. Long-running
x402andbaicommands report progress on stderr —⏳ …lines in text mode, one{"type":"activity"}line per step in JSON mode — which is informational and never carries the outcome. Theconfigview now maskstronlinkSecretIdandgasfreeApiKeyas********alongside the secrets it already hid, and reading an unset key returns onlykey.deleteon an HD wallet that has TRON sub-accounts always prints the legacy-derivation warning first, since without the password it cannot tell which path created them; the warning does not stop the deletion. The npm tarball now packagesdocs/troubleshooting/, so the recovery guide that five packaged documents link to ships with the package, andverify:packagefails the build on any dangling in-package link. The--json-schemacatalog, error-code index and every command page were re-synced for the new surface. (#1009, #1011, #1013, #1019, #1022)
Bug Fixes
Change
-
Ledger on TRON: TIP-712 signatures were unverifiable, and large contract calls could not be signed at all. The TRON app's TIP-712 APDU returns the recovery byte as parity (
00/01), andtyped-data signpassed it through unchanged, so a contractecrecoverexpecting1b/1crejected every Ledger-signed typed-data message; the byte is now normalized to 27 / 28, while raw transaction signatures keep their unchanged wire format. Separately,hw-app-trxrefuses to pack a transaction whose data field exceeds 250 bytes — acontract sendwith a long argument list failed withToo many bytes to encode.before any APDU was sent. The CLI now catches exactly that pre-transport error and falls back to signing the transaction's SHA-256 hash viasignTransactionHash, after the same integrity checks as full signing, printing a warning that the device cannot display the details so the user must verify the transaction on the computer before approving. A device rejection, transport failure or cancelled operation is never retried as a hash. (#1015, #1016) -
A mined TRON contract call was reported as
confirmedwithout an execution result. The confirmation normalizer only inspected the nestedreceipt.result: a top-levelresult: "FAILED"was ignored, a numeric receipt result was coerced away, and a receipt with no result at all defaulted to success, so a reverted call could come back asstage: confirmed. Both failure locations are now honored, and forcontract call/deploy/ TRC20 sends the poller keeps waiting until the receipt carries an execution result (native transfers and stakes, which legitimately omit it, are unchanged). In the same area, the pre-flight resource estimate for a payable call now passes--valuethrough to energy estimation instead of estimating a zero-value call, andenergyPriceSunreports the current price rather than the node's raw price-history string. (#1002, #1013, #1022)
Integrity Check
All jar files available in this release are signed via this GPG key:
- PUB: 1254 F859 D2B1 BD9F 66E7 107D F859 BCB4 4A28 290B
- UID: build@tron.network
From the download listings below you should see links to the downloadable jar files as well as sig signature files. To verify the authenticity of any jar file, grab the jar and sig files with the same prefix name and then execute the verification process: GPG signature verification
wallet-cli-4.13.1
Notice
Non-mandatory upgrade
If you created HD accounts at index 1 or above on 4.13.0 or earlier, read
Troubleshooting before upgrading — those TRON addresses need one export step
that must happen while the old wallet is still intact.
Troubleshooting
legacy_derivation — recovering TRON addresses derived before this release.
If a TRON account was derived at index 1 or above by 4.13.0 or earlier, it lives at
m/44'/195'/<index>'/0/0, a path this version no longer produces. Signing it, or deriving another
account into the same wallet, now fails with legacy_derivation (exit 1). The key is not lost —
the recovery phrase still derives it at that path — but this version's default import and derive
flow will not recreate the address, so it must be preserved before the wallet is rebuilt:
error [legacy_derivation]: account "main-1" was derived at m/44'/195'/1'/0/0, a TRON path this
version no longer produces, so it cannot be signed here. Follow the complete recovery procedure
before deleting anything:
https://github.com/tronprotocol/wallet-cli/blob/wallet-cli-4.13.1/ts/docs/troubleshooting/legacy-derivation-recovery.mdThe full procedure — save the account list and recovery phrase, export each affected TRON account
with backup --keystore and re-import it as a standalone account, then delete and re-import the
mnemonic wallet and re-derive every index — is documented in
Recover addresses after legacy_derivation.
Ethereum derivation did not change, so every EVM address is restored unchanged by the re-import;
only TRON at index 1 and above needs the export step. Do not delete the mnemonic wallet until
every TRON address you need appears as a standalone private-key account. The whole procedure
reorganizes local keys only — it moves no funds on chain.
derivation_mismatch is a different failure and has no such rescue: it means the stored address
matches no derivation path of its seed, which an edited wallets.json or a wallet pointing at the
wrong vault would cause.
New Features
Change
-
deriveno longer demands a seed id. It now selects the HD wallet the way every other account command does:--account <accountId | label | address>names any account of the wallet, and with neither flag the active account decides.--seed-id wlt_…still works and takes precedence, so an existing script is unaffected, whilewallet-cli deriveon its own is now the common case. Selecting an account that belongs to a private-key, watch-only or Ledger wallet fails withseed_not_foundat exit2and says which flag to reach for;--indexnames the address index inm/44'/<coin>'/0'/0/<index>, and re-running it on an index that already exists remains a no-op that re-activates the slot. (#1003) -
backupasks which format you want. In an interactive terminal, omitting--keystorenow opens a two-line choice — Native wallet backup (the recovery phrase for the whole HD wallet) or Web3 keystore (the single private key for the selected network's family) — instead of silently taking the native path. The prompt appears only for a fully interactive invocation: passing--keystore, or piping the password in with--password-stdin, keeps the long-standing non-interactive default, so pipes and CI stay deterministic. A native backup of a seed wallet now also warns about any account this version's default mnemonic recovery would not recreate, naming each one with the exactbackup --keystorecommand that preserves it. (#1003) -
derivationPathis now only ever reported by a command that actually opened the seed.list,current,useandrenameneed no master password, and without the seed they cannot tell an account derived under the old TRON template from one derived under the corrected one — so rather than print the current template as though it were an observed fact, they now returnderivationPath: nullfor every account. A consumer that readderivationPathfrom those four commands must switch to a command that unlocks the seed:deriveandbackupresolve each cached address against its actual current or historical template before reporting, so their value is verified rather than assumed.ledger,watchandprivateKeyaccounts returnnullas before. (#1003)
Bug Fixes
Change
-
HD accounts on TRON were derived at a path no other TRON wallet scans.
derive --index 1produced its TRON key atm/44'/195'/1'/0/0, hanging the number at BIP44's account level, while TronLink, the Java wallet-cli and the wider TRON ecosystem all increment address_index. The address was real and the funds are safe, but restoring the same recovery phrase in any other wallet would not show it. TRON now derives atm/44'/195'/0'/0/<index>, the same shape EVM already used, so a derived account follows the default restore flow everywhere. Index0is identical under both templates and is unaffected; only index1and above were reachable at the old path. Accounts already sitting there are detected rather than overwritten: the stored address is resolved against both templates before any key is used, so signing such an account fails with the newlegacy_derivationcode (exit1) pointing at the recovery guide instead of signing with a different key; deriving a further account into that wallet is refused for the same reason, because one wallet must never mix templates; the 4.13.0 → 4.13.1 wallet-file migration keeps a cached TRON address that the old template explains, rather than re-deriving over it; andbackup --keystoredeliberately still exports the old path's key, since that is the one command whose whole purpose is to let the key leave. A stored address that no template explains is a different failure with a different fix —wallets.jsonand the encrypted vault disagree — and now raisesderivation_mismatchinstead of being papered over. Both codes are published in--json-schema, and the complete ordered recovery procedure ships with the release. (#1003) -
import ledger --indexdid not mean what the device shows. The index was fed through the software derivation template, so on EVM it registeredm/44'/60'/0'/0/<index>— an account Ledger Live does not display, leaving a user who picked "account 1" on their device with a different address than the one in front of them. Hardware paths are now built from Ledger Live's own template,m/44'/<coin>'/<index>'/0/0, for both families; TRON's path is unchanged, since that already was the template it used.--pathremains the way to register any other scheme explicitly,--addressscans Ledger Live accounts to find one, and the interactive account picker now prints each candidate's full path next to its address and says which template it is listing — so an account that lives on another scheme can no longer be silently mistaken for absent. (#1003)
Integrity Check
All jar files available in this release are signed via this GPG key:
- PUB: 1254 F859 D2B1 BD9F 66E7 107D F859 BCB4 4A28 290B
- UID: build@tron.network
From the download listings below you should see links to the downloadable jar files as well as sig signature files. To verify the authenticity of any jar file, grab the jar and sig files with the same prefix name and then execute the verification process: GPG signature verification
wallet-cli-4.13.0
Notice
Non-mandatory upgrade
New Features
Change
-
The TypeScript CLI now speaks EVM as well as TRON. A network belongs to one chain family,
tronorevm, and that is what decides which commands and flags apply. Twenty-one commands are bound forevm—account balance/info/portfolio,block,chain node/prices,tx send/sign/broadcast/status/info,token balance/info/add/list/remove,contract call/send/deploy, andmessage sign/typed-data sign— against TRON's full surface, which keeps staking, permissions, proposals, TRC10, GasFree and TronLink multi-sig to itself. Four EVM networks ship built in (Ethereum, Sepolia, BNB Smart Chain and its testnet) alongside the three TRON ones. One seed produces a TRON address and a different EVM address, and a key-backed account serves both families; a watch-only or Ledger account holds one address and therefore one family, with--app tron|ethereumchoosing which at import. Fees follow the chain: EIP-1559 gas estimation with--gas-limit/--nonceon EVM, bandwidth and energy on TRON. Calling a command on the wrong family fails withfamily_mismatchat exit2before any node call, using a flag from the other family isinvalid_option, and--helptags every family-scoped row(TRON only)/(EVM only).contract deploy --artifactreads a Foundry / Hardhat / TronBox compiler artifact for both bytecode and ABI, so the same deploy command works on either family with the constructor's types coming from the compiler rather than from you. (#982, #984, #990) -
Canonical network ids are now CAIP-2, and persisted wallet data upgrades itself at startup. A network is identified by
namespace:reference—tron:728126428,tron:3448148188,eip155:56— the scheme WalletConnect, SIWE and the wider agent tooling already speak; the TRON references are the decimal genesis-hash prefix. Input is unaffected:tron:mainnet,tron:nileandtron:shastaremain permanent aliases, as do short spellings such asnile,sepoliaandbsc. Output is a different matter — the envelope'schain.network, thenetworkslisting'sidand theconfigkeys all now report the CAIP-2 id, so a consumer that string-matches or keys a map bytron:nilemust be updated; an alias resolves once at selection and can never appear in a result.chainIdgoes with it, on both the envelope'schainobject and thenetworkslisting, because it keeps mirroring the id's second segment: TRON's readablemainnet/nile/shastaspellings become728126428/3448148188/2494104990, the same decimal genesis-hash prefixes. One rule for both families beats a display string, and the alias column is where readability now lives. Because the rename would otherwise orphan stored data, every invocation — including--help,--versionand--json-schema— checks the persisted wallet schema first and upgradeswallets.jsonandtokens.jsonbefore anything else runs. An upgrade asks for consent in a terminal, returns a singlemigrationenvelope at exit0withoriginalCommandExecuted: false, and deliberately does not run the command that triggered it, so nothing continues across an unexpected durable-state change; declining is a successful cancellation, and a non-interactive run that needs the master password returnsmigration_requiredat exit2unless it is piped in with--password-stdin. The commit re-reads each file under the lock, so a concurrent process's account cannot be erased by a stale snapshot. Each file's pre-upgrade copy rides inside the same transaction and is left beside it aswallets.json.v1.bak/tokens.json.v1.bak; nothing removes it later, so it is yours to keep as the rollback or to delete once you are satisfied — it holds the same wallet state as the file it shadows. Going back is a one-way trip in one respect: 4.13.0 leaves a file newer than itself alone and 4.12.0 never read the version field at all, so an older build still reads an upgradedwallets.json, but it scopes user-added tokens by the pre-CAIP-2 network id and would therefore list none of them. (#990, #994) -
The Java implementation is now the interactive shell and nothing else. The Standard CLI — its command registry, option parser, output formatter, alias book, non-interactive Ledger signer, and their tests and resources — is deleted, together with the
qa/harness that only ever drove it. The only supported invocation is a barejava -jar wallet-cli.jar, which opens the prompt;--versionprints one plain-text line,--helpprints the shell usage plus a pointer to the TypeScript CLI, and any other argument prints that one-line pointer on stderr and exits2. The hint is deliberately not a JSON envelope, so a script cannot mistake it for the removed contract. Non-interactive, scriptable and CI use belongs to the TypeScript CLI, which reached feature parity in 4.12.0. In its place,java/qa-repl/drives the real shell over a pty against a funded Nile account — wallet lifecycle, account queries, a signed transfer, and the not-logged-in guards — and the Gradle build version is now pinned to the version string the shell itself reports, with a test that fails a release build carrying-SNAPSHOTor drifted versioning. (#991, #990) -
The error-code index is published and machine-readable.
wallet-cli --json-schema | jq '.errorCodes'returns one entry per code —{"rpc_error": {"exit": 1, "retry": "same", "meaning": "the node answered with an error"}}— so an agent no longer has to scrape prose to learn what a failure means.retryanswers "now what":same(resend immediately),later(a lock-up or rate limit — back off first),changed(raise the fee, rebuild the nonce),never. Exit status is now derived from the error code itself rather than from the class that raised it, and a test holds every throw site to its code's declared exit, which settled four codes that had been thrown at both classes. Errors that name a choice rather than a dead end carryerror.details.matches;ambiguous_accountjoinsambiguous_asset_namethere, listing the candidate accounts when--account <address>does not resolve to a single interchangeable signer for the family being acted on. (#990, #994) -
Every chain HTTP call now goes through one transport, with per-network API keys and request pacing. The TRON and EVM clients share a single transport, and
networks.<id>.apiKeyHeader/.apiKeyare readable and writable throughconfig: both must be set before a header is sent, the header name is validated as an RFC 9110 token so a hand-editedconfig.yamlcannot smuggle in a second one,apiKeyis write-only on every read surface and forces the0600permission check, and a credentialed request refuses to follow redirects so a redirecting endpoint cannot collect the key. A key can also sit in the endpoint's own path, so a result no longer echoes the endpoint back in full:chain nodereports itsendpointas the host alone, as does the one thenetworkslisting now carries, andconfig networks.<id>.httpEndpointstays the way to read the URL you configured. On top of it, requests to one endpoint are paced — a FIFO queue that starts them no closer together than 400ms — because TronGrid's anonymous tier admits about three requests per second on account-scoped endpoints and answers the rest with HTTP 429, identically whether they arrive concurrently or strictly sequentially. A wide fan-out such asaccount portfolionow runs clean instead of collecting rejections. Pacing is self-imposed, so the time a request waits is credited back to--timeoutrather than charged against it; a request that loses its deadline while queued is dropped rather than sent, so an abandoned broadcast never reaches the node after the caller was told it timed out. (#990, #996)
Bug Fixes
Change
-
An unreachable node was reported as a fact about the chain.
tx statusanswerednot_foundat exit0when the endpoint simply could not be reached, and in the four-state model that string means "keep polling" — so a script waited forever on a node that was down. TRON'sgetTransactionInfoByIdresolves for an unknown hash and rejects only when the node failed, so its resolution is now the evidence that the node answered, after which "not found" is a fact about the transaction.blockhad the mirror-image defect: a height the node has no record of came back as{block: {}}at exit0, leaving callers to guess what an empty object meant. A real block always carriesblockID, so its absence is nownot_foundfor a specific height, orinvalid_node_responseforlatest— "the chain has no latest block" is not something a node can truthfully state. (#990) -
The wallet store could be taken down, or quietly lose a secret, by one unusual account. A
wallets.jsonholding a source kind this build does not know tooklistdown with a redactedinternal_error, and the address scan walked every wallet, so a single unreadable account cost every other account its lookup —use,backupanddeleteby address all failed on a registrylistcould still show.deletewas the costly one: it removed the wallet...
wallet-cli-4.12.0
Notice
Non-mandatory upgrade
New Features
Change
-
Chain governance and super-representative operation come to the TypeScript CLI.
proposal list/showread chain-parameter proposals and are open to anyone, whileproposal create/approve/deleterequire a registered witness; proposals are expressed in named chain parameters rather than raw numeric keys, and a created proposal's id is resolved from a snapshot taken before submission instead of guessed from the list afterwards.witness create/update/set-brokerageregister and operate a super representative. Contract governance follows the same path:contract clear-abi,contract set-origin-energy-limit,contract set-user-resource-percent, andcontract create2for deterministic deployment addresses. Every write goes through the shared transaction pipeline, so--dry-run,--build-only,--sign-only,--permission-id, and multi-sig behave exactly as they do for transfers. (#972, #975) -
TRC10 issuance and the protocol-level Bancor exchange are now first-class commands.
asset issue/update/participate/unfreeze/info/listcover the life of a TRC10 token (transfers continue to go throughtx send), andexchange create/inject/withdraw/trade/show/listdrive TRON's on-chain exchange. These reads are fetched and parsed losslessly, so an int64total_supplyorfrozen_amountabove 2^53 is reported exactly as a decimal string rather than rounded — sampling 1,400 mainnet assets found 252 above that bound. Reads are bound to the id asked for and to the protocol's precision range, and issuance still refuses a supply above 2^53 because java-tron cannot parse a numeric string into that field on the non-visible broadcast path. (#972, #975) -
Web3 keystore import and export, with an audit log for what left the machine.
import keystorereads a standard Web3 v3 keystore file: the file is read and structurally validated before either password is asked for, so a mistyped path costs no typing, and both passwords — the file's own and the local master password — remain hidden-TTY-only.backup --keystorewrites an account out in the same format, andbackup --recordslists the export audit log, which is preserved rather than overwritten when its contents cannot be read. The codec refuses adklenbelow 32, which would leave the MAC's key slice empty and let any password appear to open the file, and compares the MAC as bytes so an uppercase-hex file is accepted instead of being reported as a wrong password. (#975) -
The TypeScript CLI now ships as a standalone executable, with no Node.js install required.
npm run build:standalonecompiles a single self-contained binary, and a GitHub Actions workflow builds and verifies one per platform — Linux x64/arm64, macOS x64/arm64, and Windows x64 — each built on its native runner so the embedded Ledger HID addon matches, checked against a glibc 2.35 baseline on Linux, and smoke-tested before publication. A companion CI workflow runs the architecture check, type-check, tests, and bundle build on every pull request. With this release the TypeScript CLI covers the same TRON feature surface as the Java REPL; the two now differ in how you drive them, not in what they can do. (#977)
Bug Fixes
Change
-
A broadcast receipt quoted the node's transaction id instead of deriving its own. A TRON txID is the sha256 of the transaction body — derivable from the bytes that were signed, as
--sign-onlyalready did — but the broadcast path returned whatever the node echoed back. A dishonest node therefore chose which transaction--waitpolled for and which id the receipt named, so a receipt could end up describing someone else's confirmed transaction. The derived id now wins across all three broadcast paths (the pipeline,tx broadcast --file, and the multi-sig relay); a disagreement is reported as a warning rather than an error, because the transaction has already been sent. (#975) -
Amounts in a
--waitreceipt lost precision above 2^53./wallet/gettransactioninfobyidwas still fetched through TronWeb's plainJSON.parse, so realized int64 quantities —unfreeze_amount,withdraw_amount, and the exchange amounts — were already rounded float64 values before the CLI saw them. This endpoint now follows the same lossless fetch and parse asgetAccount,getBlock,listwitnesses, andlistproposals. (#975) -
account activate --addressaccepted anything non-empty. The address was typed as a plain non-empty string rather than a TRON address, so a malformed value was only rejected once the node saw it. It is now validated locally, like every other address-taking command. Two documentation errors were corrected alongside it:contract deploy --build-onlydocumentedunsigned/unsignedHexwhile the command emitstx/hex, and the pagination inventory listedproposal show, which returns a single proposal, while omittingproposal list, which paginates. (#975)
Integrity Check
All jar files available in this release are signed via this GPG key:
- PUB: 1254 F859 D2B1 BD9F 66E7 107D F859 BCB4 4A28 290B
- UID: build@tron.network
From the download listings below you should see links to the downloadable jar files as well as sig signature files. To verify the authenticity of any jar file, grab the jar and sig files with the same prefix name and then execute the verification process: GPG signature verification
wallet-cli-4.11.0
Notice
Non-mandatory upgrade
New Features
Change
-
Multi-sig is now a first-class workflow in the TypeScript CLI.
permission showandpermission updateread and replace an account's permission structure on chain (the latter burns 100 TRX and warns before an owner lockout); every broadcast command gained--permission-id <n>,--expiration <ms>, and a new--build-onlyearly-exit mode alongside--dry-run/--sign-only.tx signnow takes a transaction hex via--hex/--file, appends exactly one signature while preserving prior ones, and reports how far the accumulated weight is from the threshold — refusing before a key is ever decrypted if the account is not in the permission group (not_authorized) or has already approved (already_signed);--offlinekeeps the air-gapped path.tx approvalsis the read-only companion that shows the permission group, threshold, accumulated weight, approved signers, and expiration without signing. (#963) -
tx multisigadds optional collaboration through the TronLink multi-sig service. Where the on-chain path passes a hex from person to person, the service holds the transaction, accumulates signatures, and pushes notifications: the default mode lists transactions awaiting this account,--createsigns an unsigned hex and opens a collection at1 / N,--sign <txId>co-signs a pending one, and--watchkeeps a WebSocket open and reports only the count awaiting your signature (never transaction content). Once the threshold is reached the service broadcasts. Credentials (tronlinkSecretId/tronlinkSecretKey/tronlinkChannel) are set withconfigand are per-environment; without them the command fails withtronlink_credentials_missing. (#963) -
gasfreebrings gas-less token transfers to the TypeScript CLI.gasfree inforeports your GasFree address, activation status, nonce, and fee schedule;gasfree transfersigns an EIP-712 structured-data transfer and submits it to the GasFree provider, which puts it on chain and charges the fee in the transferred token itself, so no TRX is required;gasfree trace <traceId>follows the provider'sWAITING → INPROGRESS → CONFIRMING → SUCCEED / FAILEDstates. Because submission goes to a provider rather than a node, the receipt carries atraceIdinstead of atxId— follow it with--waitorgasfree trace, nottx status. Credentials aregasfreeApiKey/gasfreeApiSecretviaconfig. (#963) -
New account-lifecycle and local-utility commands.
account activatecreates a not-yet-existing address on chain without transferring any asset, with the payer covering the creation fee;account setwrites the on-chain name or account id (permanent on mainnet, so it is deliberately one-at-a-time). A local contact book —contact add/list/remove, stored0600in the config directory — lets a saved name be used wherever a recipient is expected (tx send --to,gasfree transfer --to).encoding convert <input>auto-detects an input and prints every equivalent representation (TRON base58 / TRON hex / EVM / public key, or hex / Base64 / Base58Check), rejecting secrets outright.address generateproduces a throwaway keypair offline, writing the private key to a0600file rather than the terminal unless--print-secretis passed.current --qrrenders a scannable receive-address QR in text mode without unlocking or touching the network. (#963) -
The Java documentation was split out of
java/README.mdinto a browsablejava/docs/tree. The README shrank from a single ~2,700-line page to an overview with quick links; commands now live underdocs/commands/by domain (wallet, account, transfers, staking, multisig, GasFree, DEX, proposals, contracts, …), withdocs/concepts/,docs/guide/, and a field-by-fielddocs/reference/config.md. Stale planning and QA scratch documents were removed. No Java behavior changed in this release apart from the version constant. (#963)
Bug Fixes
Change
-
A transaction the node rejected could be reported as submitted. TronWeb does not throw on rejection — it hands back the node's response verbatim, and a rejected
/wallet/broadcasttransactioncarries noresultfield at all, so the previousresult === falsecheck never fired and the CLI returned a success envelope with a txId for a transaction that was never accepted. Acceptance is now white-listed (result !== trueis a rejection) on both the object and--hexbroadcast paths, surfacing the node's reason astransaction_rejected. (#963) -
blocklost precision on large int64 fields. Block responses were parsed through JavaScript numbers, so protobuf int64/uint64 values beyondNumber.MAX_SAFE_INTEGERcame back rounded. Blocks are now fetched and parsed losslessly, with out-of-range integers preserved as exact decimal strings. (#963) -
--dry-runreported doomed staking requests as fine.stake freezeandstake unfreezeare rejected by the node at broadcast time when the amount exceeds the available balance or the amount actually staked for that resource, but--dry-runnever reaches the node — so a request that could not possibly succeed previewed cleanly. Both now pre-flight against the chain and fail withinsufficient_balance/insufficient_stake. Relatedly,contract sendnow warns when the supplied--fee-limitis below the energy estimate at the current energy price, and the staked-amount computation was corrected for the node's habit of omitting the defaultBANDWIDTHenum infrozenV2. (#963) -
Chain-controlled text could repaint the terminal. Permission names, token names and symbols, and co-signer labels are written by whoever put them on chain. Terminal control bytes were already stripped, but bidirectional and zero-width formatting characters passed straight through —
U+202Ereverses the display order of everything after it, letting a crafted name change how the address or weight beside it appears, and zero-width characters can make two different names render identically. Text mode now escapes them visibly (<U+202E>) rather than dropping them, so legitimate right-to-left text still displays normally and tampering is obvious. JSON output is never rewritten. (#963) -
Filesystem failures surfaced as raw OS errors.
backupand the atomic config/keystore writers let NodeErrnoExceptions escape, producinginternal_errorand, on a failed write, leaving a truncated or empty file at the destination. Failures are now typed asio_errorwith the partial artifact removed, and the multi-file atomic write reports a rolled-back failure distinctly from one that committed but could not confirm durability. Two new config-file conditions are also reported explicitly:invalid_configwhenconfig.yamlcannot be parsed (the parser detail is withheld, since it quotes the offending line and may carry a credential) andinsecure_configwhen the file holds service credentials but is a symlink or group/world-readable. (#963) -
Positional arguments rejected number-shaped values. Yargs inferred a type for the anonymous positional tail, so a value such as
0xdeadbeefor12345arrived at its string-typed field as a number and was rejected. The tail is now typed as strings so the raw token survives parsing. As a consequence, a field exposed as a positional no longer also accepts its--<field>spelling — this affects the undocumentedconfig --key/--valueandblock --numberforms; the documented positional form is unchanged, and the global--accountflag still works onuse/rename/delete/backup. (#963)
Integrity Check
All jar files available in this release are signed via this GPG key:
- PUB: 1254 F859 D2B1 BD9F 66E7 107D F859 BCB4 4A28 290B
- UID: build@tron.network
From the download listings below you should see links to the downloadable jar files as well as sig signature files. To verify the authenticity of any jar file, grab the jar and sig files with the same prefix name and then execute the verification process: GPG signature verification
wallet-cli-4.10.1
Notice
Non-mandatory upgrade
Bug Fixes
Change
- Update the postcss build dependency to 8.5.25 (and its transitive
nanoidto 3.3.17) in the TypeScript CLI to clear GHSA-r28c-9q8g-f849. postcss is a development-only dependency of thets/package and is not shipped in the published bundle, so no runtime behavior changes for users; the bump keeps the build toolchain free of known advisories.
Integrity Check
All jar files available in this release are signed via this GPG key:
- PUB: 1254 F859 D2B1 BD9F 66E7 107D F859 BCB4 4A28 290B
- UID: build@tron.network
From the download listings below you should see links to the downloadable jar files as well as sig signature files. To verify the authenticity of any jar file, grab the jar and sig files with the same prefix name and then execute the verification process: GPG signature verification
wallet-cli-4.10.0
Notice
Non-mandatory upgrade
New Features
Change
-
Add standalone signing commands to the TypeScript CLI:
tx signandtyped-data sign.tx signsigns a transaction built elsewhere and prints the signed payload without broadcasting, so the signed result can be handed totx broadcastlater; because it appends to an existingsignaturearray rather than replacing it, a partially signed transaction can be passed from signer to signer until a TRON multi-sig permission threshold is met.typed-data signsigns EIP-712 / TIP-712 structured data and returns the signature, the digest that was signed, and the resolved primary type; it accommodates real-world payloads by ignoringEIP712Domainintypes, acceptingvalueas an alias formessageand accepting TRON base58 addresses inaddressfields, while rejecting a declaredprimaryTypethat is not the message root, since a nested type can never be what gets signed. Both commands are offline for software accounts (--networkis optional) and both work with Ledger accounts. (#957) -
Enforce TRON transaction payload integrity before any signature is produced, in the software strategy and on Ledger alike. A TRON transaction states its content three times —
raw_data(what a caller reads),raw_data_hex(what the node executes) andtxID(the only thing actually signed) — and nothing in the format forces the three to agree, so a payload that displays a harmlessraw_datacan carry the hash and bytes of a different transaction. Signing now refuses (tx_integrity) unlesstxIDis the sha256 ofraw_data_hex, the contract types encoded inraw_data_hexmatch thoseraw_datadeclares, andraw_datare-encodes to exactly those bytes wherever the contract type can be encoded. The checks reject nothing a correct transaction builder produces. (#957) -
Make Ledger failures actionable rather than opaque. APDU statuses that previously surfaced as
UNKNOWN_ERROR (0x6a8c)are now mapped to typed errors that name the fix:ledger_setting_requiredfor the TRON app's "Sign by Hash", "Transactions data" and "Custom contracts" settings, andledger_unsupportedwhen the app version does not implement the instruction. Device signing also honours an abort signal, closing the transport immediately instead of holding the native handle until the timeout expires. (#957)
Bug Fixes
Change
-
Fail closed on invalid global flag values in the TypeScript CLI. An out-of-range or non-matching value for a global flag (for example
--timeout 0or an unrecognized--output) silently fell back to the flag's default and the command ran under settings the caller never asked for. Such a value is now reported asinvalid_valuebefore any command dispatch, so no RPC is attempted. (#957) -
Reject operations that cannot succeed instead of returning misleading results.
contract infoon an address with no deployed contract returned a valid-but-empty contract normalized from TronWeb's empty response, and now fails as not found.stake withdrawwith nothing withdrawable passed the node's broadcast-time checks but never confirmed, leaving a phantom txid; the withdrawable amount is now queried up front and the command fails withnothing_to_withdraw. (#957)
Integrity Check
All jar files available in this release are signed via this GPG key:
- PUB: 1254 F859 D2B1 BD9F 66E7 107D F859 BCB4 4A28 290B
- UID: build@tron.network
From the download listings below you should see links to the downloadable jar files as well as sig signature files. To verify the authenticity of any jar file, grab the jar and sig files with the same prefix name and then execute the verification process: GPG signature verification