From 04a909294f39178e0cd64eea556312d48e2f19bb Mon Sep 17 00:00:00 2001 From: danielailie Date: Thu, 5 Jun 2025 14:58:25 +0300 Subject: [PATCH 1/3] Move mxpy to own directory --- docs/developers/data/code-metadata.md | 2 +- docs/developers/reproducible-contract-builds.md | 6 +++--- docs/developers/sc-calls-format.md | 2 +- docs/developers/setup-local-testnet.md | 2 +- .../sdk-and-tools/{sdk-py => mxpy}/installing-mxpy.md | 0 docs/sdk-and-tools/{sdk-py => mxpy}/mxpy-cli.md | 0 .../{sdk-py => mxpy}/smart-contract-interactions.md | 2 +- docs/sdk-and-tools/overview.md | 6 ++---- docs/sdk-and-tools/sdk-py/sdk-py-cookbook-v1.md | 2 +- docs/sovereign/software-dependencies.md | 2 +- docs/validators/staking/staking.md | 2 +- docs/validators/staking/unjailing.md | 4 ++-- docusaurus.config.js | 8 ++++++-- sidebars.js | 11 ++++++++--- 14 files changed, 28 insertions(+), 21 deletions(-) rename docs/sdk-and-tools/{sdk-py => mxpy}/installing-mxpy.md (100%) rename docs/sdk-and-tools/{sdk-py => mxpy}/mxpy-cli.md (100%) rename docs/sdk-and-tools/{sdk-py => mxpy}/smart-contract-interactions.md (98%) diff --git a/docs/developers/data/code-metadata.md b/docs/developers/data/code-metadata.md index cb17e8a4f..1bd5a042d 100644 --- a/docs/developers/data/code-metadata.md +++ b/docs/developers/data/code-metadata.md @@ -31,7 +31,7 @@ When deploying (or upgrading) a smart contract using **mxpy**, its default _code - `--metadata-payable` - mark the contract as `payable` - `--metadata-payable-by-sc` - mark the contract as `payable by smart contracts` -For more information, please follow [mxpy CLI](/sdk-and-tools/sdk-py/mxpy-cli). +For more information, please follow [mxpy CLI](/sdk-and-tools/mxpy/mxpy-cli). [comment]: # (mx-context-auto) diff --git a/docs/developers/reproducible-contract-builds.md b/docs/developers/reproducible-contract-builds.md index 8c79b57c3..0fba270dc 100644 --- a/docs/developers/reproducible-contract-builds.md +++ b/docs/developers/reproducible-contract-builds.md @@ -174,7 +174,7 @@ A more straightforward alternative to the previous bash script is to use **mxpy* First, make sure you have the: -- latest [mxpy](/sdk-and-tools/sdk-py/installing-mxpy) installed, +- latest [mxpy](/sdk-and-tools/mxpy/installing-mxpy) installed, - latest [docker engine](https://docs.docker.com/engine/install/) installed. Then, use the `reproducible-build` command (below, the image tag is just an example): @@ -227,11 +227,11 @@ Please note that as a **Beta** feature still in development, certain steps descr ::: :::tip -Make sure that you have the latest `mxpy` installed. In order to install mxpy, follow the instructions at [install mxpy](/sdk-and-tools/sdk-py/installing-mxpy). +Make sure that you have the latest `mxpy` installed. In order to install mxpy, follow the instructions at [install mxpy](/sdk-and-tools/mxpy/installing-mxpy). ::: 1. The contract must be deterministically built as described [above](/developers/reproducible-contract-builds#building-via-docker-reproducible-build). -2. To start with the verification process, we need to first deploy the smart contract. For deploying contracts have a look [here](/sdk-and-tools/sdk-py/smart-contract-interactions/#deploy--upgrade). +2. To start with the verification process, we need to first deploy the smart contract. For deploying contracts have a look [here](/sdk-and-tools/mxpy/mxpy-cli#deploying-a-smart-contract). 3. Upon deploying, the output will not only provide information such as the transaction hash and data, but also the address of the newly deployed contract. 4. In order to verify your contract the command you have to use is (below, the image tag is just an example): diff --git a/docs/developers/sc-calls-format.md b/docs/developers/sc-calls-format.md index 860c5b176..288bc16ef 100644 --- a/docs/developers/sc-calls-format.md +++ b/docs/developers/sc-calls-format.md @@ -128,7 +128,7 @@ There are multiple tools that one can use in order to convert an address into he ### Converting addresses using mxpy -Make sure you have `mxpy` [installed](/sdk-and-tools/sdk-py/installing-mxpy). +Make sure you have `mxpy` [installed](/sdk-and-tools/mxpy/installing-mxpy). ```bash mxpy wallet bech32 --decode erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th diff --git a/docs/developers/setup-local-testnet.md b/docs/developers/setup-local-testnet.md index f8b4a7486..cb262b7e8 100644 --- a/docs/developers/setup-local-testnet.md +++ b/docs/developers/setup-local-testnet.md @@ -19,7 +19,7 @@ If not specified otherwise, the localnet starts with two shards plus the metacha ## Prerequisites: mxpy -In order to install **mxpy**, follow [these instructions](/sdk-and-tools/sdk-py/installing-mxpy). +In order to install **mxpy**, follow [these instructions](/sdk-and-tools/mxpy/installing-mxpy). :::note This guide assumes you are using `mxpy v9.7.1` or newer. diff --git a/docs/sdk-and-tools/sdk-py/installing-mxpy.md b/docs/sdk-and-tools/mxpy/installing-mxpy.md similarity index 100% rename from docs/sdk-and-tools/sdk-py/installing-mxpy.md rename to docs/sdk-and-tools/mxpy/installing-mxpy.md diff --git a/docs/sdk-and-tools/sdk-py/mxpy-cli.md b/docs/sdk-and-tools/mxpy/mxpy-cli.md similarity index 100% rename from docs/sdk-and-tools/sdk-py/mxpy-cli.md rename to docs/sdk-and-tools/mxpy/mxpy-cli.md diff --git a/docs/sdk-and-tools/sdk-py/smart-contract-interactions.md b/docs/sdk-and-tools/mxpy/smart-contract-interactions.md similarity index 98% rename from docs/sdk-and-tools/sdk-py/smart-contract-interactions.md rename to docs/sdk-and-tools/mxpy/smart-contract-interactions.md index 3b9e1c1f3..7c0eecc73 100644 --- a/docs/sdk-and-tools/sdk-py/smart-contract-interactions.md +++ b/docs/sdk-and-tools/mxpy/smart-contract-interactions.md @@ -28,7 +28,7 @@ Let's take the following example: ### mxpy -We're going to use [**mxpy**](/sdk-and-tools/sdk-py/mxpy-cli) to deploy the contract. Follow the installation guide [here](/sdk-and-tools/sdk-py/installing-mxpy) - make sure to use the latest version available. +We're going to use [**mxpy**](/sdk-and-tools/mxpy/mxpy-cli) to deploy the contract. Follow the installation guide [here](/sdk-and-tools/mxpy/installing-mxpy) - make sure to use the latest version available. [comment]: # (mx-context-auto) diff --git a/docs/sdk-and-tools/overview.md b/docs/sdk-and-tools/overview.md index 2dd8a47cb..49d8a176b 100644 --- a/docs/sdk-and-tools/overview.md +++ b/docs/sdk-and-tools/overview.md @@ -65,10 +65,8 @@ You might also want to have a look over [**xSuite**](https://xsuite.dev), a tool | Name | Description | | -------------------------------------------------------------------------------- | ----------------------------------------- | -| [mxpy](/sdk-and-tools/sdk-py/) | High level overview about mxpy. | -| [Installing mxpy](/sdk-and-tools/sdk-py/installing-mxpy) | How to install and get started with mxpy. | -| [mxpy cli](/sdk-and-tools/sdk-py/mxpy-cli) | How to use the Command Line Interface. | -| [Smart contract interactions](/sdk-and-tools/sdk-py/smart-contract-interactions) | Interact with Smart Contract. | +| [Installing mxpy](/sdk-and-tools/mxpy/installing-mxpy) | How to install and get started with mxpy. | +| [mxpy cli](/sdk-and-tools/mxpy/mxpy-cli) | How to use the Command Line Interface. | [comment]: # (mx-context-auto) diff --git a/docs/sdk-and-tools/sdk-py/sdk-py-cookbook-v1.md b/docs/sdk-and-tools/sdk-py/sdk-py-cookbook-v1.md index 453ef5904..aab2d5de1 100644 --- a/docs/sdk-and-tools/sdk-py/sdk-py-cookbook-v1.md +++ b/docs/sdk-and-tools/sdk-py/sdk-py-cookbook-v1.md @@ -2,7 +2,7 @@ id: sdk-py-cookbook title: Cookbook (v1) pagination_prev: sdk-and-tools/sdk-py/sdk-py-cookbook-v0 -pagination_next: sdk-and-tools/sdk-py/installing-mxpy +pagination_next: sdk-and-tools/mxpy/installing-mxpy --- [comment]: # (mx-abstract) diff --git a/docs/sovereign/software-dependencies.md b/docs/sovereign/software-dependencies.md index 8e996286a..2ee16ac24 100644 --- a/docs/sovereign/software-dependencies.md +++ b/docs/sovereign/software-dependencies.md @@ -28,7 +28,7 @@ sudo pipx ensurepath --global ### mxpy -Ensure you are using the latest version of mxpy. Follow the installation or upgrade instructions provided [here](/sdk-and-tools/sdk-py/installing-mxpy#install-using-pipx) if you haven't done so already. +Ensure you are using the latest version of mxpy. Follow the installation or upgrade instructions provided [here](/sdk-and-tools/mxpy/installing-mxpy#install-using-pipx) if you haven't done so already. ### multiversx-sdk diff --git a/docs/validators/staking/staking.md b/docs/validators/staking/staking.md index 4f1fed8f9..cfd34a9ce 100644 --- a/docs/validators/staking/staking.md +++ b/docs/validators/staking/staking.md @@ -82,7 +82,7 @@ Make sure `mxpy` is installed by issuing this command on a terminal: mxpy --version ``` -If `mxpy` is not installed (`command not found`), please follow [these instructions](/sdk-and-tools/sdk-py/installing-mxpy). +If `mxpy` is not installed (`command not found`), please follow [these instructions](/sdk-and-tools/mxpy/installing-mxpy). Make sure `mxpy` is installed and has the latest version before continuing. diff --git a/docs/validators/staking/unjailing.md b/docs/validators/staking/unjailing.md index 70ab1cf17..600626c37 100644 --- a/docs/validators/staking/unjailing.md +++ b/docs/validators/staking/unjailing.md @@ -125,7 +125,7 @@ unJail@@@…@ Submitting the unjailing transaction using `mxpy` avoids having to write the "Data" field manually. Instead, the transaction is constructed automatically by `mxpy` and submitted to the network directly, in a single command. -Make sure `mxpy` is installed and has the latest version before continuing. If `mxpy` is not installed, please follow [these instructions](/sdk-and-tools/sdk-py/installing-mxpy). +Make sure `mxpy` is installed and has the latest version before continuing. If `mxpy` is not installed, please follow [these instructions](/sdk-and-tools/mxpy/installing-mxpy). [comment]: # (mx-context-auto) @@ -133,7 +133,7 @@ Make sure `mxpy` is installed and has the latest version before continuing. If ` To send transactions on your behalf _without_ using the online MultiversX Wallet, `mxpy` must be able to sign for you. For this reason, you have to generate a PEM file using your Wallet mnemonic. -Please follow the guide [Deriving the Wallet PEM file](/sdk-and-tools/sdk-py/mxpy-cli). Make sure you know exactly where the PEM file was generated, because you'll need to reference its path in the `mxpy` commands. +Please follow the guide [Deriving the Wallet PEM file](/sdk-and-tools/mxpy/mxpy-cli). Make sure you know exactly where the PEM file was generated, because you'll need to reference its path in the `mxpy` commands. After the PEM file was generated, you can issue transactions from `mxpy`directly. diff --git a/docusaurus.config.js b/docusaurus.config.js index 5ca444ae6..dcfd25215 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -420,11 +420,15 @@ const config = { }, { from: "/sdk-and-tools/sdk-py/configuring-mxpy", - to: "/sdk-and-tools/sdk-py/mxpy-cli", + to: "/sdk-and-tools/mxpy/mxpy-cli", + }, + { + from: "/sdk-and-tools/sdk-py/mxpy-cli", + to: "/sdk-and-tools/mxpy/mxpy-cli", }, { from: "/sdk-and-tools/sdk-py/deriving-the-wallet-pem-file", - to: "/sdk-and-tools/sdk-py/mxpy-cli", + to: "/sdk-and-tools/mxpy/mxpy-cli", }, { from: "/developers/log-events/esdt-events", diff --git a/sidebars.js b/sidebars.js index d73247cfa..f94ef4612 100644 --- a/sidebars.js +++ b/sidebars.js @@ -211,9 +211,14 @@ const sidebars = { "sdk-and-tools/sdk-py/sdk-py-cookbook", ] }, - "sdk-and-tools/sdk-py/installing-mxpy", - "sdk-and-tools/sdk-py/mxpy-cli", - "sdk-and-tools/sdk-py/smart-contract-interactions", + ], + }, + { + type: "category", + label: "Mxpy CLI", + items: [ + "sdk-and-tools/mxpy/installing-mxpy", + "sdk-and-tools/mxpy/mxpy-cli", ], }, { From a9c4833f06a2089a337bc607d2c6378189cb4cd0 Mon Sep 17 00:00:00 2001 From: danielailie Date: Thu, 5 Jun 2025 15:18:42 +0300 Subject: [PATCH 2/3] Fix mxpy redirect --- docs/developers/relayed-transactions.md | 2 +- docs/validators/staking/staking.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/developers/relayed-transactions.md b/docs/developers/relayed-transactions.md index cac9f3910..757cadb22 100644 --- a/docs/developers/relayed-transactions.md +++ b/docs/developers/relayed-transactions.md @@ -114,7 +114,7 @@ Here's an example of a relayed v3 transaction. Its intent is to call the `add` m ### Preparing relayed transactions using the SDKs The SDKs have built-in support for relayed transactions. Please follow: - - [mxpy support](/sdk-and-tools/sdk-py/mxpy-cli/#relayed-transactions-v3) + - [mxpy support](/sdk-and-tools/mxpy/mxpy-cli/#relayed-transactions-v3) - [sdk-py support](/sdk-and-tools/sdk-py/sdk-py-cookbook/#relayed-transactions) - [sdk-js v14 support](/sdk-and-tools/sdk-js/sdk-js-cookbook#relayed-transactions) - [sdk-js v13 support (legacy)](/sdk-and-tools/sdk-js/sdk-js-cookbook-v13#preparing-a-relayed-transaction) diff --git a/docs/validators/staking/staking.md b/docs/validators/staking/staking.md index cfd34a9ce..2b5fb40fd 100644 --- a/docs/validators/staking/staking.md +++ b/docs/validators/staking/staking.md @@ -92,7 +92,7 @@ Make sure `mxpy` is installed and has the latest version before continuing. To send transactions on your behalf _without_ using the online MultiversX Wallet, `mxpy` must be able to sign for you. For this reason, you have to generate a PEM file using your Wallet mnemonic. -Please follow the guide [Deriving the Wallet PEM file](/sdk-and-tools/sdk-py/mxpy-cli#converting-a-wallet). Make sure you know exactly where the PEM file was generated, because you'll need to reference its path in the `mxpy` commands. +Please follow the guide [Deriving the Wallet PEM file](/sdk-and-tools/mxpy/mxpy-cli#converting-a-wallet). Make sure you know exactly where the PEM file was generated, because you'll need to reference its path in the `mxpy` commands. After the PEM file was generated, you can issue transactions from `mxpy` directly. From a3a2507b70a2f8cc2a25e16ec43328b001f351ea Mon Sep 17 00:00:00 2001 From: danielailie Date: Thu, 5 Jun 2025 15:33:44 +0300 Subject: [PATCH 3/3] Update sdk-py documentation --- docs/developers/relayed-transactions.md | 2 +- .../signing-programmatically.md | 2 +- .../writing-and-running-sdk-js-snippets.md | 2 +- .../sdk-py-cookbook-v1.md => sdk-py.md} | 6 +- .../sdk-py/sdk-py-cookbook-v0.md | 1102 ----------------- docs/sdk-and-tools/sdk-py/sdk-py.md | 40 - docusaurus.config.js | 8 + scripts/render_notebooks.py | 2 +- sidebars.js | 20 +- 9 files changed, 16 insertions(+), 1168 deletions(-) rename docs/sdk-and-tools/{sdk-py/sdk-py-cookbook-v1.md => sdk-py.md} (99%) delete mode 100644 docs/sdk-and-tools/sdk-py/sdk-py-cookbook-v0.md delete mode 100644 docs/sdk-and-tools/sdk-py/sdk-py.md diff --git a/docs/developers/relayed-transactions.md b/docs/developers/relayed-transactions.md index 757cadb22..a94243429 100644 --- a/docs/developers/relayed-transactions.md +++ b/docs/developers/relayed-transactions.md @@ -115,6 +115,6 @@ Here's an example of a relayed v3 transaction. Its intent is to call the `add` m The SDKs have built-in support for relayed transactions. Please follow: - [mxpy support](/sdk-and-tools/mxpy/mxpy-cli/#relayed-transactions-v3) - - [sdk-py support](/sdk-and-tools/sdk-py/sdk-py-cookbook/#relayed-transactions) + - [sdk-py support](/sdk-and-tools/sdk-py/#relayed-transactions) - [sdk-js v14 support](/sdk-and-tools/sdk-js/sdk-js-cookbook#relayed-transactions) - [sdk-js v13 support (legacy)](/sdk-and-tools/sdk-js/sdk-js-cookbook-v13#preparing-a-relayed-transaction) diff --git a/docs/developers/signing-transactions/signing-programmatically.md b/docs/developers/signing-transactions/signing-programmatically.md index 59cbec2b5..475f9a66c 100644 --- a/docs/developers/signing-transactions/signing-programmatically.md +++ b/docs/developers/signing-transactions/signing-programmatically.md @@ -6,4 +6,4 @@ title: Signing programmatically In order to sign a transaction (or a message) using one of the SDKs, follow: - [Signing objects using **sdk-js**](/sdk-and-tools/sdk-js/sdk-js-cookbook#signing-objects) -- [Signing objects using **sdk-py**](/sdk-and-tools/sdk-py/sdk-py-cookbook#signing-objects) +- [Signing objects using **sdk-py**](/sdk-and-tools/sdk-py#signing-objects) diff --git a/docs/sdk-and-tools/sdk-js/writing-and-running-sdk-js-snippets.md b/docs/sdk-and-tools/sdk-js/writing-and-running-sdk-js-snippets.md index fae4247c1..75bbfba79 100644 --- a/docs/sdk-and-tools/sdk-js/writing-and-running-sdk-js-snippets.md +++ b/docs/sdk-and-tools/sdk-js/writing-and-running-sdk-js-snippets.md @@ -7,6 +7,6 @@ title: Writing and testing interactions Generally speaking, we recommended to use [sc-meta CLI](/developers/meta/sc-meta-cli) to [generate the boilerplate code for your contract interactions](/developers/meta/sc-meta-cli/#calling-snippets). -Though, for writing contract interaction snippets in **JavaScript** or **TypeScript**, please refer to the [`sdk-js` cookbook](/sdk-and-tools/sdk-js/sdk-js-cookbook). If you'd like these snippets to function as system tests of your contract, a choice would be to structure them as Mocha or Jest tests - take the `*.local.net.spec.ts` tests in [`mx-sdk-js-core`](https://github.com/multiversx/mx-sdk-js-core) as examples. For writing contract interaction snippets in **Python**, please refer to the [`sdk-py` cookbook](/sdk-and-tools/sdk-py/sdk-py-cookbook) - if desired, you can shape them as simple scripts, as Python unit tests, or as Jupyter notebooks. +Though, for writing contract interaction snippets in **JavaScript** or **TypeScript**, please refer to the [`sdk-js` cookbook](/sdk-and-tools/sdk-js/sdk-js-cookbook). If you'd like these snippets to function as system tests of your contract, a choice would be to structure them as Mocha or Jest tests - take the `*.local.net.spec.ts` tests in [`mx-sdk-js-core`](https://github.com/multiversx/mx-sdk-js-core) as examples. For writing contract interaction snippets in **Python**, please refer to the [`sdk-py` cookbook](/sdk-and-tools/sdk-py) - if desired, you can shape them as simple scripts, as Python unit tests, or as Jupyter notebooks. You might also want to have a look over [**xSuite**](https://xsuite.dev), a toolkit to init, build, test, deploy contracts using JavaScript, made by the [Arda team](https://arda.run). diff --git a/docs/sdk-and-tools/sdk-py/sdk-py-cookbook-v1.md b/docs/sdk-and-tools/sdk-py.md similarity index 99% rename from docs/sdk-and-tools/sdk-py/sdk-py-cookbook-v1.md rename to docs/sdk-and-tools/sdk-py.md index aab2d5de1..46e3b8fa4 100644 --- a/docs/sdk-and-tools/sdk-py/sdk-py-cookbook-v1.md +++ b/docs/sdk-and-tools/sdk-py.md @@ -1,7 +1,7 @@ --- -id: sdk-py-cookbook -title: Cookbook (v1) -pagination_prev: sdk-and-tools/sdk-py/sdk-py-cookbook-v0 +id: sdk-py +title: Python SDK +pagination_prev: developers/testing/testing-in-go pagination_next: sdk-and-tools/mxpy/installing-mxpy --- diff --git a/docs/sdk-and-tools/sdk-py/sdk-py-cookbook-v0.md b/docs/sdk-and-tools/sdk-py/sdk-py-cookbook-v0.md deleted file mode 100644 index 3b37ff778..000000000 --- a/docs/sdk-and-tools/sdk-py/sdk-py-cookbook-v0.md +++ /dev/null @@ -1,1102 +0,0 @@ ---- -id: sdk-py-cookbook-v0 -title: Cookbook (v0) -pagination_prev: sdk-and-tools/sdk-py/sdk-py ---- - -[comment]: # (mx-abstract) - -[comment]: # (mx-context-auto) - -## Overview - -This page will guide you through the process of handling common tasks using the MultiversX Python SDK (libraries) **v0 (legacy, previous version)**. - -:::important -In order to migrate to the newer `sdk-py v1`, please follow [the migration guide](https://github.com/multiversx/mx-sdk-py/issues?q=label:migration). -::: - -:::note -All examples depicted here are captured in **(interactive) [Jupyter notebooks](https://github.com/multiversx/mx-sdk-py/blob/main/examples/Cookbook.ipynb)**. -::: - -We are going to use the [multiversx-sdk-py](https://github.com/multiversx/mx-sdk-py) package. This package can be installed directly from GitHub or from [**PyPI**](https://pypi.org/project/multiversx-sdk/). - -Example for installing the package directly from GitHub, using a `requirements.txt` file: - -``` -git+https://git@github.com/multiversx/mx-sdk-py.git@v1.2.3#egg=multiversx_sdk -``` - - - -## Addresses - -Create an `Address` object from a _bech32-encoded_ string: - -```py -from multiversx_sdk import Address - -address = Address.new_from_bech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th") - -print("Address (bech32-encoded)", address.to_bech32()) -print("Public key (hex-encoded):", address.to_hex()) -print("Public key (hex-encoded):", address.get_public_key().hex()) -``` - -... or from a _hex-encoded_ string - note that you have to provide the address prefix, also known as the **HRP** (_human-readable part_ of the address): - -```py -address = Address.new_from_hex("0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1", "erd") -``` - -... or from a raw public key: - -```py -pubkey = bytes.fromhex("0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1") -address = Address(pubkey, "erd") -``` - -Alternatively, you can use an `AddressFactory` (initialized with a specific **HRP**) to create addresses: - -```py -from multiversx_sdk import AddressFactory - -factory = AddressFactory("erd") - -address = factory.create_from_bech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th") -address = factory.create_from_hex("0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1") -address = factory.create_from_public_key(bytes.fromhex("0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1")) -``` - -Addresses can be converted from one representation to another as follows: - -```py -print(address.to_bech32()) -print(address.to_hex()) -``` - -Getting the shard of an address: - -```py -from multiversx_sdk import AddressComputer - -address_computer = AddressComputer(number_of_shards=3) -print("Shard:", address_computer.get_shard_of_address(address)) -``` - -Checking whether an address is a smart contract: - -```py -address = Address.new_from_bech32("erd1qqqqqqqqqqqqqpgquzmh78klkqwt0p4rjys0qtp3la07gz4d396qn50nnm") - -print("Is contract:", address.is_smart_contract()) -``` - -### Changing the default hrp - -We have a configuration class, called `LibraryConfig`, that only stores (for the moment) the **default hrp** of the addresses. The default value is `erd`. The hrp can be changed when instantiating an address, or it can be changed in the `LibraryConfig` class, and all the addresses created will have the newly set hrp. - -```py -from multiversx_sdk import Address -from multiversx_sdk import LibraryConfig - - -print(LibraryConfig.default_address_hrp) -address = Address.new_from_hex("0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1") -print(address.to_bech32()) - -LibraryConfig.default_address_hrp = "test" -address = Address.new_from_hex("0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1") -print(address.to_bech32()) - -# setting back the default value -LibraryConfig.default_address_hrp = "erd" -``` - -## EGLD / ESDT transfers - -Create an EGLD transfer: - -```py -from multiversx_sdk import Transaction, TransactionsConverter - -transaction = Transaction( - sender="erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th", - receiver="erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx", - gas_limit=50000, - chain_id="D", - nonce=77, - value=1000000000000000000 -) - -transaction_converter = TransactionsConverter() -print(transaction_converter.transaction_to_dictionary(transaction)) -``` - -In case you are using a **guarded** account you should also populate the `guardian` and `guardian_signature` fields after creating the transaction. - -We'll see later how to [sign](#signing-objects) and [broadcast](#broadcasting-transactions) a transaction. - -Create an EGLD transfer, but this time with a payload (data): - -```py -transaction = Transaction( - sender="erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th", - receiver="erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx", - gas_limit=50000, - chain_id="D", - nonce=77, - value=1000000000000000000, - data=b"for the book" -) - -print(transaction_converter.transaction_to_dictionary(transaction)) -``` - -Alternatively, we can create an EGLD transfer using a **transaction factory** (as we will see below, transaction factories are more commonly used). But before that, we have to create a configuration object (for any factory that we might use): - -```py -from multiversx_sdk import TransactionsFactoryConfig - -config = TransactionsFactoryConfig(chain_id="D") -``` - -The **transaction factory** is parametrized at instantiation, and the transaction is obtained by invoking the `create_transaction...` method: - -```py -from multiversx_sdk import TransferTransactionsFactory - -transfer_factory = TransferTransactionsFactory(config=config) -alice = Address.new_from_bech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th") -bob = Address.new_from_bech32("erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx") - -# With "data" field -transaction = transfer_factory.create_transaction_for_native_token_transfer( - sender=alice, - receiver=bob, - native_amount=1000000000000000000, - data="for the book" -) - -print("Transaction:", transaction_converter.transaction_to_dictionary(transaction)) -print("Transaction data:", transaction.data.decode()) -``` - -Create a single ESDT transfer: - -```py -from multiversx_sdk import Token, TokenTransfer - -token = Token("TEST-8b028f") -transfer = TokenTransfer(token, 10000) - -transaction = transfer_factory.create_transaction_for_esdt_token_transfer( - sender=alice, - receiver=bob, - token_transfers=[transfer] -) - -print("Transaction:", transaction_converter.transaction_to_dictionary(transaction)) -print("Transaction data:", transaction.data.decode()) -``` - -Create a single NFT transfer: - -Keep in mind, since we are sending a NFT, we **should** set the amount to `1`. - -```py -token = Token(identifier="TEST-38f249", nonce=1) -transfer = TokenTransfer(token=token, amount=1) - -transaction = transfer_factory.create_transaction_for_esdt_token_transfer( - sender=alice, - receiver=bob, - token_transfers=[transfer] -) - -print("Transaction:", transaction_converter.transaction_to_dictionary(transaction)) -print("Transaction data:", transaction.data.decode()) -``` - -Create a single SFT transfer (almost the same as above, the only difference being that for the transfer we set the desired amount, as an integer): - -```py -token = Token(identifier="SEMI-9efd0f", nonce=1) -transfer = TokenTransfer(token=token, amount=5) - -transaction = transfer_factory.create_transaction_for_esdt_token_transfer( - sender=alice, - receiver=bob, - token_transfers=[transfer] -) - -print("Transaction:", transaction_converter.transaction_to_dictionary(transaction)) -print("Transaction data:", transaction.data.decode()) -``` - -Create a multiple ESDT / NFT transfer: - -```py -first_token = Token(identifier="TEST-38f249", nonce=1) -first_transfer = TokenTransfer(token=first_token, amount=1) - -second_token = Token(identifier="BAR-c80d29") -second_transfer = TokenTransfer(token=second_token, amount=10000000000000000000) - -transaction = transfer_factory.create_transaction_for_esdt_token_transfer( - sender=alice, - receiver=bob, - token_transfers=[first_transfer, second_transfer] -) - -print("Transaction:", transaction_converter.transaction_to_dictionary(transaction)) -print("Transaction data:", transaction.data.decode()) -``` - -Additionally, we also have a method that combines the above methods and is able to identify the kind of transfer that we intend to perform based on it's parameters. The method can be used as follows: - -For native token transfers: - -```py -from multiversx_sdk import TransferTransactionsFactory, TransactionsFactoryConfig - -transfer_factory = TransferTransactionsFactory(config=TransactionsFactoryConfig(chain_id="D")) - -alice = Address.new_from_bech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th") -bob = Address.new_from_bech32("erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx") - -# With "data" field -transaction = transfer_factory.create_transaction_for_transfer( - sender=alice, - receiver=bob, - native_amount=1000000000000000000, - data="for the book".encode() -) - -print("Transaction:", transaction_converter.transaction_to_dictionary(transaction)) -print("Transaction data:", transaction.data.decode()) -``` - -And for ESDT transfers: - -```py -first_token = Token(identifier="TEST-38f249", nonce=1) -first_transfer = TokenTransfer(token=first_token, amount=1) - -second_token = Token(identifier="BAR-c80d29") -second_transfer = TokenTransfer(token=second_token, amount=10000000000000000000) - -transaction = transfer_factory.create_transaction_for_transfer( - sender=alice, - receiver=bob, - token_transfers=[first_transfer, second_transfer] -) - -print("Transaction:", transaction_converter.transaction_to_dictionary(transaction)) -print("Transaction data:", transaction.data.decode()) -``` - -Alternatively, the protocol will support (in the very near future) sending both native and esdt tokens in the same transaction. If a `native_amount` is provided together with `token_transfers`, the native token will also be included in the `MultiESDTNFTTrasfer` built-in function call. - -```py -first_token = Token(identifier="TEST-38f249", nonce=1) -first_transfer = TokenTransfer(token=first_token, amount=1) - -second_token = Token(identifier="BAR-c80d29") -second_transfer = TokenTransfer(token=second_token, amount=10000000000000000000) - -transaction = transfer_factory.create_transaction_for_transfer( - sender=alice, - receiver=bob, - native_amount=1000000000000000000, - token_transfers=[first_transfer, second_transfer] -) - -print("Transaction:", transaction_converter.transaction_to_dictionary(transaction)) -print("Transaction data:", transaction.data.decode()) -``` - -### Decoding Transactions - -For example, when sending multiple ESDT and NFT tokens, the receiver field of the transaction is the same as the sender field and also the value is set to `0` because all the information is encoded in the `data` field of the transaction. - -For decoding the data field we have a so called `TransactionDecoder`. We fetch the transaction from the network and then use the decoder. - -```py -from multiversx_sdk import ProxyNetworkProvider, TransactionDecoder - -proxy = ProxyNetworkProvider("https://devnet-api.multiversx.com") -transaction = proxy.get_transaction("3e7b39f33f37716186b6ffa8761d066f2139bff65a1075864f612ca05c05c05d") - -decoder = TransactionDecoder() -decoded_transaction = decoder.get_transaction_metadata(transaction) - -print(decoded_transaction.to_dict()) -``` - -## Relayed Transactions - -First, we get the newtwork configuration using the network providers. - -```py -from multiversx_sdk import ProxyNetworkProvider - -provider = ProxyNetworkProvider("https://devnet-gateway.multiversx.com") -network_config = provider.get_network_config() -``` - -### Relayed V1 - -```py -from pathlib import Path - -from multiversx_sdk import (Address, RelayedTransactionsFactory, Transaction, - TransactionComputer, TransactionsFactoryConfig, - UserSigner) - -signer = UserSigner.from_pem_file(Path("../multiversx_sdk/testutils/testwallets/bob.pem")) -transaction_computer = TransactionComputer() - -inner_tx = Transaction( - chain_id=network_config.chain_id, - sender="erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx", - receiver="erd1qqqqqqqqqqqqqpgqqczn0ccd2gh8eqdswln7w9vzctv0dwq7d8ssm4y34z", - gas_limit=60000000, - nonce=198, - data=b"add@05" -) -inner_tx.signature = signer.sign(transaction_computer.compute_bytes_for_signing(inner_tx)) - -config = TransactionsFactoryConfig(chain_id="D") -factory = RelayedTransactionsFactory(config=config) -relayer = Address.new_from_bech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th") - -relayed_tx = factory.create_relayed_v1_transaction( - inner_transaction=inner_tx, - relayer_address=relayer -) -relayed_tx.nonce = 2627 - -print(transaction_converter.transaction_to_dictionary(relayed_tx)) -``` - -### Relayed V2 - -```py -from pathlib import Path - -from multiversx_sdk import (Address, RelayedTransactionsFactory, Transaction, - TransactionComputer, TransactionsFactoryConfig, - UserSigner) - -signer = UserSigner.from_pem_file(Path("../multiversx_sdk/testutils/testwallets/bob.pem")) -transaction_computer = TransactionComputer() - -# for the relayedV2 transactions, the gasLimit for the inner transaction should be 0 -inner_tx = Transaction( - chain_id=network_config.chain_id, - sender="erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx", - receiver="erd1qqqqqqqqqqqqqpgqqczn0ccd2gh8eqdswln7w9vzctv0dwq7d8ssm4y34z", - gas_limit=0, - nonce=15, - data=b"add@05" - ) -inner_tx.signature = signer.sign(transaction_computer.compute_bytes_for_signing(inner_tx)) - -config = TransactionsFactoryConfig(chain_id="D") -factory = RelayedTransactionsFactory(config=config) -relayer = Address.new_from_bech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th") - -relayed_tx = factory.create_relayed_v2_transaction( - inner_transaction=inner_tx, - inner_transaction_gas_limit=60_000_000, - relayer_address=relayer -) -relayed_tx.nonce = 37 - -print(transaction_converter.transaction_to_dictionary(relayed_tx)) -``` - -## Contract ABIs - -A contract's ABI describes the endpoints, data structure and events that a contract exposes. While contract interactions are possible without the ABI, they are easier to implement when the definitions are available. - -### Load the ABI from a file - -```py -from multiversx_sdk.abi import Abi, AbiDefinition - -abi_definition = AbiDefinition.load(Path("./contracts/adder.abi.json")) -abi = Abi(abi_definition) -``` - -Or even simpler: - -```py -abi = Abi.load(Path("./contracts/adder.abi.json")) -``` - -### Manually construct the ABI - -If an ABI file isn't directly available, but you do have knowledge of the contract's endpoints and types, you can manually construct the ABI. Let's see a simple example: - -```py -abi_definition = AbiDefinition.from_dict({ - "endpoints": [{ - "name": "add", - "inputs": [ - { - "name": "value", - "type": "BigUint" - } - ], - "outputs": [] - }] -}) -``` - -An endpoint with both inputs and outputs: - -```py -abi_definition = AbiDefinition.from_dict({ - "endpoints": [ - { - "name": "foo", - "inputs": [ - { "type": "BigUint" }, - { "type": "u32" }, - { "type": "Address" } - ], - "outputs": [ - { "type": "u32" } - ] - }, - { - "name": "bar", - "inputs": [ - { "type": "counted-variadic" }, - { "type": "variadic" } - ], - "outputs": [] - } - ] -}) -``` - -## Contract deployments - -### Load the bytecode from a file - -```py -from pathlib import Path - -bytecode = Path("contracts/adder.wasm").read_bytes() -``` - -### Perform a contract deployment - -First, let's create a `SmartContractTransactionsFactory`: - -```py -from multiversx_sdk import SmartContractTransactionsFactory - -factory = SmartContractTransactionsFactory(config) -``` - -If the contract ABI is available, provide it to the factory: - -```py -abi = Abi.load(Path("contracts/adder.abi.json")) -factory = SmartContractTransactionsFactory(config, abi) -``` - -Now, prepare the deploy transaction: - -```py -from multiversx_sdk.abi import U32Value - -# For deploy arguments, use typed value objects if you haven't provided an ABI to the factory: -args = [U32Value(42)] -# Or use simple, plain Python values and objects if you have provided an ABI to the factory: -args = [42] - -deploy_transaction = factory.create_transaction_for_deploy( - sender=alice, - bytecode=bytecode, - arguments=args, - gas_limit=10000000, - is_upgradeable=True, - is_readable=True, - is_payable=True, - is_payable_by_sc=True -) - -print("Transaction:", transaction_converter.transaction_to_dictionary(deploy_transaction)) -print("Transaction data:", deploy_transaction.data.decode()) -``` - -:::tip -When creating transactions using `SmartContractTransactionsFactory`, even if the ABI is available and provided, -you can still use _typed value_ objects as arguments for deployments and interactions. - -Even further, you can use a mix of _typed value_ objects and plain Python values and objects. For example: -``` -args = [U32Value(42), "hello", { "foo": "bar" }, TokenIdentifierValue("TEST-abcdef")]; -``` -::: - -:::note -Setting the transaction nonce, signing a transaction and broadcasting it are depicted in a later section. -::: - -### Computing the contract address - -Even before broadcasting, at the moment you know the sender address and the nonce for your deployment transaction, you can (deterministically) compute the (upcoming) address of the contract: - -```py -from multiversx_sdk import AddressComputer - -address_computer = AddressComputer() -contract_address = address_computer.compute_contract_address( - deployer=Address.new_from_bech32(deploy_transaction.sender), - deployment_nonce=deploy_transaction.nonce -) - -print("Contract address:", contract_address.to_bech32()) -``` - -### Parsing transaction outcome - -In the end, you can parse the results using a `SmartContractTransactionsOutcomeParser`. However, since the `parse_deploy` method requires a `TransactionOutcome` object as input, we need to first convert our `TransactionOnNetwork` object to a `TransactionOutcome`, by means of a `TransactionsConverter`. - -```py -from multiversx_sdk import (SmartContractTransactionsOutcomeParser, - TransactionsConverter) - -converter = TransactionsConverter() -parser = SmartContractTransactionsOutcomeParser() - -transaction_on_network = proxy.get_transaction("0a7da74038244790b5bd4cd614c26cd5a6be76a6fcfcfb037974cc116b2ee9c6") -transaction_outcome = converter.transaction_on_network_to_outcome(transaction_on_network) -parsed_outcome = parser.parse_deploy(transaction_outcome) - -print(parsed_outcome) -``` - -## Contract upgrades - -Contract upgrade transactions are similar to deployment transactions (see above), in the sense that they also require a contract bytecode. In this context, though, the contract address is already known. - -```py -contract_address = Address.new_from_bech32("erd1qqqqqqqqqqqqqpgquzmh78klkqwt0p4rjys0qtp3la07gz4d396qn50nnm") -bytecode = Path("./contracts/adder.wasm").read_bytes() - -upgrade_transaction = factory.create_transaction_for_upgrade( - sender=alice, - contract=contract_address, - bytecode=bytecode, - gas_limit=10000000, - arguments=[42], - is_upgradeable=True, - is_readable=True, - is_payable=True, - is_payable_by_sc=True -) - -print("Transaction:", transaction_converter.transaction_to_dictionary(upgrade_transaction)) -print("Transaction data:", upgrade_transaction.data.decode()) -``` - -## Contract interactions - -The recommended way to create transactions for calling (and, for that matter, deploying and upgrading) smart contracts is through a `SmartContractTransactionsFactory`. - -```py -from multiversx_sdk import SmartContractTransactionsFactory - -factory = SmartContractTransactionsFactory(config) -``` - -If the contract ABI is available, provide it to the factory: - -```py -abi = Abi.load(Path("contracts/adder.abi.json")) -factory = SmartContractTransactionsFactory(config, abi) -``` - -### Regular interactions - -Now, let's prepare a contract transaction, to call the `add` function of our previously deployed smart contract: - -```py -contract_address = Address.new_from_bech32("erd1qqqqqqqqqqqqqpgqws44xjx2t056nn79fn29q0rjwfrd3m43396ql35kxy") - -# For arguments, use typed value objects if you haven't provided an ABI to the factory: -args = [U32Value(42)] -# Or use simple, plain Python values and objects if you have provided an ABI to the factory: -args = [42] - -transaction = factory.create_transaction_for_execute( - sender=alice, - contract=contract_address, - function="add", - gas_limit=10000000, - arguments=args -) - -print("Transaction:", transaction_converter.transaction_to_dictionary(transaction)) -print("Transaction data:", transaction.data.decode()) -``` - -:::tip -When creating transactions using `SmartContractTransactionsFactory`, even if the ABI is available and provided, -you can still use _typed value_ objects as arguments for deployments and interactions. - -Even further, you can use a mix of _typed value_ objects and plain Python values and objects. For example: -``` -args = [U32Value(42), "hello", { "foo": "bar" }, TokenIdentifierValue("TEST-abcdef")]; -``` -::: - -:::note -Setting the transaction nonce, signing a transaction and broadcasting it are depicted in a later section. -::: - -### Transfer & execute - -At times, you may want to send some tokens (native EGLD or ESDT) along with the contract call. - -For transfer & execute with native EGLD, prepare your transaction as follows: - -```py -transaction = factory.create_transaction_for_execute( - sender=alice, - contract=contract_address, - function="add", - gas_limit=10000000, - arguments=[42], - native_transfer_amount=1000000000000000000 -) -``` - -Above, we're sending 1 EGLD along with the contract call. - -For transfer & execute with ESDT tokens, prepare your transaction as follows: - -```py -first_token = Token("TEST-38f249", 1) -first_transfer = TokenTransfer(first_token, 1) - -second_token = Token("BAR-c80d29") -second_transfer = TokenTransfer(second_token, 10000000000000000000) - -transfers = [first_transfer, second_transfer] - -transaction = factory.create_transaction_for_execute( - sender=alice, - contract=contract_address, - function="add", - gas_limit=10000000, - arguments=[42], - token_transfers=transfers -) - -print("Transaction:", transaction_converter.transaction_to_dictionary(transaction)) -print("Transaction data:", transaction.data.decode()) -``` - -### Parsing transaction outcome - -:::note -Documentation in this section is preliminary and subject to change. -::: - -### Decode transaction events - -You might be interested into decoding events emitted by a contract. You can do so by using the [`TransactionEventsParser`](#). - -Suppose we'd like to decode a `startPerformAction` event emitted by the [multisig](https://github.com/multiversx/mx-contracts-rs/tree/main/contracts/multisig) contract. - -Let's fetch an already processed [transaction](https://devnet-explorer.multiversx.com/transactions/05d445cdd145ecb20374844dcc67f0b1e370b9aa28a47492402bc1a150c2bab4), to serve as an example, and convert it to a [TransactionOutcome](https://multiversx.github.io/mx-sdk-py/_modules/multiversx_sdk/core/transactions_outcome_parsers/resources.html#TransactionOutcome). - -```py -from multiversx_sdk import ApiNetworkProvider, TransactionsConverter - -api = ApiNetworkProvider("https://testnet-api.multiversx.com") -converter = TransactionsConverter() - -transaction_on_network = api.get_transaction("6f006c99e45525c94629db2442d9ca27ff088ad113a09f0a3a3e24bcc164945a") -transaction_outcome = converter.transaction_on_network_to_outcome(transaction_on_network) -``` - -Now, lets find and parse the event we are interested in. - -```py -from multiversx_sdk import TransactionEventsParser, find_events_by_first_topic -from multiversx_sdk.abi import Abi - -abi = Abi.load(Path("./contracts/multisig-full.abi.json")) -events_parser = TransactionEventsParser(abi) - -[event] = find_events_by_first_topic(transaction_outcome, "startPerformAction") -parsed_event = events_parser.parse_event(event) - -print(parsed_event) -``` - -## Contract queries - -In order to perform Smart Contract queries, we recommend the use of `SmartContractQueriesController`. - -You will notice that the `SmartContractQueriesController` requires a `QueryRunner` object at initialization. A `NetworkProvider`, slightly adapted, is used to satisfy this requirement (more details about **network providers** can be found in a later section). - -```py -from multiversx_sdk import (ProxyNetworkProvider, QueryRunnerAdapter, - SmartContractQueriesController) - -contract = Address.new_from_bech32("erd1qqqqqqqqqqqqqpgqqy34h7he2ya6qcagqre7ur7cc65vt0mxrc8qnudkr4") -query_runner = QueryRunnerAdapter(ProxyNetworkProvider("https://devnet-api.multiversx.com")) - -query_controller = SmartContractQueriesController(query_runner) - -``` - -If the contract ABI is available, provide it to the controller: - -```py -abi = Abi.load(Path("contracts/adder.abi.json")) -query_controller = SmartContractQueriesController(query_runner, abi) -``` - -Query the contract as follows: - -```py -data_parts = query_controller.query( - contract=contract.to_bech32(), - function="getSum", - arguments=[], -) - -print("Return data (parsed):", data_parts) -``` - -For finer control, first create a contract query, then run it and parse the outcome at a later time: - -```py -query = query_controller.create_query( - contract=contract.to_bech32(), - function="getSum", - arguments=[], -) - -response = query_controller.run_query(query) -data_parts = query_controller.parse_query_response(response) - -print("Return code:", response.return_code) -print("Return data (raw):", response.return_data_parts) -print("Return data (parsed):", data_parts) -``` - -## Creating wallets - -Mnemonic generation is based on [`trezor/python-mnemonic`](https://github.com/trezor/python-mnemonic) and can be achieved as follows: - -```py -from multiversx_sdk import Mnemonic - -mnemonic = Mnemonic.generate() -words = mnemonic.get_words() - -print(words) -``` - -The mnemonic can be saved to a keystore file: - -```py -from pathlib import Path -from multiversx_sdk import UserWallet - -path = Path("./output") -if not path.exists(): - path.mkdir(parents=True, exist_ok=True) - -wallet = UserWallet.from_mnemonic(mnemonic.get_text(), "password") -wallet.save(path / "walletWithMnemonic.json") -``` - -Given a mnemonic, one can derive keypairs: - -```py -secret_key = mnemonic.derive_key(0) -public_key = secret_key.generate_public_key() - -print("Secret key:", secret_key.hex()) -print("Public key:", public_key.hex()) -``` - -A keypair can be saved as a JSON wallet: - -```py -path = Path("./output") -if not path.exists(): - path.mkdir(parents=True, exist_ok=True) - -wallet = UserWallet.from_secret_key(secret_key, "password") -wallet.save(path / "wallet.json", address_hrp="erd") -``` - -... or as a PEM wallet (usually not recommended): - -```py -from multiversx_sdk import Address, UserPEM - -path = Path("./output") -if not path.exists(): - path.mkdir(parents=True, exist_ok=True) - -label = Address(public_key.buffer, "erd").to_bech32() -pem = UserPEM(label=label, secret_key=secret_key) -pem.save(path / "wallet.pem") -``` - -## Loading wallets - -This is not a very common use-case - you might refer to [signing objects](#signing-objects) instead. - -Load a keystore that holds an **encrypted mnemonic** (and perform wallet derivation at the same time): - -```py -from multiversx_sdk import UserWallet - -secret_key = UserWallet.load_secret_key(Path("../multiversx_sdk/testutils/testwallets/withDummyMnemonic.json"), "password", address_index=0) -address = secret_key.generate_public_key().to_address("erd") - -print("Secret key:", secret_key.hex()) -print("Address:", address.to_bech32()) -``` - -Load a keystore that holds an **encrypted secret** key: - -```py -secret_key = UserWallet.load_secret_key(Path("../multiversx_sdk/testutils/testwallets/alice.json"), "password") -address = secret_key.generate_public_key().to_address("erd") - -print("Secret key:", secret_key.hex()) -print("Address:", address.to_bech32()) -``` - -Load the secret key from a PEM file: - -```py -from multiversx_sdk import UserPEM - -pem = UserPEM.from_file(Path("../multiversx_sdk/testutils/testwallets/alice.pem")) - -print("Secret key:", pem.secret_key.hex()) -print("Public key:", pem.public_key.hex()) -``` - -## Signing objects - -Creating a `UserSigner` from a JSON wallet: - -```py -from multiversx_sdk import UserSigner - -signer = UserSigner.from_wallet(Path("../multiversx_sdk/testutils/testwallets/alice.json"), "password") -``` - -Creating a `UserSigner` from a PEM file: - -```py -signer = UserSigner.from_pem_file(Path("../multiversx_sdk/testutils/testwallets/alice.pem")) -``` - -Signing a transaction: - -```py -from multiversx_sdk import Transaction, TransactionComputer - -tx = Transaction( - nonce=90, - sender="erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th", - receiver="erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx", - value=1000000000000000000, - gas_limit=50000, - chain_id="D" -) - -transaction_computer = TransactionComputer() - -tx.signature = signer.sign(transaction_computer.compute_bytes_for_signing(tx)) -print("Signature:", tx.signature.hex()) -``` - -Signing an arbitrary message: - -```py -from multiversx_sdk import Message, MessageComputer - -signer_address = signer.get_pubkey().to_address(hrp="erd") -message = Message(b"hello") -message_computer = MessageComputer() - -message.signature = signer.sign(message_computer.compute_bytes_for_signing(message)) - -print("Signature:", message.signature.hex()) -``` - -## Verifying signatures - -Creating a `UserVerifier`: - -```py -from multiversx_sdk import Address, UserVerifier - -alice = Address.new_from_bech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th") -bob = Address.new_from_bech32("erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx") - -alice_verifier = UserVerifier.from_address(alice) -bob_verifier = UserVerifier.from_address(bob) -``` - -Verifying a signature: - -```py -from multiversx_sdk import MessageComputer, TransactionComputer - -transaction_computer = TransactionComputer() -message_computer = MessageComputer() - -print(f"Is signature of Alice?", alice_verifier.verify(transaction_computer.compute_bytes_for_signing(tx), tx.signature)) -print(f"Is signature of Alice?", alice_verifier.verify(message_computer.compute_bytes_for_verifying(message), message.signature)) -print(f"Is signature of Bob?", bob_verifier.verify(transaction_computer.compute_bytes_for_signing(tx), tx.signature)) -print(f"Is signature of Bob?", bob_verifier.verify(message_computer.compute_bytes_for_verifying(message), message.signature)) -``` - -## Creating network providers - -It's recommended to use the `multiversx_sdk_network_providers` components **as a starting point**. As your application matures, switch to using your own network provider (e.g. deriving from the default ones), tailored to your requirements. - -Creating an API provider: - -```py -from multiversx_sdk import ApiNetworkProvider - -provider = ApiNetworkProvider("https://devnet-api.multiversx.com") -``` - -Creating a Proxy provider: - -```py -from multiversx_sdk import ProxyNetworkProvider - -provider = ProxyNetworkProvider("https://devnet-gateway.multiversx.com") -``` - -## Fetching network parameters - -In order to fetch network parameters, do as follows: - -```py -config = provider.get_network_config() - -print("Chain ID:", config.chain_id) -print("Min gas price:", config.min_gas_price) -``` - -## Fetching account state - -The following snippet fetches (from the Network) the **nonce** and the **balance** of an account: - -```py -account_on_network = provider.get_account(alice) - -print("Nonce:", account_on_network.nonce) -print("Balance:", account_on_network.balance) -``` - -When sending a number of transactions, you usually have to first fetch the account nonce from the network (see above), then manage it locally (e.g. increment upon signing & broadcasting a transaction): - -```py -from multiversx_sdk import AccountNonceHolder - -nonce_holder = AccountNonceHolder(account_on_network.nonce) - -tx.nonce = nonce_holder.get_nonce_then_increment() -# Then, sign & broadcast the transaction(s). -``` - -For further reference, please see [nonce management](/integrators/creating-transactions/#nonce-management). - -## Broadcasting transactions - -Broadcast a single transaction: - -```py -alice = Address.new_from_bech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th") - -tx = Transaction( - sender=alice.to_bech32(), - receiver=alice.to_bech32(), - gas_limit=50000, - chain_id="D" -) - -alice_on_network = provider.get_account(alice) - -tx.nonce = alice_on_network.nonce -tx.signature = signer.sign(transaction_computer.compute_bytes_for_signing(tx)) - -hash = provider.send_transaction(tx) -print("Transaction hash:", hash) -``` - -Broadcast multiple transactions: - -```py -tx_1 = Transaction( - sender=alice.to_bech32(), - receiver=alice.to_bech32(), - gas_limit=50000, - chain_id="D" -) - -tx_2 = Transaction( - sender=alice.to_bech32(), - receiver=alice.to_bech32(), - gas_limit=50000, - chain_id="D" -) - -tx_3 = Transaction( - sender=alice.to_bech32(), - receiver=alice.to_bech32(), - gas_limit=50000, - chain_id="D" -) - -alice_on_network = provider.get_account(alice) -nonce_holder = AccountNonceHolder(account_on_network.nonce) - -tx_1.nonce = nonce_holder.get_nonce_then_increment() -tx_2.nonce = nonce_holder.get_nonce_then_increment() -tx_3.nonce = nonce_holder.get_nonce_then_increment() - -tx_1.signature = signer.sign(transaction_computer.compute_bytes_for_signing(tx_1)) -tx_2.signature = signer.sign(transaction_computer.compute_bytes_for_signing(tx_2)) -tx_3.signature = signer.sign(transaction_computer.compute_bytes_for_signing(tx_3)) - -hashes = provider.send_transactions([tx_1, tx_2, tx_3]) -print("Transactions hashes:", hashes) -``` - -Now let's fetch a previously-broadcasted transaction: - -```py -tx_on_network = provider.get_transaction("9270a6879b682a7b310c659f58b641ccdd5f083e5633669817130269e5b0939b", with_process_status=True) -print("Status:", tx_on_network.status) -print("Is completed:", tx_on_network.is_completed) -``` - diff --git a/docs/sdk-and-tools/sdk-py/sdk-py.md b/docs/sdk-and-tools/sdk-py/sdk-py.md deleted file mode 100644 index 315db9fb7..000000000 --- a/docs/sdk-and-tools/sdk-py/sdk-py.md +++ /dev/null @@ -1,40 +0,0 @@ ---- -id: sdk-py -title: sdk-py ---- - -[comment]: # (mx-abstract) - -MultiversX SDK for Python - -This SDK consists of a CLI tool, namely `mxpy`, and Python helpers and utilities for interacting with the Blockchain (in general) and with Smart Contracts (in particular). - -[comment]: # (mx-context-auto) - -## `mxpy`: the CLI tool - -**mxpy** (the CLI tool) can be found here: [mx-sdk-py-cli](https://github.com/multiversx/mx-sdk-py-cli). It targets a broad audience of **users** and **developers**, as depicted below: - -| Feature | Audience | -|------------------------------------------------------------------------------------------------|---------------------------------------------------------------------| -| Compile Smart Contracts (Rust, C, C++) to WASM | Smart Contract developers | -| Deploy, execute (call), query Smart Contracts | Smart Contract developers, application developers, tech enthusiasts | -| Run scenarios (JSON tests) against Smart Contracts | Smart Contract developers | -| Sign & send [System Smart Contract transactions](/validators/staking/staking-smart-contract) | Validator owners | -| Sign & send regular transactions | Application developers, tech enthusiasts | -| Query Network status, transactions status / details | Application developers, tech enthusiasts | -| Query account details | Application developers, tech enthusiasts | -| Generate PEM files, recover private key from mnemonic | Tech enthusiasts | -| Miscellaneous support features (e.g. bech32 conversion) | Tech enthusiasts | - -[comment]: # (mx-context-auto) - -## `sdk-py`: the Python library - -:::note -The `multiversx-sdk` package is a unification of the previous packages (`multiversx-sdk-core`, `multiversx-sdk-wallet` and `multiversx-sdk-network-providers`). This is the package that **should** be used from now on. All the upcoming updates will come only to this package. The older packages will no longer receive updates and will soon be deprecated. -::: - -| Package | Source code | Description | -|---------------------------------------------------------------------------------------------|---------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------| -| [multiversx-sdk](https://pypi.org/project/multiversx-sdk) | [mx-sdk-py](https://github.com/multiversx/mx-sdk-py) | The all-in-one Python SDK for interacting with MultiversX. | diff --git a/docusaurus.config.js b/docusaurus.config.js index dcfd25215..5cc328f1d 100644 --- a/docusaurus.config.js +++ b/docusaurus.config.js @@ -414,6 +414,14 @@ const config = { from: "/developers/mandos-reference/embed", to: "/developers/testing/testing-in-go", }, + { + from: "/sdk-and-tools/sdk-py/sdk-py-cookbook", + to: "/sdk-and-tools/sdk-py", + }, + { + from: "/sdk-and-tools/sdk-py/sdk-py-cookbook-v0", + to: "/sdk-and-tools/sdk-py", + }, { from: "/sdk-and-tools/sdk-js/sdk-js-cookbook", to: "/sdk-and-tools/sdk-js/sdk-js-cookbook", diff --git a/scripts/render_notebooks.py b/scripts/render_notebooks.py index 44a55debf..80b936e37 100644 --- a/scripts/render_notebooks.py +++ b/scripts/render_notebooks.py @@ -10,7 +10,7 @@ cookbooks: List[Path] = [ - DOCS_ROOT / "sdk-and-tools/sdk-py/sdk-py-cookbook-v1.md", + DOCS_ROOT / "sdk-and-tools/sdk-py.md", ] diff --git a/sidebars.js b/sidebars.js index f94ef4612..a36a3c640 100644 --- a/sidebars.js +++ b/sidebars.js @@ -194,25 +194,7 @@ const sidebars = { type: "category", label: "SDKs", items: [ - { - type: "category", - label: "Python SDK", - items: [ - "sdk-and-tools/sdk-py/sdk-py", - { - type: "category", - label: "Cookbook (versioned)", - link: { - type: "doc", - id: "sdk-and-tools/sdk-py/sdk-py-cookbook" - }, - items: [ - "sdk-and-tools/sdk-py/sdk-py-cookbook-v0", - "sdk-and-tools/sdk-py/sdk-py-cookbook", - ] - }, - ], - }, + "sdk-and-tools/sdk-py", { type: "category", label: "Mxpy CLI",