Skip to content

frametx

frametx is the reference implementation: a Go command-line tool that generates keys, derives counterfactual addresses, and builds, signs, and submits frame transactions. It emits stable JSON on stdout, which makes it easy to script and easy to diff.

It is also the oracle the other SDKs are tested against. viem-8141 and web3-8141 are both differentially tested against frametx, so three independent implementations must produce byte-identical encodings.

Command Purpose
keygen Generate an ML-DSA keypair.
address Derive a counterfactual account address, offline.
send Build, sign, and submit a spend — with -deploy for the first send.
rotate Rotate a v2 account’s keys using the backup key.
account / account2 Inspect account material for v1 / v2 accounts.
eoa Build a frame transaction signed by a classical secp256k1 key.
aux The witness-segregation reference verifier.

There is deliberately no deploy command. Accounts are counterfactual, and deployment happens as part of the first send.

Terminal window
frametx keygen -variant mldsa65
{
"scheme": "ml-dsa",
"variant": "mldsa65",
"seed": "0x…",
"publicKeyKeccak": "0x…"
}

The 32-byte seed is the secret key. Everything else re-derives from it. -variant mldsa44 selects the cheaper parameter set (no Secure Enclave support).

Terminal window
frametx address -type v2 \
-activeseed 0xACTIVE \
-backupseed 0xBACKUP

-type is v2 (rotatable, recommended), fixed65, or fixed44. Add -index N to derive additional accounts from the same keys.

For hardware signers that never reveal a secret, pass the public key directly with -activepk 0x<1952 bytes> — that is all a Secure Enclave will give you.

This command performs no network access.

The first transaction from an account materialises it:

Terminal window
frametx send -deploy -accounttype v2 -variant mldsa65 \
-seed 0xACTIVE -backupseed 0xBACKUP \
-recipient 0xRECIPIENT -value 4000 -nonce 0

Fund the counterfactual address first, and make sure that funding transaction has been mined — admission reads the payer’s balance from head state.

Terminal window
frametx send -variant mldsa65 \
-seed 0xACTIVE -sender 0xACCOUNT \
-nonce 5 -recipient 0xRECIPIENT -value 100000 \
-feecap 2000000000

Read the nonce from the chain — a v2 account’s nonce is 3 after its first send, and rotations advance it by 2.

Terminal window
frametx rotate -sender 0xACCOUNT -nonce N \
-backupseed 0xOLD_BACKUP \
-newactiveseed 0xNEW_ACTIVE \
-newbackupseed 0xNEW_BACKUP

Signed by the backup key. See Rotate a key for what this does and why the active key cannot do it.

Variants that take public keys rather than seeds — -newactivepk, -newbackuppkhash, -backuppk — exist for hardware-backed and split-custody flows.

frametx historically defaults to a 1 gwei tip. Frost is fee-blind, so that tip buys nothing; pass -tipcap 0 if you care. This is the one field where frametx output and the other SDKs’ builders differ by default.

The repository ships e2e-rotate-drill.sh, a shell script that walks the entire account lifecycle against a live RPC endpoint using frametx, curl, and jq:

  1. derive the counterfactual address offline and assert eth_getCode is empty;
  2. fund it;
  3. self-deploying first send, asserting nonce 3 and both storage slots written;
  4. negative case — a corrupted signature refused at the gate;
  5. rotation via the backup key;
  6. assert the old active key is rejected, the new one spends, and the old backup is consumed.

This is the most complete worked example of the account lifecycle that exists, and it runs on a schedule against the live network.

Use frametx when you want a reference answer: a canonical encoding to compare against, or a quick manual check without writing code. Use viem-8141 or web3-8141 to build applications.