:2026-05-31 19:51 点击:9
在当今去中心化应用(DApps)蓬勃发展的时代,将区块链功能集成到移动应用中已成为一种趋势,iOS 作为全球领先的移动操作系统,其开发者社区对于如何使用 Swift 语言与以太坊这样的主流区块链进行交互充满了好奇与需求,本文将带你一步步了解,如何在 iOS 应用中通过 Swift 语言实现与以太坊网络的连接、数据查询和交易签名。
将 Swift 与以太坊结合,主要基于以下几点优势:
web3.swift 等库,开发者可以方便地调用以太坊的 JSON-RPC 接口,实现账户管理、交易发送、智能合约交互等功能。iOS 应用本身无法直接与以太坊区块链通信,它们需要一个中间层——以太坊节点,最常见的方式是连接到一个 
eth_getBalance(查询余额)、eth_sendTransaction(发送交易)等。web3.swift 这样的第三方库,它将底层的 JSON-RPC 调用封装成易于使用的 Swift 对象和方法,让开发者可以像调用普通函数一样与以太坊交互。在开始编码之前,我们需要准备好开发环境。
web3.swift 库。web3.swift 的仓库地址:https://github.com/attaswift/web3.swift下面,我们通过几个核心场景来展示如何使用 web3.swift。
这是最基础的操作,用于验证连接是否成功。
import web3swift
import BigInt // web3.swift 依赖 BigInt 处理以太坊上的大整数
// 1. 定义你的 Infura RPC URL
let rpcURL = "https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID"
guard let url = URL(string: rpcURL) else { fatalError("Invalid RPC URL") }
// 2. 创建一个 Web3 实例
let web3 = Web3.new(url)
// 3. 定义要查询的地址 (例如以太坊创始人 Vitalik Buterin 的地址)
let address = EthereumAddress("0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045")!
// 4. 创建一个 balance 任务
let balanceResult = web3.eth.getBalance(address: address)
// 5. 处理结果
do {
// balanceResult 是一个 Promise,我们需要在它的回调中处理结果
let balance = try balanceResult.wait()
// 余额是以 'wei' 为单位的,我们需要将其转换为 'ether'
let etherBalance = Double(balance) / pow(10.0, 18.0)
print("Address: \(address.address)")
print("Balance: \(etherBalance) ETH")
} catch {
print("Failed to get balance: \(error)")
}
发送交易比查询余额复杂,因为它需要用户签名,在 iOS 中,最佳实践是使用 本地签名,即用户在设备上通过自己的私钥对交易进行签名,然后将签名后的交易发送到网络。
注意:在实际应用中,绝对不要将用户的私钥硬编码在代码中,应该从 iOS 的 Keychain 中安全地读取。
import web3swift
import BigInt
// 假设我们已经从 Keychain 中获取了发送方的私钥
let privateKey = "YOUR_PRIVATE_KEY_HERE" // 仅作示例,实际应用中应从安全存储读取
guard let credentials = try? EthereumPrivateKey(privateKey: privateKey) else {
fatalError("Invalid private key")
}
let fromAddress = credentials.address
// 接收方地址
let toAddress = EthereumAddress("0x...")!
// 交易信息
let to = toAddress
let amount = BigUInt("1000000000000000000")! // 1 ETH in wei
let gasPrice = BigUInt("20000000000")! // 20 Gwei
let gasLimit = BigUInt("21000") // 标准转账的 gas 限制
// 创建交易对象
var transaction = EthereumTransaction(
to: to,
value: amount,
data: Data(), // 可选,用于调用智能合约
nonce: nil, // web3.swift 会自动查询 nonce
v: BigUInt(0),
r: BigUInt(0),
s: BigUInt(0),
chainID: BigUInt(1) // 主网 ChainID
)
// 估算 gas (可选但推荐)
do {
let estimatedGas = try web3.eth.estimateGas(for: transaction)
transaction.gasLimit = estimatedGas
print("Estimated Gas: \(estimatedGas)")
} catch {
print("Failed to estimate gas: \(error)")
}
// 1. 创建交易
let transactionToSend = try transaction.sign(with: credentials, chainID: BigUInt(1))
// 2. 发送交易
web3.eth.sendRaw(transaction: transactionToSend).promise
.done { txHash in
print("Transaction sent successfully! Hash: \(txHash.hex())")
}
.catch { error in
print("Failed to send transaction: \(error)")
}
与智能合约交互是 DApp 的核心,你需要合约的 ABI (Application Binary Interface) 和 地址。
假设我们有一个简单的存储合约,有一个 store(uint256) 和一个 retrieve() 函数。
import web3swift
import BigInt
// 合约地址
let contractAddress = EthereumAddress("0x...")!
// 合约 ABI (JSON 格式)
let contractABI = """
[
{
"constant": false,
"inputs": [{"name": "x", "type": "uint256"}],
"name": "store",
"outputs": [],
"payable": false,
"stateMutability": "nonpayable",
"type": "function"
},
{
"constant": true,
"inputs": [],
"name": "retrieve",
"outputs": [{"name": "retVal", "type": "uint256"}],
"payable": false,
"stateMutability": "view",
"type": "function"
}
]
"""
// 创建合约实例
guard let contract = web3.contract(Web3.Utils.abiDecode(json: contractABI)!, at: contractAddress, options: nil) else {
fatalError("Failed to create contract instance")
}
// 1. 调用 'retrieve' (常量/视图函数,不需要 gas)
let callOptions = TransactionOptions.defaultOptions
let retrieveFunction = contract.read("retrieve")!
retrieveFunction.call(options: callOptions).promise
.done { result in
if let retVal = result["0"] as? BigUInt {
print("Retrieved value: \(retVal)")
}
}
.catch { error in
print("Failed to call retrieve: \(error)")
}
// 2. 调用 'store' (写入函数,需要签名和发送)
let storeFunction = contract.write("store")!
let storeValue = BigUInt(42)
let transaction = storeFunction(arguments: [storeValue])
transaction.send(options: callOptions).promise
.done { txHash
本文由用户投稿上传,若侵权请提供版权资料并联系删除!