diff --git a/references/swift-api-reference.md b/references/swift-api-reference.md new file mode 100644 index 0000000..c1e4864 --- /dev/null +++ b/references/swift-api-reference.md @@ -0,0 +1,986 @@ +--- +title: "Swift API Reference" +excerpt: "The source code is found on GitHub at [https://github.com/icon-project/ICONKit](https://github.com/icon-project/ICONKit)" +--- + +ICON supports SDK for 3rd party or user services development. You can integrate ICON SDK for your project and utilize the ICON’s functionality. +This document provides you with information about API specification. + + +## `class` ICONService + +`ICONService` is a class which provides APIs to communicate with ICON nodes. It enables you to easily use [ICON JSON-RPC APIs](icon-json-rpc-v3) (version 3). All methods of `IconService` returns a `Request` instance. + +### Query Execution + +`Request` are executed as **synchronized** and **asynchronized**. + +#### Synchronized execution + +To execute the request synchronously, you need to run `execute()` function of `Request`. + +```swift +public func execute() -> Result +``` + +**Returns** + +`Result` + +**Example** + +```swift +// Synchronized request execution +let response = iconService.getLastBlock().execute() + +switch response { +case .success(let block): + print(block) +case .failure(let error): + print(error.errorDescription) +} +``` + +#### Asynchronized execution + +To execute the request asynchronously, you need to run `async()` function of `Request`. + +```swift +public func async(_ completion: @escaping (Result) -> Void) +``` + +**Returns** + +`async()` is a closure. Passing `Result`. + +**Example** + +```swift +// Asynchronized request execution +iconService.getLastBlock().async { (result) in + switch result { + case .success(let block): + print(block) + case .failure(let error): + print(err.errorDescription) + } +} +``` + +### Transaction Execution + +`Transaction` class is used to make a transaction instance. There are 3 types of Transaction class. + +| Class | Description | +| ------------------------------------------------------- | ------------------------------------------------------------ | +| [Transaction](#section--class-transaction) | A class for Transaction instance which is for sending ICX. | +| [CallTransaction](#section--class-calltransaction) | A class for CallTransaction instance which is for SCORE function call. CallTransaction extends `Transaction` class. | +| [MessageTransaction](#section--class-messagetransaction) | A class for MessageTransaction instance which is for transfer message. Extends `Transaction` class. | + +Request is executed as **Synchronized** or **Asynchronized** like a querying request. + +**Example** + +```swift +// Synchronized request +let response = iconService.sendTransaction(signedTransaction: signed).execute() + +switch response { +case .success(let result): // result == String + print(result) +case .error(let error): + print(error) +} + +// Asynchronized request +let request = iconService.sendTransaction(signedTransaction: signed) +request.async { (result) in + switch result { + case .success(let result): // result == String + print(result) + case .failure(let error): + print(error) + } +} +``` + +### Initialize +```swift +init(provider: String, nid: String) +``` + +#### Parameters +| Parameter | Type | Description | +| --------- | ---- | ----------- | +| provider | `String` | ICON node url. | +| nid | `String` | Network ID. | + +For more details of node URL and network id, see [ICON Network](the-icon-network) document. + +#### Example + +```swift +// ICON Mainnet +let iconService = ICONService(provider: "https://ctz.solidwallet.io/api/v3", nid: "0x1") +``` + + +### `func` getLastBlock + +Get the last block information. + +```swift +func getLastBlock() -> Request +``` + +#### Parameters + +None + +#### Returns + +`Request` - Request instance for `icx_getLastBlock` JSON-RPC API request. If the execution is successful, returns `Result`. + +#### Example + +```swift +// Returns last block +let response = iconService.getLastBlock().execute() + +switch response { +case .success(let result): // result == Response.Block + print(result) +case .error(let error): + print(error) +} +``` + +### `func` getBlock + +Get the block information. + +```swift +// Get block information by height. +func getBlock(height: UInt64) -> Request + +// Get block information by hash. +func getBlock(hash: String) -> Request +``` + +#### Parameters + +| Parameter | Type | Description | +| --------- | -------- | --------------------- | +| height | `UInt64` | Height value of block | +| hash | `String` | Hash value of block | + +#### Returns + +`Request` - Request instance for `icx_getBlockByHeight` | `icx_getBlockByHash`. If the execution is successful, returns `Result`. + +#### Example + +```swift +// Returns block information by block height +let heightBlock = iconService.getBlock(height: 10532).execute() + +// Returns block information by block hash +let hashBlock = iconService.getBlock(hash: "0xdb310dd653b2573fd673ccc7489477a0b697333f77b3cb34a940db67b994fd95").execute() + +switch heightBlock { +case .success(let block): // result == Response.Block + print(block) +case .error(let error): + print(error) +} +``` + +### `func` call + +Calls an external function of SCORE API. + +```swift +func call(_ call: Call) -> Request +``` + +#### Parameters + +| Parameter | Type | Description | +| --------- | ------ | -------------------------- | +| call | `Call` | an instance of Call class. | + +#### Returns + +`Request` - Request instance for `icx_call` JSON-RPC request. If the execution is successful, returns `Result`. + +#### Example + +In `Call` generic value, input the type of function call. The generic value should follow Codable protocol. + +For example, the type of SCORE function call is `String`, input `String ` like this. + +```swift +// Create Call instance +let call = Call(from: wallet.address, to: "cxf9148db4f8ec78823a50cb06c4fed83660af38d0", method: "tokenOwner", params: nil) + +let request: Request = iconService.call(call) +let response: Result = request.execute() + +switch response { +case .success(let owner): + print(owner) // hx70b591822468415e86fb9ba1354214902ea76196 +case .failure(let error): + print(error) +} +``` + +If SCORE call result is hex `String`, you can choice return types `String` or `BigUInt`. + +Using `Call`, return an original hex String value. + +Using `Call` return converted BigUInt value. + +```swift +let ownerAddress: String = "hx07abc7a5b8a4941fc0b6930c88b462995acf929b" +let scoreAddress: String = "cxf9148db4f8ec78823a50cb06c4fed83660af38d0" + +// Using `String`. Return hex String. +let call = Call(from: ownerAddress, to: scoreAddress, method: "balanceOf", params: ["_owner": ownerAddress]) +let request: Request = iconService.call(call) +let response: Result = request.execute() + +switch response { +case .success(let balance): + print("balance: \(balance)") // "balance: 0x11e468ef422cc60031ef" +case .failure(let error): + print(error) +} + + +// Using `BigUInt`. Return BigUInt. +let call = Call(from: ownerAddress, to: scoreAddress, method: "balanceOf", params: ["_owner": ownerAddress]) +let request: Request = iconService.call(call) +let response: Result = request.execute() + +switch response { +case .success(let balance): + print("balance: \(balance)") // "balance: 84493649192649192649199" +case .failure(let error): + print(error) +} +``` + +### `func` getBalance + +Get the balance of the address. + +```swift +func getBalance(address: String) -> Request +``` + +#### Parameters + +| Parameter | Type | Description | +| --------- | -------- | -------------- | +| address | `String` | An EOA Address | + +#### Returns + +`Request` - Request instance for `icx_getBalance` JSON-RPC API request. If the execution is successful, returns `Result`. + +#### Example + +```swift +// Returns the balance of specific address +let response = iconService.getBalance(address: "hx9d8a8376e7db9f00478feb9a46f44f0d051aab57").execute() + +switch response { +case .success(let result): // result == BigUInt + print(result) +case .error(let error): + print(error) +} +``` + +### `func` getScoreAPI + +Get the SCORE API list. + +```swift +func getScoreAPI(scoreAddress: String) -> Request<[Response.ScoreAPI]> +``` + +#### Parameters + +| Parameter | Type | Description | +| ------------ | -------- | --------------- | +| scoreAddress | `String` | A SCORE address | + +#### Returns + +`Request` - Request instance for `icx_getScoreApi` JSON-RPC API request. If the execution is successful, returns `Result<[Response.ScoreAPI], ICError>`. + +#### Example + +```swift +// Returns the SCORE API list +let response = iconService.getScoreAPI(scoreAddress: "cx0000000000000000000000000000000000000001").execute() + +switch response { +case .success(let result): // result == [Response.ScoreAPI] + print(result) +case .error(let error): + print(error) +} +``` + +### `func` getTotalSupply + +get the total number of issued coins. +```swift +func getTotalSupply() -> Request +``` + +#### Parameters + +None + +#### Returns + +`Request` - Request instance for `icx_getTotalSupply` JSON-RPC API request. If the execution is successful, returns `Result`. + +#### Example +```swift +// Returns total value of issued coins +let response = iconService.getTotalSupply().execute() + +switch response { +case .success(let result): // result == BigUInt + print(result) +case .error(let error): + print(error) +} +``` + +### `func` getTransaction +Get the transaction information. +```swift +func getTransaction(hash: String) -> Request +``` + +#### Parameters +| Parameter | Type | Description | +| --- | --- | --- | +| hash | `String` | Hash value of transaction | + +#### Returns +`Request` - Request instnace for `icx_getTransactionByHash` JSON-RPC API request. If the execution is successful, returns `Result`. + +#### Example +```swift +// Returns transaction information +let response = iconService.getTransaction(hash: "0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238").execute() + +switch response { +case .success(let result): // result == Response.TransactionByHashResult + print(result) +case .error(let error): + print(error) +} +``` + +### `func` getTransactionResult +Get the transaction result information. +```swift +func getTransactionResult(hash: String) -> Request +``` + +#### Parameters +| Parameter | Type | Description | +| --- | --- | --- | +| hash | `String` | A transaction hash. | + +#### Returns +`Request` - Request instance for `icx_getTransactionResult` JSON-RPC API request. If the execution is successful, returns `Result`. + +#### Example +```swift +// Returns transaction result information +let response = iconService.getTransactionResult(hash: "0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238").execute() + +switch response { +case .success(let result): // result == Response.TransactionResult + print(result) +case .error(let error): + print(error) +} +``` + + +### `func` sendTransaction + +Send a transaction that changes the state of address. Request is executed as **Synchronized** or **Asynchronized** like a querying request. + +```swift +func sendTransaction(signedTransaction: SignedTransaction) -> Request +``` + +#### Parameters + +| Parameter | Type | Description | +| ----------------- | ------------------- | ------------------------------------------------------------ | +| signedTransaction | `SignedTransaction` | an instance of [SignedTransaction](#section--class-signedtransaction) class. | + +#### Returns + +`Request` - Request instance for `icx_sendTransaction` JSON-RPC request. If the execution is successful, returns `Result`. + +#### Example + +```swift +// Synchronized request +let response = iconService.sendTransaction(signedTransaction: signed).execute() + +switch response { +case .success(let result): // result == String + print(result) +case .error(let error): + print(error) +} + +// Asynchronized request +let request = iconService.sendTransaction(signedTransaction: signed) +request.async { (result) in + switch result { + case .success(let result): // result == String + print(result) + case .failure(let error): + print(error) + } +} +``` + + +## `class` Wallet + +```swift +class Wallet +``` +A class which provides EOA functions. It enables you to create, transform to Keystore or load wallet from Keystore. + +### Initialize +```swift +init(privateKey: PrivateKey?) +``` + +#### Parameters +| Parameter | Type | Description | +| --- | --- | --- | +| privateKey | `PrivateKey` | If privateKey is null, it generates new private key while initializing. | + +#### Returns +`Wallet` - Wallet instance. + +#### Example +```swift +// Create new wallet +let wallet = Wallet(prviateKey: nil) // will generate private key + +// Imports from exist private key +let privateKey = PrivateKey(hexData: privateKeyData) +let wallet = Wallet(privateKey: privateKey) +``` + +```swift +// Loading wallets and storing the Keystore + +// Save wallet keystore. +let wallet = Wallet(privateKey: nil) +do { + try wallet.generateKeystore(password: "YOUR_WALLET_PASSWORD") + try wallet.save(filepath: "YOUR_STORAGE_PATH") +} catch { + // handle errors +} + +// Load a wallet from the keystore. +do { + let jsonData: Data = try Data(contentsOf: "YOUR_KEYSTORE_PATH") + let decoder = JSONDecoder() + let keystore = try decoder.decoder(Keystore.self, from: jsonData) + let wallet = Wallet(keystore: keystore, password: "YOUR_WALLET_PASSWORD") +} catch { + // handle errors +} +``` + +### `func` getSignature + +Generate signature string by signing transaction data. +```swift +func getSignature(data: Data) throws -> String +``` + +#### Parameter +| Parameter | Type | Description | +| --- | --- | --- | +| data | `Data` | the serialized transaction data. | + +#### Returns +`String` - A signature string.(**Base64 encoded**) + +#### Example +```swift +let wallet = Wallet(privateKey: nil) +do { + let signature = try wallet.getSignature(data: toBeSigned) + print("signature - \(signature)") +} catch { + // handle error +} +``` + +### Properties + +| Property | Type | Description | +| --- | --- | --- | +| address | `String` | Return wallet's address (read-only) | + + + +## `class` Transaction + +```swift +class Transaction +``` +`Transaction` is a class representing a transaction data used for sending ICX. + +### Initialize + +```swift +// Create empty transaction object +init() +// Create transaction with data +convenience init(from: String, to: String, stepLimit: BigUInt, nid: String, value: BigUInt, nonce: String, dataType: String? = nil, data: Any? = nil) +``` + +#### Parameters + +| Parameter | Description | +| --------- | ------------------------------------------------------------ | +| from | An EOA address that creates the transaction. | +| to | An EOA address to receive coins or SCORE address to execute the transaction. | +| stepLimit | Amounts of Step limit. | +| nid | A network ID. | +| value | Sending the amount of ICX in loop unit. | +| nonce | An arbitrary number used to prevent transaction hash collision. | + +### `func` from + +Setter for `from` property. +```swift +func from(_ from: String) -> Self +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| from | `String` | An EOA address that creates the transaction. | + +#### Returns + +Returns `Transaction` itself. + +#### Example + +```swift +// Set from property +let transaction = Transaction() + .from("hx9043346dbaa72bca42ecec6b6e22845a4047426d") +``` + +### `func` to + +Setter for `to` property. +```swift +func to(_ to: String) -> Self +``` + +#### Paramters + +| Paramter | Type | Description | +| --- | --- | --- | +| to | `String` | An EOA or SCORE address. | + +#### Returns + +Returns `Transaction` itself. + +#### Example + +```swift +let transaction = Transaction() + .to("hx2e26d96bd7f1f46aac030725d1e302cf91420458") +``` + +### `func` stepLimit + +Setter for `setpLimit` property. +```swift +func stepLimit(_ limit: BigUInt) -> Self +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| limit | `BigUInt` | Amounts of Step limit | + +#### Returns + +Returns `Transaction` itself. + +#### Example + +```swift +let transaction = Transaction() + .stepLimit(BigUInt(1000000)) +``` + +### `func` nid + +Setter for `nid` property. +```swift +func nid(_ nid: String) -> Self +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| nid | `String` | A network ID. (Mainnet = "0x1", Testnet = "0x2", [etc](https://github.com/icon-project/icon-project.github.io/blob/master/docs/icon_network.md)) | + +#### Returns + +Returns `Transaction` itself. + +#### Example + +```swift +let transaction = Transaction() + .nid("0x1") +``` + +### `func` value + +Setter for `value` property. +```swift +func value(_ value: BigUInt) -> Self +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| value | `BigUInt` | Sending amount of ICX in loop unit. (1 ICX = 1018 loop) | + +#### Returns + +Returns `Transaction` itself. + +#### Example + +```swift +let transaction = Transaction() + .value(BigUInt(15000000)) +``` + +### `func` nonce + +Setter for `nonce` property. +```swift +func nonce(_ nonce: String) -> Self +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| nonce | `String` | A nonce value. | + +#### Returns + +Returns `Transaction` itself. + +#### Example + +```swift +let transaction = Transaction() + .nonce("0x1") +``` + +```swift +// Creating transaction instance for Sending ICX. +let transaction = Transaction() + .from("hx9043346dbaa72bca42ecec6b6e22845a4047426d") + .to("hx2e26d96bd7f1f46aac030725d1e302cf91420458") + .value(BigUInt(15000000)) + .stepLimit(BigUInt(1000000)) + .nid("0x1") + .nonce("0x1") +``` + +## `class` CallTransaction + +```swift +class CallTransaction: Transaction +``` + +`CallTransaction` class is used for invoking a state-transition function of SCORE. It extends `Transaction` class, so instance parameters and methods of the class are mostly identical to `Transaction` class, except for the following: + +#### Parameters + +| Parameters | Description | +| ---------- | ----------------------------- | +| method | The method name of SCORE API. | +| params | The input params for method. | + +For details of extended parameters and methods, see [Transaction](#Transaction) section. + +### `func` method + +Transaction for invoking a *state-transition* function of SCORE. + +*Transaction parameter `dataType` will be fixed with `call`* + +```swift +func method(_ method: String) -> Self +``` + +**Parameters** + +| Parameter | Type | Description | +| --------- | -------- | ----------------------------- | +| method | `String` | the method name of SCORE API. | + +**Returns** + +Returns `CallTransaction` itself. + +#### params + +The input parameters of the SCORE method that will be executed by `call` function. + +```swift +func params(_ params: [String: Any]) -> Self +``` + +**Parameter** + +| Parameter | Type | Description | +| --------- | ------------------------- | --------------------------------- | +| params | `Dictionary` | Input parameters for call method. | + +**Returns** + +Returns `CallTransaction` itself. + +#### Example + +```swift +// Creating transaction instance for SCORE function call +let call = CallTransaction() + .from(wallet.address) + .to("cx000...001") + .stepLimit(BigUInt(1000000)) + .nid(self.iconService.nid) + .nonce("0x1") + .method("transfer") + .params(["_to": to, "_value": "0x1234"]) +``` + +## `class` MessageTransaction + +```swift +class MessageTransaction: Transaction +``` + +`MessageTransaction` class is used for sending message data. It extends `Transaction` class, so instance parameters and methods of the class are mostly identical to `Transaction` class, except for the following: + +#### Parameters + +| Parameters | Description | +| ---------- | ------------------ | +| message | A message to send. | + +For details of extended parameters and methods, see [Transaction](#section--class-transaction) section. + +### `func` message + +Send messages. + +*Transaction parameter `dataType` will be fixed with `message`.* + +```swift +func message(_ message: String) -> Self +``` + +#### Parameters + +| Parameter | Type | Description | +| --- | --- | --- | +| message | `String` | A message String. | + +#### Returns + +Returns `MessageTransaction` itself. + +#### Example + +```swift +// Creating transaction instance for transfering message. +let messageTransaction = MessageTransaction() + .from("hx9043346dbaa72bca42ecec6b6e22845a4047426d") + .to("hx2e26d96bd7f1f46aac030725d1e302cf91420458") + .value(BigUInt(15000000)) + .stepLimit(BigUInt(1000000)) + .nonce("0x1") + .nid("0x1") + .message("Hello, ICON!") +``` + +## `class` SignedTransaction + +`SignedTransaction` is a class to make a signed transaction. + +### Initialize + +```swift +init(transaction: Transaction, privateKey: PrivateKey) +``` + +#### Parameters + +| Parameter | Type | Description | +| ----------- | ------------- | ---------------------------------- | +| transaction | `Transaction` | A transaction that will be signed. | +| privateKey | `PrivateKey` | A privateKey. | + +#### Example + +```swift +let signed = try SignedTransaction(transaction: transaction, privateKey: yourPrivateKey) +``` + +## ICError + +There are 5 types of errors. + +- **emptyKeystore** - Keystore is empty. + +- **invalid** + - missing(parameter: JSONParameterKey) - Missing JSON parameter. + - malformedKeystore - Keystore data malformed. + - wrongPassword - Wrong password. + +- **fail** + - sign - Failed to sign. + - parsing - Failed to parse. + - decrypt - Failed to decrypt. + - convert - Failed to convert to URL or data. + +- **error(error: Error)** + +- **message(error: String**) - [JSON RPC Error Messages](icon-json-rpc-v3#section-json-rpc-error-codes) + +## Converter Functions + +ICONKit supports converter functions. + +### convert() + +Convert ICX or gLoop to loop. + +> 1 ICX = 10 9 gLoop = 1018 loop + +#### Paramters + +| Parameters | Type | Description | +| ---------- | ------ | ------------------------------------------------------------ | +| unit | `Unit` | The unit of value( `.icx`, `.gLoop`, `.loop` ). Default value is `.icx`. | + +#### Returns + +`BigUInt` - The value that converted to loop. + +#### Example + +```swift +let balance: BigUInt = 100 + +// Convert ICX to loop. +let ICXToLoop: BigUInt = balance.convert() // 100000000000000000000 + +// Convert gLoop to loop +let gLoopToLoop: BigUInt = balance.convert(unit: .gLoop) // 100000000000 +``` + +### toHexString() + +Convert `BigUInt` value to hex `String`. + +```swift +public func toHexString(unit: Unit = .loop) -> String +``` + +#### Parameters + +| Parameters | Type | Description | +| ---------- | ------ | ------------------------------------------------------------ | +| unit | `Unit` | The unit of value( `.icx`, `.gLoop`, `.loop` ). Default value is `.loop`. | + +#### Returns + +`String` - The value converted to a hex String. + +#### Example + +```swift +// Convert `BigUInt` value to hex `String`. +let ICXToLoop: BigUInt = 100000000000000000000 +let hexString: String = ICXToLoop.toHexString() // 0x56bc75e2d63100000 +``` + +### hexToBigUInt() + +Convert hex `String` to `BigUInt`. + +```swift +public func hexToBigUInt(unit: Unit = .loop) -> BigUInt? +``` + +#### Parameters + +| Parameters | Type | Description | +| ---------- | ------ | ------------------------------------------------------------ | +| unit | `Unit` | The unit of value( `.icx`, `.gLoop`, `.loop` ). Default value is `.loop`. | + +#### Returns + +`BigUInt` - The value that converted to hex String. + +If the conversion is failed, return `nil`. + +#### Example + +```swift +// Convert hex `String` to `BigUInt`. +let hexString: String = "0x56bc75e2d63100000" +let hexBigUInt: BigUInt = hexString.hexToBigUInt()! // 100000000000000000000 +``` + +## References + +- [ICON JSON-RPC API v3](icon-json-rpc-v3) +- [ICON Network](the-icon-network) diff --git a/references/swift-sdk.md b/references/swift-sdk.md new file mode 100644 index 0000000..3014949 --- /dev/null +++ b/references/swift-sdk.md @@ -0,0 +1,576 @@ +--- +title: "Swift SDK" +excerpt: "The source code is found on Github at https://github.com/icon-project/ICONKit" +--- + +ICON supports SDK for 3rd party or user services development. You can integrate ICON SDK for your project and utilize ICON’s functionality. This document provides you with information on installation and basic usage guideline. + +Get different types of examples as follows. + +| Example | Description | +| --------------------------------- | ------------------------------------------------------------ | +| [Wallet](#wallet) | An example of creating and loading a keywallet. | +| [ICX Transfer](#icx-transfer) | An example of transferring ICX and confirming the result. | +| [Token Transfer](#token-transfer) | An example of deploying an IRC token, transferring the token and confirming the result. | +| [Sync Block](#sync-block) | An example of checking block confirmation and printing the ICX and token transfer information. | + +## Prerequisite + +This SDK works on the following platforms: + +- Xcode 10 or higher +- iOS 10 or higher +- Swift 4.2 +- [Cocoapods](https://cocoapods.org) + +## Installation + +[CocoaPods](https://cocoapods.org/) is a dependency manager for Swift Cocoa projects. + +```shell +$ sudo gem install cocoapods +``` + +To integrate ICONKit into your project, specify it in your `Podfile` + +``` +target '' do + use_frameworks! + ... + pod 'ICONKit', '~> 0.3.1' + ... +end +``` + +Now install the ICONKit + +```shell +$ pod install +``` + + + +## Using the SDK + +### Result + +ICONKit uses [Result](https://github.com/antitypical/Result) framework. All functions of ICONService returns `Result`. `T` for successor, `ICONResult` for error. Refer to [Result](https://github.com/antitypical/Result) for more detail. + +### ICONService + +APIs are called through `ICONService`. It can be initialized as follows. + +```swift +let iconService = ICONService(provider: "https://ctz.solidwallet.io/api/v3", nid: "0x1") +``` + +A simple query of a block by height is as follows. + +```swift +// ICON Mainnet +let iconService = ICONService(provider: "https://ctz.solidwallet.io/api/v3", nid: "0x1") + +// Gets a block matching the block height. +let request: Request = iconService.getBlock(height: height) +let result = request.execute() + +switch result { +case .success(let responseBlock): + ... +case .failure(let error): + ... +} +``` + +### Queries + +All queries are requested by a `Request`. + +#### Synchronous query +`execute()` requests a query synchronously. + +```swift +let response = iconService.getLastBlock().execute() + +switch response { +case .success(let responseBlock): + print(responseBlock.blockHash) + ... +case .failure(let error): + print(error.errorDescription) + ... +} +``` + +#### Asynchronous query + +You can request a query asynchronously using an `async` closure as below. + +```swift +iconService.getLastBlock().async { (result) in + switch result { + case .success(let responseBlock): + print(responseBlock.blockHash) + ... + case .failure(let error): + print(err.errorDescription) + ... + } +} +``` + + + +The querying APIs are as follows. + +* [getLastBlock](#section-getlastblock) +* [getBlock(height)](#section-getblock-height-) +* [getBlock(hash)](#section-getblock-hash-) +* [call](#section-call) +* [getBalance](#section-getbalance) +* [getScoreAPI](#section-getscoreapi) +* [getTotalSupply](#section-gettotalsupply) +* [getTransaction](#section-gettransaction) +* [getTransactionResult](#section-gettransactionresult) + + +#### getLastBlock + +Gets the last block information. + +```swift +let request: Request = iconService.getLastBlock() +``` + +#### getBlock(height) + +Gets block information by block height. + +```swift +let request: Request = iconService.getBlock(height: height) +``` + +#### getBlock(hash) + +Gets block information by block hash. + +```swift +let request: Request = iconService.getBlock(hash: "0x000...000") +``` + +#### call + +Calls a SCORE read-only API. +Use the return type of method's outputs you want to call in generic type. +For example, the type of output that is `String` use `String`. + +```swift +let call = Call(from: wallet.address, to: scoreAddress, method: "name", params: params) +let request: Request = iconService.call(call) +let response: Result = request.execute() +``` + +If the output type of method is hex String (ex. `"0x56bc75e2d63100000"`), you can use `String` and `BigUInt` too! +Just input `BigUInt` at generic type, then ICONKit convert the output value to BigUInt. +If you want to use hex `String`, use `String`. + +```swift +// Using `BigUInt` +let call = Call(from: wallet.address, to: scoreAddress, method: "balanceOf", params: params) +let request: Request = iconService.call(call) +let response: Result = request.execute() // return 100000000000000000000 or ICError + +// Using `String` +let call = Call(from: wallet.address, to: scoreAddress, method: "balanceOf", params: params) +let request: Request = iconService.call(call) +let response: Result = request.execute() // return "0x56bc75e2d63100000" or ICError +``` + +#### getBalance + +Gets the balance of a given account. + +```swift +let request: Request = iconService.getBalance(address: "hx000...1") +``` + +#### getScoreAPI + +Gets the list of APIs that the given SCORE exposes. + +```swift +let request: Request = iconService.getScoreAPI(scoreAddress: "cx000...1") +``` + +#### getTotalSupply + +Gets the total supply of ICX. + +```swift +let request: Request = iconService.getTotalSupply() +``` + +#### getTransaction + +Gets a transaction matching the given transaction hash. + +```swift +let request: Request = iconService.getTransaction(hash: "0x000...000") +``` + +#### getTransactionResult + +Gets the transaction result requested by transaction hash. + +```swift +let request: Request = iconService.getTransactionResult(hash: "0x000...000") +``` + + + +### Transactions + +Calling SCORE APIs to change states is requested as sending a transaction. + +Before sending a transaction, the transaction should be signed. It can be done using a `Wallet` object. + +#### Loading wallets and storing the keystore + +```swift +// Generates a wallet. +let wallet = Wallet(privateKey: nil) + +// Load a wallet from the private key. +let privateKey = PrivateKey(hex: data) +let wallet = Wallet(privateKey: privateKey) + +// Save wallet keystore. +let wallet = Wallet(privateKey: nil) +do { + try wallet.generateKeystore(password: "YOUR_WALLET_PASSWORD") + try wallet.save(filepath: "YOUR_STORAGE_PATH") +} catch { + // handle errors +} +// Load a wallet from the keystore. +do { + let jsonData: Data = try Data(contentsOf: "YOUR_KEYSTORE_PATH") + let decoder = JSONDecoder() + let keystore = try decoder.decoder(Keystore.self, from: jsonData) + let wallet = Wallet(keystore: keystore, password: "YOUR_WALLET_PASSWORD") +} catch { + // handle errors +} +``` + +#### Creating transactions + +```swift +// Sending ICX +let coinTransfer = Transaction() + .from(wallet.address) + .to(to) + .value(BigUInt(15000000)) + .stepLimit(BigUInt(1000000)) + .nid(self.iconService.nid) + .nonce("0x1") + +// SCORE function call +let call = CallTransaction() + .from(wallet.address) + .to(scoreAddress) + .stepLimit(BigUInt(1000000)) + .nid(self.iconService.nid) + .nonce("0x1") + .method("transfer") + .params(["_to": to, "_value": "0x1234"]) + +// Message transfer +let transaction = MessageTransaction() + .from(wallet.address) + .to(to) + .value(BigUInt(15000000)) + .stepLimit(BigUInt(1000000)) + .nonce("0x1") + .nid(self.iconService.nid) + .message("Hello, ICON!") +``` + +#### Sending requests + +`SignedTransaction` object signs a transaction using the wallet. + +And a request is executed as **Synchronized** or **Asynchronized** like a querying request. + +**Synchronous request** + +```swift +do { + let signed = try SignedTransaction(transaction: coinTransfer, privateKey: privateKey) + let request = iconService.sendTransaction(signedTransaction: signed) + let response = request.execute() + + switch response { + case .result(let result): + print("SUCCESS: TXHash - \(result)") + ... + case .error(let error): + print("FAIL: \(error.errorDescription)") + ... + } +} catch { + print(error) + ... +} +``` + +**Asynchronous request** + +```swift +do { + let signed = try SignedTransaction(transaction: coinTransfer, privateKey: privateKey) + let request = iconService.sendTransaction(signedTransaction: signed) + + request.async { (result) in + switch result { + case .success(let result): + print(result) + ... + case .failure(let error): + print(error.errorDescription) + ... + } + } +} catch { + print(error) +} +``` + +### Utils + +ICONKit supports converter functions. + +```swift +// Convert ICX or gLoop to loop. +let balance: BigUInt = 100 +let ICXToLoop: BigUInt = balance.convert() // 100000000000000000000 +let gLoopToLoop: BigUInt = balance.convert(unit: .gLoop) // 100000000000 + +// Convert `BigUInt` value to HEX `String`. +let hexString: String = ICXToLoop.toHexString() // 0x56bc75e2d63100000 + +// Convert HEX `String` to `BigUInt`. +let hexBigUInt: BigUInt = hexString.hexToBigUInt()! // 100000000000000000000 + +// Convert HEX `String` to `Date` +let timestamp: NSString = "0x5850adcbaa178" +let confirmedDate: Date = timestamp.hexToDate()! // 2019-03-27 03:16:22 +0000 +``` + + + + +## Code Examples + +### Wallet + +#### Create a wallet +```swift +// Create wallet with new private key. +let wallet = Wallet(privateKey: nil) + +// Create wallet with exist private key. +let privateKey = PrivateKey(hex: YOUR_PRIVATE_KEY_DATA) +let wallet = Wallet(privateKey: privateKey) +``` + +#### Load a wallet +```swift + // Load a wallet from the keystore. +do { + let jsonData: Data = try Data(contentsOf: "YOUR_KEYSTORE_PATH") + let decoder = JSONDecoder() + let keystore = try decoder.decoder(Keystore.self, from: jsonData) + let wallet = Wallet(keystore: keystore, password: "YOUR_WALLET_PASSWORD") +} catch { + // handle errors +} +``` + +#### Store the wallet +```swift +do { + try wallet.generateKeystore(password: "YOUR_WALLET_PASSWORD") + try wallet.save(filepath: "YOUR_STORAGE_PATH") +} catch { + // handle errors +} +``` + +### ICX Transfer + +#### ICX transfer transaction +```swift +// Sending ICX +let coinTransfer = Transaction() + .from(wallet.address) + .to(to) + .value(BigUInt(15000000)) + .stepLimit(BigUInt(1000000)) + .nid(self.iconService.nid) + .nonce("0x1") + +do { + let signed = try SignedTransaction(transaction: coinTransfer, privateKey: privateKey) + let request = iconService.sendTransaction(signedTransaction: signed) + let response = request.execute() + + switch response { + case .result(let result): + print("SUCCESS: TXHash - \(result)") + ... + case .error(let error): + print("FAIL: \(error.errorDescription)") + ... + } +} catch { + print(error) + ... +} +``` + +#### Check the transaction result + +```swift +let request: Request = iconService.getTransactionResult(hash: "0x000...000") + +let result = request.execute() +switch result { +case .success(let transactionResult): + print("tx result - \(transactionResult)") + +case .failure(let error): + // handle error +} +``` + +#### Check the ICX balance + +```swift +let iconService = ICONService(SELECTED_PROVIDER, nid: NID) +let result = iconService.getBalance(address: wallet.address).execute() + +switch result { +case .success(let balance): + print("balance - \(balance)") + +case .failure(let error): + // handle error +} +``` + +### Token Transfer + +#### Token transfer transaction +```swift +let call = CallTransaction() + .from(wallet.address) + .to(scoreAddress) + .stepLimit(BigUInt(1000000)) + .nid(self.iconService.nid) + .nonce("0x1") + .method("transfer") + .params(["_to": to, "_value": "0x1234"]) + +do { + let signed = try SignedTransaction(transaction: call, privateKey: privateKey) + let request = iconService.sendTransaction(signedTransaction: signed) + let response = request.execute() + + switch response { + case .result(let result): + print("SUCCESS: TXHash - \(result)") + ... + case .error(let error): + print("FAIL: \(error.errorDescription)") + ... + } +} catch { + print(error) + ... +} +``` + +#### Check the token balance + +If the output type of method is hex String (ex. `"0x56bc75e2d63100000"`), you can use `String` and `BigUInt` too! +Just input `BigUInt` at generic type, then ICONKit convert the output value to BigUInt. +If you want to use hex `String`, use `String`. + +```swift +// Using `BigUInt` +let call = Call(from: wallet.address, to: scoreAddress, method: "balanceOf", params: params) +let request: Request = iconService.call(call) +let response: Result = request.execute() // return 100000000000000000000 or ICError + +// Using `String` +let call = Call(from: wallet.address, to: scoreAddress, method: "balanceOf", params: params) +let request: Request = iconService.call(call) +let response: Result = request.execute() // return "0x56bc75e2d63100000" or ICError +``` + +### Sync Block + +#### Read block information + +```swift +// get last block +let request: Request = iconService.getLastBlock() +// get block by height +let request: Request = iconService.getBlock(height: height) +// get block by hash +let request: Request = iconService.getBlock(hash: "0x000...000") + +let result = request.execute() +switch result { +case .success(let block): + print("block info - \(block)") + +case .failure: + // handle error +} +``` + +#### Transaction output +```swift +let request: Request = iconService.getTransaction(hash: "0x000...000") + +let result = request.execute() +switch result { +case .success(let transaction): + print("transaction - \(transaction)") + +case .failure(let error): + // handle error +} +``` + +#### Check the token name & symbol + +```swift +let call = Call(from: wallet.address, to: scoreAddress, method: "name", params: params) +let request: Request = iconService.call(call) +let response: Result = request.execute() +``` + + + +## References + +- [ICON JSON-RPC API v3](icon-json-rpc-v3) +- [ICON Network](the-icon-network) + + +## Licenses + +This project follows the Apache 2.0 License. Please refer to [LICENSE](https://www.apache.org/licenses/LICENSE-2.0) for details.