Security News
The Risks of Misguided Research in Supply Chain Security
Snyk's use of malicious npm packages for research raises ethical concerns, highlighting risks in public deployment, data exfiltration, and unauthorized testing.
ICON SDK for Python is a collection of libraries which allow you to interact with a local or remote ICON node using an HTTP connection.
ICON SDK for Python is a collection of libraries which allows you to interact with a local or remote ICON node using an HTTP connection.
This document describes how to interact with ICON Network using the ICON SDK for Python, including SDK installation, API usage guide, and code examples.
Setup a virtual environment first, and install ICON SDK.
$ virtualenv -p python3 venv
$ source venv/bin/activate
$ pip install iconsdk
IconService
and Set ProviderYou need to create an IconService
instance and set a provider.
The IconService class contains a set of API methods. It accepts an HTTPProvider
which serves the purpose of connecting to HTTP and HTTPS based JSON-RPC servers.
A provider defines how the IconService
connects to ICON node.
The HTTPProvider takes a base domain URL where the server can be found. For local development, this would be something like http://localhost:9000
.
Here is an example of calling a simple API method to get a block by its height:
from iconsdk.icon_service import IconService
from iconsdk.providers.http_provider import HTTPProvider
# Creates an IconService instance using the HTTP provider and set a provider.
icon_service = IconService(HTTPProvider("http://localhost:9000", 3))
# Gets a block by a given block height.
block = icon_service.get_block(1209)
Set a logger named ICON-SDK-PYTHON
if necessary. Use set_logger
function to set log level like "DEBUG", "INFO", etc as shown below.
from iconsdk.utils import set_logger
# Sets level in the logger. In this case, the handler is default StreamHandler which writes logging records, appropriately formatted, to a stream.
set_logger("DEBUG")
You can also set logger with a specific handler like FileHandler
or SteamHandler
and user own log format as shown below.
from logging import StreamHandler, Formatter
# Sets level in the logger. In this case, the handler is FileHandler which writes formatted logging records to disk files.
handler = FileHandler("./icon-sdk-python.log", mode='a', encoding=None, delay=False)
# Sets user own log format.
formatter = Formatter('%(asctime)s %(name)-12s %(levelname)-5s %(filename)-12s %(lineno)-4s %(funcName)-12s %(message)s')
set_logger("DEBUG", handler, formatter)
from iconsdk.builder.call_builder import CallBuilder
# Returns block information by block height
block = icon_service.get_block(1000)
# Returns block information by block hash
block = icon_service.get_block("0x000...000")
# Returns the last block information
block = icon_service.get_block("latest")
# Returns the balance of the account of given address
balance = icon_service.get_balance("hx000...1")
# Returns a list of the SCORE APIs
score_apis = icon_service.get_score_api("cx000...1")
# Returns the total supply of ICX
total_supply = icon_service.get_total_supply()
# Returns information about a transaction requested by transaction hash
tx = icon_service.get_transaction("0x000...000")
# Returns the result of a transaction by transaction hash
tx_result = icon_service.get_transaction_result("0x000...000")
# Returns the data based on the hash
tx_result = icon_service.get_data_by_hash("0x000...000")
# Returns block header for specified height.
tx_result = icon_service.get_block_header_by_height(1000)
# Returns votes for the block specified by height
tx_result = icon_service.get_votes_by_height(1000)
# Returns proof for the receipt. Proof, itself, may include the receipt.
tx_result = icon_service.get_proof_for_result("0x000...000", 0)
# Returns proof for the receipt and the events in it. The proof may include the data itself.
tx_result = icon_service.get_proof_for_events("0x000...000", 0, [ "0x0", "0x2" ])
# Generates a call instance using the CallBuilder
call = CallBuilder().from_(wallet.get_address())\
.to("cx000...1")\
.method("balance_of")\
.params({"address": "hx000...1"})\
.height(100)\
.build()
# Executes a call method to call a read-only API method on the SCORE immediately without creating a transaction
result = icon_service.call(call)
get_block(value)
Function A
Function B
Function C
Block data
Example of a returned block data
# Returns block information by block height
block = icon_service.get_block(1000)
# Returns block information by block hash
block = icon_service.get_block("0x000...000")
# Returns the last block information
block = icon_service.get_block("latest")
get_balance(address: str, height: int = None)
Returns the ICX balance of the given EOA or SCORE
Delegates to icx_getBalance RPC method
address : An address of EOA or SCORE
height(optional) : Block height
Number of ICX coins
# Returns the ICX balance of the given EOA or SCORE
balance = icon_service.get_balance("hx000...1")
get_score_api(address: str, height: int = None)
Returns SCORE's external API list
Delegates to icx_getScoreApi RPC method
address : A SCORE address to be examined
height(optional) : Block height
A list of API methods of the SCORE and its information
Fields :
# Returns SCORE's external API list
score_apis = icon_service.get_score_api("cx000...1")
get_total_supply(height: int = None)
Returns total ICX coin supply that has been issued
Delegates to icx_getTotalSupply RPC method
height(optional) : Block height
Total number of ICX coins issued
# Returns total ICX coin supply that has been issued
total_supply = icon_service.get_total_supply()
get_transaction(tx_hash: str)
Returns the transaction information requested by transaction hash
Delegates to icx_getTransactionByHash RPC method
tx_hash : Transaction hash prefixed with '0x'
Information about a transaction
Fields :
# Returns the transaction information requested by transaction hash
tx = icon_service.get_transaction("0x000...000")
get_transaction_result(tx_hash: str)
Returns the transaction result requested by transaction hash
Delegates to icx_getTransactionResult RPC method
tx_hash : Hash of a transaction prefixed with '0x'
A transaction result object
Field :
# Returns the transaction result requested by transaction hash
tx_result = icon_service.get_transaction_result("0x000...000")
get_data_by_hash(hash: str)
Get data by hash.
It can be used to retrieve data based on the hash algorithm (SHA3-256).
Following data can be retrieved by a hash.
Delegates to icx_getDataByHash RPC method
hash : The hash value of the data to retrieve.
tx_result = icon_service.get_data_by_hash("0x000...000")
get_block_header_by_height(height: int)
Get block header for specified height.
Delegates to icx_getBlockHeaderByHeight RPC method
height : The height of the block
tx_result = icon_service.get_block_header_by_height(1000)
get_votes_by_height(height: int)
Get votes for the block specified by height.
Normally votes for the block are included in the next. So, even though the block is finalized by votes already, the block including votes may not exist. For that reason, we support this API to get votes as proof for the block.
Delegates to icx_getVoteByHeight RPC method
height : The height of the block
tx_result = icon_service.get_vote_by_height(1000)
call(call: Call)
Calls SCORE's external function which is read-only without creating a transaction.
Delegates to icx_call RPC method
Call object made by CallBuilder
Fields :
Values returned by the executed SCORE function
# Generates a call instance using the CallBuilder
call = CallBuilder().from_(wallet.get_address())\
.to("cx000...1")\
.method("balance_of")\
.params({"address": "hx000...1"})\
.build()
# Calls SCORE's external function which is read-only without creating a transaction
result = icon_service.call(call)
To send transactions, first, you should make an instance of your wallet.
You can make an instance of the wallet using bytes of the private key or from a keystore file.
from iconsdk.wallet.wallet import KeyWallet
# Generates a wallet
wallet = KeyWallet.create()
# Loads a wallet from bytes of the private key
wallet = KeyWallet.load(b'-B\x99...xedy')
# Loads a wallet from a keystore file
wallet = KeyWallet.load("./keystore", "password")
# Stores a keystore file on the file path
wallet.store("./keystore", "password") # throw exception if having an error.
# Returns an Address
wallet.get_address()
# Returns a private key
wallet.get_private_key()
# Signs the transaction
signature = wallet.sign(b'D8\xe9...\xfc')
create()
Generates an instance of Wallet without a specific private key
None
An instance of Wallet class
# Generates a wallet
wallet = KeyWallet.create()
load(private_key: bytes)
Loads a wallet from bytes of the private key and generates an instance of Wallet
private_key : Bytes of the private key
An instance of Wallet class
# Loads a wallet from bytes of the private key
wallet = KeyWallet.load(b'-B\x99...xedy')
load(file_path: PathLikeObject, password: str)
Note: type alias
PathLikeObject
is defined inutils/__init__.py
PathLikeObject = Union[str, bytes, os.PathLike]
Loads a wallet from a keystore file with your password and generates an instance of Wallet
file_path : File path of the keystore file
password : Password for the keystore file. Password must include alphabet character, number, and special character
An instance of Wallet class
# Loads a wallet from a keystore file
wallet = KeyWallet.load("./keystore", "password")
store(file_path, password)
Stores data of an instance of a derived wallet class on the file path with your password
file_path : File path of the keystore file
password : Password for the keystore file. Password must include alphabet character, number, and special character
None
# Stores a keystore file on the file path
wallet.store("./keystore", "password") # throw exception if having an error.
get_address()
Returns an EOA address
The format of your account (which is generated from your public key) is hxfd7e4560ba363f5aabd32caac7317feeee70ea57.
None
An EOA address
# Returns an EOA address
wallet.get_address()
get_private_key()
Returns hex string of the private key of the wallet
None
Hex string of the private key
# Returns the private key
wallet.get_private_key()
sign(data: bytes)
Returns bytes of the ECDSA-SHA256 signature made from the data
data : bytes of the transaction
Bytes of the signature
# Signs the transaction
signature = wallet.sign(b'D8\xe9...\xfc')
Next, you should create an instance of the transaction using different types of transaction builders as follows:
Before sending a transaction, the transaction should be signed by using SignedTransaction class. The SignedTransaction class is used to sign the transaction by returning an instance of the signed transaction as demonstrated in the example below. The instance of the signed transaction has the property of a signature.
Finally, you can send a transaction with the signed transaction object as follows:
from iconsdk.builder.transaction_builder import (
TransactionBuilder,
DeployTransactionBuilder,
CallTransactionBuilder,
MessageTransactionBuilder,
DepositTransactionBuilder
)
from iconsdk.signed_transaction import SignedTransaction
# Generates an instance of transaction for sending icx.
transaction = TransactionBuilder()\
.from_(wallet.get_address())\
.to("cx00...02")\
.value(150000000)\
.step_limit(1000000)\
.nid(3)\
.nonce(100)\
.build()
# Generates an instance of transaction for deploying SCORE.
transaction = DeployTransactionBuilder()\
.from_(wallet.get_address())\
.to("cx00...02")\
.step_limit(1000000)\
.nid(3)\
.nonce(100)\
.content_type("application/java")\
.content(b'D8\xe9...\xfc')\
.params(params)\
.build()
# Generates an instance of transaction for calling method in SCORE.
transaction = CallTransactionBuilder()\
.from_(wallet.get_address())\
.to("cx00...02")\
.step_limit(1000000)\
.nid(3)\
.nonce(100)\
.method("transfer")\
.params(params)\
.build()
# Generates an instance of transaction for sending a message.
transaction = MessageTransactionBuilder()\
.from_(wallet.get_address())\
.to("cx00...02")\
.step_limit(1000000)\
.nid(3)\
.nonce(100)\
.data("0x74657374")\
.build()
# Generates an instance of transaction for adding or withdrawing a deposit.
# Case0: Adding a deposit
transaction = DepositTransactionBuilder()\
.from_(wallet.get_address())\
.to("cx00...02")\
.value(5000*(10**18))\
.step_limit(1000000)\
.nid(3)\
.nonce(100)\
.action("add") \
.build()
# Case1: Withdrawing the deposit
transaction = DepositTransactionBuilder()\
.from_(wallet.get_address())\
.to("cx00...02")\
.step_limit(1000000)\
.nid(3)\
.nonce(100)\
.action("withdraw") \
.id(tx_hash) \
.build()
# Returns the signed transaction object having a signature
signed_transaction = SignedTransaction(transaction, wallet)
# Sends the transaction
tx_hash = icon_service.send_transaction(signed_transaction)
Builder for a Transaction object
A transaction object
# Generates an instance of transaction for sending icx.
transaction = TransactionBuilder()\
.from_(wallet.get_address())\
.to("cx00...02")\
.value(150000000)\
.step_limit(1000000)\
.nid(3)\
.nonce(100)\
.build()
Builder for DeployTransaction object
A deploy transaction object
# Generates an instance of transaction for deploying SCORE.
transaction = DeployTransactionBuilder()\
.from_(wallet.get_address())\
.to("cx00...02")\
.step_limit(1000000)\
.nid(3)\
.nonce(100)\
.content_type("application/java")\
.content(b'D8\xe9...\xfc')\
.params(params)\
.build()
Builder for CallTransaction object
A call transaction object
# Generates an instance of transaction for calling method in SCORE.
transaction = CallTransactionBuilder()\
.from_(wallet.get_address())\
.to("cx00...02")\
.step_limit(1000000)\
.nid(3)\
.nonce(100)\
.method("transfer")\
.params(params)\
.build()
Builder for MessageTransaction object
A message transaction object
# Generates an instance of transaction for sending a message.
transaction = MessageTransactionBuilder()\
.from_(wallet.get_address())\
.to("cx00...02")\
.step_limit(1000000)\
.nid(3)\
.nonce(100)\
.data("0x74657374")\
.build()
Builder for DepositTransaction object
A deposit transaction object
# Generates an instance of transaction for adding or withdrawing a deposit.
# Case0: Adding a deposit
transaction = DepositTransactionBuilder()\
.from_(wallet.get_address())\
.to("cx00...02")\
.value(5000*(10**18))\
.step_limit(1000000)\
.nid(3)\
.nonce(100)\
.action("add") \
.build()
# Case1: Withdrawing the deposit
transaction = DepositTransactionBuilder()\
.from_(wallet.get_address())\
.to("cx00...02")\
.step_limit(1000000)\
.nid(3)\
.nonce(100)\
.action("withdraw") \
.id(tx_hash) \
.build()
SignedTransaction(transaction: Transaction, wallet: Wallet)
Returns the signed transaction object having a signature
The signed transaction object having a signature field finally
# Returns the signed transaction object having a signature
signed_transaction = SignedTransaction(transaction, wallet)
send_transaction(signed_transaction: SignedTransaction)
Sends the transaction
Delegates to icx_sendTransaction RPC method
Need to wait for a while after sending the transaction. Because it takes time to create consensus among nodes. We recommend 0.3 seconds at least.
signed_transaction : A signed transaction object
Transaction hash prefixed with '0x'
# Sends the transaction
tx_hash = icon_service.send_transaction(signed_transaction)
It is important to set a proper step_limit
value in your transaction to make the submitted transaction executed successfully.
estimate_step
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 step_limit
based on the estimate.
# Generates a raw transaction without the stepLimit
transaction = TransactionBuilder()\
.from_(wallet.get_address())\
.to("cx00...02")\
.value(150000000)\
.nid(3)\
.nonce(100)\
.build()
# Returns an estimated step value
estimate_step = icon_service.estimate_step(transaction)
# Adds some margin to the estimated step
estimate_step += 10000
# Returns the signed transaction object having a signature with the same raw transaction and the estimated step
signed_transaction = SignedTransaction(transaction, wallet, estimate_step)
# Sends the transaction
tx_hash = icon_service.send_transaction(signed_transaction)
Note that the estimate 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 estimate when you set the step_limit
of the SignedTransaction
.
estimate_step(transaction: Transaction)
Returns an estimated step of how much step is necessary to allow the transaction to complete
Delegates to debug_estimateStep RPC method
transaction : An Transaction object made by TransactionBuilder
Number of an estimated step
# Generates a raw transaction without the stepLimit
transaction = TransactionBuilder()\
.from_(wallet.get_address())\
.to("cx00...02")\
.value(150000000)\
.nid(3)\
.nonce(100)\
.build()
# Returns an estimated step value
estimate_step = icon_service.estimate_step(transaction)
def get_btp_network_info(self, id: int, height: int = None) -> dict:
Returns BTP Network information for specified height and ID.
Delegates to btp_getNetworkInfo RPC method.
https://github.com/icon-project/goloop/blob/master/doc/btp2_extension.md#btp_getNetworkInfo
param | description |
---|---|
id | The id of the BTP network |
height | The height of the main block |
A BTP Network information object
def get_btp_network_type_info(self, id: int, height: int = None) -> dict:
Returns BTP Network Type information for specified height and ID.
Delegates to btp_getNetworkTypeInfo RPC method.
https://github.com/icon-project/goloop/blob/master/doc/btp2_extension.md#btp_getNetworkTypeInfo
param | description |
---|---|
id | The id of the BTP network type |
height | The height of the main block |
A BTP Network Type information object
def get_btp_messages(self, height: int, network_id: int) -> list:
Returns BTP messages for specified height and network ID.
Delegates to btp_getMessages RPC method.
https://github.com/icon-project/goloop/blob/master/doc/btp2_extension.md#btp_getMessages
param | description |
---|---|
height | The height of the main block |
network_id | The id of the BTP network |
A BTP Messages object
def get_btp_header(self, height: int, network_id: int) -> str:
Returns BTP block header for specified height and network ID.
Delegates to btp_getHeader RPC method.
https://github.com/icon-project/goloop/blob/master/doc/btp2_extension.md#btp_getHeader
param | description |
---|---|
height | The height of the main block |
network_id | The id of the BTP network |
A Base64 encoded BTP block header
def get_btp_proof(self, height: int, network_id: int) -> str:
Returns BTP block proof for specified height and network ID.
Delegates to btp_getHeader RPC method.
https://github.com/icon-project/goloop/blob/master/doc/btp2_extension.md#btp_getProof
param | description |
---|---|
height | The height of the main block |
network_id | The id of the BTP network |
A Base64 encoded BTP block proof
def get_btp_source_information(self) -> dict:
Returns BTP source network information.
Delegates to btp_getSourceInformation RPC method.
https://github.com/icon-project/goloop/blob/master/doc/btp2_extension.md#btp_getSourceInformation
A BTP network information object
This project is available under the Apache License, Version 2.0.
FAQs
ICON SDK for Python is a collection of libraries which allow you to interact with a local or remote ICON node using an HTTP connection.
We found that iconsdk demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Snyk's use of malicious npm packages for research raises ethical concerns, highlighting risks in public deployment, data exfiltration, and unauthorized testing.
Research
Security News
Socket researchers found several malicious npm packages typosquatting Chalk and Chokidar, targeting Node.js developers with kill switches and data theft.
Security News
pnpm 10 blocks lifecycle scripts by default to improve security, addressing supply chain attack risks but sparking debate over compatibility and workflow changes.