diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000000..9e41b56d51 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,16 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file + +version: 2 +updates: + - package-ecosystem: "npm" + directory: "/" + schedule: + interval: "weekly" + open-pull-requests-limit: 10 + commit-message: + prefix: "chore" + include: "scope" + diff --git a/config/navbar.config.js b/config/navbar.config.js index 93b9640f83..1371ad9c89 100644 --- a/config/navbar.config.js +++ b/config/navbar.config.js @@ -16,6 +16,11 @@ module.exports = { // label: "Documentation", // position: "left", // }, + { + to: `${routePrefix}/resources/quick-start`, + label: "Quickstart", + position: "left", + }, { to: `${routePrefix}/concepts`, activeBasePath: `${routePrefix}/concepts`, diff --git a/config/sidebar.config.js b/config/sidebar.config.js index 38abaf44fc..91637b38e8 100644 --- a/config/sidebar.config.js +++ b/config/sidebar.config.js @@ -319,7 +319,22 @@ module.exports = { }, items: [ "resources/tokens/cep78/modalities", - "resources/tokens/cep78/using-casper-client", + { + type: "category", + label: "On-chain Installation", + collapsible: true, + collapsed: true, + link: { + type: "doc", + id: "resources/tokens/cep78/using-casper-client/quickstart-guide", + }, + items: [ + "resources/tokens/cep78/using-casper-client/full-installation-tutorial", + "resources/tokens/cep78/using-casper-client/interacting-with-NFTs", + "resources/tokens/cep78/using-casper-client/querying-NFTs", + "resources/tokens/cep78/using-casper-client/testing-NFTs", + ], + }, "resources/tokens/cep78/reverse-lookup", "resources/tokens/cep78/js-tutorial", ], diff --git a/source/docs/casper/concepts/accounts-and-keys.md b/source/docs/casper/concepts/accounts-and-keys.md index 53e444b53b..7acc716cc2 100644 --- a/source/docs/casper/concepts/accounts-and-keys.md +++ b/source/docs/casper/concepts/accounts-and-keys.md @@ -18,7 +18,7 @@ You can also [generate an account hash](#generating-an-account-hash) from a publ ## Creating Accounts and Keys {#creating-accounts-and-keys} -When you create an account on the Casper blockchain, a cryptographic key-pair will be created when using either the [Casper command-line client](#option-1-key-generation-using-the-casper-client) or a block explorer. +When you create an account on the Casper blockchain, a cryptographic key-pair will be created when using either the [Casper command-line client](#option-1-key-generation-using-the-casper-client) or a block explorer. Developers must use the Casper command-line client as described below. Otherwise, they won't have access to the secret key file needed during development. :::note @@ -105,6 +105,8 @@ Start by creating an account using the [Casper Wallet](https://www.casperwallet. :::caution +Developers must generate keys using the [Casper command-line client](#option-1-key-generation-using-the-casper-client) to access the `secret_key.pem` file. + The Casper Signer has been replaced with the Casper Wallet and will be deprecated. We recommend migrating all your Casper accounts to the Casper Wallet as outlined [here](https://www.casperwallet.io/user-guide/signer-user-start-here). ::: diff --git a/source/docs/casper/concepts/dictionaries.md b/source/docs/casper/concepts/dictionaries.md index 4d34efa8c8..6f4ea0fc11 100644 --- a/source/docs/casper/concepts/dictionaries.md +++ b/source/docs/casper/concepts/dictionaries.md @@ -37,7 +37,7 @@ The [Casper CEP-78 Enhanced NFT Standard](https://github.com/casper-ecosystem/ce Simple examples for dictionary use within CEP-78 include the [`approve`](https://github.com/casper-ecosystem/cep-78-enhanced-nft/blob/dev/contract/src/main.rs#L772) dictionary. -More advanced dictionary functionality can be found in the [CEP-78 Page System](https://github.com/casper-ecosystem/cep-78-enhanced-nft#the-cep-78-page-system), which uses a series of dictionaries to keep track of token ownership. These dictionaries form the basis of the reverse lookup mode, which allows users to easily view a list of owned tokens by account or contract. +More advanced dictionary functionality can be found in the [CEP-78 Page System](https://github.com/casper-ecosystem/cep-78-enhanced-nft/blob/dev/docs/reverse-lookup.md#the-cep-78-page-system), which uses a series of dictionaries to keep track of token ownership. These dictionaries form the basis of the reverse lookup mode, which allows users to easily view a list of owned tokens by account or contract. ## Creating Dictionaries in a Contract's Context diff --git a/source/docs/casper/developers/dapps/sdk/python-sdk.md b/source/docs/casper/developers/dapps/sdk/python-sdk.md index 19cf9fa7c0..436a773011 100644 --- a/source/docs/casper/developers/dapps/sdk/python-sdk.md +++ b/source/docs/casper/developers/dapps/sdk/python-sdk.md @@ -1,236 +1,53 @@ # Python SDK -The [Python SDK](https://github.com/casper-network/casper-python-sdk) allows developers to interact with the Casper Node using Python 3.9+. This page covers various examples of using this SDK. +The [Python SDK](https://github.com/casper-network/casper-python-sdk) allows developers to interact with the Casper platform using Python 3.12+. ## Installation -To install the library, run: - ```bash - - pip3 install pycspr -``` - -## Tests - -You can find examples of testing this library with python scripts in the `test` directory. To run the tests, we recommend the *pytest* library: - -```bash - pytest ./tests -``` - -## Usage Examples - -In this section, we outline a couple of essential tasks you can accomplish with the Python SDK: - -* [Sending a transfer](#sending-a-transfer) between two purses -* [Staking](#staking) tokens with a validator - -For further examples, take a look at the [How-tos](https://github.com/casper-network/casper-python-sdk/tree/main/how_tos). - -### Sending a transfer - -This example shows you how to define and transfer funds between purses on a Casper network. Replace the *path_to_cp2_account_key* in the code below with the receiver's account public key. - -```python - import os - import pathlib - import random - import typing - - import pycspr - from pycspr.client import NodeClient - from pycspr.client import NodeConnectionInfo - from pycspr.crypto import KeyAlgorithm - from pycspr.types import PrivateKey - from pycspr.types import Deploy - from pycspr.types import PublicKey - - # path to cp1 secret key - defaults to NCTL user 1. - path_to_cp1_secret_key = pathlib.Path(os.getenv("NCTL")) / "assets" / "net-1" / "users" / "user-1" / "secret_key.pem" - - # type of cp1 secret key - defaults to ED25519. - type_of_cp1_secret_key = KeyAlgorithm.ED25519.name, - - # path to cp2 account key - defaults to NCTL user 2. - path_to_cp2_account_key = pathlib.Path(os.getenv("NCTL")) / "assets" / "net-1" / "users" / "user-2" / "public_key_hex" - - # name of target chain - defaults to NCTL chain. - chain_name = "casper-net-1" - - # host address of target node - defaults to NCTL node 1. - node_host = "localhost" - - # Node API JSON-RPC port - defaults to 11101 @ NCTL node 1. - node_port_rpc = 11101 - - def _main(node_host, node_port_rpc, path_to_cp1_secret_key, type_of_cp1_secret_key,path_to_cp2_account_key, chain_name): - """Main entry point. - :param args: Parsed command line arguments. - """ - # Set node client. - client = _get_client(node_host, node_port_rpc) - - # Set counter-parties. - cp1, cp2 = _get_counter_parties(path_to_cp1_secret_key, type_of_cp1_secret_key,path_to_cp2_account_key) - - # Set deploy. - deploy: Deploy = _get_deploy(chain_name, cp1, cp2) - - # Approve deploy. - deploy.approve(cp1) - - # Dispatch deploy to a node. - client.deploys.send(deploy) - - #If deploy is successful send the indication - print(f"Deploy dispatched to node [{node_host}]: {deploy.hash.hex()}") - - - def _get_client(node_host, node_port_rpc) -> NodeClient: - """Returns a pycspr client instance. - """ - return NodeClient(NodeConnectionInfo( - host=node_host, - port_rpc=node_port_rpc, - )) - - - def _get_counter_parties(path_to_cp1_secret_key, type_of_cp1_secret_key,path_to_cp2_account_key) -> typing.Tuple[PrivateKey, PublicKey]: - """Returns the 2 counter-parties participating in the transfer. - """ - cp1 = pycspr.parse_private_key( - path_to_cp1_secret_key, - type_of_cp1_secret_key, - ) - cp2 = pycspr.parse_public_key( - path_to_cp2_account_key - ) - - return cp1, cp2 - - - def _get_deploy(chain_name, cp1: PrivateKey, cp2: PublicKey) -> Deploy: - """Returns transfer deploy to be dispatched to a node. - """ - # Set standard deploy parameters. - deploy_params = pycspr.create_deploy_parameters( - account = cp1, - chain_name = chain_name - ) - - # Set deploy. - deploy = pycspr.create_native_transfer( - params = deploy_params, - amount = int(2.5e9), - target = cp2.account_hash, - correlation_id = random.randint(1, 1e6) - ) - - return deploy - - - # Entry point. - if __name__ == '__main__': - _main(node_host, node_port_rpc, path_to_cp1_secret_key, type_of_cp1_secret_key, path_to_cp2_account_key, chain_name) +pip3 install pycspr ``` -### Staking - -This example shows you how to define and stake funds with a validator. +## How To's -```python +The following set of How To's cover the full SDK feature set and are designed to be run against a [CCTL](https://github.com/casper-network/cctl) network. - import os - import pathlib +### Cryptography - import pycspr - from pycspr.client import NodeClient - from pycspr.client import NodeConnectionInfo - from pycspr.crypto import KeyAlgorithm - from pycspr.types import Deploy - from pycspr.types import PrivateKey +* [How To: Apply a checksum](https://github.com/casper-network/casper-python-sdk/blob/main/how_tos/crypto/how_to_apply_a_checksum.py) - # path to cp1 secret key - defaults to NCTL user 1. - path_to_validator_secret_key = pathlib.Path(os.getenv("NCTL")) / "assets" / "net-1" / "users" / "user-1" / "secret_key.pem" +* [How To: Create Key Pairs](https://github.com/casper-network/casper-python-sdk/blob/main/how_tos/crypto/how_to_create_key_pairs.py) - # type of cp1 secret key - defaults to ED25519. - type_of_validator_secret_key = KeyAlgorithm.ED25519.name +* [How To: Hash data](https://github.com/casper-network/casper-python-sdk/blob/main/how_tos/crypto/how_to_hash_data.py) - # path to session code wasm binary - defaults to NCTL bin/eco/add_bid.wasm. - path_to_wasm = pathlib.Path(os.getenv("NCTL")) / "assets" / "net-1" / "bin" / "auction" / "add_bid.wasm" +* [How To: Sign data](https://github.com/casper-network/casper-python-sdk/blob/main/how_tos/crypto/how_to_sign_data.py) - # amount to stake, i.e. bond, into the network. - amount = int(2.5e9) +### Deploys - # amount to charge delegators for service provision. - delegation_rate = 2 +* [How To: Transfer funds between 2 accounts](https://github.com/casper-network/casper-python-sdk/blob/main/how_tos/deploys/how_to_transfer.py) - # name of target chain - defaults to NCTL chain. - chain_name = "casper-net-1" +* [How To: Delegate funds to a validator](https://github.com/casper-network/casper-python-sdk/blob/main/how_tos/deploys/how_to_delegate.py) - # host address of target node - defaults to NCTL node 1. - node_host = "localhost" +* [How To: Undelegate funds from a validator](https://github.com/casper-network/casper-python-sdk/blob/main/how_tos/deploys/how_to_undelegate.py) - # Node API JSON-RPC port - defaults to 11101 @ NCTL node 1. - node_port_rpc = 11101 +* [How To: Stake funds as a validator](https://github.com/casper-network/casper-python-sdk/blob/main/how_tos/deploys/how_to_stake.py) - def _main(node_host, node_port_rpc, path_to_validator_secret_key, type_of_validator_secret_key, chain_name, amount, delegation_rate, path_to_wasm): - """Main entry point. - :param args: Parsed command line arguments. - """ - # Set node client. - client: NodeClient = _get_client(node_host, node_port_rpc) +* [How To: Unstake funds as a validator](https://github.com/casper-network/casper-python-sdk/blob/main/how_tos/deploys/how_to_unstake.py) - # Set validator key. - validator: PrivateKey = pycspr.parse_private_key( - path_to_validator_secret_key, - type_of_validator_secret_key, - ) +### Smart Contracts - # Set deploy. - deploy: Deploy = _get_deploy(validator, chain_name, amount, delegation_rate, path_to_wasm) +* [How To: Install a smart contract](https://github.com/casper-network/casper-python-sdk/blob/main/how_tos/smart_contracts/how_to_install.py) - # Approve deploy. - deploy.approve(validator) +* [How To: Invoke a smart contract](https://github.com/casper-network/casper-python-sdk/blob/main/how_tos/smart_contracts/how_to_invoke.py) - # Dispatch deploy to a node. - client.deploys.send(deploy) +* [How To: Query a smart contract](https://github.com/casper-network/casper-python-sdk/blob/main/how_tos/smart_contracts/how_to_query.py) - print(f"Deploy dispatched to node [{node_host}]: {deploy.hash.hex()}") +### Node APIs +* [How To: Use REST API](https://github.com/casper-network/casper-python-sdk/blob/main/how_tos/node_apis/how_to_use_rest_client.py) - def _get_client(node_host, node_port_rpc) -> NodeClient: - """Returns a pycspr client instance. - """ - return NodeClient(NodeConnectionInfo( - host = node_host, - port_rpc = node_port_rpc, - )) +* [How To: Use RPC API](https://github.com/casper-network/casper-python-sdk/blob/main/how_tos/node_apis/how_to_use_rpc_client.py) +* [How To: Use Speculative RPC API](https://github.com/casper-network/casper-python-sdk/blob/main/how_tos/node_apis/how_to_use_speculative_rpc_client.py) - def _get_deploy(validator: PrivateKey, chain_name, amount, delegation_rate, path_to_wasm) -> Deploy: - """Returns delegation deploy to be dispatched to a node. - """ - # Set standard deploy parameters. - deploy_params = pycspr.create_deploy_parameters( - account = validator, - chain_name = chain_name - ) - - # Set deploy. - deploy = pycspr.create_validator_auction_bid( - params = deploy_params, - amount = amount, - delegation_rate = delegation_rate, - public_key = validator.as_public_key(), - path_to_wasm = path_to_wasm - ) - - return deploy - - - # Entry point. - if __name__ == '__main__': - _main(node_host, node_port_rpc, path_to_validator_secret_key, type_of_validator_secret_key, chain_name, amount, delegation_rate, path_to_wasm) -``` +* [How To: Use SSE API](https://github.com/casper-network/casper-python-sdk/blob/main/how_tos/node_apis/how_to_use_sse_client.py) diff --git a/source/docs/casper/developers/dapps/setup-nctl.md b/source/docs/casper/developers/dapps/setup-nctl.md index ba469b5800..8c2937f9b4 100644 --- a/source/docs/casper/developers/dapps/setup-nctl.md +++ b/source/docs/casper/developers/dapps/setup-nctl.md @@ -31,14 +31,14 @@ First, you will need to install a set of tools required for running NCTL. Instructions for MacOS: ```bash -$ curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py -$ python3 get-pip.py +curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py +python3 get-pip.py ``` Instructions for Linux: ```bash -$ sudo apt install python3-pip +sudo apt install python3-pip ``` **Step 2.** Install **pkg-config**, a program used to compile and link against one or more libraries. @@ -46,13 +46,13 @@ $ sudo apt install python3-pip Instructions for MacOS: ```bash -$ brew install pkg-config +brew install pkg-config ``` Instructions for Linux: ```bash -$ sudo apt install pkg-config +sudo apt install pkg-config ``` **Step 3.** Install either **libssl-dev** (Linux) or **openssl** (MacOS), which are toolkits for the Transport Layer Security (TLS) and Secure Sockets Layer (SSL) protocols. They also serve as general-purpose cryptography libraries. @@ -60,13 +60,13 @@ $ sudo apt install pkg-config Instructions for MacOS: ```bash -$ brew install openssl +brew install openssl ``` Instructions for Linux: ```bash -$ sudo apt install libssl-dev +sudo apt install libssl-dev ``` **Step 4.** You will also need the **gcc** and **g++** compilers, which usually come as part of developer command-line tools (versions 7.5.0 at the time of this writing). @@ -74,72 +74,93 @@ $ sudo apt install libssl-dev Instructions for MacOS: ```bash -$ xcode-select --install -$ gcc --version -$ g++ --version +xcode-select --install +gcc --version +g++ --version ``` Instructions for Linux: ```bash -$ sudo apt install build-essential -$ gcc --version -$ g++ --version +sudo apt install build-essential +gcc --version +g++ --version ``` -**Step 5.** Create and activate a new virtual environment. **Commands applicable to the virtual environment will be prefixed with (env)**. Run the following commands to set it up. +**Important Note:** + +The following commands need to be executed within the Bash shell. While MacOS and some Linux distributions use Zsh by default, they also include Bash. To ensure proper execution of the subsequent commands, switching to Bash is recommended. If the command does not work, please refer to the Bash documentation on how to install it on your system. + +**Step 5.** Switching to Bash Shell: + +Type the following command in your terminal: Instructions for MacOS and Linux: ```bash -$ python3 -m venv env -$ source env/bin/activate -(env) $ +bash ``` -**Step 6.** Inside the virtual environment, upgrade **pip** to the latest version. +This will launch a new Bash shell session. You can then proceed with the tutorial. + +**Step 6.** Create and activate a new virtual environment. **Commands applicable to the virtual environment will be prefixed with (env)**. Run the following commands to set it up. Instructions for MacOS and Linux: ```bash -(env) $ pip install --upgrade pip +python3 -m venv env +source env/bin/activate +``` + +Once you have activated the virtual environment, your terminal prompt will change to indicate you're working within it. It will usually look something like this: + +```bash +(env) $ // This line is for visual representation only, not to be copied ``` -**Step 7.** Install **jq**, a command-line JSON processor. +**Step 7.** Inside the virtual environment, upgrade **pip** to the latest version. Instructions for MacOS and Linux: ```bash -(env) $ pip install jq +pip install --upgrade pip ``` -**Step 8.** Install **supervisor**, a cross-platform process manager. +**Step 8.** Install **jq**, a command-line JSON processor. Instructions for MacOS and Linux: ```bash -(env) $ pip install supervisor +pip install jq ``` -**Step 9.** Install **toml**, a configuration file parser. +**Step 9.** Install **supervisor**, a cross-platform process manager. Instructions for MacOS and Linux: ```bash -(env) $ pip install toml +pip install supervisor +``` + +**Step 10.** Install **toml**, a configuration file parser. + +Instructions for MacOS and Linux: + +```bash +pip install toml ``` ## Setting up the Network {#setting-up-the-network} You are now ready to set up and run your local network of Casper nodes. -**Step 10.** Clone the _casper-node-launcher_ software in your working directory, which we will call _WORKING_DIRECTORY_. **Very Important!!! Choose a short path for your working directory**; otherwise, the NCTL tool will report that the path is too long. +**Step 11.** Clone the _casper-node-launcher_ software in your working directory, which we will call _WORKING_DIRECTORY_. **Very Important!!! Choose a short path for your working directory**; otherwise, the NCTL tool will report that the path is too long. Instructions for MacOS and Linux: ```bash -(env) $ cd -(env) $ git clone https://github.com/casper-network/casper-node-launcher +cd +git clone https://github.com/casper-network/casper-node-launcher ``` :::note @@ -148,37 +169,36 @@ Assuming you have set up a small local network, you can speed up the process of ::: -**Step 11.** Next, clone the _casper-node_ software, also in your working directory. +**Step 12.** Next, clone the _casper-node_ software, also in your working directory. Instructions for MacOS and Linux: ```bash -(env) $ git clone https://github.com/casper-network/casper-node +git clone https://github.com/casper-network/casper-node ``` -**Step 12.** Finally, clone the _casper-client-rs_ software in your working directory. +**Step 13.** Finally, clone the _casper-client-rs_ software in your working directory. Instructions for MacOS and Linux: ```bash -(env) $ git clone https://github.com/casper-ecosystem/casper-client-rs +git clone https://github.com/casper-ecosystem/casper-client-rs ``` - -**Step 13.** Activate the NCTL environment with the following command. +**Step 14.** Activate the NCTL environment with the following command. Instructions for MacOS and Linux: ```bash -(env) $ source casper-node/utils/nctl/activate +source casper-node/utils/nctl/activate ``` -**Step 14.** Compile the NCTL binary scripts. The following command compiles both the _casper-node_ and the _casper-client_ in release mode. +**Step 15.** Compile the NCTL binary scripts. The following command compiles both the _casper-node_ and the _casper-client_ in release mode. Instructions for MacOS and Linux: ```bash -(env) $ nctl-compile +nctl-compile ``` :::note @@ -187,12 +207,12 @@ The compilation takes some time, so it might be a perfect moment to get some cof ::: -**Step 15.** Set up all the assets required to run a local network, including binaries, chainspec, config, faucet, and keys. Also, spin up the network right after. The default network will have 10 nodes, with 5 active nodes and 5 inactive nodes. +**Step 16.** Set up all the assets required to run a local network, including binaries, chainspec, config, faucet, and keys. Also, spin up the network right after. The default network will have 10 nodes, with 5 active nodes and 5 inactive nodes. Instructions for MacOS and Linux: ```bash -(env) $ nctl-assets-setup && nctl-start +nctl-assets-setup && nctl-start ``` Once a network is up and running, you can control each node within the network and add new nodes to the network. @@ -209,13 +229,13 @@ Here is the command line output you would expect. ## Stopping the Network {#stopping-the-network} -**Step 15.** Although not necessary, you can stop and clean the NCTL setup with the following commands. +**Step 17.** Although not necessary, you can stop and clean the NCTL setup with the following commands. Instructions for MacOS and Linux: ```bash -(env) $ nctl-stop -(env) $ nctl-clean +nctl-stop +nctl-clean ``` ## Next Steps {#next-steps} diff --git a/source/docs/casper/developers/prerequisites.md b/source/docs/casper/developers/prerequisites.md index e2c9f8a380..87f2f7c1fd 100644 --- a/source/docs/casper/developers/prerequisites.md +++ b/source/docs/casper/developers/prerequisites.md @@ -4,13 +4,7 @@ import TabItem from '@theme/TabItem'; # Development Prerequisites -This page covers the necessary software for your Casper development environment. To develop comfortably, you should use `Linux Ubuntu 20.04` or `macOS`. Developing on Windows is not advised. - -:::caution - -Casper does not officially support `macOS`. If you encounter any problems, reach out to the community on [Telegram](https://t.me/casperblockchain) or [Discord](https://discord.com/invite/casperblockchain). - -::: +This page covers the necessary software for your Casper development environment. To develop comfortably, you should use `Linux Ubuntu 20.04`. Casper does not officially support `macOS`, but the commands are included for your convenience. If you encounter any problems, reach out to the community on [Telegram](https://t.me/casperblockchain) or [Discord](https://discord.com/invite/casperblockchain). Developing on Windows is not advised. ## Preparing your Development Environment @@ -172,7 +166,7 @@ You will find the `casper-client` executable in the `target/release` directory. If you plan to compile contracts from the source code, including those provided in the [casper-node](https://github.com/casper-network/casper-node) repository, install `CMake` with the commands below. -[CMake](https://cmake.org/) is a popular build tool that we will use, and you may have it installed. If you do, make sure that you have the latest version. If you need to install or upgrade it, follow the steps below or on the [CMake website](https://cmake.org/install/). Once installed, check your version as shown below. +[CMake](https://cmake.org/) is a popular build tool that we will use, and you may have it installed. If you do, make sure that you have the latest version. If you need to install or upgrade it, follow the steps below or on the [CMake website](https://cmake.org/resources/). Once installed, check your version as shown below. @@ -242,11 +236,9 @@ The Casper blockchain uses an on-chain account-based model, uniquely identified By default, a transactional interaction with the blockchain takes the form of a `Deploy` cryptographically signed by the key-pair corresponding to the `PublicKey` used to create the account. -Users can create accounts using the [Casper command-line client](../concepts/accounts-and-keys.md#option-1-generating-keys-using-the-casper-client-option-1-key-generation-using-the-casper-client). - -Alternatively, some Casper networks, such as the official Testnet and Mainnet, provide a browser-based block explorer that allows account creation as outlined [here](../concepts/accounts-and-keys.md#option-2-generating-keys-using-a-block-explorer-option-2-key-generation-using-a-block-explorer). +Developers must create accounts using the [Casper command-line client](../concepts/accounts-and-keys.md#option-1-generating-keys-using-the-casper-client-option-1-key-generation-using-the-casper-client) to access the `secret_key.pem` file needed during development. -Use either method to generate an account and its corresponding cryptographic key-pair. +Some Casper networks, such as the official Testnet and Mainnet, provide wallets that allow account creation as outlined here. However, these wallets do not give developers access to the secret key file. ### Generating the account hash diff --git a/source/docs/casper/developers/writing-onchain-code/testing-contracts.md b/source/docs/casper/developers/writing-onchain-code/testing-contracts.md index 344928009d..47708404fc 100644 --- a/source/docs/casper/developers/writing-onchain-code/testing-contracts.md +++ b/source/docs/casper/developers/writing-onchain-code/testing-contracts.md @@ -10,7 +10,6 @@ The Casper test support crate is one of many options for testing contracts befor ::: - ### Defining Dependencies in `Cargo.toml` This guide uses the project structure, and example contract outlined [here](./simple-contract.md#directory-structure) for creating tests. @@ -19,14 +18,14 @@ To begin, outline the required test dependencies in the `/tests/Cargo.toml` file ```rust [dependencies] -casper-execution-engine = "2.0.1" -casper-engine-test-support = { version = "2.2.0", features = ["test-support"] } -casper-types = "1.5.0" +casper-execution-engine = "5.0.0" +casper-engine-test-support = { version = "5.0.0", features = ["test-support"] } +casper-types = "3.0.0" ``` -- `casper-execution-engine` - This crate imports the execution engine functionality, enabling Wasm execution within the test framework. Each node contains an instance of an execution engine, and the testing framework simulates this behavior. -- `casper-engine-test-support` - A helper crate that provides the interface to write tests and interact with an instance of the execution engine. -- `casper-types` - Types shared by many Casper crates for use on a Casper network. +- `casper-execution-engine` - This crate imports the execution engine functionality, enabling Wasm execution within the test framework. Each node contains an instance of an execution engine, and the testing framework simulates this behavior. +- `casper-engine-test-support` - A helper crate that provides the interface to write tests and interact with an instance of the execution engine. +- `casper-types` - Types shared by many Casper crates for use on a Casper network. ## Writing the Tests {#writing-the-tests} @@ -55,7 +54,7 @@ Import external test support, which includes a variety of default values and hel // Outlining aspects of the Casper test support crate to include. use casper_engine_test_support::{ ExecuteRequestBuilder, InMemoryWasmTestBuilder, DEFAULT_ACCOUNT_ADDR, - DEFAULT_RUN_GENESIS_REQUEST, + PRODUCTION_RUN_GENESIS_REQUEST, }; // Custom Casper types that will be used within this test. use casper_types::{runtime_args, ContractHash, RuntimeArgs}; @@ -64,30 +63,36 @@ Import external test support, which includes a variety of default values and hel Next, you need to define any global variables or constants for the test. ```rust - const COUNTER_V1_WASM: &str = "counter-v1.wasm"; // The first version of the contract - const COUNTER_V2_WASM: &str = "counter-v2.wasm"; // The second version of the contract - const COUNTER_CALL_WASM: &str = "counter-call.wasm"; // Session code that calls the contract - - const CONTRACT_KEY: &str = "counter"; // Named key referencing this contract - const COUNT_KEY: &str = "count"; // Named key referencing the value to increment/decrement - const CONTRACT_VERSION_KEY: &str = "version"; // Key maintaining the version of a contract package - - const ENTRY_POINT_COUNTER_DECREMENT: &str = "counter_decrement"; // Entry point to decrement the count value - const ENTRY_POINT_COUNTER_INC: &str = "counter_inc"; // Entry point to increment the count value + // Contract Wasm File Paths (Constants) + const COUNTER_V1_WASM: &str = "counter-v1.wasm"; + const COUNTER_V2_WASM: &str = "counter-v2.wasm"; + const COUNTER_V3_WASM: &str = "counter-v3.wasm"; + const COUNTER_CALL_WASM: &str = "counter-call.wasm"; + + // Contract Storage Keys (Constants) + const CONTRACT_KEY: &str = "counter"; + const COUNT_KEY: &str = "count"; + const LAST_UPDATED_KEY: &str = "last_updated"; + const CONTRACT_VERSION_KEY: &str = "version"; + + // Contract Entry Points (Constants) + const ENTRY_POINT_COUNTER_DECREMENT: &str = "counter_decrement"; + const ENTRY_POINT_COUNTER_INC: &str = "counter_inc"; + const ENTRY_POINT_COUNTER_LAST_UPDATED_AT: &str = "counter_last_updated_at"; ``` ### Creating a Test Function Each test function installs the contract and calls entry points to assert that the contract's behavior matches expectations. The test uses the `InMemoryWasmTestBuilder` to invoke an instance of the execution engine, effectively simulating the process of installing the contract on the chain. -As part of this process, we use the `DEFAULT_RUN_GENESIS_REQUEST` to install the system contracts necessary for the tests, including the `Mint`, `Auction`, and `HandlePayment`contracts, as well as establishing a default account and funding the associated purse. +As part of this process, we use the `PRODUCTION_RUN_GENESIS_REQUEST` to install the system contracts necessary for the tests, including the `Mint`, `Auction`, and `HandlePayment`contracts, as well as establishing a default account and funding the associated purse. ```rust #[test] /// Install version 1 of the counter contract and check its available entry points. ... fn install_version1_and_check_entry_points() { let mut builder = InMemoryWasmTestBuilder::default(); - builder.run_genesis(&*DEFAULT_RUN_GENESIS_REQUEST).commit(); + builder.run_genesis(&PRODUCTION_RUN_GENESIS_REQUEST).commit(); // See the repository for the full function. } @@ -171,6 +176,33 @@ The following session code uses the contract hash to identify the contract, the .commit(); ``` +:::tip + +**Testing Time-Sensitive Functions** + +Normally, smart contracts operate on a blockchain where time advances in blocks. Testing functions that rely on time can be tricky. + +**Simulating Time with `with_block_time`** + +When building a request to call a contract function (using `ExecuteRequestBuilder`), you can set a custom block time with `.with_block_time(desired_time)`. This pretends the function is called at that specific time. + +**Example:** + +```rust + let session_code_request = ExecuteRequestBuilder::standard( + *DEFAULT_ACCOUNT_ADDR, + COUNTER_CALL_WASM, + runtime_args! { + CONTRACT_KEY => contract_v1_hash + }, + .with_block_time(5000) + .build(); +``` + +This lets you test how your contract behaves at different points in time, all within your unit test. + +::: + #### Evaluating and Comparing Results After calling the contract, we should verify the results received to ensure the contract operated as intended. The `builder` method retrieves the required information and converts it to the value type required. Then, `assert_eq!()` compares the result against the expected value. @@ -199,10 +231,10 @@ Each contract installation will require an additional Wasm file installed throug The major difference between calling a contract from session code versus contract code is the ability to use non-standard dependencies for the `ExecuteRequestBuilder`. Where session code must designate a Wasm file within the standard dependencies, contract code can use one of the four available options for calling other contracts, namely: -- `contract_call_by_hash` - Calling a contract by its `ContractHash`. -- `contract_call_by_name` - Calling a contract referenced by a named key in the signer's Account context. -- `versioned_contract_call_by_hash` - Calling a specific contract version using its `ContractHash`. -- `versioned_contract_call_by_name` - Calling a specific version of a contract referenced by a named key in the signer's Account context. +- `contract_call_by_hash` - Calling a contract by its `ContractHash`. +- `contract_call_by_name` - Calling a contract referenced by a named key in the signer's Account context. +- `versioned_contract_call_by_hash` - Calling a specific contract version using its `ContractHash`. +- `versioned_contract_call_by_name` - Calling a specific version of a contract referenced by a named key in the signer's Account context. The calling contract must also provide an entry point and any necessary runtime arguments in all cases. @@ -241,5 +273,5 @@ You may also wish to test your contracts on the Casper [Testnet](https://testnet ## What's Next? {#whats-next} -- Understand [session code](./contract-vs-session.md#what-is-session-code) and how it triggers a smart contract. -- Learn to [install a contract and query global state](../cli/installing-contracts.md) with the Casper command-line client. +- Understand [session code](./contract-vs-session.md#what-is-session-code) and how it triggers a smart contract. +- Learn to [install a contract and query global state](../cli/installing-contracts.md) with the Casper command-line client. diff --git a/source/docs/casper/operators/setup-network/create-private.md b/source/docs/casper/operators/setup-network/create-private.md index ccb53fbc4b..44c171ad3a 100644 --- a/source/docs/casper/operators/setup-network/create-private.md +++ b/source/docs/casper/operators/setup-network/create-private.md @@ -27,7 +27,7 @@ Casper private networks operate in a similar way to the Casper public network. T ## Prerequisites Follow these guides to set up the required environment and user accounts. - [Setting up the Casper client](../../developers/prerequisites.md#the-casper-command-line-client) -- [Setting up the client for interacting with the network](https://github.com/casper-ecosystem/casper-client-rs/blob/main/README.md#casper-client) +- [Setting up the client for interacting with the network](https://github.com/casper-ecosystem/casper-client-rs/blob/dev/README.md#casper-client) - [Setting up an Account](../../developers/prerequisites.md#setting-up-an-account) @@ -544,4 +544,4 @@ After this step, the private network would be ready for use. ## Setting up a Block Explorer -Private and hybrid blockchains can find information on how to set up and operate our free version of a block explorer [here](https://github.com/casper-network/casper-blockexplorer-frontend). \ No newline at end of file +Private and hybrid blockchains can find information on how to set up and operate our free version of a block explorer [here](https://github.com/casper-network/casper-blockexplorer-frontend). diff --git a/source/docs/casper/resources/advanced/cross-contract.md b/source/docs/casper/resources/advanced/cross-contract.md index 45a8908919..abe5f82c74 100644 --- a/source/docs/casper/resources/advanced/cross-contract.md +++ b/source/docs/casper/resources/advanced/cross-contract.md @@ -8,25 +8,25 @@ import useBaseUrl from '@docusaurus/useBaseUrl'; # Cross-Contract Communication This tutorial assumes that you have worked through the following examples. If you have not already done so, then we recommend that you do so now: -- [Developer Prerequisites](../../developers/prerequisites.md) -- [Getting Started with Rust](../../developers/writing-onchain-code/getting-started.md) -- [Writing a Basic Smart Contract in Rust](../../developers/writing-onchain-code/simple-contract.md) + +- [Developer Prerequisites](../../developers/prerequisites.md) +- [Getting Started with Rust](../../developers/writing-onchain-code/getting-started.md) +- [Writing a Basic Smart Contract in Rust](../../developers/writing-onchain-code/simple-contract.md) ## Tutorial Outline {#outline} This tutorial covers some variations of cross-contract communication. Most complex scenarios use cross-contract communication, so it is crucial to understand how this works. It is best explained using the uniswap v2 protocol. -Uniswap v2 protocol consists of multiple smart contracts which govern a unified blockchain application and each contract serves a different purpose. -The contracts are as follows: -- Factory -- Pair -- Pair (ERC20) -- Library -- Router01 -- Router02 +Uniswap v2 protocol consists of multiple smart contracts which govern a unified blockchain application and each contract serves a different purpose. The contracts are as follows: + +- Factory +- Pair +- Pair (ERC20) +- Library +- Router01 +- Router02 -The Factory contract is generally used to create a token pair. It throws an event that a pair has been created and allows the user to read the pair created. The most important to notice is that the generation of a token pair actually creates a contract of type Pair under a new address hash. -The Pair smart contract is used to perform operations like mint or burn on a created pair of tokens. +The Factory contract is generally used to create a token pair. It throws an event that a pair has been created and allows the user to read the pair created. The most important to notice is that the generation of a token pair actually creates a contract of type Pair under a new address hash. The Pair smart contract is used to perform operations like mint or burn on a created pair of tokens. Having this in mind we will be building two contracts which reference each other in some shape or form. We will look at how the keys are deployed in the contract's context and how we can pass the contract hash into a deployed contract so another contract can be called. @@ -38,23 +38,22 @@ In the appropriate folder, create the project for the contract using the followi cargo casper cross-contract ``` -This will create the following structure under your desired smart contract folder: +This will create the following directory structure within your smart contract folder. ```bash -cross-contract/ -└── contract/ - ├── .cargo/ - └── config.toml - ├── src/ - └── main.rs - └── Cargo.toml -└── tests/ - ├── src/ - └── integration-tests.rs - └── Cargo.toml -└── .travis.yml +cross-contract +├──contract +│ ├── Cargo.toml +│   ├── rust-toolchain +│   ├── src +│   │   └── main.rs +│   └── target +├──tests +│ ├── Cargo.toml +│ ├── src +│ │   └── integration_tests.rs +│ └── target └── Makefile -└── rust-toolchain ``` After creating the project directory structure, use the following commands to go into the project folder and compile the files: @@ -65,8 +64,7 @@ make prepare make build-contract ``` -This will also create a target folder under the contract folder where the .wasm of the contract can be found. -Additionally you can check if the tests can be performed using the following command: +This will produce the `.wasm` file of our contract. It can be found in `contract/target/wasm32-unknown-unknown/release/contract.wasm`. Additionally you can check if the tests can be performed using the following command: ```bash make test @@ -84,29 +82,29 @@ test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; fini :::tip -If this is not the case and you see the following error: +When you try to run the tests, you might encounter errors if the project's dependencies are outdated. If you see an error message similar to the following: -```bash +```rust warning: `tests` (bin "integration-tests" test) generated 2 warnings error: could not compile `tests` due to 3 previous errors; 2 warnings emitted make: *** [test] Error 101 ``` -Then it is useful to check if the dependencies in `Cargo.toml` are still up to date. +This indicates potential issues with outdated dependencies. Use the `cargo update` command to check for and install any available updates for your project's dependencies or do it manually through `Cargo.toml` file. CargoToml -If you see the red cross, it means the version is not up to date and has to be updated. +If you are using cargo extensions in your editor you will see a warning next to the outdated dependencies. ::: ## Changing the Standard Contract {#changing-contract} -The standard Casper contract from `cargo-casper` contains some methods that we will reuse. However, we will be getting rid of most auto-generated code. +The standard Casper contract from `cargo-casper` contains some methods that we will reuse. However, we will remove most of the automatically generated code. We will be changing the `main.rs` file. Your code should look exactly as below: -```bash +```rust #![no_std] #![no_main] @@ -117,7 +115,7 @@ compile_error!("target arch should be wasm32: compile with '--target wasm32-unkn // `no_std` environment. extern crate alloc; -// The elementary types +// The elementary types use alloc::string::String; use alloc::vec::Vec; use alloc::collections::BTreeMap; @@ -138,14 +136,14 @@ pub extern "C" fn call() { } ``` + This will serve as a base for introducing the elements needed for cross-contract communication. -In a contract, you should first define the `call` entry point. It should be understood as a `constructor` for the contract. Everything included in the `call` entry point will be visible as metadata on a Casper network, in the contract's context. -You should already be familiar with the `call` entry point from the [Writing a Basic Smart Contract in Rust](../../developers/writing-onchain-code/simple-contract.md) document. If this is not the case, be sure to familiarize yourself with it now. +In a contract, you should first define the `call` entry point. It should be understood as a `constructor` for the contract. Everything included in the `call` entry point will be visible as metadata on a Casper network, in the contract's context. You should already be familiar with the `call` entry point from the [Writing a Basic Smart Contract in Rust](../../developers/writing-onchain-code/simple-contract.md) document. If this is not the case, be sure to familiarize yourself with it now. -The contract code, with changes to the `call` entry point, should look as shown below: +The contract code, with changes to the `call` entry point, should look as shown below: -```bash +```rust #![no_std] #![no_main] @@ -156,7 +154,7 @@ compile_error!("target arch should be wasm32: compile with '--target wasm32-unkn // `no_std` environment. extern crate alloc; -// The elementary types +// The elementary types use alloc::string::String; use alloc::vec::Vec; use alloc::collections::BTreeMap; @@ -187,7 +185,7 @@ pub extern "C" fn call() { // Insert the new value into the named keys named_keys.insert(String::from("message"),value_ref.into()); // use into to wrap the Uref into a casper_types::Key - // Create a new vector + // Create a new vector let mut params = Vec::new(); vec.push(Parameter::new("message", CLType::String)); @@ -206,7 +204,7 @@ pub extern "C" fn call() { // The contract is stored in the global state let (stored_contract_hash, _contract_version) = storage::new_contract( entry_points, // entry points - Some(named_keys), // named keys + Some(named_keys), // named keys Some("Hello_world_package_name".to_string()), // package name Some("Hello_world_access_uref".to_string()) // access uref ); @@ -219,19 +217,19 @@ pub extern "C" fn call() { :::tip -`runtime` and `storage` appear frequently in our code. If these terms are unfamiliar to you, you should familiarize yourself with the [Contract API Modules]( https://docs.rs/casper-contract/latest/casper_contract/contract_api/index.html). +`runtime` and `storage` appear frequently in our code. If these terms are unfamiliar to you, you should familiarize yourself with the [Contract API Modules](https://docs.rs/casper-contract/latest/casper_contract/contract_api/index.html). ::: -The metadata for each of the contract's entry points is defined in the `call` entry point. When installing the contract, the system will look for the name of the entry point as specified by the metadata for that entry point. Therefore, each of the entry points defined in the code must share the same name as the `String` value passed when defining the metadata for the entry point. +The metadata for each of the contract's entry points is defined in the `call` entry point. When installing the contract, the Casper Node will search for the entry point based on the name specified in its metadata. Therefore, each of the entry points defined in the code must share the same name as the `String` value passed when defining the metadata for the entry point. -The #[no_mangle] flag ensures that the compiler does not modify the name of the entry point. The compiler will not enforce the condition that the name of the entry point is the same value present in its metadata definition, therefore the developer must be careful when defining their entry points. +The `#[no_mangle]` attribute guarantees that the compiler won't alter the entry point's name. It doesn't mandate that the name matches its metadata definition, so developers need to be cautious when specifying entry points. -In our case, we will define the entry point `update_msg` in the contract code just before `call`. +In our case, we will define the entry point `update_msg` in the contract code just before `call`. Your complete contract should match the following: -```bash +```rust #![no_std] #![no_main] @@ -242,7 +240,7 @@ compile_error!("target arch should be wasm32: compile with '--target wasm32-unkn // `no_std` environment. extern crate alloc; -// The elementary types +// The elementary types use alloc::string::String; use alloc::vec::Vec; use alloc::collections::BTreeMap; @@ -275,11 +273,11 @@ pub extern "C" fn call() { // The value will be wraped in a URef let value_ref = storage::new_uref(value); // Creating the new set of named keys - // The keys are a Map of Key/Value + // The keys are a Map of Key/Value let mut named_keys: BTreeMap = BTreeMap::new(); // Insert the new value into the named keys named_keys.insert(String::from("message"),value_ref.into()); // use into to wrap the value to the key - // Create a new vector + // Create a new vector let mut vec = Vec::new(); vec.push(Parameter::new("message", CLType::String)); // Create an Entry Point Object @@ -297,7 +295,7 @@ pub extern "C" fn call() { // The contract is stored in the global state let (stored_contract_hash, _contract_version) = storage::new_contract( entry_points, // entry points metadata - Some(named_keys), // named keys + Some(named_keys), // named keys Some("Hello_world_package_name".to_string()), // package name Some("Hello_world_access_uref".to_string()) // access uref ); @@ -320,12 +318,13 @@ There are many tools available to send a deploy to a Casper network. The simples Be sure to go through the prerequisites from the [Installing Smart Contracts and Querying Global State](../../developers/cli/installing-contracts.md) documentation. Make sure that after doing this you have: + 1. A valid private key for your account. 2. Funded your account with 2000 CSPR on the Testnet, which you can use for testing your smart contract. Create the `keys` folder in the main folder of your project and make sure that the private key which you put into the folder is called `secret_key.pem`. -Compile the contract in the contract directory so you obtain the contracts `.wasm`: +Compile the contract in the contract directory so you obtain the contracts `.wasm`: ```bash cd cross-contract @@ -341,7 +340,7 @@ cd contract && cargo build --release --target wasm32-unknown-unknown wasm-strip contract/target/wasm32-unknown-unknown/release/contract.wasm 2>/dev/null | true ``` -With this step everything is in place to deploy the contract. +With this step everything is in place to deploy the contract. :::tip @@ -387,7 +386,7 @@ casper-client get-deploy \ --node-address http://136.243.187.84:7777 af42bc6dbc58f677d138eb968d897f965f1ed118a40980bc16efbcc2a0c71832 ``` -This should return a JSON output containing information such as header data, approvers and payments. You can also receive this information by using the `verbose` flag with the `put-deploy` subcommand. Take time to familiarize yourself with the structure of the output. +This should return a JSON output containing information such as header data, approvers and payments. You can also receive this information by using the `verbose` flag with the `put-deploy` subcommand. Take time to familiarize yourself with the structure of the output. We can use the supplied deploy hash, `af42bc6dbc58f677d138eb968d897f965f1ed118a40980bc16efbcc2a0c71832` to find this contract using a block explorer. When viewed through the explorer, the status of the Deploy should be marked as `Success`. @@ -405,11 +404,11 @@ In this tutorial we will be passing the contract hash, as an argument, into the Prepare the `call` entry point as described below: -```bash +```rust #[no_mangle] pub extern "C" fn call() { - + // Create the list of required runtime arguments for the given entry point. let mut vec = Vec::new(); vec.push(Parameter::new("new_message", CLType::String)); @@ -433,7 +432,7 @@ pub extern "C" fn call() { // The contract is stored in the global state let (stored_contract_hash, _contract_version) = storage::new_contract( entry_points, // entry points - Some(named_keys), // named keys + Some(named_keys), // named keys Some("contract2_package_name".to_string()), // package name Some("contract2_access_uref".to_string()) // access uref ); @@ -448,7 +447,7 @@ This would be the easiest implementation of the `call` entry point. There is onl Now that we have defined the metadata for the `call_contract_2` entry point, we must now define the entry point itself. This entry point will take the second contract hash as an argument and call the entry point `update_msg`. It will then pass a message to the second contract as a parameter, which will be stored in that contract’s context. -```bash +```rust #[no_mangle] pub extern "C" fn call_contract_2() { @@ -458,13 +457,13 @@ pub extern "C" fn call_contract_2() { .map(|hash| ContractHash::new(hash)) .unwrap(); - // Get the value of the message from the second parameter + // Get the value of the message from the second parameter let new_value: String = runtime::get_named_arg("new_message"); // Call the update_msg entry point on the other contract with the parameter values let _: () = runtime::call_contract( - contract_hash, - "update_msg", + contract_hash, + "update_msg", runtime_args! { "message" => new_value, }, @@ -475,7 +474,7 @@ pub extern "C" fn call_contract_2() { Your complete contract implementation should look as follows: -```bash +```rust #![no_std] #![no_main] @@ -487,7 +486,7 @@ compile_error!("target arch should be wasm32: compile with '--target wasm32-unkn // `no_std` environment. extern crate alloc; -// The elementary types +// The elementary types use alloc::string::String; use alloc::vec::Vec; use crate::alloc::string::ToString; @@ -517,8 +516,8 @@ pub extern "C" fn call_contract_2() { let new_value: String = runtime::get_named_arg("new_message"); let _: () = runtime::call_contract( - contract_hash, - "update_msg", + contract_hash, + "update_msg", runtime_args! { // key => value "message" => new_value, @@ -529,7 +528,7 @@ pub extern "C" fn call_contract_2() { #[no_mangle] pub extern "C" fn call() { - + // Create a new vector - this will be the signature of the entrypoint let mut vec = Vec::new(); vec.push(Parameter::new("new_message", CLType::String)); @@ -553,7 +552,7 @@ pub extern "C" fn call() { // The contract is stored in global state let (stored_contract_hash, _contract_version) = storage::new_contract( entry_points, // entry points - Some(named_keys), // named keys + Some(named_keys), // named keys Some("contract2_package_name".to_string()), // package name Some("contract2_access_uref".to_string()) // access uref ); @@ -573,8 +572,7 @@ cd contract && cargo build --release --target wasm32-unknown-unknown wasm-strip contract/target/wasm32-unknown-unknown/release/contract.wasm 2>/dev/null | true ``` -Create the `keys` subfolder and copy the keys from the `keys` subfolder in the first contract into this subfolder. -The call from the terminal will look as follows: +Create the `keys` subfolder and copy the keys from the `keys` subfolder in the first contract into this subfolder. The call from the terminal will look as follows: ```bash casper-client put-deploy \ @@ -593,6 +591,7 @@ You may have noticed that the contract.wasm is always output to the same filenam make prepare make build-contract ``` + ::: After the deploy we can check if it was successful and inspect the runtime arguments of the deployed entry points. @@ -634,7 +633,7 @@ In the `execution_results` JSON element we should see "Success". "Success": { "cost": "16580565260", "effect": { ... - + } } } @@ -733,9 +732,9 @@ If we check the account's named keys, we can see all of the account's deployed c

-As we have now managed to deploy two contracts, we can call the entry point of this contract, passing appropriate arguments to the function. +As we have now managed to deploy two contracts, we can call the entry point of this contract, passing appropriate arguments to the function. -The Uref of the message variable is stored under the Named Keys in the contract. +The Uref of the message variable is stored under the Named Keys in the contract. ```bash casper-client query-global-state \ @@ -796,7 +795,7 @@ This is a simple `hello world` string. After invoking the entry point using the :::info -`--session-hash` - is the contract hash, which is returned from the put-deploy. +`--session-hash` - is the contract hash, which is returned from the put-deploy. `--session-arg` "hello world_contract:Key= ..." - the hash of the contract which we want to call from within the contract identified by the session-hash. @@ -1102,5 +1101,6 @@ With this we have succeeded in cross-contract communication between two contract ## Summary {#summary} In this tutorial, we: -- Developed two Rust contracts on a Casper network, where one smart contract is calling an entry point of the second smart contract -- Called an entry point on one contract from the other contract, passing a value as an argument to this entry point. + +- Developed two Rust contracts on a Casper network, where one smart contract is calling an entry point of the second smart contract +- Called an entry point on one contract from the other contract, passing a value as an argument to this entry point. diff --git a/source/docs/casper/resources/beginner/counter-testnet/walkthrough.md b/source/docs/casper/resources/beginner/counter-testnet/walkthrough.md index 7b84eadf41..f5f1c9ef99 100644 --- a/source/docs/casper/resources/beginner/counter-testnet/walkthrough.md +++ b/source/docs/casper/resources/beginner/counter-testnet/walkthrough.md @@ -12,21 +12,21 @@ git clone https://github.com/casper-ecosystem/counter If you explore the source code, you will see that there are two versions of the counter contract and one file with session code that calls the contract's entry-points: -- `contract-v1` +- `contract-v1` - - This is the first version of the counter contract. - - Defines two named keys: _counter_ to reference the contract and an associated variable _count_ to store a value. - - Provides a function to get the current count (_count_get_). - - Provides a function to increment the current count (_counter_inc_). - -- `contract-v2` + - This is the first version of the counter contract. + - Defines two named keys: _counter_ to reference the contract and an associated variable _count_ to store a value. + - Provides a function to get the current count (_count_get_). + - Provides a function to increment the current count (_counter_inc_). - - This is a second version of the counter contract, which will not be used in this tutorial. - - This version provides an additional function to decrement the counter and to demonstrate contract upgrades in another tutorial. +- `contract-v2` -- `counter-call` + - This is a second version of the counter contract, which will not be used in this tutorial. + - This version provides an additional function to decrement the counter and to demonstrate contract upgrades in another tutorial. - - This is session code that retrieves the _contract-v1_ contract, gets the current count value, increments it, and ensures the count was incremented by 1. +- `counter-call` + +- This is session code that retrieves the _contract-v1_ contract, gets the current count value, increments it, and ensures the count was incremented by 1. ## View the Network State {#view-the-network-state} @@ -54,6 +54,23 @@ casper-client get-state-root-hash --node-address http://[NODE_IP]:7777 You need to use the IP address of one of the [connected peers](https://testnet.cspr.live/tools/peers) on the Testnet as the node server since the network is running in a decentralized fashion. Make a note of the returned state root hash, but keep in mind that this hash value will need to be updated every time you modify the network state. +**Please be mindful of the node address format when using the `casper-client get-state-root-hash` command.** + +While browsing the [connected peers](https://testnet.cspr.live/tools/peers) list, you might encounter entries similar to `44.222.236.237:35000`. These entries only provide the IP address and port used for peer-to-peer communication within the network. + +**For the `casper-client get-state-root-hash` command, you need to modify the address slightly:** + +1. **Add the `http://` prefix:** This indicates that you're communicating with the node using the HTTP protocol. +2. **Replace the port:** While the peers list might show a different port (e.g., `35000`), the Casper node uses port `7777` for state queries. + +Following these steps, the correct command format for your example address would be: + +```bash +casper-client get-state-root-hash --node-address http://44.222.236.237:7777 +``` + +Remember to apply this modification to any node address you use with the `get-state-root-hash` command. + Finally, query the actual state: ```bash @@ -200,14 +217,13 @@ casper-client put-deploy \ --chain-name casper-test \ --secret-key [PATH_TO_YOUR_KEY]/secret_key.pem \ --payment-amount [PAYMENT_AMOUNT_IN_MOTES] \ - --session-path ./counter/target/wasm32-unknown-unknown/release/counter-call.wasm + --session-path ./counter-call/target/wasm32-unknown-unknown/release/counter-call.wasm ``` ## View the Final Network State {#view-the-final-network-state} To make sure that the session code ran successfully, get the new state root hash and query the network. - ```bash casper-client get-state-root-hash --node-address http://[NODE_IP]:7777 ``` @@ -220,6 +236,6 @@ casper-client query-global-state --node-address http://[NODE_IP]:7777 \ --key [ACCOUNT_HASH] -q "counter/count" ``` -If all went according to plan, your count value should be 2 at this point. +If all went according to plan, your count value should be 2 at this point. Congratulations on building, installing, and using a smart contract on the Testnet! diff --git a/source/docs/casper/resources/beginner/counter/walkthrough.md b/source/docs/casper/resources/beginner/counter/walkthrough.md index 8bf299d973..4a2c02a0b7 100644 --- a/source/docs/casper/resources/beginner/counter/walkthrough.md +++ b/source/docs/casper/resources/beginner/counter/walkthrough.md @@ -10,23 +10,31 @@ First, you will need to clone [the counter contract repository](https://github.c git clone https://github.com/casper-ecosystem/counter ``` -If you explore the source code, you will see that there are two versions of the counter contract and one file with session code that calls the contract's entry-points: +If you explore the source code, you will see that there are three versions of the counter contract and one file with session code that calls the contract's entry-points: -- `contract-v1` +- **`contract-v1`** - - This is the first version of the counter contract. - - Defines two named keys: _counter_ to reference the contract and an associated variable _count_ to store a value. - - Provides a function to get the current count (_count_get_). - - Provides a function to increment the current count (_counter_inc_). - -- `contract-v2` + - This is the first version of the counter contract. + - It defines two named keys: + - `counter`: References the contract itself. + - `count`: Stores the current counter value. + - It provides functions for: + - `get_count`: Retrieves the current counter value. + - `counter_inc`: Increments the counter value by 1. - - This is a second version of the counter contract, which will not be used in this tutorial. - - This version provides an additional function to decrement the counter and to demonstrate contract upgrades in another tutorial. +- **`contract-v2`** (Not Used in This Tutorial) -- `counter-call` + - An extension of `contract-v1`. It demonstrates decrementing the counter and contract upgrades. - - This is session code that retrieves the _contract-v1_ contract, gets the current count value, increments it, and ensures the count was incremented by 1. +- **`contract-v3` ** (Not Used in This Tutorial) + + - This version showcases how to add new functionalities during smart contract upgrades. It extends `contract-v1` and `contract-v2` by introducing: + - A new named key: `last_updated_at` - Tracks the timestamp of the last counter update. + - A new entry point: `get_last_updated_at` - Retrieves the `last_updated_at` timestamp. + - It focuses on the process of adding new fields like `last_updated_at` to existing contracts. + +- **`counter-call`** + - Session code that retrieves the specific contract version (e.g., `contract-v1`), interacts with its functions (e.g., `get_count`, `counter_inc`), and verifies the expected behavior. ## Create a Local Network {#create-a-local-network} @@ -68,7 +76,7 @@ Get the state root hash: casper-client get-state-root-hash --node-address http://localhost:11101 ``` -You are using localhost as the node server since the network is running on our local machine. Make a note of the _state-root-hash_ that is returned, but keep in mind that this hash value will need to be updated every time you modify the network state. +You are using localhost as the node server since the network is running on our local machine. Make a note of the _state-root-hash_ that is returned, but keep in mind that this hash value will need to be updated every time you modify the network state. Finally, query the actual state: @@ -223,7 +231,6 @@ casper-client put-deploy \ To make sure that the session code ran successfully, get the new state root hash and query the network. - ```bash casper-client get-state-root-hash --node-address http://localhost:11101 ``` @@ -236,6 +243,6 @@ casper-client query-global-state --node-address http://localhost:11101 \ --key [ACCOUNT_HASH] -q "counter/count" ``` -If all went according to plan, your count value should be 2 at this point. +If all went according to plan, your count value should be 2 at this point. Congratulations on building, installing, and using a smart contract on your local network! diff --git a/source/docs/casper/resources/beginner/upgrade-contract.md b/source/docs/casper/resources/beginner/upgrade-contract.md index 38c34ed419..7690091736 100644 --- a/source/docs/casper/resources/beginner/upgrade-contract.md +++ b/source/docs/casper/resources/beginner/upgrade-contract.md @@ -17,9 +17,9 @@ Here is a video walkthrough of this tutorial. ## Prerequisites {#prerequisites} -- The [ContractPackageHash](https://docs.rs/casper-types/latest/casper_types/contracts/struct.ContractPackageHash.html) referencing the [ContractPackage](https://docs.rs/casper-types/latest/casper_types/struct.ContractPackage.html) where an unlocked contract is stored in global state. -- You should be familiar with [writing smart contracts](/writing-contracts), [on-chain contracts](../../developers/cli/sending-deploys.md), and [calling contracts](../../developers/cli/calling-contracts.md) on a Casper network. -- You have installed [A Counter on the Testnet](/counter-testnet/) that you will upgrade as part of this tutorial. +- The [ContractPackageHash](https://docs.rs/casper-types/latest/casper_types/contracts/struct.ContractPackageHash.html) referencing the [ContractPackage](https://docs.rs/casper-types/latest/casper_types/struct.ContractPackage.html) where an unlocked contract is stored in global state. +- You should be familiar with [writing smart contracts](/writing-contracts), [on-chain contracts](../../developers/cli/sending-deploys.md), and [calling contracts](../../developers/cli/calling-contracts.md) on a Casper network. +- You have installed [A Counter on the Testnet](/counter-testnet/) that you will upgrade as part of this tutorial. :::note @@ -29,12 +29,13 @@ Installing the first version of the contract (contract-v1.wasm) as shown in the If you explore [the code](https://github.com/casper-ecosystem/counter/), you will observe the different versions of the contract: -- `contract-v1` is the counter contract you can see in the [A Counter on the Testnet](/counter-testnet/) tutorial. -- `contract-v2` is the contract with the new `counter_decrement` entry point. +- `contract-v1` is the counter contract you can see in the [A Counter on the Testnet](/counter-testnet/) tutorial. +- `contract-v2` is the contract with the new `counter_decrement` entry point. +- `contract-v3` is the contract with the new `get_last_updated_at` entry point and `last_updated_at` named key. ## Contract Versioning Flow {#contract-versioning-flow} -The following is an example workflow for creating a versioned contract package. Your workflow may differ if you have already created the contract package and have a handle on its hash. +The following is an example workflow for creating a versioned contract package. Your workflow may differ if you have already created the contract package and have a handle on its hash. 1. Create a contract in the most common way, using [new_contract](https://docs.rs/casper-contract/latest/casper_contract/contract_api/storage/fn.new_contract.html). 2. Add a new version of the contract using [add_contract_version](https://docs.rs/casper-contract/latest/casper_contract/contract_api/storage/fn.add_contract_version.html). @@ -81,21 +82,21 @@ There are many changes you could make to a Casper contract, like adding new entr To add a new contract version in the package, invoke the [add_contract_version](https://docs.rs/casper-contract/latest/casper_contract/contract_api/storage/fn.add_contract_version.html) function and pass in the [ContractPackageHash](https://docs.rs/casper-types/latest/casper_types/contracts/struct.ContractPackageHash.html), [EntryPoints](https://docs.rs/casper-types/latest/casper_types/contracts/struct.EntryPoints.html), and [NamedKeys](https://docs.rs/casper-types/latest/casper_types/contracts/type.NamedKeys.html). In the counter example, you will find the `add_contract_version` call [here](https://github.com/casper-ecosystem/counter/blob/57e3912735f93e1d0f667b936675964ecfdc6594/contract-v2/src/main.rs#L164). ```rust - let (contract_hash, contract_version) = - storage::add_contract_version(contract_package_hash, - entry_points, + let (contract_hash, contract_version) = + storage::add_contract_version(contract_package_hash, + entry_points, named_keys); ``` Explanation of arguments: -- `contract_package_hash` - This hash directs you to the contract package. See [Hash and Key Explanations](../../concepts/hash-types.md#hash-and-key-explanations). -- `entry_points` - Entry points of the contract, which can be modified or newly added. -- `named_keys` - Named key pairs of the contract. +- `contract_package_hash` - This hash directs you to the contract package. See [Hash and Key Explanations](../../concepts/hash-types.md#hash-and-key-explanations). +- `entry_points` - Entry points of the contract, which can be modified or newly added. +- `named_keys` - Named key pairs of the contract. The new contract version carries on named keys from the previous version. If you specify a new set of named keys, they will be combined with the old named keys in the new contract version. If the old and new contract versions use the same named keys, then the new values would be present in the new version of the contract. -You will need to manage contract versioning, considering clients that may use older versions. Here are a few options: +You will need to manage contract versioning, considering clients that may use older versions. Here are a few options: 1. Pin your client contract to the contract hash of a specific version. 2. Use [call_versioned_contract](https://docs.rs/casper-contract/latest/casper_contract/contract_api/runtime/fn.call_versioned_contract.html) with a version number to pin your client contract to that version. @@ -132,7 +133,7 @@ casper-client put-deploy \ --session-path [PATH]/contract-v2/target/wasm32-unknown-unknown/release/counter-v2.wasm ``` -### Step 5. Verify your changes +### Step 5. Verify your changes You can write unit tests to verify the behavior of the new contract version with [call_contract](https://docs.rs/casper-contract/latest/casper_contract/contract_api/runtime/fn.call_contract.html) or [call_versioned_contract](https://docs.rs/casper-contract/latest/casper_contract/contract_api/runtime/fn.call_versioned_contract.html). When you add a new contract to the package (which increments the highest enabled version), you will obtain a new contract hash, the primary identifier of the contract. You can use the contract hash with call_contract. Alternatively, you can use call_versioned_contract and specify the contract_package_hash and the newly added version. @@ -238,7 +239,6 @@ casper-client query-global-state \ - Check the version and package details with the latest state root hash: ```bash @@ -247,6 +247,7 @@ casper-client query-global-state \ --state-root-hash [STATE_ROOT_HASH] \ --key [ACCOUNT_HASH] -q "version" ``` +
Example output @@ -277,6 +278,7 @@ casper-client query-global-state \ --state-root-hash [STATE_ROOT_HASH] \ --key [ACCOUNT_HASH] -q "counter_package_name" ``` +
Example output @@ -315,7 +317,7 @@ casper-client query-global-state \
-Call the new entry point, _counter_decrement_, using the package name and check the results. +Call the new entry point, _counter_decrement_, using the package name and check the results. ```bash casper-client put-deploy \ @@ -330,6 +332,7 @@ casper-client put-deploy \ :::note There are two ways to call versioned contracts: + 1. [Calling Contracts by Package Hash](/developers/writing-onchain-code/calling-contracts/#StoredVersionedContractByHash) 2. [Calling Contracts by Package Name](/developers/writing-onchain-code/calling-contracts/#StoredVersionedContractByName) @@ -337,7 +340,6 @@ There are two ways to call versioned contracts: After calling the entry point, the count value should be decremented. You can verify it by querying the network again using the new state root hash. - ## Disabling and Enabling Contract Versions You can disable a contract version within a contract package by using the [disable_contract_version](https://docs.rs/casper-contract/latest/casper_contract/contract_api/storage/fn.disable_contract_version.html) function. @@ -345,6 +347,7 @@ You can disable a contract version within a contract package by using the [disab Disabled contract versions can no longer be executed. As such, if there is only a single contract version within the package, you will no longer be able to use the contract. + [Enable_contract_version](https://docs.rs/casper-contract/latest/casper_contract/contract_api/storage/fn.enable_contract_version.html) allows you to re-enable a previously disabled contract version. ::note @@ -359,8 +362,8 @@ You can create a locked contract package with the [new_locked_contract](https:// ```rust let (stored_contract_hash, _) = storage::new_locked_contract( - contract_entry_points, - Some(contract_named_keys), + contract_entry_points, + Some(contract_named_keys), Some("contract_package_name".to_string()), Some("contract_access_uref".to_string()), ); @@ -373,3 +376,24 @@ Apply the contract entry points and named keys when you call the function. You c Creating a locked contract package is an irreversible decision. To upgrade a contract, use [new_contract](https://docs.rs/casper-contract/latest/casper_contract/contract_api/storage/fn.new_contract.html) as Step 1 explains. ::: + +## Adding New Fields During Upgrades + +`contract-v3` demonstrates adding new data storage to your contract. It introduces a new field for the last update timestamp. + +**Key Steps:** + +1. **Define a Named Key:** A key (`LAST_UPDATED_KEY`) references the new field. + +2. **Initialize the Field:** A URef is created using `storage::new_uref` to point to the storage location. It's then added to `NamedKeys` along with the key. + +**Code Breakdown:** + +```rust +// Create NamedKeys and initialize the new field (last_updated) with default value (0). +let mut named_keys = NamedKeys::new(); +let last_updated = storage::new_uref(0_u64); +named_keys.insert(String::from(LAST_UPDATED_KEY), last_updated.into()); +``` + +For a deeper dive into the implementation details, explore the `contract-v3` code itself. This hands-on exploration will further solidify your understanding of adding new fields during contract upgrades. diff --git a/source/docs/casper/resources/casper-open-source-software.md b/source/docs/casper/resources/casper-open-source-software.md index c12ac235f7..97ad65a69b 100644 --- a/source/docs/casper/resources/casper-open-source-software.md +++ b/source/docs/casper/resources/casper-open-source-software.md @@ -37,7 +37,7 @@ Name | Description | Author | Language | License | Last Update Date | Type [Casper Swift SDK](https://github.com/hienbui9999/CasperSDKInSwift) | Casper Client SDK. Casper SDK methods implementation in Swift. | hienbui9999 | Swift | MIT license | 2022-06-08 | Client SDK [Casper Two-Party MultiSig Contract](https://github.com/casper-ecosystem/two-party-multi-sig) | This example demonstrates how to configure an account on a Casper network to require two-party multi-signature deploys. | Casper Labs | Rust | NA | 2022-04-26 | Example contracts [Casper World](https://github.com/NodesGuru/casper-world) | Casper network status and decentralization map web application | Nodes Guru | TypeScript | MIT license | 2022-01-26 | Blockchain Explorer -[CasperDash Wallet](https://github.com/CasperDash/casperdash-client) | A non-custodial wallet for the Casper blockchain | CasperDash | JavaScript | MIT license | 2022-09-14 | Wallet +[CasperDash Wallet](https://github.com/CasperDash/casperdash-extension) | A non-custodial wallet for the Casper blockchain | CasperDash | JavaScript | MIT license | 2022-09-14 | Wallet [CasperFYRE API](https://github.com/ledgerleapllc/casperfyre-frontend) | Dispensory API interface for Casper Mainnet | LedgerLeap | JavaScript-PHP | Apache-2.0 license | 2022-09-06 | Tools [CasperHolders](https://github.com/casperholders/casperholdersfront) | First 3rd party UI to interact with Casper Blockchain | CasperHolders | JavaScript | Apache-2.0 license | 2022-08-23 | Blockchain Explorer [CasperSign](https://github.com/chronologic/caspersign-validator-ui) | The First Casper-Native Dapp. CasperSign Allows Users to Sign Contracts Confidentially & Securely on the Casper Blockchain | ChronoLogic and Digital Strategies | TypeScript | NA | 2022-08-31 | dApp @@ -49,7 +49,7 @@ Name | Description | Author | Language | License | Last Update Date | Type [DAO Contracts](https://github.com/make-software/dao-contracts) | Smart Contracts for the MVPR On-Chain Governance System on Casper | MAKE Software | Rust | Apache-2.0 license | 2022-07-17 | DAO [DHF PAY](https://github.com/DHFinance/dhf-pay-front) | The crypto currency payment gateway on the CSPR blockchain | DHFinance | TypeScript | Apache-2.0 license | 2022-08-28 | Payments [DLN DAO](https://github.com/dlndao/start/) | DLN DAO | AlphaFin | TypeScript | MIT license | 2022-09-10 | DAO -[DotOracle](https://github.com/dotoracle/bridge-ui) | Realtime decentralized Oracle and Cross-chain liquidity network for EVM, non-EVM Casper, and L2 blockchains. | DotOracle Network | TypeScript | NA | 2022-09-26 | Bridge +[DotOracle](https://github.com/paradiso-io/bridge-ui) | Realtime decentralized Oracle and Cross-chain liquidity network for EVM, non-EVM Casper, and L2 blockchains. | DotOracle Network | TypeScript | NA | 2022-09-26 | Bridge [Dragon’s Lair Style Staking](https://github.com/Rengo-Labs/CasperLabs-Dragonlair) | Lair Style Staking | Rengo Labs | Rust | Apache-2.0 license | 2022-06-24 | Staking [Subscription Billing](https://github.com/Rengo-Labs/CasperLabs-EIP1337) | ERC-1337 subscription billing | Rengo Labs | Rust | MIT license | 2022-04-07 | Tokens [Casper Fungible Token](https://github.com/casper-ecosystem/cep18) | Implementation of Fungible Tokens for Casper networks | Casper Labs | Rust | Apache-2.0 license | 2022-09-01 | Tokens diff --git a/source/docs/casper/resources/condor-for-exchanges.md b/source/docs/casper/resources/condor-for-exchanges.md new file mode 100644 index 0000000000..e72fc3ca47 --- /dev/null +++ b/source/docs/casper/resources/condor-for-exchanges.md @@ -0,0 +1,107 @@ +# Condor Release Notes for Exchanges + + +## Account/Contract Merge + +* Currently, Casper contains separate Accounts and Contracts. These record types are similar, but contain small differences. Condor merges these two into one record called AddressableEntity. + + * All existing Account and Contract records will be migrated upon on-chain interaction (i.e., sending of transactions, native transfers). + + * All new “accounts” and “contracts” created on the system will result in an AddressableEntity record being created. + + * PublicKeys and AccountHashes for existing Account records remain in place and continue to function with the corresponding AddressableEntity record. + +* Named keys are now a top-level concern and stored directly in global state. + + * The outcome and behavior of named keys is the same; this is an implementation detail addressing the scalability issues of the previous design. + + * Similarly, entry points for smart contracts are now a top level concern, with each entry point being stored directly in global state rather than embedded within an AddressableEntity record.. + +* **Action Items: While the Casper node software handles all on-chain interactions with these new data structures, any off-chain logic that retrieves Account and/or Contract records from the blockchain for any purpose (i.e., processing, storage, indexing, etc) will need to be modified to retrieve and use the AddressableEntity record structure going forward.** + +# Fee Elimination + +* Condor adds support for configurable fee, refund, and pricing strategies. The current plan is to roll out Condor with “NoFee” mode on. Rather than transferring tokens from a paying purse, they are now placed on hold temporarily. + +* There is a configurable interval that determines how long a balance hold remains in effect. The available balance of a purse equals its actual total balance minus all non-expired balance holds on that purse. The held portion of a purse balance is not available to transfer or spend until it is released. + + * The on-chain logic calculates the correct values for total balance and available balance. Off-chain logic can continue to use the existing query_balance endpoint, which will return the available balance. This is sufficient for the majority of use cases. However, off-chain logic that wants to get the full details including total, available, and all hold records can use the new query_balance_details RPC endpoint. + +* **Action Items: Overall, placing holds rather than taking fees is beneficial to exchanges and other parties who send periodic transactions to the network, as their gas costs return to them over time rather than being spent.** + + * **Existing implementations should generally not need to change anything to take advantage of this behavior of the system.** + + * **Any advanced platform with automated funding that periodically tops off operating balances with new tokens to replace spent gas would benefit from some consideration of this new behavior.** + + * **Advanced platforms seeking optimal scheduling strategies would benefit from retrieving the hold records for their operating purse(s) to calculate projected future available balances and use that to inform the scheduling of automated transaction submissions.** + +## Dynamic Pricing + +* Currently, the gas price on the Casper network is equal to 1, meaning 1 unit of gas costs 1 mote. Condor introduces a configurable gas price multiplier. If turned on, at the end of each era a calculation is run to determine block usage in the current era and adjust the multiplier for the era that is starting. + + * If overall block use rises above a threshold the gas price goes up by 1, if use falls below a threshold the gas price goes down by 1. If use remains within those thresholds the gas price remains the same. + + * The gas price will not go up or down by more than 1 in a given era, and will not go above the maximum or below the minimum threshold. + + * The minimum and maximum gas prices and the go-up and go-down threshold are configurable. + + * The current gas price is used as a straight multiplier to determine actual gas cost. For instance, an operation with a base cost of 1 CSPR would cost 1 CSPR if the current gas price is 1, but would cost 2 CSPR if the current gas price is 2. + + * The calculated gas price has been added to the block header to make it easily discoverable (for determining what the current price is), and for posterity (for determining what the gas price was for a given era in the historical context). + +* **Action Items: During times of high network usage, you may find that costs for interacting with the blockchain increase. Plan accordingly for any transactions.** + + * **As a quality of life feature for those operating on a strict budget, transactions have a gas_tolerance field, which allows the sender of a transaction to specify the maximum gas price they are willing to pay for (minimum 1). For instance, if a transaction is sent with gas_tolerance = 2 and the network is currently at gas price 3 or higher, that transaction will not be included in a proposed block. If the calculated gas price later walks down to 2 before the transaction has expired, the transaction will be eligible for inclusion in a proposed block.** + +## Transaction Types + +* Currently, work to be done on the Casper network is sent using the Deploy structure. With Condor we are transitioning to a Transaction model. There are some structural changes introduced to support more advanced features. + +* The existing Deploy model is deprecated as of Condor, and support will be removed entirely in a future major release. However, Condor will continue to accept valid Deploys and will attempt to execute them. Most existing deploys that function today will continue to do so. However, deploys that depend on a data type or FFI function that has been altered or removed will fail to execute. + +* Under the new Transaction model, Condor offers direct support for native / Wasm-less usage of all user-land mint and stake management actions. + +* **Action Items: Existing off-chain systems should determine if their operation continues to work using the legacy Deploy model support.** + + * **In cases where legacy integration remains compatible, upgrading to take advantage of the new Transaction model can be delayed temporarily or indefinitely until the removal of Deploys with a later release.** + + * **In cases where one or more incompatibilities have been introduced, some fix short of a full upgrade to the Transaction model may be possible on a case by case basis, but a forced upgrade may be preferable or even necessary in some cases.** + + * **Even off-chain systems that continue to work using legacy support may want to consider upgrading to the new Transaction model to take advantage of efficiencies or new capabilities.** + +## Block Restructure + +* The structure of the Block record is being modified as part of Condor. As all blocks are immutable once added to the chain, previously produced blocks remain in their original format. All new blocks produced after Condor will have the new format. The change in structure can be seen [here in the upcoming documentation changes](https://github.com/casper-network/docs/blob/feat-2.0_docs/source/docs/casper/developers/json-rpc/types_chain.md#blockv2-blockv2). + +* **Action Items: While existing client software (including SDKs) remain able to request and parse historical blocks that use the original Block structure, they must be upgraded to request and parse new blocks if they wish to continue to follow the chain. This is the primary breaking change for most off-chain consumers of the Casper network.** + + * **To continue to service historical/archival usage of old blocks, such software should not code over or remove handling for the original block structure. Instead they should retain that capability and add handling for the new block structure.** + + +## Contract Level Events + +* Condor adds support for smart contracts to define message topics and emit their own messages which are passed to the event stream for consumption as contract level events. Details on this feature can be found [here](https://github.com/casper-network/ceps/blob/master/text/0088-contract-level-messages.md). + +* **Action Items: As this is an entirely new feature, existing systems do not have to change anything.** + + * **Some existing smart contracts have adopted a convention using one or more dictionaries to approximate contract level events. Such smart contracts cannot directly address spoofing, and repudiation protection requires off-chain support. Thus, they should consider making the necessary changes to their logic to take advantage of the built in and safe support offered in Condor.** + +## Zug Consensus Protocol + +* The Zug Consensus Protocol will replace Highway on the Casper network alongside the Condor release. Other instances of a Casper network (private/hybrid networks) may choose to use either Highway or Zug. + + * Information on Zug’s implementation can be found [here](https://github.com/casper-network/docs/blob/feat-2.0_docs/source/docs/casper/concepts/design/zug.md). + + * A more in-depth view of Zug and the theory behind it can be found [here](https://arxiv.org/abs/2205.06314). + +* **Action Items: None.** + +## Server-Sent Event (SSE) Endpoint Changes + +* Due to the previously mentioned structural changes to certain record kinds, most notably the Block record structure and the transition from the Deploy model to the Transaction model, and the addition of contract level events in the form of Messages, there are breaking changes to the contents of the event stream. + + * The changes are minor schematic changes and rather obvious; for instance instead of a DeployProcessed event there is a TransactionProcessed event, instead of a DeployExpired event there is a TransactionExpired event, and so on. + + * The overall verbs and their behavioral semantics remain the same (BlockAdded, ~Accepted, ~Processed, ~Expired, etc). + +* **Action Items: Existing software (including SDKs) that deserializes the JSON produced by the SSE event stream will require updating to continue to follow the event stream post-Condor. Software that does not follow the event stream is unaffected.** diff --git a/source/docs/casper/resources/quick-start.md b/source/docs/casper/resources/quick-start.md index 5941fc55e4..2976a3d6e6 100644 --- a/source/docs/casper/resources/quick-start.md +++ b/source/docs/casper/resources/quick-start.md @@ -7,7 +7,7 @@ Here is a list of commands for developers who already meet the prerequisites and ## Prerequisites 1. You have installed [Rust](https://www.rust-lang.org/tools/install). Verify the installation with this command: `rustup --version`. Restart the shell if needed. -2. You have installed [cmake](https://cmake.org/install/). Verify the installation with this command: `cmake --version`. +2. You have installed [cmake](https://cmake.org/resources/). Verify the installation with this command: `cmake --version`. - On Ubuntu, you can follow [this guide](https://cgold.readthedocs.io/en/latest/first-step/installation.html). - On MacOS, use this command: `brew install cmake`. 3. You have an integrated development environment (IDE). On Windows, you will need to download the C++ build developer tools, without which you cannot install `cargo-casper`. diff --git a/source/docs/casper/resources/tokens/cep78/introduction.md b/source/docs/casper/resources/tokens/cep78/introduction.md index 2fda07b83d..9f0a2e15c5 100644 --- a/source/docs/casper/resources/tokens/cep78/introduction.md +++ b/source/docs/casper/resources/tokens/cep78/introduction.md @@ -16,6 +16,8 @@ The pre-built Wasm for the contract and all other utility session code can be fo The `call` method will install the contract with the necessary entrypoints and call the `init()` entrypoint, which allows the contract to self-initialize and set up the necessary state variables for operation. +The [Full Installation Tutorial](./using-casper-client/full-installation-tutorial.md) provides a step-by-step workflow. + ### Required Runtime Arguments The following are the required runtime arguments that must be passed to the installer session code to correctly install the NFT contract. For more information on the modalities that these arguments set, please refer to the [Modalities](./modalities.md) documentation. @@ -46,7 +48,7 @@ The following are the optional parameters that can be passed in at the time of i #### Example deploy -The following is an example of installing the NFT contract via a deploy using the Rust CLI Casper client. You can find more examples [here](./using-casper-client.md). +The following is an example of installing the NFT contract via a deploy using the Rust CLI Casper client. You can find more examples [here](./using-casper-client/full-installation-tutorial.md). ```bash casper-client put-deploy -n http://65.108.0.148:7777/rpc --chain-name "casper-test" --payment-amount 500000000000 -k keys/secret_key.pem --session-path contract/target/wasm32-unknown-unknown/release/contract.wasm \ @@ -80,16 +82,16 @@ folder within the project folder. ### Checking Token Ownership -[Learn to check token ownership](https://github.com/casper-ecosystem/cep-78-enhanced-nft/blob/dev/tutorials/token-ownership-tutorial.md) starting with version [v1.1.1](https://github.com/casper-ecosystem/cep-78-enhanced-nft/releases/tag/v1.1.1). The `OwnerReverseLookupMode` modality must be set to `Complete` as described [here](./reverse-lookup.md). +[Learn to check token ownership](https://github.com/casper-ecosystem/cep-78-enhanced-nft/blob/dev/docs/tutorials/token-ownership-tutorial.md) starting with version [v1.1.1](https://github.com/casper-ecosystem/cep-78-enhanced-nft/releases/tag/v1.1.1). The `OwnerReverseLookupMode` modality must be set to `Complete` as described [here](./reverse-lookup.md). ### Upgrading to Version 1.1.1 -Upgrade to v1.1.1 using a [Standard NamedKey Convention](https://github.com/casper-ecosystem/cep-78-enhanced-nft/blob/dev/tutorials/standard-migration-tutorial.md) or a [Custom NamedKey Convention](https://github.com/casper-ecosystem/cep-78-enhanced-nft/blob/dev/tutorials/custom-migration-tutorial.md). +Upgrade to v1.1.1 using a [Standard NamedKey Convention](https://github.com/casper-ecosystem/cep-78-enhanced-nft/blob/dev/tutorials/standard-migration-tutorial.md) or a [Custom NamedKey Convention](https://github.com/casper-ecosystem/cep-78-enhanced-nft/blob/dev/docs/tutorials/custom-migration-tutorial.md). ## Installing and Interacting with the Contract using the Rust Casper Client -You can find instructions on installing an instance of the CEP-78 contract using the Rust CLI Casper client [here](./using-casper-client.md). +You can find instructions on installing an instance of the CEP-78 contract using the Rust CLI Casper client [here](./using-casper-client/full-installation-tutorial.md). ## Test Suite and Specification diff --git a/source/docs/casper/resources/tokens/cep78/reverse-lookup.md b/source/docs/casper/resources/tokens/cep78/reverse-lookup.md index 86a6026f9e..5d13bbe45f 100644 --- a/source/docs/casper/resources/tokens/cep78/reverse-lookup.md +++ b/source/docs/casper/resources/tokens/cep78/reverse-lookup.md @@ -6,7 +6,7 @@ slug: /resources/tokens/cep78/reverse-lookup # Owner Reverse Lookup Functionality -In version 1.0 of the CEP-78 Enhanced NFT Standard contract, tracking minted tokens consisted of a single, unbounded list that would grow in size with each additional token. As a result, gas costs would increase over time as the list must be overwritten with each new minting. The related tutorial can be found [here](https://github.com/casper-ecosystem/cep-78-enhanced-nft/blob/dev/tutorials/token-ownership-tutorial.md). +In version 1.0 of the CEP-78 Enhanced NFT Standard contract, tracking minted tokens consisted of a single, unbounded list that would grow in size with each additional token. As a result, gas costs would increase over time as the list must be overwritten with each new minting. The related tutorial can be found [here](https://github.com/casper-ecosystem/cep-78-enhanced-nft/blob/dev/docs/tutorials/token-ownership-tutorial.md). In an effort to stabilize the gas costs of larger NFT collections, version 1.1 of CEP-78 includes the use of a pre-allocated page system to track ownership of NFTs within the contract. diff --git a/source/docs/casper/resources/tokens/cep78/using-casper-client.md b/source/docs/casper/resources/tokens/cep78/using-casper-client.md deleted file mode 100644 index 97a975dd78..0000000000 --- a/source/docs/casper/resources/tokens/cep78/using-casper-client.md +++ /dev/null @@ -1,231 +0,0 @@ ---- -title: On-chain Installation -slug: /resources/tokens/using-casper-client ---- - - -# Installing and Interacting with a CEP-78 Contract using the Rust Casper Client - -This documentation will guide you through the process of installing and interacting with an instance of the CEP-78 enhanced NFT standard contract through Casper's Rust CLI client. The contract code installs an instance of CEP-78 as per session arguments provided at the time of installation. It requires a minimum Rust version of `1.63.0`. - -Information on the modalities used throughout this installation process can be found in the [modalities documentation](modalities.md). - -## Installing the Contract - -Installing the enhanced NFT contract to global state requires the use of a [Deploy](/developers/cli/sending-deploys/). In this case, the session code can be compiled to Wasm by running the `make build-contract` command provided in the Makefile at the top level. The Wasm will be found in the `contract/target/wasm32-unknown-unknown/release` directory as `contract.wasm`. - -Below is an example of a `casper-client` command that provides all required session arguments to install a valid instance of the CEP-78 contract on global state. - -- `casper-client put-deploy -n http://localhost:11101/rpc --chain-name "casper-net-1" --payment-amount 500000000000 -k ~/casper/casper-node/utils/nctl/assets/net-1/nodes/node-1/keys/secret_key.pem --session-path ~/casper/enhanced-nft/contract/target/wasm32-unknown-unknown/release/contract.wasm` - -1. `--session-arg "collection_name:string='CEP-78-collection'"` - - The name of the NFT collection as a string. In this instance, "CEP-78-collection". - -2. `--session-arg "collection_symbol:string='CEP78'"` - - The symbol representing the NFT collection as a string. In this instance, "CEP78". - -3. `--session-arg "total_token_supply:u64='100'"` - - The total supply of tokens to be minted. In this instance, 100. If the contract owner is unsure of the total number of NFTs they will require, they should err on the side of caution. - -4. `--session-arg "ownership_mode:u8='2'"` - - The ownership mode for this contract. In this instance the 2 represents "Transferable" mode. Under these conditions, users can freely transfer their NFTs between one another. - -5. `--session-arg "nft_kind:u8='1'"` - - The type of commodity represented by these NFTs. In this instance, the 1 represents a digital collection. - -6. `--session-arg "nft_metadata_kind:u8='0'"` - - The type of metadata used by this contract. In this instance, the 0 represents CEP-78 standard for metadata. - -7. `--session-arg "json_schema:string=''"` - - An empty JSON string, as the contract has awareness of the CEP-78 JSON schema. Using the custom validated modality would require passing through a valid JSON schema for your custom metadata. - -8. `--session-arg "identifier_mode:u8='0'"` - - The mode used to identify individual NFTs. For 0, this means an ordinal identification sequence rather than by hash. - -9. `--session-arg "metadata_mutability:u8='0'"` - - A setting allowing for mutability of metadata. This is only available when using the ordinal identification mode, as the hash mode depends on immutability for identification. In this instance, despite ordinal identification, the 0 represents immutable metadata. - -The session arguments match the available modalities as listed [here](./modalities.md). - -
-Casper client command without comments - -```bash -casper-client put-deploy -n http://localhost:11101/rpc --chain-name "casper-net-1" --payment-amount 500000000000 -k ~/casper/casper-node/utils/nctl/assets/net-1/nodes/node-1/keys/secret_key.pem --session-path ~/casper/enhanced-nft/contract/target/wasm32-unknown-unknown/release/contract.wasm \ ---session-arg "collection_name:string='CEP-78-collection'" \ ---session-arg "collection_symbol:string='CEP78'" \ ---session-arg "total_token_supply:u64='100'" \ ---session-arg "ownership_mode:u8='2'" \ ---session-arg "nft_kind:u8='1'" \ ---session-arg "nft_metadata_kind:u8='0'" \ ---session-arg "json_schema:string=''" \ ---session-arg "identifier_mode:u8='0'" \ ---session-arg "metadata_mutability:u8='0'" -``` - -
- -## Directly Invoking Entrypoints - -With the release of CEP-78 version 1.1, users that are interacting with a CEP-78 contract that does not use `ReverseLookupMode` should opt out of using the client Wasms provided as part of the release. Opting out in this situation is recommended, as directly invoking the entrypoints incurs a lower gas cost compared against using the provided client Wasm to invoke the entrypoint. - -You may invoke the `mint`, `transfer` or `burn` entrypoints directly through either the contract package hash or the contract hash directly. - -Specifically in the case of `mint`, there are fewer runtime arguments that must be provided, thereby reducing the total gas cost of minting an NFT. - -
-Example Mint using StoredVersionByHash - -```bash - -casper-client put-deploy -n http://localhost:11101/rpc --chain-name "casper-net-1" \ --payment-amount 7500000000 \ -k ~/secret_key.pem \ ---session-package-hash hash-b3b7a74ae9ef2ea8afc06d6a0830961259605e417e95a53c0cb1ca9737bb0ec7 \ ---session-entry-point "mint" \ ---session-arg "token_owner:key='account-hash-e9ff87766a1d2bab2565bfd5799054946200b51b20c3ca7e54a9269e00fe7cfb'" \ ---session-arg "token_meta_data:string='{\"name\": \"John Doe\",\"token_uri\": \"https:\/\/www.barfoo.com\",\"checksum\": \"940bffb3f2bba35f84313aa26da09ece3ad47045c6a1292c2bbd2df4ab1a55fb\"}'" - -``` - -
- -
-Example Transfer using StoredContractByHash - -Based on the identifier mode for the given contract instance, either the `token_id` runtime argument must be passed in or in the case of the hash identifier mode, the `token_hash` runtime argument. - -```bash - -casper-client put-deploy -n http://localhost:11101/rpc --chain-name "casper-net-1" \ --payment-amount 7500000000 \ -k ~/secret_key.pem \ ---session-hash hash-b3b7a74ae9ef2ea8afc06d6a0830961259605e417e95a53c0cb1ca9737bb0ec7 \ ---session-entry-point "transfer" \ ---session-arg "source_key:key='account-hash-e9ff87766a1d2bab2565bfd5799054946200b51b20c3ca7e54a9269e00fe7cfb'" \ ---session-arg "target_key:key='account-hash-b4782e7c47e4deca5bd90b7adb2d6e884f2d331825d5419d6cbfb59e17642aab'" \ ---session-arg "token_id:u64='0'" - -``` - -
- -## Minting an NFT - -Below is an example of a `casper-client` command that uses the `mint` function of the contract to mint an NFT for the user associated with `node-1` in an [NCTL environment](/developers/dapps/nctl-test/). - -- `casper-client put-deploy -n http://localhost:11101/rpc --chain-name "casper-net-1" --payment-amount 5000000000 -k ~/casper/casper-node/utils/nctl/assets/net-1/nodes/node-1/keys/secret_key.pem --session-path ~/casper/enhanced-nft/client/mint_session/target/wasm32-unknown-unknown/release/mint_call.wasm` - -1. `--session-arg "nft_contract_hash:key='hash-206339c3deb8e6146974125bb271eb510795be6f250c21b1bd4b698956669f95'"` - - The contract hash of the previously installed CEP-78 NFT contract from which we will be minting. - -2. `--session-arg "collection_name:string='cep78_'"` - - The collection name of the previously installed CEP-78 NFT contract from which we will be minting. - -3. `--session-arg "token_owner:key='account-hash-e9ff87766a1d2bab2565bfd5799054946200b51b20c3ca7e54a9269e00fe7cfb'"` - - The collection name of the NFT to be minted. - -4. `--session-arg "token_meta_data:string='{\"name\": \"John Doe\",\"token_uri\": \"https:\/\/www.barfoo.com\",\"checksum\": \"940bffb3f2bba35f84313aa26da09ece3ad47045c6a1292c2bbd2df4ab1a55fb\"}'"` - - Metadata describing the NFT to be minted, passed in as a `string`. - -
-Casper client command without comments - -```bash - -casper-client put-deploy -n http://localhost:11101/rpc --chain-name "casper-net-1" \ ---payment-amount 5000000000 \ --k ~/casper/casper-node/utils/nctl/assets/net-1/nodes/node-1/keys/secret_key.pem \ ---session-path ~/casper/enhanced-nft/client/mint_session/target/wasm32-unknown-unknown/release/mint_call.wasm \ ---session-arg "nft_contract_hash:key='hash-206339c3deb8e6146974125bb271eb510795be6f250c21b1bd4b698956669f95'" \ ---session-arg "collection_name:string='cep78_'"` \ ---session-arg "token_owner:key='account-hash-e9ff87766a1d2bab2565bfd5799054946200b51b20c3ca7e54a9269e00fe7cfb'" \ ---session-arg "token_meta_data:string='{\"name\": \"John Doe\",\"token_uri\": \"https:\/\/www.barfoo.com\",\"checksum\": \"940bffb3f2bba35f84313aa26da09ece3ad47045c6a1292c2bbd2df4ab1a55fb\"}'" - -``` - -
- -## Transferring NFTs Between Users - -Below is an example of a `casper-client` command that uses the `transfer` function to transfer ownership of an NFT from one user to another. In this case, we are transferring the previously minted NFT from the user associated with `node-2` to the user associated with `node-3`. - -- `casper-client put-deploy -n http://localhost:11101/rpc --chain-name "casper-net-1" --payment-amount 5000000000 -k ~/casper/casper-node/utils/nctl/assets/net-1/nodes/node-2/keys/secret_key.pem --session-path ~/casper/enhanced-nft/client/transfer_session/target/wasm32-unknown-unknown/release/transfer_call.wasm` - -1. `--session-arg "nft_contract_hash:key='hash-52e78ae3f6c485d036a74f65ebbb8c75fcc7c33fb42eb667fb32aeba72c63fb5'"` - - The contract hash of the CEP-78 NFT Contract associated with the NFT to be transferred. - -2. `--session-arg "source_key:key='account-hash-e9ff87766a1d2bab2565bfd5799054946200b51b20c3ca7e54a9269e00fe7cfb'"` - - The account hash of the user that currently owns the NFT and wishes to transfer it. - -3. `--session-arg "target_key:key='account-hash-b4772e7c47e4deca5bd90b7adb2d6e884f2d331825d5419d6cbfb59e17642aab'"` - - The account hash of the user that will receive the NFT. - -4. `--session-arg "is_hash_identifier_mode:bool='false'"` - - Argument that the hash identifier mode is ordinal, thereby requiring a `token_id` rather than a `token_hash`. - -5. `--session-arg "token_id:u64='0'"` - - The `token_id` of the NFT to be transferred. - -
-Casper client command without comments - -```bash -casper-client put-deploy -n http://localhost:11101/rpc --chain-name "casper-net-1" \ ---payment-amount 5000000000 \ --k ~/casper/casper-node/utils/nctl/assets/net-1/nodes/node-2/keys/secret_key.pem \ ---session-path ~/casper/enhanced-nft/client/transfer_session/target/wasm32-unknown-unknown/release/transfer_call.wasm \ ---session-arg "nft_contract_hash:key='hash-52e78ae3f6c485d036a74f65ebbb8c75fcc7c33fb42eb667fb32aeba72c63fb5'" \ ---session-arg "source_key:key='account-hash-e9ff87766a1d2bab2565bfd5799054946200b51b20c3ca7e54a9269e00fe7cfb'" \ ---session-arg "target_key:key='account-hash-b4772e7c47e4deca5bd90b7adb2d6e884f2d331825d5419d6cbfb59e17642aab'" \ ---session-arg "is_hash_identifier_mode:bool='false'" \ ---session-arg "token_id:u64='0'" -``` - -
- -## Burning an NFT - -Below is an example of a `casper-client` command that uses the `burn` function to burn an NFT within a CEP-78 collection. If this command is used, the NFT in question will no longer be accessible by anyone. - -- `casper-client put-deploy -n http://localhost:11101/rpc --chain-name "casper-net-1" --payment-amount 5000000000 -k ~/casper/casper-node/utils/nctl/assets/net-1/nodes/node-1/keys/secret_key.pem` - -1. `--session-hash hash-52e78ae3f6c485d036a74f65ebbb8c75fcc7c33fb42eb667fb32aeba72c63fb5` - - The session hash corresponding to the NFT's contract hash. - -2. `--session-entry-point "burn"` - - The entrypoint corresponding to the `burn` function. - -3. `--session-arg "token_id:u64='1'"` - - The token ID for the NFT to be burned. If the `identifier_mode` is not set to `Ordinal`, you must provide the `token_hash` instead. - -
-Casper client command without comments - -```bash -casper-client put-deploy -n http://localhost:11101/rpc --chain-name "casper-net-1" \ ---payment-amount 5000000000 \ --k ~/casper/casper-node/utils/nctl/assets/net-1/nodes/node-1/keys/secret_key.pem \ ---session-hash hash-52e78ae3f6c485d036a74f65ebbb8c75fcc7c33fb42eb667fb32aeba72c63fb5 \ ---session-entry-point "burn" \ ---session-arg "token_id:u64='1'" -``` - -
\ No newline at end of file diff --git a/source/docs/casper/resources/tokens/cep78/using-casper-client/full-installation-tutorial.md b/source/docs/casper/resources/tokens/cep78/using-casper-client/full-installation-tutorial.md new file mode 100644 index 0000000000..f5c20cd988 --- /dev/null +++ b/source/docs/casper/resources/tokens/cep78/using-casper-client/full-installation-tutorial.md @@ -0,0 +1,1519 @@ +--- +title: Installation Workflow +--- + +# Installing an NFT Contract using the Rust Casper Client + +This documentation will guide you through installing and interacting with an instance of the CEP-78 enhanced NFT standard contract through Casper's Rust CLI client. The contract code installs an instance of CEP-78 given the session arguments provided. It requires a minimum Rust version of `1.63.0`. The code for this tutorial is available in [GitHub](https://github.com/casper-ecosystem/cep-78-enhanced-nft/). A portion of this tutorial reviews the [contract](https://github.com/casper-ecosystem/cep-78-enhanced-nft/tree/dev/contract). + +Information on the modalities used throughout this installation process can be found in the [modalities documentation](../modalities.md). + +## Table of Contents + +1. [Environment Setup](#environment-setup) + - [Prerequisites](#prerequisites) + - [Building the Contract and Tests](#building-the-contract-and-tests) +2. [Reviewing the Contract Implementation](#reviewing-the-contract-implementation) + - [Included Crates and Modules](#included-crates-and-modules) + - [Initialization Flow](#initialization-flow) + - [Contract Entrypoints](#contract-entrypoints) +3. [Installing the Contract](#installing-the-contract) + - [Querying Global State](#querying-global-state) + - [Sending the Installation Deploy](#sending-the-installation-deploy) + - [Verifying the Installation](#verifying-the-installation) +4. [Next Steps](#next-steps) + +## Environment Setup + +### Prerequisites + +Before using this guide, ensure you meet the following requirements: + +- Set up the [development prerequisites](../../../../developers/prerequisites.md), including the [Casper client](../../../../developers/prerequisites.md#install-casper-client) +- Get a valid [node address](../../../../developers/prerequisites.md#acquire-node-address-from-network-peers) from the network +- Know how to install a [smart contract](../../../../developers/cli/sending-deploys.md) on a Casper network +- Hold enough CSPR tokens to pay for transactions + +The [Writing Rust Contracts on Casper](../../../../developers/writing-onchain-code/simple-contract.md) document outlines many aspects of this tutorial and should be read as a prerequisite. + +### Building the Contract and Tests + +First, clone the contract from GitHub: + +```bash +git clone https://github.com/casper-ecosystem/cep-78-enhanced-nft/ && cd cep-78-enhanced-nft +``` + +Prepare your environment with the following command: + +```bash +make prepare +``` + +If your environment is set up correctly, you will see this output: + +```bash +rustup target add wasm32-unknown-unknown +info: component 'rust-std' for target 'wasm32-unknown-unknown' is up to date +``` + +If you do not see this message, check the [Getting Started Guide](../../../../developers/writing-onchain-code/getting-started.md). + +The contract code can be compiled to Wasm by running the `make build-contract` command provided in the Makefile at the top level. The Wasm will be found in the `contract/target/wasm32-unknown-unknown/release` directory as `contract.wasm`. + +You can also compile your contract and run the contract unit tests with this command: + +```bash +make test +``` + +## Reviewing the Contract Implementation + +In this repository, you will find a library and an [example NFT implementation](https://github.com/casper-ecosystem/cep-78-enhanced-nft/tree/dev/contract) for Casper networks. This section explains the example contract in more detail. + +There are four steps to follow when you intend to create your implementation of the NFT contract, as follows: + +1. Fork the code from the example repository listed above. +2. Perform any necessary customization changes on your fork of the example contract. +3. Compile the customized code to Wasm. +4. Send the customized Wasm as a deploy to a Casper network. + +### Included Crates and Modules + +The contract implementation starts by importing the following essential Casper crates: + +- [casper_contract](https://docs.rs/casper-contract/latest/casper_contract/index.html) - A Rust library for writing smart contracts on Casper networks +- [casper_types](https://docs.rs/casper-types/latest/casper_types/) - Types used to allow the creation of Wasm contracts and tests for use on Casper networks + +The contract code defines additional modules in the `contract/src` folder: + +- `constants` - Constant values required to run the contract code +- `error` - Errors related to the NFT contract +- `events` - A library for contract-emitted events +- `metadata` - A module handling the contract's metadata and corresponding dictionary +- `modalities` - Common expectations around contract usage and behavior +- `utils` - Utility and helper functions to run the contract code + +### Initialization Flow + +Initializing the contract happens through the `call() -> install_contract() -> init()` functions inside the [main.rs](https://github.com/casper-ecosystem/cep-78-enhanced-nft/blob/dev/contract/src/main.rs) contract file. The `init()` function reads the runtime arguments and defines parameters such as `collection_name`, `collection_symbol`, and `total_token_supply`, among the other required and optional arguments described [here](../introduction.md#required-runtime-arguments). + +### Contract Entrypoints + +This section briefly explains the essential entrypoints used in the Casper NFT contract. To see their full implementation, refer to the [main.rs](https://github.com/casper-ecosystem/cep-78-enhanced-nft/blob/dev/contract/src/main.rs) contract file. For further questions, contact the Casper support team via the [Discord channel](https://discord.com/invite/casperblockchain). + +- [**approve**](https://github.com/casper-ecosystem/cep-78-enhanced-nft/blob/440bff44277ab5fd295f37229fe92278339d3753/contract/src/main.rs#L1002) - Allows a spender to transfer up to an amount of the owners’s tokens +- [**balance_of**](https://github.com/casper-ecosystem/cep-78-enhanced-nft/blob/440bff44277ab5fd295f37229fe92278339d3753/contract/src/main.rs#L1616) - Returns the token balance of the owner +- [**burn**](https://github.com/casper-ecosystem/cep-78-enhanced-nft/blob/440bff44277ab5fd295f37229fe92278339d3753/contract/src/main.rs#L874) - Burns tokens, reducing the total supply +- [**get_approved**](https://github.com/casper-ecosystem/cep-78-enhanced-nft/blob/440bff44277ab5fd295f37229fe92278339d3753/contract/src/main.rs#L1728) - Returns the hash of the approved account for a specified token identifier +- [**init**](https://github.com/casper-ecosystem/cep-78-enhanced-nft/blob/440bff44277ab5fd295f37229fe92278339d3753/contract/src/main.rs#L81) - Sets the collection name, symbol, and total token supply; initializes the allow minting setting, minting mode, ownership mode, NFT kind, holder mode, whitelist mode and contract whitelist, JSON schema, receipt name, identifier mode, and burn mode. This entrypoint can only be called once when the contract is installed on the network +- [**is_approved_for_all**](https://github.com/casper-ecosystem/cep-78-enhanced-nft/blob/440bff44277ab5fd295f37229fe92278339d3753/contract/src/main.rs#L1328) - Returns yes if an account is approved as an operator for a token owner +- [**metadata**](https://github.com/casper-ecosystem/cep-78-enhanced-nft/blob/440bff44277ab5fd295f37229fe92278339d3753/contract/src/main.rs#L1675) - Returns the metadata associated with a token identifier +- [**mint**](https://github.com/casper-ecosystem/cep-78-enhanced-nft/blob/440bff44277ab5fd295f37229fe92278339d3753/contract/src/main.rs#L619) - Mints additional tokens if minting is allowed, increasing the total supply +- [**owner_of**](https://github.com/casper-ecosystem/cep-78-enhanced-nft/blob/440bff44277ab5fd295f37229fe92278339d3753/contract/src/main.rs#L1636) - Returns the owner for a specified token identifier +- [**register_owner**](https://github.com/casper-ecosystem/cep-78-enhanced-nft/blob/440bff44277ab5fd295f37229fe92278339d3753/contract/src/main.rs#L2159) - Register an owner for a specified token identifier. Works when the *OwnerReverseLookupMode* is set to *Complete* +- [**revoke**](https://github.com/casper-ecosystem/cep-78-enhanced-nft/blob/440bff44277ab5fd295f37229fe92278339d3753/contract/src/main.rs#L1138) - Revokes an account that was approved for an identified token transfer. The *OwnershipMode* must be set to *Transferable* +- [**set_approval_for_all**](https://github.com/casper-ecosystem/cep-78-enhanced-nft/blob/440bff44277ab5fd295f37229fe92278339d3753/contract/src/main.rs#L1254) - Allows a spender to transfer all of the owner's tokens +- [**set_token_metadata**](https://github.com/casper-ecosystem/cep-78-enhanced-nft/blob/440bff44277ab5fd295f37229fe92278339d3753/contract/src/main.rs#L1773) - Sets the metadata associated with a token identifier +- [**set_variables**](https://github.com/casper-ecosystem/cep-78-enhanced-nft/blob/440bff44277ab5fd295f37229fe92278339d3753/contract/src/main.rs#L496) - Allows the user to set any combination of variables simultaneously, defining which variables are mutable or immutable +- [**transfer**](https://github.com/casper-ecosystem/cep-78-enhanced-nft/blob/440bff44277ab5fd295f37229fe92278339d3753/contract/src/main.rs#L1359) - Transfers tokens from the token owner to a specified account. The transfer will succeed if the caller is the token owner or an approved operator. The *OwnershipMode* must be set to *Transferable* +- [**updated_receipts**](https://github.com/casper-ecosystem/cep-78-enhanced-nft/blob/440bff44277ab5fd295f37229fe92278339d3753/contract/src/main.rs#L2111) - Allows an owner of one or more NFTs held by the contract instance to attain up to date receipt information for the NFTs they currently own. Works when the *OwnerReverseLookupMode* is set to *Complete* + +There is also the [**migrate**](https://github.com/casper-ecosystem/cep-78-enhanced-nft/blob/440bff44277ab5fd295f37229fe92278339d3753/contract/src/main.rs#L1975) entrypoint, which was needed only for migrating a 1.0 version of the NFT contract to version 1.1. + +:::important + +The following entrypoints return data using `runtime::ret`, which is useful mainly if the entrypoint caller is a contract: + +- `mint` (with *OwnerReverseLookupMode* set to *Complete*) +- `transfer` (with *OwnerReverseLookupMode* set to *TransfersOnly*) +- `balance_of` +- `is_approved_for_all` +- `owner_of` +- `metadata` + +::: + +## Installing the Contract + +Installing the enhanced NFT contract to global state requires using a [Deploy](../../../../developers/cli/sending-deploys.md). But before proceeding with the installation, verify the network state and the status of the account that will send the installation deploy. + +### Querying Global State + +This step queries information about the network state given the latest state root hash. You will also need the [IP address](../../../../developers/prerequisites.md#acquire-node-address-from-network-peers) from a Testnet peer node. + +```bash +casper-client get-state-root-hash --node-address http://localhost:11101/rpc/ +``` + +### Querying the Account State + +Run the following command and supply the path to your public key in hexadecimal format to get the account hash if you don't have it already. + +```bash +casper-client account-address --public-key [PATH_TO_PUBLIC_KEY_HEX] +``` + +Use the command below to query the state of your account. + +```bash +casper-client query-global-state --node-address http:// \ +--state-root-hash [STATE_ROOT_HASH] \ +--key [ACCOUNT_HASH] +``` + +
+Expand for a sample query and response + +```bash +casper-client query-global-state --node-address http://localhost:11101/rpc/ \ +--state-root-hash 376b18e95312328f212f9966200fa40734e66118cbd34ace0a1ec14eacaea6e6 \ +--key account-hash-82729ae3b368bb2c45d23c05c872c446cbcf32b694f1d9efd3d1ea46cf227a11 +``` + +```json +{ + "jsonrpc": "2.0", + "id": -6733022256306802125, + "result": { + "api_version": "1.5.6", + "block_header": null, + "stored_value": { + "Account": { + "account_hash": "account-hash-e70dbca48c2d31bc2d754e51860ceaa8a1a49dc627b20320b0ecee1b6d9ce655", + "named_keys": [], + "main_purse": "uref-11e6fc5354f61a004df98482376c45964b8b1557e8f2f13fb5f3adab5faa8be1-007", + "associated_keys": [ + { + "account_hash": "account-hash-e70dbca48c2d31bc2d754e51860ceaa8a1a49dc627b20320b0ecee1b6d9ce655", + "weight": 1 + } + ], + "action_thresholds": { + "deployment": 1, + "key_management": 1 + } + } + }, + "merkle_proof": "[32706 hex chars]" + } +} +``` + +
+ + +### Sending the Installation Deploy + +Below is an example of a `casper-client` command that provides all required session arguments to install a valid instance of the CEP-78 contract on global state. + +Use the Testnet to understand the exact gas amount required for installation. Refer to the [note about gas prices](../../../../developers/cli/sending-deploys.md#a-note-about-gas-price) to understand payment amounts and gas price adjustments. + +- `casper-client put-deploy -n http://localhost:11101/rpc/ --chain-name "casper-net-1" --payment-amount 500000000000 -k ~/casper/casper-node/utils/nctl/assets/net-1/nodes/node-2/keys/secret_key.pem --session-path contract/target/wasm32-unknown-unknown/release/contract.wasm` + +1. `--session-arg "collection_name:string='CEP-78-collection'"` + + The name of the NFT collection as a string. In this instance, "CEP-78-collection". + +2. `--session-arg "collection_symbol:string='CEP78'"` + + The symbol representing the NFT collection as a string. In this instance, "CEP78". + +3. `--session-arg "total_token_supply:u64='100'"` + + The total supply of tokens to be minted. In this instance, 100. If the contract owner is unsure of the total number of NFTs they will require, they should err on the side of caution. + +4. `--session-arg "ownership_mode:u8='2'"` + + The ownership mode for this contract. In this instance, the 2 represents "Transferable" mode. Under these conditions, users can freely transfer their NFTs between one another. + +5. `--session-arg "nft_kind:u8='1'"` + + The type of commodity represented by these NFTs. In this instance, the 1 represents a digital collection. + +6. `--session-arg "nft_metadata_kind:u8='0'"` + + The type of metadata used by this contract. In this instance, the 0 represents CEP-78 standard for metadata. + +7. `--session-arg "json_schema:string=''"` + + An empty JSON string, as the contract has awareness of the CEP-78 JSON schema. Using the custom-validated modality would require passing through a valid JSON schema for your custom metadata. + +8. `--session-arg "identifier_mode:u8='0'"` + + The mode used to identify individual NFTs. For 0, this means an ordinal identification sequence rather than by hash. + +9. `--session-arg "metadata_mutability:u8='0'"` + + A setting allowing for mutability of metadata. This is only available when using the ordinal identification mode, as the hash mode depends on immutability for identification. In this instance, despite ordinal identification, the 0 represents immutable metadata. + +The session arguments match the available [modalities](../modalities.md). + + +
+Expand for a sample query and response + +```bash +casper-client put-deploy --node-address http://localhost:11101/rpc/ \ +--chain-name "casper-net-1" \ +--payment-amount 500000000000 \ +--secret-key ~/casper/casper-node/utils/nctl/assets/net-1/nodes/node-1/keys/secret_key.pem \ +--session-path contract/target/wasm32-unknown-unknown/release/contract.wasm \ +--session-arg "collection_name:string='CEP-78-collection'" \ +--session-arg "collection_symbol:string='CEP78'" \ +--session-arg "total_token_supply:u64='100'" \ +--session-arg "ownership_mode:u8='2'" \ +--session-arg "nft_kind:u8='1'" \ +--session-arg "nft_metadata_kind:u8='0'" \ +--session-arg "json_schema:string='nft-schema'" \ +--session-arg "identifier_mode:u8='0'" \ +--session-arg "metadata_mutability:u8='0'" +``` + +This command will output the `deploy_hash`, which can be used in the next step to verify the installation. + +```bash +{ + "jsonrpc": "2.0", + "id": 3104428017957320684, + "result": { + "api_version": "1.0.0", + "deploy_hash": "2b084bdccbaaae2b9c6e4de2f5a6cdf06c72f0d02eaeb7d681a29ebdbe3c92b7" + } +} +``` + +
+ + +### Verifying the Installation + +Verify the sent deploy using the `get-deploy` command. + +```bash +casper-client get-deploy --node-address http://localhost:11101/rpc/ [DEPLOY_HASH] +``` + +
+Expand for sample deploy details + +```json +{ + "jsonrpc": "2.0", + "id": -7282936875867676694, + "result": { + "api_version": "1.5.6", + "deploy": { + "hash": "1d1f66b26eb648b5f15bc958a552036e8521b508706056817b0d41c71f6d7afe", + "header": { + "account": "0154d828baafa6858b92919c4d78f26747430dcbecb9aa03e8b44077dc6266cabf", + "timestamp": "2024-02-29T18:28:16.104Z", + "ttl": "30m", + "gas_price": 1, + "body_hash": "90866126c3dbb9a27f672307102bf651663934ee34715d46f9f02caa70226743", + "dependencies": [], + "chain_name": "casper-test" + }, + "payment": { + "ModuleBytes": { + "module_bytes": "", + "args": [ + [ + "amount", + { + "cl_type": "U512", + "bytes": "050088526a74", + "parsed": "500000000000" + } + ] + ] + } + }, + "session": { + "ModuleBytes": { + "module_bytes": "[621680 hex chars]", + "args": [ + [ + "collection_name", + { + "cl_type": "String", + "bytes": "120000004345502d37382d636f6c6c656374696f6e32", + "parsed": "CEP-78-collection" + } + ], + [ + "collection_symbol", + { + "cl_type": "String", + "bytes": "050000004345503738", + "parsed": "CEP78" + } + ], + [ + "total_token_supply", + { + "cl_type": "U64", + "bytes": "6400000000000000", + "parsed": 100 + } + ], + [ + "ownership_mode", + { + "cl_type": "U8", + "bytes": "02", + "parsed": 2 + } + ], + [ + "nft_kind", + { + "cl_type": "U8", + "bytes": "01", + "parsed": 1 + } + ], + [ + "nft_metadata_kind", + { + "cl_type": "U8", + "bytes": "00", + "parsed": 0 + } + ], + [ + "json_schema", + { + "cl_type": "String", + "bytes": "0a0000006e66742d736368656d61", + "parsed": "nft-schema" + } + ], + [ + "identifier_mode", + { + "cl_type": "U8", + "bytes": "00", + "parsed": 0 + } + ], + [ + "metadata_mutability", + { + "cl_type": "U8", + "bytes": "00", + "parsed": 0 + } + ] + ] + } + }, + "approvals": [ + { + "signer": "0154d828baafa6858b92919c4d78f26747430dcbecb9aa03e8b44077dc6266cabf", + "signature": "01f866dd88fd179fd214262d0451a92be2673e6d4095eb79beef9e5b8bbbc18862e76c3085dcb1b1ae669a185cb80d94c5084325913b8118338645952bb5ee2200" + } + ] + }, + "execution_results": [ + { + "block_hash": "dca9ff6e9ad7baeead715504dee098069f30dbb9975730be3d3926ab1c58f332", + "result": { + "Success": { + "effect": { + "operations": [], + "transforms": [ + { + "key": "account-hash-6174cf2e6f8fed1715c9a3bace9c50bfe572eecb763b0ed3f644532616452008", + "transform": "Identity" + }, + { + "key": "hash-8cf5e4acf51f54eb59291599187838dc3bc234089c46fc6ca8ad17e762ae4401", + "transform": "Identity" + }, + { + "key": "hash-8cf5e4acf51f54eb59291599187838dc3bc234089c46fc6ca8ad17e762ae4401", + "transform": "Identity" + }, + { + "key": "hash-624dbe2395b9d9503fbee82162f1714ebff6b639f96d2084d26d944c354ec4c5", + "transform": "Identity" + }, + { + "key": "hash-8cf5e4acf51f54eb59291599187838dc3bc234089c46fc6ca8ad17e762ae4401", + "transform": "Identity" + }, + { + "key": "hash-010c3fe81b7b862e50c77ef9a958a05bfa98444f26f96f23d37a13c96244cfb7", + "transform": "Identity" + }, + { + "key": "hash-9824d60dc3a5c44a20b9fd260a412437933835b52fc683d8ae36e4ec2114843e", + "transform": "Identity" + }, + { + "key": "hash-010c3fe81b7b862e50c77ef9a958a05bfa98444f26f96f23d37a13c96244cfb7", + "transform": "Identity" + }, + { + "key": "balance-11e6fc5354f61a004df98482376c45964b8b1557e8f2f13fb5f3adab5faa8be1", + "transform": "Identity" + }, + { + "key": "balance-98d945f5324f865243b7c02c0417ab6eac361c5c56602fd42ced834a1ba201b6", + "transform": "Identity" + }, + { + "key": "balance-11e6fc5354f61a004df98482376c45964b8b1557e8f2f13fb5f3adab5faa8be1", + "transform": { + "WriteCLValue": { + "cl_type": "U512", + "bytes": "05c2d627778f", + "parsed": "616179422914" + } + } + }, + { + "key": "balance-98d945f5324f865243b7c02c0417ab6eac361c5c56602fd42ced834a1ba201b6", + "transform": { + "AddUInt512": "500000000000" + } + }, + { + "key": "uref-e42cd3ae8b4bd60306a72f0f4e9faa4e114e2e2cce5db03bfdd109a8db888e14-000", + "transform": { + "WriteCLValue": { + "cl_type": "Unit", + "bytes": "", + "parsed": null + } + } + }, + { + "key": "hash-2b61207cd0e94ce1b1d40801b0abb1ab55fd7dae94c9dcf670292243f3791a30", + "transform": "WriteContractPackage" + }, + { + "key": "account-hash-e70dbca48c2d31bc2d754e51860ceaa8a1a49dc627b20320b0ecee1b6d9ce655", + "transform": { + "AddKeys": [ + { + "name": "cep78_contract_package_CEP-78-collection", + "key": "hash-2b61207cd0e94ce1b1d40801b0abb1ab55fd7dae94c9dcf670292243f3791a30" + } + ] + } + }, + { + "key": "account-hash-e70dbca48c2d31bc2d754e51860ceaa8a1a49dc627b20320b0ecee1b6d9ce655", + "transform": { + "AddKeys": [ + { + "name": "cep78_contract_package_access_CEP-78-collection", + "key": "uref-e42cd3ae8b4bd60306a72f0f4e9faa4e114e2e2cce5db03bfdd109a8db888e14-007" + } + ] + } + }, + { + "key": "hash-2b61207cd0e94ce1b1d40801b0abb1ab55fd7dae94c9dcf670292243f3791a30", + "transform": "Identity" + }, + { + "key": "hash-845d3d08e29642afba35704bcb6e38f3c40f1469763bff7a88674c9a5be3f01b", + "transform": "WriteContractWasm" + }, + { + "key": "hash-378a43e38bc5129d8aa3bcd04f5c9a97be73f85b5be574182ac1346f04520796", + "transform": "WriteContract" + }, + { + "key": "hash-2b61207cd0e94ce1b1d40801b0abb1ab55fd7dae94c9dcf670292243f3791a30", + "transform": "WriteContractPackage" + }, + { + "key": "account-hash-e70dbca48c2d31bc2d754e51860ceaa8a1a49dc627b20320b0ecee1b6d9ce655", + "transform": { + "AddKeys": [ + { + "name": "cep78_contract_hash_CEP-78-collection", + "key": "hash-378a43e38bc5129d8aa3bcd04f5c9a97be73f85b5be574182ac1346f04520796" + } + ] + } + }, + { + "key": "uref-0545c60c0a55e4d8a10fe0c3b2d356150b082e2243b6795b34f67643e4ca13d0-000", + "transform": { + "WriteCLValue": { + "cl_type": "U32", + "bytes": "01000000", + "parsed": 1 + } + } + }, + { + "key": "account-hash-e70dbca48c2d31bc2d754e51860ceaa8a1a49dc627b20320b0ecee1b6d9ce655", + "transform": { + "AddKeys": [ + { + "name": "cep78_contract_version_CEP-78-collection", + "key": "uref-0545c60c0a55e4d8a10fe0c3b2d356150b082e2243b6795b34f67643e4ca13d0-007" + } + ] + } + }, + { + "key": "hash-378a43e38bc5129d8aa3bcd04f5c9a97be73f85b5be574182ac1346f04520796", + "transform": "Identity" + }, + { + "key": "hash-2b61207cd0e94ce1b1d40801b0abb1ab55fd7dae94c9dcf670292243f3791a30", + "transform": "Identity" + }, + { + "key": "hash-845d3d08e29642afba35704bcb6e38f3c40f1469763bff7a88674c9a5be3f01b", + "transform": "Identity" + }, + { + "key": "uref-5aed76a73089e7e32f6fbf5d9a9597843215d4810cd5822c0f5c6e65a0bbb7a3-000", + "transform": { + "WriteCLValue": { + "cl_type": "String", + "bytes": "120000004345502d37382d636f6c6c656374696f6e32", + "parsed": "CEP-78-collection" + } + } + }, + { + "key": "hash-378a43e38bc5129d8aa3bcd04f5c9a97be73f85b5be574182ac1346f04520796", + "transform": { + "AddKeys": [ + { + "name": "collection_name", + "key": "uref-5aed76a73089e7e32f6fbf5d9a9597843215d4810cd5822c0f5c6e65a0bbb7a3-007" + } + ] + } + }, + { + "key": "uref-ba4247cc0354644474758d1292924c5115c61c8012cae3f094a91060d9dff779-000", + "transform": { + "WriteCLValue": { + "cl_type": "String", + "bytes": "050000004345503738", + "parsed": "CEP78" + } + } + }, + { + "key": "hash-378a43e38bc5129d8aa3bcd04f5c9a97be73f85b5be574182ac1346f04520796", + "transform": { + "AddKeys": [ + { + "name": "collection_symbol", + "key": "uref-ba4247cc0354644474758d1292924c5115c61c8012cae3f094a91060d9dff779-007" + } + ] + } + }, + { + "key": "uref-e5f06deadcbfe5a469e7c162346580744746bfdc0ec67002e0ecba5b11096827-000", + "transform": { + "WriteCLValue": { + "cl_type": "U64", + "bytes": "6400000000000000", + "parsed": 100 + } + } + }, + { + "key": "hash-378a43e38bc5129d8aa3bcd04f5c9a97be73f85b5be574182ac1346f04520796", + "transform": { + "AddKeys": [ + { + "name": "total_token_supply", + "key": "uref-e5f06deadcbfe5a469e7c162346580744746bfdc0ec67002e0ecba5b11096827-007" + } + ] + } + }, + { + "key": "uref-89711af74265427dc65d7c5a421cedde82de69d192cad36f34efa36504108572-000", + "transform": { + "WriteCLValue": { + "cl_type": "U8", + "bytes": "02", + "parsed": 2 + } + } + }, + { + "key": "hash-378a43e38bc5129d8aa3bcd04f5c9a97be73f85b5be574182ac1346f04520796", + "transform": { + "AddKeys": [ + { + "name": "ownership_mode", + "key": "uref-89711af74265427dc65d7c5a421cedde82de69d192cad36f34efa36504108572-007" + } + ] + } + }, + { + "key": "uref-e02c29a6120d5da7f14fb664ca60c3ade56a3171a670c292d0a4ea0f9ae4f0c8-000", + "transform": { + "WriteCLValue": { + "cl_type": "U8", + "bytes": "01", + "parsed": 1 + } + } + }, + { + "key": "hash-378a43e38bc5129d8aa3bcd04f5c9a97be73f85b5be574182ac1346f04520796", + "transform": { + "AddKeys": [ + { + "name": "nft_kind", + "key": "uref-e02c29a6120d5da7f14fb664ca60c3ade56a3171a670c292d0a4ea0f9ae4f0c8-007" + } + ] + } + }, + { + "key": "uref-772103052d4559fcc2f8f2c2568eb75214462d463009106938e6f20e1cc0a7c0-000", + "transform": { + "WriteCLValue": { + "cl_type": "String", + "bytes": "0a0000006e66742d736368656d61", + "parsed": "nft-schema" + } + } + }, + { + "key": "hash-378a43e38bc5129d8aa3bcd04f5c9a97be73f85b5be574182ac1346f04520796", + "transform": { + "AddKeys": [ + { + "name": "json_schema", + "key": "uref-772103052d4559fcc2f8f2c2568eb75214462d463009106938e6f20e1cc0a7c0-007" + } + ] + } + }, + { + "key": "uref-3b45a30c98d90de2c62812c6689aa2fac0cb4d08772fcfdee0584c5db2b1d12a-000", + "transform": { + "WriteCLValue": { + "cl_type": "U8", + "bytes": "00", + "parsed": 0 + } + } + }, + { + "key": "hash-378a43e38bc5129d8aa3bcd04f5c9a97be73f85b5be574182ac1346f04520796", + "transform": { + "AddKeys": [ + { + "name": "minting_mode", + "key": "uref-3b45a30c98d90de2c62812c6689aa2fac0cb4d08772fcfdee0584c5db2b1d12a-007" + } + ] + } + }, + { + "key": "uref-8443151d736bb3268815ad7848708d44ccc661799f969697c64b1cddb5ce89a7-000", + "transform": { + "WriteCLValue": { + "cl_type": "U8", + "bytes": "02", + "parsed": 2 + } + } + }, + { + "key": "hash-378a43e38bc5129d8aa3bcd04f5c9a97be73f85b5be574182ac1346f04520796", + "transform": { + "AddKeys": [ + { + "name": "holder_mode", + "key": "uref-8443151d736bb3268815ad7848708d44ccc661799f969697c64b1cddb5ce89a7-007" + } + ] + } + }, + { + "key": "uref-a77f2ac1f5e72c6b096ca414ae2c986a5387442ddf8e89a35b787a756adc4bb4-000", + "transform": { + "WriteCLValue": { + "cl_type": "U8", + "bytes": "00", + "parsed": 0 + } + } + }, + { + "key": "hash-378a43e38bc5129d8aa3bcd04f5c9a97be73f85b5be574182ac1346f04520796", + "transform": { + "AddKeys": [ + { + "name": "whitelist_mode", + "key": "uref-a77f2ac1f5e72c6b096ca414ae2c986a5387442ddf8e89a35b787a756adc4bb4-007" + } + ] + } + }, + { + "key": "uref-1ec63ea6442d9b4ef40d926280f8b72704b763d3ef7cdaccd9ecb04af5562d99-000", + "transform": { + "WriteCLValue": { + "cl_type": "String", + "bytes": "1800000063657037385f4345502d37382d636f6c6c656374696f6e32", + "parsed": "cep78_CEP-78-collection" + } + } + }, + { + "key": "hash-378a43e38bc5129d8aa3bcd04f5c9a97be73f85b5be574182ac1346f04520796", + "transform": { + "AddKeys": [ + { + "name": "receipt_name", + "key": "uref-1ec63ea6442d9b4ef40d926280f8b72704b763d3ef7cdaccd9ecb04af5562d99-007" + } + ] + } + }, + { + "key": "uref-ac99c07d666f45ff5c86a2c1bb6cc44b612ddd5d39a9de88045b441ff6e6b327-000", + "transform": { + "WriteCLValue": { + "cl_type": "String", + "bytes": "[170 hex chars]", + "parsed": "contract-package-2b61207cd0e94ce1b1d40801b0abb1ab55fd7dae94c9dcf670292243f3791a30" + } + } + }, + { + "key": "hash-378a43e38bc5129d8aa3bcd04f5c9a97be73f85b5be574182ac1346f04520796", + "transform": { + "AddKeys": [ + { + "name": "cep78_CEP-78-collection", + "key": "uref-ac99c07d666f45ff5c86a2c1bb6cc44b612ddd5d39a9de88045b441ff6e6b327-007" + } + ] + } + }, + { + "key": "uref-45e1bc671353ae58c41a703055959da243deefc7f4c3f121f3f9828d97475bda-000", + "transform": { + "WriteCLValue": { + "cl_type": "U8", + "bytes": "00", + "parsed": 0 + } + } + }, + { + "key": "hash-378a43e38bc5129d8aa3bcd04f5c9a97be73f85b5be574182ac1346f04520796", + "transform": { + "AddKeys": [ + { + "name": "nft_metadata_kind", + "key": "uref-45e1bc671353ae58c41a703055959da243deefc7f4c3f121f3f9828d97475bda-007" + } + ] + } + }, + { + "key": "uref-05c0eb8e7ef4caa6f228e8ee91874dc64926b95926d839b458fdce356063a817-000", + "transform": { + "WriteCLValue": { + "cl_type": { + "Map": { + "key": "U8", + "value": "U8" + } + }, + "bytes": "010000000000", + "parsed": [ + { + "key": 0, + "value": 0 + } + ] + } + } + }, + { + "key": "hash-378a43e38bc5129d8aa3bcd04f5c9a97be73f85b5be574182ac1346f04520796", + "transform": { + "AddKeys": [ + { + "name": "nft_metadata_kinds", + "key": "uref-05c0eb8e7ef4caa6f228e8ee91874dc64926b95926d839b458fdce356063a817-007" + } + ] + } + }, + { + "key": "uref-f53ea99b60ae6d046a6fb0d996475714ef03ed33b39674a8fe016c8324116baf-000", + "transform": { + "WriteCLValue": { + "cl_type": "U8", + "bytes": "00", + "parsed": 0 + } + } + }, + { + "key": "hash-378a43e38bc5129d8aa3bcd04f5c9a97be73f85b5be574182ac1346f04520796", + "transform": { + "AddKeys": [ + { + "name": "identifier_mode", + "key": "uref-f53ea99b60ae6d046a6fb0d996475714ef03ed33b39674a8fe016c8324116baf-007" + } + ] + } + }, + { + "key": "uref-2ca963a70a69df2db931b8761b4de13bd22e2fc54a415b0b57d4204c9b90dde9-000", + "transform": { + "WriteCLValue": { + "cl_type": "U8", + "bytes": "00", + "parsed": 0 + } + } + }, + { + "key": "hash-378a43e38bc5129d8aa3bcd04f5c9a97be73f85b5be574182ac1346f04520796", + "transform": { + "AddKeys": [ + { + "name": "metadata_mutability", + "key": "uref-2ca963a70a69df2db931b8761b4de13bd22e2fc54a415b0b57d4204c9b90dde9-007" + } + ] + } + }, + { + "key": "uref-eb1a7f69592881587805fde2d53e8e5b3dcbabd81311faa7b9d19ea731f83d9b-000", + "transform": { + "WriteCLValue": { + "cl_type": "U8", + "bytes": "00", + "parsed": 0 + } + } + }, + { + "key": "hash-378a43e38bc5129d8aa3bcd04f5c9a97be73f85b5be574182ac1346f04520796", + "transform": { + "AddKeys": [ + { + "name": "burn_mode", + "key": "uref-eb1a7f69592881587805fde2d53e8e5b3dcbabd81311faa7b9d19ea731f83d9b-007" + } + ] + } + }, + { + "key": "uref-f226eed9d0c5fcf58e6b481d45417721e35435c2ef5eb4d26d215209149438ba-000", + "transform": { + "WriteCLValue": { + "cl_type": "Bool", + "bytes": "00", + "parsed": false + } + } + }, + { + "key": "hash-378a43e38bc5129d8aa3bcd04f5c9a97be73f85b5be574182ac1346f04520796", + "transform": { + "AddKeys": [ + { + "name": "operator_burn_mode", + "key": "uref-f226eed9d0c5fcf58e6b481d45417721e35435c2ef5eb4d26d215209149438ba-007" + } + ] + } + }, + { + "key": "uref-51acad53fd1a6ce6a52cf83ed7f921565311ed86cd362969bacf9457b6bf5c1a-000", + "transform": { + "WriteCLValue": { + "cl_type": "U8", + "bytes": "00", + "parsed": 0 + } + } + }, + { + "key": "hash-378a43e38bc5129d8aa3bcd04f5c9a97be73f85b5be574182ac1346f04520796", + "transform": { + "AddKeys": [ + { + "name": "events_mode", + "key": "uref-51acad53fd1a6ce6a52cf83ed7f921565311ed86cd362969bacf9457b6bf5c1a-007" + } + ] + } + }, + { + "key": "uref-dca79aa4244d0123ad52799fc4f922b2ae9fc023c9e56f999979f535a792eef5-000", + "transform": { + "WriteCLValue": { + "cl_type": "Bool", + "bytes": "01", + "parsed": true + } + } + }, + { + "key": "hash-378a43e38bc5129d8aa3bcd04f5c9a97be73f85b5be574182ac1346f04520796", + "transform": { + "AddKeys": [ + { + "name": "allow_minting", + "key": "uref-dca79aa4244d0123ad52799fc4f922b2ae9fc023c9e56f999979f535a792eef5-007" + } + ] + } + }, + { + "key": "uref-f86e2c4057cc17d93593fb203a923d67e5bc68e6428a6d94f6eab0c35450653d-000", + "transform": { + "WriteCLValue": { + "cl_type": "U64", + "bytes": "0000000000000000", + "parsed": 0 + } + } + }, + { + "key": "hash-378a43e38bc5129d8aa3bcd04f5c9a97be73f85b5be574182ac1346f04520796", + "transform": { + "AddKeys": [ + { + "name": "number_of_minted_tokens", + "key": "uref-f86e2c4057cc17d93593fb203a923d67e5bc68e6428a6d94f6eab0c35450653d-007" + } + ] + } + }, + { + "key": "uref-ff53b7094bcb6659b558d31fdf63f837b05c0ee6030bfe18ad4c3fb0462b9b17-000", + "transform": { + "WriteCLValue": { + "cl_type": "Unit", + "bytes": "", + "parsed": null + } + } + }, + { + "key": "hash-378a43e38bc5129d8aa3bcd04f5c9a97be73f85b5be574182ac1346f04520796", + "transform": { + "AddKeys": [ + { + "name": "token_owners", + "key": "uref-ff53b7094bcb6659b558d31fdf63f837b05c0ee6030bfe18ad4c3fb0462b9b17-007" + } + ] + } + }, + { + "key": "uref-5700d04b36eb1f50204c0d1d05c8ed6aae77eaeaa8a425c78f5a24cbae2e4d26-000", + "transform": { + "WriteCLValue": { + "cl_type": "Unit", + "bytes": "", + "parsed": null + } + } + }, + { + "key": "hash-378a43e38bc5129d8aa3bcd04f5c9a97be73f85b5be574182ac1346f04520796", + "transform": { + "AddKeys": [ + { + "name": "token_issuers", + "key": "uref-5700d04b36eb1f50204c0d1d05c8ed6aae77eaeaa8a425c78f5a24cbae2e4d26-007" + } + ] + } + }, + { + "key": "uref-76aac8f7224c5c1624b4255fff59ecc8ee2c7a1ba460b4f70945d7548abbffd0-000", + "transform": { + "WriteCLValue": { + "cl_type": "Unit", + "bytes": "", + "parsed": null + } + } + }, + { + "key": "hash-378a43e38bc5129d8aa3bcd04f5c9a97be73f85b5be574182ac1346f04520796", + "transform": { + "AddKeys": [ + { + "name": "approved", + "key": "uref-76aac8f7224c5c1624b4255fff59ecc8ee2c7a1ba460b4f70945d7548abbffd0-007" + } + ] + } + }, + { + "key": "uref-ff8ad952307b57a051ef6cb597a55cc2007e587c575584addf6a6fc12c0efd7b-000", + "transform": { + "WriteCLValue": { + "cl_type": "Unit", + "bytes": "", + "parsed": null + } + } + }, + { + "key": "hash-378a43e38bc5129d8aa3bcd04f5c9a97be73f85b5be574182ac1346f04520796", + "transform": { + "AddKeys": [ + { + "name": "operators", + "key": "uref-ff8ad952307b57a051ef6cb597a55cc2007e587c575584addf6a6fc12c0efd7b-007" + } + ] + } + }, + { + "key": "uref-0c144d231ac070adb2668f2a9f3d0eba32c7468efa879f0f29c832c63698966b-000", + "transform": { + "WriteCLValue": { + "cl_type": "Unit", + "bytes": "", + "parsed": null + } + } + }, + { + "key": "hash-378a43e38bc5129d8aa3bcd04f5c9a97be73f85b5be574182ac1346f04520796", + "transform": { + "AddKeys": [ + { + "name": "burnt_tokens", + "key": "uref-0c144d231ac070adb2668f2a9f3d0eba32c7468efa879f0f29c832c63698966b-007" + } + ] + } + }, + { + "key": "uref-3d271bac2030ddee54bf4ea92b9b854d800a10a0df5d6e328a045be19af27538-000", + "transform": { + "WriteCLValue": { + "cl_type": "Unit", + "bytes": "", + "parsed": null + } + } + }, + { + "key": "hash-378a43e38bc5129d8aa3bcd04f5c9a97be73f85b5be574182ac1346f04520796", + "transform": { + "AddKeys": [ + { + "name": "balances", + "key": "uref-3d271bac2030ddee54bf4ea92b9b854d800a10a0df5d6e328a045be19af27538-007" + } + ] + } + }, + { + "key": "uref-575108b0258e92ebede1e50345b608d42963bdac24379022be20b76cfde15301-000", + "transform": { + "WriteCLValue": { + "cl_type": "Unit", + "bytes": "", + "parsed": null + } + } + }, + { + "key": "hash-378a43e38bc5129d8aa3bcd04f5c9a97be73f85b5be574182ac1346f04520796", + "transform": { + "AddKeys": [ + { + "name": "metadata_custom_validated", + "key": "uref-575108b0258e92ebede1e50345b608d42963bdac24379022be20b76cfde15301-007" + } + ] + } + }, + { + "key": "uref-2c2176a9efd465d2e4d5de05d75d029e03040d0a5668c4e08facb0cd3442d30a-000", + "transform": { + "WriteCLValue": { + "cl_type": "Unit", + "bytes": "", + "parsed": null + } + } + }, + { + "key": "hash-378a43e38bc5129d8aa3bcd04f5c9a97be73f85b5be574182ac1346f04520796", + "transform": { + "AddKeys": [ + { + "name": "metadata_cep78", + "key": "uref-2c2176a9efd465d2e4d5de05d75d029e03040d0a5668c4e08facb0cd3442d30a-007" + } + ] + } + }, + { + "key": "uref-eb37c0fe3b53fa5c72b02976f2840b7bf3692954fc830f8a10dc538d0c506e63-000", + "transform": { + "WriteCLValue": { + "cl_type": "Unit", + "bytes": "", + "parsed": null + } + } + }, + { + "key": "hash-378a43e38bc5129d8aa3bcd04f5c9a97be73f85b5be574182ac1346f04520796", + "transform": { + "AddKeys": [ + { + "name": "metadata_nft721", + "key": "uref-eb37c0fe3b53fa5c72b02976f2840b7bf3692954fc830f8a10dc538d0c506e63-007" + } + ] + } + }, + { + "key": "uref-cdb17062423b769a7b0bc18fe0a2202b68d2ba77786291018a24fd53f4532ab8-000", + "transform": { + "WriteCLValue": { + "cl_type": "Unit", + "bytes": "", + "parsed": null + } + } + }, + { + "key": "hash-378a43e38bc5129d8aa3bcd04f5c9a97be73f85b5be574182ac1346f04520796", + "transform": { + "AddKeys": [ + { + "name": "metadata_raw", + "key": "uref-cdb17062423b769a7b0bc18fe0a2202b68d2ba77786291018a24fd53f4532ab8-007" + } + ] + } + }, + { + "key": "uref-e280dd23c847724422543b0d70f1ed4c95c8da9e1a71927ae39add652859775c-000", + "transform": { + "WriteCLValue": { + "cl_type": "Unit", + "bytes": "", + "parsed": null + } + } + }, + { + "key": "hash-378a43e38bc5129d8aa3bcd04f5c9a97be73f85b5be574182ac1346f04520796", + "transform": { + "AddKeys": [ + { + "name": "hash_by_index", + "key": "uref-e280dd23c847724422543b0d70f1ed4c95c8da9e1a71927ae39add652859775c-007" + } + ] + } + }, + { + "key": "uref-6299c9322631f374fc1a5e20920641b23f437a3c0ba8da22cc23cba11b0fa3a5-000", + "transform": { + "WriteCLValue": { + "cl_type": "Unit", + "bytes": "", + "parsed": null + } + } + }, + { + "key": "hash-378a43e38bc5129d8aa3bcd04f5c9a97be73f85b5be574182ac1346f04520796", + "transform": { + "AddKeys": [ + { + "name": "index_by_hash", + "key": "uref-6299c9322631f374fc1a5e20920641b23f437a3c0ba8da22cc23cba11b0fa3a5-007" + } + ] + } + }, + { + "key": "uref-00efcfa874a60b5b615b3c6d781cf69c3559b5372d15457fe4a3bb6d07c66acd-000", + "transform": { + "WriteCLValue": { + "cl_type": "Unit", + "bytes": "", + "parsed": null + } + } + }, + { + "key": "hash-378a43e38bc5129d8aa3bcd04f5c9a97be73f85b5be574182ac1346f04520796", + "transform": { + "AddKeys": [ + { + "name": "page_table", + "key": "uref-00efcfa874a60b5b615b3c6d781cf69c3559b5372d15457fe4a3bb6d07c66acd-007" + } + ] + } + }, + { + "key": "uref-77b5861bdc04f3c63417dd2ed1943f659f6180603982a24587f79cbc38801cf4-000", + "transform": { + "WriteCLValue": { + "cl_type": "Unit", + "bytes": "", + "parsed": null + } + } + }, + { + "key": "hash-378a43e38bc5129d8aa3bcd04f5c9a97be73f85b5be574182ac1346f04520796", + "transform": { + "AddKeys": [ + { + "name": "acl_whitelist", + "key": "uref-77b5861bdc04f3c63417dd2ed1943f659f6180603982a24587f79cbc38801cf4-007" + } + ] + } + }, + { + "key": "uref-5e950cdd5497633c1d03284ec6e70ce436744cc172d6e26e21e4e474d1b34312-000", + "transform": { + "WriteCLValue": { + "cl_type": "Bool", + "bytes": "00", + "parsed": false + } + } + }, + { + "key": "hash-378a43e38bc5129d8aa3bcd04f5c9a97be73f85b5be574182ac1346f04520796", + "transform": { + "AddKeys": [ + { + "name": "acl_package_mode", + "key": "uref-5e950cdd5497633c1d03284ec6e70ce436744cc172d6e26e21e4e474d1b34312-007" + } + ] + } + }, + { + "key": "uref-05c2868f179f6b2323f1d4ea069858956c9666d14073748aae4a748d27a8a894-000", + "transform": { + "WriteCLValue": { + "cl_type": "Bool", + "bytes": "00", + "parsed": false + } + } + }, + { + "key": "hash-378a43e38bc5129d8aa3bcd04f5c9a97be73f85b5be574182ac1346f04520796", + "transform": { + "AddKeys": [ + { + "name": "package_operator_mode", + "key": "uref-05c2868f179f6b2323f1d4ea069858956c9666d14073748aae4a748d27a8a894-007" + } + ] + } + }, + { + "key": "uref-4d851152d7b89dff805dcf6eb61a33870dab9345084a5874575476a584d71b83-000", + "transform": { + "WriteCLValue": { + "cl_type": "U8", + "bytes": "00", + "parsed": 0 + } + } + }, + { + "key": "hash-378a43e38bc5129d8aa3bcd04f5c9a97be73f85b5be574182ac1346f04520796", + "transform": { + "AddKeys": [ + { + "name": "reporting_mode", + "key": "uref-4d851152d7b89dff805dcf6eb61a33870dab9345084a5874575476a584d71b83-007" + } + ] + } + }, + { + "key": "uref-2e3b8aafb27aae47c9b7d3728d20d8815b706e2245c23b84f0e712cd1d1e9124-000", + "transform": { + "WriteCLValue": { + "cl_type": "Bool", + "bytes": "00", + "parsed": false + } + } + }, + { + "key": "hash-378a43e38bc5129d8aa3bcd04f5c9a97be73f85b5be574182ac1346f04520796", + "transform": { + "AddKeys": [ + { + "name": "rlo_mflag", + "key": "uref-2e3b8aafb27aae47c9b7d3728d20d8815b706e2245c23b84f0e712cd1d1e9124-007" + } + ] + } + }, + { + "key": "deploy-1d1f66b26eb648b5f15bc958a552036e8521b508706056817b0d41c71f6d7afe", + "transform": { + "WriteDeployInfo": { + "deploy_hash": "1d1f66b26eb648b5f15bc958a552036e8521b508706056817b0d41c71f6d7afe", + "transfers": [], + "from": "account-hash-e70dbca48c2d31bc2d754e51860ceaa8a1a49dc627b20320b0ecee1b6d9ce655", + "source": "uref-11e6fc5354f61a004df98482376c45964b8b1557e8f2f13fb5f3adab5faa8be1-007", + "gas": "443359442322" + } + } + }, + { + "key": "hash-8cf5e4acf51f54eb59291599187838dc3bc234089c46fc6ca8ad17e762ae4401", + "transform": "Identity" + }, + { + "key": "hash-8cf5e4acf51f54eb59291599187838dc3bc234089c46fc6ca8ad17e762ae4401", + "transform": "Identity" + }, + { + "key": "hash-8cf5e4acf51f54eb59291599187838dc3bc234089c46fc6ca8ad17e762ae4401", + "transform": "Identity" + }, + { + "key": "hash-624dbe2395b9d9503fbee82162f1714ebff6b639f96d2084d26d944c354ec4c5", + "transform": "Identity" + }, + { + "key": "hash-8cf5e4acf51f54eb59291599187838dc3bc234089c46fc6ca8ad17e762ae4401", + "transform": "Identity" + }, + { + "key": "balance-98d945f5324f865243b7c02c0417ab6eac361c5c56602fd42ced834a1ba201b6", + "transform": "Identity" + }, + { + "key": "hash-8cf5e4acf51f54eb59291599187838dc3bc234089c46fc6ca8ad17e762ae4401", + "transform": "Identity" + }, + { + "key": "account-hash-e70dbca48c2d31bc2d754e51860ceaa8a1a49dc627b20320b0ecee1b6d9ce655", + "transform": "Identity" + }, + { + "key": "hash-010c3fe81b7b862e50c77ef9a958a05bfa98444f26f96f23d37a13c96244cfb7", + "transform": "Identity" + }, + { + "key": "hash-9824d60dc3a5c44a20b9fd260a412437933835b52fc683d8ae36e4ec2114843e", + "transform": "Identity" + }, + { + "key": "hash-010c3fe81b7b862e50c77ef9a958a05bfa98444f26f96f23d37a13c96244cfb7", + "transform": "Identity" + }, + { + "key": "balance-98d945f5324f865243b7c02c0417ab6eac361c5c56602fd42ced834a1ba201b6", + "transform": "Identity" + }, + { + "key": "balance-11e6fc5354f61a004df98482376c45964b8b1557e8f2f13fb5f3adab5faa8be1", + "transform": "Identity" + }, + { + "key": "balance-98d945f5324f865243b7c02c0417ab6eac361c5c56602fd42ced834a1ba201b6", + "transform": { + "WriteCLValue": { + "cl_type": "U512", + "bytes": "055bdf0a5c67", + "parsed": "443925847899" + } + } + }, + { + "key": "balance-11e6fc5354f61a004df98482376c45964b8b1557e8f2f13fb5f3adab5faa8be1", + "transform": { + "AddUInt512": "56074152101" + } + }, + { + "key": "hash-010c3fe81b7b862e50c77ef9a958a05bfa98444f26f96f23d37a13c96244cfb7", + "transform": "Identity" + }, + { + "key": "hash-9824d60dc3a5c44a20b9fd260a412437933835b52fc683d8ae36e4ec2114843e", + "transform": "Identity" + }, + { + "key": "hash-010c3fe81b7b862e50c77ef9a958a05bfa98444f26f96f23d37a13c96244cfb7", + "transform": "Identity" + }, + { + "key": "balance-98d945f5324f865243b7c02c0417ab6eac361c5c56602fd42ced834a1ba201b6", + "transform": "Identity" + }, + { + "key": "balance-dcf5abbbe00715e9a05f7449109b1d297cb1584560ec4f3f5a86401452e40d85", + "transform": "Identity" + }, + { + "key": "balance-98d945f5324f865243b7c02c0417ab6eac361c5c56602fd42ced834a1ba201b6", + "transform": { + "WriteCLValue": { + "cl_type": "U512", + "bytes": "00", + "parsed": "0" + } + } + }, + { + "key": "balance-dcf5abbbe00715e9a05f7449109b1d297cb1584560ec4f3f5a86401452e40d85", + "transform": { + "AddUInt512": "443925847899" + } + } + ] + }, + "transfers": [], + "cost": "443359442322" + } + } + } + ] + } +} +``` + +
+ +## Next Steps + +- Learn to [Query](./querying-NFTs.md) the NFT contract +- Learn to [Mint, Transfer, and Burn](./interacting-with-NFTs.md) NFT tokens diff --git a/source/docs/casper/resources/tokens/cep78/using-casper-client/interacting-with-NFTs.md b/source/docs/casper/resources/tokens/cep78/using-casper-client/interacting-with-NFTs.md new file mode 100644 index 0000000000..9ca3f5b8b3 --- /dev/null +++ b/source/docs/casper/resources/tokens/cep78/using-casper-client/interacting-with-NFTs.md @@ -0,0 +1,356 @@ +--- +title: Interaction Workflow +--- + +# Interacting with the NFT Contract using the Rust Casper Client + +This document describes interacting with NFTs on a Casper network using the Rust command-line client. + + +## Prerequisites + +- Install the contract using the [Quickstart](./quickstart-guide.md) or the [Full Installation](./full-installation-tutorial.md) tutorials +- Learn to [Query NFT Contracts](./querying-NFTs.md) and save the various hashes and URefs required throughout this document + + +## Table of Contents + +1. [Directly Invoking Entrypoints](#directly-invoking-entrypoints) + +2. [Minting NFTs](#minting-nfts) + +3. [Transferring NFTs](#transferring-nfts) + +4. [Checking Balances](#checking-balances) + +5. [Approving an Account](#approving-an-account) + +6. [Burning NFTs](#burning-nfts) + +7. [Next Steps](#next-steps) + + +## Directly Invoking Entrypoints + +With the release of CEP-78 version 1.1, users interacting with a CEP-78 contract that does not use `ReverseLookupMode` should opt out of using the client Wasm files provided as part of the release. Opting out in this situation is recommended, as directly invoking the entrypoints incurs a lower gas cost than using the provided client Wasm to invoke the entrypoint. + +You may invoke the `mint`, `transfer`, or `burn` entrypoints directly through either the contract package hash or the contract hash directly. + +In the case of `mint`, fewer runtime arguments must be provided, thereby reducing the total gas cost of minting an NFT. + +
+Example `mint` using the stored package hash + +```bash +casper-client put-deploy --node-address http://localhost:11101/rpc/ \ +--chain-name "casper-net-1” \ +--payment-amount 5000000000 \ +--secret-key ~/casper/casper-node/utils/nctl/assets/net-1/nodes/node-1/keys/secret_key.pem \ +--session-package-hash hash-2b61207cd0e94ce1b1d40801b0abb1ab55fd7dae94c9dcf670292243f3791a30 \ +--session-entry-point "mint" \ +--session-arg "token_owner:key='account-hash-e70dbca48c2d31bc2d754e51860ceaa8a1a49dc627b20320b0ecee1b6d9ce655'" \ +--session-arg "token_meta_data:string='{\"name\": \"John Doe\",\"token_uri\": \"https:\/\/www.barfoo.com\",\"checksum\": \"940bffb3f2bba35f84313aa26da09ece3ad47045c6a1292c2bbd2df4ab1a55fb\"}'" +``` + +
+ +
+Example `transfer` using the stored contract hash + +Based on the identifier mode for the given contract instance, either the `token_id` runtime argument must be passed in or, in the case of the hash identifier mode, the `token_hash` runtime argument. + +```bash +casper-client put-deploy --node-address http://localhost:11101/rpc/ \ +--chain-name "casper-net-1” \ +--payment-amount 5000000000 \ +--secret-key ~/casper/casper-node/utils/nctl/assets/net-1/nodes/node-1/keys/secret_key.pem \ +--session-hash hash-378a43e38bc5129d8aa3bcd04f5c9a97be73f85b5be574182ac1346f04520796 \ +--session-entry-point "transfer" \ +--session-arg "source_key:key='account-hash-e70dbca48c2d31bc2d754e51860ceaa8a1a49dc627b20320b0ecee1b6d9ce655'" \ +--session-arg "target_key:key='account-hash-0ea7998b2822afe5b62b08a21d54c941ad791279b089f3f7ede0d72b477eca34'" \ +--session-arg "token_id:u64='0'" +``` + +
+ + +## Minting NFTs + +Below is an example of a `casper-client` command that uses the `mint` entrypoint of the contract to mint an NFT for the user associated with `node-1` in an [NCTL environment](../../../../developers/dapps/nctl-test.md). + +- `casper-client put-deploy -n http://localhost:11101/rpc --chain-name "casper-net-1" --payment-amount 5000000000 -k ~/casper/casper-node/utils/nctl/assets/net-1/nodes/node-1/keys/secret_key.pem --session-entry-point "mint"` + +1. `--session-package-hash hash-2b61207cd0e94ce1b1d40801b0abb1ab55fd7dae94c9dcf670292243f3791a30` + + The package hash of the previously installed CEP-78 NFT contract from which we will be minting. + +2. `--session-arg "token_owner:key='account-hash-e9ff87766a1d2bab2565bfd5799054946200b51b20c3ca7e54a9269e00fe7cfb'"` + + The collection name of the NFT to be minted. + +3. `--session-arg "token_meta_data:string='{\"name\": \"John Doe\",\"token_uri\": \"https:\/\/www.barfoo.com\",\"checksum\": \"940bffb3f2bba35f84313aa26da09ece3ad47045c6a1292c2bbd2df4ab1a55fb\"}'"` + + Metadata describing the NFT to be minted, passed in as a `string`. + +
+Casper client command without comments + +```bash +casper-client put-deploy --node-address http://localhost:11101/rpc/ \ +--chain-name "casper-net-1” \ +--payment-amount 5000000000 \ +--secret-key ~/casper/casper-node/utils/nctl/assets/net-1/nodes/node-1/keys/secret_key.pem \ +--session-entry-point "mint" \ +--session-package-hash hash-2b61207cd0e94ce1b1d40801b0abb1ab55fd7dae94c9dcf670292243f3791a30 \ +--session-arg "token_owner:key='account-hash-e70dbca48c2d31bc2d754e51860ceaa8a1a49dc627b20320b0ecee1b6d9ce655'" \ +--session-arg "token_meta_data:string='{\"name\": \"John Doe\",\"token_uri\": \"https:\/\/www.barfoo.com\",\"checksum\": \"940bffb3f2bba35f84313aa26da09ece3ad47045c6a1292c2bbd2df4ab1a55fb\"}'" +``` + +
+ +:::note + +If the `identifier_mode` was set to hash (1) during installation, the `token_hash` runtime argument needs to be specified during minting. Since you already know the NFT's identifier, you can easily query the NFT's `meta_data`, which is a very useful feature. This example uses an ordinal (0) `identifier_mode`. + +::: + +### Minting NFTs using Wasm + +This example invokes the `mint_call.wasm` session code provided in the `client` folder. + +- `casper-client put-deploy -n http://localhost:11101/rpc --chain-name "casper-net-1" --payment-amount 5000000000 -k ~/casper/casper-node/utils/nctl/assets/net-1/nodes/node-1/keys/secret_key.pem --session-path ~/casper/enhanced-nft/client/mint_session/target/wasm32-unknown-unknown/release/mint_call.wasm` + +1. `--session-arg "nft_contract_hash:key='hash-206339c3deb8e6146974125bb271eb510795be6f250c21b1bd4b698956669f95'"` + + The contract hash of the previously installed CEP-78 NFT contract from which we will be minting. + +2. `--session-arg "collection_name:string='cep78_'"` + + The collection name of the previously installed CEP-78 NFT contract from which we will be minting. + +3. `--session-arg "token_owner:key='account-hash-e9ff87766a1d2bab2565bfd5799054946200b51b20c3ca7e54a9269e00fe7cfb'"` + + The collection name of the NFT to be minted. + +4. `--session-arg "token_meta_data:string='{\"name\": \"John Doe\",\"token_uri\": \"https:\/\/www.barfoo.com\",\"checksum\": \"940bffb3f2bba35f84313aa26da09ece3ad47045c6a1292c2bbd2df4ab1a55fb\"}'"` + + Metadata describing the NFT to be minted, passed in as a `string`. + + +
+Casper client command without comments + +```bash +casper-client put-deploy --node-address http://localhost:11101/rpc/ \ +--chain-name "casper-net-1” \ +--payment-amount 5000000000 \ +--secret-key ~/casper/casper-node/utils/nctl/assets/net-1/nodes/node-1/keys/secret_key.pem \ +--session-path ~/casper/enhanced-nft/client/mint_session/target/wasm32-unknown-unknown/release/mint_call.wasm \ +--session-arg "nft_contract_hash:key='hash-206339c3deb8e6146974125bb271eb510795be6f250c21b1bd4b698956669f95'" \ +--session-arg "collection_name:string='cep78_'" \ +--session-arg "token_owner:key='account-hash-e9ff87766a1d2bab2565bfd5799054946200b51b20c3ca7e54a9269e00fe7cfb'" \ +--session-arg "token_meta_data:string='{\"name\": \"John Doe\",\"token_uri\": \"https:\/\/www.barfoo.com\",\"checksum\": \"940bffb3f2bba35f84313aa26da09ece3ad47045c6a1292c2bbd2df4ab1a55fb\"}'" +``` + +
+ + +## Transferring NFTs + +Below is an example of a `casper-client` command that uses the `transfer` entrypoint to transfer ownership of an NFT from one user to another. + +- `casper-client put-deploy -n http://localhost:11101/rpc --chain-name "casper-net-1" --payment-amount 5000000000 -k ~/casper/casper-node/utils/nctl/assets/net-1/nodes/node-1/keys/secret_key.pem --session-entry-point "transfer"` + +1. `--session-hash hash-52e78ae3f6c485d036a74f65ebbb8c75fcc7c33fb42eb667fb32aeba72c63fb5'"` + + The contract hash of the CEP-78 NFT Contract associated with the NFT to be transferred. + +2. `--session-arg "source_key:key='account-hash-e9ff87766a1d2bab2565bfd5799054946200b51b20c3ca7e54a9269e00fe7cfb'"` + + The account hash of the user that currently owns the NFT and wishes to transfer it. + +3. `--session-arg "target_key:key='account-hash-b4772e7c47e4deca5bd90b7adb2d6e884f2d331825d5419d6cbfb59e17642aab'"` + + The account hash of the user that will receive the NFT. + +4. `--session-arg "is_hash_identifier_mode:bool='false'"` + + The argument that the hash identifier mode is ordinal, thereby requiring a `token_id` rather than a `token_hash`. + +5. `--session-arg "token_id:u64='0'"` + + The `token_id` of the NFT to be transferred. + +
+Casper client command without comments + +```bash +casper-client put-deploy -n http://localhost:11101/rpc --chain-name "casper-net-1" \ +--payment-amount 5000000000 \ +-k ~/casper/casper-node/utils/nctl/assets/net-1/nodes/node-1/keys/secret_key.pem \ +--session-entry-point "transfer" \ +--session-hash hash-52e78ae3f6c485d036a74f65ebbb8c75fcc7c33fb42eb667fb32aeba72c63fb5 \ +--session-arg "source_key:key='account-hash-e9ff87766a1d2bab2565bfd5799054946200b51b20c3ca7e54a9269e00fe7cfb'" \ +--session-arg "target_key:key='account-hash-b4772e7c47e4deca5bd90b7adb2d6e884f2d331825d5419d6cbfb59e17642aab'" \ +--session-arg "is_hash_identifier_mode:bool='false'" \ +--session-arg "token_id:u64='0'" +``` + +
+ +This command will return a deploy hash that you can query using `casper-client get-deploy`. Querying the deploy allows you to verify execution success, but you will need to use the `balance_of` entrypoint to verify the account's balance as shown [below](#checking-the-balance). + + +### Transferring NFTs using Wasm + +This example uses the `transfer_call.wasm` session code to transfer ownership of an NFT from one user to another. + +- `casper-client put-deploy -n http://localhost:11101/rpc --chain-name "casper-net-1" --payment-amount 5000000000 -k ~/secret_key.pem --session-path ~/casper/enhanced-nft/client/transfer_session/target/wasm32-unknown-unknown/release/transfer_call.wasm` + +1. `--session-arg "nft_contract_hash:key='hash-52e78ae3f6c485d036a74f65ebbb8c75fcc7c33fb42eb667fb32aeba72c63fb5'"` + + The contract hash of the CEP-78 NFT Contract associated with the NFT to be transferred. + +2. `--session-arg "source_key:key='account-hash-e9ff87766a1d2bab2565bfd5799054946200b51b20c3ca7e54a9269e00fe7cfb'"` + + The account hash of the user that currently owns the NFT and wishes to transfer it. + +3. `--session-arg "target_key:key='account-hash-b4772e7c47e4deca5bd90b7adb2d6e884f2d331825d5419d6cbfb59e17642aab'"` + + The account hash of the user that will receive the NFT. + +4. `--session-arg "is_hash_identifier_mode:bool='false'"` + + Argument that the hash identifier mode is ordinal, thereby requiring a `token_id` rather than a `token_hash`. + +5. `--session-arg "token_id:u64='0'"` + + The `token_id` of the NFT to be transferred. + +
+Casper client command without comments + +```bash +casper-client put-deploy -n http://localhost:11101/rpc --chain-name "casper-net-1" \ +--payment-amount 5000000000 \ +-k ~/casper/casper-node/utils/nctl/assets/net-1/nodes/node-2/keys/secret_key.pem \ +--session-path ~/casper/enhanced-nft/client/transfer_session/target/wasm32-unknown-unknown/release/transfer_call.wasm \ +--session-arg "nft_contract_hash:key='hash-52e78ae3f6c485d036a74f65ebbb8c75fcc7c33fb42eb667fb32aeba72c63fb5'" \ +--session-arg "source_key:key='account-hash-e9ff87766a1d2bab2565bfd5799054946200b51b20c3ca7e54a9269e00fe7cfb'" \ +--session-arg "target_key:key='account-hash-b4772e7c47e4deca5bd90b7adb2d6e884f2d331825d5419d6cbfb59e17642aab'" \ +--session-arg "is_hash_identifier_mode:bool='false'" \ +--session-arg "token_id:u64='0'" +``` + +
+ + +## Checking Balances + +To check an account's balance, get the latest state root hash and query the `balances` dictionary given the NFT contract hash and the owner's account hash without the "account-hash-" prefix, as shown below. + +- `casper-client get-dictionary-item -n http://localhost:11101/rpc` + +1. `--state-root-hash f22e8ecfb3d2700d5f902c83da456c32f130b73d0d35037fe89b2d4b4933673f` + + The latest state root hash. + +2. `--contract-hash hash-378a43e38bc5129d8aa3bcd04f5c9a97be73f85b5be574182ac1346f04520796` + + The NFT contract hash. + +3. `--dictionary-name "balances"` + + The dictionary tracking the number of tokens for each account hash. + +4. `--dictionary-item-key "0ea7998b2822afe5b62b08a21d54c941ad791279b089f3f7ede0d72b477eca34"` + + The account hash of the user whose token balance we are checking without the `account-hash-` prefix. + +
+Casper client commands without comments + +```bash +casper-client get-state-root-hash --node-address https://rpc.testnet.casperlabs.io/ + +casper-client get-dictionary-item -n http://localhost:11101/rpc/ \ +--state-root-hash f22e8ecfb3d2700d5f902c83da456c32f130b73d0d35037fe89b2d4b4933673f \ +--contract-hash hash-378a43e38bc5129d8aa3bcd04f5c9a97be73f85b5be574182ac1346f04520796 \ +--dictionary-name "balances" \ +--dictionary-item-key "0ea7998b2822afe5b62b08a21d54c941ad791279b089f3f7ede0d72b477eca34" +``` + +
+ +## Approving an Account + +The Casper NFT contract features an `approve` entrypoint, allowing another account to manage a specific token. During contract installation, the `ownership_mode` must be set to 2, meaning `Transferable`. + +- `casper-client put-deploy -n http://localhost:11101/rpc --chain-name "casper-net-1" --payment-amount 5000000000 -k ~/casper/casper-node/utils/nctl/assets/net-1/nodes/node-1/keys/secret_key.pem --session-entry-point "approve"` + +1. `--session-hash hash-52e78ae3f6c485d036a74f65ebbb8c75fcc7c33fb42eb667fb32aeba72c63fb5` + + The contract hash of the previously installed CEP-78 NFT contract. + +2. `--session-arg "spender:key='account-hash-17192017d32db5dc9f598bf8ac6ac35ee4b64748669b00572d88335941479513'"` + + The hash of the account receiving the approval. + +3. `--session-arg "token_id:u64='1'"` + + The token ID of the approved NFT. + + +
+Casper client command without comments + +```bash +casper-client put-deploy -n http://localhost:11101/rpc/ \ +--chain-name "casper-net-1" \ +--payment-amount 5000000000 \ +-k ~/casper/casper-node/utils/nctl/assets/net-1/nodes/node-1/keys/secret_key.pem \ +--session-entry-point "approve" \ +--session-hash hash-52e78ae3f6c485d036a74f65ebbb8c75fcc7c33fb42eb667fb32aeba72c63fb5 \ +--session-arg "spender:key='account-hash-17192017d32db5dc9f598bf8ac6ac35ee4b64748669b00572d88335941479513'" \ +--session-arg "token_id:u64='1'" +``` + +
+ + +## Burning NFTs + +Below is an example of a `casper-client` command that uses the `burn` entrypoint to burn an NFT within a CEP-78 collection. If this command is used, the NFT in question will no longer be accessible by anyone. + +- `casper-client put-deploy -n http://localhost:11101/rpc --chain-name "casper-net-1" --payment-amount 5000000000 -k ~/casper/casper-node/utils/nctl/assets/net-1/nodes/node-1/keys/secret_key.pem` + +1. `--session-hash hash-52e78ae3f6c485d036a74f65ebbb8c75fcc7c33fb42eb667fb32aeba72c63fb5` + + The session hash corresponding to the NFT's contract hash. + +2. `--session-entry-point "burn"` + + The entrypoint corresponding to the `burn` function. + +3. `--session-arg "token_id:u64='1'"` + + The token ID for the NFT to be burned. If the `identifier_mode` is not set to `Ordinal`, you must provide the `token_hash` instead. + +
+Casper client command without comments + +```bash +casper-client put-deploy -n http://localhost:11101/rpc --chain-name "casper-net-1" \ +--payment-amount 5000000000 \ +-k ~/casper/casper-node/utils/nctl/assets/net-1/nodes/node-1/keys/secret_key.pem \ +--session-hash hash-52e78ae3f6c485d036a74f65ebbb8c75fcc7c33fb42eb667fb32aeba72c63fb5 \ +--session-entry-point "burn" \ +--session-arg "token_id:u64='1'" +``` + +
+ + +## Next Steps + +- [Testing Framework for CEP-78](./testing-NFTs.md) diff --git a/source/docs/casper/resources/tokens/cep78/using-casper-client/querying-NFTs.md b/source/docs/casper/resources/tokens/cep78/using-casper-client/querying-NFTs.md new file mode 100644 index 0000000000..7e8b9b534f --- /dev/null +++ b/source/docs/casper/resources/tokens/cep78/using-casper-client/querying-NFTs.md @@ -0,0 +1,550 @@ +--- +title: CEP-78 Contract Details +--- + +import useBaseUrl from '@docusaurus/useBaseUrl'; + +# Querying NFT Contracts + +This document covers different commands to query and interact with an NFT (CEP-78) contract instance. + +## Prerequisites + +- Install the contract using the [Quickstart](./quickstart-guide.md) or the [Full Installation](./full-installation-tutorial.md) tutorials + +## Querying the Contract + +First, identify the contract hash by looking at the account that installed the contract. Under the account's named keys, you will see a named key for the contract hash, representing the stored contract. Copy this value and save it for future queries. + +The NFT contract hash + +Next, query the contract details. + +- `casper-client query-global-state -n http://localhost:11101/rpc/` + +1. `--key [CONTRACT_HASH]` + + The contract hash, found within the `NamedKeys` of the account that sent the installing deploy. + +2. `--state-root-hash [STATE_ROOT_HASH]` + + The most up-to-date state root hash, which can be found by using the `get-state-root-hash` command in the Casper client. + +
+Expand to see the query and sample contract + + +```bash +casper-client query-global-state -n http://localhost:11101/rpc/ \ +--key hash-378a43e38bc5129d8aa3bcd04f5c9a97be73f85b5be574182ac1346f04520796 \ +--state-root-hash 2a8cfc20d24b4bc629ea6d26cc820560a1baf3d4275079d5382242c9fa1e86fe +``` + +```json +{ + "jsonrpc": "2.0", + "id": -5355991397545050403, + "result": { + "api_version": "1.5.6", + "block_header": null, + "stored_value": { + "Contract": { + "contract_package_hash": "contract-package-2b61207cd0e94ce1b1d40801b0abb1ab55fd7dae94c9dcf670292243f3791a30", + "contract_wasm_hash": "contract-wasm-845d3d08e29642afba35704bcb6e38f3c40f1469763bff7a88674c9a5be3f01b", + "named_keys": [ + { + "name": "acl_package_mode", + "key": "uref-5e950cdd5497633c1d03284ec6e70ce436744cc172d6e26e21e4e474d1b34312-007" + }, + { + "name": "acl_whitelist", + "key": "uref-77b5861bdc04f3c63417dd2ed1943f659f6180603982a24587f79cbc38801cf4-007" + }, + { + "name": "allow_minting", + "key": "uref-dca79aa4244d0123ad52799fc4f922b2ae9fc023c9e56f999979f535a792eef5-007" + }, + { + "name": "approved", + "key": "uref-76aac8f7224c5c1624b4255fff59ecc8ee2c7a1ba460b4f70945d7548abbffd0-007" + }, + { + "name": "balances", + "key": "uref-3d271bac2030ddee54bf4ea92b9b854d800a10a0df5d6e328a045be19af27538-007" + }, + { + "name": "burn_mode", + "key": "uref-eb1a7f69592881587805fde2d53e8e5b3dcbabd81311faa7b9d19ea731f83d9b-007" + }, + { + "name": "burnt_tokens", + "key": "uref-0c144d231ac070adb2668f2a9f3d0eba32c7468efa879f0f29c832c63698966b-007" + }, + { + "name": "cep78_CEP-78-collection2", + "key": "uref-ac99c07d666f45ff5c86a2c1bb6cc44b612ddd5d39a9de88045b441ff6e6b327-007" + }, + { + "name": "collection_name", + "key": "uref-5aed76a73089e7e32f6fbf5d9a9597843215d4810cd5822c0f5c6e65a0bbb7a3-007" + }, + { + "name": "collection_symbol", + "key": "uref-ba4247cc0354644474758d1292924c5115c61c8012cae3f094a91060d9dff779-007" + }, + { + "name": "events_mode", + "key": "uref-51acad53fd1a6ce6a52cf83ed7f921565311ed86cd362969bacf9457b6bf5c1a-007" + }, + { + "name": "hash_by_index", + "key": "uref-e280dd23c847724422543b0d70f1ed4c95c8da9e1a71927ae39add652859775c-007" + }, + { + "name": "holder_mode", + "key": "uref-8443151d736bb3268815ad7848708d44ccc661799f969697c64b1cddb5ce89a7-007" + }, + { + "name": "identifier_mode", + "key": "uref-f53ea99b60ae6d046a6fb0d996475714ef03ed33b39674a8fe016c8324116baf-007" + }, + { + "name": "index_by_hash", + "key": "uref-6299c9322631f374fc1a5e20920641b23f437a3c0ba8da22cc23cba11b0fa3a5-007" + }, + { + "name": "installer", + "key": "account-hash-e70dbca48c2d31bc2d754e51860ceaa8a1a49dc627b20320b0ecee1b6d9ce655" + }, + { + "name": "json_schema", + "key": "uref-772103052d4559fcc2f8f2c2568eb75214462d463009106938e6f20e1cc0a7c0-007" + }, + { + "name": "metadata_cep78", + "key": "uref-2c2176a9efd465d2e4d5de05d75d029e03040d0a5668c4e08facb0cd3442d30a-007" + }, + { + "name": "metadata_custom_validated", + "key": "uref-575108b0258e92ebede1e50345b608d42963bdac24379022be20b76cfde15301-007" + }, + { + "name": "metadata_mutability", + "key": "uref-2ca963a70a69df2db931b8761b4de13bd22e2fc54a415b0b57d4204c9b90dde9-007" + }, + { + "name": "metadata_nft721", + "key": "uref-eb37c0fe3b53fa5c72b02976f2840b7bf3692954fc830f8a10dc538d0c506e63-007" + }, + { + "name": "metadata_raw", + "key": "uref-cdb17062423b769a7b0bc18fe0a2202b68d2ba77786291018a24fd53f4532ab8-007" + }, + { + "name": "minting_mode", + "key": "uref-3b45a30c98d90de2c62812c6689aa2fac0cb4d08772fcfdee0584c5db2b1d12a-007" + }, + { + "name": "nft_kind", + "key": "uref-e02c29a6120d5da7f14fb664ca60c3ade56a3171a670c292d0a4ea0f9ae4f0c8-007" + }, + { + "name": "nft_metadata_kind", + "key": "uref-45e1bc671353ae58c41a703055959da243deefc7f4c3f121f3f9828d97475bda-007" + }, + { + "name": "nft_metadata_kinds", + "key": "uref-05c0eb8e7ef4caa6f228e8ee91874dc64926b95926d839b458fdce356063a817-007" + }, + { + "name": "number_of_minted_tokens", + "key": "uref-f86e2c4057cc17d93593fb203a923d67e5bc68e6428a6d94f6eab0c35450653d-007" + }, + { + "name": "operator_burn_mode", + "key": "uref-f226eed9d0c5fcf58e6b481d45417721e35435c2ef5eb4d26d215209149438ba-007" + }, + { + "name": "operators", + "key": "uref-ff8ad952307b57a051ef6cb597a55cc2007e587c575584addf6a6fc12c0efd7b-007" + }, + { + "name": "ownership_mode", + "key": "uref-89711af74265427dc65d7c5a421cedde82de69d192cad36f34efa36504108572-007" + }, + { + "name": "package_operator_mode", + "key": "uref-05c2868f179f6b2323f1d4ea069858956c9666d14073748aae4a748d27a8a894-007" + }, + { + "name": "page_table", + "key": "uref-00efcfa874a60b5b615b3c6d781cf69c3559b5372d15457fe4a3bb6d07c66acd-007" + }, + { + "name": "receipt_name", + "key": "uref-1ec63ea6442d9b4ef40d926280f8b72704b763d3ef7cdaccd9ecb04af5562d99-007" + }, + { + "name": "reporting_mode", + "key": "uref-4d851152d7b89dff805dcf6eb61a33870dab9345084a5874575476a584d71b83-007" + }, + { + "name": "rlo_mflag", + "key": "uref-2e3b8aafb27aae47c9b7d3728d20d8815b706e2245c23b84f0e712cd1d1e9124-007" + }, + { + "name": "token_issuers", + "key": "uref-5700d04b36eb1f50204c0d1d05c8ed6aae77eaeaa8a425c78f5a24cbae2e4d26-007" + }, + { + "name": "token_owners", + "key": "uref-ff53b7094bcb6659b558d31fdf63f837b05c0ee6030bfe18ad4c3fb0462b9b17-007" + }, + { + "name": "total_token_supply", + "key": "uref-e5f06deadcbfe5a469e7c162346580744746bfdc0ec67002e0ecba5b11096827-007" + }, + { + "name": "whitelist_mode", + "key": "uref-a77f2ac1f5e72c6b096ca414ae2c986a5387442ddf8e89a35b787a756adc4bb4-007" + } + ], + "entry_points": [ + { + "name": "approve", + "args": [ + { + "name": "spender", + "cl_type": "Key" + } + ], + "ret": "Unit", + "access": "Public", + "entry_point_type": "Contract" + }, + { + "name": "balance_of", + "args": [ + { + "name": "token_owner", + "cl_type": "Key" + } + ], + "ret": "U64", + "access": "Public", + "entry_point_type": "Contract" + }, + { + "name": "burn", + "args": [], + "ret": "Unit", + "access": "Public", + "entry_point_type": "Contract" + }, + { + "name": "get_approved", + "args": [], + "ret": { + "Option": "Key" + }, + "access": "Public", + "entry_point_type": "Contract" + }, + { + "name": "init", + "args": [ + { + "name": "collection_name", + "cl_type": "String" + }, + { + "name": "collection_symbol", + "cl_type": "String" + }, + { + "name": "total_token_supply", + "cl_type": "U64" + }, + { + "name": "allow_minting", + "cl_type": "Bool" + }, + { + "name": "minting_mode", + "cl_type": "U8" + }, + { + "name": "ownership_mode", + "cl_type": "U8" + }, + { + "name": "nft_kind", + "cl_type": "U8" + }, + { + "name": "holder_mode", + "cl_type": "U8" + }, + { + "name": "whitelist_mode", + "cl_type": "U8" + }, + { + "name": "acl_whitelist", + "cl_type": { + "List": "Key" + } + }, + { + "name": "acl_package_mode", + "cl_type": "Bool" + }, + { + "name": "package_operator_mode", + "cl_type": "Bool" + }, + { + "name": "json_schema", + "cl_type": "String" + }, + { + "name": "receipt_name", + "cl_type": "String" + }, + { + "name": "identifier_mode", + "cl_type": "U8" + }, + { + "name": "burn_mode", + "cl_type": "U8" + }, + { + "name": "operator_burn_mode", + "cl_type": "Bool" + }, + { + "name": "nft_metadata_kind", + "cl_type": "U8" + }, + { + "name": "metadata_mutability", + "cl_type": "U8" + }, + { + "name": "owner_reverse_lookup_mode", + "cl_type": "U8" + }, + { + "name": "events_mode", + "cl_type": "U8" + }, + { + "name": "transfer_filter_contract", + "cl_type": { + "Option": "Key" + } + } + ], + "ret": "Unit", + "access": "Public", + "entry_point_type": "Contract" + }, + { + "name": "is_approved_for_all", + "args": [ + { + "name": "token_owner", + "cl_type": "Key" + }, + { + "name": "operator", + "cl_type": "Key" + } + ], + "ret": "Bool", + "access": "Public", + "entry_point_type": "Contract" + }, + { + "name": "metadata", + "args": [], + "ret": "String", + "access": "Public", + "entry_point_type": "Contract" + }, + { + "name": "migrate", + "args": [ + { + "name": "cep78_package_key", + "cl_type": "Any" + } + ], + "ret": "Unit", + "access": "Public", + "entry_point_type": "Contract" + }, + { + "name": "mint", + "args": [ + { + "name": "token_owner", + "cl_type": "Key" + }, + { + "name": "token_meta_data", + "cl_type": "String" + } + ], + "ret": { + "Tuple3": [ + "String", + "Key", + "String" + ] + }, + "access": "Public", + "entry_point_type": "Contract" + }, + { + "name": "owner_of", + "args": [], + "ret": "Key", + "access": "Public", + "entry_point_type": "Contract" + }, + { + "name": "register_owner", + "args": [], + "ret": { + "Tuple2": [ + "String", + "URef" + ] + }, + "access": "Public", + "entry_point_type": "Contract" + }, + { + "name": "revoke", + "args": [], + "ret": "Unit", + "access": "Public", + "entry_point_type": "Contract" + }, + { + "name": "set_approval_for_all", + "args": [ + { + "name": "approve_all", + "cl_type": "Bool" + }, + { + "name": "operator", + "cl_type": "Key" + } + ], + "ret": "Unit", + "access": "Public", + "entry_point_type": "Contract" + }, + { + "name": "set_token_metadata", + "args": [ + { + "name": "token_meta_data", + "cl_type": "String" + } + ], + "ret": "Unit", + "access": "Public", + "entry_point_type": "Contract" + }, + { + "name": "set_variables", + "args": [ + { + "name": "allow_minting", + "cl_type": "Bool" + }, + { + "name": "contract_whitelist", + "cl_type": { + "List": { + "ByteArray": 32 + } + } + }, + { + "name": "acl_whitelist", + "cl_type": { + "List": "Key" + } + }, + { + "name": "acl_package_mode", + "cl_type": "Bool" + }, + { + "name": "package_operator_mode", + "cl_type": "Bool" + }, + { + "name": "operator_burn_mode", + "cl_type": "Bool" + } + ], + "ret": "Unit", + "access": "Public", + "entry_point_type": "Contract" + }, + { + "name": "transfer", + "args": [ + { + "name": "source_key", + "cl_type": "Key" + }, + { + "name": "target_key", + "cl_type": "Key" + } + ], + "ret": { + "Tuple2": [ + "String", + "Key" + ] + }, + "access": "Public", + "entry_point_type": "Contract" + }, + { + "name": "updated_receipts", + "args": [], + "ret": { + "List": { + "Tuple2": [ + "String", + "Key" + ] + } + }, + "access": "Public", + "entry_point_type": "Contract" + } + ], + "protocol_version": "1.5.6" + } + }, + "merkle_proof": "[33244 hex chars]" + } +} +``` + +
+ +## Next Steps + +- Learn to [Mint, Transfer, and Burn](./interacting-with-NFTs.md) NFT tokens \ No newline at end of file diff --git a/source/docs/casper/resources/tokens/cep78/using-casper-client/quickstart-guide.md b/source/docs/casper/resources/tokens/cep78/using-casper-client/quickstart-guide.md new file mode 100644 index 0000000000..5c39735c7a --- /dev/null +++ b/source/docs/casper/resources/tokens/cep78/using-casper-client/quickstart-guide.md @@ -0,0 +1,68 @@ +--- +title: Quick Installation +--- + +# Casper NFT Quick Installation Guide + +This quick installation guide introduces you to the Casper client commands and Wasm files necessary to deploy a CEP-78 Casper Enhanced NFT contract to the [Casper Testnet](https://testnet.cspr.live/). For greater detail into the creation and mechanics of the Casper NFT contract, see the complete [Casper NFT Tutorial](./full-installation-tutorial.md). + +To execute transactions on a Casper network involving NFTs, you will need some CSPR tokens to pay for the transactions. The Testnet provides test tokens using a [faucet](../../../../users/csprlive/testnet-faucet.md). + +## Prerequisites + +Before using this guide, ensure you meet the following requirements: + +- Set up the [development prerequisites](../../../../developers/prerequisites.md), including the [Casper client](../../../../developers/prerequisites.md#install-casper-client) +- Get a valid [node address](../../../../developers/prerequisites.md#acquire-node-address-from-network-peers) from the network +- Know how to install a [smart contract](../../../../developers/cli/sending-deploys.md) on a Casper network +- Hold enough CSPR tokens to pay for transactions + +## Setup + +Clone the Casper NFT (CEP-78) [contract repository](https://github.com/casper-ecosystem/cep-78-enhanced-nft/). + +```bash +git clone https://github.com/casper-ecosystem/cep-78-enhanced-nft/ && cd cep-78-enhanced-nft +``` + +Run the following commands to build the `contract.wasm` in the `contract/target/wasm32-unknown-unknown/release` directory and run the tests. + +```bash +make prepare +make test +``` + +The output of the command would end with the following message: + +```bash +test result: ok. 159 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in 15.33s +``` + +## Installing the NFT Contract + +The following command will install a sample NFT contract on the Testnet: + +```bash +casper-client put-deploy --node-address http://localhost:11101/rpc/ \ +--chain-name "casper-net-1" \ +--payment-amount 5000000000 \ +--secret-key ~/casper/casper-node/utils/nctl/assets/net-1/nodes/node-1/keys/secret_key.pem \ +--session-path contract/target/wasm32-unknown-unknown/release/contract.wasm \ +--session-arg "collection_name:string='CEP-78-collection'" \ +--session-arg "collection_symbol:string='CEP78'" \ +--session-arg "total_token_supply:u64='100'" \ +--session-arg "ownership_mode:u8='2'" \ +--session-arg "nft_kind:u8='1'" \ +--session-arg "nft_metadata_kind:u8='0'" \ +--session-arg "json_schema:string='nft-schema'" \ +--session-arg "identifier_mode:u8='0'" \ +--session-arg "metadata_mutability:u8='0'" +``` + +## Next Steps + +Learn to query the contract, perform token transfers, set up approvals, and understand the testing framework. + +- [Query](./querying-NFTs.md) the NTF Contract +- Learn to [Mint, Transfer, and Burn](./interacting-with-NFTs.md) NFT tokens +- Review the [Tests](./testing-NFTs.md) \ No newline at end of file diff --git a/source/docs/casper/resources/tokens/cep78/using-casper-client/testing-NFTs.md b/source/docs/casper/resources/tokens/cep78/using-casper-client/testing-NFTs.md new file mode 100644 index 0000000000..0d7fbd53f1 --- /dev/null +++ b/source/docs/casper/resources/tokens/cep78/using-casper-client/testing-NFTs.md @@ -0,0 +1,29 @@ +--- +title: Testing NFTs +--- + +# Testing NFT Contracts + +## Prerequisites + +- Install the contract using the [Quickstart](./quickstart-guide.md) or the [Full Installation](./full-installation-tutorial.md) tutorials + +## Framework Description + +The testing framework in this tutorial uses the [Casper engine test support](https://crates.io/crates/casper-engine-test-support) crate for testing the contract implementation against the Casper execution environment. + +The [tests](https://github.com/casper-ecosystem/cep-78-enhanced-nft/tree/dev/tests/src) source folder contains over 150 tests covering a variety of scenarios, including contract installation, minting and burning tokens, sending transfers, upgrading the contract, and listening to events. + +For more details about the test framework and how each test is set up, visit the [Testing Smart Contracts](../../../../developers/writing-onchain-code/testing-contracts.md) documentation page. + +## Running the Tests + +To build and run the tests, issue the following command in the project folder: + +```bash +make test +``` + +The project contains a [Makefile](https://github.com/casper-ecosystem/cep-78-enhanced-nft/blob/dev/Makefile), which is a custom build script that compiles the contract before running tests in _release_ mode. Then, the script copies the `contract.wasm` file to the corresponding version folder in a `tests/wasm` directory. In practice, you only need to run the `make test` command during development without building the contract separately. + +This example uses `bash`. If you use a Rust IDE, you must configure it to run the tests. \ No newline at end of file diff --git a/source/docs/casper/resources/tokens/index.md b/source/docs/casper/resources/tokens/index.md index edd77dc8d6..62a805a484 100644 --- a/source/docs/casper/resources/tokens/index.md +++ b/source/docs/casper/resources/tokens/index.md @@ -20,6 +20,6 @@ slug: /resources/tokens/ | ------------------------------------------------------------------------------ | ---------------------------------------------------------------- | | [CEP-78 Enhanced NFT Standard Introduction](./cep78/introduction.md) | An introduction to the CEP-78 Enhanced NFT Standard. | | [CEP-78 Modalities](./cep78/introduction.md) | Information on the features available when installing a CEP-78 contract instance.| -| [Installing and Interacting with a CEP-78 Contract](./cep78/using-casper-client.md)| An introduction to features present in the CEP-78 Enhanced NFT Standard.| +| [Installing and Interacting with a CEP-78 Contract](./cep78/using-casper-client/full-installation-tutorial.md)| An introduction to features present in the CEP-78 Enhanced NFT Standard.| | [Owner Reverse Lookup Functionality](./cep78/reverse-lookup.md) | Information on the Onwer Reverse Lookup feature of CEP-78 contracts.| | [A CEP-78 JavaScript Client Tutorial](./cep78/js-tutorial.md) | A tutorial for using the JavaScript CEP-78 client. | diff --git a/src/plugins/docusaurus-plugin-cookiesbanner/yarn.lock b/src/plugins/docusaurus-plugin-cookiesbanner/yarn.lock index 3cb7dc6daf..17ec28ce38 100644 --- a/src/plugins/docusaurus-plugin-cookiesbanner/yarn.lock +++ b/src/plugins/docusaurus-plugin-cookiesbanner/yarn.lock @@ -17,6 +17,14 @@ dependencies: "@babel/highlight" "^7.22.5" +"@babel/code-frame@^7.23.5": + version "7.23.5" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.23.5.tgz#9009b69a8c602293476ad598ff53e4562e15c244" + integrity sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA== + dependencies: + "@babel/highlight" "^7.23.4" + chalk "^2.4.2" + "@babel/compat-data@^7.22.5", "@babel/compat-data@^7.22.6", "@babel/compat-data@^7.22.9": version "7.22.9" resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.22.9.tgz#71cdb00a1ce3a329ce4cbec3a44f9fef35669730" @@ -43,7 +51,7 @@ json5 "^2.2.2" semver "^6.3.1" -"@babel/generator@^7.22.7", "@babel/generator@^7.22.9": +"@babel/generator@^7.22.9": version "7.22.9" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.22.9.tgz#572ecfa7a31002fa1de2a9d91621fd895da8493d" integrity sha512-KtLMbmicyuK2Ak/FTCJVbDnkN1SlT8/kceFTiuDiiRUUSMnHMidxSCdG4ndkTOHHpoomWe/4xkvHkEOncwjYIw== @@ -53,6 +61,16 @@ "@jridgewell/trace-mapping" "^0.3.17" jsesc "^2.5.1" +"@babel/generator@^7.23.6": + version "7.23.6" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.6.tgz#9e1fca4811c77a10580d17d26b57b036133f3c2e" + integrity sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw== + dependencies: + "@babel/types" "^7.23.6" + "@jridgewell/gen-mapping" "^0.3.2" + "@jridgewell/trace-mapping" "^0.3.17" + jsesc "^2.5.1" + "@babel/helper-annotate-as-pure@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz#e7f06737b197d580a01edf75d97e2c8be99d3882" @@ -127,6 +145,11 @@ lodash.debounce "^4.0.8" resolve "^1.14.2" +"@babel/helper-environment-visitor@^7.22.20": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167" + integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA== + "@babel/helper-environment-visitor@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz#f06dd41b7c1f44e1f8da6c4055b41ab3a09a7e98" @@ -140,6 +163,14 @@ "@babel/template" "^7.22.5" "@babel/types" "^7.22.5" +"@babel/helper-function-name@^7.23.0": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759" + integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw== + dependencies: + "@babel/template" "^7.22.15" + "@babel/types" "^7.23.0" + "@babel/helper-hoist-variables@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb" @@ -228,6 +259,16 @@ resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz#533f36457a25814cf1df6488523ad547d784a99f" integrity sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw== +"@babel/helper-string-parser@^7.23.4": + version "7.23.4" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz#9478c707febcbbe1ddb38a3d91a2e054ae622d83" + integrity sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ== + +"@babel/helper-validator-identifier@^7.22.20": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0" + integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== + "@babel/helper-validator-identifier@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz#9544ef6a33999343c8740fa51350f30eeaaaf193" @@ -265,11 +306,25 @@ chalk "^2.0.0" js-tokens "^4.0.0" +"@babel/highlight@^7.23.4": + version "7.23.4" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.23.4.tgz#edaadf4d8232e1a961432db785091207ead0621b" + integrity sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A== + dependencies: + "@babel/helper-validator-identifier" "^7.22.20" + chalk "^2.4.2" + js-tokens "^4.0.0" + "@babel/parser@^7.1.0", "@babel/parser@^7.11.5", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.22.5", "@babel/parser@^7.22.7", "@babel/parser@^7.7.0": version "7.22.7" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.22.7.tgz#df8cf085ce92ddbdbf668a7f186ce848c9036cae" integrity sha512-7NF8pOkHP5o2vpmGgNGcfAeCvOYhGLyA3Z4eBQkT1RJlWu47n63bCs93QfJ2hIAFCil7L5P2IWhs1oToVgrL0Q== +"@babel/parser@^7.23.9": + version "7.23.9" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.9.tgz#7b903b6149b0f8fa7ad564af646c4c38a77fc44b" + integrity sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA== + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.22.5.tgz#87245a21cd69a73b0b81bcda98d443d6df08f05e" @@ -938,6 +993,15 @@ dependencies: regenerator-runtime "^0.13.11" +"@babel/template@^7.22.15": + version "7.23.9" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.23.9.tgz#f881d0487cba2828d3259dcb9ef5005a9731011a" + integrity sha512-+xrD2BWLpvHKNmX2QbpdpsBaWnRxahMwJjO+KZk2JOElj5nSmKezyS1B4u+QbHMTX69t4ukm6hh9lsYQ7GHCKA== + dependencies: + "@babel/code-frame" "^7.23.5" + "@babel/parser" "^7.23.9" + "@babel/types" "^7.23.9" + "@babel/template@^7.22.5", "@babel/template@^7.3.3": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.5.tgz#0c8c4d944509875849bd0344ff0050756eefc6ec" @@ -948,19 +1012,19 @@ "@babel/types" "^7.22.5" "@babel/traverse@^7.1.0", "@babel/traverse@^7.11.5", "@babel/traverse@^7.22.6", "@babel/traverse@^7.22.8", "@babel/traverse@^7.7.0": - version "7.22.8" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.22.8.tgz#4d4451d31bc34efeae01eac222b514a77aa4000e" - integrity sha512-y6LPR+wpM2I3qJrsheCTwhIinzkETbplIgPBbwvqPKc+uljeA5gP+3nP8irdYt1mjQaDnlIcG+dw8OjAco4GXw== - dependencies: - "@babel/code-frame" "^7.22.5" - "@babel/generator" "^7.22.7" - "@babel/helper-environment-visitor" "^7.22.5" - "@babel/helper-function-name" "^7.22.5" + version "7.23.9" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.9.tgz#2f9d6aead6b564669394c5ce0f9302bb65b9d950" + integrity sha512-I/4UJ9vs90OkBtY6iiiTORVMyIhJ4kAVmsKo9KFc8UOxMeUfi2hvtIBsET5u9GizXE6/GFSuKCTNfgCswuEjRg== + dependencies: + "@babel/code-frame" "^7.23.5" + "@babel/generator" "^7.23.6" + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-function-name" "^7.23.0" "@babel/helper-hoist-variables" "^7.22.5" "@babel/helper-split-export-declaration" "^7.22.6" - "@babel/parser" "^7.22.7" - "@babel/types" "^7.22.5" - debug "^4.1.0" + "@babel/parser" "^7.23.9" + "@babel/types" "^7.23.9" + debug "^4.3.1" globals "^11.1.0" "@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.22.5", "@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.7.0": @@ -972,6 +1036,15 @@ "@babel/helper-validator-identifier" "^7.22.5" to-fast-properties "^2.0.0" +"@babel/types@^7.23.0", "@babel/types@^7.23.6", "@babel/types@^7.23.9": + version "7.23.9" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.9.tgz#1dd7b59a9a2b5c87f8b41e52770b5ecbf492e002" + integrity sha512-dQjSq/7HaSjRM43FFGnv5keM2HsxpmyV1PfaSVm0nzzjwwTmjOe6J4bC8e3+pTEIgHaHj+1ZlLThRJ2auc/w1Q== + dependencies: + "@babel/helper-string-parser" "^7.23.4" + "@babel/helper-validator-identifier" "^7.22.20" + to-fast-properties "^2.0.0" + "@bcoe/v8-coverage@^0.2.3": version "0.2.3" resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" @@ -2756,7 +2829,7 @@ debug@^3.2.7: dependencies: ms "^2.1.1" -debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: +debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== diff --git a/src/plugins/docusaurus-plugin-navdata/yarn.lock b/src/plugins/docusaurus-plugin-navdata/yarn.lock index e098e23e79..d44ec0682e 100644 --- a/src/plugins/docusaurus-plugin-navdata/yarn.lock +++ b/src/plugins/docusaurus-plugin-navdata/yarn.lock @@ -17,6 +17,14 @@ dependencies: "@babel/highlight" "^7.22.5" +"@babel/code-frame@^7.23.5": + version "7.23.5" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.23.5.tgz#9009b69a8c602293476ad598ff53e4562e15c244" + integrity sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA== + dependencies: + "@babel/highlight" "^7.23.4" + chalk "^2.4.2" + "@babel/compat-data@^7.22.5", "@babel/compat-data@^7.22.6", "@babel/compat-data@^7.22.9": version "7.22.9" resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.22.9.tgz#71cdb00a1ce3a329ce4cbec3a44f9fef35669730" @@ -43,7 +51,7 @@ json5 "^2.2.2" semver "^6.3.1" -"@babel/generator@^7.22.7", "@babel/generator@^7.22.9": +"@babel/generator@^7.22.9": version "7.22.9" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.22.9.tgz#572ecfa7a31002fa1de2a9d91621fd895da8493d" integrity sha512-KtLMbmicyuK2Ak/FTCJVbDnkN1SlT8/kceFTiuDiiRUUSMnHMidxSCdG4ndkTOHHpoomWe/4xkvHkEOncwjYIw== @@ -53,6 +61,16 @@ "@jridgewell/trace-mapping" "^0.3.17" jsesc "^2.5.1" +"@babel/generator@^7.23.6": + version "7.23.6" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.6.tgz#9e1fca4811c77a10580d17d26b57b036133f3c2e" + integrity sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw== + dependencies: + "@babel/types" "^7.23.6" + "@jridgewell/gen-mapping" "^0.3.2" + "@jridgewell/trace-mapping" "^0.3.17" + jsesc "^2.5.1" + "@babel/helper-annotate-as-pure@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz#e7f06737b197d580a01edf75d97e2c8be99d3882" @@ -127,6 +145,11 @@ lodash.debounce "^4.0.8" resolve "^1.14.2" +"@babel/helper-environment-visitor@^7.22.20": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167" + integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA== + "@babel/helper-environment-visitor@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz#f06dd41b7c1f44e1f8da6c4055b41ab3a09a7e98" @@ -140,6 +163,14 @@ "@babel/template" "^7.22.5" "@babel/types" "^7.22.5" +"@babel/helper-function-name@^7.23.0": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759" + integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw== + dependencies: + "@babel/template" "^7.22.15" + "@babel/types" "^7.23.0" + "@babel/helper-hoist-variables@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb" @@ -228,6 +259,16 @@ resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz#533f36457a25814cf1df6488523ad547d784a99f" integrity sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw== +"@babel/helper-string-parser@^7.23.4": + version "7.23.4" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz#9478c707febcbbe1ddb38a3d91a2e054ae622d83" + integrity sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ== + +"@babel/helper-validator-identifier@^7.22.20": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0" + integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== + "@babel/helper-validator-identifier@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz#9544ef6a33999343c8740fa51350f30eeaaaf193" @@ -265,11 +306,25 @@ chalk "^2.0.0" js-tokens "^4.0.0" +"@babel/highlight@^7.23.4": + version "7.23.4" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.23.4.tgz#edaadf4d8232e1a961432db785091207ead0621b" + integrity sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A== + dependencies: + "@babel/helper-validator-identifier" "^7.22.20" + chalk "^2.4.2" + js-tokens "^4.0.0" + "@babel/parser@^7.1.0", "@babel/parser@^7.11.5", "@babel/parser@^7.14.7", "@babel/parser@^7.20.7", "@babel/parser@^7.22.5", "@babel/parser@^7.22.7", "@babel/parser@^7.7.0": version "7.22.7" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.22.7.tgz#df8cf085ce92ddbdbf668a7f186ce848c9036cae" integrity sha512-7NF8pOkHP5o2vpmGgNGcfAeCvOYhGLyA3Z4eBQkT1RJlWu47n63bCs93QfJ2hIAFCil7L5P2IWhs1oToVgrL0Q== +"@babel/parser@^7.23.9": + version "7.23.9" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.9.tgz#7b903b6149b0f8fa7ad564af646c4c38a77fc44b" + integrity sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA== + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.22.5.tgz#87245a21cd69a73b0b81bcda98d443d6df08f05e" @@ -938,6 +993,15 @@ dependencies: regenerator-runtime "^0.13.11" +"@babel/template@^7.22.15": + version "7.23.9" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.23.9.tgz#f881d0487cba2828d3259dcb9ef5005a9731011a" + integrity sha512-+xrD2BWLpvHKNmX2QbpdpsBaWnRxahMwJjO+KZk2JOElj5nSmKezyS1B4u+QbHMTX69t4ukm6hh9lsYQ7GHCKA== + dependencies: + "@babel/code-frame" "^7.23.5" + "@babel/parser" "^7.23.9" + "@babel/types" "^7.23.9" + "@babel/template@^7.22.5", "@babel/template@^7.3.3": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.22.5.tgz#0c8c4d944509875849bd0344ff0050756eefc6ec" @@ -948,19 +1012,19 @@ "@babel/types" "^7.22.5" "@babel/traverse@^7.1.0", "@babel/traverse@^7.11.5", "@babel/traverse@^7.22.6", "@babel/traverse@^7.22.8", "@babel/traverse@^7.7.0": - version "7.22.8" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.22.8.tgz#4d4451d31bc34efeae01eac222b514a77aa4000e" - integrity sha512-y6LPR+wpM2I3qJrsheCTwhIinzkETbplIgPBbwvqPKc+uljeA5gP+3nP8irdYt1mjQaDnlIcG+dw8OjAco4GXw== - dependencies: - "@babel/code-frame" "^7.22.5" - "@babel/generator" "^7.22.7" - "@babel/helper-environment-visitor" "^7.22.5" - "@babel/helper-function-name" "^7.22.5" + version "7.23.9" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.9.tgz#2f9d6aead6b564669394c5ce0f9302bb65b9d950" + integrity sha512-I/4UJ9vs90OkBtY6iiiTORVMyIhJ4kAVmsKo9KFc8UOxMeUfi2hvtIBsET5u9GizXE6/GFSuKCTNfgCswuEjRg== + dependencies: + "@babel/code-frame" "^7.23.5" + "@babel/generator" "^7.23.6" + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-function-name" "^7.23.0" "@babel/helper-hoist-variables" "^7.22.5" "@babel/helper-split-export-declaration" "^7.22.6" - "@babel/parser" "^7.22.7" - "@babel/types" "^7.22.5" - debug "^4.1.0" + "@babel/parser" "^7.23.9" + "@babel/types" "^7.23.9" + debug "^4.3.1" globals "^11.1.0" "@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.22.5", "@babel/types@^7.3.3", "@babel/types@^7.4.4", "@babel/types@^7.7.0": @@ -972,6 +1036,15 @@ "@babel/helper-validator-identifier" "^7.22.5" to-fast-properties "^2.0.0" +"@babel/types@^7.23.0", "@babel/types@^7.23.6", "@babel/types@^7.23.9": + version "7.23.9" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.9.tgz#1dd7b59a9a2b5c87f8b41e52770b5ecbf492e002" + integrity sha512-dQjSq/7HaSjRM43FFGnv5keM2HsxpmyV1PfaSVm0nzzjwwTmjOe6J4bC8e3+pTEIgHaHj+1ZlLThRJ2auc/w1Q== + dependencies: + "@babel/helper-string-parser" "^7.23.4" + "@babel/helper-validator-identifier" "^7.22.20" + to-fast-properties "^2.0.0" + "@bcoe/v8-coverage@^0.2.3": version "0.2.3" resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" @@ -2763,7 +2836,7 @@ debug@^3.2.7: dependencies: ms "^2.1.1" -debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: +debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== diff --git a/static/image/tutorials/cep-78/the-nft-contract-hash.png b/static/image/tutorials/cep-78/the-nft-contract-hash.png new file mode 100644 index 0000000000..8130d8b425 Binary files /dev/null and b/static/image/tutorials/cep-78/the-nft-contract-hash.png differ diff --git a/yarn.lock b/yarn.lock index b6d8a79462..a1c4379c5a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -241,6 +241,14 @@ dependencies: "@babel/highlight" "^7.22.5" +"@babel/code-frame@^7.23.5": + version "7.23.5" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.23.5.tgz#9009b69a8c602293476ad598ff53e4562e15c244" + integrity sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA== + dependencies: + "@babel/highlight" "^7.23.4" + chalk "^2.4.2" + "@babel/compat-data@^7.22.5", "@babel/compat-data@^7.22.6", "@babel/compat-data@^7.22.9": version "7.22.9" resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.22.9.tgz#71cdb00a1ce3a329ce4cbec3a44f9fef35669730" @@ -289,7 +297,7 @@ json5 "^2.2.2" semver "^6.3.1" -"@babel/generator@^7.12.5", "@babel/generator@^7.18.7", "@babel/generator@^7.22.7", "@babel/generator@^7.22.9": +"@babel/generator@^7.12.5", "@babel/generator@^7.18.7", "@babel/generator@^7.22.9": version "7.22.9" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.22.9.tgz#572ecfa7a31002fa1de2a9d91621fd895da8493d" integrity sha512-KtLMbmicyuK2Ak/FTCJVbDnkN1SlT8/kceFTiuDiiRUUSMnHMidxSCdG4ndkTOHHpoomWe/4xkvHkEOncwjYIw== @@ -299,6 +307,16 @@ "@jridgewell/trace-mapping" "^0.3.17" jsesc "^2.5.1" +"@babel/generator@^7.23.6": + version "7.23.6" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.23.6.tgz#9e1fca4811c77a10580d17d26b57b036133f3c2e" + integrity sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw== + dependencies: + "@babel/types" "^7.23.6" + "@jridgewell/gen-mapping" "^0.3.2" + "@jridgewell/trace-mapping" "^0.3.17" + jsesc "^2.5.1" + "@babel/helper-annotate-as-pure@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz#e7f06737b197d580a01edf75d97e2c8be99d3882" @@ -359,6 +377,11 @@ lodash.debounce "^4.0.8" resolve "^1.14.2" +"@babel/helper-environment-visitor@^7.22.20": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz#96159db61d34a29dba454c959f5ae4a649ba9167" + integrity sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA== + "@babel/helper-environment-visitor@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.5.tgz#f06dd41b7c1f44e1f8da6c4055b41ab3a09a7e98" @@ -372,6 +395,14 @@ "@babel/template" "^7.22.5" "@babel/types" "^7.22.5" +"@babel/helper-function-name@^7.23.0": + version "7.23.0" + resolved "https://registry.yarnpkg.com/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz#1f9a3cdbd5b2698a670c30d2735f9af95ed52759" + integrity sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw== + dependencies: + "@babel/template" "^7.22.15" + "@babel/types" "^7.23.0" + "@babel/helper-hoist-variables@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz#c01a007dac05c085914e8fb652b339db50d823bb" @@ -465,6 +496,16 @@ resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz#533f36457a25814cf1df6488523ad547d784a99f" integrity sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw== +"@babel/helper-string-parser@^7.23.4": + version "7.23.4" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz#9478c707febcbbe1ddb38a3d91a2e054ae622d83" + integrity sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ== + +"@babel/helper-validator-identifier@^7.22.20": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0" + integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== + "@babel/helper-validator-identifier@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.5.tgz#9544ef6a33999343c8740fa51350f30eeaaaf193" @@ -502,11 +543,25 @@ chalk "^2.0.0" js-tokens "^4.0.0" +"@babel/highlight@^7.23.4": + version "7.23.4" + resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.23.4.tgz#edaadf4d8232e1a961432db785091207ead0621b" + integrity sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A== + dependencies: + "@babel/helper-validator-identifier" "^7.22.20" + chalk "^2.4.2" + js-tokens "^4.0.0" + "@babel/parser@^7.12.7", "@babel/parser@^7.18.8", "@babel/parser@^7.22.5", "@babel/parser@^7.22.7": version "7.22.7" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.22.7.tgz#df8cf085ce92ddbdbf668a7f186ce848c9036cae" integrity sha512-7NF8pOkHP5o2vpmGgNGcfAeCvOYhGLyA3Z4eBQkT1RJlWu47n63bCs93QfJ2hIAFCil7L5P2IWhs1oToVgrL0Q== +"@babel/parser@^7.23.9": + version "7.23.9" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.9.tgz#7b903b6149b0f8fa7ad564af646c4c38a77fc44b" + integrity sha512-9tcKgqKbs3xGJ+NtKF2ndOBBLVwPjl1SHxPQkd36r3Dlirw3xWUeGaTbqr7uGZcTaxkVNwc+03SVP7aCdWrTlA== + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@^7.22.5": version "7.22.5" resolved "https://registry.yarnpkg.com/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.22.5.tgz#87245a21cd69a73b0b81bcda98d443d6df08f05e" @@ -1292,20 +1347,29 @@ "@babel/parser" "^7.22.5" "@babel/types" "^7.22.5" -"@babel/traverse@^7.12.9", "@babel/traverse@^7.18.8", "@babel/traverse@^7.22.6", "@babel/traverse@^7.22.8": - version "7.22.8" - resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.22.8.tgz#4d4451d31bc34efeae01eac222b514a77aa4000e" - integrity sha512-y6LPR+wpM2I3qJrsheCTwhIinzkETbplIgPBbwvqPKc+uljeA5gP+3nP8irdYt1mjQaDnlIcG+dw8OjAco4GXw== +"@babel/template@^7.22.15": + version "7.23.9" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.23.9.tgz#f881d0487cba2828d3259dcb9ef5005a9731011a" + integrity sha512-+xrD2BWLpvHKNmX2QbpdpsBaWnRxahMwJjO+KZk2JOElj5nSmKezyS1B4u+QbHMTX69t4ukm6hh9lsYQ7GHCKA== dependencies: - "@babel/code-frame" "^7.22.5" - "@babel/generator" "^7.22.7" - "@babel/helper-environment-visitor" "^7.22.5" - "@babel/helper-function-name" "^7.22.5" + "@babel/code-frame" "^7.23.5" + "@babel/parser" "^7.23.9" + "@babel/types" "^7.23.9" + +"@babel/traverse@^7.12.9", "@babel/traverse@^7.18.8", "@babel/traverse@^7.22.6", "@babel/traverse@^7.22.8": + version "7.23.9" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.23.9.tgz#2f9d6aead6b564669394c5ce0f9302bb65b9d950" + integrity sha512-I/4UJ9vs90OkBtY6iiiTORVMyIhJ4kAVmsKo9KFc8UOxMeUfi2hvtIBsET5u9GizXE6/GFSuKCTNfgCswuEjRg== + dependencies: + "@babel/code-frame" "^7.23.5" + "@babel/generator" "^7.23.6" + "@babel/helper-environment-visitor" "^7.22.20" + "@babel/helper-function-name" "^7.23.0" "@babel/helper-hoist-variables" "^7.22.5" "@babel/helper-split-export-declaration" "^7.22.6" - "@babel/parser" "^7.22.7" - "@babel/types" "^7.22.5" - debug "^4.1.0" + "@babel/parser" "^7.23.9" + "@babel/types" "^7.23.9" + debug "^4.3.1" globals "^11.1.0" "@babel/types@^7.12.6", "@babel/types@^7.12.7", "@babel/types@^7.20.0", "@babel/types@^7.22.5", "@babel/types@^7.4.4": @@ -1317,6 +1381,15 @@ "@babel/helper-validator-identifier" "^7.22.5" to-fast-properties "^2.0.0" +"@babel/types@^7.23.0", "@babel/types@^7.23.6", "@babel/types@^7.23.9": + version "7.23.9" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.9.tgz#1dd7b59a9a2b5c87f8b41e52770b5ecbf492e002" + integrity sha512-dQjSq/7HaSjRM43FFGnv5keM2HsxpmyV1PfaSVm0nzzjwwTmjOe6J4bC8e3+pTEIgHaHj+1ZlLThRJ2auc/w1Q== + dependencies: + "@babel/helper-string-parser" "^7.23.4" + "@babel/helper-validator-identifier" "^7.22.20" + to-fast-properties "^2.0.0" + "@cmfcmf/docusaurus-search-local@^0.10.0": version "0.10.0" resolved "https://registry.yarnpkg.com/@cmfcmf/docusaurus-search-local/-/docusaurus-search-local-0.10.0.tgz#0a77847641ec490f4663666e5eee07416f5a0c63" @@ -3733,7 +3806,7 @@ chalk@^1.0.0, chalk@^1.1.1, chalk@^1.1.3: strip-ansi "^3.0.0" supports-color "^2.0.0" -chalk@^2.0.0, chalk@^2.0.1, chalk@^2.4.1: +chalk@^2.0.0, chalk@^2.0.1, chalk@^2.4.1, chalk@^2.4.2: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== @@ -5590,9 +5663,9 @@ fn-name@^2.0.1: integrity sha512-oIDB1rXf3BUnn00bh2jVM0byuqr94rBh6g7ZfdKcbmp1we2GQtPzKdloyvBXHs+q3fvxB8EqX5ecFba3RwCSjA== follow-redirects@^1.0.0, follow-redirects@^1.14.7: - version "1.15.2" - resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.2.tgz#b460864144ba63f2681096f274c4e57026da2c13" - integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA== + version "1.15.5" + resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.5.tgz#54d4d6d062c0fa7d9d17feb008461550e3ba8020" + integrity sha512-vSFWUON1B+yAw1VN4xMfxgn5fTUiaOzAJCKBwIIgT/+7CuGy9+r+5gITvP62j3RmaD5Ph65UaERdOSRGUzZtgw== for-each@^0.3.3: version "0.3.3"