Overview
This guide covers basic wallet operations including balance management, message signing, and typed data signing with the Dynamic Swift SDK.Prerequisites
- Dynamic SDK initialized (see Installation Guide)
- User authenticated (see Authentication Guide)
- Wallets available (see Wallet Creation)
Balance Management
Get Wallet Balance
Copy
Ask AI
import DynamicSDKSwift
let sdk = DynamicSDK.instance()
func getBalance(wallet: BaseWallet) async {
do {
let balance = try await sdk.wallets.getBalance(wallet: wallet)
print("Balance: \(balance)")
} catch {
print("Failed to get balance: \(error)")
}
}
Get Balance with UI Updates
Copy
Ask AI
import SwiftUI
import DynamicSDKSwift
@MainActor
class WalletBalanceViewModel: ObservableObject {
@Published var balance: String?
@Published var isLoading = false
@Published var errorMessage: String?
private let sdk = DynamicSDK.instance()
func fetchBalance(wallet: BaseWallet) {
isLoading = true
errorMessage = nil
Task {
do {
balance = try await sdk.wallets.getBalance(wallet: wallet)
} catch {
errorMessage = "Failed to get balance: \(error.localizedDescription)"
}
isLoading = false
}
}
}
struct WalletBalanceView: View {
let wallet: BaseWallet
@StateObject private var viewModel = WalletBalanceViewModel()
var body: some View {
VStack(alignment: .leading, spacing: 8) {
Text("Balance")
.font(.caption)
.foregroundColor(.secondary)
if viewModel.isLoading {
HStack {
ProgressView()
Text("Loading...")
.foregroundColor(.secondary)
}
} else if let balance = viewModel.balance {
Text(balance)
.font(.headline)
} else if let error = viewModel.errorMessage {
Text(error)
.foregroundColor(.red)
.font(.caption)
}
}
.onAppear {
viewModel.fetchBalance(wallet: wallet)
}
}
}
Get Current Network
Get Wallet’s Current Network
Copy
Ask AI
import DynamicSDKSwift
let sdk = DynamicSDK.instance()
func getCurrentNetwork(wallet: BaseWallet) async {
do {
let network = try await sdk.wallets.getNetwork(wallet: wallet)
print("Current network: \(network)")
} catch {
print("Failed to get network: \(error)")
}
}
Display Network Information
Copy
Ask AI
import DynamicSDKSwift
@MainActor
class WalletNetworkViewModel: ObservableObject {
@Published var networkDescription: String?
@Published var isLoading = false
private let sdk = DynamicSDK.instance()
func fetchNetwork(wallet: BaseWallet) {
isLoading = true
Task {
do {
let network = try await sdk.wallets.getNetwork(wallet: wallet)
networkDescription = resolveNetworkDisplay(
wallet: wallet,
networkValue: network
)
} catch {
print("Failed to get network: \(error)")
}
isLoading = false
}
}
private func resolveNetworkDisplay(wallet: BaseWallet, networkValue: Any) -> String {
let chain = wallet.chain.uppercased()
if chain == "EVM" {
// Look up network name from available EVM networks
if let match = sdk.networks.evm.first(where: {
String(describing: $0.chainId.value) == String(describing: networkValue)
}) {
return "\(match.name) (chainId: \(match.chainId.value))"
}
return "Chain ID: \(networkValue)"
}
if chain == "SOL" {
// Look up network name from available Solana networks
if let match = sdk.networks.solana.first(where: {
String(describing: $0.networkId.value) == String(describing: networkValue)
}) {
return match.name
}
return String(describing: networkValue)
}
return String(describing: networkValue)
}
}
Message Signing
Sign a Message
Copy
Ask AI
import DynamicSDKSwift
let sdk = DynamicSDK.instance()
func signMessage(wallet: BaseWallet, message: String) async {
do {
let signature = try await sdk.wallets.signMessage(
wallet: wallet,
message: message
)
print("Message signed successfully!")
print("Signature: \(signature)")
} catch {
print("Failed to sign message: \(error)")
}
}
Complete Sign Message Example
Copy
Ask AI
import SwiftUI
import DynamicSDKSwift
struct SignMessageView: View {
let wallet: BaseWallet
@State private var message = ""
@State private var signature: String?
@State private var isLoading = false
@State private var errorMessage: String?
private let sdk = DynamicSDK.instance()
var body: some View {
VStack(spacing: 16) {
TextField("Enter message to sign", text: $message)
.textFieldStyle(.roundedBorder)
Button("Sign Message") {
signMessage()
}
.disabled(message.isEmpty || isLoading)
if isLoading {
ProgressView()
}
if let signature = signature {
VStack(alignment: .leading, spacing: 8) {
Text("Signature:")
.font(.caption)
.foregroundColor(.secondary)
Text(signature)
.font(.system(.caption, design: .monospaced))
.lineLimit(4)
.truncationMode(.middle)
Button("Copy") {
UIPasteboard.general.string = signature
}
.font(.caption)
}
.padding()
.background(Color(.systemGray6))
.cornerRadius(8)
}
if let error = errorMessage {
Text(error)
.foregroundColor(.red)
.font(.caption)
}
}
.padding()
}
private func signMessage() {
isLoading = true
errorMessage = nil
signature = nil
Task { @MainActor in
do {
signature = try await sdk.wallets.signMessage(
wallet: wallet,
message: message
)
} catch {
errorMessage = "Failed to sign: \(error.localizedDescription)"
}
isLoading = false
}
}
}
Sign Typed Data (EIP-712)
For EVM wallets, you can sign typed data following the EIP-712 standard:Copy
Ask AI
import DynamicSDKSwift
let sdk = DynamicSDK.instance()
func signTypedData(wallet: BaseWallet) async {
// Example EIP-712 typed data
let typedDataJson = """
{
"types": {
"EIP712Domain": [
{"name": "name", "type": "string"},
{"name": "version", "type": "string"},
{"name": "chainId", "type": "uint256"}
],
"Message": [
{"name": "content", "type": "string"}
]
},
"primaryType": "Message",
"domain": {
"name": "Example App",
"version": "1",
"chainId": 1
},
"message": {
"content": "Hello, World!"
}
}
"""
do {
let signature = try await sdk.wallets.signTypedData(
wallet: wallet,
typedDataJson: typedDataJson
)
print("Typed data signed!")
print("Signature: \(signature)")
} catch {
print("Failed to sign typed data: \(error)")
}
}
Complete Sign Typed Data Example
Copy
Ask AI
import SwiftUI
import DynamicSDKSwift
struct SignTypedDataView: View {
let wallet: BaseWallet
@State private var signature: String?
@State private var isLoading = false
@State private var errorMessage: String?
private let sdk = DynamicSDK.instance()
private let exampleTypedData = """
{
"types": {
"EIP712Domain": [
{"name": "name", "type": "string"},
{"name": "version", "type": "string"},
{"name": "chainId", "type": "uint256"}
],
"Mail": [
{"name": "from", "type": "string"},
{"name": "to", "type": "string"},
{"name": "contents", "type": "string"}
]
},
"primaryType": "Mail",
"domain": {
"name": "Example DApp",
"version": "1",
"chainId": 1
},
"message": {
"from": "Alice",
"to": "Bob",
"contents": "Hello!"
}
}
"""
var body: some View {
VStack(spacing: 16) {
Text("EIP-712 Typed Data")
.font(.headline)
Text(exampleTypedData)
.font(.system(.caption2, design: .monospaced))
.padding()
.background(Color(.systemGray6))
.cornerRadius(8)
Button("Sign Typed Data") {
signTypedData()
}
.disabled(isLoading)
if isLoading {
ProgressView()
}
if let signature = signature {
VStack(alignment: .leading) {
Text("Signature:")
.font(.caption)
Text(signature)
.font(.system(.caption2, design: .monospaced))
.lineLimit(3)
}
.padding()
.background(Color.green.opacity(0.1))
.cornerRadius(8)
}
if let error = errorMessage {
Text(error)
.foregroundColor(.red)
.font(.caption)
}
}
.padding()
}
private func signTypedData() {
isLoading = true
errorMessage = nil
signature = nil
Task { @MainActor in
do {
signature = try await sdk.wallets.signTypedData(
wallet: wallet,
typedDataJson: exampleTypedData
)
} catch {
errorMessage = "Failed to sign: \(error.localizedDescription)"
}
isLoading = false
}
}
}
Best Practices
1. Always Handle Errors
Copy
Ask AI
do {
let balance = try await sdk.wallets.getBalance(wallet: wallet)
// Use balance
} catch {
// Show user-friendly error message
print("Could not fetch balance. Please try again.")
}
2. Show Loading States
Copy
Ask AI
@Published var isLoading = false
func fetchBalance(wallet: BaseWallet) {
isLoading = true
Task {
defer { isLoading = false }
// ... fetch balance
}
}
3. Refresh Data When Needed
Copy
Ask AI
struct WalletDetailsView: View {
let wallet: BaseWallet
@StateObject private var viewModel = WalletDetailsViewModel()
var body: some View {
// ... UI
.onAppear {
viewModel.refresh(wallet: wallet)
}
.refreshable {
await viewModel.refreshAsync(wallet: wallet)
}
}
}