Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.startale.com/llms.txt

Use this file to discover all available pages before exploring further.

Privy provides embedded wallets with email, OAuth, and external wallet login. Privy exposes an EIP-1193 provider via wallet.getEthereumProvider(), which you wrap with viem’s createWalletClient and feed to toStartaleSmartAccount as a signer.

Install

npm install @startale-scs/aa-sdk viem @privy-io/react-auth
PackageWhy
@startale-scs/aa-sdkThe AA SDK itself.
viemChain, transport, and createWalletClient.
@privy-io/react-authPrivy React provider and hooks.

1. Wrap the app in PrivyProvider

providers.tsx
import { PrivyProvider } from "@privy-io/react-auth"
import { soneiumMinato } from "viem/chains"

export function Providers({ children }: { children: React.ReactNode }) {
  return (
    <PrivyProvider
      appId={process.env.NEXT_PUBLIC_PRIVY_APP_ID!}
      config={{
        loginMethods: ["email", "google", "wallet"],
        embeddedWallets: {
          createOnLogin: "all-users",
          showWalletUIs: false,
        },
        supportedChains: [soneiumMinato],
        defaultChain: soneiumMinato,
      }}
    >
      {children}
    </PrivyProvider>
  )
}
SettingEffect
loginMethodsWhich login flows are available to the user.
embeddedWallets.createOnLoginWhen set to "all-users", Privy creates an embedded wallet for every user automatically.
embeddedWallets.showWalletUIsDisable Privy’s own send/sign UIs so the smart account drives the UX.
supportedChains / defaultChainRestrict Privy to Soneium Minato (or soneium for mainnet).

2. Build the smart account from the embedded wallet

useWallets() returns the connected wallets. Take the first one (typically the embedded wallet), pull its EIP-1193 provider, and wrap it with viem.
useStartaleFromPrivy.ts
import { useEffect, useState } from "react"
import { usePrivy, useWallets } from "@privy-io/react-auth"
import { createPublicClient, createWalletClient, custom, http } from "viem"
import { soneiumMinato } from "viem/chains"
import {
  createSCSPaymasterClient,
  createSmartAccountClient,
  toStartaleSmartAccount,
  type StartaleAccountClient,
} from "@startale-scs/aa-sdk"

export function useStartaleFromPrivy() {
  const { authenticated } = usePrivy()
  const { wallets } = useWallets()
  const [client, setClient] = useState<StartaleAccountClient>()

  useEffect(() => {
    if (!authenticated || wallets.length === 0) return

    let cancelled = false
    ;(async () => {
      const wallet = wallets[0]
      const provider = await wallet.getEthereumProvider()

      const walletClient = createWalletClient({
        account: wallet.address as `0x${string}`,
        chain: soneiumMinato,
        transport: custom(provider),
      })

      const publicClient = createPublicClient({ chain: soneiumMinato, transport: http() })

      const account = await toStartaleSmartAccount({
        signer: walletClient,
        chain: soneiumMinato,
        transport: http(),
        index: 0n,
      })

      const paymasterClient = createSCSPaymasterClient({
        transport: http(process.env.NEXT_PUBLIC_PAYMASTER_URL!),
      })

      const smartAccountClient = createSmartAccountClient({
        account,
        transport: http(process.env.NEXT_PUBLIC_BUNDLER_URL!),
        client: publicClient,
        paymaster: paymasterClient,
        paymasterContext: {
          paymasterId: process.env.NEXT_PUBLIC_PAYMASTER_ID!,
        },
      })

      if (!cancelled) setClient(smartAccountClient)
    })()

    return () => {
      cancelled = true
    }
  }, [authenticated, wallets])

  return client
}
SymbolSourceRole
usePrivy@privy-io/react-authHook exposing authenticated, user, and login helpers.
useWallets@privy-io/react-authHook returning the user’s connected wallets.
wallet.getEthereumProvider()PrivyReturns an EIP-1193 provider for the embedded wallet.
createWalletClient / customviemWraps the EIP-1193 provider as a viem WalletClient.
toStartaleSmartAccount@startale-scs/aa-sdkBuilds the smart account from the wallet client.
createSmartAccountClient@startale-scs/aa-sdkWraps the account with bundler and paymaster for sending UserOperations.

3. Send a sponsored UserOperation

const hash = await client!.sendUserOperation({
  calls: [{ to: counterAddress, data: callData, value: 0n }],
})
const receipt = await client!.waitForUserOperationReceipt({ hash })

Common adjustments

toStartaleSmartAccount accepts an EIP-1193 provider as a signer too. You can skip createWalletClient if you do not need viem’s wallet methods elsewhere:
const provider = await wallets[0].getEthereumProvider()
const account = await toStartaleSmartAccount({
  signer: provider,
  chain: soneiumMinato,
  transport: http(),
  index: 0n,
})
wallets may contain external wallets (MetaMask, Rabby) alongside the embedded wallet. Pick the one whose walletClientType matches your needs before building the signer.
Replace paymasterId with token in paymasterContext. See ERC-20 paymaster.

Next steps

Dynamic integration

The same flow with Dynamic as the auth provider.

Smart account setup

Lift the smart account into a context provider.

Smart sessions

Reduce signature friction with scoped session keys.

Social recovery

Add guardian-based key rotation.