Quick Start

Transfer

Para handles signing and broadcasting in one call:
import ParaSwift

let paraManager = ParaManager(apiKey: "your-api-key")
let wallet = (try await paraManager.fetchWallets()).first { $0.type == .evm }!

// Send ETH - Para signs and broadcasts
let result = try await paraManager.transfer(
    walletId: wallet.id,
    to: "0x742d35Cc6634C0532925a3b844Bc454e4438f44e",
    amount: "1000000000000000", // 0.001 ETH in wei
    chainId: "11155111", // Optional: Sepolia testnet (defaults to wallet's chain)
    rpcUrl: nil // Optional: override default RPC
)
print("Transaction sent: \(result.hash)")
print("From: \(result.from), To: \(result.to)")
print("Amount: \(result.amount), Chain: \(result.chainId)")

Advanced Control

Sign with Para, then broadcast yourself for custom gas/RPC settings:
import ParaSwift
import BigInt

// Step 1: Sign transaction with Para
let transaction = EVMTransaction(
    to: "0x742d35Cc6634C0532925a3b844Bc454e4438f44e",
    value: BigUInt("1000000000000000")!,
    gasLimit: BigUInt("21000")!
)

let result = try await paraManager.signTransaction(
    walletId: wallet.id,
    transaction: transaction,
    chainId: "11155111" // Sepolia testnet
)

// Step 2: Broadcast using your preferred method (e.g., web3.swift)
// let txHash = try await broadcastWithWeb3Swift(result.signature)

Common Operations

Send ETH

// Para handles everything - signing and broadcasting
let result = try await paraManager.transfer(
    walletId: wallet.id,
    to: "0x742d35Cc6634C0532925a3b844Bc454e4438f44e",
    amount: "1000000000000000", // 0.001 ETH in wei
    chainId: "11155111", // Optional: Sepolia testnet
    rpcUrl: nil // Optional: custom RPC URL
)
print("Transaction hash: \(result.hash)")
print("From: \(result.from), To: \(result.to), Chain: \(result.chainId)")

Sign Transaction

import BigInt

let transaction = EVMTransaction(
    to: "0x742d35Cc6634C0532925a3b844Bc454e4438f44e",
    value: BigUInt("1000000000000000")!,
    gasLimit: BigUInt("21000")!,
    maxPriorityFeePerGas: BigUInt("1000000000")!,
    maxFeePerGas: BigUInt("3000000000")!,
    nonce: BigUInt("0")!,
    chainId: BigUInt("11155111")!, // Sepolia
    type: 2
)

let result = try await paraManager.signTransaction(
    walletId: wallet.id,
    transaction: transaction,
    chainId: "11155111"
)
print("Signed: \(result.signature)")

Check Balance

// Native ETH balance
let ethBalance = try await paraManager.getBalance(walletId: wallet.id)

// ERC-20 token balance
let tokenBalance = try await paraManager.getBalance(
    walletId: wallet.id,
    token: "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48" // USDC
)

Sign Message

let message = "Hello, Ethereum!"
let result = try await paraManager.signMessage(
    walletId: wallet.id,
    message: message
)
print("Signature: \(result.signature)")

Networks

Testnets

NetworkChain IDNative TokenDefault RPC
Sepolia11155111ETHhttps://ethereum-sepolia-rpc.publicnode.com
Polygon Mumbai80001MATIChttps://rpc-mumbai.maticvigil.com
Base Sepolia84532ETHhttps://sepolia.base.org

Mainnets

NetworkChain IDNative TokenDefault RPC
Ethereum1ETHhttps://eth.llamarpc.com
Polygon137MATIChttps://polygon-rpc.com
Base8453ETHhttps://mainnet.base.org
Arbitrum42161ETHhttps://arb1.arbitrum.io/rpc
Optimism10ETHhttps://mainnet.optimism.io

Complete Example

import SwiftUI
import ParaSwift
import BigInt

struct EVMWalletView: View {
    @EnvironmentObject var paraManager: ParaManager
    @State private var isLoading = false
    @State private var txHash: String?
    
    let wallet: Wallet
    
    var body: some View {
        VStack(spacing: 20) {
            Text(wallet.address ?? "No address")
                .font(.system(.caption, design: .monospaced))
            
            Button(action: sendETH) {
                Text(isLoading ? "Sending..." : "Send 0.001 ETH")
            }
            .disabled(isLoading)
            
            if let txHash = txHash {
                Text("Sent: \(txHash)")
                    .font(.caption)
            }
        }
        .padding()
    }
    
    private func sendETH() {
        isLoading = true
        Task {
            do {
                let result = try await paraManager.transfer(
                    walletId: wallet.id,
                    to: "0x742d35Cc6634C0532925a3b844Bc454e4438f44e",
                    amount: "1000000000000000",
                    chainId: "11155111", // Optional: Sepolia testnet
                    rpcUrl: nil // Optional: custom RPC
                )
                txHash = result.hash
            } catch {
                print("Error: \(error)")
            }
            isLoading = false
        }
    }
}

Smart Contract Interaction

// Call a contract function
let contractTransaction = EVMTransaction(
    to: "0x123abc...", // Contract address
    value: BigUInt(0),
    gasLimit: BigUInt("150000")!,
    maxPriorityFeePerGas: BigUInt("1000000000")!,
    maxFeePerGas: BigUInt("3000000000")!,
    nonce: BigUInt("0")!,
    chainId: BigUInt("11155111")!, // Sepolia testnet
    smartContractAbi: """
    [{
        "inputs": [{"name":"num","type":"uint256"}],
        "name": "store",
        "type": "function"
    }]
    """,
    smartContractFunctionName: "store",
    smartContractFunctionArgs: ["42"],
    type: 2
)

let result = try await paraManager.signTransaction(
    walletId: wallet.id,
    transaction: contractTransaction,
    chainId: "11155111" // Sepolia testnet
)