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. |
This SDK works on the following platforms:
- Xcode 10 or higher
- iOS 10 or higher
- Swift 4.2
- Cocoapods
CocoaPods is a dependency manager for Swift Cocoa projects.
$ sudo gem install cocoapods
To integrate ICONKit into your project, specify it in your Podfile
target '<Your Target Name>' do
use_frameworks!
...
pod 'ICONKit', '~> 0.3.1'
...
end
Now install the ICONKit
$ pod install
ICONKit uses Result framework. All functions of ICONService returns Result<T, ICONResult>
. T
for successor, ICONResult
for error. Refer to Result for more detail.
APIs are called through ICONService
. It can be initialized as follows.
let iconService = ICONService(provider: "https://ctz.solidwallet.io/api/v3", nid: "0x1")
A simple query of a block by height is as follows.
// ICON Mainnet
let iconService = ICONService(provider: "https://ctz.solidwallet.io/api/v3", nid: "0x1")
// Gets a block matching the block height.
let request: Request<Response.Block> = iconService.getBlock(height: height)
let result = request.execute()
switch result {
case .success(let responseBlock):
...
case .failure(let error):
...
}
All queries are requested by a Request<T>
.
Synchronous query
execute()
requests a query synchronously.
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.
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
- getBlock(height)
- getBlock(hash)
- call
- getBalance
- getScoreAPI
- getTotalSupply
- getTransaction
- getTransactionResult
getLastBlock
Gets the last block information.
let request: Request<Response.Block> = iconService.getLastBlock()
getBlock(height)
Gets block information by block height.
let request: Request<Response.Block> = iconService.getBlock(height: height)
getBlock(hash)
Gets block information by block hash.
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
.
let call = Call<String>(from: wallet.address, to: scoreAddress, method: "name", params: params)
let request: Request<String> = iconService.call(call)
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
.
// Using `BigUInt`
let call = Call<BigUInt>(from: wallet.address, to: scoreAddress, method: "balanceOf", params: params)
let request: Request<BigUInt> = iconService.call(call)
let response: Result<BigUInt, ICError> = request.execute() // return 100000000000000000000 or ICError
// Using `String`
let call = Call<String>(from: wallet.address, to: scoreAddress, method: "balanceOf", params: params)
let request: Request<String> = iconService.call(call)
let response: Result<String, ICError> = request.execute() // return "0x56bc75e2d63100000" or ICError
getBalance
Gets the balance of a given account.
let request: Request<BigUInt> = iconService.getBalance(address: "hx000...1")
getScoreAPI
Gets the list of APIs that the given SCORE exposes.
let request: Request<Response.ScoreAPI> = iconService.getScoreAPI(scoreAddress: "cx000...1")
getTotalSupply
Gets the total supply of ICX.
let request: Request<BigUInt> = iconService.getTotalSupply()
getTransaction
Gets a transaction matching the given transaction hash.
let request: Request<Response.TransactionByHashResult> = iconService.getTransaction(hash: "0x000...000")
getTransactionResult
Gets the transaction result requested by transaction hash.
let request: Request<Response.TransactionResult> = iconService.getTransactionResult(hash: "0x000...000")
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
// 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
// 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
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
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)
}
ICONKit supports converter functions.
// 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
Create a wallet
// 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
// 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
do {
try wallet.generateKeystore(password: "YOUR_WALLET_PASSWORD")
try wallet.save(filepath: "YOUR_STORAGE_PATH")
} catch {
// handle errors
}
ICX transfer transaction
// 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
let request: Request<Response.TransactionResult> = 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
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 transaction
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
.
// Using `BigUInt`
let call = Call<BigUInt>(from: wallet.address, to: scoreAddress, method: "balanceOf", params: params)
let request: Request<BigUInt> = iconService.call(call)
let response: Result<BigUInt, ICError> = request.execute() // return 100000000000000000000 or ICError
// Using `String`
let call = Call<String>(from: wallet.address, to: scoreAddress, method: "balanceOf", params: params)
let request: Request<String> = iconService.call(call)
let response: Result<String, ICError> = request.execute() // return "0x56bc75e2d63100000" or ICError
Read block information
// get last block
let request: Request<Response.Block> = iconService.getLastBlock()
// get block by height
let request: Request<Response.Block> = iconService.getBlock(height: height)
// get block by hash
let request: Request<Response.Block> = 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
let request: Request<Response.TransactionByHashResult> = 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
let call = Call<String>(from: wallet.address, to: scoreAddress, method: "name", params: params)
let request: Request<String> = iconService.call(call)
let response: Result<String, ICError> = request.execute()
This project follows the Apache 2.0 License. Please refer to LICENSE for details.