DEV Community

Jack Ridersor
Jack Ridersor

Posted on

How to Handle Hardware Wallet Signatures Across Networks

Build one signature request for each transaction the user must authorize, and bind each request to its own network context. A cross-chain flow may need only a source-chain signature if a service executes the destination leg; the architecture, not the number of networks shown to the user, determines the signing work.

What does “one signature per network” mean?

It means a hardware wallet signs each network’s transaction or authorization separately; it does not mean every cross-chain flow requires a signature on every network. A bridge deposit on one chain and a later claim on another are distinct operations, but the claim may be submitted by a relayer rather than signed by the user.

  • Count user-authorized transactions. A wallet signature authorizes a specific payload. Count the transactions or typed authorizations that require the user’s key.
  • Bind each payload to its domain. Include the network’s replay-protection context and the exact transaction data in the signature request.
  • Expect separate device confirmations. A wallet can streamline prompts, but bundling prompts does not combine independent chain transactions into one atomic action.
  • Model partial completion. One signature can succeed while a later request is rejected, expires, or fails on-chain.

For an integrator, “one flow” describes the product experience, not a protocol-level transaction. A quickswap swap service lets a user move and swap assets across chains in one flow; your wallet integration still needs to identify which steps actually require that user’s signature.

Why can’t one signature authorize both sides?

A signature authenticates a message under a particular key and signing scheme; it does not automatically authorize the same intent on unrelated ledgers. On EVM chains, replay-protected transactions incorporate a chain ID into the signing data, so a transaction signed for one chain is not ordinarily valid on another chain with a different ID.

Consider an EVM-to-EVM route between Arbitrum One and BNB Smart Chain. Even if the account uses the same secp256k1 key and address on both, transactions have separate chain IDs, nonces, fee markets, and execution state. If the user must make a source-chain deposit and a destination-chain call, prepare and request signatures for each; if a relayer makes the destination call, only the user-authorized source step needs their signature.

Bitcoin-to-Solana is a sharper contrast: Bitcoin spends UTXOs, commonly delivered to a hardware signer as a PSBT, while Solana signs a serialized message with Ed25519. There is no shared transaction format or signature that crosses between them. The service or protocol coordinates the route; it cannot turn the Bitcoin authorization into a Solana authorization.

How should the signing flow be built?

Derive the signature count from the route’s execution plan, then construct each request from the transaction that will actually be broadcast. For every request, track the network identifier, account, nonce or input set, destination, value, calldata or instructions, and fee parameters; do not infer a signature requirement from a chain appearing in the route alone.

For EVM transactions, check the RPC’s chain ID against the intended network before asking the device to sign, and pass the same chain context through the wallet interface. For typed data, verify the domain’s chain ID and verifying contract as well as the message: a valid signature over an unexpected approval or permit can be more consequential than a rejected transaction.

For Bitcoin, preserve the PSBT’s input and output map through signing and finalization. The signer should verify the supplied UTXOs and scripts against the spending transaction; the coordinator must not silently substitute outputs after signature collection. A missing prevout or unsupported script type may cause the device to refuse signing or prevent safe transaction review.

For Solana, the signature covers the compiled message, including its account keys, instructions, and recent blockhash. A normal recent blockhash is valid for about 150 slots, so a prompt that waits too long can become unusable; rebuild the message and collect a new signature rather than changing signed bytes after approval.

What happens when a user signs only part of the route?

Treat each signed step as an independent state transition and make retries idempotent. If a user signs the source transaction but rejects a later user-authorized destination action, the first transaction may already be final; present that as a pending or recoverable route state, not as a failed all-or-nothing transaction.

I would request signatures as late as practical, after quotes and transaction data are fixed, and persist each signed payload with its chain and route identifier. Recheck nonce, blockhash, allowance, and route state before submission; if any signed parameter is stale, rebuild and ask again. The word “quickswap” should describe the reader’s cross-chain task, never imply that separate network execution is atomic.

  • Count signatures from user-authorized transactions, not from the number of chains in the route.
  • Bind and validate every payload against its network and signer context.
  • Track partial completion, expiry, and retry state per transaction.

Top comments (0)