{"id":13951053,"url":"https://github.com/zeriontech/Web3Swift","last_synced_at":"2025-07-20T13:32:19.377Z","repository":{"id":44380714,"uuid":"114914740","full_name":"zeriontech/Web3Swift","owner":"zeriontech","description":"Ethereum Web3 library implementation for Swift","archived":true,"fork":false,"pushed_at":"2023-12-15T11:41:51.000Z","size":850,"stargazers_count":108,"open_issues_count":56,"forks_count":32,"subscribers_count":15,"default_branch":"develop","last_synced_at":"2025-07-15T06:25:48.970Z","etag":null,"topics":["contract-abi","crypto","daap","decentralized-applications","ethereum","ethereum-dapp","infura","mainnet","pure-swift","solidity","swift","web3","web3swift"],"latest_commit_sha":null,"homepage":"https://web3swift.io","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zeriontech.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","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}},"created_at":"2017-12-20T17:42:46.000Z","updated_at":"2025-01-19T18:52:16.000Z","dependencies_parsed_at":"2024-01-07T21:14:58.445Z","dependency_job_id":null,"html_url":"https://github.com/zeriontech/Web3Swift","commit_stats":{"total_commits":313,"total_committers":10,"mean_commits":31.3,"dds":0.4920127795527156,"last_synced_commit":"4e04054ac06a9875137ebbfac5a4b8c9f94d49f6"},"previous_names":["blockstoreapp/web3swift"],"tags_count":4,"template":false,"template_full_name":null,"purl":"pkg:github/zeriontech/Web3Swift","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zeriontech%2FWeb3Swift","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zeriontech%2FWeb3Swift/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zeriontech%2FWeb3Swift/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zeriontech%2FWeb3Swift/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zeriontech","download_url":"https://codeload.github.com/zeriontech/Web3Swift/tar.gz/refs/heads/develop","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zeriontech%2FWeb3Swift/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266135013,"owners_count":23881774,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","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":["contract-abi","crypto","daap","decentralized-applications","ethereum","ethereum-dapp","infura","mainnet","pure-swift","solidity","swift","web3","web3swift"],"created_at":"2024-08-08T06:01:12.143Z","updated_at":"2025-07-20T13:32:18.436Z","avatar_url":"https://github.com/zeriontech.png","language":"Swift","funding_links":[],"categories":["Swift","OOM-Leaks-Crash"],"sub_categories":["Blockchain"],"readme":"## Installation\n\n### CocoaPods\n\nWeb3 is available through [CocoaPods](https://cocoapods.org/pods/Web3Swift.io). To install\nit, simply add the following line to your `Podfile`:\n\n```ruby\npod 'Web3Swift.io'\n```\n\n## Sending ethers\n\nTo send some wei from an account with a private key `0x1636e10756e62baabddd4364010444205f1216bdb1644ff8f776f6e2982aa9f5` to an account with an address `0x79d2c50Ba0cA4a2C6F8D65eBa1358bEfc1cFD403` on a mainnet:\n\n```swift\nimport Web3Swift\n\nlet sender: PrivateKey = EthPrivateKey(\n    hex: \"0x1636e10756e62baabddd4364010444205f1216bdb1644ff8f776f6e2982aa9f5\"\n)\n\nlet recipient: BytesScalar = EthAddress(\n    hex: \"0x79d2c50Ba0cA4a2C6F8D65eBa1358bEfc1cFD403\"\n)\n\nlet network: Network = InfuraNetwork(\n    chain: \"mainnet\",\n    apiKey: \"0c4d6dc730244b4185a6bde26f981bff\"\n)\n\nlet amount: BytesScalar = EthNumber(\n    hex: \"0xde0b6b3a7640000\" // 10^18 in hex that represents 1 ETH\n)\n\nlet response = try SendRawTransactionProcedure(\n    network: network,\n    transactionBytes: EthDirectTransactionBytes(\n        network: network,\n        senderKey: sender,\n        recipientAddress: recipient,\n        weiAmount: amount\n    )\n).call()\n\n//If Ethereum network accepts the transaction, you could get transaction hash from the response. Otherwise, library will throw `DescribedError`\nprint(response[\"result\"].string ?? \"Something went wrong\")\n```\n\nIf you want to specify gas price or gas amount take a look at [`EthDirectTransactionBytes.swift`](https://github.com/BlockStoreApp/Web3Swift/blob/develop/Web3Swift/TransactionBytes/EthDirectTransactionBytes.swift).\n\nTo send ether instead of wei:\n\n```swift\nlet ethAmount = 1.1\n\ntry SendRawTransactionProcedure(\n    ...,\n    weiAmount: EthToWei(\n        amount: ethAmount\n    )\n).call()\n```\n\n## Dealing with ERC-20 tokens\n\n### Sending tokens to an address\n\nTo send some ERC-20 tokens, for example [OmiseGO](https://etherscan.io/token/OmiseGo), we need to get the smart contract address.\nOMG tokens are managed by smart contract at `0xd26114cd6EE289AccF82350c8d8487fedB8A0C07`.\nIn this example we send token from an account with a private key `0x1636e10756e62baabddd4364010444205f1216bdb1644ff8f776f6e2982aa9f5` to an account with an address `0x79d2c50Ba0cA4a2C6F8D65eBa1358bEfc1cFD403` on a mainnet:\n\n```swift\nimport Web3Swift\n\nlet network: Network = InfuraNetwork(\n    chain: \"mainnet\", apiKey: \"0c4d6dc730244b4185a6bde26f981bff\"\n)\n\nlet sender: PrivateKey = EthPrivateKey(\n    hex: \"0x1636e10756e62baabddd4364010444205f1216bdb1644ff8f776f6e2982aa9f5\"\n)\n\nlet recipient: BytesScalar = EthAddress(\n    hex: \"0x79d2c50Ba0cA4a2C6F8D65eBa1358bEfc1cFD403\"\n)\n\nlet token: BytesScalar = EthAddress(\n    hex: \"0xd26114cd6EE289AccF82350c8d8487fedB8A0C07\"\n)\n\nlet amount: BytesScalar = EthNumber(\n    hex: \"0xde0b6b3a7640000\" // 10^18 in hex that represents 1 OMG token\n)\n\nlet response = try SendRawTransactionProcedure(\n    network: network,\n    transactionBytes: EthContractCallBytes(\n        network: network,\n        senderKey: sender,\n        contractAddress: token,\n        weiAmount: EthNumber(\n            hex: \"0x00\" //We do not need to provide ethers to not payable functions.\n        ),\n        functionCall: EncodedABIFunction(\n            signature: SimpleString(\n                string: \"transfer(address,uint256)\"\n            ),\n            parameters: [\n                ABIAddress(\n                    address: recipient\n                ),\n                ABIUnsignedNumber(\n                    origin: amount\n                )\n            ]\n        )\n    )\n).call()\n\n//If Ethereum network accepts the transaction, you could get transaction hash from the response. Otherwise, library will throw `DescribedError`\nprint(response[\"result\"].string ?? \"Something went wrong\")\n```\n\nYou can swiftly deal with other ERC-20 functions just by encoding another `EncodedABIFunction` .\n\n### Sending delegated tokens to an address\n\nHere is an example of encoding `transferFrom(from,to,value)` function\n\n```swift\nEncodedABIFunction(\n    signature: SimpleString(\n        string: \"transferFrom(address,address,uint256)\"\n    ),\n    parameters: [\n        ABIAddress(\n            address: EthAddress(\n                hex: \"0xFBb1b73C4f0BDa4f67dcA266ce6Ef42f520fBB98\"\n            )\n        ),\n        ABIAddress(\n            address: EthAddress(\n                hex: \"0x79d2c50Ba0cA4a2C6F8D65eBa1358bEfc1cFD403\"\n            )\n        ),\n        ABIUnsignedNumber(\n            origin: EthNumber(\n                hex: \"0x01\"\n            )\n        )\n    ]\n)\n```\nMore encoding example including advanced ones are placed at [`Example/Tests/ABI`](https://github.com/zeriontech/Web3Swift/tree/develop/Example/Tests/ABI)\n\n### Checking an address balance\nYou do not need to send transaction for reading data from a smart contract. Here is an example of checking address balance by making a call to smart contract function `balanceOf(owner)`.\n\n```swift\nlet balance = try HexAsDecimalString(\n    hex: EthContractCall(\n        network: InfuraNetwork(\n            chain: \"mainnet\", apiKey: \"0c4d6dc730244b4185a6bde26f981bff\"\n        ),\n        contractAddress: EthAddress(\n            hex: \"0xd26114cd6EE289AccF82350c8d8487fedB8A0C07\" //OmiseGO token contract\n        ),\n        functionCall: EncodedABIFunction(\n            signature: SimpleString(\n                string: \"balanceOf(address)\"\n            ),\n            parameters: [\n                ABIAddress(\n                    address: EthAddress(\n                        hex: \"0xFBb1b73C4f0BDa4f67dcA266ce6Ef42f520fBB98\" //Bittrex\n                    )\n                )\n            ]\n        )\n    )\n).value()\n\nprint(balance) // 13098857909137917398909558 is 13 098 857.909137917398909558 OMG tokens\n```\n\n## Signing\n\n```swift\nimport CryptoSwift\n\n// Add your private key\nlet privateKey = EthPrivateKey(\n        hex: \"YOUR_PRIVATE_KEY\"\n)\n\n// Form the bytes for your message\n// In our example we sign null Ethereum address\nlet messageBytes = try! EthAddress(\n        hex: \"0x0000000000000000000000000000000000000000\"\n).value().bytes\n\n// Create a message\n// Don't forget that some services may expect\n// a message with Ethereum prefix as here\nlet message = ConcatenatedBytes(\n        bytes: [\n            //Ethereum prefix\n            UTF8StringBytes(\n                    string: SimpleString(\n                            string: \"\\u{19}Ethereum Signed Message:\\n32\"\n                    )\n            ),\n            //message\n            Keccak256Bytes(\n                    origin: SimpleBytes(\n                            bytes:\n                    )\n            )\n        ]\n)\n\n// Use your custom hash function if needed\nlet hashFunction = SHA3(variant: .keccak256).calculate\n\n// Create the signature\n// Calculations are performed in a lazy way\n// so you don't have to worry about performance\nlet signature = SECP256k1Signature(\n        privateKey: privateKey,\n        message: message,\n        hashFunction: hashFunction\n)\n\n// Now you can retrieve all the parameters\n// of the signature or use it for the signing with web3\nlet r = PrefixedHexString(\n        bytes: try! signature.r()\n)\nlet s = PrefixedHexString(\n        bytes: try! signature.s()\n)\nlet v = try! signature.recoverID().value() + 27\n```\n\n## Getting information about transactions\n### Fetching information\nGetting results of the recent or previous transaction is one of the most common tasks during developing interactions with DApps. There are two JSON-RPC methods for getting basic and additional transaction info. The first one is `eth_getTransactionByHash` ([example](https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_gettransactionbyhash)) and the second one is `eth_getTransactionReceipt`([example](https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_gettransactionreceipt)). You could use next library example to get needed information from the Ethereum blockchain.\n```swift\nimport Web3Swift\nimport SwiftyJSON\n\nlet transactionHash = BytesFromHexString(\n    hex: \"0x5798fbc45e3b63832abc4984b0f3574a13545f415dd672cd8540cd71f735db56\"\n)\n\nlet network = InfuraNetwork(\n    chain: \"mainnet\",\n    apiKey: \"0c4d6dc730244b4185a6bde26f981bff\"\n)\n\nlet basicInfo: JSON = try TransactionProcedure(\n    network: network,\n    transactionHash: transactionHash\n).call()\n\nlet advancedInfo: JSON = try TransactionReceiptProcedure(\n    network: network,\n    transactionHash: transactionHash\n).call()\n\nprint(basicInfo[\"result\"].dictionary ?? \"Something went wrong\")\n/**\n[\n    \"blockNumber\": 0x196666,\n    \"value\": 0x0,\n    \"v\": 0x1b,\n    \"input\":0x612e45a3000000000000000000000000b656b2a9c3b2416437a811e07466ca712f5a5b5a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000c000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000093a80000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000116c6f6e656c792c20736f206c6f6e656c7900000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000,\n    \"hash\": 0x5798fbc45e3b63832abc4984b0f3574a13545f415dd672cd8540cd71f735db56,\n    \"to\": 0xbb9bc244d798123fde783fcc1c72d3bb8c189413,\n    \"transactionIndex\": 0x7,\n    \"gasPrice\": 0x4a817c800,\n    \"r\": 0xd92d67e4a982c45c78c1260fc2f644ed78483e2bf7d6151aab9ea40a8e172472,\n    \"nonce\": 0x0,\n    \"blockHash\": 0x1f716531f40858da4d4b08269f571f9f22c7b8bd921764e8bdf9cb2e0508efa1,\n    \"from\": 0xb656b2a9c3b2416437a811e07466ca712f5a5b5a,\n    \"s\": 0x6ee7e259e4f13378cf167bb980659520a7e5897643a2642586f246c6de5367d6,\n    \"gas\": 0x4c449\n]\n*/\n\nprint(advancedInfo[\"result\"].dictionary ?? \"Something went wrong\")\n\n/**\n[\n    \"root\": 0xee69c77c73cd53b90e928e786b1c7f5b743a36dccd877128cf1dce7b46980a97,\n    \"blockNumber\": 0x196666,\n    \"transactionIndex\": 0x7,\n    \"transactionHash\": 0x5798fbc45e3b63832abc4984b0f3574a13545f415dd672cd8540cd71f735db56,\n    \"blockHash\": 0x1f716531f40858da4d4b08269f571f9f22c7b8bd921764e8bdf9cb2e0508efa1,\n    \"from\": 0xb656b2a9c3b2416437a811e07466ca712f5a5b5a,\n    \"contractAddress\": null,\n    \"logsBloom\": 0x00000000000000020000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000200000000000000000000800000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000000000000,\n    \"to\": 0xbb9bc244d798123fde783fcc1c72d3bb8c189413,\n    \"logs\": [\n        {\n            \"blockNumber\" : \"0x196666\",\n            \"topics\" : [\n                \"0x5790de2c279e58269b93b12828f56fd5f2bc8ad15e61ce08572585c81a38756f\",\n                \"0x000000000000000000000000000000000000000000000000000000000000003b\"\n            ],\n            \"data\" : \"0x000000000000000000000000b656b2a9c3b2416437a811e07466ca712f5a5b5a00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000116c6f6e656c792c20736f206c6f6e656c79000000000000000000000000000000\",\n            \"logIndex\" : \"0x5\",\n            \"transactionHash\" : \"0x5798fbc45e3b63832abc4984b0f3574a13545f415dd672cd8540cd71f735db56\",\n            \"removed\" : false,\n            \"address\" : \"0xbb9bc244d798123fde783fcc1c72d3bb8c189413\",\n            \"blockHash\" : \"0x1f716531f40858da4d4b08269f571f9f22c7b8bd921764e8bdf9cb2e0508efa1\",\n            \"transactionIndex\" : \"0x7\"\n        }\n    ],\n    \"gasUsed\": 0x33da9,\n    \"cumulativeGasUsed\": 0xf98e3\n]\n*/\n```\n**NOTE:** Library is still in development. Domain level objects for all RPC structures are on the roadmap.\n\n### Parsing transaction\nAfter fetching the information you could transparently convert it to suitable objects.\n\n```swift\n// Get the number of the block in which the transaction occurred\nlet block = try HexAsDecimalString(\n    hex: EthNumber(\n        hex: basicInfo[\"result\"][\"blockNumber\"].stringValue\n    )   \n).value()\n\nprint(block)\n// 1664614\n\n// Get the recipient of the transaction\nlet recipient = try EthAddress(\n    hex: basicInfo[\"result\"][\"to\"].stringValue\n).value().toHexString()\n\nprint(recipient)\n// bb9bc244d798123fde783fcc1c72d3bb8c189413\n\n// Get the transaction fee in WEI\nlet gasPrice = EthNumber(\n    hex: basicInfo[\"result\"][\"gasPrice\"].stringValue\n)\n\nlet gasUsed = EthNumber(\n    hex: advancedInfo[\"result\"][\"gasUsed\"].stringValue\n)\n\nlet fee = try HexAsDecimalString(\n    hex: gasPrice * gasUsed\n).value()\n\nprint(fee)\n// 4247860000000000 WEI = 0,00424786 ETH\n```\n\n### Parsing transaction's input data\nYou could easily parse any transaction's input by knowing it's ABI or types the data passed into it.\n\n```swift\n// Parse the transaction input parameters\n/*\n    newProposal(\n        [0] address _recipient,\n        [1] uint256 _amount,\n        [2] string _description,\n        [3] bytes _transactionData,\n        [4] uint256 _debatingPeriod,\n        [5] bool _newCurator\n    )\n*/\n\n// Prepare the transaction's input for parsing - trim the signature of the executed function\nlet input = ABIMessage(\n    message: TrimmedPrefixString(\n        string: SimpleString{\n            basicInfo[\"result\"][\"input\"].stringValue\n        },\n        prefix: SimpleString{\n            \"0x612e45a3\"\n        }\n    )\n)\n\n// Get the recipient's address\nlet abiRecipient = try DecodedABIAddress(\n    abiMessage: input,\n    index: 0\n).value().toHexString()\n\nprint(abiRecipient)\n// b656b2a9c3b2416437a811e07466ca712f5a5b5a\n\n// Get the description string\nlet description = try DecodedABIString(\n    abiMessage: input,\n    index: 2\n).value()\n\nprint(description)\n// lonely, so lonely\n\n// Get the debating period number\nlet debatingPeriod = try HexAsDecimalString(\n    hex: DecodedABINumber(\n        abiMessage: input,\n        index: 4\n    )\n).value()\n\nprint(debatingPeriod)\n// 604800\n\n// Get the boolean flag\nlet flag = try DecodedABIBoolean(\n    abiMessage: input,\n    index: 5\n).value()\n\nprint(flag)\n// true\n```\n\n## Author\n\n- Timofey Solonin [@biboran](https://github.com/biboran), abdulowork@gmail.com\n- Vadim Koleoshkin [@rockfridrich](https://github.com/rockfridrich), vadim@zerion.io\n\n## License\n\nWeb3Swift is available under the Apache License 2.0. See the LICENSE file for more info.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzeriontech%2FWeb3Swift","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzeriontech%2FWeb3Swift","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzeriontech%2FWeb3Swift/lists"}