Privy isn’t a wallet itself, but serves as an essential wallet infrastructure that can be integrated seamlessly into any application. Its primary function is to offer more tailored flows for decentralized applications (dApps) or even blockchain wallets alike, solving the user onboarding and key management problem.

Users can easily login with a number of different platforms such as Twitter or Google mail. An Etherspot smart contract wallet is then created for them and they are ready to interact with your dapp.

Start by installing the Privy packages:

npm install @privy-io/react-auth

We’ll take a look at two files here, index.js and App.js

To use Privy in production you will need to request an appId.

For testing purposes you can use their test appId like we do in this tutorial.


Here we import the Privy Provider component and add some values.

Wallets are not created by default for social logins so we must set createPrivyWalletOnLogin to true.

import React from 'react';
import ReactDOM from 'react-dom/client';
import './index.css';
import App from './App';
import { PrivyProvider } from '@privy-io/react-auth';

const root = ReactDOM.createRoot(document.getElementById('root'));
      onSuccess={(user) => console.log(`User ${} logged in!`)}
      <App />


In this file we’ll import both the Privy and Etherspot hooks we need, and return them below. Once we have logged in via Privy, we’ll pass the provider which is obtained from the Privy wallet, and use this to generate our Etherspot smart contract account.

import "./App.css";
import { usePrivy, useWallets } from "@privy-io/react-auth";
import { PrimeSdk, Web3WalletProvider, Web3eip1193WalletProvider } from "@etherspot/prime-sdk";

function App() {
  const { ready, authenticated, user, login, logout } = usePrivy();
  const { wallets } = useWallets();

  // Wait until the Privy client is ready before taking any actions
  if (!ready) {
    return null;

  const etherspotLogin = async () => {
  const privyProvider = await wallets[0].getWeb3jsProvider();
  const provider = privyProvider.walletProvider;

    let mappedProvider;
    if (!isWalletProvider(provider)) {
      try {
        mappedProvider = new Web3eip1193WalletProvider(provider);
        await mappedProvider.refresh();
      } catch (e) {
        // no need to log, this is an attempt

      if (!mappedProvider) {
        throw new Error('Invalid provider!');

    const etherspotPrimeSdk = new PrimeSdk(mappedProvider ?? provider, {
      chainId: 1,


  return (
    <div className="App">
      <header className="App-header">
        {ready && authenticated ? (
              value={JSON.stringify(user, null, 2)}
            <br />
            <button onClick={logout}>Log Out of Privy</button>
        ) : (
          <button onClick={login}>Log In with Privy</button>

        <button onClick={etherspotLogin}>Log In with Etherspot</button>

export default App;