diff --git a/docs/multiversx_sdk.abi.rst b/docs/multiversx_sdk.abi.rst new file mode 100644 index 00000000..a3a7f9bf --- /dev/null +++ b/docs/multiversx_sdk.abi.rst @@ -0,0 +1,229 @@ +multiversx\_sdk.abi package +=========================== + +Submodules +---------- + +multiversx\_sdk.abi.abi module +------------------------------ + +.. automodule:: multiversx_sdk.abi.abi + :members: + :undoc-members: + :show-inheritance: + +multiversx\_sdk.abi.abi\_definition module +------------------------------------------ + +.. automodule:: multiversx_sdk.abi.abi_definition + :members: + :undoc-members: + :show-inheritance: + +multiversx\_sdk.abi.address\_value module +----------------------------------------- + +.. automodule:: multiversx_sdk.abi.address_value + :members: + :undoc-members: + :show-inheritance: + +multiversx\_sdk.abi.bigint\_value module +---------------------------------------- + +.. automodule:: multiversx_sdk.abi.bigint_value + :members: + :undoc-members: + :show-inheritance: + +multiversx\_sdk.abi.biguint\_value module +----------------------------------------- + +.. automodule:: multiversx_sdk.abi.biguint_value + :members: + :undoc-members: + :show-inheritance: + +multiversx\_sdk.abi.bool\_value module +-------------------------------------- + +.. automodule:: multiversx_sdk.abi.bool_value + :members: + :undoc-members: + :show-inheritance: + +multiversx\_sdk.abi.bytes\_value module +--------------------------------------- + +.. automodule:: multiversx_sdk.abi.bytes_value + :members: + :undoc-members: + :show-inheritance: + +multiversx\_sdk.abi.codec module +-------------------------------- + +.. automodule:: multiversx_sdk.abi.codec + :members: + :undoc-members: + :show-inheritance: + +multiversx\_sdk.abi.enum\_value module +-------------------------------------- + +.. automodule:: multiversx_sdk.abi.enum_value + :members: + :undoc-members: + :show-inheritance: + +multiversx\_sdk.abi.fields module +--------------------------------- + +.. automodule:: multiversx_sdk.abi.fields + :members: + :undoc-members: + :show-inheritance: + +multiversx\_sdk.abi.interface module +------------------------------------ + +.. automodule:: multiversx_sdk.abi.interface + :members: + :undoc-members: + :show-inheritance: + +multiversx\_sdk.abi.list\_value module +-------------------------------------- + +.. automodule:: multiversx_sdk.abi.list_value + :members: + :undoc-members: + :show-inheritance: + +multiversx\_sdk.abi.multi\_value module +--------------------------------------- + +.. automodule:: multiversx_sdk.abi.multi_value + :members: + :undoc-members: + :show-inheritance: + +multiversx\_sdk.abi.option\_value module +---------------------------------------- + +.. automodule:: multiversx_sdk.abi.option_value + :members: + :undoc-members: + :show-inheritance: + +multiversx\_sdk.abi.optional\_value module +------------------------------------------ + +.. automodule:: multiversx_sdk.abi.optional_value + :members: + :undoc-members: + :show-inheritance: + +multiversx\_sdk.abi.parts module +-------------------------------- + +.. automodule:: multiversx_sdk.abi.parts + :members: + :undoc-members: + :show-inheritance: + +multiversx\_sdk.abi.serializer module +------------------------------------- + +.. automodule:: multiversx_sdk.abi.serializer + :members: + :undoc-members: + :show-inheritance: + +multiversx\_sdk.abi.shared module +--------------------------------- + +.. automodule:: multiversx_sdk.abi.shared + :members: + :undoc-members: + :show-inheritance: + +multiversx\_sdk.abi.small\_int\_values module +--------------------------------------------- + +.. automodule:: multiversx_sdk.abi.small_int_values + :members: + :undoc-members: + :show-inheritance: + +multiversx\_sdk.abi.string\_value module +---------------------------------------- + +.. automodule:: multiversx_sdk.abi.string_value + :members: + :undoc-members: + :show-inheritance: + +multiversx\_sdk.abi.struct\_value module +---------------------------------------- + +.. automodule:: multiversx_sdk.abi.struct_value + :members: + :undoc-members: + :show-inheritance: + +multiversx\_sdk.abi.token\_identifier\_value module +--------------------------------------------------- + +.. automodule:: multiversx_sdk.abi.token_identifier_value + :members: + :undoc-members: + :show-inheritance: + +multiversx\_sdk.abi.tuple\_value module +--------------------------------------- + +.. automodule:: multiversx_sdk.abi.tuple_value + :members: + :undoc-members: + :show-inheritance: + +multiversx\_sdk.abi.type\_formula module +---------------------------------------- + +.. automodule:: multiversx_sdk.abi.type_formula + :members: + :undoc-members: + :show-inheritance: + +multiversx\_sdk.abi.type\_formula\_parser module +------------------------------------------------ + +.. automodule:: multiversx_sdk.abi.type_formula_parser + :members: + :undoc-members: + :show-inheritance: + +multiversx\_sdk.abi.typesystem module +------------------------------------- + +.. automodule:: multiversx_sdk.abi.typesystem + :members: + :undoc-members: + :show-inheritance: + +multiversx\_sdk.abi.variadic\_values module +------------------------------------------- + +.. automodule:: multiversx_sdk.abi.variadic_values + :members: + :undoc-members: + :show-inheritance: + +Module contents +--------------- + +.. automodule:: multiversx_sdk.abi + :members: + :undoc-members: + :show-inheritance: diff --git a/docs/multiversx_sdk.rst b/docs/multiversx_sdk.rst index 5602d523..45d0f95f 100644 --- a/docs/multiversx_sdk.rst +++ b/docs/multiversx_sdk.rst @@ -7,6 +7,7 @@ Subpackages .. toctree:: :maxdepth: 4 + multiversx_sdk.abi multiversx_sdk.adapters multiversx_sdk.converters multiversx_sdk.core diff --git a/examples/Cookbook.ipynb b/examples/Cookbook.ipynb index 03908aee..0aee1a5c 100644 --- a/examples/Cookbook.ipynb +++ b/examples/Cookbook.ipynb @@ -2,7 +2,7 @@ "cells": [ { "cell_type": "code", - "execution_count": 2, + "execution_count": 63, "metadata": {}, "outputs": [], "source": [ @@ -26,7 +26,7 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 64, "metadata": {}, "outputs": [ { @@ -58,7 +58,7 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 65, "metadata": {}, "outputs": [], "source": [ @@ -74,7 +74,7 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": 66, "metadata": {}, "outputs": [], "source": [ @@ -91,7 +91,7 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": 67, "metadata": {}, "outputs": [], "source": [ @@ -113,7 +113,7 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": 68, "metadata": {}, "outputs": [ { @@ -139,7 +139,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 69, "metadata": {}, "outputs": [ { @@ -166,7 +166,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": 70, "metadata": {}, "outputs": [ { @@ -199,7 +199,7 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 71, "metadata": {}, "outputs": [ { @@ -249,7 +249,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 72, "metadata": {}, "outputs": [ { @@ -283,7 +283,7 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 73, "metadata": {}, "outputs": [], "source": [ @@ -301,7 +301,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 74, "metadata": {}, "outputs": [ { @@ -317,8 +317,8 @@ "from multiversx_sdk import TransferTransactionsFactory\n", "\n", "transfer_factory = TransferTransactionsFactory(config=config)\n", - "alice = Address.from_bech32(\"erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th\")\n", - "bob = Address.from_bech32(\"erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx\")\n", + "alice = Address.new_from_bech32(\"erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th\")\n", + "bob = Address.new_from_bech32(\"erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx\")\n", "\n", "# With \"data\" field\n", "transaction = transfer_factory.create_transaction_for_native_token_transfer(\n", @@ -341,7 +341,7 @@ }, { "cell_type": "code", - "execution_count": 14, + "execution_count": 75, "metadata": {}, "outputs": [ { @@ -380,7 +380,7 @@ }, { "cell_type": "code", - "execution_count": 15, + "execution_count": 76, "metadata": {}, "outputs": [ { @@ -415,7 +415,7 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": 77, "metadata": {}, "outputs": [ { @@ -450,7 +450,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 78, "metadata": {}, "outputs": [ { @@ -497,7 +497,7 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": 79, "metadata": {}, "outputs": [ { @@ -536,7 +536,7 @@ }, { "cell_type": "code", - "execution_count": 19, + "execution_count": 80, "metadata": {}, "outputs": [], "source": [ @@ -555,7 +555,7 @@ }, { "cell_type": "code", - "execution_count": 20, + "execution_count": 81, "metadata": {}, "outputs": [ { @@ -588,7 +588,7 @@ "\n", "config = TransactionsFactoryConfig(chain_id=\"D\")\n", "factory = RelayedTransactionsFactory(config=config)\n", - "relayer = Address.from_bech32(\"erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th\")\n", + "relayer = Address.new_from_bech32(\"erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th\")\n", "\n", "relayed_tx = factory.create_relayed_v1_transaction(\n", " inner_transaction=inner_tx,\n", @@ -608,16 +608,9 @@ }, { "cell_type": "code", - "execution_count": 21, + "execution_count": 82, "metadata": {}, "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "The `serialize()` method is deprecated and will soon be removed\n" - ] - }, { "name": "stdout", "output_type": "stream", @@ -649,7 +642,7 @@ "\n", "config = TransactionsFactoryConfig(chain_id=\"D\")\n", "factory = RelayedTransactionsFactory(config=config)\n", - "relayer = Address.from_bech32(\"erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th\")\n", + "relayer = Address.new_from_bech32(\"erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th\")\n", "\n", "relayed_tx = factory.create_relayed_v2_transaction(\n", " inner_transaction=inner_tx,\n", @@ -665,42 +658,213 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## Contract deployments and interactions" + "## Contract ABIs\n", + "\n", + "A contract's ABI describes the endpoints, data structure and events that a contract exposes. While contract interactions are possible without the ABI, they are easier to implement when the definitions are available." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Load the ABI from a file" + ] + }, + { + "cell_type": "code", + "execution_count": 83, + "metadata": {}, + "outputs": [], + "source": [ + "from multiversx_sdk.abi import Abi, AbiDefinition\n", + "\n", + "abi_definition = AbiDefinition.load(Path(\"./contracts/adder.abi.json\"))\n", + "abi = Abi(abi_definition)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Or even simpler:" + ] + }, + { + "cell_type": "code", + "execution_count": 84, + "metadata": {}, + "outputs": [], + "source": [ + "abi = Abi.load(Path(\"./contracts/adder.abi.json\"))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Manually construct the ABI" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If an ABI file isn't directly available, but you do have knowledge of the contract's endpoints and types, you can manually construct the ABI. Let's see a simple example:" + ] + }, + { + "cell_type": "code", + "execution_count": 85, + "metadata": {}, + "outputs": [], + "source": [ + "abi_definition = AbiDefinition.from_dict({\n", + " \"endpoints\": [{\n", + " \"name\": \"add\",\n", + " \"inputs\": [\n", + " {\n", + " \"name\": \"value\",\n", + " \"type\": \"BigUint\"\n", + " }\n", + " ],\n", + " \"outputs\": []\n", + " }]\n", + "})" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "An endpoint with both inputs and outputs:" + ] + }, + { + "cell_type": "code", + "execution_count": 86, + "metadata": {}, + "outputs": [], + "source": [ + "abi_definition = AbiDefinition.from_dict({\n", + " \"endpoints\": [\n", + " {\n", + " \"name\": \"foo\",\n", + " \"inputs\": [\n", + " { \"type\": \"BigUint\" },\n", + " { \"type\": \"u32\" },\n", + " { \"type\": \"Address\" }\n", + " ],\n", + " \"outputs\": [\n", + " { \"type\": \"u32\" }\n", + " ]\n", + " },\n", + " {\n", + " \"name\": \"bar\",\n", + " \"inputs\": [\n", + " { \"type\": \"counted-variadic\" },\n", + " { \"type\": \"variadic\" }\n", + " ],\n", + " \"outputs\": []\n", + " }\n", + " ]\n", + "})" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Contract deployments" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Load the bytecode from a file" + ] + }, + { + "cell_type": "code", + "execution_count": 87, + "metadata": {}, + "outputs": [], + "source": [ + "from pathlib import Path\n", + "\n", + "bytecode = Path(\"contracts/adder.wasm\").read_bytes()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Perform a contract deployment\n", + "\n", + "First, let's create a `SmartContractTransactionsFactory`:" + ] + }, + { + "cell_type": "code", + "execution_count": 88, + "metadata": {}, + "outputs": [], + "source": [ + "from multiversx_sdk import SmartContractTransactionsFactory\n", + "\n", + "factory = SmartContractTransactionsFactory(config)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If the contract ABI is available, provide it to the factory:" + ] + }, + { + "cell_type": "code", + "execution_count": 89, + "metadata": {}, + "outputs": [], + "source": [ + "abi = Abi.load(Path(\"contracts/adder.abi.json\"))\n", + "factory = SmartContractTransactionsFactory(config, abi)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Create a transaction to deploy a smart contract:" + "Now, prepare the deploy transaction:" ] }, { "cell_type": "code", - "execution_count": 22, + "execution_count": 90, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Transaction: {'nonce': 0, 'value': '0', 'receiver': 'erd1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq6gq4hu', 'sender': 'erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th', 'senderUsername': '', 'receiverUsername': '', 'gasPrice': 1000000000, 'gasLimit': 10000000, 'data': 'MDA2MTczNmQwMTAwMDAwMDAxMTUwNDYwMDM3ZjdmN2UwMTdmNjAwMjdmN2YwMTdlNjAwMTdlMDA2MDAwMDAwMjQyMDMwMzY1NmU3NjExNjk2ZTc0MzYzNDczNzQ2ZjcyNjE2NzY1NTM3NDZmNzI2NTAwMDAwMzY1NmU3NjEwNjk2ZTc0MzYzNDczNzQ2ZjcyNjE2NzY1NGM2ZjYxNjQwMDAxMDM2NTZlNzYwYjY5NmU3NDM2MzQ2NjY5NmU2OTczNjgwMDAyMDMwNTA0MDMwMzAzMDMwNDA1MDE3MDAxMDEwMTA1MDMwMTAwMDIwNjA4MDE3ZjAxNDE5MDg4MDQwYjA3MmYwNTA2NmQ2NTZkNmY3Mjc5MDIwMDA0Njk2ZTY5NzQwMDAzMDk2OTZlNjM3MjY1NmQ2NTZlNzQwMDA0MDk2NDY1NjM3MjY1NmQ2NTZlNzQwMDA1MDM2NzY1NzQwMDA2MGE4YTAxMDQxMzAwNDE4MDg4ODA4MDAwNDEwNzQyMDExMDgwODA4MDgwMDAxYTBiMmUwMTAxN2U0MTgwODg4MDgwMDA0MTA3NDE4MDg4ODA4MDAwNDEwNzEwODE4MDgwODAwMDQyMDE3YzIyMDAxMDgwODA4MDgwMDAxYTIwMDAxMDgyODA4MDgwMDAwYjJlMDEwMTdlNDE4MDg4ODA4MDAwNDEwNzQxODA4ODgwODAwMDQxMDcxMDgxODA4MDgwMDA0MjdmN2MyMjAwMTA4MDgwODA4MDAwMWEyMDAwMTA4MjgwODA4MDAwMGIxNjAwNDE4MDg4ODA4MDAwNDEwNzEwODE4MDgwODAwMDEwODI4MDgwODAwMDBiMGIwZjAxMDA0MTgwMDgwYjA4NDM0ZjU1NGU1NDQ1NTIwMEAwNTAwQDA1MDZAMmFANzQ2NTczNzQ=', 'chainID': 'D', 'version': 2, 'options': 0, 'guardian': '', 'signature': '', 'guardianSignature': ''}\n", - "Transaction data: 0061736d0100000001150460037f7f7e017f60027f7f017e60017e0060000002420303656e7611696e74363473746f7261676553746f7265000003656e7610696e74363473746f726167654c6f6164000103656e760b696e74363466696e6973680002030504030303030405017001010105030100020608017f01419088040b072f05066d656d6f7279020004696e6974000309696e6372656d656e7400040964656372656d656e7400050367657400060a8a01041300418088808000410742011080808080001a0b2e01017e4180888080004107418088808000410710818080800042017c22001080808080001a20001082808080000b2e01017e41808880800041074180888080004107108180808000427f7c22001080808080001a20001082808080000b160041808880800041071081808080001082808080000b0b0f01004180080b08434f554e54455200@0500@0506@2a@74657374\n" + "Transaction: {'nonce': 0, 'value': '0', 'receiver': 'erd1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq6gq4hu', 'sender': 'erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th', 'senderUsername': '', 'receiverUsername': '', 'gasPrice': 1000000000, 'gasLimit': 10000000, 'data': 'MDA2MTczNmQwMTAwMDAwMDAxMjkwODYwMDAwMDYwMDAwMTdmNjAwMjdmN2YwMTdmNjAwMjdmN2YwMDYwMDE3ZjAwNjAwMzdmN2Y3ZjAxN2Y2MDAzN2Y3ZjdmMDA2MDAxN2YwMTdmMDI5MDAyMGIwMzY1NmU3NjE5NjI2OTY3NDk2ZTc0NDc2NTc0NTU2ZTczNjk2NzZlNjU2NDQxNzI2Nzc1NmQ2NTZlNzQwMDAzMDM2NTZlNzYwZjY3NjU3NDRlNzU2ZDQxNzI2Nzc1NmQ2NTZlNzQ3MzAwMDEwMzY1NmU3NjBiNzM2OTY3NmU2MTZjNDU3MjcyNmY3MjAwMDMwMzY1NmU3NjEyNmQ0Mjc1NjY2NjY1NzI1Mzc0NmY3MjYxNjc2NTRjNmY2MTY0MDAwMjAzNjU2ZTc2MTc2ZDQyNzU2NjY2NjU3MjU0NmY0MjY5Njc0OTZlNzQ1NTZlNzM2OTY3NmU2NTY0MDAwMjAzNjU2ZTc2MTk2ZDQyNzU2NjY2NjU3MjQ2NzI2ZjZkNDI2OTY3NDk2ZTc0NTU2ZTczNjk2NzZlNjU2NDAwMDIwMzY1NmU3NjEzNmQ0Mjc1NjY2NjY1NzI1Mzc0NmY3MjYxNjc2NTUzNzQ2ZjcyNjUwMDAyMDM2NTZlNzYwZjZkNDI3NTY2NjY2NTcyNTM2NTc0NDI3OTc0NjU3MzAwMDUwMzY1NmU3NjBlNjM2ODY1NjM2YjRlNmY1MDYxNzk2ZDY1NmU3NDAwMDAwMzY1NmU3NjE0NjI2OTY3NDk2ZTc0NDY2OTZlNjk3MzY4NTU2ZTczNjk2NzZlNjU2NDAwMDQwMzY1NmU3NjA5NjI2OTY3NDk2ZTc0NDE2NDY0MDAwNjAzMGIwYTAxMDEwNDA3MDMwMTAwMDAwMDAwMDUwMzAxMDAwMzA2MGYwMjdmMDA0MWEwODAwODBiN2YwMDQxYTA4MDA4MGIwNzQ2MDcwNjZkNjU2ZDZmNzI3OTAyMDAwNDY5NmU2OTc0MDAxMTA2Njc2NTc0NTM3NTZkMDAxMjAzNjE2NDY0MDAxMzA4NjM2MTZjNmM0MjYxNjM2YjAwMTQwYTVmNWY2NDYxNzQ2MTVmNjU2ZTY0MDMwMDBiNWY1ZjY4NjU2MTcwNWY2MjYxNzM2NTAzMDEwYWNhMDEwYTBlMDEwMTdmNDEwMDEwMGMyMjAwMTAwMDIwMDAwYjE5MDEwMTdmNDE5YzgwMDg0MTljODAwODI4MDIwMDQxMDE2YjIyMDAzNjAyMDAyMDAwMGIxNDAwMTAwMTIwMDA0NjA0NDAwZjBiNDE4MDgwMDg0MTE5MTAwMjAwMGIxNjAwMjAwMDEwMGMyMjAwMTAwMzFhMjAwMDEwMGMyMjAwMTAwNDFhMjAwMDBiMTQwMTAxN2YxMDBjMjIwMjIwMDExMDA1MWEyMDAwMjAwMjEwMDYxYTBiMTMwMTAxN2YxMDBjMjIwMDQxOTk4MDA4NDEwMzEwMDcxYTIwMDAwYjE0MDEwMTdmMTAwODQxMDExMDBkMTAwYjIxMDAxMDEwMjAwMDEwMGYwYjBlMDAxMDA4NDEwMDEwMGQxMDEwMTAwZTEwMDkwYjIyMDEwMzdmMTAwODQxMDExMDBkMTAwYjIxMDExMDEwMjIwMjEwMGUyMjAwMjAwMDIwMDExMDBhMjAwMjIwMDAxMDBmMGIwMzAwMDEwYjBiMmYwMjAwNDE4MDgwMDgwYjFjNzc3MjZmNmU2NzIwNmU3NTZkNjI2NTcyMjA2ZjY2MjA2MTcyNjc3NTZkNjU2ZTc0NzM3Mzc1NmQwMDQxOWM4MDA4MGIwNDljZmZmZmZmQDA1MDBAMDUwNkAyYQ==', 'chainID': 'D', 'version': 2, 'options': 0, 'guardian': '', 'signature': '', 'guardianSignature': ''}\n", + "Transaction data: 0061736d010000000129086000006000017f60027f7f017f60027f7f0060017f0060037f7f7f017f60037f7f7f0060017f017f0290020b03656e7619626967496e74476574556e7369676e6564417267756d656e74000303656e760f6765744e756d417267756d656e7473000103656e760b7369676e616c4572726f72000303656e76126d42756666657253746f726167654c6f6164000203656e76176d427566666572546f426967496e74556e7369676e6564000203656e76196d42756666657246726f6d426967496e74556e7369676e6564000203656e76136d42756666657253746f7261676553746f7265000203656e760f6d4275666665725365744279746573000503656e760e636865636b4e6f5061796d656e74000003656e7614626967496e7446696e697368556e7369676e6564000403656e7609626967496e744164640006030b0a010104070301000000000503010003060f027f0041a080080b7f0041a080080b074607066d656d6f7279020004696e697400110667657453756d00120361646400130863616c6c4261636b00140a5f5f646174615f656e6403000b5f5f686561705f6261736503010aca010a0e01017f4100100c2200100020000b1901017f419c8008419c800828020041016b220036020020000b1400100120004604400f0b4180800841191002000b16002000100c220010031a2000100c220010041a20000b1401017f100c2202200110051a2000200210061a0b1301017f100c220041998008410310071a20000b1401017f10084101100d100b210010102000100f0b0e0010084100100d1010100e10090b2201037f10084101100d100b210110102202100e220020002001100a20022000100f0b0300010b0b2f0200418080080b1c77726f6e67206e756d626572206f6620617267756d656e747373756d00419c80080b049cffffff@0500@0506@2a\n" ] } ], "source": [ - "from pathlib import Path\n", + "from multiversx_sdk.abi import U32Value\n", "\n", - "from multiversx_sdk import SmartContractTransactionsFactory\n", + "# For deploy arguments, use typed value objects if you haven't provided an ABI to the factory:\n", + "args = [U32Value(42)]\n", + "# Or use simple, plain Python values and objects if you have provided an ABI to the factory:\n", + "args = [42]\n", "\n", - "sc_factory = SmartContractTransactionsFactory(config)\n", - "bytecode = Path(\"./data/counter.wasm\").read_bytes()\n", - "\n", - "deploy_transaction = sc_factory.create_transaction_for_deploy(\n", + "deploy_transaction = factory.create_transaction_for_deploy(\n", " sender=alice,\n", " bytecode=bytecode,\n", - " arguments=[42, \"test\"],\n", + " arguments=args,\n", " gas_limit=10000000,\n", " is_upgradeable=True,\n", " is_readable=True,\n", @@ -716,33 +880,139 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Create a transaction to upgrade an existing smart contract:" + "When creating transactions using `SmartContractTransactionsFactory`, even if the ABI is available and provided,\n", + "you can still use _typed value_ objects as arguments for deployments and interactions.\n", + "\n", + "Even further, you can use a mix of _typed value_ objects and plain Python values and objects. For example:\n", + "```\n", + "args = [U32Value(42), \"hello\", { \"foo\": \"bar\" }, TokenIdentifierValue(\"TEST-abcdef\")];\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Setting the transaction nonce, signing a transaction and broadcasting it are depicted in a later section." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Computing the contract address" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Even before broadcasting, at the moment you know the sender address and the nonce for your deployment transaction, you can (deterministically) compute the (upcoming) address of the contract:" + ] + }, + { + "cell_type": "code", + "execution_count": 91, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Contract address: erd1qqqqqqqqqqqqqpgqak8zt22wl2ph4tswtyc39namqx6ysa2sd8ss4xmlj3\n" + ] + } + ], + "source": [ + "from multiversx_sdk import AddressComputer\n", + "\n", + "address_computer = AddressComputer()\n", + "contract_address = address_computer.compute_contract_address(\n", + " deployer=Address.new_from_bech32(deploy_transaction.sender),\n", + " deployment_nonce=deploy_transaction.nonce\n", + ")\n", + "\n", + "print(\"Contract address:\", contract_address.to_bech32())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Parsing transaction outcome" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In the end, you can parse the results using a `SmartContractTransactionsOutcomeParser`. However, since the `parse_deploy` method requires a `TransactionOutcome` object as input, we need to first convert our `TransactionOnNetwork` object to a `TransactionOutcome`, by means of a `TransactionsConverter`." + ] + }, + { + "cell_type": "code", + "execution_count": 92, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "SmartContractDeployOutcome(return_code='', return_message='', contracts=[DeployedSmartContract(address=erd1qqqqqqqqqqqqqpgqws44xjx2t056nn79fn29q0rjwfrd3m43396ql35kxy, owner_address=erd1testnlersh4z0wsv8kjx39me4rmnvjkwu8dsaea7ukdvvc9z396qykv7z7, code_hash=384b680df7a95ebceca02ffb3e760a2fc288dea1b802685ef15df22ae88ba15b)])\n" + ] + } + ], + "source": [ + "from multiversx_sdk import SmartContractTransactionsOutcomeParser, TransactionsConverter\n", + "\n", + "converter = TransactionsConverter()\n", + "parser = SmartContractTransactionsOutcomeParser()\n", + "\n", + "transaction_on_network = proxy.get_transaction(\"0a7da74038244790b5bd4cd614c26cd5a6be76a6fcfcfb037974cc116b2ee9c6\")\n", + "transaction_outcome = converter.transaction_on_network_to_outcome(transaction_on_network)\n", + "parsed_outcome = parser.parse_deploy(transaction_outcome)\n", + "\n", + "print(parsed_outcome)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Contract upgrades" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Contract upgrade transactions are similar to deployment transactions (see above), in the sense that they also require a contract bytecode. In this context, though, the contract address is already known." ] }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 93, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Transaction: {'nonce': 0, 'value': '0', 'receiver': 'erd1qqqqqqqqqqqqqpgquzmh78klkqwt0p4rjys0qtp3la07gz4d396qn50nnm', 'sender': 'erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th', 'senderUsername': '', 'receiverUsername': '', 'gasPrice': 1000000000, 'gasLimit': 10000000, 'data': 'dXBncmFkZUNvbnRyYWN0QDAwNjE3MzZkMDEwMDAwMDAwMTE1MDQ2MDAzN2Y3ZjdlMDE3ZjYwMDI3ZjdmMDE3ZTYwMDE3ZTAwNjAwMDAwMDI0MjAzMDM2NTZlNzYxMTY5NmU3NDM2MzQ3Mzc0NmY3MjYxNjc2NTUzNzQ2ZjcyNjUwMDAwMDM2NTZlNzYxMDY5NmU3NDM2MzQ3Mzc0NmY3MjYxNjc2NTRjNmY2MTY0MDAwMTAzNjU2ZTc2MGI2OTZlNzQzNjM0NjY2OTZlNjk3MzY4MDAwMjAzMDUwNDAzMDMwMzAzMDQwNTAxNzAwMTAxMDEwNTAzMDEwMDAyMDYwODAxN2YwMTQxOTA4ODA0MGIwNzJmMDUwNjZkNjU2ZDZmNzI3OTAyMDAwNDY5NmU2OTc0MDAwMzA5Njk2ZTYzNzI2NTZkNjU2ZTc0MDAwNDA5NjQ2NTYzNzI2NTZkNjU2ZTc0MDAwNTAzNjc2NTc0MDAwNjBhOGEwMTA0MTMwMDQxODA4ODgwODAwMDQxMDc0MjAxMTA4MDgwODA4MDAwMWEwYjJlMDEwMTdlNDE4MDg4ODA4MDAwNDEwNzQxODA4ODgwODAwMDQxMDcxMDgxODA4MDgwMDA0MjAxN2MyMjAwMTA4MDgwODA4MDAwMWEyMDAwMTA4MjgwODA4MDAwMGIyZTAxMDE3ZTQxODA4ODgwODAwMDQxMDc0MTgwODg4MDgwMDA0MTA3MTA4MTgwODA4MDAwNDI3ZjdjMjIwMDEwODA4MDgwODAwMDFhMjAwMDEwODI4MDgwODAwMDBiMTYwMDQxODA4ODgwODAwMDQxMDcxMDgxODA4MDgwMDAxMDgyODA4MDgwMDAwYjBiMGYwMTAwNDE4MDA4MGIwODQzNGY1NTRlNTQ0NTUyMDBAMDUwNkAyYUA3NDY1NzM3NA==', 'chainID': 'D', 'version': 2, 'options': 0, 'guardian': '', 'signature': '', 'guardianSignature': ''}\n", - "Transaction data: upgradeContract@0061736d0100000001150460037f7f7e017f60027f7f017e60017e0060000002420303656e7611696e74363473746f7261676553746f7265000003656e7610696e74363473746f726167654c6f6164000103656e760b696e74363466696e6973680002030504030303030405017001010105030100020608017f01419088040b072f05066d656d6f7279020004696e6974000309696e6372656d656e7400040964656372656d656e7400050367657400060a8a01041300418088808000410742011080808080001a0b2e01017e4180888080004107418088808000410710818080800042017c22001080808080001a20001082808080000b2e01017e41808880800041074180888080004107108180808000427f7c22001080808080001a20001082808080000b160041808880800041071081808080001082808080000b0b0f01004180080b08434f554e54455200@0506@2a@74657374\n" + "Transaction: {'nonce': 0, 'value': '0', 'receiver': 'erd1qqqqqqqqqqqqqpgquzmh78klkqwt0p4rjys0qtp3la07gz4d396qn50nnm', 'sender': 'erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th', 'senderUsername': '', 'receiverUsername': '', 'gasPrice': 1000000000, 'gasLimit': 10000000, 'data': 'dXBncmFkZUNvbnRyYWN0QDAwNjE3MzZkMDEwMDAwMDAwMTI5MDg2MDAwMDA2MDAwMDE3ZjYwMDI3ZjdmMDE3ZjYwMDI3ZjdmMDA2MDAxN2YwMDYwMDM3ZjdmN2YwMTdmNjAwMzdmN2Y3ZjAwNjAwMTdmMDE3ZjAyOTAwMjBiMDM2NTZlNzYxOTYyNjk2NzQ5NmU3NDQ3NjU3NDU1NmU3MzY5Njc2ZTY1NjQ0MTcyNjc3NTZkNjU2ZTc0MDAwMzAzNjU2ZTc2MGY2NzY1NzQ0ZTc1NmQ0MTcyNjc3NTZkNjU2ZTc0NzMwMDAxMDM2NTZlNzYwYjczNjk2NzZlNjE2YzQ1NzI3MjZmNzIwMDAzMDM2NTZlNzYxMjZkNDI3NTY2NjY2NTcyNTM3NDZmNzI2MTY3NjU0YzZmNjE2NDAwMDIwMzY1NmU3NjE3NmQ0Mjc1NjY2NjY1NzI1NDZmNDI2OTY3NDk2ZTc0NTU2ZTczNjk2NzZlNjU2NDAwMDIwMzY1NmU3NjE5NmQ0Mjc1NjY2NjY1NzI0NjcyNmY2ZDQyNjk2NzQ5NmU3NDU1NmU3MzY5Njc2ZTY1NjQwMDAyMDM2NTZlNzYxMzZkNDI3NTY2NjY2NTcyNTM3NDZmNzI2MTY3NjU1Mzc0NmY3MjY1MDAwMjAzNjU2ZTc2MGY2ZDQyNzU2NjY2NjU3MjUzNjU3NDQyNzk3NDY1NzMwMDA1MDM2NTZlNzYwZTYzNjg2NTYzNmI0ZTZmNTA2MTc5NmQ2NTZlNzQwMDAwMDM2NTZlNzYxNDYyNjk2NzQ5NmU3NDQ2Njk2ZTY5NzM2ODU1NmU3MzY5Njc2ZTY1NjQwMDA0MDM2NTZlNzYwOTYyNjk2NzQ5NmU3NDQxNjQ2NDAwMDYwMzBiMGEwMTAxMDQwNzAzMDEwMDAwMDAwMDA1MDMwMTAwMDMwNjBmMDI3ZjAwNDFhMDgwMDgwYjdmMDA0MWEwODAwODBiMDc0NjA3MDY2ZDY1NmQ2ZjcyNzkwMjAwMDQ2OTZlNjk3NDAwMTEwNjY3NjU3NDUzNzU2ZDAwMTIwMzYxNjQ2NDAwMTMwODYzNjE2YzZjNDI2MTYzNmIwMDE0MGE1ZjVmNjQ2MTc0NjE1ZjY1NmU2NDAzMDAwYjVmNWY2ODY1NjE3MDVmNjI2MTczNjUwMzAxMGFjYTAxMGEwZTAxMDE3ZjQxMDAxMDBjMjIwMDEwMDAyMDAwMGIxOTAxMDE3ZjQxOWM4MDA4NDE5YzgwMDgyODAyMDA0MTAxNmIyMjAwMzYwMjAwMjAwMDBiMTQwMDEwMDEyMDAwNDYwNDQwMGYwYjQxODA4MDA4NDExOTEwMDIwMDBiMTYwMDIwMDAxMDBjMjIwMDEwMDMxYTIwMDAxMDBjMjIwMDEwMDQxYTIwMDAwYjE0MDEwMTdmMTAwYzIyMDIyMDAxMTAwNTFhMjAwMDIwMDIxMDA2MWEwYjEzMDEwMTdmMTAwYzIyMDA0MTk5ODAwODQxMDMxMDA3MWEyMDAwMGIxNDAxMDE3ZjEwMDg0MTAxMTAwZDEwMGIyMTAwMTAxMDIwMDAxMDBmMGIwZTAwMTAwODQxMDAxMDBkMTAxMDEwMGUxMDA5MGIyMjAxMDM3ZjEwMDg0MTAxMTAwZDEwMGIyMTAxMTAxMDIyMDIxMDBlMjIwMDIwMDAyMDAxMTAwYTIwMDIyMDAwMTAwZjBiMDMwMDAxMGIwYjJmMDIwMDQxODA4MDA4MGIxYzc3NzI2ZjZlNjcyMDZlNzU2ZDYyNjU3MjIwNmY2NjIwNjE3MjY3NzU2ZDY1NmU3NDczNzM3NTZkMDA0MTljODAwODBiMDQ5Y2ZmZmZmZkAwNTA2QDJh', 'chainID': 'D', 'version': 2, 'options': 0, 'guardian': '', 'signature': '', 'guardianSignature': ''}\n", + "Transaction data: upgradeContract@0061736d010000000129086000006000017f60027f7f017f60027f7f0060017f0060037f7f7f017f60037f7f7f0060017f017f0290020b03656e7619626967496e74476574556e7369676e6564417267756d656e74000303656e760f6765744e756d417267756d656e7473000103656e760b7369676e616c4572726f72000303656e76126d42756666657253746f726167654c6f6164000203656e76176d427566666572546f426967496e74556e7369676e6564000203656e76196d42756666657246726f6d426967496e74556e7369676e6564000203656e76136d42756666657253746f7261676553746f7265000203656e760f6d4275666665725365744279746573000503656e760e636865636b4e6f5061796d656e74000003656e7614626967496e7446696e697368556e7369676e6564000403656e7609626967496e744164640006030b0a010104070301000000000503010003060f027f0041a080080b7f0041a080080b074607066d656d6f7279020004696e697400110667657453756d00120361646400130863616c6c4261636b00140a5f5f646174615f656e6403000b5f5f686561705f6261736503010aca010a0e01017f4100100c2200100020000b1901017f419c8008419c800828020041016b220036020020000b1400100120004604400f0b4180800841191002000b16002000100c220010031a2000100c220010041a20000b1401017f100c2202200110051a2000200210061a0b1301017f100c220041998008410310071a20000b1401017f10084101100d100b210010102000100f0b0e0010084100100d1010100e10090b2201037f10084101100d100b210110102202100e220020002001100a20022000100f0b0300010b0b2f0200418080080b1c77726f6e67206e756d626572206f6620617267756d656e747373756d00419c80080b049cffffff@0506@2a\n" ] } ], "source": [ - "contract_address = Address.from_bech32(\"erd1qqqqqqqqqqqqqpgquzmh78klkqwt0p4rjys0qtp3la07gz4d396qn50nnm\")\n", - "bytecode = Path(\"./data/counter.wasm\").read_bytes()\n", + "contract_address = Address.new_from_bech32(\"erd1qqqqqqqqqqqqqpgquzmh78klkqwt0p4rjys0qtp3la07gz4d396qn50nnm\")\n", + "bytecode = Path(\"./contracts/adder.wasm\").read_bytes()\n", "\n", - "upgrade_transaction = sc_factory.create_transaction_for_upgrade(\n", + "upgrade_transaction = factory.create_transaction_for_upgrade(\n", " sender=alice,\n", " contract=contract_address,\n", " bytecode=bytecode,\n", " gas_limit=10000000,\n", - " arguments=[42, \"test\"],\n", + " arguments=[42],\n", " is_upgradeable=True,\n", " is_readable=True,\n", " is_payable=True,\n", @@ -757,56 +1027,164 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "Create a transaction that invokes a smart contract function:" + "## Contract interactions" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The recommended way to create transactions for calling (and, for that matter, deploying and upgrading) smart contracts is through a `SmartContractTransactionsFactory`." ] }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 94, + "metadata": {}, + "outputs": [], + "source": [ + "from multiversx_sdk import SmartContractTransactionsFactory\n", + "\n", + "factory = SmartContractTransactionsFactory(config)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If the contract ABI is available, provide it to the factory:" + ] + }, + { + "cell_type": "code", + "execution_count": 95, + "metadata": {}, + "outputs": [], + "source": [ + "abi = Abi.load(Path(\"contracts/adder.abi.json\"))\n", + "factory = SmartContractTransactionsFactory(config, abi)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Regular interactions" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now, let's prepare a contract transaction, to call the `add` function of our previously deployed smart contract:" + ] + }, + { + "cell_type": "code", + "execution_count": 96, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Transaction: {'nonce': 0, 'value': '0', 'receiver': 'erd1qqqqqqqqqqqqqpgquzmh78klkqwt0p4rjys0qtp3la07gz4d396qn50nnm', 'sender': 'erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th', 'senderUsername': '', 'receiverUsername': '', 'gasPrice': 1000000000, 'gasLimit': 10000000, 'data': 'Zm9vQDJhQDc0NjU3Mzc0', 'chainID': 'D', 'version': 2, 'options': 0, 'guardian': '', 'signature': '', 'guardianSignature': ''}\n", - "Transaction data: foo@2a@74657374\n" + "Transaction: {'nonce': 0, 'value': '0', 'receiver': 'erd1qqqqqqqqqqqqqpgqws44xjx2t056nn79fn29q0rjwfrd3m43396ql35kxy', 'sender': 'erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th', 'senderUsername': '', 'receiverUsername': '', 'gasPrice': 1000000000, 'gasLimit': 10000000, 'data': 'YWRkQDJh', 'chainID': 'D', 'version': 2, 'options': 0, 'guardian': '', 'signature': '', 'guardianSignature': ''}\n", + "Transaction data: add@2a\n" ] } ], "source": [ - "contract_address = Address.from_bech32(\"erd1qqqqqqqqqqqqqpgquzmh78klkqwt0p4rjys0qtp3la07gz4d396qn50nnm\")\n", + "contract_address = Address.new_from_bech32(\"erd1qqqqqqqqqqqqqpgqws44xjx2t056nn79fn29q0rjwfrd3m43396ql35kxy\")\n", "\n", - "call_transaction = sc_factory.create_transaction_for_execute(\n", + "# For arguments, use typed value objects if you haven't provided an ABI to the factory:\n", + "args = [U32Value(42)]\n", + "# Or use simple, plain Python values and objects if you have provided an ABI to the factory:\n", + "args = [42]\n", + "\n", + "transaction = factory.create_transaction_for_execute(\n", " sender=alice,\n", " contract=contract_address,\n", - " function=\"foo\",\n", + " function=\"add\",\n", " gas_limit=10000000,\n", - " arguments=[42, \"test\"]\n", + " arguments=args\n", ")\n", "\n", - "print(\"Transaction:\", transaction_converter.transaction_to_dictionary(call_transaction))\n", - "print(\"Transaction data:\", call_transaction.data.decode())" + "print(\"Transaction:\", transaction_converter.transaction_to_dictionary(transaction))\n", + "print(\"Transaction data:\", transaction.data.decode())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "When creating transactions using `SmartContractTransactionsFactory`, even if the ABI is available and provided,\n", + "you can still use _typed value_ objects as arguments for deployments and interactions.\n", + "\n", + "Even further, you can use a mix of _typed value_ objects and plain Python values and objects. For example:\n", + "```\n", + "args = [U32Value(42), \"hello\", { \"foo\": \"bar\" }, TokenIdentifierValue(\"TEST-abcdef\")];\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Setting the transaction nonce, signing a transaction and broadcasting it are depicted in a later section." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Transfer & execute" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "At times, you may want to send some tokens (native EGLD or ESDT) along with the contract call.\n", + "\n", + "For transfer & execute with native EGLD, prepare your transaction as follows:" + ] + }, + { + "cell_type": "code", + "execution_count": 97, + "metadata": {}, + "outputs": [], + "source": [ + "transaction = factory.create_transaction_for_execute(\n", + " sender=alice,\n", + " contract=contract_address,\n", + " function=\"add\",\n", + " gas_limit=10000000,\n", + " arguments=[42],\n", + " native_transfer_amount=1000000000000000000\n", + ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ - "Now, let's create a call that also transfers one or more tokens (**transfer & execute**):" + "Above, we're sending 1 EGLD along with the contract call.\n", + "\n", + "For transfer & execute with ESDT tokens, prepare your transaction as follows:" ] }, { "cell_type": "code", - "execution_count": 25, + "execution_count": 98, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Transaction: {'nonce': 0, 'value': '0', 'receiver': 'erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th', 'sender': 'erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th', 'senderUsername': '', 'receiverUsername': '', 'gasPrice': 1000000000, 'gasLimit': 10000000, 'data': 'TXVsdGlFU0RUTkZUVHJhbnNmZXJAMDAwMDAwMDAwMDAwMDAwMDA1MDBlMGI3N2YxZWRmYjAxY2I3ODZhMzkxMjBmMDJjMzFmZjVmZTQwYWFkODk3NEAwMkA1NDQ1NTM1NDJkMzMzODY2MzIzNDM5QDAxQDAxQDQyNDE1MjJkNjMzODMwNjQzMjM5QEA4YWM3MjMwNDg5ZTgwMDAwQDY4NjU2YzZjNmZAMmFANzQ2NTczNzQ=', 'chainID': 'D', 'version': 2, 'options': 0, 'guardian': '', 'signature': '', 'guardianSignature': ''}\n", - "Transaction data: MultiESDTNFTTransfer@00000000000000000500e0b77f1edfb01cb786a39120f02c31ff5fe40aad8974@02@544553542d333866323439@01@01@4241522d633830643239@@8ac7230489e80000@68656c6c6f@2a@74657374\n" + "Transaction: {'nonce': 0, 'value': '0', 'receiver': 'erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th', 'sender': 'erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th', 'senderUsername': '', 'receiverUsername': '', 'gasPrice': 1000000000, 'gasLimit': 10000000, 'data': 'TXVsdGlFU0RUTkZUVHJhbnNmZXJAMDAwMDAwMDAwMDAwMDAwMDA1MDA3NDJiNTM0OGNhNWJlOWE5Y2ZjNTRjZDQ1MDNjNzI3MjQ2ZDhlZWIxODk3NEAwMkA1NDQ1NTM1NDJkMzMzODY2MzIzNDM5QDAxQDAxQDQyNDE1MjJkNjMzODMwNjQzMjM5QEA4YWM3MjMwNDg5ZTgwMDAwQDYxNjQ2NEAyYQ==', 'chainID': 'D', 'version': 2, 'options': 0, 'guardian': '', 'signature': '', 'guardianSignature': ''}\n", + "Transaction data: MultiESDTNFTTransfer@00000000000000000500742b5348ca5be9a9cfc54cd4503c727246d8eeb18974@02@544553542d333866323439@01@01@4241522d633830643239@@8ac7230489e80000@616464@2a\n" ] } ], @@ -819,17 +1197,35 @@ "\n", "transfers = [first_transfer, second_transfer]\n", "\n", - "call_transaction = sc_factory.create_transaction_for_execute(\n", + "transaction = factory.create_transaction_for_execute(\n", " sender=alice,\n", " contract=contract_address,\n", - " function=\"hello\",\n", + " function=\"add\",\n", " gas_limit=10000000,\n", - " arguments=[42, \"test\"],\n", + " arguments=[42],\n", " token_transfers=transfers\n", ")\n", "\n", - "print(\"Transaction:\", transaction_converter.transaction_to_dictionary(call_transaction))\n", - "print(\"Transaction data:\", call_transaction.data.decode())" + "print(\"Transaction:\", transaction_converter.transaction_to_dictionary(transaction))\n", + "print(\"Transaction data:\", transaction.data.decode())" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Parsing transaction outcome\n", + "\n", + "Documentation in this section is preliminary and subject to change." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Decode transaction events\n", + "\n", + "Documentation in this section is preliminary and subject to change." ] }, { @@ -843,31 +1239,64 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "In order to do a contract query against the network (more details about **network providers** can be found below), do as follows:" + "In order to perform Smart Contract queries, we recommend the use of `SmartContractQueriesController`.\n", + "\n", + "You will notice that the `SmartContractQueriesController` requires a `QueryRunner` object at initialization. A `NetworkProvider`, slighly adapted, is used to satisfy this requirement (more details about **network providers** can be found in a later section)." + ] + }, + { + "cell_type": "code", + "execution_count": 99, + "metadata": {}, + "outputs": [], + "source": [ + "from multiversx_sdk import (ProxyNetworkProvider, QueryRunnerAdapter,\n", + " SmartContractQueriesController)\n", + "\n", + "contract = Address.new_from_bech32(\"erd1qqqqqqqqqqqqqpgqqy34h7he2ya6qcagqre7ur7cc65vt0mxrc8qnudkr4\")\n", + "query_runner = QueryRunnerAdapter(ProxyNetworkProvider(\"https://devnet-api.multiversx.com\"))\n", + "\n", + "query_controller = SmartContractQueriesController(query_runner)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "If the contract ABI is available, provide it to the controller:" ] }, { "cell_type": "code", - "execution_count": 26, + "execution_count": 100, + "metadata": {}, + "outputs": [], + "source": [ + "abi = Abi.load(Path(\"contracts/adder.abi.json\"))\n", + "query_controller = SmartContractQueriesController(query_runner, abi)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Query the contract as follows:" + ] + }, + { + "cell_type": "code", + "execution_count": 101, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Return data (parsed): [b'\\x05']\n" + "Return data (parsed): [5]\n" ] } ], "source": [ - "from multiversx_sdk import (ProxyNetworkProvider, QueryRunnerAdapter,\n", - " SmartContractQueriesController)\n", - "\n", - "contract = Address.from_bech32(\"erd1qqqqqqqqqqqqqpgqqy34h7he2ya6qcagqre7ur7cc65vt0mxrc8qnudkr4\")\n", - "query_runner = QueryRunnerAdapter(ProxyNetworkProvider(\"https://devnet-api.multiversx.com\"))\n", - "\n", - "query_controller = SmartContractQueriesController(query_runner)\n", - "\n", "data_parts = query_controller.query(\n", " contract=contract.to_bech32(),\n", " function=\"getSum\",\n", @@ -886,7 +1315,7 @@ }, { "cell_type": "code", - "execution_count": 56, + "execution_count": 102, "metadata": {}, "outputs": [ { @@ -895,7 +1324,7 @@ "text": [ "Return code: ok\n", "Return data (raw): [b'\\x05']\n", - "Return data (parsed): [b'\\x05']\n" + "Return data (parsed): [5]\n" ] } ], @@ -930,14 +1359,14 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": 103, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "['duck', 'road', 'best', 'card', 'rapid', 'belt', 'shuffle', 'umbrella', 'trophy', 'donor', 'discover', 'maple', 'inherit', 'play', 'chat', 'need', 'siege', 'tiny', 'broom', 'ugly', 'margin', 'life', 'shove', 'frown']\n" + "['calm', 'correct', 'orchard', 'earn', 'army', 'tower', 'token', 'dice', 'bleak', 'tackle', 'copper', 'walnut', 'sell', 'cradle', 'typical', 'supreme', 'lesson', 'laundry', 'silk', 'sand', 'feel', 'cancel', 'shoulder', 'rail']\n" ] } ], @@ -960,7 +1389,7 @@ }, { "cell_type": "code", - "execution_count": 8, + "execution_count": 104, "metadata": {}, "outputs": [], "source": [ @@ -984,15 +1413,15 @@ }, { "cell_type": "code", - "execution_count": 10, + "execution_count": 105, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Secret key: 2f0c8a8f516f820c09d1c13a35cf90eaedcb59a66203810b515c4c6162e0a234\n", - "Public key: b80a407e1a7e05ef0b5b91351b1818e695a2defb41ff211311f99aad9846394f\n" + "Secret key: 74a35a90d0554b87277f432b00db2b2c17543034c86f3d23204f4d75cb2ca0a9\n", + "Public key: 2234d1d5eee679f5391d3c04678ee7761a3692e2f5b15393248a8a28b35d1a98\n" ] } ], @@ -1014,7 +1443,7 @@ }, { "cell_type": "code", - "execution_count": 11, + "execution_count": 106, "metadata": {}, "outputs": [], "source": [ @@ -1035,7 +1464,7 @@ }, { "cell_type": "code", - "execution_count": 13, + "execution_count": 107, "metadata": {}, "outputs": [], "source": [ @@ -1074,7 +1503,7 @@ }, { "cell_type": "code", - "execution_count": 31, + "execution_count": 108, "metadata": {}, "outputs": [ { @@ -1106,7 +1535,7 @@ }, { "cell_type": "code", - "execution_count": 32, + "execution_count": 109, "metadata": {}, "outputs": [ { @@ -1136,7 +1565,7 @@ }, { "cell_type": "code", - "execution_count": 33, + "execution_count": 110, "metadata": {}, "outputs": [ { @@ -1173,7 +1602,7 @@ }, { "cell_type": "code", - "execution_count": 34, + "execution_count": 111, "metadata": {}, "outputs": [], "source": [ @@ -1191,7 +1620,7 @@ }, { "cell_type": "code", - "execution_count": 35, + "execution_count": 112, "metadata": {}, "outputs": [], "source": [ @@ -1207,7 +1636,7 @@ }, { "cell_type": "code", - "execution_count": 36, + "execution_count": 113, "metadata": {}, "outputs": [ { @@ -1245,7 +1674,7 @@ }, { "cell_type": "code", - "execution_count": 37, + "execution_count": 114, "metadata": {}, "outputs": [ { @@ -1284,7 +1713,7 @@ }, { "cell_type": "code", - "execution_count": 38, + "execution_count": 115, "metadata": {}, "outputs": [], "source": [ @@ -1306,7 +1735,7 @@ }, { "cell_type": "code", - "execution_count": 39, + "execution_count": 116, "metadata": {}, "outputs": [ { @@ -1355,7 +1784,7 @@ }, { "cell_type": "code", - "execution_count": 40, + "execution_count": 117, "metadata": {}, "outputs": [], "source": [ @@ -1373,7 +1802,7 @@ }, { "cell_type": "code", - "execution_count": 41, + "execution_count": 118, "metadata": {}, "outputs": [], "source": [ @@ -1398,7 +1827,7 @@ }, { "cell_type": "code", - "execution_count": 42, + "execution_count": 119, "metadata": {}, "outputs": [ { @@ -1433,15 +1862,15 @@ }, { "cell_type": "code", - "execution_count": 43, + "execution_count": 120, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Nonce: 1133\n", - "Balance: 17869817183859999837\n" + "Nonce: 1465\n", + "Balance: 7728263062706014403\n" ] } ], @@ -1461,7 +1890,7 @@ }, { "cell_type": "code", - "execution_count": 44, + "execution_count": 121, "metadata": {}, "outputs": [], "source": [ @@ -1496,19 +1925,19 @@ }, { "cell_type": "code", - "execution_count": 45, + "execution_count": 122, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Transaction hash: 4c57f147644bf21ad83c5e732e95dd6cebf56bded40827929130dfcc1bf721c5\n" + "Transaction hash: 0e32fcf92dc500c343714092df451296820bcd35d1158302729fe7d6b505a1ce\n" ] } ], "source": [ - "alice = Address.from_bech32(\"erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th\")\n", + "alice = Address.new_from_bech32(\"erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th\")\n", "\n", "tx = Transaction(\n", " sender=alice.to_bech32(),\n", @@ -1535,14 +1964,14 @@ }, { "cell_type": "code", - "execution_count": 46, + "execution_count": 123, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ - "Transactions hashes: (3, {'0': '4c57f147644bf21ad83c5e732e95dd6cebf56bded40827929130dfcc1bf721c5', '1': '1dc19cc442afdc80bfe341120778b197bd24e5f4ff41511f9be8b882132060d8', '2': '795e81c21c4c613479ebdbfc466140d8c24574f71d672bcffd2e5fee0580da42'})\n" + "Transactions hashes: (3, {'0': '0e32fcf92dc500c343714092df451296820bcd35d1158302729fe7d6b505a1ce', '1': 'dbcb03c474069ab994ad636be4732e35c1fefbbe206d571fb5126229b251f8e3', '2': 'a809e28394cd998808a21c71ce9e1df79c13a12b707134fe1df263bf07cc1d45'})\n" ] } ], @@ -1592,7 +2021,7 @@ }, { "cell_type": "code", - "execution_count": 47, + "execution_count": 124, "metadata": {}, "outputs": [ { diff --git a/examples/contracts/adder.abi.json b/examples/contracts/adder.abi.json new file mode 100644 index 00000000..4772ced4 --- /dev/null +++ b/examples/contracts/adder.abi.json @@ -0,0 +1,48 @@ +{ + "name": "Adder", + "constructor": { + "inputs": [ + { + "name": "initial_value", + "type": "BigUint" + } + ], + "outputs": [] + }, + "upgradeConstructor": { + "inputs": [ + { + "name": "initial_value", + "type": "BigUint" + } + ], + "outputs": [] + }, + "endpoints": [ + { + "name": "getSum", + "mutability": "readonly", + "inputs": [], + "outputs": [ + { + "type": "BigUint" + } + ] + }, + { + "docs": ["Add desired amount to the storage variable."], + "name": "add", + "mutability": "mutable", + "inputs": [ + { + "name": "value", + "type": "BigUint" + } + ], + "outputs": [] + } + ], + "esdtAttributes": [], + "hasCallback": false, + "types": {} +} diff --git a/examples/contracts/adder.wasm b/examples/contracts/adder.wasm new file mode 100755 index 00000000..77ce7e23 Binary files /dev/null and b/examples/contracts/adder.wasm differ diff --git a/examples/data/counter.wasm b/examples/data/counter.wasm deleted file mode 100755 index 4f31dbb4..00000000 Binary files a/examples/data/counter.wasm and /dev/null differ diff --git a/multiversx_sdk/abi/__init__.py b/multiversx_sdk/abi/__init__.py index 19e3f234..28986b79 100644 --- a/multiversx_sdk/abi/__init__.py +++ b/multiversx_sdk/abi/__init__.py @@ -1,3 +1,5 @@ +from multiversx_sdk.abi.abi import Abi +from multiversx_sdk.abi.abi_definition import AbiDefinition from multiversx_sdk.abi.address_value import AddressValue from multiversx_sdk.abi.bigint_value import BigIntValue from multiversx_sdk.abi.biguint_value import BigUIntValue @@ -20,6 +22,9 @@ from multiversx_sdk.abi.variadic_values import VariadicValues __all__ = [ + "Abi", + "AbiDefinition", + "AddressValue", "BigIntValue", "BigUIntValue", @@ -42,6 +47,7 @@ "StructValue", "TokenIdentifierValue", "TupleValue", + "MultiValue", "OptionalValue", "VariadicValues", diff --git a/multiversx_sdk/abi/abi_definition.py b/multiversx_sdk/abi/abi_definition.py index c1fb3032..a18c2a31 100644 --- a/multiversx_sdk/abi/abi_definition.py +++ b/multiversx_sdk/abi/abi_definition.py @@ -16,10 +16,10 @@ def __init__(self, @classmethod def from_dict(cls, data: Dict[str, Any]) -> "AbiDefinition": - constructor = EndpointDefinition.from_dict(data["constructor"]) + constructor = cls._get_definition_for_constructor(data) constructor.name = "constructor" - upgrade_constructor = cls._get_endpoint_for_upgrade(data) + upgrade_constructor = cls._get_definition_for_upgrade(data) upgrade_constructor.name = "upgrade_constructor" endpoints = [EndpointDefinition.from_dict(item) for item in data["endpoints"]] if "endpoints" in data else [] @@ -33,7 +33,14 @@ def from_dict(cls, data: Dict[str, Any]) -> "AbiDefinition": ) @classmethod - def _get_endpoint_for_upgrade(cls, data: Dict[str, Any]) -> "EndpointDefinition": + def _get_definition_for_constructor(cls, data: Dict[str, Any]): + if "constructor" in data: + return EndpointDefinition.from_dict(data["constructor"]) + + return NullEndpointDefinition() + + @classmethod + def _get_definition_for_upgrade(cls, data: Dict[str, Any]) -> "EndpointDefinition": if "upgradeConstructor" in data: return EndpointDefinition.from_dict(data["upgradeConstructor"]) @@ -42,7 +49,10 @@ def _get_endpoint_for_upgrade(cls, data: Dict[str, Any]) -> "EndpointDefinition" return EndpointDefinition.from_dict(data["endpoints"]["upgrade"]) # Fallback for contracts written using an old Rust framework: - return EndpointDefinition.from_dict(data["constructor"]) + if "constructor" in data: + EndpointDefinition.from_dict(data["constructor"]) + + return NullEndpointDefinition() @classmethod def load(cls, path: Path) -> "AbiDefinition": @@ -87,6 +97,22 @@ def __repr__(self): return f"EndpointDefinition(name={self.name})" +class NullEndpointDefinition(EndpointDefinition): + def __init__(self) -> None: + super().__init__( + name="", + docs="", + mutability="", + inputs=[], + outputs=[], + payable_in_tokens=[], + only_owner=False + ) + + def __repr__(self): + return "NullEndpointDefinition()" + + class ParameterDefinition: def __init__(self, name: str, type: str) -> None: self.name = name diff --git a/multiversx_sdk/core/transactions_outcome_parsers/smart_contract_transactions_outcome_parser_types.py b/multiversx_sdk/core/transactions_outcome_parsers/smart_contract_transactions_outcome_parser_types.py index a47a581d..54ddf669 100644 --- a/multiversx_sdk/core/transactions_outcome_parsers/smart_contract_transactions_outcome_parser_types.py +++ b/multiversx_sdk/core/transactions_outcome_parsers/smart_contract_transactions_outcome_parser_types.py @@ -8,6 +8,9 @@ class DeployedSmartContract: owner_address: str code_hash: bytes + def __repr__(self) -> str: + return f"DeployedSmartContract(address={self.address}, owner_address={self.owner_address}, code_hash={self.code_hash.hex()})" + @dataclass class SmartContractDeployOutcome: diff --git a/pyproject.toml b/pyproject.toml index 7ba0a2d9..54d972eb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -7,7 +7,7 @@ allow-direct-references = true [project] name = "multiversx-sdk" -version = "0.9.1" +version = "0.10.0" authors = [ { name="MultiversX" }, ]