iOS SDK for Dynamic's authentication and Web3 wallet infrastructure.
- Authentication: Social (Google, Apple, Farcaster), Email/SMS OTP, Passkey, External JWT
- Multi-Chain Wallets: EVM (Ethereum, Polygon, Base, etc.) and Solana
- Wallet Operations: Balances, signing, transactions, network switching
- Security: MFA/TOTP, Passkey management, Recovery codes
- Reactive State: Combine framework integration
- iOS 15.0+
- Xcode 16.0+
- Swift 5.9+
Add the SDK to your project using one of the following methods:
- Open your project in Xcode
- Go to File > Add Package Dependencies...
- Enter the repository URL:
https://github.com/dynamic-labs/swift-sdk-and-sample-app - Select the version rule (e.g., Up to Next Major Version from
1.2.0) - Click Add Package
- Select
DynamicSDKSwiftlibrary and add it to your target
Add the dependency to your Package.swift:
dependencies: [
.package(url: "https://github.com/dynamic-labs/swift-sdk-and-sample-app.git", from: "1.2.0")
]Then add DynamicSDKSwift to your target's dependencies:
.target(
name: "YourApp",
dependencies: [
.product(name: "DynamicSDKSwift", package: "DynamicSDKSwift")
]
)The SDK includes a dynamic framework (DynamicSDKSwift.xcframework) that must be embedded in your app. If you're using SPM, Xcode handles this automatically. If you're integrating manually:
- Drag
DynamicSDKSwift.xcframeworkinto your project's Frameworks, Libraries, and Embedded Content section - Set DynamicSDKSwift.xcframework to Embed & Sign
- Set the stub frameworks (SwiftBigInt, SolanaWeb3, AnyCodableSwift) to Do Not Embed
import SwiftUI
import DynamicSDKSwift
@main
struct YourApp: App {
init() {
_ = DynamicSDK.initialize(
props: ClientProps(
environmentId: "YOUR_ENVIRONMENT_ID",
appLogoUrl: "https://yourdomain.com/logo.png",
appName: "Your App Name",
redirectUrl: "yourapp://",
appOrigin: "https://yourdomain.com"
)
)
}
var body: some Scene {
WindowGroup { ContentView() }
}
}let sdk = try DynamicSDK.getInstance()sdk.ui.showAuth()try await sdk.auth.social.connect(provider: .google) // or .apple, .farcastertry await sdk.auth.email.sendOTP(email: "user@example.com")
try await sdk.auth.email.verifyOTP(token: "123456")let phoneData = PhoneData(countryCode: "1", phoneNumber: "5555551234")
try await sdk.auth.sms.sendOTP(phoneData: phoneData)
try await sdk.auth.sms.verifyOTP(token: "123456")try await sdk.auth.passkey.signIn()
try await sdk.passkeys.registerPasskey()try await sdk.auth.externalAuth.signInWithExternalJwt(
props: SignInWithExternalJwtParams(jwt: "your-jwt-token")
)let user = sdk.auth.authenticatedUser
sdk.auth.authenticatedUserChanges
.receive(on: DispatchQueue.main)
.sink { user in /* handle user changes */ }
.store(in: &cancellables)
try await sdk.auth.logout()let wallets = sdk.wallets.userWallets
let balance = try await sdk.wallets.getBalance(wallet: wallet)
let network = try await sdk.wallets.getNetwork(wallet: wallet)try await sdk.wallets.switchNetwork(wallet: wallet, network: targetNetwork)
try await sdk.wallets.setPrimary(walletId: walletId)let signature = try await sdk.wallets.signMessage(wallet: wallet, message: "Hello!")let client = try await sdk.evm.createPublicClient(chainId: chainId)
let gasPrice = try await client.getGasPrice()
let transaction = EthereumTransaction(
from: wallet.address,
to: recipientAddress,
value: BigUInt("1000000000000000000"), // 1 ETH in Wei
gas: BigUInt(21000),
maxFeePerGas: gasPrice * 2,
maxPriorityFeePerGas: gasPrice * 2
)
let txHash = try await sdk.evm.sendTransaction(transaction: transaction, wallet: wallet)let signature = try await sdk.wallets.signTypedData(wallet: wallet, typedDataJson: typedDataJson)let input = WriteContractInput(
contractAddress: tokenContractAddress,
functionName: "transfer",
args: [recipientAddress, tokenAmount],
abi: Erc20.abi
)
let txHash = try await sdk.evm.writeContract(wallet: wallet, input: input)let connection = try await sdk.solana.createConnection()
let signer = try await sdk.solana.createSigner(wallet: wallet)
let blockhash = try await connection.getLatestBlockhash()
let signature = try await signer.signAndSendEncodedTransaction(base64Transaction: base64Tx)let devices = try await sdk.mfa.getUserDevices()
// Add TOTP device
let device = try await sdk.mfa.addDevice(type: .totp)
try await sdk.mfa.verifyDevice(code: "123456", type: .totp)
// Delete device
let token = try await sdk.mfa.createMfaToken(singleUse: true)
try await sdk.mfa.deleteUserDevice(deviceId: deviceId, mfaAuthToken: token)let codes = try await sdk.mfa.getRecoveryCodes(generateNewCodes: false)
try await sdk.mfa.authenticateRecoveryCode(code: recoveryCode)let passkeys = try await sdk.passkeys.getPasskeys()
try await sdk.passkeys.registerPasskey()
try await sdk.passkeys.deletePasskey(DeletePasskeyRequest(passkeyPublicKeyId: passkeyId))sdk.ui.showUserProfile()
if let user = sdk.auth.authenticatedUser {
print("User ID: \(user.userId)")
print("Email: \(user.email ?? "N/A")")
}let evmNetworks = sdk.networks.evm // Ethereum, Polygon, Arbitrum, Base, etc.
let solanaNetworks = sdk.networks.solana // Mainnet, Devnet, Testnet- Open
ExampleApp/DynamicSDKExample.xcodeproj - Update
environmentIdinDynamicSDKExampleApp.swift - Run on iOS Simulator or device
Demonstrates all auth flows, wallet operations, EVM/Solana transactions, MFA, and passkeys.