Blueprint SDK — API
Introduction
This article is the reference for the Python API provided by the blueprint SDK. The blueprint SDK Python API comprises all names from package hathor.nanocontracts that can be imported in a blueprint module.
This API reference is divided into the following sections:
- Type aliases: simplify handling of the most common data types in contracts.
- Classes: define the structure required by Hathor engine for a blueprint module.
- Decorators: used to define the type of a method in the blueprint class.
- Objects: describe the interface of internal objects from the available classes. That is, you can use them through instances of available classes, but you cannot import and use their classes directly.
Not all names from the hathor.nanocontracts package can be imported into a blueprint module. Only strictly allowed names may be imported. For the list of these names, see Imports at Blueprint SDK — guidelines.
Type aliases
Source code: type aliases in hathor.nanocontracts.types
Address
- Description: wallet address
- Alias for:
bytes - Constraint: 20 bytes
- Example:
b'\x28\x1e\xd3\x2c\xcd\x0d\x28\xac\xea\x3a\xfc\xf4\x79\x8e\x2d\x4d\xb2\x14\x01\xed\xef\xa9\xa8\x98\x22' - Usage:
from hathor.nanocontracts.types import Address
...
address: Address
...
# In base58check this wallet address is: H9L7do74fkLF7VHa662a4huGni1zKW4EGZ
address = b'\x28\x1e\xd3\x2c\xcd\x0d\x28\xac\xea\x3a\xfc\xf4\x79\x8e\x2d\x4d\xb2\x14\x01\xed\xef\xa9\xa8\x98\x22'
Amount
- Description: denotes an amount of tokens
- Alias for:
int - Constraint: integer where the last two digits are decimals
- Example:
1025represents 10.25 tokens - Usage:
from hathor.nanocontracts.types import Amount
...
amount: Amount
...
amount = 1025
BlueprintId
- Description: identifier of a blueprint. For built-in blueprints, ids are hardcode with the network's environment variables (testnet, mainnet, etc.). For on-chain blueprints, the id is the hash of the transaction that deployed it.
- Alias for:
VextexId - Constraint: 32 bytes
- Example:
bytes.fromhex("3cb032600bdf7db784800e4ea911b10676fa2f67591f82bb62628c234e771595") - Usage:
from hathor.nanocontracts.types import BlueprintId
...
blueprint: BlueprintId
...
blueprint = bytes.fromhex("3cb032600bdf7db784800e4ea911b10676fa2f67591f82bb62628c234e771595")
ContractId
- Description: identifier of a contract. It is recorded in the transaction where it was created.
- Alias for:
VextexId - Constraint: 32 bytes
- Example:
bytes.fromhex("000063f99b133c7630bc9d0117919f5b8726155412ad063dbbd618bdc7f85d7a") - Usage:
from hathor.nanocontracts.types import ContractId
...
contract: ContractId
...
contract = bytes.fromhex("000063f99b133c7630bc9d0117919f5b8726155412ad063dbbd618bdc7f85d7a")
Timestamp
- Description: timestamp following Unix epoch standard
- Alias for:
int - Constraint: integer representing the number of seconds elapsed since January 1st, 1970 00:00:00 UTC.
- Example: timestamp for January 3, 2020, at noon UTC is
1578052800 - Usage:
from hathor.nanocontracts.types import Timestamp
...
timestamp: Timestamp
...
timestamp = 1578052800
TokenUid
- Description: identifier of a token. It is recorded in the transaction where it was created.
- Alias for:
bytes - Constraint: 32 bytes
- Example:
bytes.fromhex("00000943573723a28e3dd980c10e08419d0e00bc647a95f4ca9671ebea7d5669") - Usage:
from hathor.nanocontracts.types import TokenUid
...
token: TokenUid
...
token = bytes.fromhex("00000943573723a28e3dd980c10e08419d0e00bc647a95f4ca9671ebea7d5669")
TxOutputScript
- Description: lock script of a transaction output
- Alias for:
bytes - Constraint: 32 bytes
- Usage:
from hathor.nanocontracts.types import TxOutputScript
...
oracle: TxOutputScript
VertexId
- Description: identifier of a transaction in the ledger (blockchain). It is the hash of the transaction.
- Alias for:
bytes - Constraint: 32 bytes
- Example:
bytes.fromhex("00000943573723a28e3dd980c10e08419d0e00bc647a95f4ca9671ebea7d5669") - Usage:
from hathor.nanocontracts.types import VertexId
...
tx: VertexId
...
tx = bytes.fromhex("00000943573723a28e3dd980c10e08419d0e00bc647a95f4ca9671ebea7d5669")
NCAction
- Description: union type alias representing any of the four possible action types. Use for type annotations when a parameter, variable, or attribute can accept any action type.
- Alias for: one of the possible action classes:
NCDepositAction,NCWithdrawalAction,NCGrantAuthorityAction, orNCAcquireAuthorityAction. - Constraint: must be an instance of one of the classes above.
- Usage:
from hathor.nanocontracts.types import NCAction
...
actions: list[NCAction] = []
...
def fail_if_invalid_action(self, action: NCAction) -> None:
if action.token_uid != VALID_TOKEN:
... - Source code:
hathor.nanocontracts.types.NCAction
Classes
Blueprint
Serves as the base class for all blueprints. You must subclass Blueprint exactly once in your blueprint module.
Usage:
from hathor.nanocontracts.blueprint import Blueprint
...
# Define your blueprint class as subclass of Blueprint:
class Bet(Blueprint):
...
Objects:
Blueprint provides contracts the following objects:
syscall: instance attribute used for all external interactions outside the contract itself — e.g., reading and writing to the ledger, calling other contracts, etc. SeeBlueprint.syscallat section Objects.log: instance attribute used to record contract execution logs. Useful during development for debugging and testing, and in production for audits. SeeBlueprint.logat section Objects.
Source code:
hathor.nanocontracts.blueprint.Blueprint
Context
Provides the public method with the context in which it was called — namely, who called it, when it was called, and what the origin transaction is. The origin transaction is the transaction that originated the current call chain; in other words, it contains the entry point call.
When Hathor engine invokes a public method, it always passes a Context object as the first argument. Therefore, every public method must have a Context object as its second parameter.
The Context object is immutable, and what is passed is only a copy of the original maintained by Hathor engine. As such, you cannot, and should not attempt to, modify the call context in your blueprint's code.
Data attributes:
vertex:VertexDatathat contains the origin transaction.address:AddressorContractIdthat denotes who called the method (also known as the caller).timestamp:Timestampthat denotes the timestamp of the first block confirming the origin transaction.actions:MappingProxyTypewhere the keys areTokenUidand the values are tuples ofNCActionobjects. All actions requested in the current call. It may contain zero, one, or more elements.
Note that a token is associated with a tuple of actions. However, not all combinations of actions are possible for the same token. For example, Hathor engine will never pass to a public method a Context.actions in which, for the same token UID (TokenUid), there are:
- Two actions (
NCAction) of the same type (NCActionType) — e.g., two deposits for the same token. - One
DEPOSITaction and oneWITHDRAWALaction. - One
GRANT_AUTHORITYaction and oneACQUIRE_AUTHORITYaction.
Method:
get_single_action
The following subsection describes the (only) method of this class that available to use in your blueprint.
Context.get_single_action
Given a token UID, returns the single NCAction from actions that should be associated with it — i.e., the action whose key matches the token. Otherwise, raises an exception.
get_single_action(self, token_uid: TokenUid) -> NCAction:
Parameter:
token_uid:TokenUidthat identifies the single action.
Return: NCAction if there is one and only one action associated with the token UID. If no action is found, raises an NCFail exception. If more than one action is found, also raises an NCFail exception.
Usage:
from hathor.nanocontracts.context import Context
...
# Second parameter of a public method is always a Context object:
@public(allow_deposit=True, allow_withdrawal=True)
def swap(self, ctx: Context) -> None:
"""Execute a token swap."""
# Check if there is exactly one action related to each token:
# You should use the method get_single_action for it:
action_a = ctx.get_single_action(self.token_a)
action_b = ctx.get_single_action(self.token_b)
...
Source code:
hathor.nanocontracts.context.Context
NCActionType
An enumeration (Enum) that defines the possible types of actions a contract user (wallet or another contract) can perform on a contract's multi-token balance. Can be one of the following:
DEPOSIT: deposit tokens into contract.WITHDRAWAL: withdrawal tokens from contract.GRANT_AUTHORITY: grant mint/melt authority to contract.ACQUIRE_AUTHORITY: acquire mint/melt authority from contract.
For more about it, see Actions section at Nano contracts: how it works.
Usage:
from hathor.nanocontracts.types import NCActionType
...
# Checking the type of a given action
# You can use:
if not isinstance(action, NCDepositAction)
raise InvalidActions
# OR with NCActionType the equivalent:
if action.type != NCActionType.DEPOSIT:
raise InvalidActions
# Defining what actions a public method shall receive:
# You can use in the decorator:
@public(allow_deposit=True, allow_withdrawal=True)
# OR with NCActionType the equivalent:
@public(allow_actions=[NCActionType.DEPOSIT, NCActionType.WITHDRAWAL])
Source code:
hathor.nanocontracts.types.NCActionType
NCDepositAction
Used to create or validate actions of type DEPOSIT.
Data attributes:
name: always"DEPOSIT"type: alwaysNCActionType.DEPOSITtoken_uid:TokenUidthat denotes the token the caller wants to deposit.amount:Amountthat denotes the amount of tokens to be deposited.
Usage:
from hathor.nanocontracts.types import NCDepositAction
...
# Use it whenever you want to represent the specific deposit action:
# For example, to check if a given action is a deposit:
if not isinstance(action, NCDepositAction)
...
Source code:
hathor.nanocontracts.types.NCDepositAction
NCWithdrawalAction
Used to create or validate actions of type WITHDRAWAL.
Data attributes:
name: always"WITHDRAWAL"type: alwaysNCActionType.WITHDRAWALtoken_uid:TokenUidthat denotes the token the caller wants to withdraw.amount:Amountthat denotes the amount of tokens to be withdrawn.
Usage:
from hathor.nanocontracts.types import NCWithdrawalAction
...
# Use it whenever you want to represent the specific withdrawal action:
# For example, to check if a given action is a withdrawal:
if not isinstance(action, NCWithdrawalAction)
...
Source code:
hathor.nanocontracts.types.NCWithdrawalAction
NCGrantAuthorityAction
Used to create or validate actions of type GRANT_AUTHORITY.
Data attributes:
name: always"GRANT_AUTHORITY".type: alwaysNCActionType.GRANT_AUTHORITY.token_uid:TokenUidthat denotes the token the caller wants to grant authority to contract.mint:bool; ifTrue, contract will be allowed to issue new amounts of the token, increasing its total supply.melt:bool; ifTrue, contract will be allowed to destroy amounts of the token, decreasing its total supply.
Usage:
from hathor.nanocontracts.types import NCGrantAuthorityAction
...
# Use it whenever you want to represent the specific grant authority action:
# For example, to check if a given action is a grant authority:
if not isinstance(action, NCGrantAuthorityAction)
...
Source code:
hathor.nanocontracts.types.NCGrantAuthorityAction
NCAcquireAuthorityAction
Used to create or validate actions of type ACQUIRE_AUTHORITY.
Data attributes:
name: always"ACQUIRE_AUTHORITY".type: alwaysNCActionType.ACQUIRE_AUTHORITY.token_uid:TokenUidthat denotes the token the caller wants to grant authority to contract.mint:bool; ifTrue, caller will be allowed to issue new amounts of the token, increasing its total supply.melt:bool; ifTrue, caller will be allowed to destroy amounts of the token, decreasing its total supply.
Usage:
from hathor.nanocontracts.types import NCAcquireAuthorityAction
...
# Use it whenever you want to represent the specific acquire authority action:
# For example, to check if a given action is an acquire authority:
if not isinstance(action, NCAcquireAuthorityAction)
...
Source code:
hathor.nanocontracts.types.NCAcquireAuthorityAction
NCFail
An NCFail exception signals to Hathor engine that a contract's creation or execution has failed. Use it in your blueprint's methods to indicate execution failures. Also, define subclasses of NCFail to provide more specific and clearer failure reasons for contract users (wallets and other contracts).
Usage:
from hathor.nanocontracts.exception import NCFail
...
# Raise a generic NCFail exception.
if len(ctx.actions) != 0:
raise NCFail('must be a single call')
...
# Define specific exception classes.
class WithdrawalNotAllowed(NCFail):
pass
...
# Raise a specific exception.
if action.type != NCActionType.DEPOSIT:
raise WithdrawalNotAllowed('must be deposit')
...
Source code:
hathor.nanocontracts.exception.NCFail
SignedData
Out-of-the-box support for oracles in blueprints. To achieve this, the blueprint should have a public method exclusively for oracle use, which receives a SignedData as a parameter.
Data attributes:
data: off-chain data that the oracle wants to feed into the contract. The type ofdatais defined in theSignedDataparameter received by the oracle's public method referred to.script_input:bytesdenoting the script used to authenticate the oracle.
Examples:
Suppose a sports betting contract in which an oracle should submit the result of a game after it has ended. In this scenario, SignedData[str] specifies that the result in data must be passed as a string. For example:
data: "Barcelona2x1Real-Madrid"
script_input: <unlock_script_to_auth_oracle_as_bytes>
Now, suppose an oracle needs to submit the exchange rate of 1 BTC in US dollars (USD) every minute. In this scenario, SignedData[int] specifies that the result in data must be passed as an integer, with the last two digits representing cents. For example:
data: 9654292
script_input: <unlock_script_to_auth_oracle_as_bytes>
Methods:
checksigget_data_bytes
The following subsections describe each of these methods.
SignedData.checksig
Called in the oracle's public method to authenticate the oracle. That is, checks if this object's script_input attribute resolves the oracle script registered in the contract state.
checksig(script: bytes) -> bool:
Parameter:
script:bytesthat denotes the oracle script. That is, a script from the contract state used to authenticate the oracle.
Return: True if this object's script_input attribute unlocks script received as parameter. That is, oracle is authenticated.
SignedData.get_data_bytes
Given a contract ID, returns a serialized version of data as bytes. Use it to perform unit tests on your blueprint.
get_data_bytes(self, contract_id: ContractId) -> bytes:
Parameter:
contract_id:ContractIdthat denotes a contract ID that is being used in the unit test.
Return: bytes that denotes the serialized version of the attribute data. Use it to generate the script_input during unit tests.
Usage:
The following snippet presents how to write a public method that allows an oracle to feed off-chain data to a contract:
from hathor.nanocontracts.types import TxOutputScript
from hathor.nanocontracts.types import SignedData
# Script that must be resolved to authenticate oracle.
oracle_script: TxOutputScript
# SignedData[str] specifies that off-chain data being passed is of type string.
@public
def provide_offchain_data(self, ctx: Context, signed_data: SignedData[str]) -> None:
"""Called by oracle to input off-chain data into contract."""
# Check if script_input resolves oracle_script, to authenticate oracle.
if not signed_data.checksig(self.oracle_script):
raise NCFail('Oracle not authenticated')
# Once oracle authenticated, off-chain data can be input into contract.
self.offchain_data = signed_data.data
Source code:
hathor.nanocontracts.types.SignedData
Decorators
public
Decorator that marks a method in your blueprint class as 'public'. All public methods must be marked with the public decorator. In addition, you must explicitly specify which types of actions the public method can receive. This should be done using the following keyword arguments:
- Option 1: use
allow_actionsto provide the list of allowedNCActionTypevalues. Example:allow_actions=[NCActionType.DEPOSIT, NCActionType.WITHDRAWAL]). - Option 2: pass
Truefor each action type you want to allow:
"""
- allow_deposit=True for DEPOSIT
- allow_withdrawal=True for WITHDRAWAL
- allow_grant_authority=True for GRANT_AUTHORITY
- allow_acquire_authority=True for ACQUIRE_AUTHORITY
"""
You cannot use allow_actions (option 1) together with the other keyword arguments (option 2). Doing so will always raise a BlueprintSyntaxError exception.
If an action type is not explicitly allowed using the keyword arguments in the @public decorator, the public method will not be able to receive or handle that type of action. If you use the @public decorator with no keyword arguments, the method will not be allowed to receive any actions. Finally, calling a public method with actions it is not allowed to handle will cause the method call to fail.
Usage:
from hathor.nanocontracts.types import public, NCActionType, SignedData
from hathor.nanocontracts.context import Context
...
# Mark all your public methods:
@public
def set_result(self, ctx: Context, result: SignedData[Result]) -> None:
"""Public method that CANNOT receive any type of action.
This is because you didn't explicitly allow any type
alongside the public decorator.
"""
...
# If you want your method to receive any type of action
# You must do it explicitly:
@public(allow_actions=[NCActionType.DEPOSIT, NCActionType.WITHDRAWAL])
def swap(self, ctx: Context) -> None:
"""Public method that works with deposits and withdrawals.
It can receive ANY number of deposits and withdrawals
of any token. It is up to your code to validate these
actions.
We used the allow_actions arg to pass a list of enabled
actions, and we needed to use the NCActionTypes.
"""
...
# There are two alternative syntaxes to state the types of actions
# You either pass the allow_actions arg or:
@public(allow_deposit=True, allow_withdrawal=True)
def swap(self, ctx: Context) -> None:
"""Decorator using the other keyword args of public.
Both work the same way.
Here we do the same we did above but using one keyword arg
for each specific type of action.
"""
...
# It is not required to pass one of them as False:
@public(allow_grant_authority=False, allow_acquire_authority=False)
def foo(self, ctx: Context) -> None:
"""False with <allow_some_action_type> arg changes nothing.
You may decide to use it just for human-reading purposes if you prefer.
"""
...
Source code:
hathor.nanocontracts.types.public
view
Decorator that marks a method in your blueprint class as 'view'. All view methods must be marked with the view decorator.
Usage:
from hathor.nanocontracts.types import view
...
# Mark all your view methods.
@view
def get_max_withdrawal(self, address: Address) -> int:
"""Return the maximum amount available for withdrawal."""
...
Source code:
hathor.nanocontracts.types.view
fallback
Decorator that marks the method named 'fallback' in your blueprint class. That is, you can only use the @fallback decorator once in the entire blueprint class, and only to mark a method named fallback.
Just like with public methods, you must explicitly specify the allowed action types. For more on it, see Method fallback at Blueprint development guidelines
Usage:
from hathor.nanocontracts.types import public, NCActionType
from hathor.nanocontracts.context import Context
...
# Mark your fallback method:
@fallback(allow_actions=[NCActionType.DEPOSIT, NCActionType.WITHDRAWAL, NCActionType.GRANT_AUTHORITY, NCActionType.ACQUIRE_AUTHORITY])
def fallback(self, ctx: Context, method_name: str, nc_args: NCArgs) -> None:
"""THE only fallback method of your blueprint class.
You can only use this decorator with the method named 'fallback'.
Whenever a caller calls a non-existent PUBLIC method, Hathor engine
will invoke the fallback method.
Thus: just like any public method, you must explicitly state
what action types the method works with.
"""
...
Source code:
hathor.nanocontracts.types.fallback
Objects
Blueprint.syscall
For all interactions outside the scope of the blueprint itself (external interactions). That is, whenever you need to perform reads and writes to the ledger, call methods from other contracts, or access special features provided by Hathor engine.
Methods:
get_contract_idget_blueprint_idget_balance_before_current_callget_current_balancecan_mint_before_current_callcan_mintcan_melt_before_current_callrevoke_authoritiesmint_tokensmelt_tokenscreate_tokencall_view_methodcall_public_methodemit_eventcreate_contract
The following subsections describe each of these methods.
syscall.get_contract_id
Returns the contract's own ID.
get_contract_id(self) -> ContractId:
syscall.get_blueprint_id
Returns the blueprint ID of the given contract.
get_blueprint_id(self, contract_id: Optional[ContractId] = None) -> BlueprintId:
Parameter:
contract_id:ContractIdto query; defaults to the contract itself.
syscall.get_balance_before_current_call
Returns the balance of a token held by a contract; it does not take into account the effects of the current call.
get_balance_before_current_call(
self,
token_uid: Optional[TokenUid] = None,
*,
contract_id: Optional[ContractId] = None,
) -> Amount:
Parameters:
token_uid:TokenUidto check balance; defaults to 'HTR'.contract_id:ContractIdto query; defaults to the contract itself.
Return: Amount, such that:
- It takes into account:
- Everything that happened in the call chain before this call, including any actions.
- It does not take into account:
- Actions or changes that occurred during the current call.
- Actions or changes that will occur later in this call or in subsequent calls (since they haven’t happened yet, by definition).
Example: if a contract holds 50 HTR and the current call is requesting to withdraw 3 HTR, this method still returns 50 HTR.
syscall.get_current_balance
Returns the balance of a token held by a contract; it does take into account the actions and changes already performed in the current call.
get_current_balance(
self,
token_uid: Optional[TokenUid] = None,
*,
contract_id: Optional[ContractId] = None,
) -> Amount:
Parameters:
token_uid:TokenUidto check balance; defaults to 'HTR'.contract_id:ContractIdto query; defaults to the contract itself.
Return: Amount, such that:
- It takes into account:
- Everything that happened in the call chain before this call, including any actions.
- All actions and changes that occurred during the current call.
- It does not take into account:
- Actions or changes that will occur later in this call or in subsequent calls (since they haven’t happened yet, by definition).
Example: if a contract holds 50 HTR and the current call is requesting to withdraw 3 HTR, this method returns 47 HTR.
syscall.can_mint_before_current_call
Returns whether a contract has mint authority over a token; it does not take into account the actions and changes already performed in the current call.
can_mint_before_current_call(
self,
token_uid: TokenUid,
*,
contract_id: Optional[ContractId] = None,
) -> bool:
Parameters:
token_uid:TokenUidto check authority.contract_id:ContractIdto query; defaults to the contract itself.
Return: bool, such that:
Truemeans the contract has mint authority over the token.- It takes into account:
- Everything that happened in the call chain before this call, including any actions.
- It does not take into account:
- All actions and changes that occurred during the current call.
- Actions or changes that will occur later in this call or in subsequent calls (since they haven’t happened yet, by definition).
Example: if a contract has mint authority over a token and the current call revokes it before invoking this method, it still returns True.
syscall.can_mint
Returns whether a contract has mint authority over a token; it does take into account the actions and changes already performed in the current call.
can_mint(
self,
token_uid: TokenUid,
*,
contract_id: Optional[ContractId] = None,
) -> bool:
Parameters:
token_uid:TokenUidto check authority.contract_id:ContractIdto query; defaults to the contract itself.
Return: bool, such that:
Truemeans the contract has mint authority over the token.- It takes into account:
- Everything that happened in the call chain before this call, including any actions.
- All actions and changes that occurred during the current call.
- It does not take into account:
- Actions or changes that will occur later in this call or in subsequent calls (since they haven’t happened yet, by definition).
Example: if a contract has mint authority over a token and the current call revokes it before invoking this method, it returns False.
syscall.can_melt_before_current_call
Returns whether a contract has melt authority over a token; it does not take into account the actions and changes already performed in the current call.
can_melt_before_current_call(
self,
token_uid: TokenUid,
*,
contract_id: Optional[ContractId] = None,
) -> bool:
Parameters:
token_uid:TokenUidto check authority.contract_id:ContractIdto query; defaults to the contract itself.
Return: bool, such that:
Truemeans the contract has melt authority over the token.- It takes into account:
- Everything that happened in the call chain before this call, including any actions.
- It does not take into account:
- All actions and changes that occurred during the current call.
- Actions or changes that will occur later in this call or in subsequent calls (since they haven’t happened yet, by definition).
Example: if a contract has melt authority over a token and the current call revokes it before invoking this method, it still returns True.
syscall.can_melt
Returns whether a contract has melt authority over a token; it does take into account the actions and changes already performed in the current call.
can_melt(
self,
token_uid: TokenUid,
*,
contract_id: Optional[ContractId] = None,
) -> bool:
Parameters:
token_uid:TokenUidto check authority.contract_id:ContractIdto query; defaults to the contract itself.
Return: bool, such that:
Truemeans the contract has melt authority over the token.- It takes into account:
- Everything that happened in the call chain before this call, including any actions.
- All actions and changes that occurred during the current call.
- It does not take into account:
- Actions or changes that will occur later in this call or in subsequent calls (since they haven’t happened yet, by definition).
Example: if a contract has melt authority over a token and the current call revokes it before invoking this method, it returns False.
syscall.revoke_authorities
Revokes the contract’s own mint/melt authorities over a token.
revoke_authorities(
self,
token_uid: TokenUid,
*,
revoke_mint: bool,
revoke_melt: bool
) -> None:
Parameters:
token_uid:TokenUidto revoke authorities over.revoke_mint:bool; ifTrue, will revoke mint authority.revoke_melt:bool; ifTrue, will revoke melt authority.
syscall.mint_tokens
Mints a new amount of a given token and adds it to the contract balance.
mint_tokens(self, token_uid: TokenUid, amount: int) -> None:
Parameters:
token_uid:TokenUidto mint; contract must have mint authority over it.amount:Amountto mint; contract must hold enough HTR in its balance to be consumed in the process.
syscall.melt_tokens
Melts an amount of a given token by removing it to the contract balance.
melt_tokens(self, token_uid: TokenUid, amount: int) -> None:
Parameters:
token_uid:TokenUidto melt; contract must have melt authority over it.amount:Amountto melt; contract receives in its balance the redemption of HTR.
syscall.create_token
Creates a new fungible token and adds its initial supply to the contract balance.
create_token(
self,
token_name: str,
token_symbol: str,
amount: int,
mint_authority: bool = True,
melt_authority: bool = True,
) -> TokenUid:
Parameters:
token_name:str; 1-30 UTF-8 characters.token_symbol:str; 1-5 UTF-8 characters.amount:Amountthat denotes initial supply of the token; contract must hold enough HTR in its balance to be consumed in minting initial supply.mint_authority:bool; ifTrue, creates a mint authority for the contract over the new token.melt_authority:bool; ifTrue, creates a melt authority for the contract over the new token.
Return: TokenUid that uniquely identifies the token on the ledger (blockchain).
syscall.call_view_method
Calls a view method of another contract.
call_view_method(self, nc_id: ContractId, method_name: str, *args: Any, **kwargs: Any) -> Any:
Parameters:
nc_id:ContractId; contract to be called.method_name:str; view method to be called.- Use
*argsor**kwargsto pass the method arguments according to the blueprint API of the target contract.
Return: you should know the blueprint API of target contract in order to properly handle return value.
syscall.call_public_method
Calls a public method of another contract.
call_public_method(
self,
nc_id: ContractId,
method_name: str,
actions: list[NCAction],
*args: Any,
**kwargs: Any,
) -> Any:
Parameters:
nc_id:ContractId; contract to be called.method_name:str; public method to be called.actions: list ofNCActionto be performed over target contract; caller contract (itself) must have sufficient funds to perform deposits and target contract must have sufficient funds for withdrawals.- Use
*argsor**kwargsto pass the method arguments according to the blueprint API of the target contract.
Return: you should know the blueprint API of target contract in order to properly handle return value.
syscall.emit_event
Registers an event related to the current contract execution. The event is recorded by all full nodes configured to produce events — i.e., with the ledger events producer feature enabled — and can be consumed by client applications connected to them. For more on ledger events, see Ledger events at Highlighted configurations.
emit_event(self, data: bytes) -> None:
Parameter:
data:bytesthat denotes the event to be registered; limited to 100 KiB. The event is marked as typeNC_EVENTin the event database of each full node. Its contentdataconsists of raw bytes, intended for client applications that know how to interpret it.
syscall.create_contract
Create a new contract.
create_contract(
self,
blueprint_id: BlueprintId,
salt: bytes,
actions: list[NCAction],
*args: Any,
**kwargs: Any,
) -> tuple[ContractId, Any]:
Parameters:
blueprint_id:BlueprintIdto instantiate new contract from.salt:bytesused to generate theContractIdfor contracts created by the current contract itself. This value must be unique for each contract it creates. You can use UUIDs generated via a pseudo-random number generator, or even a simple counter.actions: list ofNCActionas required by methodinitializeof chosen blueprint.- Use
*argsor**kwargsto pass the arguments required by methodinitializeof chosen blueprint.
Return: tuple where the first item is ContractId that uniquely identifies the newly created contract; and second is the return value of method initialize of the chosen blueprint. You should know the chosen blueprint API in order to properly handle return value.
syscall.change_blueprint
Changes the contract blueprint.
change_blueprint(
self,
blueprint_id: BlueprintId
) -> None:
Parameter:
blueprint_id:BlueprintId; denotes the new blueprint for the contract.
syscall.proxy_call_public_method
Invokes the public method of any blueprint as if the contract had that method. Suppose contract uses blueprint . With this method, contract can invoke a public method from a blueprint other than . In the case of fallback method, use syscall.proxy_call_public_method_nc_args.
proxy_call_public_method(
self,
blueprint_id: BlueprintId,
method_name: str,
actions: list[NCAction],
*args: Any,
**kwargs: Any,
) -> Any:
Parameters:
blueprint_id:BlueprintId; blueprint to be used.method_name:str; public method to be invoked.actions: list ofNCActionto be performed.- Use
*argsor**kwargsto pass the method arguments according to API target blueprint.
Return: you should know target blueprint API in order to properly handle return value.
syscall.proxy_call_public_method_nc_args
Same as syscall.proxy_call_public_method, but intended for use within the fallback method. In other words, if you need proxy_call_public_method in fallback method, use proxy_call_public_method_nc_args instead.
proxy_call_public_method_nc_args(
self,
blueprint_id: BlueprintId,
method_name: str,
actions: list[NCAction],
nc_args: NCArgs,
) -> Any:
Parameters: only difference from proxy_call_public_method is that arguments for public method to be invoked are passed via nc_args parameter, rather than *args or **kwargs.
Object:
rng: instance attribute used for random number generation. Seesyscall.rngat section Objects.
Source code:
hathor.nanocontracts.blueprint_env.BlueprintEnvironment
Blueprint.log
Use it to record method execution logs. Useful during development for debugging and testing, and in production for audits. Then, at runtime, use the full node HTTP API to retrieve the logs.
Methods:
debuginfowarnerror
The following subsections describe each of these methods.
log.debug
Create a new DEBUG log entry.
debug(self, message: str, **kwargs: Any) -> None:
log.info
Create a new INFO log entry.
info(self, message: str, **kwargs: Any) -> None:
log.warn
Create a new WARN log entry.
warn(self, message: str, **kwargs: Any) -> None:
log.error
Create a new ERROR log entry.
error(self, message: str, **kwargs: Any) -> None:
In addition to the log message (argument message), all methods accept arbitrary arguments via **kwargs: Any. These arguments will be recorded as key/value pairs. bytes will be represented as hexadecimals, and all values will be recorded as strings.
Source code:
hathor.nanocontracts.nc_exec_logs.NCLogger
syscall.rng
Random number generator (RNG) for use cases that require randomness. This RNG is deterministic based on the hash of the block that executes the contract. As a result, all nodes on the network will generate the same number. However, since it is virtually impossible to know this value beforehand, true randomness is achieved at the time of contract execution. It is based on the ChaCha20 algorithm.
Data attribute:
seed:bytes; seed used to create the RNG object. The seed is the double hash of the first block validating the transaction.
Methods:
randbitsrandbelowrandrangerandintchoicerandom
The following subsections describe each of these methods.
rng.randbits
Returns a random integer in the range , where is integer and . In other words, a random non-negative integer with size .
randbits(self, bits: int) -> int:
rng.randbelow
Returns a random integer in the range , where is integer and .
randbelow(self, n: int) -> int:
rng.randrange
Returns a random integer in the range with step size , where , , and are integers such that and . The result will always be within the given interval, and of the form for a random integer . For example: randrange(start=10, stop=20, step=2) may return any of the following values: 10, 12, 14, 16, or 18.
randrange(self, start: int, stop: int, step: int = 1) -> int:
rng.randint
Returns a random integer in the range , where and are integers such that and .
randint(self, a: int, b: int) -> int:
rng.choice
Chooses a random element from the non-empty Sequence.
choice(self, seq: Sequence[T]) -> T:
Parameter:
seq: anySequencetype supported by the blueprint SDK. See Allowed value types at Blueprint development guidelines.
rng.random
Returns a random float in the range .
random(self) -> float:
Source code:
hathor.nanocontracts.rng.NanoRNG