I’m developing a native (SwiftUI) iOS mobile app for my dissertation project and I’m trying to send a transaction to my contract using the eth_sendTransaction in this example: github. com/MetaMask/MetaMask-ios-sdk?tab=readme-ov-file#example-send-transaction . However, when I’m sending the transaction. It will open the MetaMask wallet and immediately go back to my app without any confirmation on the MetaMask.
I’m not sure why the deeplink detects an account change, which never occured.
Function to connect to MetaMask
func connectAndSign() async {
showProgressView = true
guard let url = URL(string: "metamask://"), UIApplication.shared.canOpenURL(url) else {
print("MetaMask is not installed.")
errorMessage = "MetaMask is not installed. Please install MetaMask."
return
}
metaMaskSDK.clearSession()
do {
let jsonString = try await withTimeout(seconds: 30) {
try await withCheckedThrowingContinuation { continuation in
DeepLinkManager.shared.setContinuation(continuation)
Task {
_ = await self.metaMaskSDK.connectAndSign(message: "I hereby request to register as a patient.")
}
}
}
// Parse the successful response
guard let jsonData = jsonString.data(using: .utf8),
let response = try? JSONSerialization.jsonObject(with: jsonData) as? [String: String] else {
throw ConnectionError.invalidResponseFormat
}
// Update UI and SDK state
DispatchQueue.main.async {
self.result = """
Connected Account: \(response["account"] ?? "")
Signature: \(response["signature"] ?? "")
Chain ID: \(response["chainId"] ?? "")
"""
self.metaMaskSDK.account = response["account"] ?? ""
self.isConnected = true
self.account = self.metaMaskSDK.account
self.chainId = self.metaMaskSDK.chainId
self.webSocketManager = WebSocketManager(userAddress: self.metaMaskSDK.account)
self.dismiss()
}
} catch {
DispatchQueue.main.async {
self.errorMessage = error.localizedDescription
}
}
showProgressView = false
}
Function to send data
func sendHealthDataTransaction(heartRate: Int, oxygenLevel: Int, contractAddress: String) async throws -> String {
// 1. Verify account consistency
let currentAccount = metaMaskSDK.account
guard !currentAccount.isEmpty else {
throw NSError(domain: "MetaMask", code: -1,
userInfo: [NSLocalizedDescriptionKey: "No connected account"])
}
// 2. Store the account we're using for this transaction
let transactionAccount = currentAccount
print("My account: \(metaMaskSDK.account)")
// 3. Prepare transaction
let txData = try await prepareTransaction(
userAddress: transactionAccount,
heartRate: heartRate,
oxygenLevel: oxygenLevel
)
// 4. Create and send transaction
let transaction = HealthDataTransaction(
to: contractAddress,
from: transactionAccount,
value: "0x0",
data: txData.data,
gas: txData.gas,
gasPrice: txData.gasPrice
)
let request = EthereumRequest(
method: .ethSendTransaction,
params: [transaction]
)
// 5. Send with account verification
return try await withCheckedThrowingContinuation { continuation in
DeepLinkManager.shared.setContinuation(continuation)
Task {
do {
print("Starting transaction with account:", transactionAccount)
print("Current account after return:", metaMaskSDK.account)
// Verify account hasn't changed
if self.metaMaskSDK.account != transactionAccount {
throw ConnectionError.accountChanged
}
let result = try await self.metaMaskSDK.request(request)
// Final verification
if self.metaMaskSDK.account != transactionAccount {
print("Account changed during transaction")
throw NSError(domain: "MetaMask", code: -32602,
userInfo: [NSLocalizedDescriptionKey: "Account changed during transaction"])
}
} catch {
continuation.resume(throwing: error)
}
}
}
}
These are the logs:
This is the response from my API to prepare the transaction:
API Response: [“nonce”: 0x5, “to”: 0xd8e8DD50888C2159ce0c200bA3047149B3911b8A, “data”: 0xd8db9b7800000000000000000000000000000000000000000000000000000000000000480000000000000000000000000000000000000000000000000000000000000062, “gas”: 0x30d40]Deeplink:
My account: 0xe361EcbfEB52E224Cfe5f8c00868934aDf1bFDD7
API Response: [“nonce”: 0x5, “to”: 0xd8e8DD50888C2159ce0c200bA3047149B3911b8A, “data”: 0xd8db9b7800000000000000000000000000000000000000000000000000000000000000480000000000000000000000000000000000000000000000000000000000000062, “gas”: 0x30d40]
Starting transaction with account: 0xe361EcbfEB52E224Cfe5f8c00868934aDf1bFDD7
Current account after return: 0xe361EcbfEB52E224Cfe5f8c00868934aDf1bFDD7
App moving to background (MetaMask opening)
[DEEP LINK] Received URL: myhealth://mmsdk?message=eyJkYXRhIjp7ImlkIjoiMTc0MzQzMzQ4ODY0NiIsImVycm9yIjp7ImNvZGUiOi0zMjYwMiwibWVzc2FnZSI6IlRoZSBzZWxlY3RlZCBhY2NvdW50IGhhcyBjaGFuZ2VkLiBQbGVhc2UgdHJ5IGFnYWluLiJ9LCJqc29ucnBjIjoiMi4wIiwiY2hhaW5JZCI6IjB4NjEiLCJhY2NvdW50cyI6WyIweGUzNjFFY2JmRUI1MkUyMjRDZmU1ZjhjMDA4Njg5MzRhRGYxYkZERDciXX0sIm5hbWUiOiJtZXRhbWFzay1wcm92aWRlciJ9
Account changed error detected
[DEEP LINK] Received URL: myhealth://mmsdk?message=eyJkYXRhIjp7ImlkIjoiMTc0MzQzMzQ4ODY0NiIsImVycm9yIjp7ImNvZGUiOi0zMjYwMiwibWVzc2FnZSI6IlRoZSBzZWxlY3RlZCBhY2NvdW50IGhhcyBjaGFuZ2VkLiBQbGVhc2UgdHJ5IGFnYWluLiJ9LCJqc29ucnBjIjoiMi4wIiwiY2hhaW5JZCI6IjB4NjEiLCJhY2NvdW50cyI6WyIweGUzNjFFY2JmRUI1MkUyMjRDZmU1ZjhjMDA4Njg5MzRhRGYxYkZERDciXX0sIm5hbWUiOiJtZXRhbWFzay1wcm92aWRlciJ9
No active continuation to handle deep link
Account changed - please reconnect
App returned to foreground