Logo
New RPC users get 35% off their first monthView the offer
OnFinality Learn
Integration & Development11 min read

Tempo Wallet: Account Model, CLI Workflows, and RPC Verification

A technical guide to the Tempo Wallet account model, the tempoctl CLI, private balances via Zones, and how to verify wallet state against Tempo RPC endpoints.

TL;DR

The Tempo Wallet is the first-party account surface for Tempo, a payments-first Layer 1 incubated by Stripe and Paradigm. It covers balances, transfers, deposits, private balances through Zones, and passkey-based sign-in, while a separate CLI (tempoctl) exposes the same account primitives to scripts and agents. This article explains the mental model behind a Tempo wallet, shows runnable CLI and JSON-RPC workflows, and describes how to verify wallet state independently of the wallet UI. It separates documented Tempo behavior from operational recommendations and from measurements you should run yourself against your own RPC endpoint.

What the Tempo Wallet actually manages

Tempo is a payments-first Layer 1 blockchain incubated by Stripe and Paradigm, positioned around stablecoin payments, stablecoin accounts, agentic payments, and institutional settlement. The Tempo Wallet at wallet.tempo.xyz is the first-party interface for that chain: it holds Tempo balances, sends and receives funds, accepts deposits through supported rails, exposes private balances under the Zones product, and centralizes account controls with passkey sign-in.

For a developer, the important distinction is between the wallet as a user-facing product and the wallet as an account abstraction over chain state. The UI shows a balance and a recent-activity feed; underneath, each wallet is an on-chain account whose balance, nonce, and authorization state can be read through a Tempo RPC endpoint. Treating those two layers separately is what makes wallet behavior debuggable.

This article is scoped to the technical mechanics: how a Tempo wallet account is structured, how the tempoctl command-line wallet maps onto it, how private balances differ from public ones, and how to verify what the UI reports. It is not a custody recommendation, and it does not assert which rails, regions, or assets are supported beyond what Tempo's own documentation states.

  • Public balance: visible on-chain and readable through standard account queries.
  • Private balance (Zones): balances and payment activity kept private with compliance controls, per Tempo's product description.
  • Account controls: passkey sign-in and access controls managed in the wallet product.
  • CLI surface: tempoctl creates wallets, manages keys, and issues HTTP requests that pay automatically.

Assumptions and prerequisites before you start

The workflows below assume you have a Tempo account or can create one, a terminal with Node.js or Python available, and access to a Tempo RPC endpoint. They also assume you understand that a wallet address is public while its key material is not, and that any command that signs a transaction must be run in an environment you control.

You need three things configured before the diagnostic steps make sense: an RPC_URL pointing at a Tempo endpoint you trust, a PRIVATE_KEY or keystore reference held outside version control, and a chain identifier so your tooling does not accidentally target a different network. If you have not yet chosen an endpoint, the endpoint selection itself is a separate decision covered by the RPC Assistant rather than by this page.

  • A Tempo RPC_URL (never commit it if it contains an API key).
  • A funded test account for write operations; read-only checks need no funds.
  • tempoctl installed if you intend to follow the CLI sections.
  • A shell with curl and jq, or a Python/Node runtime for the JSON-RPC examples.

Mental model: wallet, key, and account state

A Tempo wallet is best understood as three separable things. First, key material: the passkey or private key that authorizes actions. Second, the account: an address on Tempo whose balance and nonce are chain state. Third, the presentation layer: the wallet UI or CLI that renders that state and constructs transactions.

This separation matters because most wallet problems are layer-confusion problems. A balance that looks wrong in the UI may be correct on-chain and stale in the client. A transfer that "failed" may have been signed and broadcast but rejected by the node for insufficient funds or a nonce gap. A private balance that appears missing may simply live in a Zones context that the public balance query does not cover.

The practical rule: when the wallet UI and your tooling disagree, trust the chain query and then reconcile the client. The chain query is reproducible; the UI state is a cache.

Reading wallet state over JSON-RPC

The most reliable way to confirm what a Tempo wallet holds is to query the account directly. The example below uses standard Ethereum-compatible JSON-RPC methods, which is the shape most EVM-style tooling expects; confirm the exact method set and any Tempo-specific extensions in Tempo's own developer documentation before relying on them in production.

Replace RPC_URL with your endpoint and WALLET_ADDRESS with the address shown in the wallet. The balance is returned in the smallest unit, so divide by the token's decimals before comparing to the UI.

curl -s RPC_URL \
  -H 'Content-Type: application/json' \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "eth_getBalance",
    "params": ["WALLET_ADDRESS", "latest"]
  }' | jq

curl -s RPC_URL \
  -H 'Content-Type: application/json' \
  -d '{
    "jsonrpc": "2.0",
    "id": 2,
    "method": "eth_getTransactionCount",
    "params": ["WALLET_ADDRESS", "pending"]
  }' | jq

Scripted balance and nonce checks in Python

For repeated checks, wrap the same calls in a small script so you can diff results over time. The script below reads balance and nonce, prints them in a stable format, and fails loudly if the endpoint returns an error object instead of a result. That failure mode is common when an API key is missing or a rate limit is hit, and it is easy to mistake for a zero balance if you only print the result field.

import json, os, urllib.request

RPC_URL = os.environ["RPC_URL"]
ADDRESS = os.environ["WALLET_ADDRESS"]

def call(method, params):
    body = json.dumps({"jsonrpc": "2.0", "id": 1, "method": method, "params": params}).encode()
    req = urllib.request.Request(RPC_URL, data=body, headers={"Content-Type": "application/json"})
    with urllib.request.urlopen(req, timeout=15) as resp:
        payload = json.load(resp)
    if "error" in payload:
        raise RuntimeError(payload["error"])
    return payload["result"]

balance = int(call("eth_getBalance", [ADDRESS, "latest"]), 16)
nonce = int(call("eth_getTransactionCount", [ADDRESS, "pending"]), 16)
print(f"address={ADDRESS} balance_wei={balance} pending_nonce={nonce}")

Using tempoctl for wallet and payment workflows

Tempo also ships a command-line wallet, tempoctl, described as a CLI that creates a wallet, manages keys, and makes HTTP requests that pay automatically without API keys. That last capability is the interesting one for agents and automation: instead of embedding a credential in a script, the client pays per request from the wallet.

The exact subcommands and flags should be taken from the tempoctl repository rather than assumed. The pattern below illustrates the shape of a typical flow — create or import a wallet, inspect its address, then issue a paid request — with placeholders where your installation's syntax applies. Run tempoctl --help first and substitute the real subcommands.

# Illustrative flow — confirm subcommands with `tempoctl --help`
tempoctl wallet create --name agent-wallet
tempoctl wallet address --name agent-wallet

# Issue an HTTP request that pays from the wallet
tempoctl request GET https://example.com/paid-endpoint \
  --wallet agent-wallet \
  --max-spend 0.01

Public versus private balances in Tempo Zones

Tempo Zones are the privacy layer: per Tempo's product messaging, they let enterprises keep customer stablecoin balances and payments private while retaining compliance controls and access to liquidity. The wallet exposes this as a separate private balance alongside the public one.

Operationally, this means a single wallet can present two different views of funds. A public balance query against the account address will not reflect private balances held in a Zones context, and a private balance shown in the wallet will not appear in a naive on-chain read. When reconciling, always record which context a number came from.

The compliance angle is not incidental. Privacy that is decoupled from controls is hard to operate in regulated payments, so any integration that touches Zones should document who can view what, and should log context identifiers alongside amounts so audits can reconstruct the flow.

  • Tag every balance record with its context: public account or Zones.
  • Do not sum public and private balances into a single figure without labeling it.
  • Confirm current Zones availability and access requirements in Tempo's documentation before designing around it.

Verification procedure and results table

To verify a wallet end to end, run the following sequence and record each result. The point is not to produce a single number but to confirm that the UI, the CLI, and the RPC endpoint agree, or to localize where they diverge.

Step one: read the address from the wallet UI and from tempoctl, and confirm they match. Step two: query balance and nonce over RPC and compare to the UI. Step three: send a small transfer and confirm the nonce increments by exactly one. Step four: re-query after the transaction is included and confirm the balance delta matches the amount plus fees. Step five: if private balances are in use, repeat the balance check inside the Zones context.

Record results in a table like the one below. Leave the measured column empty until you run it; do not copy figures from any article, including this one.

  • | Check | Source A | Source B | Match? | Measured value |
  • | Address | Wallet UI | tempoctl | | |
  • | Public balance | Wallet UI | eth_getBalance | | |
  • | Pending nonce | Wallet UI | eth_getTransactionCount | | |
  • | Post-transfer delta | Expected | Observed | | |
  • | Private balance | Zones view | Zones query | | |

Troubleshooting common wallet discrepancies

Most discrepancies fall into a small set of causes. A stale UI cache shows an old balance after a confirmed transfer; refreshing or re-querying resolves it. A nonce gap leaves a transaction pending indefinitely because a prior transaction was dropped; comparing pending and latest nonces exposes it. An endpoint returning errors is misread as a zero balance when the script ignores the error field.

A fourth cause is context confusion: querying the public account when funds are held privately in Zones, or the reverse. A fifth is network confusion: pointing tooling at a different Tempo environment than the wallet uses. Each of these is diagnosable with the same two queries — balance and nonce — as long as you also record which endpoint and which context produced the answer.

  • Stale UI: re-query over RPC before assuming loss of funds.
  • Nonce gap: compare pending and latest transaction counts.
  • Silent RPC errors: always check the error field, not just result.
  • Context mismatch: confirm whether the balance is public or Zones-held.
  • Endpoint mismatch: log the RPC_URL host alongside every result.

Limitations, tradeoffs, and what this guide does not cover

This guide describes the wallet's structure and a verification methodology; it does not certify specific asset support, fee levels, or regional availability, all of which change and should be read from Tempo's documentation. It also does not benchmark RPC latency or reliability. Those are measurable, but only against your own endpoint and workload.

The tradeoff between public and private balances is real: privacy reduces the amount of state visible to naive tooling, which raises the bar for reconciliation and audit logging. Similarly, a CLI that pays automatically is convenient for agents but introduces spend-control requirements that a manual wallet does not. Both are design decisions, not defaults to accept uncritically.

Finally, the JSON-RPC examples use Ethereum-compatible method names as a working assumption. If Tempo exposes additional or different methods for Zones or payment flows, the authoritative source is Tempo's developer documentation, and your scripts should be adjusted accordingly.

Next steps for builders and operators

Once you can reproduce the verification table against your own endpoint, the next step is to make that check part of your operational routine: run it after every deployment that touches wallet logic, and alert on divergence between the UI-reported and RPC-reported balance. For teams running their own infrastructure, a dedicated Tempo node removes a shared dependency from that loop; see the dedicated node options and the RPC pricing model before sizing.

For endpoint selection specifically, the RPC Assistant covers concrete provider and network recommendations, which this page deliberately does not duplicate. If you are still deciding how to structure multi-network access, the multi-chain RPC endpoints guide and the broader networks directory are useful starting points.

  • Read the multi-chain RPC endpoints guide at /en/learn/multi-chain-rpc-endpoints-guide.
  • Compare dedicated node options at /en/dedicated-node.
  • Review RPC pricing at /en/pricing/rpc.
  • Browse supported networks at /en/networks.
  • Explore the API service at /en/api-service.

Never Worry about Infrastructure Again

OnFinality takes away the heavy lifting of DevOps so you can build smarter and faster.

Get Started