toViemAccount
Adapts a secp256k1 signing session into a viem local account. Every signing method signs through session.signDigest, so signing shows no passkey prompt. The function lives in the @category-labs/mera/viem entry point, which requires viem (^2.28.0) as an optional peer dependency; the root entry point does not use viem.
Import
Section titled “Import”import { function toViemAccount(session: Secp256k1SigningSession, options?: ToViemAccountOptions): LocalAccount<"mera">
Adapts a secp256k1 signing session into a viem local account.
Each signing method hashes its input with viem's own hashers and signs the
resulting 32-byte digest with session.signDigest, so signing never shows a
passkey prompt. The account's address is the EIP-55 checksummed address of
the session key, and publicKey is the 65-byte uncompressed public key as
hex.
toViemAccount } from "@category-labs/mera/viem";import { function createSecp256k1SigningSession({ privateKey, }: CreateSigningSessionOptions): Secp256k1SigningSession
Creates a signing session from a secp256k1 private key.
createSecp256k1SigningSession } from "@category-labs/mera";import { function toViemAccount(session: Secp256k1SigningSession, options?: ToViemAccountOptions): LocalAccount<"mera">
Adapts a secp256k1 signing session into a viem local account.
Each signing method hashes its input with viem's own hashers and signs the
resulting 32-byte digest with session.signDigest, so signing never shows a
passkey prompt. The account's address is the EIP-55 checksummed address of
the session key, and publicKey is the 65-byte uncompressed public key as
hex.
toViemAccount } from "@category-labs/mera/viem";import { function createWalletClient<transport extends Transport, chain extends Chain | undefined = undefined, accountOrAddress extends Account | Address | undefined = undefined, rpcSchema extends RpcSchema | undefined = undefined, const tokens extends Tokens | undefined = undefined>(parameters: WalletClientConfig<transport, chain, accountOrAddress, rpcSchema, tokens>): WalletClient<transport, chain, ParseAccount<accountOrAddress>, rpcSchema, tokens>
Creates a Wallet Client with a given Transport configured for a Chain.
A Wallet Client is an interface to interact with Ethereum Account(s) and provides the ability to retrieve accounts, execute transactions, sign messages, etc. through Wallet Actions.
The Wallet Client supports signing over:
- JSON-RPC Accounts (e.g. Browser Extension Wallets, WalletConnect, etc).
- Local Accounts (e.g. private key/mnemonic wallets).
createWalletClient, function http<rpcSchema extends RpcSchema | undefined = undefined, raw extends boolean = false>(url?: string | undefined, config?: HttpTransportConfig<rpcSchema, raw>): HttpTransport<rpcSchema, raw>
http, function parseEther(ether: string, unit?: "wei" | "gwei"): bigint
Converts a string representation of ether to numerical wei.
parseEther } from "viem";import { const sepolia: { blockExplorers: { readonly default: { readonly name: "Etherscan"; readonly url: "https://sepolia.etherscan.io"; readonly apiUrl: "https://api-sepolia.etherscan.io/api"; }; }; blockTime?: number | undefined | undefined; contracts: { readonly multicall3: { readonly address: "0xca11bde05977b3631167028862be2a173976ca11"; readonly blockCreated: 751532; }; readonly ensUniversalResolver: { readonly address: "0xeeeeeeee14d718c2b47d9923deab1335e144eeee"; readonly blockCreated: 8928790; }; }; ... 15 more ...; verifyHash?: ((client: Client<...>, parameters: VerifyHashParameters) => Promise<boolean>) | undefined;}
sepolia } from "viem/chains";
const const privateKey: Uint8Array<ArrayBuffer>
privateKey = var crypto: Crypto
crypto.Crypto.getRandomValues<Uint8Array<ArrayBuffer>>(array: Uint8Array<ArrayBuffer>): Uint8Array<ArrayBuffer>
The Crypto.getRandomValues() method lets you get cryptographically strong random values.
getRandomValues(new var Uint8Array: Uint8ArrayConstructornew (length: number) => Uint8Array<ArrayBuffer> (+6 overloads)
Uint8Array(32));const const session: Secp256k1SigningSession
session = function createSecp256k1SigningSession({ privateKey, }: CreateSigningSessionOptions): Secp256k1SigningSession
Creates a signing session from a secp256k1 private key.
createSecp256k1SigningSession({ privateKey: Uint8Array<ArrayBufferLike>
Curve private key. Must be exactly 32 bytes and, for secp256k1, a valid
scalar.
privateKey });
const const client: { account: { address: Address; nonceManager?: NonceManager | undefined; sign?: ((parameters: { hash: Hash; }) => Promise<Hex>) | undefined | undefined; signAuthorization?: ((parameters: AuthorizationRequest) => Promise<SignAuthorizationReturnType>) | undefined | undefined; signMessage: ({ message }: { message: SignableMessage; }) => Promise<Hex>; ... 4 more ...; type: "local"; }; ... 43 more ...; extend: <const client extends { ...; } & ExactPartial<...>>(fn: (client: Client<...>) => client) => Client<...>;}
client = createWalletClient<HttpTransport<undefined, false>, { blockExplorers: { readonly default: { readonly name: "Etherscan"; readonly url: "https://sepolia.etherscan.io"; readonly apiUrl: "https://api-sepolia.etherscan.io/api"; }; }; blockTime?: number | undefined | undefined; contracts: { readonly multicall3: { readonly address: "0xca11bde05977b3631167028862be2a173976ca11"; readonly blockCreated: 751532; }; readonly ensUniversalResolver: { readonly address: "0xeeeeeeee14d718c2b47d9923deab1335e144eeee"; readonly blockCreated: 8928790; }; }; ... 15 more ...; verifyHash?: ((client: Client<...>, parameters: VerifyHashParameters) => Promise<boolean>) | undefined;}, { ...;}, undefined, undefined>(parameters: { ...;}): { ...;}
Creates a Wallet Client with a given Transport configured for a Chain.
A Wallet Client is an interface to interact with Ethereum Account(s) and provides the ability to retrieve accounts, execute transactions, sign messages, etc. through Wallet Actions.
The Wallet Client supports signing over:
- JSON-RPC Accounts (e.g. Browser Extension Wallets, WalletConnect, etc).
- Local Accounts (e.g. private key/mnemonic wallets).
createWalletClient({ account?: `0x${string}` | { address: Address; nonceManager?: NonceManager | undefined; sign?: ((parameters: { hash: Hash; }) => Promise<Hex>) | undefined | undefined; signAuthorization?: ((parameters: AuthorizationRequest) => Promise<SignAuthorizationReturnType>) | undefined | undefined; signMessage: ({ message }: { message: SignableMessage; }) => Promise<Hex>; ... 4 more ...; type: "local";} | Account | undefined
The Account to use for the Client. This will be used for Actions that require an account as an argument.
account: function toViemAccount(session: Secp256k1SigningSession, options?: ToViemAccountOptions): LocalAccount<"mera">
Adapts a secp256k1 signing session into a viem local account.
Each signing method hashes its input with viem's own hashers and signs the
resulting 32-byte digest with session.signDigest, so signing never shows a
passkey prompt. The account's address is the EIP-55 checksummed address of
the session key, and publicKey is the 65-byte uncompressed public key as
hex.
toViemAccount(const session: Secp256k1SigningSession
session), chain?: Chain | { blockExplorers: { readonly default: { readonly name: "Etherscan"; readonly url: "https://sepolia.etherscan.io"; readonly apiUrl: "https://api-sepolia.etherscan.io/api"; }; }; blockTime?: number | undefined | undefined; contracts: { readonly multicall3: { readonly address: "0xca11bde05977b3631167028862be2a173976ca11"; readonly blockCreated: 751532; }; readonly ensUniversalResolver: { readonly address: "0xeeeeeeee14d718c2b47d9923deab1335e144eeee"; readonly blockCreated: 8928790; }; }; ... 15 more ...; verifyHash?: ((client: Client<...>, parameters: VerifyHashParameters) => Promise<boolean>) | undefined;} | undefined
Chain for the client.
chain: const sepolia: { blockExplorers: { readonly default: { readonly name: "Etherscan"; readonly url: "https://sepolia.etherscan.io"; readonly apiUrl: "https://api-sepolia.etherscan.io/api"; }; }; blockTime?: number | undefined | undefined; contracts: { readonly multicall3: { readonly address: "0xca11bde05977b3631167028862be2a173976ca11"; readonly blockCreated: 751532; }; readonly ensUniversalResolver: { readonly address: "0xeeeeeeee14d718c2b47d9923deab1335e144eeee"; readonly blockCreated: 8928790; }; }; ... 15 more ...; verifyHash?: ((client: Client<...>, parameters: VerifyHashParameters) => Promise<boolean>) | undefined;}
sepolia, transport: HttpTransport<undefined, false>
The RPC transport
transport: http<undefined, false>(url?: string | undefined, config?: HttpTransportConfig<undefined, false> | undefined): HttpTransport<undefined, false>
http(),});
const const recipient: "0x70997970C51812dc3A010C7d01b50e0d17dc79C8"
recipient = "0x70997970C51812dc3A010C7d01b50e0d17dc79C8";const const hash: `0x${string}`
hash = await const client: { account: { address: Address; nonceManager?: NonceManager | undefined; sign?: ((parameters: { hash: Hash; }) => Promise<Hex>) | undefined | undefined; signAuthorization?: ((parameters: AuthorizationRequest) => Promise<SignAuthorizationReturnType>) | undefined | undefined; signMessage: ({ message }: { message: SignableMessage; }) => Promise<Hex>; ... 4 more ...; type: "local"; }; ... 43 more ...; extend: <const client extends { ...; } & ExactPartial<...>>(fn: (client: Client<...>) => client) => Client<...>;}
client.sendTransaction: <{ readonly to: "0x70997970C51812dc3A010C7d01b50e0d17dc79C8"; readonly value: bigint;}, undefined>(args: SendTransactionParameters<{ blockExplorers: { readonly default: { readonly name: "Etherscan"; readonly url: "https://sepolia.etherscan.io"; readonly apiUrl: "https://api-sepolia.etherscan.io/api"; }; }; blockTime?: number | undefined | undefined; contracts: { readonly multicall3: { readonly address: "0xca11bde05977b3631167028862be2a173976ca11"; readonly blockCreated: 751532; }; readonly ensUniversalResolver: { readonly address: "0xeeeeeeee14d718c2b47d9923deab1335e144eeee"; readonly blockCreated: 8928790; }; }; ... 15 more ...; verifyHash?: ((client: Client<...>, parameters: VerifyHashParameters) => Promise<boolean>) | undefined;}, { ...;}, undefined, { readonly to: "0x70997970C51812dc3A010C7d01b50e0d17dc79C8"; readonly value: bigint;}>) => Promise<SendTransactionReturnType>
Creates, signs, and sends a new transaction to the network.
- Docs: https://viem.sh/docs/actions/wallet/sendTransaction
- Examples: https://stackblitz.com/github/wevm/viem/tree/main/examples/transactions_sending-transactions
- JSON-RPC Methods:
- JSON-RPC Accounts:
eth_sendTransaction
- Local Accounts:
eth_sendRawTransaction
sendTransaction({ to: "0x70997970C51812dc3A010C7d01b50e0d17dc79C8"
to: const recipient: "0x70997970C51812dc3A010C7d01b50e0d17dc79C8"
recipient, value: bigint
value: function parseEther(ether: string, unit?: "wei" | "gwei"): bigint
Converts a string representation of ether to numerical wei.
parseEther("0.01"),});
const session: Secp256k1SigningSession
session.function end(): void
Zeroes the session-owned private-key copy; later signing throws
SESSION_ENDED.
end();Parameters
Section titled “Parameters”The session is positional; options is a ToViemAccountOptions and may be omitted.
session
Section titled “session”- Type:
Secp256k1SigningSession - Required
Live secp256k1 signing session that backs the account. createSecp256k1SigningSession produces one.
options.nonceManager
Section titled “options.nonceManager”- Type:
NonceManager, from viem - Optional; when omitted the account carries no nonce manager
viem nonce manager forwarded to the account. viem clients use it to assign transaction nonces automatically.
Returns
Section titled “Returns”import type { type LocalAccount<source extends string = string, address extends Address = `0x${string}`> = { address: (CustomSource & { address: address; publicKey: Hex; source: source; type: "local"; })["address"]; nonceManager?: (CustomSource & { address: address; publicKey: Hex; source: source; type: "local"; })["nonceManager"] | undefined; sign?: (CustomSource & { address: address; publicKey: Hex; source: source; type: "local"; })["sign"] | undefined; signAuthorization?: (CustomSource & { address: address; publicKey: Hex; source: source; type: "local"; })["signAuthorization"] | undefined; ... 5 more ...; type: (CustomSource & { address: address; publicKey: Hex; source: source; type: "local"; })["type"];}
LocalAccount } from "viem";
type type ReturnType = { address: Address; nonceManager?: NonceManager | undefined; sign?: ((parameters: { hash: Hash; }) => Promise<Hex>) | undefined | undefined; signAuthorization?: ((parameters: AuthorizationRequest) => Promise<SignAuthorizationReturnType>) | undefined | undefined; signMessage: ({ message }: { message: SignableMessage; }) => Promise<Hex>; ... 4 more ...; type: "local";}
ReturnType = type LocalAccount<source extends string = string, address extends Address = `0x${string}`> = { address: (CustomSource & { address: address; publicKey: Hex; source: source; type: "local"; })["address"]; nonceManager?: (CustomSource & { address: address; publicKey: Hex; source: source; type: "local"; })["nonceManager"] | undefined; sign?: (CustomSource & { address: address; publicKey: Hex; source: source; type: "local"; })["sign"] | undefined; signAuthorization?: (CustomSource & { address: address; publicKey: Hex; source: source; type: "local"; })["signAuthorization"] | undefined; ... 5 more ...; type: (CustomSource & { address: address; publicKey: Hex; source: source; type: "local"; })["type"];}
LocalAccount<"mera">;A viem LocalAccount with source: "mera", accepted anywhere viem takes an account.
address
Section titled “address”The EIP-55 checksummed address of the session key, the same value getEvmAddress returns for session.publicKey.
publicKey
Section titled “publicKey”The 65-byte uncompressed secp256k1 public key as hex: the 0x04 prefix, then 128 hex characters.
signTransaction(transaction, options?)
Section titled “signTransaction(transaction, options?)”Serializes the transaction, signs its keccak-256 digest, and resolves to the signed serialized transaction. options.serializer replaces viem’s serializeTransaction for both steps. EIP-4844 transactions are hashed without their sidecars and serialized with them.
signMessage({ message })
Section titled “signMessage({ message })”Resolves to the EIP-191 personal-message signature for message, 65 bytes as hex.
signTypedData(typedData)
Section titled “signTypedData(typedData)”Resolves to the EIP-712 signature for the typed data, 65 bytes as hex.
signAuthorization(authorization)
Section titled “signAuthorization(authorization)”Signs an EIP-7702 authorization and resolves to the signed authorization object: the contract address, chain ID, and nonce together with the signature fields.
sign({ hash })
Section titled “sign({ hash })”Signs a 32-byte hash directly, with no additional hashing, and resolves to the 65-byte hex signature.
Errors
Section titled “Errors”SESSION_ENDED: any signing method rejects with this aftersession.end().INPUT_INVALID:signrejects with this whenhashis not exactly 32 bytes.
Signatures are low-S, which EVM chains require since EIP-2.
See also
Section titled “See also”- Send a transaction with viem: the recipe built on this adapter.
- createSecp256k1SigningSession: produces the session this adapter consumes.
- Signing sessions: how a session owns the key, and the lifecycle.