Skip to main content
Portal’s iOS SDK integrates with Blockaid to provide real-time security scanning for transactions, addresses, tokens, and URLs. This integration helps detect malicious activity, phishing attempts, scam tokens, and suspicious interactions before users sign or submit transactions.

Overview

The Blockaid integration enables you to:
  • Scan transactions before signing or submission (EVM, Solana)
  • Scan addresses for known malicious actors or compromised contracts
  • Validate tokens to detect scams or security risks
  • Verify URLs to prevent phishing attacks

Prerequisites

Before using Blockaid security scanning, ensure you have:
  • A properly initialized Portal client
  • Blockaid integration enabled in your Portal Dashboard

Scanning EVM Transactions

Use scanEVMTx to analyze Ethereum transactions before signing or broadcasting them. This method scans EVM transactions for malicious contract interactions, risky approvals, phishing attempts, and other on-chain security threats.
Task {
    do {
        let transactionData = BlockaidScanEVMTransactionData(
            from: "0x7C01728004d3F2370C1BBC36a4Ad680fE6FE8729",
            to: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
            data: "0x095ea7b3...",
            value: "0x0",
            gas: "0x2dc6c0",
            gasPrice: "0x2dc6c0",
            nonce: "0x924"
        )
        
        let request = BlockaidScanEVMRequest(
            chain: "eip155:1",
            data: transactionData,
            options: [.simulation, .validation]
        )
        
        let response = try await portal.security.blockaid.scanEVMTx(request: request)
        
        if let rawResponse = response.data?.rawResponse {
            print("Chain: \(rawResponse.chain)")
            print("Block: \(rawResponse.block)")
            
            if let validation = rawResponse.validation {
                print("Validation Status: \(validation.status)")
                print("Result Type: \(validation.resultType)")
                
                if validation.resultType == "Malicious" {
                    print("⚠️ Transaction flagged as MALICIOUS")
                } else {
                    print("✅ Transaction appears safe")
                }
            }
        }
    } catch {
        print("Error scanning EVM transaction: \(error)")
    }
}

Scanning Solana Transactions

Use scanSolanaTx to analyze Solana transactions before signing. This method detects malicious program invocations, suspicious token movements, and other Solana-specific risks.
Task {
    do {
        let transactions = [
            "AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAQADCQkVR3SiiKbW0l4c3NBsEn6+zn1o0YsyypPwN0GUhg4K5HK0Tb5GckDLYW+MsovQASt5EZ3bSH3nluRJAE69H61w0BRUDTrpYQcXosUun6/z2BROkRoH/1bL7KLU9s4lCav6k3ZZgV6qeZFwu4pu89WoIGaqUxG4C93XwVmmDy81v8qBaCSP4/UZfdo3q1bud/W+ixymkH8IMe0laQZYrSx4Uhyxec67hYm1VqLV7JTSSYaC/fm7KvWtZOSRzEFT2gMGRm/lIRcy/+ytunLDm+e8jOW7xfcSayxDmzpAAAAAT4tlY/P4mFG1wDJl0ektVggHiZf73lTlHBVJ3fK0nDoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANG5fPtlMEOI/eXV7aPDlpcdLUKm8L3VoW6k/oJlCNLaBQYABQLARQQABgAJAwYAAAAAAAAABzwACQoLCwgyMzQMNQ0ONjcPEDg5EgETFBUWOhEXGBkaGxwdHh8gISI7IyQlJicCKCkqKywtAwQuLzAxPBFVCg8JAQcHBgYBAAAAAwHwCgYBExUbBgICAAAPAwIAAAYBISMoEQQBGQAPAwIAAAYBLjA2DwMCAAAGAgIAAAAIBgYICAADAQkGCQUFBgACBQAEBwEAAAgCAAUMAgAAADwaAAAAAAAABgAFBGDMBQAEPPm21Wu6wrmHu23/ZFNIumpp+ADooZjd4JQgvjnBxkUJAgEDBqWqCgmmCAUIBwu1tp+gcP/+Ri3C1tRXUbPdgqo6rVsj/qnqC959wTdC/mRARysLz9HS09TW19jZ2tsC1QYsNrdxMcm5Nq5FXZrM0IXpEA+ApFa+pz/JvkLz0+2vnwuztLW2t7i5uru8vgAPvBv8VUeRwDy9yD1NHIH5Ji6ZA+zrmpHejKOz4MP8SwrKy8zNzs/S09TVAdY="
        ]
        
        let request = BlockaidScanSolanaRequest(
            accountAddress: "86xCnPeV69n6t3DnyGvkKobf9FdN2H9oiVDdaMpo2MMY",
            transactions: transactions,
            encoding: .base64,
            chain: "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
            options: [.simulation, .validation],
            method: "signAndSendTransaction"
        )
        
        let response = try await portal.security.blockaid.scanSolanaTx(request: request)
        
        if let rawResponse = response.data?.rawResponse {
            print("Status: \(rawResponse.status ?? "Unknown")")
            
            if let result = rawResponse.result, let validation = result.validation {
                print("Result Type: \(validation.resultType)")
                
                if validation.resultType == "Malicious" {
                    print("⚠️ Transaction flagged as MALICIOUS")
                } else {
                    print("✅ Transaction appears safe")
                }
            }
        }
    } catch {
        print("Error scanning Solana transaction: \(error)")
    }
}

Scanning Addresses

Use scanAddress to analyze a single address for known security risks. This method can be used for both EVM and Solana addresses and detects malicious contracts, compromised wallets, sanctioned addresses, and other flagged entities.

EVM Address Scan

Task {
    do {
        let request = BlockaidScanAddressRequest(
            address: "0x31c05d73f2333b5a176cfdbb7c5ef96ec7bb04ac",
            chain: "eip155:1"
        )
        
        let response = try await portal.security.blockaid.scanAddress(request: request)
        
        if let rawResponse = response.data?.rawResponse {
            print("Result Type: \(rawResponse.resultType)")
            
            if let features = rawResponse.features {
                print("Features: \(features.count)")
                for feature in features {
                    print("  - [\(feature.type)] \(feature.featureId): \(feature.description)")
                }
            }
        }
    } catch {
        print("Error scanning EVM address: \(error)")
    }
}

Solana Address Scan

Task {
    do {
        let request = BlockaidScanAddressRequest(
            address: "BBQUMqaFELxTFh8r1xSttYMHX6ZKzLWhsmGod2vuxgEc",
            chain: "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp"
        )
        
        let response = try await portal.security.blockaid.scanAddress(request: request)
        
        if let rawResponse = response.data?.rawResponse {
            print("Result Type: \(rawResponse.resultType)")
        }
    } catch {
        print("Error scanning Solana address: \(error)")
    }
}

Scanning Tokens

Use scanTokens to analyze multiple tokens in a single request for known security risks. This method detects scam tokens, honeypots, compromised contracts, and other malicious token behavior.
Task {
    do {
        let request = BlockaidScanTokensRequest(
            chain: "eip155:1",
            tokens: [
                "0x66587563e933bbf3974b89156b47bb82b921eb35",
                "0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d"
            ]
        )
        
        let response = try await portal.security.blockaid.scanTokens(request: request)
        
        if let rawResponse = response.data?.rawResponse {
            print("Results count: \(rawResponse.results.count)")
            
            for (address, result) in rawResponse.results {
                print("Token: \(address)")
                print("  Result Type: \(result.resultType)")
                
                if let score = result.maliciousScore {
                    print("  Malicious Score: \(score)")
                }
                
                if let metadata = result.metadata {
                    print("  Name: \(metadata.name ?? "Unknown")")
                    print("  Symbol: \(metadata.symbol ?? "Unknown")")
                }
                
                if result.resultType == "Malicious" {
                    print("  ⚠️ Token is MALICIOUS")
                }
            }
        }
    } catch {
        print("Error scanning tokens: \(error)")
    }
}

Scanning URLs

Use scanURL to detect phishing sites and malicious domains before users navigate to them. This method helps protect users from social engineering attacks and malicious off-chain activity.
Task {
    do {
        let request = BlockaidScanURLRequest(
            url: "https://ethlen.com"
        )
        
        let response = try await portal.security.blockaid.scanURL(request: request)
        
        if let rawResponse = response.data?.rawResponse {
            print("Status: \(rawResponse.status)")
            
            if rawResponse.status == "hit" {
                if let isMalicious = rawResponse.isMalicious, isMalicious {
                    print("⚠️ URL flagged as MALICIOUS")
                } else {
                    print("✅ URL appears safe")
                }
                
                print("Malicious Score: \(rawResponse.maliciousScore ?? 0)")
                print("Is Web3 Site: \(rawResponse.isWeb3Site ?? false)")
            } else if rawResponse.status == "miss" {
                print("ℹ️ URL not in database (miss)")
            }
        }
    } catch {
        print("Error scanning URL: \(error)")
    }
}

Error Handling

All Blockaid scan methods are async throwing functions. If a request fails, the function will throw an exception. You should wrap all scan calls in a do-catch block to handle potential errors. The following errors may be thrown:
ErrorDescription
PortalRequestsError.unauthorizedAuthentication failed (401). Verify your Portal client is properly initialized.
PortalRequestsError.clientErrorClient error (4xx). The request was invalid or malformed.
PortalRequestsError.internalServerErrorServer error (5xx). A server-side issue occurred.
PortalRequestsError.redirectErrorRedirect error (3xx). An unexpected redirect occurred.
do {
    let response = try await portal.security.blockaid.scanEVMTx(request: request)
    // Handle successful response
} catch PortalRequestsError.unauthorized {
    print("Authentication failed - check your Portal configuration")
} catch PortalRequestsError.clientError(let message, let url) {
    print("Client error: \(message) at \(url)")
} catch PortalRequestsError.internalServerError(let message, let url) {
    print("Server error: \(message) at \(url)")
} catch {
    print("Unexpected error: \(error)")
}

Next Steps