From a279b44e94907d83d4d6e9934445d1501feed922 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Tue, 7 Nov 2023 15:41:33 +0200 Subject: [PATCH 1/3] update py-examples --- docs/sdk-and-tools/sdk-py/mxpy-cli.md | 2 + docs/sdk-and-tools/sdk-py/sdk-py-cookbook.md | 404 +++++++++---------- 2 files changed, 185 insertions(+), 221 deletions(-) diff --git a/docs/sdk-and-tools/sdk-py/mxpy-cli.md b/docs/sdk-and-tools/sdk-py/mxpy-cli.md index 6f3a6efca..0295367a6 100644 --- a/docs/sdk-and-tools/sdk-py/mxpy-cli.md +++ b/docs/sdk-and-tools/sdk-py/mxpy-cli.md @@ -330,6 +330,8 @@ That's it! As easy as that. We sent a transaction from Alice to Bob. We choose t In case you want to save the transaction you can also provide the `--outfile` argument and a `json` file containing the transaction will be saved at the specified location. If you just want to prepare the transaction without broadcasting it simply remove the `--send` argument. +[comment]: # (mx-context-auto) + ## Using the Ledger hardware wallet You can sign any transaction (regular transfers, smart contract deployments and calls) using a Ledger hardware wallet by leveraging the `--ledger` command-line argument. 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 3e36cfe47..797f3d327 100644 --- a/docs/sdk-and-tools/sdk-py/sdk-py-cookbook.md +++ b/docs/sdk-and-tools/sdk-py/sdk-py-cookbook.md @@ -42,17 +42,17 @@ Create an `Address` object from a _bech32-encoded_ string: ``` from multiversx_sdk_core import Address -address = Address.from_bech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th") +address = Address.new_from_bech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th") -print("Address (bech32-encoded)", address.bech32()) -print("Public key (hex-encoded):", address.hex()) +print("Address (bech32-encoded)", address.to_bech32()) +print("Public key (hex-encoded):", address.to_hex()) 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.new_from_hex("0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1", "erd") ``` ... or from a raw public key: @@ -71,37 +71,29 @@ factory = AddressFactory("erd") address = factory.create_from_bech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th") address = factory.create_from_hex("0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1") -address = factory.create_from_pubkey(bytes.fromhex("0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1")) +address = factory.create_from_public_key(bytes.fromhex("0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1")) ``` Addresses can be converted from one representation to another as follows: ``` -print(address.bech32()) -print(address.hex()) -``` - -... or using a converter: - -``` -from multiversx_sdk_core import AddressConverter - -converter = AddressConverter("erd") - -pubkey = converter.bech32_to_pubkey("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th") -bech32 = converter.pubkey_to_bech32(bytes.fromhex("0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1")) +print(address.to_bech32()) +print(address.to_hex()) ``` Getting the shard of an address: ``` -print("Shard:", address.get_shard()) +from multiversx_sdk_core 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: ``` -address = Address.from_bech32("erd1qqqqqqqqqqqqqpgquzmh78klkqwt0p4rjys0qtp3la07gz4d396qn50nnm") +address = Address.new_from_bech32("erd1qqqqqqqqqqqqqpgquzmh78klkqwt0p4rjys0qtp3la07gz4d396qn50nnm") print("Is contract:", address.is_smart_contract()) ``` @@ -113,154 +105,139 @@ print("Is contract:", address.is_smart_contract()) Create an EGLD transfer: ``` -from multiversx_sdk_core import Address, TokenPayment, Transaction +from multiversx_sdk_core import Transaction -tx = Transaction( - nonce=90, - sender=Address.from_bech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"), - receiver=Address.from_bech32("erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx"), - value=TokenPayment.egld_from_amount("1.0"), +transaction = Transaction( + sender="erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th", + receiver="erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx", gas_limit=50000, - gas_price=1000000000, chain_id="D", - version=1 + nonce=77, + amount=1000000000000000000 ) -print(tx.to_dictionary()) +print(transaction.__dict__) ``` -In case you are using a **guarded** account you should also provide the _guardian_ argument when creating the 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): ``` -from multiversx_sdk_core import TransactionPayload - -data = TransactionPayload.from_str("for the book") - -tx = Transaction( - nonce=91, - sender=Address.from_bech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"), - receiver=Address.from_bech32("erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx"), - value=TokenPayment.egld_from_amount("3.0"), - data=data, - gas_limit=50000 + 1500 * data.length(), - gas_price=1000000000, +transaction = Transaction( + sender="erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th", + receiver="erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx", + gas_limit=50000, chain_id="D", - version=1 + nonce=77, + amount=1000000000000000000, + data=b"for the book" ) -print(tx.to_dictionary()) +print(transaction.__dict__) ``` -Alternatively, we can create an EGLD transfer using a **transaction builder** (as we will see below, transaction builders are more commonly used). But before that, we have to create a configuration object (for any builder that we might use): +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): ``` -from multiversx_sdk_core.transaction_builders import DefaultTransactionBuildersConfiguration +from multiversx_sdk_core.transaction_factories import TransactionsFactoryConfig -config = DefaultTransactionBuildersConfiguration(chain_id="D") +config = TransactionsFactoryConfig("D") ``` -The **transaction builder** is parametrized at instantiation, and the transaction is obtained by invoking the `build()` method: +The **transaction factory** is parametrized at instantiation, and the transaction is obtained by invoking the `create_transaction...` method: ``` -from multiversx_sdk_core.transaction_builders import EGLDTransferBuilder +from multiversx_sdk_core import TokenComputer +from multiversx_sdk_core.transaction_factories import TransferTransactionsFactory +transfer_factory = TransferTransactionsFactory(config, TokenComputer()) alice = Address.from_bech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th") bob = Address.from_bech32("erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx") -payment = TokenPayment.egld_from_amount("1.00") # With "data" field -builder = EGLDTransferBuilder( - config=config, +transaction = transfer_factory.create_transaction_for_native_token_transfer( sender=alice, receiver=bob, - payment=payment, - data="for the book", - # Nonce can be set now, or later, prior signing - nonce=42 + native_amount=1000000000000000000, + data="for the book" ) -tx = builder.build() -print("Transaction:", tx.to_dictionary()) -print("Transaction data:", tx.data) +print("Transaction:", transaction.__dict__) +print("Transaction data:", transaction.data) ``` Create a single ESDT transfer: ``` -from multiversx_sdk_core.transaction_builders import ESDTTransferBuilder +from multiversx_sdk_core import Token, TokenTransfer -payment = TokenPayment.fungible_from_amount("TEST-8b028f", "100.00", 2) +token = Token("TEST-8b028f") +transfer = TokenTransfer(token, 10000) -builder = ESDTTransferBuilder( - config=config, +transaction = transfer_factory.create_transaction_for_esdt_token_transfer( sender=alice, receiver=bob, - payment=payment + token_transfers=[transfer] ) -tx = builder.build() -print("Transaction:", tx.to_dictionary()) -print("Transaction data:", tx.data) +print("Transaction:", transaction.__dict__) +print("Transaction data:", transaction.data) ``` Create a single NFT transfer: -``` -from multiversx_sdk_core.transaction_builders import ESDTNFTTransferBuilder +Keep in mind, since we are sending a NFT, we `should` set the amount to `1`. -payment = TokenPayment.non_fungible("TEST-38f249", 1) +``` +token = Token(identifier="TEST-38f249", nonce=1) +transfer = TokenTransfer(token=token, amount=1) -builder = ESDTNFTTransferBuilder( - config=config, +transaction = transfer_factory.create_transaction_for_esdt_token_transfer( sender=alice, - destination=bob, - payment=payment + receiver=bob, + token_transfers=[transfer] ) -tx = builder.build() -print("Transaction:", tx.to_dictionary()) -print("Transaction data:", tx.data) +print("Transaction:", transaction.__dict__) +print("Transaction data:", transaction.data) ``` -Create a single SFT transfer (almost the same as above, the only difference being that for the token payment object we additionally use a quantity, as an integer): +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): ``` -payment = TokenPayment.semi_fungible("SEMI-9efd0f", 1, 5) +token = Token(identifier="SEMI-9efd0f", nonce=1) +transfer = TokenTransfer(token=token, amount=5) -builder = ESDTNFTTransferBuilder( - config=config, +transaction = transfer_factory.create_transaction_for_esdt_token_transfer( sender=alice, - destination=bob, - payment=payment + receiver=bob, + token_transfers=[transfer] ) -tx = builder.build() -print("Transaction:", tx.to_dictionary()) -print("Transaction data:", tx.data) +print("Transaction:", transaction.__dict__) +print("Transaction data:", transaction.data) ``` Create a multiple ESDT / NFT transfer: ``` -from multiversx_sdk_core.transaction_builders import MultiESDTNFTTransferBuilder +first_token = Token(identifier="TEST-38f249", nonce=1) +first_transfer = TokenTransfer(token=first_token, amount=1) -payment_one = TokenPayment.non_fungible("TEST-38f249", 1) -payment_two = TokenPayment.fungible_from_amount("BAR-c80d29", "10.00", 18) +second_token = Token(identifier="BAR-c80d29") +second_transfer = TokenTransfer(token=second_token, amount=10000000000000000000) -builder = MultiESDTNFTTransferBuilder( - config=config, +transaction = transfer_factory.create_transaction_for_esdt_token_transfer( sender=alice, - destination=bob, - payments=[payment_one, payment_two] + receiver=bob, + token_transfers=[first_transfer, second_transfer] ) -tx = builder.build() -print("Transaction:", tx.to_dictionary()) -print("Transaction data:", tx.data) +print("Transaction:", transaction.__dict__) +print("Transaction data:", transaction.data) ``` [comment]: # (mx-context-auto) @@ -283,20 +260,21 @@ network_config = provider.get_network_config() ``` 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_core import Transaction, TransactionComputer, Address from multiversx_sdk_wallet.user_signer import UserSigner signer = UserSigner.from_pem_file(Path("./testwallets/bob.pem")) +transaction_computer = TransactionComputer() inner_tx = Transaction( chain_id=network_config.chain_id, - sender=Address.from_bech32("erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx"), - receiver=Address.from_bech32("erd1qqqqqqqqqqqqqpgqqczn0ccd2gh8eqdswln7w9vzctv0dwq7d8ssm4y34z"), + sender="erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx", + receiver="erd1qqqqqqqqqqqqqpgqqczn0ccd2gh8eqdswln7w9vzctv0dwq7d8ssm4y34z", gas_limit=60000000, nonce=198, - data=TransactionPayload.from_str("add@05") + data=b"add@05" ) -inner_tx.signature = signer.sign(inner_tx.serialize_for_signing()) +inner_tx.signature = signer.sign(transaction_computer.compute_bytes_for_signing(inner_tx)) relayed_builder = RelayedTransactionV1Builder() relayed_builder.set_inner_transaction(inner_tx) @@ -305,7 +283,7 @@ 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()) +print(relayed_tx.__dict__) ``` [comment]: # (mx-context-auto) @@ -314,20 +292,19 @@ print(relayed_tx.to_dictionary()) ``` 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"), + sender="erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx", + receiver="erd1qqqqqqqqqqqqqpgqqczn0ccd2gh8eqdswln7w9vzctv0dwq7d8ssm4y34z", gas_limit=0, nonce=15, - data=TransactionPayload.from_str("add@05") + data=b"add@05" ) -inner_tx.signature = signer.sign(inner_tx.serialize_for_signing()) +inner_tx.signature = signer.sign(transaction_computer.compute_bytes_for_signing(inner_tx)) builder = RelayedTransactionV2Builder() builder.set_inner_transaction(inner_tx) @@ -337,7 +314,7 @@ builder.set_network_config(network_config) builder.set_relayer_address(Address.from_bech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th")) relayed_tx = builder.build() -print(relayed_tx.to_dictionary()) +print(relayed_tx.__dict__) ``` [comment]: # (mx-context-auto) @@ -348,92 +325,87 @@ Create a transaction to deploy a smart contract: ``` from pathlib import Path +from multiversx_sdk_core.transaction_factories import SmartContractTransactionsFactory -from multiversx_sdk_core import CodeMetadata -from multiversx_sdk_core.transaction_builders import ContractDeploymentBuilder - -metadata = CodeMetadata(upgradeable=True, readable=True, payable=True, payable_by_contract=True) +sc_factory = SmartContractTransactionsFactory(config, TokenComputer()) +bytecode = Path("./contracts/counter.wasm").read_bytes() -builder = ContractDeploymentBuilder( - config, - owner=alice, - deploy_arguments=[42, "test"], - code_metadata=metadata, - code=Path("./contracts/counter.wasm").read_bytes(), - gas_limit=10000000 +deploy_transaction = sc_factory.create_transaction_for_deploy( + sender=alice, + bytecode=bytecode, + arguments=[42, "test"], + gas_limit=10000000, + is_upgradeable=True, + is_readable=True, + is_payable=True, + is_payable_by_sc=True ) -tx = builder.build() -print("Transaction:", tx.to_dictionary()) -print("Transaction data:", tx.data) +print("Transaction:", deploy_transaction.__dict__) +print("Transaction data:", deploy_transaction.data) ``` Create a transaction to upgrade an existing smart contract: ``` -from multiversx_sdk_core.transaction_builders import ContractUpgradeBuilder - contract_address = Address.from_bech32("erd1qqqqqqqqqqqqqpgquzmh78klkqwt0p4rjys0qtp3la07gz4d396qn50nnm") -owner = Address.from_bech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th") -metadata = CodeMetadata(upgradeable=True, readable=True, payable=True, payable_by_contract=True) +bytecode = Path("./contracts/counter.wasm").read_bytes() -builder = ContractUpgradeBuilder( - config, +upgrade_transaction = sc_factory.create_transaction_for_upgrade( + sender=alice, contract=contract_address, - owner=owner, - upgrade_arguments=[42, "test"], - code_metadata=metadata, - code=Path("./contracts/counter.wasm").read_bytes(), - gas_limit=10000000 + bytecode=bytecode, + gas_limit=10000000, + arguments=[42, "test"], + is_upgradeable=True, + is_readable=True, + is_payable=True, + is_payable_by_sc=True ) -tx = builder.build() -print("Transaction:", tx.to_dictionary()) -print("Transaction data:", tx.data) +print("Transaction:", upgrade_transaction.__dict__) +print("Transaction data:", upgrade_transaction.data) ``` Create a transaction that invokes a smart contract function: ``` -from multiversx_sdk_core.transaction_builders import ContractCallBuilder - contract_address = Address.from_bech32("erd1qqqqqqqqqqqqqpgquzmh78klkqwt0p4rjys0qtp3la07gz4d396qn50nnm") -builder = ContractCallBuilder( - config, +call_transaction = sc_factory.create_transaction_for_execute( + sender=alice, contract=contract_address, - function_name="foo", - caller=alice, - call_arguments=[42, "test", bob], - gas_limit=10000000 + function="foo", + gas_limit=10000000, + arguments=[42, "test"] ) -tx = builder.build() -print("Transaction:", tx.to_dictionary()) -print("Transaction data:", tx.data) +print("Transaction:", call_transaction.__dict__) +print("Transaction data:", call_transaction.data) ``` Now, let's create a call that also transfers one or more tokens (**transfer & execute**): ``` -transfers = [ - TokenPayment.non_fungible("TEST-38f249", 1), - TokenPayment.fungible_from_amount("BAR-c80d29", "10.00", 18) -] +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] -builder = ContractCallBuilder( - config, +call_transaction = sc_factory.create_transaction_for_execute( + sender=alice, contract=contract_address, - function_name="hello", - caller=alice, - call_arguments=[42, "test", bob], + function="hello", gas_limit=10000000, - esdt_transfers=transfers + arguments=[42, "test"], + token_transfers=transfers ) -tx = builder.build() -print("Transaction:", tx.to_dictionary()) -print("Transaction data:", tx.data) +print("Transaction:", call_transaction.__dict__) +print("Transaction data:", call_transaction.data) ``` [comment]: # (mx-context-auto) @@ -447,7 +419,7 @@ from multiversx_sdk_core import ContractQueryBuilder from multiversx_sdk_core.interfaces import IAddress from multiversx_sdk_network_providers import ApiNetworkProvider -contract: IAddress = Address.from_bech32("erd1qqqqqqqqqqqqqpgqnzm7yhayarylux045qlm4lgzmtcsgrqg396qr9kupx") +contract: IAddress = Address.from_bech32("erd1qqqqqqqqqqqqqpgqqy34h7he2ya6qcagqre7ur7cc65vt0mxrc8qnudkr4") builder = ContractQueryBuilder( contract=contract, @@ -495,8 +467,8 @@ Given a mnemonic, one can derive keypairs: 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()) +print("Secret key:", secret_key.hex()) +print("Public key:", public_key.hex()) ``` A keypair can be saved as a JSON wallet: @@ -511,7 +483,7 @@ wallet.save(Path("./output/wallet.json"), address_hrp="erd") ``` from multiversx_sdk_wallet import UserPEM -label = Address(public_key.buffer, "erd").bech32() +label = Address(public_key.buffer, "erd").to_bech32() pem = UserPEM(label=label, secret_key=secret_key) pem.save(Path("./output/wallet.pem")) ``` @@ -530,8 +502,8 @@ from multiversx_sdk_wallet import UserWallet secret_key = UserWallet.load_secret_key(Path("./testwallets/withMnemonic.json"), "password", address_index=0) address = secret_key.generate_public_key().to_address("erd") -print("Secret key", secret_key.hex()) -print("Address", address) +print("Secret key:", secret_key.hex()) +print("Address:", address.to_bech32()) ``` Load a keystore that holds an **encrypted secret** key: @@ -540,8 +512,8 @@ Load a keystore that holds an **encrypted secret** key: secret_key = UserWallet.load_secret_key(Path("./testwallets/alice.json"), "password") address = secret_key.generate_public_key().to_address("erd") -print("Secret key", secret_key.hex()) -print("Address", address) +print("Secret key:", secret_key.hex()) +print("Address:", address.to_bech32()) ``` Load the secret key from a PEM file: @@ -551,8 +523,8 @@ from multiversx_sdk_wallet import UserPEM pem = UserPEM.from_file(Path("./testwallets/alice.pem")) -print("Secret key", pem.secret_key.hex()) -print("Public key", pem.public_key.hex()) +print("Secret key:", pem.secret_key.hex()) +print("Public key:", pem.public_key.hex()) ``` [comment]: # (mx-context-auto) @@ -573,14 +545,6 @@ Creating a `UserSigner` from a PEM file: signer = UserSigner.from_pem_file(Path("./testwallets/alice.pem")) ``` -Signable objects (messages, transactions) must adhere to the following interface: -``` -class ISignable(Protocol): - def serialize_for_signing(self) -> bytes: ... -``` - -Both `Transaction` and `Message` - defined in `multiversx_sdk_core` - implement `ISignable`. - Signing a transaction: ``` @@ -588,28 +552,30 @@ from multiversx_sdk_core import Transaction tx = Transaction( nonce=90, - sender=Address.from_bech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th"), - receiver=Address.from_bech32("erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx"), - value=TokenPayment.egld_from_amount("1.0"), + sender="erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th", + receiver="erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx", + amount=1000000000000000000, gas_limit=50000, - gas_price=1000000000, - chain_id="D", - version=1 + chain_id="D" ) -tx.signature = signer.sign(tx.serialize_for_signing()) -print("Signature", tx.signature.hex()) +transaction_computer = TransactionComputer() + +tx.signature = signer.sign(transaction_computer.compute_bytes_for_signing(tx)) +print("Signature:", tx.signature.hex()) ``` Signing an arbitrary message: ``` -from multiversx_sdk_core import MessageV1 +from multiversx_sdk_core import Message, MessageComputer + +message = Message(b"hello") +message_computer = MessageComputer() -message = MessageV1.from_string("hello") -message.signature = signer.sign(message.serialize_for_signing()) +message.signature = signer.sign(message_computer.compute_bytes_for_signing(message)) -print("Signature", message.signature.hex()) +print("Signature:", message.signature.hex()) ``` [comment]: # (mx-context-auto) @@ -622,29 +588,25 @@ Creating a `UserVerifier`: from multiversx_sdk_core import Address from multiversx_sdk_wallet import UserVerifier -alice = Address.from_bech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th") -bob = Address.from_bech32("erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx") +alice = Address.new_from_bech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th") +bob = Address.new_from_bech32("erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx") + alice_verifier = UserVerifier.from_address(alice) bob_verifier = UserVerifier.from_address(bob) ``` -For objects to support signature verification, they must adhere to the following interface: +Verifying a signature: ``` -class IVerifiable(Protocol): - signature: ISignature - def serialize_for_signing(self) -> bytes: ... -``` - -Both `Transaction` and `Message` - defined in `multiversx_sdk_core` - implement `IVerifiable`. +from multiversx_sdk_core import TransactionComputer, MessageComputer -Verifying a signature: +transaction_computer = TransactionComputer() +message_computer = MessageComputer() -``` -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.serialize_for_signing(), 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.serialize_for_signing(), message.signature)) +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_signing(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_signing(message), message.signature)) ``` [comment]: # (mx-context-auto) @@ -678,7 +640,7 @@ In order to fetch network parameters, do as follows: ``` config = provider.get_network_config() -print("Chain ID", config.chain_id) +print("Chain ID:", config.chain_id) print("Min gas price:", config.min_gas_price) ``` @@ -691,8 +653,8 @@ The following snippet fetches (from the Network) the **nonce** and the **balance ``` account_on_network = provider.get_account(alice) -print("Nonce", account_on_network.nonce) -print("Balance", account_on_network.balance) +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): @@ -718,8 +680,8 @@ Broadcast a single transaction: alice = Address.from_bech32("erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th") tx = Transaction( - sender=alice, - receiver=alice, + sender=alice.to_bech32(), + receiver=alice.to_bech32(), gas_limit=50000, chain_id="D" ) @@ -727,7 +689,7 @@ tx = Transaction( alice_on_network = provider.get_account(alice) tx.nonce = alice_on_network.nonce -tx.signature = signer.sign(tx.serialize_for_signing()) +tx.signature = signer.sign(transaction_computer.compute_bytes_for_signing(tx)) hash = provider.send_transaction(tx) print("Transaction hash:", hash) @@ -737,22 +699,22 @@ Broadcast multiple transactions: ``` tx_1 = Transaction( - sender=alice, - receiver=alice, + sender=alice.to_bech32(), + receiver=alice.to_bech32(), gas_limit=50000, chain_id="D" ) tx_2 = Transaction( - sender=alice, - receiver=alice, + sender=alice.to_bech32(), + receiver=alice.to_bech32(), gas_limit=50000, chain_id="D" ) tx_3 = Transaction( - sender=alice, - receiver=alice, + sender=alice.to_bech32(), + receiver=alice.to_bech32(), gas_limit=50000, chain_id="D" ) @@ -764,9 +726,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.serialize_for_signing()) -tx_2.signature = signer.sign(tx_2.serialize_for_signing()) -tx_3.signature = signer.sign(tx_3.serialize_for_signing()) +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) @@ -775,7 +737,7 @@ print("Transactions hashes:", hashes) Now let's fetch a previously-broadcasted transaction: ``` -tx_on_network = provider.get_transaction("09e3b68d39f3759913239b927c7feb9ac871c8877e76bc56e1be45a2a597eb53", with_process_status=True) +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) ``` From 3612a2ae3c3d0c7e2ee66a41ed9ee89dda6cbde6 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Tue, 7 Nov 2023 15:59:28 +0200 Subject: [PATCH 2/3] git push --- docs/sdk-and-tools/sdk-py/sdk-py-cookbook.md | 38 ++++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) 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 797f3d327..0f00199fa 100644 --- a/docs/sdk-and-tools/sdk-py/sdk-py-cookbook.md +++ b/docs/sdk-and-tools/sdk-py/sdk-py-cookbook.md @@ -3,9 +3,8 @@ id: sdk-py-cookbook title: Cookbook --- -[comment]: # (mx-abstract) - -[comment]: # (mx-context-auto) +[comment]: # "mx-abstract" +[comment]: # "mx-context-auto" ## Overview @@ -33,7 +32,7 @@ Documentation is preliminary and subject to change (the packages might suffer a -[comment]: # (mx-context-auto) +[comment]: # "mx-context-auto" ## Addresses @@ -98,7 +97,7 @@ address = Address.new_from_bech32("erd1qqqqqqqqqqqqqpgquzmh78klkqwt0p4rjys0qtp3l print("Is contract:", address.is_smart_contract()) ``` -[comment]: # (mx-context-auto) +[comment]: # "mx-context-auto" ## EGLD / ESDT transfers @@ -144,7 +143,7 @@ Alternatively, we can create an EGLD transfer using a **transaction factory** (a ``` from multiversx_sdk_core.transaction_factories import TransactionsFactoryConfig -config = TransactionsFactoryConfig("D") +config = TransactionsFactoryConfig(chain_id="D") ``` The **transaction factory** is parametrized at instantiation, and the transaction is obtained by invoking the `create_transaction...` method: @@ -240,7 +239,7 @@ print("Transaction:", transaction.__dict__) print("Transaction data:", transaction.data) ``` -[comment]: # (mx-context-auto) +[comment]: # "mx-context-auto" ## Relayed Transactions @@ -253,7 +252,7 @@ provider = ProxyNetworkProvider("https://devnet-gateway.multiversx.com") network_config = provider.get_network_config() ``` -[comment]: # (mx-context-auto) +[comment]: # "mx-context-auto" ### Relayed V1 @@ -286,7 +285,7 @@ relayed_tx = relayed_builder.build() print(relayed_tx.__dict__) ``` -[comment]: # (mx-context-auto) +[comment]: # "mx-context-auto" ### Relayed V2 @@ -317,7 +316,7 @@ relayed_tx = builder.build() print(relayed_tx.__dict__) ``` -[comment]: # (mx-context-auto) +[comment]: # "mx-context-auto" ## Contract deployments and interactions @@ -408,7 +407,7 @@ print("Transaction:", call_transaction.__dict__) print("Transaction data:", call_transaction.data) ``` -[comment]: # (mx-context-auto) +[comment]: # "mx-context-auto" ## Contract queries @@ -437,7 +436,7 @@ print("Return code:", response.return_code) print("Return data:", response.return_data) ``` -[comment]: # (mx-context-auto) +[comment]: # "mx-context-auto" ## Creating wallets @@ -488,7 +487,7 @@ pem = UserPEM(label=label, secret_key=secret_key) pem.save(Path("./output/wallet.pem")) ``` -[comment]: # (mx-context-auto) +[comment]: # "mx-context-auto" ## Loading wallets @@ -527,7 +526,7 @@ print("Secret key:", pem.secret_key.hex()) print("Public key:", pem.public_key.hex()) ``` -[comment]: # (mx-context-auto) +[comment]: # "mx-context-auto" ## Signing objects @@ -578,7 +577,7 @@ message.signature = signer.sign(message_computer.compute_bytes_for_signing(messa print("Signature:", message.signature.hex()) ``` -[comment]: # (mx-context-auto) +[comment]: # "mx-context-auto" ## Verifying signatures @@ -609,7 +608,7 @@ print(f"Is signature of Bob?", bob_verifier.verify(transaction_computer.compute_ print(f"Is signature of Bob?", bob_verifier.verify(message_computer.compute_bytes_for_signing(message), message.signature)) ``` -[comment]: # (mx-context-auto) +[comment]: # "mx-context-auto" ## Creating network providers @@ -631,7 +630,7 @@ from multiversx_sdk_network_providers import ProxyNetworkProvider provider = ProxyNetworkProvider("https://devnet-gateway.multiversx.com") ``` -[comment]: # (mx-context-auto) +[comment]: # "mx-context-auto" ## Fetching network parameters @@ -644,7 +643,7 @@ print("Chain ID:", config.chain_id) print("Min gas price:", config.min_gas_price) ``` -[comment]: # (mx-context-auto) +[comment]: # "mx-context-auto" ## Fetching account state @@ -670,7 +669,7 @@ tx.nonce = nonce_holder.get_nonce_then_increment() For further reference, please see [nonce management](/integrators/creating-transactions/#nonce-management). -[comment]: # (mx-context-auto) +[comment]: # "mx-context-auto" ## Broadcasting transactions @@ -741,4 +740,5 @@ tx_on_network = provider.get_transaction("9270a6879b682a7b310c659f58b641ccdd5f08 print("Status:", tx_on_network.status) print("Is completed:", tx_on_network.is_completed) ``` + From 211644189be5c54e8b6109af7b2061aa390f0cb7 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Tue, 7 Nov 2023 16:06:44 +0200 Subject: [PATCH 3/3] add bot markers --- docs/sdk-and-tools/sdk-py/sdk-py-cookbook.md | 32 ++++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) 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 0f00199fa..9360074ce 100644 --- a/docs/sdk-and-tools/sdk-py/sdk-py-cookbook.md +++ b/docs/sdk-and-tools/sdk-py/sdk-py-cookbook.md @@ -4,7 +4,7 @@ title: Cookbook --- [comment]: # "mx-abstract" -[comment]: # "mx-context-auto" +[comment]: # (mx-context-auto) ## Overview @@ -32,7 +32,7 @@ Documentation is preliminary and subject to change (the packages might suffer a -[comment]: # "mx-context-auto" +[comment]: # (mx-context-auto) ## Addresses @@ -97,7 +97,7 @@ address = Address.new_from_bech32("erd1qqqqqqqqqqqqqpgquzmh78klkqwt0p4rjys0qtp3l print("Is contract:", address.is_smart_contract()) ``` -[comment]: # "mx-context-auto" +[comment]: # (mx-context-auto) ## EGLD / ESDT transfers @@ -239,7 +239,7 @@ print("Transaction:", transaction.__dict__) print("Transaction data:", transaction.data) ``` -[comment]: # "mx-context-auto" +[comment]: # (mx-context-auto) ## Relayed Transactions @@ -252,7 +252,7 @@ provider = ProxyNetworkProvider("https://devnet-gateway.multiversx.com") network_config = provider.get_network_config() ``` -[comment]: # "mx-context-auto" +[comment]: # (mx-context-auto) ### Relayed V1 @@ -285,7 +285,7 @@ relayed_tx = relayed_builder.build() print(relayed_tx.__dict__) ``` -[comment]: # "mx-context-auto" +[comment]: # (mx-context-auto) ### Relayed V2 @@ -316,7 +316,7 @@ relayed_tx = builder.build() print(relayed_tx.__dict__) ``` -[comment]: # "mx-context-auto" +[comment]: # (mx-context-auto) ## Contract deployments and interactions @@ -407,7 +407,7 @@ print("Transaction:", call_transaction.__dict__) print("Transaction data:", call_transaction.data) ``` -[comment]: # "mx-context-auto" +[comment]: # (mx-context-auto) ## Contract queries @@ -436,7 +436,7 @@ print("Return code:", response.return_code) print("Return data:", response.return_data) ``` -[comment]: # "mx-context-auto" +[comment]: # (mx-context-auto) ## Creating wallets @@ -487,7 +487,7 @@ pem = UserPEM(label=label, secret_key=secret_key) pem.save(Path("./output/wallet.pem")) ``` -[comment]: # "mx-context-auto" +[comment]: # (mx-context-auto) ## Loading wallets @@ -526,7 +526,7 @@ print("Secret key:", pem.secret_key.hex()) print("Public key:", pem.public_key.hex()) ``` -[comment]: # "mx-context-auto" +[comment]: # (mx-context-auto) ## Signing objects @@ -577,7 +577,7 @@ message.signature = signer.sign(message_computer.compute_bytes_for_signing(messa print("Signature:", message.signature.hex()) ``` -[comment]: # "mx-context-auto" +[comment]: # (mx-context-auto) ## Verifying signatures @@ -608,7 +608,7 @@ print(f"Is signature of Bob?", bob_verifier.verify(transaction_computer.compute_ print(f"Is signature of Bob?", bob_verifier.verify(message_computer.compute_bytes_for_signing(message), message.signature)) ``` -[comment]: # "mx-context-auto" +[comment]: # (mx-context-auto) ## Creating network providers @@ -630,7 +630,7 @@ from multiversx_sdk_network_providers import ProxyNetworkProvider provider = ProxyNetworkProvider("https://devnet-gateway.multiversx.com") ``` -[comment]: # "mx-context-auto" +[comment]: # (mx-context-auto) ## Fetching network parameters @@ -643,7 +643,7 @@ print("Chain ID:", config.chain_id) print("Min gas price:", config.min_gas_price) ``` -[comment]: # "mx-context-auto" +[comment]: # (mx-context-auto) ## Fetching account state @@ -669,7 +669,7 @@ tx.nonce = nonce_holder.get_nonce_then_increment() For further reference, please see [nonce management](/integrators/creating-transactions/#nonce-management). -[comment]: # "mx-context-auto" +[comment]: # (mx-context-auto) ## Broadcasting transactions