Swift SDK
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 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​
An example of creating and loading a keywallet.
​ICX Transfer​
An example of transferring ICX and confirming the result.
​Token Transfer​
An example of deploying an IRC token, transferring the token and confirming the result.
​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​

Installation

​CocoaPods is a dependency manager for Swift Cocoa projects.
1
$ sudo gem install cocoapods
To integrate ICONKit into your project, specify it in your Podfile
1
target '<Your Target Name>' do
2
use_frameworks!
3
...
4
pod 'ICONKit', '~> 0.3.1'
5
...
6
end
Now install the ICONKit
1
$ pod install

Using the SDK

Result

ICONKit uses Result framework. All functions of ICONService returns Result<T, ICONResult>. T for successor, ICONResult for error. Refer to Result for more detail.

ICONService

APIs are called through ICONService. It can be initialized as follows.
1
let iconService = ICONService(provider: "https://ctz.solidwallet.io/api/v3", nid: "0x1")
A simple query of a block by height is as follows.
1
// ICON Mainnet
2
let iconService = ICONService(provider: "https://ctz.solidwallet.io/api/v3", nid: "0x1")
3
​
4
// Gets a block matching the block height.
5
let request: Request<Response.Block> = iconService.getBlock(height: height)
6
let result = request.execute()
7
​
8
switch result {
9
case .success(let responseBlock):
10
...
11
case .failure(let error):
12
...
13
}

Queries

All queries are requested by a Request<T>.
Synchronous query
execute() requests a query synchronously.
1
let response = iconService.getLastBlock().execute()
2
​
3
switch response {
4
case .success(let responseBlock):
5
print(responseBlock.blockHash)
6
...
7
case .failure(let error):
8
print(error.errorDescription)
9
...
10
}
Asynchronous query
You can request a query asynchronously using an async closure as below.
1
iconService.getLastBlock().async { (result) in
2
switch result {
3
case .success(let responseBlock):
4
print(responseBlock.blockHash)
5
...
6
case .failure(let error):
7
print(err.errorDescription)
8
...
9
}
10
}
The querying APIs are as follows.
getLastBlock
Gets the last block information.
1
let request: Request<Response.Block> = iconService.getLastBlock()
getBlock(height)
Gets block information by block height.
1
let request: Request<Response.Block> = iconService.getBlock(height: height)
getBlock(hash)
Gets block information by block hash.
1
let request: Request<Response.Block> = 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.
1
let call = Call<String>(from: wallet.address, to: scoreAddress, method: "name", params: params)
2
let request: Request<String> = iconService.call(call)
3
let response: Result<String, ICError> = 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.
1
// Using `BigUInt`
2
let call = Call<BigUInt>(from: wallet.address, to: scoreAddress, method: "balanceOf", params: params)
3
let request: Request<BigUInt> = iconService.call(call)
4
let response: Result<BigUInt, ICError> = request.execute() // return 100000000000000000000 or ICError
5
​
6
// Using `String`
7
let call = Call<String>(from: wallet.address, to: scoreAddress, method: "balanceOf", params: params)
8
let request: Request<String> = iconService.call(call)
9
let response: Result<String, ICError> = request.execute() // return "0x56bc75e2d63100000" or ICError
getBalance
Gets the balance of a given account.
1
let request: Request<BigUInt> = iconService.getBalance(address: "hx000...1")
getScoreAPI
Gets the list of APIs that the given SCORE exposes.
1
let request: Request<Response.ScoreAPI> = iconService.getScoreAPI(scoreAddress: "cx000...1")
getTotalSupply
Gets the total supply of ICX.
1
let request: Request<BigUInt> = iconService.getTotalSupply()
getTransaction
Gets a transaction matching the given transaction hash.
1
let request: Request<Response.TransactionByHashResult> = iconService.getTransaction(hash: "0x000...000")
getTransactionResult
Gets the transaction result requested by transaction hash.
1
let request: Request<Response.TransactionResult> = 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
1
// Generates a wallet.
2
let wallet = Wallet(privateKey: nil)
3
​
4
// Load a wallet from the private key.
5
let privateKey = PrivateKey(hex: data)
6
let wallet = Wallet(privateKey: privateKey)
7
​
8
// Save wallet keystore.
9
let wallet = Wallet(privateKey: nil)
10
do {
11
try wallet.generateKeystore(password: "YOUR_WALLET_PASSWORD")
12
try wallet.save(filepath: "YOUR_STORAGE_PATH")
13
} catch {
14
// handle errors
15
}
16
// Load a wallet from the keystore.
17
do {
18
let jsonData: Data = try Data(contentsOf: "YOUR_KEYSTORE_PATH")
19
let decoder = JSONDecoder()
20
let keystore = try decoder.decoder(Keystore.self, from: jsonData)
21
let wallet = Wallet(keystore: keystore, password: "YOUR_WALLET_PASSWORD")
22
} catch {
23
// handle errors
24
}
Creating transactions
1
// Sending ICX
2
let coinTransfer = Transaction()
3
.from(wallet.address)
4
.to(to)
5
.value(BigUInt(15000000))
6
.stepLimit(BigUInt(1000000))
7
.nid(self.iconService.nid)
8
.nonce("0x1")
9
​
10
// SCORE function call
11
let call = CallTransaction()
12
.from(wallet.address)
13
.to(scoreAddress)
14
.stepLimit(BigUInt(1000000))
15
.nid(self.iconService.nid)
16
.nonce("0x1")
17
.method("transfer")
18
.params(["_to": to, "_value": "0x1234"])
19
​
20
// Message transfer
21
let transaction = MessageTransaction()
22
.from(wallet.address)
23
.to(to)
24
.value(BigUInt(15000000))
25
.stepLimit(BigUInt(1000000))
26
.nonce("0x1")
27
.nid(self.iconService.nid)
28
.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
1
do {
2
let signed = try SignedTransaction(transaction: coinTransfer, privateKey: privateKey)
3
let request = iconService.sendTransaction(signedTransaction: signed)
4
let response = request.execute()
5
​
6
switch response {
7
case .result(let result):
8
print("SUCCESS: TXHash - \(result)")
9
...
10
case .error(let error):
11
print("FAIL: \(error.errorDescription)")
12
...
13
}
14
} catch {
15
print(error)
16
...
17
}
Asynchronous request
1
do {
2
let signed = try SignedTransaction(transaction: coinTransfer, privateKey: privateKey)
3
let request = iconService.sendTransaction(signedTransaction: signed)
4
​
5
request.async { (result) in
6
switch result {
7
case .success(let result):
8
print(result)
9
...
10
case .failure(let error):
11
print(error.errorDescription)
12
...
13
}
14
}
15
} catch {
16
print(error)
17
}

Utils

ICONKit supports converter functions.
1
// Convert ICX or gLoop to loop.
2
let balance: BigUInt = 100
3
let ICXToLoop: BigUInt = balance.convert() // 100000000000000000000
4
let gLoopToLoop: BigUInt = balance.convert(unit: .gLoop) // 100000000000
5
​
6
// Convert `BigUInt` value to HEX `String`.
7
let hexString: String = ICXToLoop.toHexString() // 0x56bc75e2d63100000
8
​
9
// Convert HEX `String` to `BigUInt`.
10
let hexBigUInt: BigUInt = hexString.hexToBigUInt()! // 100000000000000000000
11
​
12
// Convert HEX `String` to `Date`
13
let timestamp: NSString = "0x5850adcbaa178"
14
let confirmedDate: Date = timestamp.hexToDate()! // 2019-03-27 03:16:22 +0000

Code Examples

Wallet

Create a wallet
1
// Create wallet with new private key.
2
let wallet = Wallet(privateKey: nil)
3
​
4
// Create wallet with exist private key.
5
let privateKey = PrivateKey(hex: YOUR_PRIVATE_KEY_DATA)
6
let wallet = Wallet(privateKey: privateKey)
Load a wallet
1
// Load a wallet from the keystore.
2
do {
3
let jsonData: Data = try Data(contentsOf: "YOUR_KEYSTORE_PATH")
4
let decoder = JSONDecoder()
5
let keystore = try decoder.decoder(Keystore.self, from: jsonData)
6
let wallet = Wallet(keystore: keystore, password: "YOUR_WALLET_PASSWORD")
7
} catch {
8
// handle errors
9
}
Store the wallet
1
do {
2
try wallet.generateKeystore(password: "YOUR_WALLET_PASSWORD")
3
try wallet.save(filepath: "YOUR_STORAGE_PATH")
4
} catch {
5
// handle errors
6
}

ICX Transfer

ICX transfer transaction
1
// Sending ICX
2
let coinTransfer = Transaction()
3
.from(wallet.address)
4
.to(to)
5
.value(BigUInt(15000000))
6
.stepLimit(BigUInt(1000000))
7
.nid(self.iconService.nid)
8
.nonce("0x1")
9
​
10
do {
11
let signed = try SignedTransaction(transaction: coinTransfer, privateKey: privateKey)
12
let request = iconService.sendTransaction(signedTransaction: signed)
13
let response = request.execute()
14
​
15
switch response {
16
case .result(let result):
17
print("SUCCESS: TXHash - \(result)")
18
...
19
case .error(let error):
20
print("FAIL: \(error.errorDescription)")
21
...
22
}
23
} catch {
24
print(error)
25
...
26
}
Check the transaction result
1
let request: Request<Response.TransactionResult> = iconService.getTransactionResult(hash: "0x000...000")
2
​
3
let result = request.execute()
4
switch result {
5
case .success(let transactionResult):
6
print("tx result - \(transactionResult)")
7
​
8
case .failure(let error):
9
// handle error
10
}
Check the ICX balance
1
let iconService = ICONService(SELECTED_PROVIDER, nid: NID)
2
let result = iconService.getBalance(address: wallet.address).execute()
3
​
4
switch result {
5
case .success(let balance):
6
print("balance - \(balance)")
7
​
8
case .failure(let error):
9
// handle error
10
}

Token Transfer

Token transfer transaction
1
let call = CallTransaction()
2
.from(wallet.address)
3
.to(scoreAddress)
4
.stepLimit(BigUInt(1000000))
5
.nid(self.iconService.nid)
6
.nonce("0x1")
7
.method("transfer")
8
.params(["_to": to, "_value": "0x1234"])
9
​
10
do {
11
let signed = try SignedTransaction(transaction: call, privateKey: privateKey)
12
let request = iconService.sendTransaction(signedTransaction: signed)
13
let response = request.execute()
14
​
15
switch response {
16
case .result(let result):
17
print("SUCCESS: TXHash - \(result)")
18
...
19
case .error(let error):
20
print("FAIL: \(error.errorDescription)")
21
...
22
}
23
} catch {
24
print(error)
25
...
26
}
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.
1
// Using `BigUInt`
2
let call = Call<BigUInt>(from: wallet.address, to: scoreAddress, method: "balanceOf", params: params)
3
let request: Request<BigUInt> = iconService.call(call)
4
let response: Result<BigUInt, ICError> = request.execute() // return 100000000000000000000 or ICError
5
​
6
// Using `String`
7
let call = Call<String>(from: wallet.address, to: scoreAddress, method: "balanceOf", params: params)
8
let request: Request<String> = iconService.call(call)
9
let response: Result<String, ICError> = request.execute() // return "0x56bc75e2d63100000" or ICError

Sync Block

Read block information
1
// get last block
2
let request: Request<Response.Block> = iconService.getLastBlock()
3
// get block by height
4
let request: Request<Response.Block> = iconService.getBlock(height: height)
5
// get block by hash
6
let request: Request<Response.Block> = iconService.getBlock(hash: "0x000...000")
7
​
8
let result = request.execute()
9
switch result {
10
case .success(let block):
11
print("block info - \(block)")
12
​
13
case .failure:
14
// handle error
15
}
Transaction output
1
let request: Request<Response.TransactionByHashResult> = iconService.getTransaction(hash: "0x000...000")
2
​
3
let result = request.execute()
4
switch result {
5
case .success(let transaction):
6
print("transaction - \(transaction)")
7
​
8
case .failure(let error):
9
// handle error
10
}
Check the token name & symbol
1
let call = Call<String>(from: wallet.address, to: scoreAddress, method: "name", params: params)
2
let request: Request<String> = iconService.call(call)
3
let response: Result<String, ICError> = request.execute()

References

Licenses

This project follows the Apache 2.0 License. Please refer to LICENSE for details.