ICON supports SDK for 3rd party or user services development. You can integrate ICON SDK for your project and utilize ICON’s functionality.
- ICONKit now provide Swift 5
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.4.3'
...
end
Now install the ICONKit.
$ pod install
0.3.2 is a last version of ICONKit for Swift 4.x.
try
pod 'ICONKit', '0.3.2'
A simple query of the 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):
...
}
APIs called through ICONService
.
It can be initialized as follows.
let iconService = ICONService(provider: "https://ctz.solidwallet.io/api/v3", nid: "0x1")
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 a 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
- sendTransaction
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 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 an given account.
let request: Request<BigUInt> = iconService.getBalance(address: "hx000...1")
Gets a list of ScoreAPI.
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.
// 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 .success(let result):
print("SUCCESS: TXHash - \(result)")
...
case .failure(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)
}
It is important to set a proper stepLimit
value in your transaction to make the submitted transaction executed successfully.
estimateStep
API provides a way to estimate the Step usage of a given transaction. Using the method, you can get an estimated Step usage before sending your transaction then make a SignedTransaction
with the stepLimit
based on the estimation.
// Make a raw transaction without the stepLimit
let message = MessageTransaction()
.from(fromAddress)
.to(toAddress)
.nid(self.iconService.nid)
.message("Hello, ICON!")
// Estimate step
let estimateStepResponse = iconService.estimateStep(transaction: message).execute()
if let estimatedStepCost = try? estimateStepResponse.get() {
// Add some margin to estimated step
let stepLimit = estimatedStepCost + 10000
message.stepLimit(estimatedStepCost)
}
// Send transaction
do {
let signed = try SignedTransaction(transaction: message, privateKey: yourPrivateKey)
let response = self.iconService.sendTransaction(signedTransaction: signed).execute()
switch response {
case .success(let result):
print("Message tx result - \(result)")
case .failure(let error):
print(error)
}
} catch {
print(error)
}
Note that the estimation can be smaller or larger than the actual amount of step to be used by the transaction, so it is recommended to add some margin to the estimation when you set the stepLimit
of the SignedTransaction
.
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: String = "0x5850adcbaa178"
let confirmedDate: Date = timestamp.hexToDate()! // 2019-03-27 03:16:22 +0000
0.4.0
- Xcode 10 or higher
- iOS 10 or higher
- Swift 5
- Cocoapods
This project follows the Apache 2.0 License. Please refer to LICENSE for details.