From 254b2b48e0dc2b73f4a9565ef8e62a64e95ed150 Mon Sep 17 00:00:00 2001 From: Sojin Kim Date: Mon, 29 Apr 2019 12:40:51 +0900 Subject: [PATCH] merge into master to publish on icondev --- references/icon-json-rpc-v3.md | 1204 ++++++++++++++++++++++++++++++++ references/swift-sdk.md | 576 +++++++++++++++ 2 files changed, 1780 insertions(+) create mode 100644 references/icon-json-rpc-v3.md create mode 100644 references/swift-sdk.md diff --git a/references/icon-json-rpc-v3.md b/references/icon-json-rpc-v3.md new file mode 100644 index 0000000..2d25cf2 --- /dev/null +++ b/references/icon-json-rpc-v3.md @@ -0,0 +1,1204 @@ +--- +title: "ICON JSON-RPC API v3 Guide" +--- + +ICON JSON-RPC APIs (version 3) are interfaces to interact with ICON nodes. This document explains ICON JSON-RPC API (version 3) data structures, rules and the list of methods. + +## ICON JSON-RPC API v3 Specification + +### API Convention + +Follows [JSON-RPC 2.0 Specification](http://www.jsonrpc.org/specification). + +```javascript +// Request +{ + "jsonrpc": "2.0", + "method": "$STRING1", + "id": $INT, + "params": { + "$KEY1": "$VALUE1", + "$KEY2": { + "method": "$STRING2", + "params": { + "$KEY3": "$VALUE3" + } + } + } +} + +// Response - success +{ + "jsonrpc": "2.0", + "id": $INT, + "result": "$STRING" + // or + "result": { + "$KEY1": "$VALUE1", + "$KEY2": "$VALUE2" + } +} + +// Response - error +{ + "jsonrpc": "2.0", + "id": $INT1, + "error": { + "code": $INT2, + "message": "$STRING" + } +} +``` + +- "KEY" naming follows camel case. + +### VALUE Types + +Basically, every VALUE in JSON-RPC message is string. +Below table shows the most common "VALUE types". + +| VALUE type | Description | Example | +| :------------------------------------ | :------------------------------------------------ | :----------------------------------------------------------- | +| T_ADDR_EOA | "hx" + 40 digit HEX string | hxbe258ceb872e08851f1f59694dac2558708ece11 | +| T_ADDR_SCORE | "cx" + 40 digit HEX string | cxb0776ee37f5b45bfaea8cff1d8232fbb6122ec32 | +| T_HASH | "0x" + 64 digit HEX string | 0xc71303ef8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238 | +| T_INT | "0x" + lowercase HEX string | 0xa | +| T_BIN_DATA | "0x" + lowercase HEX string. Length must be even. | 0x34b2 | +| T_SIG | base64 encoded string | VAia7YZ2Ji6igKWzjR2YsGa2m53nKPrfK7uXYW78QLE+ATehAVZPC40szvAiA6NEU5gCYB4c4qaQzqDh2ugcHgA= | +| T_DATA_TYPE | Type of data | call, deploy, or message | + +### JSON-RPC Error Codes + +This chapter explains the error codes used in ICON JSON-RPC API response. + +Below table shows the default error messages for the error code. Actual message may vary depending on the implementation. + +#### Error Codes + +| Error code | Message | Description | +| :--------- | :--------------- | :----------------------------------------------------------- | +| -32700 | Parse error | Invalid JSON was received by the server. An error occurred on the server while parsing the JSON text. | +| -32600 | Invalid Request | The JSON sent is not a valid Request object. | +| -32601 | Method not found | The method does not exist / is not available. | +| -32602 | Invalid params | Invalid method parameter(s). | +| -32603 | Internal error | Internal JSON-RPC error. | +| -32000 | Server error | IconServiceEngine internal error. | +| -32100 | Score error | Score internal error. | + +- Some error codes may change + +#### JSON-RPC Error Response + +```json +{ + "jsonrpc": "2.0", + "id": 1, + "error": { + "code": -32601, + "message": "Method not found" + } +} +``` + +### JSON-RPC API v3 ChangeLog + +- Fixed to conform to JSON-RPC 2.0 specification + - Success response: result + - Failure response: error +- Removed additional response generated by loopchain such as "response_code" in SCORE's JSON-PRC Response. + - v2: "result": {"response_code": "0x0", "response": "0x12345"} + - v3: "result": "0x12345" +- Fixed inconsistent KEY naming in v2 API + - v2: icx_getBlockByHeight: "time_stamp" + - v2: icx_sendTransaction: "timestamp" + - v3: "timestamp" +- Fixed inconsistent VALUE format in v2 API + - timestamp + - v2: icx_sendTransaction: "timestamp": "1234567890" + - v2: icx_getBlockByHeight: "timestamp": 1234567890 + - v3: "timestamp": "0x499602d2" + - hash + - v2: icx_getBlockByHash: "hash": "af5570f5a1810b7af78caf4bc70a660f0df51e42baf91d4de5b2328de0e83dfc" + - v3: "hash": "0xaf5570f5a1810b7af78caf4bc70a660f0df51e42baf91d4de5b2328de0e83dfc" +- KEY naming follows camel case. + - v2: "data_type" + - v3: "dataType" +- Removed tx_hash from the icx_sendTransaction message. + +### JSON-RPC APIs + +> For multichannel requests, add `/` at the end of the API path. + +#### Main API + +API path : `:///api/v3` + +- [icx_getLastBlock](#icx_getlastblock) +- [icx_getBlockByHeight](#icx_getblockbyheight) +- [icx_getBlockByHash](#icx_getblockbyhash) +- [icx_call](#icx_call) +- [icx_getBalance](#icx_getbalance) +- [icx_getScoreApi](#icx_getscoreapi) +- [icx_getTotalSupply](#icx_gettotalsupply) +- [icx_getTransactionResult](#icx_gettransactionresult) +- [icx_getTransactionByHash](#icx_gettransactionbyhash) +- [icx_sendTransaction](#icx_sendtransaction) + +#### Debug API + +API path : `:///api/debug/v3` + +- [debug_estimateStep](#debug_estimatestep) + +#### Other API + +API path : `:///api/v3` + +- [ise_getStatus](#ise_getstatus) +- [rep_getList](#rep_getlist) + +## JSON-RPC Methods + +### icx_getLastBlock + +- Returns the last block information. + +#### Parameters + +None + +#### Returns + +- Block data + +#### Example + +```javascript +// Request +{ + "jsonrpc": "2.0", + "method": "icx_getLastBlock", + "id": 1234 +} + +// Response - success +{ + "jsonrpc": "2.0", + "id": 1234, + "result": { + "version": "0.1a", // NOTE: Block data itself still uses ICON JSON-RPC v2 representation. This will be fixed in the future. + "prev_block_hash": "48757af881f76c858890fb41934bee228ad50a71707154a482826c39b8560d4b", + "merkle_tree_root_hash": "fabc1884932cf52f657475b6d62adcbce5661754ff1a9d50f13f0c49c7d48c0c", + "time_stamp": 1516498781094429, + "confirmed_transaction_list": [ // Transaction data could be either v2 or v3 depending on its original request + { + "version": "0x3", + "from": "hxbe258ceb872e08851f1f59694dac2558708ece11", + "to": "cxb0776ee37f5b45bfaea8cff1d8232fbb6122ec32", + "value": "0xde0b6b3a7640000", + "stepLimit": "0x12345", + "timestamp": "0x563a6cf330136", + "nid": "0x3", + "nonce": "0x1", + "signature": "VAia7YZ2Ji6igKWzjR2YsGa2m53nKPrfK7uXYW78QLE+ATehAVZPC40szvAiA6NEU5gCYB4c4qaQzqDh2ugcHgA=", + "txHash": "0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238", + "dataType": "call", + "data": { + "method": "transfer", + "params": { + "to": "hxab2d8215eab14bc6bdd8bfb2c8151257032ecd8b", + "value": "0x1" + } + } + } + ], + "block_hash": "1fcf7c34dc875681761bdaa5d75d770e78e8166b5c4f06c226c53300cbe85f57", + "height": 3, + "peer_id": "hx86aba2210918a9b116973f3c4b27c41a54d5dafe", + "signature": "MEQCICT8mTIL6pRwMWsJjSBHcl4QYiSgG8+0H3U32+05mO9HAiBOhIfBdHNm71WpAZYwJWwQbPVVXFJ8clXGKT3ScDWcvw==" + } +} +``` + +### icx_getBlockByHeight + +- Returns block information by block height. + +#### Parameters + +| KEY | VALUE type | Description | +| :----- | :-------------- | :------------------------ | +| height | [T_INT](#T_INT) | Integer of a block height | + +#### Returns + +- Block data + +#### Example + +```javascript +// Request +{ + "jsonrpc": "2.0", + "method": "icx_getBlockByHeight", + "id": 1234, + "params": { + "height": "0x3" + } +} + +// Response - success +{ + "jsonrpc": "2.0", + "id": 1234, + "result": { + "version": "0.1a", // NOTE: Block data itself still uses ICON JSON-RPC v2 representation. This will be fixed in the future. + "prev_block_hash": "48757af881f76c858890fb41934bee228ad50a71707154a482826c39b8560d4b", + "merkle_tree_root_hash": "fabc1884932cf52f657475b6d62adcbce5661754ff1a9d50f13f0c49c7d48c0c", + "time_stamp": 1516498781094429, + "confirmed_transaction_list": [ // Transaction data could be either v2 or v3 depending on its original request + { + "version": "0x3", + "from": "hxbe258ceb872e08851f1f59694dac2558708ece11", + "to": "cxb0776ee37f5b45bfaea8cff1d8232fbb6122ec32", + "value": "0xde0b6b3a7640000", + "stepLimit": "0x12345", + "timestamp": "0x563a6cf330136", + "nid": "0x3", + "nonce": "0x1", + "signature": "VAia7YZ2Ji6igKWzjR2YsGa2m53nKPrfK7uXYW78QLE+ATehAVZPC40szvAiA6NEU5gCYB4c4qaQzqDh2ugcHgA=", + "txHash": "0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238", + "dataType": "call", + "data": { + "method": "transfer", + "params": { + "to": "hxab2d8215eab14bc6bdd8bfb2c8151257032ecd8b", + "value": "0x1" + } + } + } + ], + "block_hash": "1fcf7c34dc875681761bdaa5d75d770e78e8166b5c4f06c226c53300cbe85f57", + "height": 3, + "peer_id": "hx86aba2210918a9b116973f3c4b27c41a54d5dafe", + "signature": "MEQCICT8mTIL6pRwMWsJjSBHcl4QYiSgG8+0H3U32+05mO9HAiBOhIfBdHNm71WpAZYwJWwQbPVVXFJ8clXGKT3ScDWcvw==" + } +} + +// Response - error +{ + "jsonrpc": "2.0", + "id": 1234, + "error": { + "code": -32602, + "message": "Invalid params height" + } +} +``` + +### icx_getBlockByHash + +- Returns block information by block hash. + +#### Parameters + +| KEY | VALUE type | Description | +| :--- | :---------------- | :-------------- | +| hash | [T_HASH](#T_HASH) | Hash of a block | + +#### Returns + +- Block data + +#### Example + +```javascript +// Request +{ + "jsonrpc": "2.0", + "method": "icx_getBlockByHash", + "id": 1234, + "params": { + "hash": "0x1fcf7c34dc875681761bdaa5d75d770e78e8166b5c4f06c226c53300cbe85f57" + } +} + +// Response - success +{ + "jsonrpc": "2.0", + "id": 1234, + "result": { + "version": "0.1a", // NOTE: Block data itself still uses ICON JSON-RPC v2 representation. This will be fixed in the future. + "prev_block_hash": "48757af881f76c858890fb41934bee228ad50a71707154a482826c39b8560d4b", + "merkle_tree_root_hash": "fabc1884932cf52f657475b6d62adcbce5661754ff1a9d50f13f0c49c7d48c0c", + "time_stamp": 1516498781094429, + "confirmed_transaction_list": [ // Transaction data could be either v2 or v3 depending on its original request + { + "version": "0x3", + "from": "hxbe258ceb872e08851f1f59694dac2558708ece11", + "to": "cxb0776ee37f5b45bfaea8cff1d8232fbb6122ec32", + "value": "0xde0b6b3a7640000", + "stepLimit": "0x12345", + "timestamp": "0x563a6cf330136", + "nid": "0x3", + "nonce": "0x1", + "signature": "VAia7YZ2Ji6igKWzjR2YsGa2m53nKPrfK7uXYW78QLE+ATehAVZPC40szvAiA6NEU5gCYB4c4qaQzqDh2ugcHgA=", + "txHash": "0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238", + "dataType": "call", + "data": { + "method": "transfer", + "params": { + "to": "hxab2d8215eab14bc6bdd8bfb2c8151257032ecd8b", + "value": "0x1" + } + } + } + ], + "block_hash": "1fcf7c34dc875681761bdaa5d75d770e78e8166b5c4f06c226c53300cbe85f57", + "height": 3, + "peer_id": "hx86aba2210918a9b116973f3c4b27c41a54d5dafe", + "signature": "MEQCICT8mTIL6pRwMWsJjSBHcl4QYiSgG8+0H3U32+05mO9HAiBOhIfBdHNm71WpAZYwJWwQbPVVXFJ8clXGKT3ScDWcvw==" + } +} + +// Response - error +{ + "jsonrpc": "2.0", + "id": 1234, + "error": { + "code": -32602, + "message": "Invalid params hash" + } +} +``` + +### icx_call + +- Calls SCORE's external function. +- Does not make state transition (i.e., read-only). + +#### Parameters + +| KEY | VALUE type | Description | +| :---------- | :---------------------------- | :--------------------------------------------- | +| from | [T_ADDR_EOA](#T_ADDR_EOA) | Message sender's address. | +| to | [T_ADDR_SCORE](#T_ADDR_SCORE) | SCORE address that will handle the message. | +| dataType | [T_DATA_TYPE](#T_DATA_TYPE) | `call` is the only possible data type. | +| data | T_DICT | See [Parameters - data](#sendtxparameterdata). | +| data.method | String | Name of the function. | +| data.params | T_DICT | Parameters to be passed to the function. | + +#### Returns + +- Values returned by the executed SCORE function. + +#### Example + +```javascript +// Request +{ + "jsonrpc": "2.0", + "method": "icx_call", + "id": 1234, + "params": { + "from": "hxbe258ceb872e08851f1f59694dac2558708ece11", // TX sender address + "to": "cxb0776ee37f5b45bfaea8cff1d8232fbb6122ec32", // SCORE address + "dataType": "call", + "data": { + "method": "get_balance", // SCORE external function + "params": { + "address": "hx1f9a3310f60a03934b917509c86442db703cbd52" // input parameter of "get_balance" + } + } + } +} + +// Response - success +{ + "jsonrpc": "2.0", + "id": 1234, + "result": "0x2961fff8ca4a62327800000" +} + +// Response - error +{ + "jsonrpc": "2.0", + "id": 1234, + "error": { + "code": -32601, + "message": "Method not found" + } +} + +// Response - error +{ + "jsonrpc": "2.0", + "id": 1234, + "error": { + "code": -32602, + "message": "Invalid params" + } +} +``` + +### icx_getBalance + +- Returns the ICX balance of the given EOA or SCORE. + +#### Parameters + +| KEY | VALUE type | Description | +| :------ | :--------------------------------------------------------- | :---------------------- | +| address | [T_ADDR_EOA](#T_ADDR_EOA) or [T_ADDR_SCORE](#T_ADDR_SCORE) | Address of EOA or SCORE | + +#### Returns + +- Number of ICX coins. + +#### Example + +```javascript +// Request +{ + "jsonrpc": "2.0", + "method": "icx_getBalance", + "id": 1234, + "params": { + "address": "hxb0776ee37f5b45bfaea8cff1d8232fbb6122ec32" + } +} + +// Response - success +{ + "jsonrpc": "2.0", + "id": 1234, + "result": "0xde0b6b3a7640000" +} + +// Response - error +{ + "jsonrpc": "2.0", + "id": 1234, + "error": { + "code": -32602, + "message": "Invalid address" + } +} +``` + +### icx_getScoreApi + +- Returns SCORE's external API list. + +#### Parameters + +| KEY | VALUE type | Description | +| :------ | :---------------------------- | :--------------------------- | +| address | [T_ADDR_SCORE](#T_ADDR_SCORE) | SCORE adress to be examined. | + +#### Returns + +Fields containing information about the function + +| KEY | VALUE type | Description | +| :------- | :-------------- | :----------------------------------------------------------- | +| type | String | `function`, `fallback`, or `eventlog` | +| name | String | function name | +| inputs | T_LIST(T_DICT) | parameters in array
- name : parameter
- nametype : parameter type (`int`, `str`, `bytes`, `bool`, `Address`)
- indexed : `0x1` if the parameter is indexed (when this is `eventlog`) | +| outputs | T_LIST(T_DICT) | return value
- type : return value type (`int`, `str`, `bytes`, `bool`, `Address`, `dict`, `list`) | +| readonly | [T_INT](#T_INT) | `0x1` if this is declared as `external(readonly=True)` | +| payable | [T_INT](#T_INT) | `0x1` if this has `payable` decorator | + +#### Example + +```javascript +// Request +{ + "jsonrpc": "2.0", + "method": "icx_getScoreApi", + "id": 1234, + "params": { + "address": "cxb0776ee37f5b45bfaea8cff1d8232fbb6122ec32" // SCORE address + } +} + +// Response - success +{ + "jsonrpc": "2.0", + "id": 1234, + "result": [ + { + "type": "function", + "name": "balanceOf", + "inputs": [ + { + "name": "_owner", + "type": "Address" + } + ], + "outputs": [ + { + "type": "int" + } + ], + "readonly": "0x1" + }, + { + "type": "eventlog", + "name": "FundTransfer", + "inputs": [ + { + "name": "backer", + "type": "Address", + "indexed": "0x1" + }, + { + "name": "amount", + "type": "int", + "indexed": "0x1" + }, + { + "name": "is_contribution", + "type": "bool", + "indexed": "0x1" + } + ] + }, + {...} + ] +} + +// Response - error +{ + "jsonrpc": "2.0", + "id": 1234, + "error": { + "code": -32602, + "message": "Invalid address" + } +} +``` + +### icx_getTotalSupply + +- Returns total ICX coin supply that has been issued. + +#### Parameters + +None + +#### Returns + +- Total number of ICX coins issued. + +#### Example + +```javascript +// Request +{ + "jsonrpc": "2.0", + "method": "icx_getTotalSupply", + "id": 1234 +} + +// Response - success +{ + "jsonrpc": "2.0", + "id": 1234, + "result": "0x2961fff8ca4a62327800000" +} +``` + +### icx_getTransactionResult + +- Returns the transaction result requested by transaction hash. + +#### Parameters + +| KEY | VALUE type | Description | +| :----- | :---------------- | :---------------------- | +| txHash | [T_HASH](#T_HASH) | Hash of the transaction | + +#### Returns + +| KEY | VALUE type | Description | +| :----------------- | :--------------------------------------------------------- | :----------------------------------------------------------- | +| status | [T_INT](#T_INT) | `0x1` on success, `0x0` on failure. | +| to | [T_ADDR_EOA](#T_ADDR_EOA) or [T_ADDR_SCORE](#T_ADDR_SCORE) | Recipient address of the transaction | +| failure | T_DICT | This field exists when status is `0x1`. Contains code(string) and message(string). | +| txHash | [T_HASH](#T_HASH) | Transaction hash | +| txIndex | [T_INT](#T_INT) | Transaction index in the block | +| blockHeight | [T_INT](#T_INT) | Height of the block that includes the transaction. | +| blockHash | [T_HASH](#T_HASH) | Hash of the block that includes the transation. | +| cumulativeStepUsed | [T_INT](#T_INT) | Sum of stepUsed by this transaction and all preceeding transactions in the same block. | +| stepUsed | [T_INT](#T_INT) | The amount of step used by this transaction. | +| stepPrice | [T_INT](#T_INT) | The step price used by this transaction. | +| scoreAddress | [T_ADDR_SCORE](#T_ADDR_SCORE) | SCORE address if the transaction created a new SCORE. (optional) | +| eventLogs | [T_ARRAY](#T_ARRAY) | Array of eventlogs, which this transaction generated. | +| logsBloom | [T_BIN_DATA](#T_BIN_DATA) | Bloom filter to quickly retrieve related eventlogs. | + +#### Example + +```javascript +// Request +{ + "jsonrpc": "2.0", + "method": "icx_getTransactionResult", + "id": 1234, + "params": { + "txHash": "0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238" + } +} + +// Response - success +{ + "jsonrpc": "2.0", + "id": 1234, + "result": { + "status": "0x1", + "to": "cx4d6f646441a3f9c9b91019c9b98e3c342cceb114", + "txHash": "0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238", + "txIndex": "0x1", + "blockHeight": "0x1234", + "blockHash": "0xc71303ef8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238", + "cumulativeStepUsed": "0x1234", + "stepUsed": "0x1234", + "stepPrice": "0x5678", + "scoreAddress": "cxb0776ee37f5b45bfaea8cff1d8232fbb6122ec32", + "eventLogs":[ + { + "scoreAddress": "cx4d6f646441a3f9c9b91019c9b98e3c342cceb114", + "indexed": [ + "Transfer(Address,Address,int)", + "hx4873b94352c8c1f3b2f09aaeccea31ce9e90bd31", + "hx0000000000000000000000000000000000000000", + "0x8ac7230489e80000" + ], + "data":[] + } + ], + "logsBloom":"0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000002000000000021000000000000000000000000000000000000000000000000003000000000031400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000" + } +} + +// Response - failed tx +{ + "jsonrpc": "2.0", + "id": 1234, + "result": { + "status": "0x0", + "failure": { + "code": "0x7d00", + "message": "Out of balance" + }, + "to": "cx4d6f646441a3f9c9b91019c9b98e3c342cceb114", + "txHash": "0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238", + "txIndex": "0x1", + "blockHeight": "0x1234", + "blockHash": "0xc71303ef8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238", + "cumulativeStepUsed": "0x1234", + "stepUsed": "0x1234", + "stepPrice": "0x5678" + } +} + +// Response - error (invalid txHash was given) +{ + "jsonrpc": "2.0", + "id": 1234, + "error": { + "code": -32602, + "message": "Invalid txHash" + } +} + +// Response - pending tx +{ + "jsonrpc": "2.0", + "id": 1234, + "error": { + "code": -32602, + "message": "Pending transaction" + } +} +``` + +### icx_getTransactionByHash + +- Returns the transaction information requested by transaction hash. + +#### Parameters + +| KEY | VALUE type | Description | +| :----- | :---------------- | :---------------------- | +| txHash | [T_HASH](#T_HASH) | Hash of the transaction | + +#### Returns + +| KEY | VALUE type | Description | +| :---------- | :--------------------------------------------------------- | :----------------------------------------------------------- | +| version | [T_INT](#T_INT) | Protocol version (`0x3` for V3) | +| from | [T_ADDR_EOA](#T_ADDR_EOA) | EOA address that created the transaction | +| to | [T_ADDR_EOA](#T_ADDR_EOA) or [T_ADDR_SCORE](#T_ADDR_SCORE) | EOA address to receive coins, or SCORE address to execute the transaction. | +| value | [T_INT](#T_INT) | Amount of ICX coins in loop to transfer. When ommitted, assumes 0. (1 icx = 1 ^ 18 loop) | +| stepLimit | [T_INT](#T_INT) | Maximum step allowance that can be used by the transaction. | +| timestamp | [T_INT](#T_INT) | Transaction creation time. timestamp is in microsecond. | +| nid | [T_INT](#T_INT) | Network ID | +| nonce | [T_INT](#T_INT) | An arbitrary number used to prevent transaction hash collision. | +| txHash | [T_HASH](#T_HASH) | Transaction hash | +| txIndex | [T_INT](#T_INT) | Transaction index in a block. Null when it is pending. | +| blockHeight | [T_INT](#T_INT) | Block height where this transaction was in. Null when it is pending. | +| blockHash | [T_HASH](#T_HASH) | Hash of the block where this transaction was in. Null when it is pending. | +| signature | [T_SIG](#T_SIG) | Signature of the transaction. | +| dataType | [T_DATA_TYPE](#T_DATA_TYPE) | Type of data. (call, deploy, or message) | +| data | T_DICT or String | Contains various type of data depending on the dataType. See [Parameters - data](#sendtxparameterdata). | + +#### Example + +```javascript +// Request +{ + "jsonrpc": "2.0", + "method": "icx_getTransactionByHash", + "id": 1234, + "params": { + "txHash": "0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238" + } +} + +// Response - coin transfer +{ + "jsonrpc": "2.0", + "id": 1234, + "result": { + "version": "0x3", + "from": "hxbe258ceb872e08851f1f59694dac2558708ece11", + "to": "hx5bfdb090f43a808005ffc27c25b213145e80b7cd", + "value": "0xde0b6b3a7640000", + "stepLimit": "0x12345", + "timestamp": "0x563a6cf330136", + "nid": "0x3", + "nonce": "0x1", + "txHash": "0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238", + "txIndex": "0x1", + "blockHeight": "0x1234", + "blockHash": "0xc71303ef8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238", + "signature": "VAia7YZ2Ji6igKWzjR2YsGa2m53nKPrfK7uXYW78QLE+ATehAVZPC40szvAiA6NEU5gCYB4c4qaQzqDh2ugcHgA=" + } +} + +// Response - SCORE function call +{ + "jsonrpc": "2.0", + "id": 1234, + "result": { + "version": "0x3", + "from": "hxbe258ceb872e08851f1f59694dac2558708ece11", + "to": "cxb0776ee37f5b45bfaea8cff1d8232fbb6122ec32", + "stepLimit": "0x12345", + "timestamp": "0x563a6cf330136", + "nid": "0x3", + "nonce": "0x1", + "txHash": "0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238", + "txIndex": "0x1", + "blockHeight": "0x1234", + "blockHash": "0xc71303ef8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238", + "signature": "VAia7YZ2Ji6igKWzjR2YsGa2m53nKPrfK7uXYW78QLE+ATehAVZPC40szvAiA6NEU5gCYB4c4qaQzqDh2ugcHgA=", + "dataType": "call", + "data": { + "method": "transfer", + "params": { + "to": "hxab2d8215eab14bc6bdd8bfb2c8151257032ecd8b", + "value": "0x1" + } + } + } +} + +// Response - error +{ + "jsonrpc": "2.0", + "id": 1234, + "error": { + "code": -32602, + "message": "Invalid params txHash" + } +} +``` +### icx_sendTransaction + +You can do one of the followings using this method. +- Transfer designated amount of ICX coins from 'from' address to 'to' address. +- Install a new SCORE. +- Update the SCORE in the 'to' address. +- Invoke a function of the SCORE in the 'to' address. +- Transfer a message. + +This function causes state transitions. + +#### Parameters + +| KEY | VALUE type | Required | Description | +| :-------- | :--------------------------------------------------------- | :------: | :----------------------------------------------------------- | +| version | [T_INT](#T_INT) | required | Protocol version (`0x3` for V3) | +| from | [T_ADDR_EOA](#T_ADDR_EOA) | required | EOA address that created the transaction | +| to | [T_ADDR_EOA](#T_ADDR_EOA) or [T_ADDR_SCORE](#T_ADDR_SCORE) | required | EOA address to receive coins, or SCORE address to execute the transaction. | +| value | [T_INT](#T_INT) | optional | Amount of ICX coins in loop to transfer. When omitted, assumes 0. (1 icx = 1 ^ 18 loop) | +| stepLimit | [T_INT](#T_INT) | required | Maximum step allowance that can be used by the transaction. | +| timestamp | [T_INT](#T_INT) | required | Transaction creation time. timestamp is in microsecond. | +| nid | [T_INT](#T_INT) | required | Network ID (`0x1` for Mainnet, `0x2` for Testnet, etc) | +| nonce | [T_INT](#T_INT) | optional | An arbitrary number used to prevent transaction hash collision. | +| signature | [T_SIG](#T_SIG) | required | Signature of the transaction. | +| dataType | [T_DATA_TYPE](#T_DATA_TYPE) | optional | Type of data. (call, deploy, or message) | +| data | T_DICT or String | optional | The content of data varies depending on the dataType. See [Parameters - data](#sendtxparameterdata).
The maximum size of data is 512 KB. | + +**Parameters - data** + +`data` contains the following data in various formats depending on the dataType. + +**1. dataType == call** + +It is used when calling a function in SCORE, and `data` has dictionary value as follows. + +| KEY | VALUE type | Required | Description | +| :----- | :--------- | :------: | :-------------------------------------- | +| method | String | required | Name of the function to invoke in SCORE | +| params | T_DICT | optional | Function parameters | + +**2. dataType == deploy** + +It is used when installing or updating a SCORE, and `data` has dictionary value as follows. + +| KEY | VALUE type | Required | Description | +| :---------- | :------------------------ | :------: | :----------------------------------------------------------- | +| contentType | String | required | Mime-type of the content | +| content | [T_BIN_DATA](#T_BIN_DATA) | required | Compressed SCORE data | +| params | T_DICT | optional | Function parameters will be delivered to on_install() or on_update() | + +**3. dataType == message** + +It is used when transferring a message, and `data` has a HEX string. + +#### Returns + +- Transaction hash ([T_HASH](#T_HASH)) on success +- Error code and message on failure + +#### Example +- **Coin transfer** +```javascript +// Request +{ + "jsonrpc": "2.0", + "method": "icx_sendTransaction", + "id": 1234, + "params": { + "version": "0x3", + "from": "hxbe258ceb872e08851f1f59694dac2558708ece11", + "to": "hx5bfdb090f43a808005ffc27c25b213145e80b7cd", + "value": "0xde0b6b3a7640000", + "stepLimit": "0x12345", + "timestamp": "0x563a6cf330136", + "nid": "0x3", + "nonce": "0x1", + "signature": "VAia7YZ2Ji6igKWzjR2YsGa2m53nKPrfK7uXYW78QLE+ATehAVZPC40szvAiA6NEU5gCYB4c4qaQzqDh2ugcHgA=" + } +} +``` +- **SCORE function call** +```javascript +// Request +{ + "jsonrpc": "2.0", + "method": "icx_sendTransaction", + "id": 1234, + "params": { + "version": "0x3", + "from": "hxbe258ceb872e08851f1f59694dac2558708ece11", + "to": "cxb0776ee37f5b45bfaea8cff1d8232fbb6122ec32", + "stepLimit": "0x12345", + "timestamp": "0x563a6cf330136", + "nid": "0x3", + "nonce": "0x1", + "signature": "VAia7YZ2Ji6igKWzjR2YsGa2m53nKPrfK7uXYW78QLE+ATehAVZPC40szvAiA6NEU5gCYB4c4qaQzqDh2ugcHgA=", + "dataType": "call", + "data": { + "method": "transfer", + "params": { + "to": "hxab2d8215eab14bc6bdd8bfb2c8151257032ecd8b", + "value": "0x1" + } + } + } +} +``` +- **SCORE install** +```javascript +// Request +{ + "jsonrpc": "2.0", + "method": "icx_sendTransaction", + "id": 1234, + "params": { + "version": "0x3", + "from": "hxbe258ceb872e08851f1f59694dac2558708ece11", + "to": "cx0000000000000000000000000000000000000000", // address 0 means SCORE install + "stepLimit": "0x12345", + "timestamp": "0x563a6cf330136", + "nid": "0x3", + "nonce": "0x1", + "signature": "VAia7YZ2Ji6igKWzjR2YsGa2m53nKPrfK7uXYW78QLE+ATehAVZPC40szvAiA6NEU5gCYB4c4qaQzqDh2ugcHgA=", + "dataType": "deploy", + "data": { + "contentType": "application/zip", + "content": "0x1867291283973610982301923812873419826abcdef91827319263187263a7326e...", // compressed SCORE data + "params": { // parameters to be passed to on_install() + "name": "ABCToken", + "symbol": "abc", + "decimals": "0x12" + } + } + } +} +``` +- **SCORE update** +```javascript +// Request +{ + "jsonrpc": "2.0", + "method": "icx_sendTransaction", + "id": 1234, + "params": { + "version": "0x3", + "from": "hxbe258ceb872e08851f1f59694dac2558708ece11", + "to": "cxb0776ee37f5b45bfaea8cff1d8232fbb6122ec32", // SCORE address to be updated + "stepLimit": "0x12345", + "timestamp": "0x563a6cf330136", + "nid": "0x3", + "nonce": "0x1", + "signature": "VAia7YZ2Ji6igKWzjR2YsGa2m53nKPrfK7uXYW78QLE+ATehAVZPC40szvAiA6NEU5gCYB4c4qaQzqDh2ugcHgA=", + "dataType": "deploy", + "data": { + "contentType": "application/zip", + "content": "0x1867291283973610982301923812873419826abcdef91827319263187263a7326e...", // compressed SCORE data + "params": { // parameters to be passed to on_update() + "amount": "0x1234" + } + } + } +} +``` +- **Message transfer** +```javascript +// Request +{ + "jsonrpc": "2.0", + "method": "icx_sendTransaction", + "id": 1234, + "params": { + "version": "0x3", + "from": "hxbe258ceb872e08851f1f59694dac2558708ece11", + "to": "hxbe258ceb872e08851f1f59694dac2558708ece11", + "stepLimit": "0x12345", + "timestamp": "0x563a6cf330136", + "nid": "0x3", + "nonce": "0x1", + "signature": "VAia7YZ2Ji6igKWzjR2YsGa2m53nKPrfK7uXYW78QLE+ATehAVZPC40szvAiA6NEU5gCYB4c4qaQzqDh2ugcHgA=", + "dataType": "message", + "data": "0x4c6f72656d20697073756d20646f6c6f722073697420616d65742c20636f6e7365637465747572206164697069736963696e6720656c69742c2073656420646f20656975736d6f642074656d706f7220696e6369646964756e74207574206c61626f726520657420646f6c6f7265206d61676e6120616c697175612e20557420656e696d206164206d696e696d2076656e69616d2c2071756973206e6f737472756420657865726369746174696f6e20756c6c616d636f206c61626f726973206e69736920757420616c697175697020657820656120636f6d6d6f646f20636f6e7365717561742e2044756973206175746520697275726520646f6c6f7220696e20726570726568656e646572697420696e20766f6c7570746174652076656c697420657373652063696c6c756d20646f6c6f726520657520667567696174206e756c6c612070617269617475722e204578636570746575722073696e74206f6363616563617420637570696461746174206e6f6e2070726f6964656e742c2073756e7420696e2063756c706120717569206f666669636961206465736572756e74206d6f6c6c697420616e696d20696420657374206c61626f72756d2e" + } +} +``` +- **Responses** +```javascript +// Response - success +{ + "jsonrpc": "2.0", + "id": 1234, + "result": "0x4bf74e6aeeb43bde5dc8d5b62537a33ac8eb7605ebbdb51b015c1881b45b3aed" // transaction hash +} + +// Response - error +{ + "jsonrpc": "2.0", + "id": 1234, + "error": { + "code": -32600, + "message": "Invalid signature" + } +} + +// Response - error +{ + "jsonrpc": "2.0", + "id": 1234, + "error": { + "code": -32601, + "message": "Method not found" + } +} +``` + +### debug_estimateStep + +- Generates and returns an estimated step of how much step is necessary to allow the transaction to complete. The transaction will not be added to the blockchain. Note that the estimation can be larger than the actual amount of step to be used by the transaction for several reasons such as node performance. + +#### Parameters + +- The transaction information without stepLimit and signature + +| KEY | VALUE type | Required | Description | +| :-------- | :--------------------------------------------------------- | :------: | :----------------------------------------------------------- | +| version | [T_INT](#T_INT) | required | Protocol version (`0x3` for V3) | +| from | [T_ADDR_EOA](#T_ADDR_EOA) | required | EOA address that created the transaction | +| to | [T_ADDR_EOA](#T_ADDR_EOA) or [T_ADDR_SCORE](#T_ADDR_SCORE) | required | EOA address to receive coins, or SCORE address to execute the transaction. | +| value | [T_INT](#T_INT) | optional | Amount of ICX coins in loop to transfer. When omitted, assumes 0. (1 icx = 1 ^ 18 loop) | +| timestamp | [T_INT](#T_INT) | required | Transaction creation time. timestamp is in microsecond. | +| nid | [T_INT](#T_INT) | required | Network ID (`0x1` for Mainnet, `0x2` for Testnet, etc) | +| nonce | [T_INT](#T_INT) | optional | An arbitrary number used to prevent transaction hash collision. | +| dataType | [T_DATA_TYPE](#T_DATA_TYPE) | optional | Type of data. (call, deploy, or message) | +| data | T_DICT or String | optional | The content of data varies depending on the dataType. See [Parameters - data](#sendtxparameterdata). | + +#### Returns + +- The amount of an estimated step + +#### Example + +```javascript +// Request +{ + "jsonrpc": "2.0", + "method": "debug_estimateStep", + "id": 1234, + "params": { + "version": "0x3", + "from": "hxbe258ceb872e08851f1f59694dac2558708ece11", + "to": "hx5bfdb090f43a808005ffc27c25b213145e80b7cd", + "value": "0xde0b6b3a7640000", + "timestamp": "0x563a6cf330136", + "nid": "0x3", + "nonce": "0x1" + } +} + +// Response - success +{ + "jsonrpc": "2.0", + "id": 1234, + "result": "0x109eb0" +} + +// Response - error +{ + "jsonrpc": "2.0", + "id": 1234, + "error": { + "code": -32602, + "message": "JSON schema validation error: 'version' is a required property" + } +} +``` + +### rep_getList + +- Get all list of Representatives and information about terms & RepRootHash + +#### Parameters + +None + +#### Returns + +- The list of Representatives of the last block + +#### Example + +```javascript +// Request +{ + "jsonrpc" : "2.0", + "method": "rep_getList", + "id": 1234 +} + +// Response - success +{ + "jsonrpc": "2.0", + "result": { + "startTermHeight": "0x0", + "endTermHeight": "0x0", + "repHash": "0xb903239f8543d04b5dc1ba6579132b143087c68db1b2168786408fcbce568238", + "rep": [ + { + "id": "hx86aba2210918a9b116973f3c4b27c41a54d5dafe" + }, + { + "id": "hx9f049228bade72bc0a3490061b824f16bbb74589" + }, + { + "id": "hx6435405122df9fe5187d659588beccdf7aee8557" + }, + { + "id": "hx475bfec4178f3abc88c959faa2e6384e6b409c8f" + } + ] + }, + "id": 1234 +} +``` + +### ise_getStatus + +- Returns the status of iconservice + +#### Parameters + +| KEY | VALUE type | Description | +| :----- | :------------------------ | :--------------------- | +| filter | [T_LIST(String)](#T_LIST) | List of keys to filter | + +#### Returns + +- T_DICT(String) + +#### Example + +```javascript +// Request +{ + "jsonrpc": "2.0", + "method": "ise_getStatus", + "id": 1234, + "params": { + "filter": ["lastBlock"] + } +} + +// Response - success +{ + "jsonrpc": "2.0", + "id": 1234, + "result": { + "lastBlock": { + "blockHeight": "0x3", + "blockHash": "0x1145f61e69d2a6265f00c29ae2da9a2c73100c9ab4221c6612cfd04edfa0e30d", + "timestamp": "0x5739b20776a61", + "prevBlockHash": "0xaeb6768558648eed2a36ac13bc6501d075a8dd2ee6a23e277a5def596bfed603" + } +} + +// Response - error +{ + "jsonrpc": "2.0", + "id": 1234, + "error": { + "code": -32602, + "message": "Invalid address" + } +} +``` +## References + +- [JSON-RPC 2.0 Specification](http://www.jsonrpc.org/specification) +- [ICON JSON RPC API v2](https://github.com/icon-project/icx_JSON_RPC) diff --git a/references/swift-sdk.md b/references/swift-sdk.md new file mode 100644 index 0000000..5b3e6ad --- /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.