> ## 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 integration

> Authenticate users with Dynamic and create Startale smart accounts from their embedded wallet.

[Dynamic](https://www.dynamic.xyz/) 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.

<Note>
  Source: [`StartaleGroup/scs-aa-sdk`](https://github.com/StartaleGroup/scs-aa-sdk). The flow below is the one used by the Startale super-app.
</Note>

## Install

```bash theme={null}
npm install @startale-scs/aa-sdk viem \
  @dynamic-labs/sdk-react-core @dynamic-labs/ethereum
```

| Package                        | Why                                                   |
| ------------------------------ | ----------------------------------------------------- |
| `@startale-scs/aa-sdk`         | The AA SDK itself.                                    |
| `viem`                         | Chain and transport utilities.                        |
| `@dynamic-labs/sdk-react-core` | Dynamic React provider and hooks.                     |
| `@dynamic-labs/ethereum`       | EVM connectors and the `isEthereumWallet` type guard. |

## 1. Wrap the app in `DynamicContextProvider`

```tsx providers.tsx theme={null}
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>
  )
}
```

| Symbol                     | Source                         | Role                                                                         |
| -------------------------- | ------------------------------ | ---------------------------------------------------------------------------- |
| `DynamicContextProvider`   | `@dynamic-labs/sdk-react-core` | Top-level provider that exposes the user's wallet, session, and login state. |
| `EthereumWalletConnectors` | `@dynamic-labs/ethereum`       | Enables 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.

```tsx useStartaleFromDynamic.ts theme={null}
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
}
```

| Symbol                            | Source                         | Role                                                                       |
| --------------------------------- | ------------------------------ | -------------------------------------------------------------------------- |
| `useDynamicContext`               | `@dynamic-labs/sdk-react-core` | Hook exposing `primaryWallet`, session, and auth state.                    |
| `isEthereumWallet`                | `@dynamic-labs/ethereum`       | Type guard ensuring `primaryWallet` exposes EVM methods.                   |
| `primaryWallet.getWalletClient()` | Dynamic                        | Returns a viem `WalletClient` over the user's embedded or external wallet. |
| `toStartaleSmartAccount`          | `@startale-scs/aa-sdk`         | Builds the smart account from the wallet client.                           |
| `createSmartAccountClient`        | `@startale-scs/aa-sdk`         | Wraps the account with bundler and paymaster for sending UserOperations.   |

## 3. Send a sponsored UserOperation

```ts theme={null}
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](/aa-sdk/tutorials/portal).

## Common adjustments

<AccordionGroup>
  <Accordion title="Multiple smart accounts per signer">
    Vary the `index` parameter passed to `toStartaleSmartAccount`. Each `bigint` value produces a different counterfactual address for the same signer.
  </Accordion>

  <Accordion title="Pay gas in tokens instead of sponsoring">
    Replace `paymasterId` with `token` in `paymasterContext`. See [ERC-20 paymaster](/aa-sdk/tutorials/erc20-payment).
  </Accordion>

  <Accordion title="Use Dynamic in non-React environments">
    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.
  </Accordion>
</AccordionGroup>

## Next steps

<CardGroup cols={2}>
  <Card title="Privy integration" icon="user-check" href="/aa-sdk/auth-providers/privy">
    The same flow with Privy as the auth provider.
  </Card>

  <Card title="Smart account setup" icon="wallet" href="/aa-sdk/tutorials/smart-account-setup">
    Lift the smart account into a context provider.
  </Card>

  <Card title="Smart sessions" icon="key-skeleton" href="/aa-sdk/tutorials/smart-sessions">
    Reduce signature friction with scoped session keys.
  </Card>

  <Card title="Social recovery" icon="user-shield" href="/aa-sdk/tutorials/social-recovery">
    Add guardian-based key rotation.
  </Card>
</CardGroup>
