Message signing allows users to cryptographically sign arbitrary messages off-chain without submitting a transaction. This is useful for authentication, proof of ownership, and secure messaging.NEAR Connect iOS implements the NEP-413 standard for message signing.
message: The human-readable message to sign (e.g., “Sign in to MyApp”)
recipient: The intended recipient account ID (typically your app’s contract or domain)
nonce: A 32-byte random nonce to prevent replay attacks. If nil, a secure random nonce is generated automatically
The nonce is automatically generated using iOS’s secure random number generator (SecRandomCopyBytes). You only need to provide a custom nonce if implementing a specific authentication protocol.
The signMessage() method returns a MessageSignResult:
public struct MessageSignResult { public let accountId: String? // Signer's account ID public let publicKey: String? // Public key used for signing public let signature: String? // Signed message payload (JSON)}
The signature field contains a JSON-encoded NEP-413 payload:
{ "accountId": "alice.near", "publicKey": "ed25519:...", "signature": "ed25519:...", "message": "Welcome to NEAR Connect!", "recipient": "myapp.near", "nonce": "base64-encoded-nonce", "callbackUrl": "..."}
Combine wallet connection and message signing in one user interaction:
do { let result = try await walletManager.connectAndSignMessage( message: "Sign in to NEAR Connect Demo", recipient: "near-connect-demo.near", nonce: nil ) // Account info print("Connected: \(result.account.accountId)") print("Wallet: \(result.account.walletId)") // Signed message (if wallet supports it) if let signedMessage = result.signedMessage { print("Signed message: \(signedMessage)") } else { print("Wallet does not support sign-in-and-sign") }} catch { print("Connect & sign failed: \(error.localizedDescription)")}
Use connectAndSignMessage() for authentication flows. It presents a single wallet approval screen for both connection and message signing, improving UX.
// Sign in with NEARlet result = try await walletManager.connectAndSignMessage( message: "Sign in to MyApp", recipient: "myapp.near")// Send to backend for session creationif let signature = result.signedMessage { let sessionToken = try await authenticateWithBackend(signature: signature) UserDefaults.standard.set(sessionToken, forKey: "session_token")}
// Prove ownership of NEAR accountlet timestamp = Int(Date().timeIntervalSince1970)let result = try await walletManager.signMessage( message: "I own this account at \(timestamp)", recipient: "verification.near")
// Sign a message for off-chain communicationlet result = try await walletManager.signMessage( message: "Hello, this is a secure message from me!", recipient: "chat.near")if let signature = result.signature { // Send message + signature to recipient await sendMessage(content: message, signature: signature)}