Skip to main content
Get started with Dynamic’s Swift SDK to add embedded wallets, multi-chain support, and flexible authentication (email, social login, passkeys) to your iOS app in just a few lines.
📱 Complete Example App: For a fully functional iOS app demonstrating all SDK features, check out our Swift SDK Example App. It includes authentication flows (email/SMS OTP, social login, passkeys), wallet management, EVM/Solana transactions, MFA, and passkey examples with SwiftUI.
Requirements: iOS 15.5+, Swift 5.9+, Xcode 14.0+, and a Dynamic environment ID from the Dynamic dashboard.
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 Swift app.
# Swift SDK Quickstart

## Purpose and Usage

This document provides structured quickstart information for the Dynamic Swift 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** (Xcode + SwiftUI, zero configuration — recommended if you're just getting started) or a **Custom setup** (choose your installation method 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:** Xcode + SwiftUI + Swift Package Manager

### Step 1 — Prerequisites

Tell the user:
- Xcode 14.0+ is required
- iOS 15.5+ deployment target is required
- 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 the SDK via Xcode

1. Open your project in Xcode
2. Go to **File → Add Package Dependencies**
3. Enter the repository URL: `https://github.com/dynamic-labs/swift-sdk-and-sample-app.git`
4. Select version `1.0.2` or later
5. Add to your app target

### Step 3 — Configure URL scheme

The SDK requires a URL scheme for authentication callbacks. Add the following to your `Info.plist`:

```xml
<key>CFBundleURLTypes</key>
<array>
    <dict>
        <key>CFBundleTypeRole</key>
        <string>Editor</string>
        <key>CFBundleURLName</key>
        <string>com.yourcompany.yourapp</string>
        <key>CFBundleURLSchemes</key>
        <array>
            <string>yourapp</string>
        </array>
    </dict>
</array>
```

> Replace `yourapp` with your app's URL scheme (e.g. `myapp`). This must match the `redirectUrl` you set in Step 4.

In the [Dynamic dashboard](https://app.dynamic.xyz), go to **Security → Whitelist Mobile Deeplink** and add the same deep link URL you will use as `redirectUrl` (e.g. `yourapp://`). Auth callbacks and social login can fail if this URL is not whitelisted.

### Step 4 — Initialize the SDK

In your `@main` App struct, initialize the SDK in `init()` before any views are rendered:

```swift
import SwiftUI
import DynamicSDKSwift

@main
struct YourApp: App {
    init() {
        _ = DynamicSDK.initialize(
            props: ClientProps(
                environmentId: "YOUR_ENVIRONMENT_ID",
                appLogoUrl: "https://demo.dynamic.xyz/favicon-32x32.png",
                appName: "My App",
                redirectUrl: "yourapp://",   // Must match your Info.plist URL scheme
                appOrigin: "https://your-domain.com"
            )
        )
    }

    var body: some Scene {
        WindowGroup {
            ContentView()
        }
    }
}
```

> All five `ClientProps` fields are required. `redirectUrl` must match the URL scheme you configured in Step 3.

### Step 5 — Build the content view

Replace the contents of `ContentView.swift`:

```swift
import SwiftUI
import DynamicSDKSwift
import Combine

@MainActor
class AuthViewModel: ObservableObject {
    @Published var isAuthenticated = false
    @Published var walletAddress: String? = nil
    private let sdk = DynamicSDK.instance()
    private var cancellables = Set<AnyCancellable>()

    init() {
        isAuthenticated = sdk.auth.authenticatedUser != nil

        sdk.auth.authenticatedUserChanges
            .receive(on: DispatchQueue.main)
            .sink { [weak self] user in
                self?.isAuthenticated = user != nil
            }
            .store(in: &cancellables)

        sdk.wallets.userWalletsChanges
            .receive(on: DispatchQueue.main)
            .sink { [weak self] wallets in
                self?.walletAddress = wallets.first?.address
            }
            .store(in: &cancellables)
    }

    func signIn() { sdk.ui.showAuth() }
    func signOut() { Task { try await sdk.auth.logout() } }
}

struct ContentView: View {
    @StateObject private var vm = AuthViewModel()

    var body: some View {
        VStack(spacing: 20) {
            if vm.isAuthenticated {
                Text("Connected!")
                    .font(.headline)
                if let address = vm.walletAddress {
                    Text(address)
                        .font(.caption)
                        .foregroundColor(.secondary)
                }
                Button("Disconnect") { vm.signOut() }
                    .foregroundColor(.red)
            } else {
                Button("Connect Wallet") { vm.signIn() }
                    .buttonStyle(.borderedProminent)
            }
        }
        .padding()
    }
}
```

### Step 6 — Run the app

Build and run in Xcode (`Cmd + R`) or via terminal:

```bash
xcodebuild -scheme YourApp -destination 'platform=iOS Simulator,name=iPhone 16' build
```

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
4. **Mobile deep link whitelisted** — go to **Security → Whitelist Mobile Deeplink** and add the exact `redirectUrl` value (e.g. `yourapp://`). It must match `Info.plist` and `ClientProps`.

---

## 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 installation method do you prefer? (Xcode SPM — recommended, or Package.swift)
2. Which chains do you want to support? (EVM, SVM/Solana — one or both)

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

### Installation Methods

**Xcode (recommended):**
1. File → Add Package Dependencies
2. URL: `https://github.com/dynamic-labs/swift-sdk-and-sample-app.git`
3. Version: `1.0.2` or later

**Package.swift:**
```swift
dependencies: [
    .package(url: "https://github.com/dynamic-labs/swift-sdk-and-sample-app.git", from: "1.0.2")
]
```

### ClientProps — All Fields Required

| Property | Description | Example |
|---|---|---|
| `environmentId` | Your Dynamic environment ID | `"abc123..."` |
| `appLogoUrl` | URL to your app logo | `"https://your-app.com/logo.png"` |
| `appName` | Your app's display name | `"My App"` |
| `redirectUrl` | URL scheme for auth callbacks — must match `Info.plist` | `"yourapp://"` |
| `appOrigin` | Your app's origin domain | `"https://your-app.com"` |

**Dashboard:** In **Security → Whitelist Mobile Deeplink**, add the same value as `redirectUrl` (e.g. `yourapp://`).

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

---

## Critical Reference

| Correct | Incorrect | Notes |
|---|---|---|
| `DynamicSDK.initialize()` in `@main` App `init()` | Initializing inside a View | Must happen before any views are rendered |
| `redirectUrl` matches `Info.plist` URL scheme | Mismatched URL scheme | Auth callbacks will silently fail if these don't match |
| `redirectUrl` whitelisted under **Security → Whitelist Mobile Deeplink** | Deep link not whitelisted | OAuth and return-to-app flows can fail |
| All 5 `ClientProps` fields set | Omitting `redirectUrl` or `appOrigin` | All fields are required |
| Combine publishers for auth/wallet state | One-time checks | SDK state is async — always observe publishers |
| `sdk.wallets.userWalletsChanges` for wallet updates | Reading wallets immediately after auth | Wallets are created asynchronously after authentication |

---

## Troubleshooting

### 1 — "Could not find module 'DynamicSDKSwift'"
Make sure the package is added to your app target (not just the project). Try Product → Clean Build Folder, then rebuild. Restart Xcode if needed.

### 2 — Auth UI not appearing
Verify `DynamicSDK.initialize()` is called in `@main` App `init()` before any views load. Do not call `DynamicSDK.instance()` before initialization.

### 3 — Auth callbacks not working / social login fails
Verify your URL scheme is configured in `Info.plist` and matches `redirectUrl` in `ClientProps`. Whitelist your deeplink URL in the Dynamic dashboard under **Security → Whitelist Mobile Deeplink**.

### 4 — Wallets not appearing after login
Wallets are created asynchronously — use `sdk.wallets.userWalletsChanges` publisher to observe updates. Verify embedded wallets are enabled in the dashboard.

### 5 — Session state not updating
Use Combine publishers (`authenticatedUserChanges`, `userWalletsChanges`) with `@StateObject` / `@ObservedObject`. Do not read state once — always observe.

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