Local Validator Wallet

Use an encrypted node-generated wallet to lock, bond, set session keys, and declare validator intent without a browser extension.

Enroll with a local node-generated wallet

Use the local node wallet as the primary validator enrollment path. As of the October 23, 2026 operator correction, it is the only path with successful validator deployment reported for ordinary users. MetaMask/Talisman enrollment is unverified or known-failing; browser wallet connection, balances and network setup do not prove enrollment support.

It signs the same native runtime transactions used by the managed validator setup: pwRoko.lock, staking.bond, session.setKeys, and staking.validate. The operator funds and controls the staking account. No administrator or sudo account is used.

The staking wallet is an ECDSA account generated by roko-node key generate. It is separate from the node's seven session keys and P2P identity. This tool captures the exact raw node seed in memory, checks its public key, and saves only password-encrypted keyring JSON. It does not print a seed or mnemonic. Never substitute a session key, node key, or Ethereum-derived mnemonic.

Addresses you will use

Use testnet chain ID 52370. Your wallet's public account is 0x followed by 40 hexadecimal characters. Copy it from the account field printed by create; use that same value when funding the wallet and for every --account argument below. The tool checks that it matches the encrypted wallet.

For reference, pwROKO is 0x0000000000000000000000000000000000000500 (symbol pwROKO, 18 decimals), and the EVM staking precompile is 0x0000000000000000000000000000000000000700. Do not put either precompile in --account or send funds to it. This command uses native runtime calls and has no contract-address option. You do not need to import a token, enter an ABI, or approve an EVM spender to use this workflow. See the address and function reference.

Verification status

Current operator guidance (October 23, 2026): local node-wallet deployment has succeeded for ordinary users. This is the enrollment procedure to follow. MetaMask/Talisman enrollment remains unverified or known-failing. Successful candidate registration still requires separate activation, election and finalized-authorship checks.

Historical September 13, 2026 verification: encryption/recovery tests, the existing installer smoke suite, and read-only call encoding against testnet runtime 286 passed; funded end-to-end enrollment was unverified at publication. That historical test boundary does not override the current operator guidance or qualify any additional release, architecture or runtime.

1. Open the validator terminal and check software

First complete the guided validator-candidate installation. Use your hosting provider's SSH login to open a terminal on the validator host. Keep this terminal open for the steps below. Commands run as your normal Linux user unless a step explicitly says sudo.

Check the tools before installing the optional wallet command:

python3 --version
node --version
npm --version
git --version
/usr/local/bin/roko-node --version

Expect Python 3.x, Node v22.x or newer, version numbers for npm and Git, and a ROKO node version. If a command says command not found, install that prerequisite before continuing. On Ubuntu/Debian, Git and Python are available with sudo apt update followed by sudo apt install git python3. For Node.js, use the official installation instructions and choose a supported LTS version 22 or newer with npm. Reopen the SSH session if the installer asks, then repeat the version checks. Do not assume the distribution's default Node package meets this minimum.

If your verified node binary is somewhere else, replace /usr/local/bin/roko-node with that absolute path in this guide. A Docker-only installation also needs a verified matching host binary for wallet creation; follow the node installation guide's binary verification procedure first.

The wallet command is available in the source checkout; the existing signed enrollment bundle does not install its Node.js dependencies. Use a dedicated checkout pinned to the reviewed wallet release:

mkdir -p "$HOME/roko-tools"
git clone https://github.com/Roko-Network/roko-edge-tools.git "$HOME/roko-tools/validator-wallet"
cd "$HOME/roko-tools/validator-wallet"
git checkout --detach 12c77a5d6ff276e271e587659946edaefde277a2
npm ci --ignore-scripts --prefix wallet
npm test --prefix wallet
bin/roko-validator-wallet --help

The tests must pass and help must list create, plan, and enroll. If the clone destination already exists, do not delete it or overwrite files: use that checkout only after checking git status and its revision with git rev-parse HEAD. Save your own changes before updating a checkout. For each later SSH session, return here with cd "$HOME/roko-tools/validator-wallet" before running a bin/ command.

Run the command as your normal operator user on the validator host. RPC must listen only on loopback, with WebSocket enabled on 127.0.0.1:9944. Do not publish or forward RPC. Signing works with the node's normal Safe RPC policy; only session-key generation uses the existing guarded key-management window.

2. Create and fund the staking wallet

install -d -m 700 "$HOME/.local/share/roko-validator"
bin/roko-validator-wallet create \
  --binary /usr/local/bin/roko-node \
  --wallet "$HOME/.local/share/roko-validator/staking-wallet.json"

Enter a unique password of at least 12 characters at the hidden prompt. The command prints JSON containing account, wallet, and encrypted: true. The account value is your public 0x address and refuses to overwrite an existing wallet. Back up the encrypted wallet and keep its password separately. Losing either prevents future staking transactions and withdrawal. Do not commit wallet files or send them to support.

Fund the printed address with native ROKO on testnet (chain ID 52370). Enrollment defaults to 50 ROKO bonded and also needs native ROKO for each transaction fee and the existential deposit. The tool checks the current minimum validator bond and estimates each next transaction fee. If the minimum exceeds 50 ROKO, use --stake-planck with the desired integer amount in base units; one ROKO is 1000000000000000000 planck.

This first version creates a new staking wallet. It does not migrate funds, import Talisman accounts, or replace an existing validator's wallet. Fund the new address through your existing funded account or the testnet funding route.

3. Prepare the public session package

Install and verify the signed enrollment helper using the current installer and its signed checksum manifest before following the guarded key workflow.

Complete the node readiness and guarded session-key workflow on this same node. Restore and verify Safe RPC before proceeding. The public roko-validator-enrollment.json must be fresh and identify this node, runtime, and testnet genesis:

0x0a2296f8f036f71437e8f6f2028ccbf0dc3dd6b3de9120fc15e43789c794e8bb

Keep the node in its non-authoring candidate configuration during enrollment. Use the existing session tuple when refreshing an expired package; do not rotate keys to retry a transaction.

4. Review the next transaction

Keep the enrollment file in this checkout, or replace its filename in every command with its actual absolute path. Confirm it is present:

pwd
ls -l roko-validator-enrollment.json

pwd should end in /roko-tools/validator-wallet. If ls reports No such file or directory, find the output path from the session-key workflow and use that path. This JSON contains public session facts; it is different from the encrypted staking-wallet.json and cannot replace it.

Replace 0xYOUR_40_HEX_CHARACTER_ACCOUNT below with the complete account value printed at wallet creation. It is a placeholder, not an example account to fund. Copy the whole block after replacing it:

bin/roko-validator-wallet plan \
  --wallet "$HOME/.local/share/roko-validator/staking-wallet.json" \
  --account 0xYOUR_40_HEX_CHARACTER_ACCOUNT \
  --enrollment roko-validator-enrollment.json

plan never opens the wallet or asks for its password. It checks the current loopback listener, chain, runtime metadata, node identity, synchronization, advancing finality, live minimum bond, pending nonce, and finalized staking state. It prints the next needed call, encoded call data, estimated fee, and native balance requirement. Review the full sequence: lock enough ROKO to reach the requested pwROKO balance, bond that amount with rewards set to Staked, register the package's session tuple with the current empty proof, then declare validator intent with zero commission and nominations unblocked. Existing validator preferences are preserved. Estimates are refreshed before each call; fee reserves are estimates, not a guarantee of future network fees.

The JSON fields nextCall, estimatedFeePlanck, nativeRequiredPlanck, and nativeFreePlanck explain the next step. Amounts here are integer base units: 50000000000000000000 is 50 ROKO. plan checks one next transaction; rerun it after funding if it reports insufficient balance. It does not reserve funds.

5. Sign and wait for finalization

This next command submits transactions. Continue only after checking the account, network, stake amount, and plan. The default is 50 ROKO; if you choose a different --stake-planck amount, use the same value for both plan and enroll. Keep the SSH session open while it runs.

bin/roko-validator-wallet enroll --execute \
  --wallet "$HOME/.local/share/roko-validator/staking-wallet.json" \
  --account 0xYOUR_40_HEX_CHARACTER_ACCOUNT \
  --enrollment roko-validator-enrollment.json

The hidden password unlocks the wallet locally. Its derived address must match --account. Each submission reports its public transaction hash, waits for finalization, prints the finalized block receipt, then rechecks state before the next step. Avoid other transactions from this account during enrollment.

6. Confirm completion or recover from an interruption

  • Insufficient funds: fund the displayed account, then rerun plan.
  • Pending nonce or timeout: a transaction may still finalize. Inspect its explorer status and wait for pending activity to settle before rerunning. Do not create a second wallet or blindly resubmit from another tool.
  • Dispatch failure: inspect the transaction's explorer receipt and resolve the runtime error. Earlier finalized calls remain effective.
  • Expired package or runtime change: refresh the package with the same session keys using the guarded workflow, then rerun plan.
  • Different registered keys or insufficient existing bond: stop and review the existing validator. This enrollment command does not rotate keys, increase existing bonds, change commissions, unbond, or withdraw.

A successful enrollment prints "status":"candidate registration finalized" and a finalizedHash. Save the public transaction/block hashes so you can look them up in the explorer. This does not mean the validator is active.

If your SSH connection drops, reconnect, return to the checkout with cd, and run plan before deciding whether to resume. Do not rerun create. For support, share the command name, exact error, public account and transaction hash; leave out wallet files and passwords.

Rerunning checks finalized state and skips completed steps. A finalized candidate registration does not mean the node has been elected or authored a block. Continue the join and monitor procedure, verify the session tuple and custody on the node, then enable validator mode according to that procedure. Confirm election and authorship separately.

Before enabling validator mode, use the enrollment command from this updated source checkout to verify finalized state and local custody under Safe RPC:

bin/roko-validator-enroll \
  --rpc http://127.0.0.1:9944 \
  --check-account 0xYOUR_40_HEX_CHARACTER_ACCOUNT \
  --qualification reviewed-public-qualification.json \
  --expected-session-keys "$(python3 -c 'import json; print(json.load(open("roko-validator-enrollment.json"))["session"]["encodedKeys"])')"

The tuple is public. reviewed-public-qualification.json contains only sourceCommit (40 hex characters), imageDigest (a 0x SHA-256 digest, or null for native), binarySha256, genesisHash, specName, specVersion, and metadataHash. Obtain these from reviewed release/image qualification; never invent identities. The CLI checks the local binary and live genesis, runtime and metadata against them. Verify source/image provenance through the reviewed signed release out of band; this RPC cannot attest build provenance. Without qualification, the handoff is blocked. The public roko.validator-transition-status.v2 receipt has a canonical SHA-256 digest checked by validator_receipt.verify_receipt. Its evidence records only public material: the submitted tuple, finalized session.nextKeys, the active set, BABE/temporal/producer indices and the queued-set evidence below.

Nodes that include roko_network#456 add the raw public queuedValidators and activeValidators to Safe readiness. The receipt then records queuedSetEvidence: "Safe readiness RPC queuedValidators/activeValidators (raw public sets)", the candidate's queuedCandidate entry (account plus seven public keys in protocol order), queuedTupleMatchesLocal (the queued keys compared with the locally held public tuple) and candidateInReadinessActiveSet. A waiting candidate that has not yet been elected is absent from the queued set. This is recorded (queuedSetEvidence ends with candidate not yet queued) and does not block the handoff, because pre-activation safety rests on the finalized nextKeys proof. Once the account is queued, the gate fails with Queued session tuple mismatch, naming the differing keys, when the queued tuple is not the local one. Older nodes expose only queuedKeysMatch; the receipt records queuedSetEvidence: "unavailable (node predates readiness queued set)" with null queued fields, and the gate is unchanged.

Require safeToEnableValidatorMode: true; keep Safe RPC enabled. This pre-activation handoff gate now also requires seven matched keys, configured candidacy, a synced node, and at least two mapped active-authority temporal peers; generic P2P peers do not count. Before activation, a null producer index is expected and does not block the handoff; on older nodes without the raw queued set, queuedKeysMatch: false does not block it either. Once active, safeToAuthor additionally requires exact active keys, matching BABE/temporal/producer mappings, converged time and a canonical finalized block attributed to the expected producer. Generic P2P peers and system_nodeRoles: Authority are separate diagnostics, not readiness evidence. Neither authorship nor retirement is implied by pre-activation handoff. Follow failedStages; never use --timesync-min-sources 1 as remediation without a separately reviewed protocol policy authorizing that profile. A not-ready result is not permission to skip custody verification. Older signed tool bundles may lack the Safe readiness fallback; use the source command above until a new signed bundle includes it.