From dea51eae9fb38f5776cd93b99a3bec0eb0136e1a Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Wed, 7 Feb 2024 15:37:52 +0200 Subject: [PATCH 1/4] add jupyter notebook with examples --- examples/Cookbook.ipynb | 1564 +++++++++++++++++ examples/output/wallet.json | 23 + examples/output/wallet.pem | 5 + examples/output/walletWithMnemonic.json | 21 + .../testutils/testdata/counter.wasm | Bin 0 -> 335 bytes pyproject.toml | 6 + requirements-dev.txt | 1 + 7 files changed, 1620 insertions(+) create mode 100644 examples/Cookbook.ipynb create mode 100644 examples/output/wallet.json create mode 100644 examples/output/wallet.pem create mode 100644 examples/output/walletWithMnemonic.json create mode 100755 multiversx_sdk/testutils/testdata/counter.wasm diff --git a/examples/Cookbook.ipynb b/examples/Cookbook.ipynb new file mode 100644 index 00000000..b8248153 --- /dev/null +++ b/examples/Cookbook.ipynb @@ -0,0 +1,1564 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 57, + "metadata": {}, + "outputs": [], + "source": [ + "import sys\n", + "sys.path.append(\"..\") # Add the parent directory of 'examples' to the Python path\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Addresses" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create an `Address` object from a _bech32-encoded_ string:" + ] + }, + { + "cell_type": "code", + "execution_count": 58, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Address (bech32-encoded) erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th\n", + "Public key (hex-encoded): 0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1\n", + "Public key (hex-encoded): 0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1\n" + ] + } + ], + "source": [ + "from multiversx_sdk.core import Address\n", + "\n", + "address = Address.new_from_bech32(\"erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th\")\n", + "\n", + "print(\"Address (bech32-encoded)\", address.to_bech32())\n", + "print(\"Public key (hex-encoded):\", address.to_hex())\n", + "print(\"Public key (hex-encoded):\", address.pubkey.hex())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "... 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):" + ] + }, + { + "cell_type": "code", + "execution_count": 59, + "metadata": {}, + "outputs": [], + "source": [ + "address = Address.new_from_hex(\"0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1\", \"erd\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "... or from a raw public key:" + ] + }, + { + "cell_type": "code", + "execution_count": 60, + "metadata": {}, + "outputs": [], + "source": [ + "pubkey = bytes.fromhex(\"0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1\")\n", + "address = Address(pubkey, \"erd\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Alternatively, you can use an `AddressFactory` (initialized with a specific **HRP**) to create addresses:" + ] + }, + { + "cell_type": "code", + "execution_count": 61, + "metadata": {}, + "outputs": [], + "source": [ + "from multiversx_sdk.core import AddressFactory\n", + "\n", + "factory = AddressFactory(\"erd\")\n", + "\n", + "address = factory.create_from_bech32(\"erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th\")\n", + "address = factory.create_from_hex(\"0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1\")\n", + "address = factory.create_from_public_key(bytes.fromhex(\"0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1\"))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Addresses can be converted from one representation to another as follows:" + ] + }, + { + "cell_type": "code", + "execution_count": 62, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th\n", + "0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1\n" + ] + } + ], + "source": [ + "print(address.to_bech32())\n", + "print(address.to_hex())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Getting the shard of an address:" + ] + }, + { + "cell_type": "code", + "execution_count": 63, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Shard: 1\n" + ] + } + ], + "source": [ + "from multiversx_sdk.core import AddressComputer\n", + "\n", + "address_computer = AddressComputer(number_of_shards=3)\n", + "print(\"Shard:\", address_computer.get_shard_of_address(address))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Checking whether an address is a smart contract:" + ] + }, + { + "cell_type": "code", + "execution_count": 64, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Is contract: True\n" + ] + } + ], + "source": [ + "address = Address.new_from_bech32(\"erd1qqqqqqqqqqqqqpgquzmh78klkqwt0p4rjys0qtp3la07gz4d396qn50nnm\")\n", + "\n", + "print(\"Is contract:\", address.is_smart_contract())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## EGLD / ESDT transfers" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create an EGLD transfer:" + ] + }, + { + "cell_type": "code", + "execution_count": 65, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'chain_id': 'D', 'sender': 'erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th', 'receiver': 'erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx', 'gas_limit': 50000, 'nonce': 77, 'value': 1000000000000000000, 'data': b'', 'signature': b'', 'sender_username': '', 'receiver_username': '', 'gas_price': 1000000000, 'version': 2, 'options': 0, 'guardian': '', 'guardian_signature': b''}\n" + ] + } + ], + "source": [ + "from multiversx_sdk.core import Transaction\n", + "\n", + "transaction = Transaction(\n", + " sender=\"erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th\",\n", + " receiver=\"erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx\",\n", + " gas_limit=50000,\n", + " chain_id=\"D\",\n", + " nonce=77,\n", + " value=1000000000000000000\n", + ")\n", + "\n", + "print(transaction.__dict__)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In case you are using a **guarded** account you should also populate the `guardian` and `guardian_signature` fields after creating the transaction." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We'll see later how to [sign](#signing-objects) and [broadcast](#broadcasting-transactions) a transaction." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create an EGLD transfer, but this time with a payload (data):" + ] + }, + { + "cell_type": "code", + "execution_count": 66, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'chain_id': 'D', 'sender': 'erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th', 'receiver': 'erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx', 'gas_limit': 50000, 'nonce': 77, 'value': 1000000000000000000, 'data': b'for the book', 'signature': b'', 'sender_username': '', 'receiver_username': '', 'gas_price': 1000000000, 'version': 2, 'options': 0, 'guardian': '', 'guardian_signature': b''}\n" + ] + } + ], + "source": [ + "transaction = Transaction(\n", + " sender=\"erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th\",\n", + " receiver=\"erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx\",\n", + " gas_limit=50000,\n", + " chain_id=\"D\",\n", + " nonce=77,\n", + " value=1000000000000000000,\n", + " data=b\"for the book\"\n", + ")\n", + "\n", + "print(transaction.__dict__)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "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):" + ] + }, + { + "cell_type": "code", + "execution_count": 67, + "metadata": {}, + "outputs": [], + "source": [ + "from multiversx_sdk.core.transaction_factories import TransactionsFactoryConfig\n", + "\n", + "config = TransactionsFactoryConfig(chain_id=\"D\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The **transaction factory** is parametrized at instantiation, and the transaction is obtained by invoking the `create_transaction...` method:" + ] + }, + { + "cell_type": "code", + "execution_count": 68, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Transaction: {'chain_id': 'D', 'sender': 'erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th', 'receiver': 'erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx', 'gas_limit': 68000, 'nonce': 0, 'value': 1000000000000000000, 'data': b'for the book', 'signature': b'', 'sender_username': '', 'receiver_username': '', 'gas_price': 1000000000, 'version': 2, 'options': 0, 'guardian': '', 'guardian_signature': b''}\n", + "Transaction data: b'for the book'\n" + ] + } + ], + "source": [ + "from multiversx_sdk.core import TokenComputer\n", + "from multiversx_sdk.core.transaction_factories import \\\n", + " TransferTransactionsFactory\n", + "\n", + "transfer_factory = TransferTransactionsFactory(config, TokenComputer())\n", + "alice = Address.from_bech32(\"erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th\")\n", + "bob = Address.from_bech32(\"erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx\")\n", + "\n", + "# With \"data\" field\n", + "transaction = transfer_factory.create_transaction_for_native_token_transfer(\n", + " sender=alice,\n", + " receiver=bob,\n", + " native_amount=1000000000000000000,\n", + " data=\"for the book\"\n", + ")\n", + "\n", + "print(\"Transaction:\", transaction.__dict__)\n", + "print(\"Transaction data:\", transaction.data)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a single ESDT transfer:" + ] + }, + { + "cell_type": "code", + "execution_count": 69, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Transaction: {'chain_id': 'D', 'sender': 'erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th', 'receiver': 'erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx', 'gas_limit': 410000, 'nonce': 0, 'value': 0, 'data': b'ESDTTransfer@544553542d386230323866@2710', 'signature': b'', 'sender_username': '', 'receiver_username': '', 'gas_price': 1000000000, 'version': 2, 'options': 0, 'guardian': '', 'guardian_signature': b''}\n", + "Transaction data: b'ESDTTransfer@544553542d386230323866@2710'\n" + ] + } + ], + "source": [ + "from multiversx_sdk.core import Token, TokenTransfer\n", + "\n", + "token = Token(\"TEST-8b028f\")\n", + "transfer = TokenTransfer(token, 10000)\n", + "\n", + "transaction = transfer_factory.create_transaction_for_esdt_token_transfer(\n", + " sender=alice,\n", + " receiver=bob,\n", + " token_transfers=[transfer]\n", + ")\n", + "\n", + "print(\"Transaction:\", transaction.__dict__)\n", + "print(\"Transaction data:\", transaction.data)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a single NFT transfer:\n", + "\n", + "Keep in mind, since we are sending a NFT, we `should` set the amount to `1`." + ] + }, + { + "cell_type": "code", + "execution_count": 70, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Transaction: {'chain_id': 'D', 'sender': 'erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th', 'receiver': 'erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th', 'gas_limit': 1213500, 'nonce': 0, 'value': 0, 'data': b'ESDTNFTTransfer@544553542d333866323439@01@01@8049d639e5a6980d1cd2392abcce41029cda74a1563523a202f09641cc2618f8', 'signature': b'', 'sender_username': '', 'receiver_username': '', 'gas_price': 1000000000, 'version': 2, 'options': 0, 'guardian': '', 'guardian_signature': b''}\n", + "Transaction data: b'ESDTNFTTransfer@544553542d333866323439@01@01@8049d639e5a6980d1cd2392abcce41029cda74a1563523a202f09641cc2618f8'\n" + ] + } + ], + "source": [ + "token = Token(identifier=\"TEST-38f249\", nonce=1)\n", + "transfer = TokenTransfer(token=token, amount=1)\n", + "\n", + "transaction = transfer_factory.create_transaction_for_esdt_token_transfer(\n", + " sender=alice,\n", + " receiver=bob,\n", + " token_transfers=[transfer]\n", + ")\n", + "\n", + "print(\"Transaction:\", transaction.__dict__)\n", + "print(\"Transaction data:\", transaction.data)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "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):" + ] + }, + { + "cell_type": "code", + "execution_count": 71, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Transaction: {'chain_id': 'D', 'sender': 'erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th', 'receiver': 'erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th', 'gas_limit': 1213500, 'nonce': 0, 'value': 0, 'data': b'ESDTNFTTransfer@53454d492d396566643066@01@05@8049d639e5a6980d1cd2392abcce41029cda74a1563523a202f09641cc2618f8', 'signature': b'', 'sender_username': '', 'receiver_username': '', 'gas_price': 1000000000, 'version': 2, 'options': 0, 'guardian': '', 'guardian_signature': b''}\n", + "Transaction data: b'ESDTNFTTransfer@53454d492d396566643066@01@05@8049d639e5a6980d1cd2392abcce41029cda74a1563523a202f09641cc2618f8'\n" + ] + } + ], + "source": [ + "token = Token(identifier=\"SEMI-9efd0f\", nonce=1)\n", + "transfer = TokenTransfer(token=token, amount=5)\n", + "\n", + "transaction = transfer_factory.create_transaction_for_esdt_token_transfer(\n", + " sender=alice,\n", + " receiver=bob,\n", + " token_transfers=[transfer]\n", + ")\n", + "\n", + "print(\"Transaction:\", transaction.__dict__)\n", + "print(\"Transaction data:\", transaction.data)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a multiple ESDT / NFT transfer:" + ] + }, + { + "cell_type": "code", + "execution_count": 72, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Transaction: {'chain_id': 'D', 'sender': 'erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th', 'receiver': 'erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th', 'gas_limit': 1484000, 'nonce': 0, 'value': 0, 'data': b'MultiESDTNFTTransfer@8049d639e5a6980d1cd2392abcce41029cda74a1563523a202f09641cc2618f8@02@544553542d333866323439@01@01@4241522d633830643239@@8ac7230489e80000', 'signature': b'', 'sender_username': '', 'receiver_username': '', 'gas_price': 1000000000, 'version': 2, 'options': 0, 'guardian': '', 'guardian_signature': b''}\n", + "Transaction data: b'MultiESDTNFTTransfer@8049d639e5a6980d1cd2392abcce41029cda74a1563523a202f09641cc2618f8@02@544553542d333866323439@01@01@4241522d633830643239@@8ac7230489e80000'\n" + ] + } + ], + "source": [ + "first_token = Token(identifier=\"TEST-38f249\", nonce=1)\n", + "first_transfer = TokenTransfer(token=first_token, amount=1)\n", + "\n", + "second_token = Token(identifier=\"BAR-c80d29\")\n", + "second_transfer = TokenTransfer(token=second_token, amount=10000000000000000000)\n", + "\n", + "transaction = transfer_factory.create_transaction_for_esdt_token_transfer(\n", + " sender=alice,\n", + " receiver=bob,\n", + " token_transfers=[first_transfer, second_transfer]\n", + ")\n", + "\n", + "print(\"Transaction:\", transaction.__dict__)\n", + "print(\"Transaction data:\", transaction.data)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Relayed Transactions" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "First, we get the newtwork configuration using the network providers." + ] + }, + { + "cell_type": "code", + "execution_count": 73, + "metadata": {}, + "outputs": [], + "source": [ + "from multiversx_sdk.network_providers import ProxyNetworkProvider\n", + "\n", + "provider = ProxyNetworkProvider(\"https://devnet-gateway.multiversx.com\")\n", + "network_config = provider.get_network_config()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Relayed V1" + ] + }, + { + "cell_type": "code", + "execution_count": 74, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'chain_id': 'D', 'sender': 'erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th', 'receiver': 'erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx', 'gas_limit': 61052000, 'nonce': 2627, 'value': 0, 'data': b'relayedTx@7b226e6f6e6365223a3139382c2273656e646572223a2267456e574f65576d6d413063306a6b71764d354241707a61644b46574e534f69417643575163776d4750673d222c227265636569766572223a22414141414141414141414146414159464e2b4d4e5569353867624233352b635667734c59397267656165453d222c2276616c7565223a302c226761735072696365223a313030303030303030302c226761734c696d6974223a36303030303030302c2264617461223a225957526b51444131222c227369676e6174757265223a22474c43344a59354c30756f4a4d7048753448505767474148476f476a7a476136352b754830302f774c515945515230645a4c635134546d7155394b6d515a3554716d4c6e5351345657466f354366793963642b6c43413d3d222c22636861696e4944223a2252413d3d222c2276657273696f6e223a327d', 'signature': b'', 'sender_username': '', 'receiver_username': '', 'gas_price': 1000000000, 'version': 2, 'options': 0, 'guardian': '', 'guardian_signature': b''}\n" + ] + } + ], + "source": [ + "from pathlib import Path\n", + "\n", + "from multiversx_sdk.core import Address, Transaction, TransactionComputer\n", + "from multiversx_sdk.core.transaction_factories.relayed_transactions_factory import \\\n", + " RelayedTransactionsFactory\n", + "from multiversx_sdk.core.transaction_factories.transactions_factory_config import \\\n", + " TransactionsFactoryConfig\n", + "from multiversx_sdk.wallet.user_signer import UserSigner\n", + "\n", + "signer = UserSigner.from_pem_file(Path(\"../multiversx_sdk/testutils/testwallets/bob.pem\"))\n", + "transaction_computer = TransactionComputer()\n", + "\n", + "inner_tx = Transaction(\n", + " chain_id=network_config.chain_id,\n", + " sender=\"erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx\",\n", + " receiver=\"erd1qqqqqqqqqqqqqpgqqczn0ccd2gh8eqdswln7w9vzctv0dwq7d8ssm4y34z\",\n", + " gas_limit=60000000,\n", + " nonce=198,\n", + " data=b\"add@05\"\n", + ")\n", + "inner_tx.signature = signer.sign(transaction_computer.compute_bytes_for_signing(inner_tx))\n", + "\n", + "config = TransactionsFactoryConfig(chain_id=\"D\")\n", + "factory = RelayedTransactionsFactory(config=config)\n", + "relayer = Address.from_bech32(\"erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th\")\n", + "\n", + "relayed_tx = factory.create_relayed_v1_transaction(\n", + " inner_transaction=inner_tx,\n", + " relayer_address=relayer\n", + ")\n", + "relayed_tx.nonce = 2627\n", + "\n", + "print(relayed_tx.__dict__)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Relayed V2" + ] + }, + { + "cell_type": "code", + "execution_count": 75, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "WARNING:address:The `serialize()` method is deprecated and will soon be removed\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{'chain_id': 'D', 'sender': 'erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th', 'receiver': 'erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx', 'gas_limit': 60381500, 'nonce': 37, 'value': 0, 'data': b'relayedTxV2@00000000000000000500060537e30d522e7c81b077e7e71582c2d8f6b81e69e1@0f@616464403035@65072a9118db14747a4f1cf857a6e4373e3e9ead6ea6036f5111bf68803c5cadfdc44d37a21b920449b5e83c783975425c3f476020173ac0fc71481646d4a900', 'signature': b'', 'sender_username': '', 'receiver_username': '', 'gas_price': 1000000000, 'version': 2, 'options': 0, 'guardian': '', 'guardian_signature': b''}\n" + ] + } + ], + "source": [ + "from pathlib import Path\n", + "\n", + "from multiversx_sdk.core import Address, Transaction, TransactionComputer\n", + "from multiversx_sdk.core.transaction_factories.relayed_transactions_factory import \\\n", + " RelayedTransactionsFactory\n", + "from multiversx_sdk.core.transaction_factories.transactions_factory_config import \\\n", + " TransactionsFactoryConfig\n", + "from multiversx_sdk.wallet.user_signer import UserSigner\n", + "\n", + "signer = UserSigner.from_pem_file(Path(\"../multiversx_sdk/testutils/testwallets/bob.pem\"))\n", + "transaction_computer = TransactionComputer()\n", + "\n", + "# for the relayedV2 transactions, the gasLimit for the inner transaction should be 0\n", + "inner_tx = Transaction(\n", + " chain_id=network_config.chain_id,\n", + " sender=\"erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx\",\n", + " receiver=\"erd1qqqqqqqqqqqqqpgqqczn0ccd2gh8eqdswln7w9vzctv0dwq7d8ssm4y34z\",\n", + " gas_limit=0,\n", + " nonce=15,\n", + " data=b\"add@05\"\n", + " )\n", + "inner_tx.signature = signer.sign(transaction_computer.compute_bytes_for_signing(inner_tx))\n", + "\n", + "config = TransactionsFactoryConfig(chain_id=\"D\")\n", + "factory = RelayedTransactionsFactory(config=config)\n", + "relayer = Address.from_bech32(\"erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th\")\n", + "\n", + "relayed_tx = factory.create_relayed_v2_transaction(\n", + " inner_transaction=inner_tx,\n", + " inner_transaction_gas_limit=60_000_000,\n", + " relayer_address=relayer\n", + ")\n", + "relayed_tx.nonce = 37\n", + "\n", + "print(relayed_tx.__dict__)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Contract deployments and interactions" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a transaction to deploy a smart contract:" + ] + }, + { + "cell_type": "code", + "execution_count": 76, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Transaction: {'chain_id': 'D', 'sender': 'erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th', 'receiver': 'erd1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq6gq4hu', 'gas_limit': 10000000, 'nonce': 0, 'value': 0, 'data': b'0061736d0100000001150460037f7f7e017f60027f7f017e60017e0060000002420303656e7611696e74363473746f7261676553746f7265000003656e7610696e74363473746f726167654c6f6164000103656e760b696e74363466696e6973680002030504030303030405017001010105030100020608017f01419088040b072f05066d656d6f7279020004696e6974000309696e6372656d656e7400040964656372656d656e7400050367657400060a8a01041300418088808000410742011080808080001a0b2e01017e4180888080004107418088808000410710818080800042017c22001080808080001a20001082808080000b2e01017e41808880800041074180888080004107108180808000427f7c22001080808080001a20001082808080000b160041808880800041071081808080001082808080000b0b0f01004180080b08434f554e54455200@0500@0506@2a@74657374', 'signature': b'', 'sender_username': '', 'receiver_username': '', 'gas_price': 1000000000, 'version': 2, 'options': 0, 'guardian': '', 'guardian_signature': b''}\n", + "Transaction data: b'0061736d0100000001150460037f7f7e017f60027f7f017e60017e0060000002420303656e7611696e74363473746f7261676553746f7265000003656e7610696e74363473746f726167654c6f6164000103656e760b696e74363466696e6973680002030504030303030405017001010105030100020608017f01419088040b072f05066d656d6f7279020004696e6974000309696e6372656d656e7400040964656372656d656e7400050367657400060a8a01041300418088808000410742011080808080001a0b2e01017e4180888080004107418088808000410710818080800042017c22001080808080001a20001082808080000b2e01017e41808880800041074180888080004107108180808000427f7c22001080808080001a20001082808080000b160041808880800041071081808080001082808080000b0b0f01004180080b08434f554e54455200@0500@0506@2a@74657374'\n" + ] + } + ], + "source": [ + "from pathlib import Path\n", + "\n", + "from multiversx_sdk.core.transaction_factories import \\\n", + " SmartContractTransactionsFactory\n", + "\n", + "sc_factory = SmartContractTransactionsFactory(config, TokenComputer())\n", + "bytecode = Path(\"../multiversx_sdk/testutils/testdata/counter.wasm\").read_bytes()\n", + "\n", + "deploy_transaction = sc_factory.create_transaction_for_deploy(\n", + " sender=alice,\n", + " bytecode=bytecode,\n", + " arguments=[42, \"test\"],\n", + " gas_limit=10000000,\n", + " is_upgradeable=True,\n", + " is_readable=True,\n", + " is_payable=True,\n", + " is_payable_by_sc=True\n", + ")\n", + "\n", + "print(\"Transaction:\", deploy_transaction.__dict__)\n", + "print(\"Transaction data:\", deploy_transaction.data)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a transaction to upgrade an existing smart contract:" + ] + }, + { + "cell_type": "code", + "execution_count": 77, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Transaction: {'chain_id': 'D', 'sender': 'erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th', 'receiver': 'erd1qqqqqqqqqqqqqpgquzmh78klkqwt0p4rjys0qtp3la07gz4d396qn50nnm', 'gas_limit': 10000000, 'nonce': 0, 'value': 0, 'data': b'upgradeContract@0061736d0100000001150460037f7f7e017f60027f7f017e60017e0060000002420303656e7611696e74363473746f7261676553746f7265000003656e7610696e74363473746f726167654c6f6164000103656e760b696e74363466696e6973680002030504030303030405017001010105030100020608017f01419088040b072f05066d656d6f7279020004696e6974000309696e6372656d656e7400040964656372656d656e7400050367657400060a8a01041300418088808000410742011080808080001a0b2e01017e4180888080004107418088808000410710818080800042017c22001080808080001a20001082808080000b2e01017e41808880800041074180888080004107108180808000427f7c22001080808080001a20001082808080000b160041808880800041071081808080001082808080000b0b0f01004180080b08434f554e54455200@0506@2a@74657374', 'signature': b'', 'sender_username': '', 'receiver_username': '', 'gas_price': 1000000000, 'version': 2, 'options': 0, 'guardian': '', 'guardian_signature': b''}\n", + "Transaction data: b'upgradeContract@0061736d0100000001150460037f7f7e017f60027f7f017e60017e0060000002420303656e7611696e74363473746f7261676553746f7265000003656e7610696e74363473746f726167654c6f6164000103656e760b696e74363466696e6973680002030504030303030405017001010105030100020608017f01419088040b072f05066d656d6f7279020004696e6974000309696e6372656d656e7400040964656372656d656e7400050367657400060a8a01041300418088808000410742011080808080001a0b2e01017e4180888080004107418088808000410710818080800042017c22001080808080001a20001082808080000b2e01017e41808880800041074180888080004107108180808000427f7c22001080808080001a20001082808080000b160041808880800041071081808080001082808080000b0b0f01004180080b08434f554e54455200@0506@2a@74657374'\n" + ] + } + ], + "source": [ + "contract_address = Address.from_bech32(\"erd1qqqqqqqqqqqqqpgquzmh78klkqwt0p4rjys0qtp3la07gz4d396qn50nnm\")\n", + "bytecode = Path(\"../multiversx_sdk/testutils/testdata/counter.wasm\").read_bytes()\n", + "\n", + "upgrade_transaction = sc_factory.create_transaction_for_upgrade(\n", + " sender=alice,\n", + " contract=contract_address,\n", + " bytecode=bytecode,\n", + " gas_limit=10000000,\n", + " arguments=[42, \"test\"],\n", + " is_upgradeable=True,\n", + " is_readable=True,\n", + " is_payable=True,\n", + " is_payable_by_sc=True\n", + ")\n", + "\n", + "print(\"Transaction:\", upgrade_transaction.__dict__)\n", + "print(\"Transaction data:\", upgrade_transaction.data)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Create a transaction that invokes a smart contract function:" + ] + }, + { + "cell_type": "code", + "execution_count": 78, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Transaction: {'chain_id': 'D', 'sender': 'erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th', 'receiver': 'erd1qqqqqqqqqqqqqpgquzmh78klkqwt0p4rjys0qtp3la07gz4d396qn50nnm', 'gas_limit': 10000000, 'nonce': 0, 'value': 0, 'data': b'foo@2a@74657374', 'signature': b'', 'sender_username': '', 'receiver_username': '', 'gas_price': 1000000000, 'version': 2, 'options': 0, 'guardian': '', 'guardian_signature': b''}\n", + "Transaction data: b'foo@2a@74657374'\n" + ] + } + ], + "source": [ + "contract_address = Address.from_bech32(\"erd1qqqqqqqqqqqqqpgquzmh78klkqwt0p4rjys0qtp3la07gz4d396qn50nnm\")\n", + "\n", + "call_transaction = sc_factory.create_transaction_for_execute(\n", + " sender=alice,\n", + " contract=contract_address,\n", + " function=\"foo\",\n", + " gas_limit=10000000,\n", + " arguments=[42, \"test\"]\n", + ")\n", + "\n", + "print(\"Transaction:\", call_transaction.__dict__)\n", + "print(\"Transaction data:\", call_transaction.data)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, let's create a call that also transfers one or more tokens (**transfer & execute**):" + ] + }, + { + "cell_type": "code", + "execution_count": 79, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Transaction: {'chain_id': 'D', 'sender': 'erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th', 'receiver': 'erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th', 'gas_limit': 10000000, 'nonce': 0, 'value': 0, 'data': b'MultiESDTNFTTransfer@00000000000000000500e0b77f1edfb01cb786a39120f02c31ff5fe40aad8974@02@544553542d333866323439@01@01@4241522d633830643239@@8ac7230489e80000@68656c6c6f@2a@74657374', 'signature': b'', 'sender_username': '', 'receiver_username': '', 'gas_price': 1000000000, 'version': 2, 'options': 0, 'guardian': '', 'guardian_signature': b''}\n", + "Transaction data: b'MultiESDTNFTTransfer@00000000000000000500e0b77f1edfb01cb786a39120f02c31ff5fe40aad8974@02@544553542d333866323439@01@01@4241522d633830643239@@8ac7230489e80000@68656c6c6f@2a@74657374'\n" + ] + } + ], + "source": [ + "first_token = Token(\"TEST-38f249\", 1)\n", + "first_transfer = TokenTransfer(first_token, 1)\n", + "\n", + "second_token = Token(\"BAR-c80d29\")\n", + "second_transfer = TokenTransfer(second_token, 10000000000000000000)\n", + "\n", + "transfers = [first_transfer, second_transfer]\n", + "\n", + "call_transaction = sc_factory.create_transaction_for_execute(\n", + " sender=alice,\n", + " contract=contract_address,\n", + " function=\"hello\",\n", + " gas_limit=10000000,\n", + " arguments=[42, \"test\"],\n", + " token_transfers=transfers\n", + ")\n", + "\n", + "print(\"Transaction:\", call_transaction.__dict__)\n", + "print(\"Transaction data:\", call_transaction.data)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Contract queries" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In order to create a contract query and run it against a network provider (more details about **network providers** can be found below), do as follows:" + ] + }, + { + "cell_type": "code", + "execution_count": 80, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Return code: ok\n", + "Return data: ['BQ==']\n" + ] + } + ], + "source": [ + "from multiversx_sdk.core import ContractQueryBuilder\n", + "from multiversx_sdk.core.interfaces import IAddress\n", + "from multiversx_sdk.network_providers import ApiNetworkProvider\n", + "\n", + "contract: IAddress = Address.from_bech32(\"erd1qqqqqqqqqqqqqpgqqy34h7he2ya6qcagqre7ur7cc65vt0mxrc8qnudkr4\")\n", + "\n", + "builder = ContractQueryBuilder(\n", + " contract=contract,\n", + " function=\"getSum\",\n", + " call_arguments=[],\n", + " caller=alice\n", + ")\n", + "\n", + "query = builder.build()\n", + "\n", + "network_provider = ApiNetworkProvider(\"https://devnet-api.multiversx.com\")\n", + "response = network_provider.query_contract(query)\n", + "\n", + "print(\"Return code:\", response.return_code)\n", + "print(\"Return data:\", response.return_data)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Creating wallets" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Mnemonic generation is based on [`trezor/python-mnemonic`](https://github.com/trezor/python-mnemonic) and can be achieved as follows:" + ] + }, + { + "cell_type": "code", + "execution_count": 81, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "['top', 'danger', 'dad', 'refuse', 'toe', 'duty', 'wrestle', 'force', 'junk', 'arrive', 'toilet', 'simple', 'total', 'mention', 'trust', 'mechanic', 'height', 'maple', 'deny', 'update', 'race', 'hen', 'venue', 'grace']\n" + ] + } + ], + "source": [ + "from multiversx_sdk.wallet import Mnemonic\n", + "\n", + "mnemonic = Mnemonic.generate()\n", + "words = mnemonic.get_words()\n", + "\n", + "print(words)" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The mnemonic can be saved to a keystore file:" + ] + }, + { + "cell_type": "code", + "execution_count": 82, + "metadata": {}, + "outputs": [], + "source": [ + "from multiversx_sdk.wallet import UserWallet\n", + "\n", + "wallet = UserWallet.from_mnemonic(mnemonic.get_text(), \"password\")\n", + "wallet.save(Path(\"./output/walletWithMnemonic.json\"))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Given a mnemonic, one can derive keypairs:" + ] + }, + { + "cell_type": "code", + "execution_count": 83, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Secret key: af1f83aaf73fcda5532bf6f2b8725d3bd282512f3465e69e39d5a300676f2028\n", + "Public key: e6a9924776f4ca2d75c8f3b0e753c7c00a03f0a5fc8feab6f578cddb40447686\n" + ] + } + ], + "source": [ + "secret_key = mnemonic.derive_key(0)\n", + "public_key = secret_key.generate_public_key()\n", + "\n", + "print(\"Secret key:\", secret_key.hex())\n", + "print(\"Public key:\", public_key.hex())" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "A keypair can be saved as a JSON wallet:" + ] + }, + { + "cell_type": "code", + "execution_count": 84, + "metadata": {}, + "outputs": [], + "source": [ + "wallet = UserWallet.from_secret_key(secret_key, \"password\")\n", + "wallet.save(Path(\"./output/wallet.json\"), address_hrp=\"erd\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "... or as a PEM wallet (usually not recommended):" + ] + }, + { + "cell_type": "code", + "execution_count": 85, + "metadata": {}, + "outputs": [], + "source": [ + "from multiversx_sdk.wallet import UserPEM\n", + "\n", + "label = Address(public_key.buffer, \"erd\").to_bech32()\n", + "pem = UserPEM(label=label, secret_key=secret_key)\n", + "pem.save(Path(\"./output/wallet.pem\"))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Loading wallets" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "This is not a very common use-case - you might refer to [signing objects](#signing-objects) instead." + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Load a keystore that holds an **encrypted mnemonic** (and perform wallet derivation at the same time):" + ] + }, + { + "cell_type": "code", + "execution_count": 86, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Secret key: 413f42575f7f26fad3317a778771212fdb80245850981e48b58a4f25e344e8f9\n", + "Address: erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th\n" + ] + } + ], + "source": [ + "from multiversx_sdk.wallet import UserWallet\n", + "\n", + "secret_key = UserWallet.load_secret_key(Path(\"../multiversx_sdk/testutils/testwallets/withDummyMnemonic.json\"), \"password\", address_index=0)\n", + "address = secret_key.generate_public_key().to_address(\"erd\")\n", + "\n", + "print(\"Secret key:\", secret_key.hex())\n", + "print(\"Address:\", address.to_bech32())" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Load a keystore that holds an **encrypted secret** key:" + ] + }, + { + "cell_type": "code", + "execution_count": 87, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Secret key: 413f42575f7f26fad3317a778771212fdb80245850981e48b58a4f25e344e8f9\n", + "Address: erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th\n" + ] + } + ], + "source": [ + "secret_key = UserWallet.load_secret_key(Path(\"../multiversx_sdk/testutils/testwallets/alice.json\"), \"password\")\n", + "address = secret_key.generate_public_key().to_address(\"erd\")\n", + "\n", + "print(\"Secret key:\", secret_key.hex())\n", + "print(\"Address:\", address.to_bech32())" + ] + }, + { + "attachments": {}, + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Load the secret key from a PEM file:" + ] + }, + { + "cell_type": "code", + "execution_count": 88, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Secret key: 413f42575f7f26fad3317a778771212fdb80245850981e48b58a4f25e344e8f9\n", + "Public key: 0139472eff6886771a982f3083da5d421f24c29181e63888228dc81ca60d69e1\n" + ] + } + ], + "source": [ + "from multiversx_sdk.wallet import UserPEM\n", + "\n", + "pem = UserPEM.from_file(Path(\"../multiversx_sdk/testutils/testwallets/alice.pem\"))\n", + "\n", + "print(\"Secret key:\", pem.secret_key.hex())\n", + "print(\"Public key:\", pem.public_key.hex())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Signing objects" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Creating a `UserSigner` from a JSON wallet:" + ] + }, + { + "cell_type": "code", + "execution_count": 89, + "metadata": {}, + "outputs": [], + "source": [ + "from multiversx_sdk.wallet import UserSigner\n", + "\n", + "signer = UserSigner.from_wallet(Path(\"../multiversx_sdk/testutils/testwallets/alice.json\"), \"password\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Creating a `UserSigner` from a PEM file:" + ] + }, + { + "cell_type": "code", + "execution_count": 90, + "metadata": {}, + "outputs": [], + "source": [ + "signer = UserSigner.from_pem_file(Path(\"../multiversx_sdk/testutils/testwallets/alice.pem\"))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Signing a transaction:" + ] + }, + { + "cell_type": "code", + "execution_count": 91, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Signature: ee6d665981c00258858923bbbe51e1cfe29911716190a3eedc24e2205100bb05faf3d8133fc973b00409aa18708b41488702d635efefe6a24b4a2b7f66267a00\n" + ] + } + ], + "source": [ + "from multiversx_sdk.core import Transaction, TransactionComputer\n", + "\n", + "tx = Transaction(\n", + " nonce=90,\n", + " sender=\"erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th\",\n", + " receiver=\"erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx\",\n", + " value=1000000000000000000,\n", + " gas_limit=50000,\n", + " chain_id=\"D\"\n", + ")\n", + "\n", + "transaction_computer = TransactionComputer()\n", + "\n", + "tx.signature = signer.sign(transaction_computer.compute_bytes_for_signing(tx))\n", + "print(\"Signature:\", tx.signature.hex())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Signing an arbitrary message:" + ] + }, + { + "cell_type": "code", + "execution_count": 92, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Signature: 561bc58f1dc6b10de208b2d2c22c9a474ea5e8cabb59c3d3ce06bbda21cc46454aa71a85d5a60442bd7784effa2e062fcb8fb421c521f898abf7f5ec165e5d0f\n" + ] + } + ], + "source": [ + "from multiversx_sdk.core import Message, MessageComputer\n", + "\n", + "message = Message(b\"hello\")\n", + "message_computer = MessageComputer()\n", + "\n", + "message.signature = signer.sign(message_computer.compute_bytes_for_signing(message))\n", + "\n", + "print(\"Signature:\", message.signature.hex())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Verifying signatures" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Creating a `UserVerifier`:" + ] + }, + { + "cell_type": "code", + "execution_count": 93, + "metadata": {}, + "outputs": [], + "source": [ + "from multiversx_sdk.core import Address\n", + "from multiversx_sdk.wallet import UserVerifier\n", + "\n", + "alice = Address.new_from_bech32(\"erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th\")\n", + "bob = Address.new_from_bech32(\"erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx\")\n", + "\n", + "alice_verifier = UserVerifier.from_address(alice)\n", + "bob_verifier = UserVerifier.from_address(bob)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Verifying a signature:" + ] + }, + { + "cell_type": "code", + "execution_count": 94, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Is signature of Alice? True\n", + "Is signature of Alice? True\n", + "Is signature of Bob? False\n", + "Is signature of Bob? False\n" + ] + } + ], + "source": [ + "from multiversx_sdk.core import TransactionComputer, MessageComputer\n", + "\n", + "transaction_computer = TransactionComputer()\n", + "message_computer = MessageComputer()\n", + "\n", + "print(f\"Is signature of Alice?\", alice_verifier.verify(transaction_computer.compute_bytes_for_signing(tx), tx.signature))\n", + "print(f\"Is signature of Alice?\", alice_verifier.verify(message_computer.compute_bytes_for_signing(message), message.signature))\n", + "print(f\"Is signature of Bob?\", bob_verifier.verify(transaction_computer.compute_bytes_for_signing(tx), tx.signature))\n", + "print(f\"Is signature of Bob?\", bob_verifier.verify(message_computer.compute_bytes_for_signing(message), message.signature))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Creating network providers" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "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." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Creating an API provider:" + ] + }, + { + "cell_type": "code", + "execution_count": 95, + "metadata": {}, + "outputs": [], + "source": [ + "from multiversx_sdk.network_providers import ApiNetworkProvider\n", + "\n", + "provider = ApiNetworkProvider(\"https://devnet-api.multiversx.com\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Creating a Proxy provider:" + ] + }, + { + "cell_type": "code", + "execution_count": 96, + "metadata": {}, + "outputs": [], + "source": [ + "from multiversx_sdk.network_providers import ProxyNetworkProvider\n", + "\n", + "provider = ProxyNetworkProvider(\"https://devnet-gateway.multiversx.com\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Fetching network parameters" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In order to fetch network parameters, do as follows:" + ] + }, + { + "cell_type": "code", + "execution_count": 97, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Chain ID: D\n", + "Min gas price: 1000000000\n" + ] + } + ], + "source": [ + "config = provider.get_network_config()\n", + "\n", + "print(\"Chain ID:\", config.chain_id)\n", + "print(\"Min gas price:\", config.min_gas_price)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Fetching account state" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The following snippet fetches (from the Network) the **nonce** and the **balance** of an account:" + ] + }, + { + "cell_type": "code", + "execution_count": 98, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Nonce: 848\n", + "Balance: 1544458693139999963\n" + ] + } + ], + "source": [ + "account_on_network = provider.get_account(alice)\n", + "\n", + "print(\"Nonce:\", account_on_network.nonce)\n", + "print(\"Balance:\", account_on_network.balance)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "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):" + ] + }, + { + "cell_type": "code", + "execution_count": 99, + "metadata": {}, + "outputs": [], + "source": [ + "from multiversx_sdk.core import AccountNonceHolder\n", + "\n", + "nonce_holder = AccountNonceHolder(account_on_network.nonce)\n", + "\n", + "tx.nonce = nonce_holder.get_nonce_then_increment()\n", + "# Then, sign & broadcast the transaction(s)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For further reference, please see [nonce management](https://docs.multiversx.com/integrators/creating-transactions/#nonce-management)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Broadcasting transactions" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Broadcast a single transaction:" + ] + }, + { + "cell_type": "code", + "execution_count": 100, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Transaction hash: 4fcbadad2ecf8e505cfbf8e7ef4a05bc516c76efe01bdd963cefc052d6d66c90\n" + ] + } + ], + "source": [ + "alice = Address.from_bech32(\"erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th\")\n", + "\n", + "tx = Transaction(\n", + " sender=alice.to_bech32(),\n", + " receiver=alice.to_bech32(),\n", + " gas_limit=50000,\n", + " chain_id=\"D\"\n", + ")\n", + "\n", + "alice_on_network = provider.get_account(alice)\n", + "\n", + "tx.nonce = alice_on_network.nonce\n", + "tx.signature = signer.sign(transaction_computer.compute_bytes_for_signing(tx))\n", + "\n", + "hash = provider.send_transaction(tx)\n", + "print(\"Transaction hash:\", hash)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Broadcast multiple transactions:" + ] + }, + { + "cell_type": "code", + "execution_count": 101, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Transactions hashes: (3, {'0': '4fcbadad2ecf8e505cfbf8e7ef4a05bc516c76efe01bdd963cefc052d6d66c90', '1': '1bbb818d7f6a1b5304af5a78216e8b59331faa84f0bfcc3561ff6e0ff8204625', '2': 'dfc4df48dbffebf8efde7e3b5d5be1d6c5e3914ceb988a5eeb164d676e588087'})\n" + ] + } + ], + "source": [ + "tx_1 = Transaction(\n", + " sender=alice.to_bech32(),\n", + " receiver=alice.to_bech32(),\n", + " gas_limit=50000,\n", + " chain_id=\"D\"\n", + ")\n", + "\n", + "tx_2 = Transaction(\n", + " sender=alice.to_bech32(),\n", + " receiver=alice.to_bech32(),\n", + " gas_limit=50000,\n", + " chain_id=\"D\"\n", + ")\n", + "\n", + "tx_3 = Transaction(\n", + " sender=alice.to_bech32(),\n", + " receiver=alice.to_bech32(),\n", + " gas_limit=50000,\n", + " chain_id=\"D\"\n", + ")\n", + "\n", + "alice_on_network = provider.get_account(alice)\n", + "nonce_holder = AccountNonceHolder(account_on_network.nonce)\n", + "\n", + "tx_1.nonce = nonce_holder.get_nonce_then_increment()\n", + "tx_2.nonce = nonce_holder.get_nonce_then_increment()\n", + "tx_3.nonce = nonce_holder.get_nonce_then_increment()\n", + "\n", + "tx_1.signature = signer.sign(transaction_computer.compute_bytes_for_signing(tx_1))\n", + "tx_2.signature = signer.sign(transaction_computer.compute_bytes_for_signing(tx_2))\n", + "tx_3.signature = signer.sign(transaction_computer.compute_bytes_for_signing(tx_3))\n", + "\n", + "hashes = provider.send_transactions([tx_1, tx_2, tx_3])\n", + "print(\"Transactions hashes:\", hashes)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now let's fetch a previously-broadcasted transaction:" + ] + }, + { + "cell_type": "code", + "execution_count": 102, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Status: success\n", + "Is completed: True\n" + ] + } + ], + "source": [ + "tx_on_network = provider.get_transaction(\"9270a6879b682a7b310c659f58b641ccdd5f083e5633669817130269e5b0939b\", with_process_status=True)\n", + "print(\"Status:\", tx_on_network.status)\n", + "print(\"Is completed:\", tx_on_network.is_completed)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "venv", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.4" + }, + "orig_nbformat": 4, + "vscode": { + "interpreter": { + "hash": "a81f6786c16244bc0f6c6471fabecdd0e4c33960b50c66ebff3e0612ad1f5926" + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/examples/output/wallet.json b/examples/output/wallet.json new file mode 100644 index 00000000..123cb47a --- /dev/null +++ b/examples/output/wallet.json @@ -0,0 +1,23 @@ +{ + "version": 4, + "kind": "secretKey", + "id": "12b21ac8-96d4-4c10-b2a3-815530a9c85f", + "address": "e6a9924776f4ca2d75c8f3b0e753c7c00a03f0a5fc8feab6f578cddb40447686", + "bech32": "erd1u65ey3mk7n9z6awg7wcww578cq9q8u99lj874dh40rxakszyw6rq4mc4kv", + "crypto": { + "ciphertext": "9802812ff1e5585e66fd092f50b027587dbf5a665012ca212fb8389d48fab29808659ab20b5aa344b1e2439f9f20044f7acb9b2e3cbebed18718699865676233", + "cipherparams": { + "iv": "0b3973944885d72b1c9de99bbc95f102" + }, + "cipher": "aes-128-ctr", + "kdf": "scrypt", + "kdfparams": { + "dklen": 32, + "salt": "172d1d911c5c874e1dabf514e1c0730474333c1809c2af0c3e53c7a333d8f464", + "n": 4096, + "r": 8, + "p": 1 + }, + "mac": "214d563fe2db4e57268f992659f1f57ba38e298f63673fed04eb8dcf574a2ff3" + } +} diff --git a/examples/output/wallet.pem b/examples/output/wallet.pem new file mode 100644 index 00000000..ac891d47 --- /dev/null +++ b/examples/output/wallet.pem @@ -0,0 +1,5 @@ +-----BEGIN PRIVATE KEY for erd1u65ey3mk7n9z6awg7wcww578cq9q8u99lj874dh40rxakszyw6rq4mc4kv----- +YWYxZjgzYWFmNzNmY2RhNTUzMmJmNmYyYjg3MjVkM2JkMjgyNTEyZjM0NjVlNjll +MzlkNWEzMDA2NzZmMjAyOGU2YTk5MjQ3NzZmNGNhMmQ3NWM4ZjNiMGU3NTNjN2Mw +MGEwM2YwYTVmYzhmZWFiNmY1NzhjZGRiNDA0NDc2ODY= +-----END PRIVATE KEY for erd1u65ey3mk7n9z6awg7wcww578cq9q8u99lj874dh40rxakszyw6rq4mc4kv----- diff --git a/examples/output/walletWithMnemonic.json b/examples/output/walletWithMnemonic.json new file mode 100644 index 00000000..259a6d67 --- /dev/null +++ b/examples/output/walletWithMnemonic.json @@ -0,0 +1,21 @@ +{ + "version": 4, + "kind": "mnemonic", + "id": "9c2cc8c0-9837-4e5b-aa2a-15b7a8ac9ea2", + "crypto": { + "ciphertext": "f11abd52509b8e0d6d282a9e3169ff1e7fd8243d7f8ac634ac0ab2f2514a618cdbff64424284c7ccffc5b09f1b4998a2196c7e9834a77a17a74dc60231671f3dd7224e2028f205506e26b9886d5154cb0887bb6b31acb2661802edd086e317d5b3a9aa3a5a4072cdbac617ade41feab635aa729fbc45bf5010cfa9528eb3ae2bfa9abdc4ef69a50f3ace20a3444c541eeb", + "cipherparams": { + "iv": "7e3352a0488a16cf7bdc167958fa958d" + }, + "cipher": "aes-128-ctr", + "kdf": "scrypt", + "kdfparams": { + "dklen": 32, + "salt": "e645c624c1a20e43da3b1a64d7e33ca051592c0a9f897968e3c5522a69a9fa1d", + "n": 4096, + "r": 8, + "p": 1 + }, + "mac": "a0214b6b6d512bae230ceacd577b82ac058519bc244f789da941ddeff0c83c89" + } +} diff --git a/multiversx_sdk/testutils/testdata/counter.wasm b/multiversx_sdk/testutils/testdata/counter.wasm new file mode 100755 index 0000000000000000000000000000000000000000..4f31dbb4b4199cd1d4c3a906ec86a710182ff30d GIT binary patch literal 335 zcmaKly-UPE6vSutBbRdvBcg?s_y=es_KDbuf**Z?x1K4INU{imWTVw#<)7?EFJd81 zGmqcQdk;ld5de2oF1_#RbKyPvoIP?tWK!DtX{)T=$#LhJwpiNhU=|p8@|&MG#R43$ z`NH>QU3L!;QY#sxG#^Q7Nr)(>XZo>HW_F~b%2rMLETF=IgPfQ3U27{_JE-}>PP3Lv z>kw_cQ*9$1R>OdFmN6NEuxAd*exj2nuVa?+ Date: Thu, 8 Feb 2024 11:10:50 +0200 Subject: [PATCH 2/4] git ignored the output of the examples --- .gitignore | 2 ++ examples/output/wallet.json | 23 ----------------------- examples/output/wallet.pem | 5 ----- examples/output/walletWithMnemonic.json | 21 --------------------- pyproject.toml | 3 ++- 5 files changed, 4 insertions(+), 50 deletions(-) delete mode 100644 examples/output/wallet.json delete mode 100644 examples/output/wallet.pem delete mode 100644 examples/output/walletWithMnemonic.json diff --git a/.gitignore b/.gitignore index 8aa0319f..11a51a3b 100644 --- a/.gitignore +++ b/.gitignore @@ -137,3 +137,5 @@ typings/** !libbls.so !libbls.dylib !libbls.dll + +examples/output diff --git a/examples/output/wallet.json b/examples/output/wallet.json deleted file mode 100644 index 123cb47a..00000000 --- a/examples/output/wallet.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "version": 4, - "kind": "secretKey", - "id": "12b21ac8-96d4-4c10-b2a3-815530a9c85f", - "address": "e6a9924776f4ca2d75c8f3b0e753c7c00a03f0a5fc8feab6f578cddb40447686", - "bech32": "erd1u65ey3mk7n9z6awg7wcww578cq9q8u99lj874dh40rxakszyw6rq4mc4kv", - "crypto": { - "ciphertext": "9802812ff1e5585e66fd092f50b027587dbf5a665012ca212fb8389d48fab29808659ab20b5aa344b1e2439f9f20044f7acb9b2e3cbebed18718699865676233", - "cipherparams": { - "iv": "0b3973944885d72b1c9de99bbc95f102" - }, - "cipher": "aes-128-ctr", - "kdf": "scrypt", - "kdfparams": { - "dklen": 32, - "salt": "172d1d911c5c874e1dabf514e1c0730474333c1809c2af0c3e53c7a333d8f464", - "n": 4096, - "r": 8, - "p": 1 - }, - "mac": "214d563fe2db4e57268f992659f1f57ba38e298f63673fed04eb8dcf574a2ff3" - } -} diff --git a/examples/output/wallet.pem b/examples/output/wallet.pem deleted file mode 100644 index ac891d47..00000000 --- a/examples/output/wallet.pem +++ /dev/null @@ -1,5 +0,0 @@ ------BEGIN PRIVATE KEY for erd1u65ey3mk7n9z6awg7wcww578cq9q8u99lj874dh40rxakszyw6rq4mc4kv----- -YWYxZjgzYWFmNzNmY2RhNTUzMmJmNmYyYjg3MjVkM2JkMjgyNTEyZjM0NjVlNjll -MzlkNWEzMDA2NzZmMjAyOGU2YTk5MjQ3NzZmNGNhMmQ3NWM4ZjNiMGU3NTNjN2Mw -MGEwM2YwYTVmYzhmZWFiNmY1NzhjZGRiNDA0NDc2ODY= ------END PRIVATE KEY for erd1u65ey3mk7n9z6awg7wcww578cq9q8u99lj874dh40rxakszyw6rq4mc4kv----- diff --git a/examples/output/walletWithMnemonic.json b/examples/output/walletWithMnemonic.json deleted file mode 100644 index 259a6d67..00000000 --- a/examples/output/walletWithMnemonic.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "version": 4, - "kind": "mnemonic", - "id": "9c2cc8c0-9837-4e5b-aa2a-15b7a8ac9ea2", - "crypto": { - "ciphertext": "f11abd52509b8e0d6d282a9e3169ff1e7fd8243d7f8ac634ac0ab2f2514a618cdbff64424284c7ccffc5b09f1b4998a2196c7e9834a77a17a74dc60231671f3dd7224e2028f205506e26b9886d5154cb0887bb6b31acb2661802edd086e317d5b3a9aa3a5a4072cdbac617ade41feab635aa729fbc45bf5010cfa9528eb3ae2bfa9abdc4ef69a50f3ace20a3444c541eeb", - "cipherparams": { - "iv": "7e3352a0488a16cf7bdc167958fa958d" - }, - "cipher": "aes-128-ctr", - "kdf": "scrypt", - "kdfparams": { - "dklen": 32, - "salt": "e645c624c1a20e43da3b1a64d7e33ca051592c0a9f897968e3c5522a69a9fa1d", - "n": 4096, - "r": 8, - "p": 1 - }, - "mac": "a0214b6b6d512bae230ceacd577b82ac058519bc244f789da941ddeff0c83c89" - } -} diff --git a/pyproject.toml b/pyproject.toml index 27c2d7d1..912900b5 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -35,5 +35,6 @@ dependencies = [ exclude = [ ".github", "./examples", - ".vscode" + ".vscode", + "./multiversx_sdk/testutils/testdata" ] From 8f3f489c297cd0d23f65c20bfae6d8ec46e22bce Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Thu, 8 Feb 2024 11:29:17 +0200 Subject: [PATCH 3/4] move contract used in examples --- examples/Cookbook.ipynb | 48 +++++++++--------- .../testdata => examples/data}/counter.wasm | Bin 2 files changed, 24 insertions(+), 24 deletions(-) rename {multiversx_sdk/testutils/testdata => examples/data}/counter.wasm (100%) diff --git a/examples/Cookbook.ipynb b/examples/Cookbook.ipynb index b8248153..9fa79c89 100644 --- a/examples/Cookbook.ipynb +++ b/examples/Cookbook.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 57, + "execution_count": 1, "metadata": {}, "outputs": [], "source": [ @@ -26,7 +26,7 @@ }, { "cell_type": "code", - "execution_count": 58, + "execution_count": 2, "metadata": {}, "outputs": [ { @@ -58,7 +58,7 @@ }, { "cell_type": "code", - "execution_count": 59, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ @@ -74,7 +74,7 @@ }, { "cell_type": "code", - "execution_count": 60, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ @@ -91,7 +91,7 @@ }, { "cell_type": "code", - "execution_count": 61, + "execution_count": 5, "metadata": {}, "outputs": [], "source": [ @@ -113,7 +113,7 @@ }, { "cell_type": "code", - "execution_count": 62, + "execution_count": 6, "metadata": {}, "outputs": [ { @@ -139,7 +139,7 @@ }, { "cell_type": "code", - "execution_count": 63, + "execution_count": 7, "metadata": {}, "outputs": [ { @@ -166,7 +166,7 @@ }, { "cell_type": "code", - "execution_count": 64, + "execution_count": 8, "metadata": {}, "outputs": [ { @@ -199,7 +199,7 @@ }, { "cell_type": "code", - "execution_count": 65, + "execution_count": 9, "metadata": {}, "outputs": [ { @@ -248,7 +248,7 @@ }, { "cell_type": "code", - "execution_count": 66, + "execution_count": 10, "metadata": {}, "outputs": [ { @@ -282,7 +282,7 @@ }, { "cell_type": "code", - "execution_count": 67, + "execution_count": 11, "metadata": {}, "outputs": [], "source": [ @@ -300,7 +300,7 @@ }, { "cell_type": "code", - "execution_count": 68, + "execution_count": 12, "metadata": {}, "outputs": [ { @@ -342,7 +342,7 @@ }, { "cell_type": "code", - "execution_count": 69, + "execution_count": 13, "metadata": {}, "outputs": [ { @@ -381,7 +381,7 @@ }, { "cell_type": "code", - "execution_count": 70, + "execution_count": 14, "metadata": {}, "outputs": [ { @@ -416,7 +416,7 @@ }, { "cell_type": "code", - "execution_count": 71, + "execution_count": 15, "metadata": {}, "outputs": [ { @@ -451,7 +451,7 @@ }, { "cell_type": "code", - "execution_count": 72, + "execution_count": 16, "metadata": {}, "outputs": [ { @@ -496,7 +496,7 @@ }, { "cell_type": "code", - "execution_count": 73, + "execution_count": 17, "metadata": {}, "outputs": [], "source": [ @@ -515,7 +515,7 @@ }, { "cell_type": "code", - "execution_count": 74, + "execution_count": 18, "metadata": {}, "outputs": [ { @@ -571,14 +571,14 @@ }, { "cell_type": "code", - "execution_count": 75, + "execution_count": 19, "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ - "WARNING:address:The `serialize()` method is deprecated and will soon be removed\n" + "The `serialize()` method is deprecated and will soon be removed\n" ] }, { @@ -643,7 +643,7 @@ }, { "cell_type": "code", - "execution_count": 76, + "execution_count": 20, "metadata": {}, "outputs": [ { @@ -662,7 +662,7 @@ " SmartContractTransactionsFactory\n", "\n", "sc_factory = SmartContractTransactionsFactory(config, TokenComputer())\n", - "bytecode = Path(\"../multiversx_sdk/testutils/testdata/counter.wasm\").read_bytes()\n", + "bytecode = Path(\"./data/counter.wasm\").read_bytes()\n", "\n", "deploy_transaction = sc_factory.create_transaction_for_deploy(\n", " sender=alice,\n", @@ -688,7 +688,7 @@ }, { "cell_type": "code", - "execution_count": 77, + "execution_count": 21, "metadata": {}, "outputs": [ { @@ -702,7 +702,7 @@ ], "source": [ "contract_address = Address.from_bech32(\"erd1qqqqqqqqqqqqqpgquzmh78klkqwt0p4rjys0qtp3la07gz4d396qn50nnm\")\n", - "bytecode = Path(\"../multiversx_sdk/testutils/testdata/counter.wasm\").read_bytes()\n", + "bytecode = Path(\"./data/counter.wasm\").read_bytes()\n", "\n", "upgrade_transaction = sc_factory.create_transaction_for_upgrade(\n", " sender=alice,\n", diff --git a/multiversx_sdk/testutils/testdata/counter.wasm b/examples/data/counter.wasm similarity index 100% rename from multiversx_sdk/testutils/testdata/counter.wasm rename to examples/data/counter.wasm From baea48fd069d2171c9f37e7f3fb041e0b6cd4953 Mon Sep 17 00:00:00 2001 From: Alexandru Popenta Date: Thu, 8 Feb 2024 11:41:28 +0200 Subject: [PATCH 4/4] update pyproject.toml --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 912900b5..f4c0e8de 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -36,5 +36,5 @@ exclude = [ ".github", "./examples", ".vscode", - "./multiversx_sdk/testutils/testdata" + "./multiversx_sdk/testutils/" ]