Skip to main content

Frictionless On‑Ramp with zkLogin

· 6 min read
Dora Noda
Software Engineer

How to drop wallet friction, keep users flowing, and forecast the upside

What if your Web3 app had the same seamless sign-up flow as a modern Web2 service? That's the core promise of zkLogin on the Sui blockchain. It functions like OAuth for Sui, letting users sign in with familiar accounts from Google, Apple, X, and more. A zero-knowledge proof then securely links that Web2 identity to an on-chain Sui address—no wallet pop-ups, no seed phrases, no user churn.

The impact is real and immediate. With hundreds of thousands of zkLogin accounts already live, case studies report massive gains in user conversion, jumping from a dismal 17% to a healthy 42% after removing traditional wallet barriers. Let's break down how it works and what it can do for your project.


Why Wallets Kill First‑Time Conversion

You've built a groundbreaking dApp, but your user acquisition funnel is leaking. The culprit is almost always the same: the "Connect Wallet" button. Standard Web3 onboarding is a maze of extension installations, seed phrase warnings, and crypto-jargon quizzes.

It’s a massive barrier for newcomers. UX researchers observed a staggering 87% drop-off the moment a wallet prompt appeared. In a telling experiment, simply re-routing that prompt to a later stage in the checkout process flipped the completion rate to 94%. Even for crypto-curious users, the primary fear is, “I might lose my funds if I click the wrong button.” Removing that single, intimidating step is the key to unlocking exponential growth.


How zkLogin Works (in Plain English)

zkLogin elegantly sidesteps the wallet problem by using technologies every internet user already trusts. The magic happens behind the scenes in a few quick steps:

  1. Ephemeral Key Pair: When a user wants to sign in, a temporary, single-session key pair is generated locally in their browser. Think of it as a temporary passkey, valid only for this session.
  2. OAuth Dance: The user signs in with their Google, Apple, or other social account. Your app cleverly embeds a unique value (nonce) into this login request.
  3. ZKP Service: After a successful login, a ZKP (Zero-Knowledge Proof) service generates a cryptographic proof. This proof confirms, "This OAuth token authorizes the owner of the temporary passkey," without ever revealing the user's personal identity on-chain.
  4. Derive Address: The user's JWT (JSON Web Token) from the OAuth provider is combined with a unique salt to deterministically generate their permanent Sui address. The salt is kept private, either client-side or in a secure backend.
  5. Submit Transaction: Your app signs transactions with the temporary key and attaches the ZK proof. Sui validators verify the proof on-chain, confirming the transaction's legitimacy without the user ever needing a traditional wallet.

Step‑by‑Step Integration Guide

Ready to implement this? Here’s a quick guide using the TypeScript SDK. The principles are identical for Rust or Python.

1. Install SDK

The @mysten/sui package includes all the zklogin helpers you'll need.

pnpm add @mysten/sui

2. Generate Keys & Nonce

First, create an ephemeral keypair and a nonce tied to the current epoch on the Sui network.

const keypair = new Ed25519Keypair();
const { epoch } = await suiClient.getLatestSuiSystemState();
const nonce = generateNonce(keypair.getPublicKey(), Number(epoch) + 2, generateRandomness());

3. Redirect to OAuth

Construct the appropriate OAuth login URL for the provider you're using (e.g., Google, Facebook, Apple) and redirect the user.

4. Decode JWT & Fetch User Salt

After the user logs in and is redirected back, grab the id_token from the URL. Use it to fetch the user-specific salt from your backend, then derive their Sui address.

const jwt = new URLSearchParams(window.location.search).get('id_token')!;
const salt = await fetch('/api/salt?jwt=' + jwt).then(r => r.text());
const address = jwtToAddress(jwt, salt);

5. Request ZK Proof

Send the JWT to a prover service to get the ZK proof. For development, you can use Mysten’s public prover. In production, you should host your own or use a service like Enoki.

const proof = await fetch('/api/prove', {
method:'POST',
body: JSON.stringify({ jwt, ... })
}).then(r => r.json());

6. Sign & Send

Now, build your transaction, set the sender to the user's zkLogin address, and execute it. The SDK handles attaching the zkLoginInputs (the proof) automatically. ✨

const tx = new TransactionBlock();
tx.moveCall({ target:'0x2::example::touch_grass' }); // Any Move call
tx.setSender(address);
tx.setGasBudget(5_000_000);

await suiClient.signAndExecuteTransactionBlock({
transactionBlock: tx,
zkLoginInputs: proof // The magic happens here
});

7. Persist Session

For a smoother user experience, encrypt and store the keypair and salt in IndexedDB or local storage. Remember to rotate them every few epochs for enhanced security.


KPI Projection Template

The difference zkLogin makes isn't just qualitative; it's quantifiable. Compare a typical onboarding funnel with a zkLogin-powered one:

Funnel StageTypical with Wallet PopupWith zkLoginDelta
Landing → Sign-in100 %100 %
Sign-in → Wallet Ready15 % (install, seed phrase)55 % (social login)+40 pp
Wallet Ready → First Tx~23 %~90 %+67 pp
Overall Tx Conversion~3 %≈ 25‑40 %~8‑13×

👉 What this means: For a campaign driving 10,000 unique visitors, that's the difference between 300 first-day on-chain actions and over 2,500.


Best Practices & Gotchas

To create an even more seamless experience, keep these pro-tips in mind:

  • Use Sponsored Transactions: Pay for your users' first few transaction fees. This removes all friction and delivers an incredible "aha" moment.
  • Handle Salts Carefully: Changing a user's salt will generate a new address. Only do this if you control a reliable recovery path for them.
  • Expose the Sui Address: After signup, show users their on-chain address. This empowers advanced users to import it into a traditional wallet later if they choose.
  • Prevent Refresh Loops: Cache the JWT and ephemeral keypair until they expire to avoid asking the user to log in repeatedly.
  • Monitor Prover Latency: Keep an eye on the proof-generation round-trip time. If it exceeds 2 seconds, consider hosting a regional prover to keep things snappy.

Where BlockEden.xyz Adds Value

While zkLogin perfects the user-facing flow, scaling it introduces new backend challenges. That's where BlockEden.xyz comes in.

  • API Layer: Our high-throughput, geo-routed RPC nodes ensure your zkLogin transactions are processed with minimal latency, regardless of user location.
  • Observability: Get out-of-the-box dashboards to track key metrics like proof latency, success/fail ratios, and your conversion funnel's health.
  • Compliance: For apps that bridge into fiat, our optional KYC module provides a compliant on-ramp directly from the user's verified identity.

Ready to Ship?

The era of clunky, intimidating wallet flows is over. Spin up a zkLogin sandbox, plug in BlockEden’s full-node endpoint, and watch your sign-up graph bend upward—while your users never even have to hear the word “wallet.” 😉