diff --git a/docs/sdk-and-tools/sdk-js/sdk-js-cookbook.md b/docs/sdk-and-tools/sdk-js/sdk-js-cookbook.md index 0aef8a0a9..2078a28ad 100644 --- a/docs/sdk-and-tools/sdk-js/sdk-js-cookbook.md +++ b/docs/sdk-and-tools/sdk-js/sdk-js-cookbook.md @@ -416,6 +416,7 @@ console.log("Return code:", returnCode); + [comment]: # (mx-context-auto) ## ABI diff --git a/docs/sdk-and-tools/sdk-py/sdk-py-cookbook.md b/docs/sdk-and-tools/sdk-py/sdk-py-cookbook.md index 469dc1073..9f4699d37 100644 --- a/docs/sdk-and-tools/sdk-py/sdk-py-cookbook.md +++ b/docs/sdk-and-tools/sdk-py/sdk-py-cookbook.md @@ -3,7 +3,8 @@ id: sdk-py-cookbook title: Cookbook --- -[comment]: # (mx-abstract) +[comment]: # "mx-abstract" +[comment]: # (mx-context-auto) ## Overview @@ -13,7 +14,7 @@ This page will guide you through the process of handling common tasks using the All examples depicted here are captured in **(interactive) [Jupyter notebooks](https://github.com/multiversx/mx-sdk-py-examples)**. ::: -We are going to make use of the packages [multiversx-sdk-core](https://github.com/multiversx/mx-sdk-py-core), [multiversx-sdk-wallet](https://github.com/multiversx/mx-sdk-py-wallet) and [multiversx-sdk-network-providers](https://github.com/multiversx/mx-sdk-py-network-providers) (available as of January 2023), which were previously nicknamed _erdpy-eggs_. These packages can be installed directly from GitHub or from [**PyPI**](https://pypi.org/user/MultiversX). +We are going to make use of the packages [multiversx-sdk-core](https://github.com/multiversx/mx-sdk-py-core), [multiversx-sdk-wallet](https://github.com/multiversx/mx-sdk-py-wallet) and [multiversx-sdk-network-providers](https://github.com/multiversx/mx-sdk-py-network-providers) (available as of January 2023), which were previously nicknamed _erdpy-eggs_. These packages can be installed directly from GitHub or from [**PyPI**](https://pypi.org/user/MultiversX). Example for installing the packages directly from GitHub, using a `requirements.txt` file: @@ -50,7 +51,7 @@ print("Public key (hex-encoded):", address.pubkey.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): ``` -address = Address.from_hex("0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1", "erd"); +address = Address.from_hex("0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1", "erd") ``` ... or from a raw public key: @@ -127,6 +128,8 @@ tx = Transaction( print(tx.to_dictionary()) ``` +In case you are using a **guarded** account you should also provide the _guardian_ argument when 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): @@ -261,6 +264,83 @@ print("Transaction data:", tx.data) [comment]: # (mx-context-auto) +## Relayed Transactions + +First, we get the newtwork configuration using the network providers. + +``` +from multiversx_sdk_network_providers import ProxyNetworkProvider + +provider = ProxyNetworkProvider("https://devnet-gateway.multiversx.com") +network_config = provider.get_network_config() +``` + +[comment]: # (mx-context-auto) + +### Relayed V1 + +``` +from pathlib import Path +from multiversx_sdk_core.transaction_builders.relayed_v1_builder import RelayedTransactionV1Builder +from multiversx_sdk_core import Transaction, Address, TransactionPayload +from multiversx_sdk_wallet.user_signer import UserSigner + +signer = UserSigner.from_pem_file(Path("./testwallets/bob.pem")) + +inner_tx = Transaction( + chain_id=network_config.chain_id, + sender=Address.from_bech32("erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx"), + receiver=Address.from_bech32("erd1qqqqqqqqqqqqqpgqqczn0ccd2gh8eqdswln7w9vzctv0dwq7d8ssm4y34z"), + gas_limit=60000000, + nonce=198, + data=TransactionPayload.from_str("add@05") +) +inner_tx.signature = signer.sign(inner_tx.serialize_for_signing()) + +relayed_builder = RelayedTransactionV1Builder() +relayed_builder.set_inner_transaction(inner_tx) +relayed_builder.set_relayer_nonce(2627) +relayed_builder.set_network_config(network_config) +relayed_builder.set_relayer_address(Address.from_bech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th")) + +relayed_tx = relayed_builder.build() +print(relayed_tx.to_dictionary()) +``` + +[comment]: # (mx-context-auto) + +### Relayed V2 + +``` +from multiversx_sdk_core.transaction_builders.relayed_v2_builder import RelayedTransactionV2Builder +from multiversx_sdk_core import Transaction, Address, TransactionPayload +from multiversx_sdk_wallet.user_signer import UserSigner + +signer = UserSigner.from_pem_file(Path("./testwallets/bob.pem")) + +inner_tx = Transaction( + chain_id=network_config.chain_id, + sender=Address.from_bech32("erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx"), + receiver=Address.from_bech32("erd1qqqqqqqqqqqqqpgqqczn0ccd2gh8eqdswln7w9vzctv0dwq7d8ssm4y34z"), + gas_limit=0, + nonce=15, + data=TransactionPayload.from_str("add@05") + ) +inner_tx.signature = signer.sign(inner_tx.serialize_for_signing()) + +builder = RelayedTransactionV2Builder() +builder.set_inner_transaction(inner_tx) +builder.set_inner_transaction_gas_limit(60_000_000) +builder.set_relayer_nonce(37) +builder.set_network_config(network_config) +builder.set_relayer_address(Address.from_bech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th")) + +relayed_tx = builder.build() +print(relayed_tx.to_dictionary()) +``` + +[comment]: # (mx-context-auto) + ## Contract deployments and interactions Create a transaction to deploy a smart contract: @@ -278,7 +358,7 @@ builder = ContractDeploymentBuilder( owner=alice, deploy_arguments=[42, "test"], code_metadata=metadata, - code=Path("./contracts/contract.wasm").read_bytes(), + code=Path("./contracts/counter.wasm").read_bytes(), gas_limit=10000000 ) @@ -302,7 +382,7 @@ builder = ContractUpgradeBuilder( owner=owner, upgrade_arguments=[42, "test"], code_metadata=metadata, - code=Path("./contracts/contract.wasm").read_bytes(), + code=Path("./contracts/counter.wasm").read_bytes(), gas_limit=10000000 ) @@ -517,7 +597,7 @@ tx = Transaction( version=1 ) -tx.signature = signer.sign(tx) +tx.signature = signer.sign(tx.serialize_for_signing()) print("Signature", tx.signature.hex()) ``` @@ -527,7 +607,7 @@ Signing an arbitrary message: from multiversx_sdk_core import MessageV1 message = MessageV1.from_string("hello") -message.signature = signer.sign(message) +message.signature = signer.sign(message.data) print("Signature", message.signature.hex()) ``` @@ -561,10 +641,10 @@ Both `Transaction` and `Message` - defined in `multiversx_sdk_core` - implement Verifying a signature: ``` -print(f"Is signature of Alice?", alice_verifier.verify(tx)) -print(f"Is signature of Alice?", alice_verifier.verify(message)) -print(f"Is signature of Bob?", bob_verifier.verify(tx)) -print(f"Is signature of Bob?", bob_verifier.verify(message)) +print(f"Is signature of Alice?", alice_verifier.verify(tx.serialize_for_signing(), tx.signature)) +print(f"Is signature of Alice?", alice_verifier.verify(message.data, message.signature)) +print(f"Is signature of Bob?", bob_verifier.verify(tx.serialize_for_signing(), tx.signature)) +print(f"Is signature of Bob?", bob_verifier.verify(message.data, message.signature)) ``` [comment]: # (mx-context-auto) @@ -578,7 +658,7 @@ Creating an API provider: ``` from multiversx_sdk_network_providers import ApiNetworkProvider -provider = ApiNetworkProvider("https://devnet-api.multiversx.com"); +provider = ApiNetworkProvider("https://devnet-api.multiversx.com") ``` Creating a Proxy provider: @@ -586,7 +666,7 @@ Creating a Proxy provider: ``` from multiversx_sdk_network_providers import ProxyNetworkProvider -provider = ProxyNetworkProvider("https://devnet-gateway.multiversx.com"); +provider = ProxyNetworkProvider("https://devnet-gateway.multiversx.com") ``` [comment]: # (mx-context-auto) @@ -596,10 +676,10 @@ provider = ProxyNetworkProvider("https://devnet-gateway.multiversx.com"); In order to fetch network parameters, do as follows: ``` -config = provider.get_network_config(); +config = provider.get_network_config() -print("Chain ID", config.chain_id); -print("Min gas price:", config.min_gas_price); +print("Chain ID", config.chain_id) +print("Min gas price:", config.min_gas_price) ``` [comment]: # (mx-context-auto) @@ -647,7 +727,7 @@ tx = Transaction( alice_on_network = provider.get_account(alice) tx.nonce = alice_on_network.nonce -tx.signature = signer.sign(tx) +tx.signature = signer.sign(tx.serialize_for_signing()) hash = provider.send_transaction(tx) print("Transaction hash:", hash) @@ -684,9 +764,9 @@ 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(tx_1) -tx_2.signature = signer.sign(tx_2) -tx_3.signature = signer.sign(tx_3) +tx_1.signature = signer.sign(tx_1.serialize_for_signing()) +tx_2.signature = signer.sign(tx_2.serialize_for_signing()) +tx_3.signature = signer.sign(tx_3.serialize_for_signing()) hashes = provider.send_transactions([tx_1, tx_2, tx_3]) print("Transactions hashes:", hashes) @@ -695,8 +775,9 @@ print("Transactions hashes:", hashes) Now let's fetch a previously-broadcasted transaction: ``` -tx_on_network = provider.get_transaction("09e3b68d39f3759913239b927c7feb9ac871c8877e76bc56e1be45a2a597eb53") +tx_on_network = provider.get_transaction("09e3b68d39f3759913239b927c7feb9ac871c8877e76bc56e1be45a2a597eb53", with_process_status=True) print("Status:", tx_on_network.status) print("Is completed:", tx_on_network.is_completed) ``` +