Appearance
EVM ECDSA
EVM-family signing uses threshold ECDSA over secp256k1. Strict Router A/B threshold-PRF derivation produces additive client and server scalar shares:
text
x = x_client + x_server mod n
X = X_client + X_server
ethereum_address = address(X)ECDSA does not use the Ed25519 Streaming Yao circuit. Deriver A and Deriver B own role-local threshold-PRF material during lifecycle operations. The browser worker receives the client share, and SigningWorker receives the activated server share and one-use presignature state.
Address invariant
Tempo, Arc, Ethereum, and future EVM-family targets share one threshold owner address for the same wallet, RP, signing root, and key version.
Concrete chain targets may partition sessions, budgets, nonce lanes, and transaction serialization. They cannot partition the persistent ECDSA key or the displayed owner address.
Normal signing
Normal ECDSA signing uses Router admission plus SigningWorker participation. Deriver A and Deriver B remain outside the signing hot path. Pool refill and normal signing use strict Router A/B routes and one-use presignature state.
Execute an EVM-family transaction
Application code supplies the chain target and typed transaction. Nonce allocation remains inside the signing engine.
Runnable TypeScript example
ts
import { logWalletEvents, type SeamsWeb } from '@seams/wallet';
// EIP-1559 on any configured EVM chain. `seams.tempo` mirrors this API for
// Tempo's EIP-2718 typed transactions; the two stay separate because the
// envelopes and the signed results differ.
export async function executeEvmTransaction(seams: SeamsWeb): Promise<string> {
const execution = await seams.evm.executeTransaction({
// A configured network slug. The RPC endpoint comes from that chain, and
// `tx.chainId` is filled in from it. Omitting `walletSession` targets the
// authenticated wallet.
chainTarget: 'ethereum-sepolia',
request: {
chain: 'evm',
kind: 'eip1559',
senderSignatureAlgorithm: 'secp256k1',
tx: {
maxPriorityFeePerGas: 1n,
maxFeePerGas: 1n,
gasLimit: 21_000n,
to: '0x1234567890abcdef1234567890abcdef12345678',
value: 0n,
data: '0x',
},
},
options: { onEvent: logWalletEvents() },
});
console.log('transaction hash', execution.txHash);
return execution.txHash;
}