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.

Dynamic provides embedded wallets with social login, email, MPC, and WebAuthn key custody. It exposes a viem WalletClient directly through primaryWallet.getWalletClient(), which slots straight into toStartaleSmartAccount as a signer.
Source: StartaleGroup/scs-aa-sdk. The flow below is the one used by the Startale super-app.

Install

npm install @startale-scs/aa-sdk viem \
  @dynamic-labs/sdk-react-core @dynamic-labs/ethereum
PackageWhy
@startale-scs/aa-sdkThe AA SDK itself.
viemChain and transport utilities.
@dynamic-labs/sdk-react-coreDynamic React provider and hooks.
@dynamic-labs/ethereumEVM connectors and the isEthereumWallet type guard.

1. Wrap the app in DynamicContextProvider

providers.tsx
import { DynamicContextProvider } from "@dynamic-labs/sdk-react-core"
import { EthereumWalletConnectors } from "@dynamic-labs/ethereum"

export function Providers({ children }: { children: React.ReactNode }) {
  return (
    <DynamicContextProvider
      settings={{
        environmentId: process.env.NEXT_PUBLIC_DYNAMIC_ENV_ID!,
        walletConnectors: [EthereumWalletConnectors],
      }}
    >
      {children}
    </DynamicContextProvider>
  )
}
SymbolSourceRole
DynamicContextProvider@dynamic-labs/sdk-react-coreTop-level provider that exposes the user’s wallet, session, and login state.
EthereumWalletConnectors@dynamic-labs/ethereumEnables EVM wallets (embedded and external) inside Dynamic.

2. Build the smart account from primaryWallet

Once the user is authenticated, useDynamicContext exposes primaryWallet. Guard the type with isEthereumWallet, then call getWalletClient() to get a viem WalletClient you can hand to the SDK.
useStartaleFromDynamic.ts
import { useEffect, useState } from "react"
import { useDynamicContext } from "@dynamic-labs/sdk-react-core"
import { isEthereumWallet } from "@dynamic-labs/ethereum"
import { http, createPublicClient } from "viem"
import { soneiumMinato } from "viem/chains"
import {
  createSCSPaymasterClient,
  createSmartAccountClient,
  toStartaleSmartAccount,
  type StartaleAccountClient,
} from "@startale-scs/aa-sdk"

export function useStartaleFromDynamic() {
  const { primaryWallet } = useDynamicContext()
  const [client, setClient] = useState<StartaleAccountClient>()

  useEffect(() => {
    if (!primaryWallet || !isEthereumWallet(primaryWallet)) return

    let cancelled = false
    ;(async () => {
      const walletClient = await primaryWallet.getWalletClient()

      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
    }
  }, [primaryWallet])

  return client
}
SymbolSourceRole
useDynamicContext@dynamic-labs/sdk-react-coreHook exposing primaryWallet, session, and auth state.
isEthereumWallet@dynamic-labs/ethereumType guard ensuring primaryWallet exposes EVM methods.
primaryWallet.getWalletClient()DynamicReturns a viem WalletClient over the user’s embedded or external wallet.
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 })
The user does not need ETH; gas is sponsored by the paymaster you configured in the SCS Portal.

Common adjustments

Vary the index parameter passed to toStartaleSmartAccount. Each bigint value produces a different counterfactual address for the same signer.
Replace paymasterId with token in paymasterContext. See ERC-20 paymaster.
Dynamic ships server-only utilities through @dynamic-labs/sdk-react-core/server. Use those to derive the signer, then pass it to toStartaleSmartAccount exactly the same way.

Next steps

Privy integration

The same flow with Privy 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.