SolanaSwift
Solana区块链客户端,使用纯Swift编写。
特点
- 支持Swift并发(从2.0.0开始)
- 密钥对生成
- Solana JSON RPC API
- 创建、签署交易
- 发送、模拟交易
- Solana代币列表
- 套接字通信
- OrcaSwapSwift
- RenVMSwift
示例
要运行示例项目,请克隆仓库,然后从Example目录中首先运行`pod install`。演示钱包:[p2p-wallet](https://github.com/p2p-org/p2p-wallet-ios)
需求
- iOS 13 或更高版本
依赖项
- TweetNacl
- secp256k1.swift
安装
Cocoapods
SolanaSwift 通过 CocoaPods 提供。要安装它,只需将以下行添加到您的 Podfile 中
pod 'SolanaSwift', '~> 3.0.0'
Swift 包管理器
...
dependencies: [
...
.package(url: "https://github.com/p2p-org/solana-swift", from: "3.0.0")
],
...
如何使用
版本 2.0 更新公告
- 从 v2.0.0 开始,我们正式删除了 Rx 库和许多依赖项,因此我们还采用了 Swift 并发以支持
solana-swift
。 `有哪些变化?` - 对于仍然使用
SolanaSDK
类的用户,请查阅 `此链接`
导入
import SolanaSwift
Logger
创建一个符合 SolanaSwiftLogger 规范的日志记录器
import SolanaSwift
class MyCustomLogger: SolanaSwiftLogger {
func log(event: String, data: String?, logLevel: SolanaSwiftLoggerLogLevel) {
// Custom log goes here
}
}
// AppDelegate or somewhere eles
let customLogger: SolanaSwiftLogger = MyCustomLogger()
SolanaSwift.Logger.setLoggers([customLogger])
AccountStorage
创建一个用于保存账户的 keyPairs
(公钥和私钥)的 SolanaAccountStorage
。例如:用于在生产环境中保存到 Keychain
的 KeychainAccountStorage
或用于测试时临时保存到内存中的 InMemoryAccountStorage
。"CustomAccountStorage" 必须符合 SolanaAccountStorage
协议,该协议有 2 个要求:用于保存的 save(_ account:) throws
函数和一个用于检索用户账户的计算属性 account: Account? { get thrrows }
。
示例
import SolanaSwift
import KeychainSwift
struct KeychainAccountStorage: SolanaAccountStorage {
let tokenKey = <YOUR_KEY_TO_STORE_IN_KEYCHAIN>
func save(_ account: Account) throws {
let data = try JSONEncoder().encode(account)
keychain.set(data, forKey: tokenKey)
}
var account: Account? {
guard let data = keychain.getData(tokenKey) else {return nil}
return try JSONDecoder().decode(Account.self, from: data)
}
}
struct InMemoryAccountStorage: SolanaAccountStorage {
private var _account: Account?
func save(_ account: Account) throws {
_account = account
}
var account: Account? {
_account
}
}
创建账户(密钥对)
let account = try await Account(network: .mainnetBeta)
// optional
accountStorage.save(account)
从助记词恢复账户(密钥对)
let account = try await Account(phrases: ["miracle", "hundred", ...], network: .mainnetBeta, derivablePath: ...)
// optional
accountStorage.save(account)
Solana RPC 客户端
用于 Solana JSON RPC API 的 API 客户端。详见 文档
示例
import SolanaSwift
let endpoint = APIEndPoint(
address: "https://api.mainnet-beta.solana.com",
network: .mainnetBeta
)
// To get block height
let apiClient = JSONRPCAPIClient(endpoint: endpoint)
let result = try await apiClient.getBlockHeight()
// To get balance of the current account
guard let account = try? accountStorage.account?.publicKey.base58EncodedString else { throw SolanaError.unauthorized }
let balance = try await apiClient.getBalance(account: account, commitment: "recent")
等待确认方法。
// Wait for confirmation
let signature = try await blockChainClient.sendTransaction(...)
try await apiClient.waitForConfirmation(signature: signature, ignoreStatus: true) // transaction will be mark as confirmed after timeout no matter what status is when ignoreStatus = true
let signature2 = try await blockchainClient.sendTransaction(/* another transaction that requires first transaction to be completed */)
观察签名状态。而不是使用 socket 来观察签名状态,因为 socket 并不可靠(socket Often 返回 signature status == finalized
当它们没有完全完成时),我们通过定期发送 getSignatureStatuses
(通过 observeSignatureStatus
方法)来观察其状态。
// Observe signature status with `observeSignatureStatus` method
var statuses = [TransactionStatus]()
for try await status in apiClient.observeSignatureStatus(signature: "jaiojsdfoijvaij", timeout: 60, delay: 3) {
print(status)
statuses.append(status)
}
// statuses.last == .sending // the signature is not confirmed
// statuses.last?.numberOfConfirmations == x // the signature is confirmed by x nodes (partially confirmed)
// statuses.last == .finalized // the signature is confirmed by all nodes
批量支持
// Batch request with different types
let req1: JSONRPCAPIClientRequest<AnyDecodable> = JSONRPCAPIClientRequest(method: "getAccountInfo", params: ["63ionHTAM94KaSujUCg23hfg7TLharchq5BYXdLGqia1"])
let req2: JSONRPCAPIClientRequest<AnyDecodable> = JSONRPCAPIClientRequest(method: "getBalance", params: ["63ionHTAM94KaSujUCg23hfg7TLharchq5BYXdLGqia1"])
let response = try await apiClient.batchRequest(with: [req1, req2])
// Batch request with same type
let balances: [Rpc<UInt64>?] = try await apiClient.batchRequest(method: "getBalance", params: [["63ionHTAM94KaSujUCg23hfg7TLharchq5BYXdLGqia1"], ["63ionHTAM94KaSujUCg23hfg7TLharchq5BYXdLGqia1"], ["63ionHTAM94KaSujUCg23hfg7TLharchq5BYXdLGqia1"]])
对于未列出的方法,使用通用的方法 request(method:params:)
或 request(method:)
无参数调用。
let result: String = try await apiClient.request(method: "getHealth")
XCTAssertEqual(result, "ok")
Solana 区块链客户端
准备、发送和模拟交易。请参阅文档
示例
import SolanaSwift
let blockchainClient = BlockchainClient(apiClient: JSONRPCAPIClient(endpoint: endpoint))
/// Prepare any transaction, use any Solana program to create instructions, see section Solana program.
let preparedTransaction = try await blockchainClient.prepareTransaction(
instructions: [...],
signers: [...],
feePayer: ...
)
/// SPECIAL CASE: Prepare Sending Native SOL
let preparedTransaction = try await blockchainClient.prepareSendingNativeSOL(
account: account,
to: toPublicKey,
amount: 0
)
/// SPECIAL CASE: Sending SPL Tokens
let preparedTransactions = try await blockchainClient.prepareSendingSPLTokens(
account: account,
mintAddress: <SPL TOKEN MINT ADDRESS>, // USDC mint
decimals: 6,
from: <YOUR SPL TOKEN ADDRESS>, // Your usdc address
to: destination,
amount: <AMOUNT IN LAMPORTS>
)
/// Simulate or send
blockchainClient.simulateTransaction(
preparedTransaction: preparedTransaction
)
blockchainClient.sendTransaction(
preparedTransaction: preparedTransaction
)
Solana 程序
预定义在 Solana 网络上的默认程序和方法列表
- SystemProgram。请参阅文档
- TokenProgram。请参阅文档
- AssociatedTokenProgram。请参阅文档
- OwnerValidationProgram。请参阅文档
- TokenSwapProgram。请参阅文档
Solana 令牌仓库
当你需要获取令牌列表时非常有用的令牌仓库。请参阅文档
示例
let tokenRepository = TokensRepository(endpoint: endpoint)
let list = try await tokenRepository.getTokensList()
默认情况下,TokenRepository 使用缓存以避免额外的调用,可以手动禁用:`.getTokensList(useCache: false)`
如何使用OrcaSwap
OrcaSwap已迁移到新的库OrcaSwapSwift
如何使用RenVM
RenVM已迁移到新的库RenVMSwift
如何使用Serum Swap (DEX)(不稳定版)
SerumSwap已迁移到新的库SerumSwapSwift
贡献
- 欢迎贡献,请随意修改和提交PR。
作者
Chung Tran,[email protected]
许可证
SolanaSwift 在 MIT 许可下可用。更多信息请参阅 LICENSE 文件。