Untitled

mail@pastecode.io avatar
unknown
plain_text
a month ago
3.2 kB
2
Indexable
Never
import { useWallets } from '@privy-io/react-auth'
import {
  SmartAccountClient,
  createSmartAccountClient,
  walletClientToCustomSigner
} from 'permissionless'
import {
  SmartAccount,
  signerToSimpleSmartAccount
} from 'permissionless/accounts'
import { createPimlicoPaymasterClient } from 'permissionless/clients/pimlico'
import React, { useEffect, useMemo, useState } from 'react'
import {
  Address,
  Chain,
  Transport,
  createWalletClient,
  custom,
  http
} from 'viem'
import { base, baseSepolia } from 'viem/chains'
import { usePublicClient } from 'wagmi'

interface SmartAccountInterface {
  smartAccountClient?: SmartAccountClient<Transport, Chain, SmartAccount> | null
  smartAccount?: SmartAccount
  smartAccountAddress: string
}

export const SmartAccountContext = React.createContext<SmartAccountInterface>({
  smartAccountClient: undefined,
  smartAccount: undefined,
  smartAccountAddress: '0x0000000000000000000000000000000000000000'
})

const chain = process.env.NEXT_PUBLIC_CHAIN_ID === '8453' ? base : baseSepolia

const cloudPaymaster = createPimlicoPaymasterClient({
  chain: chain,
  transport: http(process.env.NEXT_PUBLIC_RPC_URL!)
})

export const SmarAccountProvider = ({
  children
}: {
  children: React.ReactNode
}) => {
  const [smartAccountClient, setSmartAccountClient] =
    useState<SmartAccountClient<Transport, Chain, SmartAccount> | null>(null)
  const publicClient = usePublicClient()
  const { wallets } = useWallets()
  const embeddedWallet = useMemo(
    () => wallets.find((wallet) => wallet.walletClientType === 'privy'),
    [wallets]
  )

  useEffect(() => {
    ;(async () => {
      if (
        !embeddedWallet ||
        !(await embeddedWallet.isConnected()) ||
        !publicClient
      ) {
        return
      }
      console.log('Setting up smart account')
      const ethereumProvider = await embeddedWallet?.getEthereumProvider()
      const walletClient = createWalletClient({
        account: embeddedWallet.address as `0x${string}`,
        chain: chain,
        transport: custom(ethereumProvider)
      })

      const customSigner = walletClientToCustomSigner(walletClient)

      const safeSmartAccountClient = await signerToSimpleSmartAccount(
        publicClient,
        {
          entryPoint: process.env.NEXT_PUBLIC_ENTRYPOINT! as Address,
          signer: customSigner,
          factoryAddress: process.env.NEXT_PUBLIC_FACTORY_ADDRESS! as Address
        }
      )

      const smartAccountClient = createSmartAccountClient({
        account: safeSmartAccountClient,
        chain: chain,
        transport: http(process.env.NEXT_PUBLIC_RPC_URL!),
        sponsorUserOperation: cloudPaymaster.sponsorUserOperation
      })

      setSmartAccountClient(smartAccountClient)
    })()
  }, [embeddedWallet, publicClient])

  return (
    <SmartAccountContext.Provider
      value={{
        smartAccountClient: smartAccountClient,
        smartAccount: smartAccountClient?.account,
        smartAccountAddress:
          smartAccountClient?.account.address ??
          '0x0000000000000000000000000000000000000000'
      }}
    >
      {children}
    </SmartAccountContext.Provider>
  )
}
Leave a Comment