Documentation Index
Fetch the complete documentation index at: https://docs.dynamic.xyz/docs/llms.txt
Use this file to discover all available pages before exploring further.
Overview
Message signing on Solana allows users to prove wallet ownership by signing arbitrary messages.
Prerequisites
Sign Message
import DynamicSDKSwift
let sdk = DynamicSDK.instance()
func signMessage(wallet: BaseWallet, message: String) async throws -> String {
let signer = sdk.solana.createSigner(wallet: wallet)
return try await signer.signMessage(message: message)
}
// Usage
let wallet = sdk.wallets.userWallets.first { $0.chain.uppercased() == "SOL" }!
let signature = try await signMessage(wallet: wallet, message: "Hello, Solana!")
print("Signature: \(signature)")
SwiftUI Example
import SwiftUI
import DynamicSDKSwift
struct SolanaSignView: View {
let wallet: BaseWallet
@State private var message = ""
@State private var signature: String?
@State private var isLoading = false
@State private var error: String?
private let sdk = DynamicSDK.instance()
var body: some View {
VStack(spacing: 16) {
Text("Wallet: \(formatAddress(wallet.address))")
.font(.caption)
TextField("Message to sign", text: $message)
.textFieldStyle(.roundedBorder)
Button("Sign Message") { signMessage() }
.buttonStyle(.borderedProminent)
.disabled(message.isEmpty || isLoading)
if let signature = signature {
VStack(alignment: .leading) {
Text("Signature:").font(.headline)
Text(signature)
.font(.system(.caption, design: .monospaced))
.textSelection(.enabled)
Button("Copy") {
UIPasteboard.general.string = signature
}
}
.padding()
.background(Color.green.opacity(0.1))
.cornerRadius(8)
}
if let error = error {
Text(error).foregroundColor(.red).font(.caption)
}
}
.padding()
.navigationTitle("Sign Message")
}
private func formatAddress(_ address: String) -> String {
"\(address.prefix(6))...\(address.suffix(4))"
}
private func signMessage() {
isLoading = true
error = nil
Task { @MainActor in
do {
let signer = sdk.solana.createSigner(wallet: wallet)
signature = try await signer.signMessage(message: message)
} catch {
self.error = error.localizedDescription
}
isLoading = false
}
}
}
Authentication Use Case
/// Sign a message to prove wallet ownership
func authenticateWithSignature(wallet: BaseWallet) async throws -> String {
let nonce = UUID().uuidString
let message = "Sign to authenticate: \(nonce)"
let signer = sdk.solana.createSigner(wallet: wallet)
let signature = try await signer.signMessage(message: message)
// Send signature to your backend for verification
return signature
}
Sign Action Confirmation
/// Sign a message to confirm user action
func signActionConfirmation(
wallet: BaseWallet,
action: String,
timestamp: Date
) async throws -> String {
let message = """
Action: \(action)
Wallet: \(wallet.address)
Timestamp: \(timestamp.timeIntervalSince1970)
"""
let signer = sdk.solana.createSigner(wallet: wallet)
return try await signer.signMessage(message: message)
}
Verify Signature Data
Structure for sending to backend:
struct SolanaSignatureData {
let message: String
let signature: String
let publicKey: String
func toJSON() -> [String: String] {
return [
"message": message,
"signature": signature,
"publicKey": publicKey
]
}
}
// Usage
let signatureData = SolanaSignatureData(
message: "Hello, Solana!",
signature: signature,
publicKey: wallet.address
)
let jsonData = signatureData.toJSON()
// Send to backend for verification
Best Practices
1. Include Context
// Bad: Unclear message
let message = "12345"
// Good: Clear message with context
let message = """
Welcome to MyApp!
Sign to prove ownership of this wallet.
Wallet: \(wallet.address)
Nonce: 12345
Timestamp: \(Date().timeIntervalSince1970)
"""
2. Handle Errors
do {
let signer = sdk.solana.createSigner(wallet: wallet)
let signature = try await signer.signMessage(message: message)
} catch {
let errorDesc = error.localizedDescription.lowercased()
if errorDesc.contains("rejected") || errorDesc.contains("denied") {
print("User rejected the signature request")
} else {
print("Signing failed: \(error)")
}
}
3. Clear Sensitive Data
var signature: String? = try await signer.signMessage(message: message)
// ... use signature ...
signature = nil // Clear from memory
Error Handling
do {
let signer = sdk.solana.createSigner(wallet: wallet)
let signature = try await signer.signMessage(message: message)
print("Message signed: \(signature)")
} catch {
print("Failed to sign message: \(error)")
}
Next Steps