Login with ZK Email: OAuth API

ZK Email Oauth SDK Documentation


The ZK Email Oauth SDK provides a set of functionalities to interact with a decentralized, email-based OAuth-based authentication system. It allows users to perform OAuth sign-in and sign-up operations for natural usernames via an email, and broadcast transactions on-chain via an ephemeral key for that browser session.

Unlike Email Wallet, the Oauth SDK only asks for one one email reply at the start of each user login in order to login on that device, and then you can execute all further transcations in the background via the ephemeral key.

You can see example frontend code here for more specific implementation details, and the deployed version here.


To install the SDK, use the following command:

npm install @zk-email/oauth-sdk

Importing the SDK

To use our SDK, import OauthClient and related libraries into your project as follows:

import { OauthClient } from "@zk-email/oauth-sdk";
import { PublicClient, createPublicClient, Address } from 'viem';

Creating an Instance of OauthClient

To create an instance of OauthClient, you need to provide the following parameters:

  • client: An instance of PublicClient.

  • coreAddress: The address of the core contract.

  • oauthAddress: The address of the OAuth contract.

  • relayerHost: The host URL of the relayer service.

The constructor can also take the following optional arguments. You can set them to skip calling the setup and waitEpheAddrActivatedfunctions when the user's browser local storage stores a cached ephemeral key.

  • userEmailAddr: The user's email address (optional).

  • userWalletAddr: The user's wallet address (optional).

  • ephePrivateKey: The ephemeral private key (optional).

  • epheAddrNonce: The nonce when the ephemeral private key is registered (optional).


const publicClient = createPublicClient({
        chain: baseSepolia, // Chain ID
        transport: http("https://sepolia.base.org"), // Transport URL
const coreAddress: Address = '0xb6BA1Fa0A02c62CDaB29dD6d79835Dc817a0c8c0'; // Your core contract address. This prefilled default is already deployed on Base Sepolia
const oauthAddress: Address = '0x63B5822131BA821Eb0B57a45d35Ee620253f87f0'; // Your OAuth core contract address, deployed on Base Sepolia
const relayerHost: string = "https://oauth-api.emailwallet.org"; // Your relayer host; this one is public and deployed on Base Sepolia

const oauthClient = new OauthClient(publicClient, coreAddress, oauthAddress, relayerHost);


When an instance of OauthClient is created, a new ephemeral ECDSA key is internally generated.


To sign-up/sign-in the user's account and broadcast transactions via an ephemeral key, you just need to call three functions: setup, waitEpheAddrActivated, and oauthExecuteTx.

Step 1. setup

Signs up a new user or signs in an existing user with the given username and configurations of the ephemeral key. It requests the relayer service to send an email to the given user's email address, allowing the user to sign up or sign in the account by replying to the sent email. This reply email will simultaneously creates a new Email Wallet account if the user has not created it.


  • userEmailAddr: The email address of the user.

  • username: The desired username for the new user. This is mandatory for the sign up and optional for the sign in. If the username taken by the existing user is different from the given one, the relayer service automatically sends an email to sign in the taken username (not the given username).

  • expiryTime: The expiry time for the ephemeral key (optional). If you set no time limitation, you can set expiryTime to null.

  • tokenAllowance: Array of token allowances that the ephemeral key can consume (optional). Each element in the array is defined as [number, string], where the first and second ones, respectively, denote token amount and names to be displayed in the email subject field. You can set at most three token allowances.


  • Promise<number>: A number of request ID that the relayer service issues for each sign-up/sign-in request.


// Case 1: the user of 'user@example.com' sign-ups/sign-ins 'newUserName' and activates the ephemeral key forever with no token allowance. 
const requestId = await oauthClient.setup('user@example.com', 'newUserName', null, null);
// Case 2: the user of 'user@example.com' sign-ups/sign-ins 'newUserName' and activates the ephemeral key until timestamp '1720489011' with token allowances up to 3 ETH and 100 USDC. 
const requestId = await oauthClient.setup('user@example.com', 'newUserName', 1720489011, [[3, "ETH"], [100, "USDC"]]);
// Case 3: the user of 'user@example.com' sign-ins the username that the user already took and activates the ephemeral key until timestamp '1720489011' with token allowances up to 3 ETH and 100 USDC.
const requestId = await oauthClient.setup('user@example.com', null, 1720489011, [[3, "ETH"], [100, "USDC"]]);

Step 2. waitEpheAddrActivated

Waits until the ephemeral key corresponding to the given request ID is activated on-chain, i.e., the proof of the user's email is processed on-chain. Before calling this function, please ensure that the setup function is already called.


  • requestId: The ID number that the relayer service issued for each sign-up/sign-in request.


  • Promise<boolean>: A true value is returned when the corresponding ephemeral key is activated.


const isActivated = await oauthClient.waitEpheAddrActivated('your-request-id');

Step 3. oauthExecuteTx

Executes a transaction on behalf of the authenticated user. Before calling this function, please ensure that the waitEpheAddrActivated function is already called.


  • target: The target address to be called by the Email Wallet contract .

  • data: The data payload when the Email Wallet contract calls target.

  • ethValue: The amount of Ether to send (optional).

  • token_amount: The amount of ERC20 tokens to send (optional). This value must be equal to that of the amount argument when the Email Wallet contract calls any of transfer, transferFrom, and approve functions in an ERC20 token as target; otherwise, it can be omitted.


  • Promise<string> an executed transaction hash.


const txHash = await oauthClient.oauthExecuteTx('0xTargetAddress', '0xDataPayload', null, null);
console.log(`Transaction Hash: ${txHash}`);


When the token_amount is larger than zero, the Email Wallet contract deducts its value from the allowance of target. If the deducted value is less than zero, it returns an error. Similarly, when the ethValue is larger than zero, that contract deducts its value from the allowance of the Wrapped ETH (WETH) address because the contract converts all incoming native ETH into WETH.

Error Handling

Ensure to handle errors appropriately when calling the SDK functions. For example:

try {
  await oauthClient.oauthExecuteTx('0xTargetAddress', '0xDataPayload', null, null);
} catch (error) {
  console.error('Error requesting email authentication:', error);


The OauthCore SDK provides a comprehensive set of functions to manage ZK Email based OAuth-style authentication and transactions. By following the examples provided, you can easily integrate these functionalities into your application.

For more detailed information, refer to the source code or ask questions in the ZK Email telegram.

This documentation should help users understand how to create an instance of the OauthClient SDK and use its various functions effectively.

Last updated