Skip to content

Latest commit

 

History

History
150 lines (104 loc) · 9.13 KB

File metadata and controls

150 lines (104 loc) · 9.13 KB

wallet-cli tx sign

Add your signature to a transaction hex (multi-sig co-signing).

Synopsis

wallet-cli tx sign (--hex <hex> | --file <path> | --transaction <json>) [--offline] [--out <path>] [options]

Description

Adds the active account's signature to a (unsigned or partially signed) transaction hex, outputs the new hex, and reports how far the accumulated signing weight is from the permission group's threshold.

Two input modes: with --hex / --file it appends exactly one signature while preserving prior signatures; with --transaction it takes unsigned transaction JSON, preserving the direct single-signature flow.

It is the on-chain co-signing path: an initiator produces a partially signed hex with tx send --sign-only (or any broadcast command in --sign-only mode), each co-signer runs tx sign in turn — passing the hex from person to person — and once the weight reaches the threshold, anyone broadcasts the final hex with tx broadcast --hex. All signatures must be collected before the transaction expires (default ~60s, up to 24h via --expiration).

Signing endorses the transaction with your key: the command shows no preview or confirmation, reads the master password from --password-stdin, and signs directly — to inspect a transaction without signing it, use tx approvals. It does not broadcast, and has no --permission-id (the group is fixed in the transaction body; it's shown on the Permission line). Watch-only accounts fail with watch_only_no_signer.

What is verified before signing

With --hex / --file the command contacts the node and refuses to sign unless this account is a key in the transaction's permission group (not_authorized) and has not already approved it (already_signed). Both are checked before a key is decrypted, so a mistaken signer never produces a signature at all.

--offline skips those two checks and never contacts a node — for signing machines with no network. Signature-eligibility errors then surface only when the transaction is broadcast, so confirm the signing account is in the group beforehand.

Payload integrity is checked in every mode, offline included. A TRON transaction states its content three times — raw_data (what you read), raw_data_hex (what the node executes), and txID (what the signature actually covers) — and nothing in the format forces them to agree, so a transaction whose raw_data reads "1 TRX" can carry the txID of a 1000 TRX transfer. tx sign therefore refuses (tx_integrity) unless txID is the sha256 of raw_data_hex, and raw_data re-encodes to exactly those bytes wherever the contract type can be decoded.

Four contract types cannot be re-encoded by the bundled decoder — UnfreezeAssetContract, ShieldedTransferContract, MarketSellAssetContract, MarketCancelOrderContract. --hex / --file input carrying one is refused with invalid_transaction; sign those through --transaction JSON instead.

Options

Option Description
--hex <hex> Required (one of). Complete protocol.Transaction hex
--file <path> Required (one of). File containing the transaction hex (prefer this for long hex)
--transaction <json> Required (one of). Unsigned TRON transaction JSON; retained for direct single-signature compatibility
--offline Sign locally without contacting a node; skips the signer-permission and approval-weight checks. Only with --hex / --file
--out <path> Write the resulting hex to a file (mode 0644, written atomically) instead of stdout

Plus the global options and --password-stdin.

The transaction is passed on argv, not stdin: it is not a secret, and this leaves fd 0 free for --password-stdin.

Examples

In the examples, $PW is your master password, fed on stdin via --password-stdin.

An initiator first produces a partially signed tx.hex with tx send --sign-only:

echo "$PW" | wallet-cli tx send --to TBy6mQ7Y3nJ8sD2fWpXk4LhVc9Ra1Zt5Ub --amount 1000 --sign-only --permission-id 2 --expiration 86400000 --network tron:nile --password-stdin > tx.hex

A second signer appends their signature — no preview, no confirmation; the receipt carries the transaction content and progress blocks:

echo "$PW" | wallet-cli tx sign --file tx.hex --account cosigner --out tx.signed.hex --network tron:nile --password-stdin
✅ Signature added
  Signer   TXe4Kd8nP2rF9gH5jL3mV6cW1bN7yS0aQz  (weight 1)
  Hex      written to tx.signed.hex

Transaction
  TxID        9c1...
  Type        Transfer TRX — 1,000 TRX
  From        TQkXm4vN8pR2sD6fWbYc3LhJa9Ee5Zt7Uw
  To          TBy6mQ7Y3nJ8sD2fWpXk4LhVc9Ra1Zt5Ub
  Permission  active "finance" (id 2)  threshold 2
  Expires     2026-07-14 15:32 (~23h)

Progress  2 / 2 — threshold reached
| Approved signer                    | Weight |
| ---------------------------------- | ------ |
| TQkXm4vN8pR2sD6fWbYc3LhJa9Ee5Zt7Uw  |      1 |
| TXe4Kd8nP2rF9gH5jL3mV6cW1bN7yS0aQz  |      1 |

! Broadcast it: wallet-cli tx broadcast --file tx.signed.hex

With --offline the group name, threshold and per-signer weights are unavailable, so the receipt degrades to locally derivable fields and says so. Signatures is a count, not accumulated weight:

echo "$PW" | wallet-cli tx sign --file tx.hex --account cosigner --offline --network tron:nile --password-stdin
✅ Signature added
  Signer  TXe4Kd8nP2rF9gH5jL3mV6cW1bN7yS0aQz
  Hex     0a02...9f31

Transaction (local inspection)
  TxID        9c1...
  Type        Transfer TRX — 1,000 TRX
  From        TQkXm4vN8pR2sD6fWbYc3LhJa9Ee5Zt7Uw
  To          TBy6mQ7Y3nJ8sD2fWpXk4LhVc9Ra1Zt5Ub
  Permission  active (id 2)
  Signatures  1
  Expires     2026-07-14 15:32 (~23h)

! Approval state was not checked online. Inspect it with: wallet-cli tx approvals --hex <hex-above>
echo "$PW" | wallet-cli tx sign --file tx.hex --account cosigner --out tx.signed.hex --network tron:nile --password-stdin -o json
{"schema":"wallet-cli.result.v1","success":true,"command":"tx.sign","data":{"kind":"tx-sign","signer":"TXe4Kd8nP2rF9gH5jL3mV6cW1bN7yS0aQz","hex":"0a02...9f31","checked":true,"transaction":{"txId":"9c1...","contractType":"TransferContract","operation":"Transfer TRX","from":"TQkXm4vN8pR2sD6fWbYc3LhJa9Ee5Zt7Uw","to":"TBy6mQ7Y3nJ8sD2fWpXk4LhVc9Ra1Zt5Ub","rawAmount":"1000000000","permissionId":2,"expiration":1784388720000,"expired":false,"signatures":2},"signerWeight":1,"approval":{"txId":"9c1...","contractType":"TransferContract","operation":"Transfer TRX","from":"TQkXm4vN8pR2sD6fWbYc3LhJa9Ee5Zt7Uw","to":"TBy6mQ7Y3nJ8sD2fWpXk4LhVc9Ra1Zt5Ub","rawAmount":"1000000000","permission":{"id":2,"name":"finance","threshold":2},"currentWeight":2,"missingWeight":0,"thresholdReached":true,"approved":[{"address":"TQkXm4vN8pR2sD6fWbYc3LhJa9Ee5Zt7Uw","weight":1},{"address":"TXe4Kd8nP2rF9gH5jL3mV6cW1bN7yS0aQz","weight":1}],"expiration":1784388720000,"expired":false,"signatures":2}},"meta":{"durationMs":310,"warnings":[]},"chain":{"family":"tron","network":"tron:nile","chainId":"nile"}}

Output

The two input modes return different shapes.

--hex / --file (artifact signing):

Field Type Meaning
kind string "tx-sign"
signer string The address that just signed
hex string The transaction hex with the new signature appended
checked boolean Whether the online permission/approval verification ran — false under --offline
transaction object Locally decoded summary: txId, contractType, operation, from, to, rawAmount, permissionId (a scalar — no group name or threshold), expiration, expired, signatures (count)
signerWeight number The signer's weight in the group. Present only when checked is true
approval object Authoritative online approval state, same shape as tx approvals data. Present only when checked is true

transaction is always present and identical in both modes, so a consumer can read it unconditionally; test checked before reaching for approval.

--transaction (direct JSON signing) returns the same shape tx send --sign-only emits, so consumers need no branch:

Field Type Meaning
kind string "sign"
mode string "sign-only"
address string Address that produced the signature
txId string Transaction id
signed object The signed transaction — exactly what tx broadcast accepts

No fee is reported for --transaction: nothing was estimated, because the transaction was not built here.

Exit status

0 success · 1 execution failure (tx_integrity — the three payload representations disagree, invalid_transaction, tx_expired, not_authorized — this account isn't in the group's key list, already_signed, watch_only_no_signer, auth_failed, signing_rejected, rpc_error) · 2 usage error (invalid_value, missing_option).

See also

tx approvals · tx broadcast · tx multisig · permission show