title | excerpt |
---|---|
Swift SDK |
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 | 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>
.
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)
...
}
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
Gets the last block information.
let request: Request<Response.Block> = iconService.getLastBlock()
Gets block information by block height.
let request: Request<Response.Block> = iconService.getBlock(height: height)
Gets block information by block hash.
let request: Request<Response.Block> = iconService.getBlock(hash: "0x000...000")
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
Gets the balance of a given account.
let request: Request<BigUInt> = iconService.getBalance(address: "hx000...1")
Gets the list of APIs that the given SCORE exposes.
let request: Request<Response.ScoreAPI> = iconService.getScoreAPI(scoreAddress: "cx000...1")
Gets the total supply of ICX.
let request: Request<BigUInt> = iconService.getTotalSupply()
Gets a transaction matching the given transaction hash.
let request: Request<Response.TransactionByHashResult> = iconService.getTransaction(hash: "0x000...000")
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.
// 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
}
// 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!")
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 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 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
}
do {
try wallet.generateKeystore(password: "YOUR_WALLET_PASSWORD")
try wallet.save(filepath: "YOUR_STORAGE_PATH")
} catch {
// handle errors
}
// 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)
...
}
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
}
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
}
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)
...
}
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
// 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
}
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
}
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.