Skip to main content
Get started with Dynamic’s Flutter SDK to add embedded wallets, multi-chain support, and flexible authentication (email, social login, passkeys) to your mobile app in just a few lines.
Requirements: Flutter 3.0+, Dart 3.0+, iOS 15.5+ / Android 6.0+, and a Dynamic environment ID from the Dynamic dashboard.Platform support: The Flutter SDK currently supports iOS and Android only. Web and desktop platforms are not supported at this time.
Add the Dynamic docs MCP to your AI editor first — your agent can then query the docs directly. Instructions are on the Welcome page.
Copy this prompt into your LLM (e.g. Claude, ChatGPT, Cursor) to implement Dynamic in your Flutter app.
# Flutter SDK Quickstart

## Purpose and Usage

This document provides structured quickstart information for the Dynamic Flutter SDK. It is designed to be consumed by LLMs to generate accurate installation commands and code examples based on user requirements.

**How to use this document:**

**BEFORE WRITING ANY CODE**, ask the user which path they want:

> "Would you like a **Quick start** (EVM support, zero configuration — recommended if you're just getting started) or a **Custom setup** (choose your chains and configuration)?"

Do not proceed until the user has answered. Do not assume a path.

- If the user chooses **Quick start**: follow the Quick Start Path section exactly. Do not ask any configuration questions — execute the happy path as written.
- If the user chooses **Custom setup**: follow the Custom Setup Path section and ask all configuration questions before proceeding.

---

## Quick Start Path

> Use this path when the user chooses Quick start. Execute every step in order. Do not skip steps. Do not ask configuration questions.

**Stack:** Flutter + EVM only

### Step 1 — Prerequisites

Tell the user:
- Flutter 3.0+ and Dart 3.0+ are required — verify with `flutter --version`
- iOS 15.5+ / Android 6.0+ is required
- A simulator or device must be running before Step 5 — start one now if not already running
- A Dynamic environment ID is required — get one at https://app.dynamic.xyz/dashboard/developer/api

Ask the user for their environment ID before proceeding.

### Step 2 — Install

```bash
flutter pub add dynamic_sdk dynamic_sdk_web3dart
```

### Step 3 — Initialize the SDK

In `lib/main.dart`, initialize the SDK in `main()` before `runApp()`:

```dart
import 'package:dynamic_sdk/dynamic_sdk.dart';
import 'package:flutter/material.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  DynamicSDK.init(
    props: ClientProps(
      environmentId: 'YOUR_ENVIRONMENT_ID',
      appLogoUrl: 'https://demo.dynamic.xyz/favicon-32x32.png',
      appName: 'My App',
    ),
  );
  runApp(const MyApp());
}
```

> `WidgetsFlutterBinding.ensureInitialized()` must be called before `DynamicSDK.init()`. Do not access `DynamicSDK.instance` before initialization.

### Step 4 — Set up the app with the Dynamic widget

The `dynamicWidget` **must always be present in the widget tree** — it provides the overlay for authentication UI. Without it, auth flows will not appear.

Replace the contents of `MyApp` in `lib/main.dart`:

```dart
class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'My App',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: Stack(
        children: [
          // Wait for SDK to be ready before rendering app content
          StreamBuilder<bool?>(
            stream: DynamicSDK.instance.sdk.readyChanges,
            builder: (context, snapshot) {
              final sdkReady = snapshot.data ?? false;
              return sdkReady
                  ? const HomePage()
                  : const Scaffold(
                      body: Center(child: CircularProgressIndicator()),
                    );
            },
          ),
          // dynamicWidget must always be present — handles auth UI overlay
          DynamicSDK.instance.dynamicWidget,
        ],
      ),
    );
  }
}
```

### Step 5 — Add a home page with sign in

Create `lib/home_page.dart`:

```dart
import 'package:dynamic_sdk/dynamic_sdk.dart';
import 'package:flutter/material.dart';

class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Dynamic Demo')),
      body: Center(
        child: StreamBuilder<String?>(
          stream: DynamicSDK.instance.auth.tokenChanges,
          builder: (context, snapshot) {
            final isAuthenticated = snapshot.data != null;

            if (isAuthenticated) {
              return Column(
                mainAxisAlignment: MainAxisAlignment.center,
                children: [
                  const Text('Connected!'),
                  const SizedBox(height: 16),
                  StreamBuilder<List<BaseWallet>>(
                    stream: DynamicSDK.instance.wallets.userWalletsChanges,
                    builder: (context, walletSnapshot) {
                      final wallets = walletSnapshot.data ?? [];
                      if (wallets.isEmpty) return const CircularProgressIndicator();
                      return Text('Wallet: ${wallets.first.address}');
                    },
                  ),
                  const SizedBox(height: 16),
                  ElevatedButton(
                    onPressed: () => DynamicSDK.instance.auth.logout(),
                    child: const Text('Disconnect'),
                  ),
                ],
              );
            }

            return ElevatedButton(
              onPressed: () => DynamicSDK.instance.ui.showAuth(),
              child: const Text('Connect Wallet'),
            );
          },
        ),
      ),
    );
  }
}
```

Then add the import to `lib/main.dart`:
```dart
import 'home_page.dart';
```

### Step 6 — Run the app

Make sure a simulator or device is running, then:

```bash
flutter run
```

You should see a **Connect Wallet** button. Tapping it opens the Dynamic auth UI.

### Step 7 — Dashboard configuration checklist

Before testing auth, verify these settings in your Dynamic dashboard at https://app.dynamic.xyz:

1. **Login method enabled** — go to **Sign-in Methods** and enable at least one (e.g. email OTP)
2. **Embedded wallets enabled** — go to **Wallets** and enable embedded wallets
3. **Chains enabled** — go to **Chains & Networks** and enable EVM

---

## Custom Setup Path

> Use this path when the user chooses Custom setup. Ask ALL questions below before generating any code.

**Questions to ask the user:**

1. Which chains do you want to support? (EVM, SVM/Solana — one or both)
2. Do you need social auth (Google, Apple, etc.)? If so, you will need to configure deeplinks.

**Only after receiving answers**, use the sections below to generate the correct setup.

### Package Mapping
- Core (always required): `dynamic_sdk`
- EVM: `dynamic_sdk_web3dart`
- SVM (Solana): `dynamic_sdk_solana`

### Installation
```bash
flutter pub add dynamic_sdk          # always required
flutter pub add dynamic_sdk_web3dart # if EVM selected
flutter pub add dynamic_sdk_solana   # if SVM selected
```

### SDK Initialization
Same pattern as Quick Start — `WidgetsFlutterBinding.ensureInitialized()``DynamicSDK.init()``runApp()`.

### Valid Chain Combinations
- Core only (auth only, no chain operations)
- Core + EVM
- Core + SVM
- Core + EVM + SVM

### Documentation
All docs for this SDK: https://docs.dynamic.xyz (paths starting with `/flutter/`)
Environment ID: https://app.dynamic.xyz/dashboard/developer/api

---

## Critical Reference

| Correct | Incorrect | Notes |
|---|---|---|
| `WidgetsFlutterBinding.ensureInitialized()` before `DynamicSDK.init()` | Calling `DynamicSDK.init()` first | Flutter binding must be initialized first |
| `DynamicSDK.init()` in `main()` before `runApp()` | Initializing inside a widget | Must happen before the widget tree is built |
| `DynamicSDK.instance.dynamicWidget` always in widget tree | Omitting `dynamicWidget` | Required for auth UI overlay — auth will silently fail without it |
| `StreamBuilder` on `sdk.readyChanges` before rendering app | Using SDK before ready | SDK is async — always wait for ready state |
| `DynamicSDK.instance.auth.tokenChanges` for auth state | Polling or one-time checks | Use streams for reactive auth state |

---

## Troubleshooting

### 1 — "Could not find package 'dynamic_sdk'"
Run `flutter pub get`. If that fails, try `flutter clean && flutter pub get`.

### 2 — Auth UI not appearing
`DynamicSDK.instance.dynamicWidget` is missing from the widget tree. Add it inside a `Stack` above your app content.

### 3 — Wallets not appearing after login
Wallets are created asynchronously after authentication. Use `DynamicSDK.instance.wallets.userWalletsChanges` stream to listen for updates. Also verify embedded wallets are enabled in the dashboard.

### 4 — Social auth / OAuth redirects not working
Configure your URL scheme in `ios/Runner/Info.plist` and `android/app/src/main/AndroidManifest.xml`. Whitelist your deeplink URL in the Dynamic dashboard under **Security → Whitelist Mobile Deeplink**. See https://docs.dynamic.xyz/flutter/social-authentication.

### 5 — "SDK not initialized" error
Ensure `DynamicSDK.init()` is called in `main()` before `runApp()`, and `WidgetsFlutterBinding.ensureInitialized()` is called first.

If the issue persists, check https://docs.dynamic.xyz/overview/troubleshooting/general.