The Para Swift SDK provides robust support for Ethereum Virtual Machine (EVM) compatible blockchains through the ParaEvmSigner
class. This guide demonstrates how to perform common operations such as signing messages, signing transactions, and sending transactions on EVM chains.
Getting Started
To work with EVM chains, you’ll need:
- An initialized
ParaManager
instance
- A wallet with EVM capabilities
- An RPC URL for your target EVM network
Initializing the EVM Signer
First, create an instance of ParaEvmSigner
by providing your Para manager, an RPC URL, and optionally a wallet ID:
import ParaSwift
// Create the EVM signer
let paraEvmSigner = try ParaEvmSigner(
paraManager: paraManager,
rpcUrl: "https://sepolia.infura.io/v3/YOUR_API_KEY",
walletId: wallet.id // Optional, can be selected later
)
Replace YOUR_API_KEY
with your actual API key from providers like Infura, Alchemy, or your own RPC node.
Selecting a Wallet
If you didn’t specify a wallet ID when creating the signer, or if you want to switch to a different wallet, use the selectWallet
method:
// Select a wallet for signing
try await paraEvmSigner.selectWallet(walletId: wallet.id)
Signing Messages
Para makes it easy to sign arbitrary messages with your EVM wallet using the ParaEvmSigner
:
// Sign a message with the EVM signer
let message = "Hello, Ethereum!"
let signature = try await paraEvmSigner.signMessage(message: message)
// Alternatively, you can use the ParaManager directly
let signature2 = try await paraManager.signMessage(
walletId: wallet.id,
message: message // SDK handles Base64 encoding internally
)
Working with Transactions
Creating an EVM Transaction
Para uses the EVMTransaction
model to represent transactions:
import BigInt
// Create transaction parameters
let transaction = EVMTransaction(
to: "0x301d75d850c878b160ad9e1e3f6300202de9e97f",
value: BigUInt("1000000000000000")!, // 0.001 ETH in wei
gasLimit: BigUInt("21000")!,
gasPrice: nil, // For Type 2 transactions (EIP-1559)
maxPriorityFeePerGas: BigUInt("1000000000")!, // 1 Gwei
maxFeePerGas: BigUInt("3000000000")!, // 3 Gwei
nonce: BigUInt("0")!, // Transaction count for the address
chainId: BigUInt("11155111")!, // Sepolia testnet
smartContractAbi: nil, // Optional: ABI for contract interactions
smartContractFunctionName: nil, // Optional: Function to call
smartContractFunctionArgs: [], // Optional: Function arguments
smartContractByteCode: nil, // Optional: For contract deployment
type: 2 // Transaction type (2 for EIP-1559)
)
Signing a Transaction
To sign a transaction without broadcasting it to the network:
// Sign the transaction
let signedTransaction = try await paraEvmSigner.signTransaction(
transactionB64: transaction.b64Encoded()
)
Signing an EVM Transaction (RLP-Encoded with ParaManager)
Alternatively, you can sign RLP-encoded transactions directly using ParaManager:
// Assume rlpEncodedTxHex is a hex string of the RLP-encoded transaction
// Assume chainIdString is the string representation of the chain ID
let rlpEncodedTxHex = "0x..." // Your RLP encoded transaction
let chainIdString = "11155111" // Sepolia chain ID
let signature = try await paraManager.signTransaction(
walletId: selectedWallet.id,
rlpEncodedTx: rlpEncodedTxHex, // SDK handles Base64 encoding
chainId: chainIdString
)
print("RLP Transaction Signature: \(signature)")
Sending a Transaction
To sign and broadcast a transaction in a single step:
// Sign and send the transaction
let transactionHash = try await paraEvmSigner.sendTransaction(
transactionB64: transaction.b64Encoded()
)
Interacting with Smart Contracts
Para’s EVMTransaction
model supports smart contract interactions:
Calling a Contract Function (Read-Only)
// Example of creating a transaction for calling a read function
let contractTransaction = EVMTransaction(
to: "0x123abc...", // Contract address
value: BigUInt(0), // No value sent
gasLimit: BigUInt("100000")!,
gasPrice: nil,
maxPriorityFeePerGas: BigUInt("1000000000")!,
maxFeePerGas: BigUInt("3000000000")!,
nonce: BigUInt("5")!,
chainId: BigUInt("11155111")!,
smartContractAbi: """
[
{
"inputs": [],
"name": "retrieve",
"outputs": [{"internalType":"uint256","name":"","type":"uint256"}],
"stateMutability":"view",
"type":"function"
}
]
""",
smartContractFunctionName: "retrieve",
smartContractFunctionArgs: [],
smartContractByteCode: nil,
type: 2
)
Sending a Transaction to a Contract (Write)
// Example of creating a transaction for a state-changing function
let contractWriteTransaction = EVMTransaction(
to: "0x123abc...", // Contract address
value: BigUInt(0), // No value sent
gasLimit: BigUInt("150000")!,
gasPrice: nil,
maxPriorityFeePerGas: BigUInt("1000000000")!,
maxFeePerGas: BigUInt("3000000000")!,
nonce: BigUInt("6")!,
chainId: BigUInt("11155111")!,
smartContractAbi: """
[
{
"inputs": [{"internalType":"uint256","name":"num","type":"uint256"}],
"name": "store",
"outputs": [],
"stateMutability":"nonpayable",
"type":"function"
}
]
""",
smartContractFunctionName: "store",
smartContractFunctionArgs: ["42"], // Arguments as strings
smartContractByteCode: nil,
type: 2
)
// Send the transaction
try await paraEvmSigner.sendTransaction(
transactionB64: contractWriteTransaction.b64Encoded()
)
Deploying a Smart Contract
// Example of creating a transaction for contract deployment
let deployTransaction = EVMTransaction(
to: nil, // nil for contract deployment
value: BigUInt(0),
gasLimit: BigUInt("4000000")!,
gasPrice: nil,
maxPriorityFeePerGas: BigUInt("1500000000")!,
maxFeePerGas: BigUInt("3500000000")!,
nonce: BigUInt("7")!,
chainId: BigUInt("11155111")!,
smartContractAbi: nil,
smartContractFunctionName: nil,
smartContractFunctionArgs: [],
smartContractByteCode: "0x608060405234801561001057600080fd5b50...", // Contract bytecode
type: 2
)
// Send the transaction to deploy the contract
try await paraEvmSigner.sendTransaction(
transactionB64: deployTransaction.b64Encoded()
)
Working with Different Networks
Para supports any EVM-compatible network. Simply update the RPC URL and chain ID to target different networks:
// Ethereum Mainnet
let mainnetSigner = try ParaEvmSigner(
paraManager: paraManager,
rpcUrl: "https://mainnet.infura.io/v3/YOUR_API_KEY",
walletId: wallet.id
)
// Create transaction with appropriate chain ID
let mainnetTransaction = EVMTransaction(
// ... other parameters
chainId: BigUInt("1")!, // Ethereum Mainnet
// ... other parameters
)
Example Integration