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

Non-Custodial Hardware Wallet: Architecture, Signing Workflows, and Verification

A technical guide to how non-custodial hardware wallets isolate keys, sign transactions, and connect to RPC infrastructure, with reproducible verification procedures.

TL;DR

A non-custodial hardware wallet is a dedicated signing device that stores private keys in an isolated element and requires physical confirmation for every transaction, while the host computer or phone only broadcasts already-signed payloads. This article explains the key-isolation model, the signing and broadcast workflow, how the device interacts with RPC endpoints, and how to verify that a transaction was signed locally and transmitted correctly. It also covers troubleshooting, tradeoffs, and reproducible measurement procedures so you can validate your own setup rather than rely on vendor claims.

Direct answer and scope

A non-custodial hardware wallet is a physical device that generates and stores private keys in a secure element or isolated microcontroller, never exposing the seed phrase to the host operating system. The host (desktop app, browser extension, or mobile app) constructs an unsigned transaction, sends it to the device for review, and receives a signed payload back. The host then broadcasts that signed payload to a blockchain node through an RPC endpoint.

This article covers the architecture, the signing workflow, how to verify that signing happened on-device, how the device's host software talks to RPC infrastructure, and how to troubleshoot common failures. It does not recommend a specific hardware vendor or a specific RPC provider; for concrete endpoint choices, use the RPC Assistant.

  • Assumes you already own or are evaluating a hardware wallet that supports the chain you care about.
  • Assumes basic familiarity with public/private key pairs and transaction broadcasting.
  • All code uses placeholders such as RPC_URL and PRIVATE_KEY; never paste a real seed phrase into any script.

Prerequisites and assumptions

Before running any verification procedure, confirm that your device firmware is current, that the vendor's companion app is installed from an official source, and that you have a funded test account on a testnet or a small-value mainnet account. You also need a working RPC endpoint for the target chain; you can review supported networks on the OnFinality networks page and compare endpoint options through the RPC API service.

The procedures below assume the host machine has Python 3.10+ or Node.js 18+ and that you can install packages. They do not assume any specific hardware model, because the signing interface differs by vendor. Where a vendor-specific step is required, the procedure describes what to look for rather than a hard-coded command.

Key isolation model: what the device actually protects

The security value of a non-custodial hardware wallet comes from separating key material from the general-purpose computer. The device generates entropy internally, derives a seed phrase, and stores it in protected memory. The host never sees the seed phrase during normal operation. When a transaction must be signed, the host sends the unsigned transaction and derivation path to the device; the device displays the destination, amount, and fee on its own screen, and the user physically confirms.

This model protects against malware on the host that tries to exfiltrate keys, but it does not protect against a user who approves a malicious transaction. It also does not protect against supply-chain attacks on the device itself, which is why firmware verification and purchasing from official channels matter. The device is a signing boundary, not a complete security system.

  • Private keys remain inside the secure element or isolated MCU.
  • The host receives only signatures and public keys.
  • Physical confirmation binds the signed payload to what the user saw on the device screen.
  • Seed backup remains the user's responsibility and is the single point of recovery.

Signing and broadcast workflow end to end

A typical flow has six stages. First, the host app queries an RPC endpoint for the account nonce, balance, and current gas parameters. Second, the host constructs an unsigned transaction object. Third, the host serializes that object and sends it to the hardware wallet over USB, Bluetooth, or a QR channel. Fourth, the device displays the decoded transaction and waits for physical approval. Fifth, the device returns a signature. Sixth, the host attaches the signature and broadcasts the raw signed transaction through the RPC endpoint.

The critical property is that the RPC endpoint only ever sees the signed transaction. It does not see the private key or the seed phrase. This means RPC provider trust is limited to availability and correct chain data, not to custody of funds. That distinction is why self-custody hardware wallets can be paired with third-party RPC infrastructure without giving up key control.

curl -s -X POST RPC_URL \
  -H 'Content-Type: application/json' \
  -d '{"jsonrpc":"2.0","id":1,"method":"eth_getTransactionCount","params":["0xYOUR_ADDRESS","pending"]}'

Constructing an unsigned transaction for device review

The host must build a transaction that the device can decode and display unambiguously. Use explicit fields rather than defaults, and verify that the chain ID matches the network you intend to use. The example below uses a placeholder RPC_URL and a placeholder address; it only reads chain data and does not sign anything.

When the transaction is ready, pass it to your vendor's signing library or CLI. The exact call differs by vendor, but the input is always the same: an unsigned transaction object plus a derivation path. The output is a signature or a signed raw transaction. Never log the seed phrase or the private key during this step.

import json, urllib.request

RPC_URL = "RPC_URL"
ADDRESS = "0xYOUR_ADDRESS"

def rpc(method, params):
    payload = json.dumps({"jsonrpc":"2.0","id":1,"method":method,"params":params}).encode()
    req = urllib.request.Request(RPC_URL, data=payload, headers={"Content-Type":"application/json"})
    with urllib.request.urlopen(req, timeout=15) as resp:
        return json.loads(resp.read())["result"]

nonce = rpc("eth_getTransactionCount", [ADDRESS, "pending"])
chain_id = rpc("eth_chainId", [])
gas_price = rpc("eth_gasPrice", [])
print({"nonce": nonce, "chain_id": chain_id, "gas_price": gas_price})

Verifying that signing happened on the device

Verification is a measurement procedure, not a trust exercise. The goal is to confirm three things: the signature was produced by the device, the signed payload matches what the device displayed, and the broadcast was accepted by the network. You can verify the first two without broadcasting by recovering the signer address from the signature and comparing it to the device's public address.

Run the procedure below against a testnet transaction. Record the recovered address, the device-displayed address, and the broadcast transaction hash. A correct setup produces a recovered address that matches the device address exactly, and a transaction hash that appears on a block explorer for the correct chain.

  • Recovered signer address equals the device's public address.
  • Device screen shows the same destination, amount, and fee as the host transaction.
  • Broadcast returns a transaction hash, not an error.
  • The hash is visible on the correct chain's explorer after inclusion.

Results table for your own verification run

Use the following table to record your own measurements. Do not fill in values from this article; the table is a template. Each row should be completed from your own testnet or small-value mainnet run, and the pass criteria are stated so you can judge the result without external benchmarks.

CheckWhat to recordPass criteria
Device addressAddress shown by the deviceMatches the address derived by the host
Recovered signerAddress recovered from the signatureEquals the device address
Displayed destinationDestination shown on device screenEquals the host transaction destination
Displayed amountAmount shown on device screenEquals the host transaction amount
Broadcast resultTransaction hash or errorHash returned and visible on explorer
RPC latencyRound-trip time for eth_getTransactionCountStable across repeated calls

How the host software talks to RPC infrastructure

The hardware wallet itself does not usually make network requests. The companion app or browser extension does. That means RPC reliability, rate limits, and chain correctness are properties of the host software's configuration, not the device. If your wallet app allows a custom RPC URL, you can point it at a dedicated endpoint for better consistency; see the dedicated node options and the RPC pricing page for capacity planning.

For multi-chain portfolios, the host may switch RPC endpoints per chain. Verify that each chain's endpoint returns the expected chain ID before signing. A mismatched chain ID is one of the most common causes of failed or misdirected transactions, and it is detectable before signing with a single RPC call.

const RPC_URL = "RPC_URL";

async function checkChain(expectedChainId) {
  const res = await fetch(RPC_URL, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ jsonrpc: "2.0", id: 1, method: "eth_chainId", params: [] })
  });
  const { result } = await res.json();
  const actual = parseInt(result, 16);
  if (actual !== expectedChainId) {
    throw new Error(`Chain mismatch: expected ${expectedChainId}, got ${actual}`);
  }
  return actual;
}

checkChain(1).then(console.log).catch(console.error);

Troubleshooting common failures

Most hardware wallet failures fall into four categories: connection, chain mismatch, nonce or fee problems, and display mismatch. Connection failures usually mean the device is locked, the cable or Bluetooth pairing is stale, or the companion app lacks permission. Chain mismatch means the RPC endpoint and the device's expected network disagree; check the chain ID before signing. Nonce problems produce replacement or stuck transactions; query the pending nonce and compare it to the last confirmed nonce. Display mismatch means the host transaction and the device screen disagree, which is a stop condition: reject the transaction and investigate.

If a broadcast fails after signing, the signed payload is still valid. You can rebroadcast it through a different endpoint without re-signing, as long as the nonce has not been consumed. Keep the raw signed transaction in a safe place until it is confirmed or replaced.

  • Device not detected: unlock the device, reopen the companion app, and try a different cable or port.
  • Chain mismatch: verify eth_chainId against the intended network before signing.
  • Stuck transaction: query pending nonce and rebroadcast or replace with a higher fee.
  • Display mismatch: reject on the device and inspect the host transaction construction.

Limitations and tradeoffs

Non-custodial hardware wallets trade convenience for key isolation. Every transaction requires physical confirmation, which is slow for high-frequency operations. Seed backup is a single point of failure: lose the seed and the device, and funds are unrecoverable. Firmware and supply-chain trust remain residual risks that no amount of RPC reliability can eliminate.

On the infrastructure side, the device does not solve RPC availability. A correct signature broadcast to an unavailable endpoint still fails to reach the network. Pairing a hardware wallet with a reliable RPC provider addresses availability, but it does not change the custody model. For teams running many signing devices, consider documenting derivation paths, chain IDs, and endpoint configurations so that recovery and audit procedures are reproducible.

Next steps

After completing a verification run, document the device address, derivation path, chain ID, and RPC endpoint for each account you manage. Test a recovery flow on a testnet before relying on it for mainnet funds. If you need to choose an endpoint for the host software, use the RPC Assistant for a concrete recommendation, and review the multi-chain RPC endpoints guide for configuration patterns. For teams standardizing on managed infrastructure, the blockchain node hosting guide covers operational considerations that complement self-custody signing.

Never Worry about Infrastructure Again

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

Get Started