Overview

This guide outlines how to integrate and use external cryptocurrency wallets with the ParaSwift SDK. It covers setup, deep-linking protocols, authentication, and transaction signing processes for wallets such as MetaMask.

Deep Linking

The ParaSwift SDK communicates with other apps via deep linking. To enable deep linking for your application, you’ll need to configure your app appropriately.

Configure URL Schemes

First, you need to configure your app to handle custom URL schemes:

  1. Open your app’s Info.plist file
  2. Add a new entry for LSApplicationQueriesSchemes as an array
  3. Add the URL schemes of supported wallets as strings to this array
<key>LSApplicationQueriesSchemes</key>
<array>
    <string>metamask</string>
</array>

Configure URL Types

Next, you need to set up URL Types to handle callbacks from external wallets:

  1. In Xcode, select your app target
  2. Go to “Info” tab
  3. Expand “URL Types”
  4. Click the ”+” button to add a new URL Type
  5. Set the “Identifier” to your app’s bundle identifier
  6. Set the “URL Schemes” to a unique scheme for your app

MetaMask Connector

Setup

Create and initialize the MetaMask connector with your app’s configuration:

import ParaSwift

// Create MetaMask configuration
let bundleId = Bundle.main.bundleIdentifier ?? ""
let metaMaskConfig = MetaMaskConfig(
    appName: "Your App Name",
    appId: bundleId,
    apiVersion: "1.0"
)

// Initialize the connector
let metaMaskConnector = MetaMaskConnector(
    para: paraManager,
    appUrl: "https://\(bundleId)",  // Your app's URL
    config: metaMaskConfig
)

Handle incoming deep links from MetaMask by adding a URL handler in your SwiftUI app:

@main
struct YourApp: App {
    @StateObject private var metaMaskConnector = MetaMaskConnector(
        para: paraManager,
        appUrl: "https://your-app-url",
        config: metaMaskConfig
    )
    
    var body: some Scene {
        WindowGroup {
            ContentView()
                .environmentObject(metaMaskConnector)
                .onOpenURL { url in
                    metaMaskConnector.handleURL(url)
                }
        }
    }
}

Connecting

To connect to MetaMask and retrieve the user’s accounts:

do {
    try await metaMaskConnector.connect()
    // Access connected accounts via metaMaskConnector.accounts
} catch {
    // Handle connection error
}

Sign Message

To request a signature for a message from MetaMask:

guard let account = metaMaskConnector.accounts.first else { return }

do {
    let signature = try await metaMaskConnector.signMessage(
        "Message to sign! Hello World",
        account: account
    )
    // Use the signature
} catch {
    // Handle signing error
}

Send Transaction

To send a transaction through MetaMask using the standard transaction parameters:

import Web3Core

guard let account = metaMaskConnector.accounts.first else { return }

do {
    let valueInWei = Web3Core.Utilities.parseToBigUInt("0.001", units: .ether)!
    let gasLimit = Web3Core.Utilities.parseToBigUInt("100000", units: .wei)!
    
    let transaction = EVMTransaction(
        to: "0x13158486860B81Dee9e43Dd0391e61c2F82B577F",
        value: valueInWei,
        gasLimit: gasLimit
    )
    
    let txHash = try await metaMaskConnector.sendTransaction(transaction, account: account)
    // Transaction sent successfully, use txHash
} catch {
    // Handle transaction error
}

Alternatively, you can use a raw transaction dictionary format:

guard let account = metaMaskConnector.accounts.first else { return }

let transaction: [String: String] = [
    "from": account,
    "to": "0x13158486860B81Dee9e43Dd0391e61c2F82B577F",
    "value": "0x38D7EA4C68000", // 0.001 ETH in wei (hex)
    "gasLimit": "0x186A0" // 100000 in hex
]

do {
    let txHash = try await metaMaskConnector.sendTransaction(
        transaction,
        account: account
    )
    // Transaction sent successfully
} catch {
    // Handle transaction error
}

Properties

The MetaMask connector provides several useful properties:

// Check if connected to MetaMask
let isConnected = metaMaskConnector.isConnected

// Get list of connected accounts
let accounts = metaMaskConnector.accounts

// Get current chain ID (e.g., "0x1" for Ethereum mainnet)
let chainId = metaMaskConnector.chainId

Advanced Configuration

Customizing MetaMask Connection

You can customize various aspects of the MetaMask connection by modifying the MetaMaskConfig:

let metaMaskConfig = MetaMaskConfig(
    appName: "Your App Name",
    appId: bundleId,
    apiVersion: "1.0",
    appIcon: "https://yourapp.com/icon.png" // Optional custom icon URL
)

Working with Different Networks

MetaMask supports multiple networks. You can check the current network and adjust your app’s behavior accordingly:

switch metaMaskConnector.chainId {
case "0x1":
    // Ethereum Mainnet
case "0x5":
    // Goerli Testnet
case "0x89":
    // Polygon
default:
    // Other network
}