{"id":20841281,"url":"https://github.com/iotexproject/solanaswift","last_synced_at":"2026-04-21T12:31:46.548Z","repository":{"id":250131302,"uuid":"833563326","full_name":"iotexproject/solanaswift","owner":"iotexproject","description":null,"archived":false,"fork":false,"pushed_at":"2024-12-12T03:36:11.000Z","size":1375,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-12-26T01:56:20.042Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/iotexproject.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-07-25T09:49:19.000Z","updated_at":"2024-12-12T03:36:15.000Z","dependencies_parsed_at":"2025-12-24T13:02:52.485Z","dependency_job_id":null,"html_url":"https://github.com/iotexproject/solanaswift","commit_stats":null,"previous_names":["iotexproject/solanaswift"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/iotexproject/solanaswift","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iotexproject%2Fsolanaswift","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iotexproject%2Fsolanaswift/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iotexproject%2Fsolanaswift/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iotexproject%2Fsolanaswift/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/iotexproject","download_url":"https://codeload.github.com/iotexproject/solanaswift/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/iotexproject%2Fsolanaswift/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32091820,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-21T11:25:29.218Z","status":"ssl_error","status_checked_at":"2026-04-21T11:25:28.499Z","response_time":128,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-18T01:19:32.188Z","updated_at":"2026-04-21T12:31:46.517Z","avatar_url":"https://github.com/iotexproject.png","language":"Swift","funding_links":[],"categories":[],"sub_categories":[],"readme":"# SolanaSwift\n\nSolana-blockchain client, written in pure swift.\n\n[![Version](https://img.shields.io/cocoapods/v/SolanaSwift.svg?style=flat)](https://cocoapods.org/pods/SolanaSwift)\n[![License](https://img.shields.io/cocoapods/l/SolanaSwift.svg?style=flat)](https://www.apache.org/licenses/LICENSE-2.0.html)\n[![Platform](https://img.shields.io/cocoapods/p/SolanaSwift.svg?style=flat)](https://cocoapods.org/pods/SolanaSwift)\n[![Documentation Status](https://readthedocs.org/projects/ansicolortags/badge/?version=latest)](https://p2p-org.github.io/solana-swift/documentation/solanaswift)\n\n## Breaking changes\n### v5.0\n...\n- Remove deprecated typealias Mint, use SPLTokenMintState or Token2022MintState instead.\n- Remove deprecated typealias Wallet, use AccountBalance instead.\n- Support token 2022 via method getAccountBalances (See GetAccountBalancesTests).\n- Support token 2022 and Token2022Program.\n...\n[See more](https://github.com/p2p-org/solana-swift/blob/main/CHANGELOG.md)\n\n### v2.0\n- From v2.0.0 we officially omited Rx library and a lot of dependencies, thus we also adopt swift concurrency to `solana-swift`. [What have been changed?](https://github.com/p2p-org/solana-swift/issues/42)\n- For those who still use `SolanaSDK` class, follow [this link](https://github.com/p2p-org/solana-swift/blob/deprecated/1.3.8/README.md)\n\n## Features\n- [x] Supported swift concurrency (from 2.0.0)\n- [x] Key pairs generation\n- [x] Solana JSON RPC API\n- [x] Create, sign transactions\n- [x] Send, simulate transactions\n- [x] Solana token list\n- [x] Socket communication\n- [x] OrcaSwapSwift\n- [x] RenVMSwift\n- [x] Token2022\n\n## Requirements\n- iOS 13 or later\n\n## Dependencies\n- TweetNacl\n- secp256k1.swift\n- Task_retrying\n\n## Installation\n\n### Cocoapods\nSolanaSwift is available through [CocoaPods](https://cocoapods.org). To install\nit, simply add the following line to your Podfile:\n\n```ruby\npod 'SolanaSwift', '~\u003e 5.0.0'\n```\n\n### Swift package manager\n```swift\n...\ndependencies: [\n    ...\n    .package(url: \"https://github.com/p2p-org/solana-swift\", from: \"5.0.0\")\n],\n...\n```\n\n## How to use\n\n### Import\n```swift\nimport SolanaSwift\n```\n\n### Logger\nCreate a logger that confirm to SolanaSwiftLogger\n```swift\nimport SolanaSwift\n\nclass MyCustomLogger: SolanaSwiftLogger {\n    func log(event: String, data: String?, logLevel: SolanaSwiftLoggerLogLevel) {\n        // Custom log goes here\n    }\n}\n\n// AppDelegate or somewhere eles\n\nlet customLogger: SolanaSwiftLogger = MyCustomLogger()\nSolanaSwift.Logger.setLoggers([customLogger])\n```\n\n### AccountStorage\nCreate an `SolanaAccountStorage` for saving account's `keyPairs` (public and private key), for example: `KeychainAccountStorage` for saving into `Keychain` in production, or `InMemoryAccountStorage` for temporarily saving into memory for testing. The \"`CustomAccountStorage`\" must conform to protocol `SolanaAccountStorage`, which has 2 requirements: function for saving `save(_ account:) throws` and computed property `account: Account? { get thrrows }` for retrieving user's account.\n\nExample:\n```swift\nimport SolanaSwift\nimport KeychainSwift\nstruct KeychainAccountStorage: SolanaAccountStorage {\n    let tokenKey = \u003cYOUR_KEY_TO_STORE_IN_KEYCHAIN\u003e\n    func save(_ account: Account) throws {\n        let data = try JSONEncoder().encode(account)\n        keychain.set(data, forKey: tokenKey)\n    }\n    \n    var account: Account? {\n        guard let data = keychain.getData(tokenKey) else {return nil}\n        return try JSONDecoder().decode(Account.self, from: data)\n    }\n}\n\nstruct InMemoryAccountStorage: SolanaAccountStorage {\n    private var _account: Account?\n    func save(_ account: Account) throws {\n        _account = account\n    }\n    \n    var account: Account? {\n        _account\n    }\n}\n```\n\n### Create an account (keypair)\n```swift\nlet account = try await KeyPair(network: .mainnetBeta)\n// optional\naccountStorage.save(account)\n```\n\n### Restore an account from a seed phrase (keypair)\n```swift\nlet account = try await KeyPair(phrases: [\"miracle\", \"hundred\", ...], network: .mainnetBeta, derivablePath: ...)\n// optional\naccountStorage.save(account)\n```\n\n### Solana RPC Client\nAPIClient for [Solana JSON RPC API](https://docs.solana.com/developing/clients/jsonrpc-api). See [Documentation](https://p2p-org.github.io/solana-swift/documentation/solanaswift/solanaapiclient)\n\nExample: \n```swift\nimport SolanaSwift\n\nlet endpoint = APIEndPoint(\n    address: \"https://api.mainnet-beta.solana.com\",\n    network: .mainnetBeta\n)\n\n// To get block height\nlet apiClient = JSONRPCAPIClient(endpoint: endpoint)\nlet result = try await apiClient.getBlockHeight()\n\n// To get balance of the current account\nguard let account = try? accountStorage.account?.publicKey.base58EncodedString else { throw UnauthorizedError }\nlet balance = try await apiClient.getBalance(account: account, commitment: \"recent\")\n```\n\nWait for confirmation method.\n\n```swift\n// Wait for confirmation\nlet signature = try await blockChainClient.sendTransaction(...)\ntry await apiClient.waitForConfirmation(signature: signature, ignoreStatus: true) // transaction will be mark as confirmed after timeout no matter what status is when ignoreStatus = true\nlet signature2 = try await blockchainClient.sendTransaction(/* another transaction that requires first transaction to be completed */)\n```\n\nObserve signature status. In stead of using socket to observe signature status, which is not really reliable (socket often returns signature status == `finalized` when it is not fully finalized), we observe its status by periodically sending `getSignatureStatuses` (with `observeSignatureStatus` method)\n```swift\n// Observe signature status with `observeSignatureStatus` method\nvar statuses = [TransactionStatus]()\nfor try await status in apiClient.observeSignatureStatus(signature: \"jaiojsdfoijvaij\", timeout: 60, delay: 3) {\n    print(status)\n    statuses.append(status)\n}\n// statuses.last == .sending // the signature is not confirmed\n// statuses.last?.numberOfConfirmations == x // the signature is confirmed by x nodes (partially confirmed)\n// statuses.last == .finalized // the signature is confirmed by all nodes\n```\n\nBatch support\n\n```swift\n// Batch request with different types\nlet req1: JSONRPCAPIClientRequest\u003cAnyDecodable\u003e = JSONRPCAPIClientRequest(method: \"getAccountInfo\", params: [\"63ionHTAM94KaSujUCg23hfg7TLharchq5BYXdLGqia1\"])\nlet req2: JSONRPCAPIClientRequest\u003cAnyDecodable\u003e = JSONRPCAPIClientRequest(method: \"getBalance\", params: [\"63ionHTAM94KaSujUCg23hfg7TLharchq5BYXdLGqia1\"])\nlet response = try await apiClient.batchRequest(with: [req1, req2])\n\n// Batch request with same type\nlet balances: [Rpc\u003cUInt64\u003e?] = try await apiClient.batchRequest(method: \"getBalance\", params: [[\"63ionHTAM94KaSujUCg23hfg7TLharchq5BYXdLGqia1\"], [\"63ionHTAM94KaSujUCg23hfg7TLharchq5BYXdLGqia1\"], [\"63ionHTAM94KaSujUCg23hfg7TLharchq5BYXdLGqia1\"]])\n```\n\nFor the method that is not listed, use generic method `request(method:params:)` or `request(method:)` without params.\n\n```swift\nlet result: String = try await apiClient.request(method: \"getHealth\")\nXCTAssertEqual(result, \"ok\")\n```\n\n### Solana Blockchain Client\nPrepare, send and simulate transactions. See [Documentation](https://p2p-org.github.io/solana-swift/documentation/solanaswift/solanablockchainclient)\n\nExample: \n```swift\nimport SolanaSwift\n\nlet blockchainClient = BlockchainClient(apiClient: JSONRPCAPIClient(endpoint: endpoint))\n\n/// Prepare any transaction, use any Solana program to create instructions, see section Solana program. \nlet preparedTransaction = try await blockchainClient.prepareTransaction(\n    instructions: [...],\n    signers: [...],\n    feePayer: ...\n)\n\n/// SPECIAL CASE: Prepare Sending Native SOL\nlet preparedTransaction = try await blockchainClient.prepareSendingNativeSOL(\n    account: account,\n    to: toPublicKey,\n    amount: 0\n)\n\n/// SPECIAL CASE: Sending SPL Tokens\nlet preparedTransactions = try await blockchainClient.prepareSendingSPLTokens(\n    account: account,\n    mintAddress: \u003cSPL TOKEN MINT ADDRESS\u003e,  // USDC mint\n    decimals: 6,\n    from: \u003cYOUR SPL TOKEN ADDRESS\u003e, // Your usdc address\n    to: destination,\n    amount: \u003cAMOUNT IN LAMPORTS\u003e\n)\n\n/// Simulate or send\n\nblockchainClient.simulateTransaction(\n    preparedTransaction: preparedTransaction\n)\n\nblockchainClient.sendTransaction(\n    preparedTransaction: preparedTransaction\n)\n```\n\n### Solana Program\nList of default programs and pre-defined method that live on Solana network:\n1. SystemProgram. See [Documentation](https://p2p-org.github.io/solana-swift/documentation/solanaswift/systemprogram)\n2. TokenProgram. See [Documentation](https://p2p-org.github.io/solana-swift/documentation/solanaswift/tokenprogram)\n3. AssociatedTokenProgram. See [Documentation](https://p2p-org.github.io/solana-swift/documentation/solanaswift/associatedtokenprogram)\n4. OwnerValidationProgram. See [Documentation](https://p2p-org.github.io/solana-swift/documentation/solanaswift/ownervalidationprogram)\n5. TokenSwapProgram. See [Documentation](https://p2p-org.github.io/solana-swift/documentation/solanaswift/tokenswapprogram)\n6. Token2022Program. See [Documentation](https://p2p-org.github.io/solana-swift/documentation/solanaswift/token2022program)\n\n### Solana Tokens Repository\nTokens repository usefull when you need to get a list of tokens. See [Documentation](https://p2p-org.github.io/solana-swift/documentation/solanaswift/tokensrepository)\n\nExample:\n```swift\nlet tokenRepository = TokensRepository(endpoint: endpoint)\nlet list = try await tokenRepository.getTokensList()\n```\nTokenRepository be default uses cache not to make extra calls, it can disabled manually `.getTokensList(useCache: false)`\n\n## Contribution\n- Welcome to contribute, feel free to change and open a PR.\n\n## Author\nChung Tran, chung.t@p2p.org\n\n## License\n\nSolanaSwift is available under the MIT license. See the LICENSE file for more info.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fiotexproject%2Fsolanaswift","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fiotexproject%2Fsolanaswift","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fiotexproject%2Fsolanaswift/lists"}