NERONERO 402
Guides

Web3Auth integration

Use Web3Auth as the EOA owner behind an ERC-4337 SCW for NERO 402 payments.

The reference Playground uses Web3Auth for social-login wallets: a user signs in with Google, X, or Discord; the resulting key is an EOA that owns an SCW; the SCW is the paying account in aa-native. This guide shows how to wire that flow into your own app.

Stack

  • @web3auth/modal — the social-login modal and embedded MPC signer.
  • wagmi + @tanstack/react-query — connector glue (Web3Auth ships a Wagmi adapter).
  • ethers — converts the Web3Auth provider into a signer the SDK can use.
  • @nerochain/x402-client + @nerochain/x402-aa — the payment surface.

Bridging Web3Auth → ethers signer

Once Web3Auth has connected, get an ethers.JsonRpcSigner from its provider:

import { BrowserProvider } from "ethers";
import { useWeb3Auth } from "@web3auth/modal/react";

const { provider } = useWeb3Auth();
const browser = new BrowserProvider(provider);
const signer = await browser.getSigner();

That signer becomes the signer argument to aaNativeSigner. The ethers.Wallet | ethers.HDNodeWallet type signature is conservative — a JsonRpcSigner works at runtime, just cast through unknown:

import { aaNativeSigner } from "@nerochain/x402-aa";
import type { Wallet as EthersWallet } from "ethers";

const aaSigner = aaNativeSigner({
  signer: signer as unknown as EthersWallet,
  rpcUrl, bundlerUrl, paymasterUrl, paymasterApiKey,
  settlementContract,
});

The Playground's useWallet hook in apps/playground/src/hooks/use-wallet.ts is the reference implementation.

Deriving the SCW address

The SCW is determined by the EOA + the canonical SimpleAccountFactory + a salt (0 is fine). Once you have the signer:

import { Presets } from "userop";

const builder = await Presets.Builder.SimpleAccount.init(
  signer,
  rpcUrl,
  { overrideBundlerRpc: bundlerUrl },
);
const scwAddress = builder.proxy?.address;

Display the SCW address to the user before they pay. Before the first UserOp the SCW does not exist on chain, but the address is still computable; this is the standard ERC-4337 counterfactual addressing pattern.

Funding flow

For testnet, the Playground exposes a "Mint 10 DEMO-USDT" button that constructs a paymaster-sponsored UserOp calling DEMO-USDT's public mint(address, uint256). The reference implementation is in apps/playground/src/components/wallet-panel.tsx.

For mainnet, send real USDT to the SCW address by any means (transfer from another wallet, exchange withdrawal, etc.). The funds sit at the counterfactual address until the SCW deploys.

What changes vs. a private-key wallet

  • Key custody. With a raw ethers.Wallet, your app holds the key. With Web3Auth, the user's social-login session backs the key (MPC-style; the key is sharded between Web3Auth and the user's session).
  • Refresh resilience. A Web3Auth-derived signer is restored automatically across page reloads as long as the user's session is alive.
  • Owner-key visibility. The application code never sees raw private-key bytes. Signing happens through the Web3Auth provider's personal_sign / eth_signTypedData_v4 interfaces.

The SCW behaves identically in both cases; the difference is purely in how the EOA owner is custodied.

On this page