Overview
Message signing on Solana allows users to prove wallet ownership by signing arbitrary messages.Prerequisites
- Dynamic SDK initialized (see Quickstart)
- User authenticated (see Authentication)
- Solana wallet available (see Wallet Creation)
Sign Message
Copy
Ask AI
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
Copy
Ask AI
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
Copy
Ask AI
/// 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
Copy
Ask AI
/// 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:Copy
Ask AI
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
Copy
Ask AI
// 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
Copy
Ask AI
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
Copy
Ask AI
var signature: String? = try await signer.signMessage(message: message)
// ... use signature ...
signature = nil // Clear from memory
Error Handling
Copy
Ask AI
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
- Send Solana Transactions - Transfer SOL
- Solana Connection - Connection setup
- EVM Message Signing - Sign with EVM wallets