web3.swift is the primary Swift library for the Avalanche C-Chain, letting native iOS and macOS apps read AVAX balances and send transactions against the EVM at chain ID 43114. It targets iOS 13+ and macOS 10.15+, so it covers any modern Apple platform deployment. Add it through Swift Package Manager using the repository at https://github.com/argentlabs/web3.swift.
web3.swift targets iOS 13+ and macOS 10.15+, matching the async/await availability you want for clean C-Chain calls. Add it to your project through Swift Package Manager, pointing at the argentlabs/web3.swift repository.
Web3.swift
Create a client with Web3(rpcURL: "https://avalanche.therpc.io/YOUR_API_KEY") to connect to the C-Chain. Every network call is async throws, so invoke it from an async context or inside a Task { }, and use try await. Wrap the calls in do/catch to handle a reverted Avalanche transaction or a network error gracefully rather than letting it propagate to the UI.
import Web3
import BigInt
class EthereumClient {
private let web3= Web3(rpcURL: "https://avalanche.therpc.io/YOUR_API_KEY")
Key features: a native Swift implementation, iOS and macOS support, async/await throughout, type-safe contract interactions on the Avalanche C-Chain, wallet management, and ENS resolution
SwiftUI Integration
In SwiftUI, drive a live AVAX balance with an ObservableObject view model exposing @Published properties, held in the view as a @StateObject so updates re-render automatically. Call the async C-Chain methods from inside a Task { } — triggered by a Button action or the .task modifier when the view appears — and assign the result to the published property to refresh the display.
import SwiftUI
import Web3
struct WalletView: View {
@StateObject private var viewModel = WalletViewModel()
To call a C-Chain contract, load its ABI JSON and construct a contract instance through web3.eth.Contract(json:address:), then invoke a named method with its parameters. This works against any deployed Avalanche contract — a token, an NFT collection, or a DeFi pool — and the call returns decoded results you can map into your app's models.
struct Contract {
let web3= Web3(rpcURL: "https://avalanche.therpc.io/YOUR_API_KEY")
let contractAddress: EthereumAddress
func callMethod() async throws -> String {
let contract = try await web3.eth.Contract(
json: contractABI,
address: contractAddress
)
return try await contract.method(
"methodName",
parameters: [param1, param2],
extraData: Data()
).call()
}
}
Error Handling
Define a typed EthereumError enum so your app can tell an invalid address apart from a network failure or insufficient funds, and present each case with the right message. Validate the address format — at minimum the 0x prefix and length — before issuing any C-Chain network call, so you reject bad input locally instead of spending a round trip to the Avalanche endpoint only to get an error back.