Tempo Signature Integration (secp256k1 / P-256 / WebAuthn / Keychain V2)
Tempo Signature Integration (secp256k1 / P-256 / WebAuthn / Keychain V2)
Accept Tempo wallets signing with secp256k1, raw P-256, WebAuthn passkeys, or Keychain V2 access-key envelopes for EVM credits redemption on the Tempo chain.
Overview
Coinflow’s Tempo credits-redemption path accepts four signature shapes
through the same <CoinflowPurchase> integration:
- secp256k1 — the standard EVM curve used by MetaMask and any EIP-1193 wallet.
- P-256 (raw) — secp256r1 / NIST-P-256 keys signing a digest directly, without the WebAuthn envelope. Useful for non-browser signers.
- WebAuthn — P-256 keys held in a passkey authenticator (browser, OS keychain, hardware key). Coinflow accepts root WebAuthn passkey signatures for credits-only redemptions, so users do not need a separate MetaMask-style secp256k1 wallet.
- Keychain V2 access keys (
0x04) — an authorized access key signing on behalf of a root Tempo account, wrapped in a canonical Keychain V2 envelope. The wallet must register the access key on-chain via Tempo’s AccountKeychain precompile before signing — see Tempo access-key wallets (Keychain V2) below.
All four resolve through the same Coinflow checkout API. The merchant’s
<CoinflowPurchase> integration stays the same regardless of which signer
the user holds — only the bytes inside the permitCredits field differ.
Your app owns the registration / sign-in UI and passes a compatible
EthWallet adapter into <CoinflowPurchase>. Coinflow does not create or
store keys or passkeys for the merchant.
If you are also settling to a merchant contract on Tempo, your contract must be whitelisted first. See Whitelist Your Contracts.
What’s supported
Tempo access-key wallets (Keychain V2)
Tempo lets a root account authorize a separate access key to sign on its behalf, sparing users a root-passkey prompt on every transaction. Coinflow accepts these access-key signatures when the wallet emits a canonical Keychain V2 envelope:
Prerequisites
The wallet must complete the following BEFORE the customer reaches checkout — Coinflow performs only the verification step:
- Authorize the access key on-chain. The wallet submits a Tempo AA
transaction (type
0x76) carrying akey_authorizationfield, signed by the root account’s secp256k1 / P-256 / WebAuthn key. The Tempo node writes the authorization into the AccountKeychain precompile at0xaAAA…0000. See Tempo’s AccountKeychain spec for the canonical registration flow. - Sign with the access key. The wallet signs the credits-auth digest
with the registered access key, wraps the inner signature in the V2
envelope, and returns the resulting bytes through
EthWallet.signMessageas usual. - Match the registered signature type. The on-chain
signatureTyperecorded for the access key (0=Secp256k1,1=P-256,2=WebAuthn) must match the inner signature’s scheme. Mismatched types reject on-chain per Tempo’svalidate_keychain_authorizationrule.
Common failure: unregistered access key
If the wallet emits a V2 envelope without registering the access key first, Coinflow’s on-chain verification surfaces “Invalid credits auth signature” to the user. The wallet team must either:
- Implement the
authorizeKeyAA-transaction registration flow above, or - Downgrade to raw secp256k1 /
0x01P-256 /0x02WebAuthn signatures, which require no AccountKeychain registration.
Merchant integration impact
None. The merchant’s <CoinflowPurchase> integration code stays
identical — the customer’s wallet emits the V2 envelope, your EthWallet
adapter forwards the opaque bytes unchanged, and Coinflow’s contract
performs the keychain composition (TIP-1020 inner-signature recovery
followed by AccountKeychain authorization lookup) on-chain. No new SDK
parameters and no new API fields.
How it works
- Your app — hosts the registration / sign-in UI, manages the signer
session, and exposes a standard
EthWalletadapter to<CoinflowPurchase>. The adapter routes Coinflow’ssignMessagerequest to whichever signer the user chose (secp256k1, raw P-256, or WebAuthn). Nothing else in your Coinflow integration changes. - Coinflow — forwards the opaque signature bytes to Tempo’s on-chain signature-verification precompile, which accepts any of the three types. Coinflow does not need to know which type the user used.
- Networks — Coinflow supports Tempo mainnet and the Moderato testnet. Switch between them by changing the wagmi chain id — no other configuration.
Constructing each signer with viem
The snippets below show the minimum viem / viem/tempo calls to construct
each signer type. In a real merchant integration, wrap the resulting
Account (or wagmi connection) inside an EthWallet adapter — see
Adapt the wagmi session to an EthWallet
below for the WebAuthn path; the secp256k1 / P-256 paths follow the same
shape.
The snippets below generate ephemeral keys at runtime for illustration only. In production, derive keys from your secure key-management system and never commit private keys to source control.
secp256k1
Raw P-256
WebAuthn (passkey)
For production browser flows, use Tempo’s wagmi webAuthn connector with a
remote KeyManager (covered in detail below). For headless / non-browser
contexts and tests, Account.fromHeadlessWebAuthn constructs a WebAuthn
signer from a P-256 key:
Merchant integration (WebAuthn passkey reference flow)
The walkthrough below targets the WebAuthn / passkey case, which has the
most setup. The secp256k1 and raw P-256 paths reuse the same
<CoinflowPurchase> integration; only the signer backing
EthWallet.signMessage differs. For secp256k1 or P-256, use any wagmi
connector (injected, walletConnect, or a custom one wrapping a
viem/tempo Account) and skip to
Adapt the wagmi session to an EthWallet.
1. Configure the Tempo webAuthn connector in your wagmi config
Register Tempo’s WebAuthn connector alongside your existing EVM
connectors. Use a remote key manager in production. Use
KeyManager.localStorage() for demos only: it stores the credential /
public-key mapping in the browser, so clearing storage or switching
devices breaks lookup. (The passkey key material itself stays in the
authenticator.)
KeyManager.localStorage() is demo-only — ship a server-backed
KeyManager.http(url) before production. The snippet below disables the
connector entirely in production builds when VITE_TEMPO_KEY_MANAGER_URL
is missing, preventing silent fallback to browser storage.
2. Drive sign-up / sign-in through wagmi
The connector accepts a capabilities argument on connect() that
selects between registering a new passkey (sign-up) and authenticating
with an existing one (sign-in). Pass the Tempo chain id when connecting
so the connector session targets the same Tempo network Coinflow uses.
3. Adapt the wagmi session to an EthWallet for <CoinflowPurchase>
Coinflow’s iframe passes EIP-712 typed data into signMessage as a
JSON-stringified object — the same shape secp256k1 merchants already
handle. Parse the string, detect the EIP-712 shape, and route typed data
through wagmi’s useSignTypedData (which invokes the chosen connector).
Let typed-data errors surface — do not retry as personal_sign.
Compose the gate, adapter hook, and <CoinflowPurchase>:
Login signatures
The signMessage adapter from step 3 also handles Coinflow’s login
challenge. Users sign in with their Tempo signer (secp256k1, P-256, or
WebAuthn) with no extra client-side code.
Errors your users may see
The Coinflow iframe surfaces this message to the user during the Tempo signature flow:
Operational notes
- Production key storage (WebAuthn). Point
KeyManager.http(url)at a server-side key store.KeyManager.localStorage()is demo-only — it stores the credential / public-key mapping in the browser, so the app loses the mapping when browser storage is cleared or the user switches devices. - Same OpenAPI shape across all three signer types. Coinflow adds no
new request / response fields. The
permitCreditsfield carries the opaque signature bytes for whichever signer the user used.
Related documentation
- Implement Settlement to EVM Contract — baseline EVM settlement guide.
- How EVM Transactions Work — lifecycle of a Coinflow EVM transaction.
- Whitelist Your Contracts — whitelisting prerequisite for merchants settling to a contract.

