For the complete documentation index, see llms.txt. This page is also available as Markdown.

Privy Integration

Open and close leveraged positions from a Privy wallet — an embedded EOA via the wagmi connector, or an ERC-4337 smart account via batched userOps.

A Privy embedded wallet is an EOA and ships with a wagmi connector, so it drops into the Direct EOA flow unchanged — the vault sees an ordinary msg.sender. Enabling Privy smart wallets instead makes msg.sender an ERC-4337 account; see Smart wallets.

Both flows are verified end-to-end in the demo UI (WalletProviders.tsx, config.privy.ts, ConnectControls.tsx).


1. Wrap your app

Use Privy's WagmiProvider (from @privy-io/wagmi), not wagmi's own — it wires the connector and auto-connect.

npm install @privy-io/react-auth @privy-io/wagmi
import {PrivyProvider} from "@privy-io/react-auth";
import {WagmiProvider, createConfig} from "@privy-io/wagmi";
import {QueryClient, QueryClientProvider} from "@tanstack/react-query";
import {http} from "wagmi";
import {polygon} from "wagmi/chains";

// No `connectors` — PrivyProvider injects the wallet connector.
const wagmiConfig = createConfig({
  chains: [polygon],
  transports: {[polygon.id]: http()},
});

const queryClient = new QueryClient();

export function Providers({children}: {children: React.ReactNode}) {
  return (
    <PrivyProvider
      appId={import.meta.env.VITE_PRIVY_APP_ID}
      config={{
        defaultChain: polygon,
        supportedChains: [polygon],
        embeddedWallets: {ethereum: {createOnLogin: "users-without-wallets"}},
      }}
    >
      <QueryClientProvider client={queryClient}>
        <WagmiProvider config={wagmiConfig}>{children}</WagmiProvider>
      </QueryClientProvider>
    </PrivyProvider>
  );
}

appId is a public client identifier. Get it from the Privy dashboard.


2. Read the wallet address

The address that signs on-chain is the wallet_address you must quote for. After login, read it from wagmi:


3. Open and close

Each call is a wagmi writeContract, signed by Privy — identical to the Direct EOA flow.

The backend handles the rest — exchange order on open, proceeds on close, with position.opened / position.closed over WebSocket.


Smart wallets (Account Abstraction)

Enable Smart wallets in the dashboard and each user also gets an ERC-4337 account that becomes msg.sender. Two changes from the EOA flow:

  1. Quote for the smart account. wallet_address is client.account.address (the contract that signs), not the owner EOA.

  2. Submit via the smart-wallet client, batching approve + open into one userOperation.

Closing is the same with a single requestClose call.

A 4337 wallet needs a bundler (Privy dashboard). Use a keyed endpoint — https://api.pimlico.io/v2/137/rpc?apikey=<key>; the keyless public.pimlico.io blocks browser CORS. Add a paymaster for gasless opens; without one the smart account pays its own gas (fund it with POL — the first userOp also deploys it).

Verified end-to-end in the demo UI (contract/smartWalletHooks.ts, SmartWalletBridge in WalletProviders.tsx).


Notes

  • Funding. useFundWallet opens Privy's on-ramp/transfer flow; or send pUSD and a little POL to the wallet directly.

  • Export. useExportWallet reveals the embedded key for self-custody.

  • One switch. In the demo UI the whole RainbowKit ↔ Privy swap is gated on VITE_PRIVY_APP_ID; the contract layer is untouched.

Last updated