From edd02bb4cd19a7b210cbb7ed5f929b40772c2f5d Mon Sep 17 00:00:00 2001 From: Sorin Stanculeanu Date: Thu, 5 Dec 2024 15:10:19 +0200 Subject: [PATCH 1/6] updated relayed v3 docs --- docs/developers/relayed-transactions.md | 133 ++++++------------------ docs/sdk-and-tools/sdk-py/mxpy-cli.md | 47 ++++++--- 2 files changed, 66 insertions(+), 114 deletions(-) diff --git a/docs/developers/relayed-transactions.md b/docs/developers/relayed-transactions.md index ec26daa0..2a6095f2 100644 --- a/docs/developers/relayed-transactions.md +++ b/docs/developers/relayed-transactions.md @@ -253,136 +253,65 @@ Decoding the arguments ([useful resources here](/developers/sc-calls-format/)) w This feature is not yet available on **Mainnet**. See [Spica Protocol Upgrade](https://governance.multiversx.com/proposal/erd1qqqqqqqqqqqqqpgq4qvrwlr2e6ld50f3qfc94am38p8298kthg4s3f0vfn/1). ::: -Relayed transactions v3 feature comes with a change on the entire transaction structure, adding a new optional field `InnerTransactions`, which is a collection of inner transactions. That being said, relayed transactions v3 allow the user to send multiple inner transactions on the same relayed transaction which will be executed as normal transactions, without the gas consuming data field of the old relayed transactions versions. +Relayed transactions v3 feature comes with a change on the entire transaction structure, adding two new optional fields: +- `relayer`, which is the relayer address that will pay the fees. +- `relayerSignature`, the signature of the relayer that proves the agreement of the relayer. -In terms of gas limit computation, let's consider the following example: relayed transaction with one inner transaction of type move balance, that also has a data field `test` of length 4. +That being said, relayed transactions v3 will look and behave very similar to a regular transaction, the only difference being the gas consumption from the relayer. So the consuming data field of the old relayed transactions versions was removed. + +In terms of gas limit computation, an extra base cost will be consumed. Let's consider the following example: relayed transaction with inner transaction of type move balance, that also has a data field `test` of length 4. ```js - gasLimitInnerTxs = + * length(txData) - gasLimitInnerTxs = 50_000 + 4 * 1_500 - gasLimitInnerTxs = 56_000 + gasLimitInnerTx = + * length(txData) + gasLimitInnerTx = 50_000 + 4 * 1_500 + gasLimitInnerTx = 56_000 - gasLimitRelayedTx = * len(inner_transactions) + - gasLimitRelayedTx = 50_000 * 1 + 56_000 + gasLimitRelayedTx = + + gasLimitRelayedTx = 50_000 + 56_000 gasLimitRelayedTx = 106_000 ``` -Similar for a relayed transaction v3 that has 3 inner transactions of type move balance(empty data field on each): -```js - gasLimitInnerTxs = + + - gasLimitInnerTxs = 50_000 + 50_000 + 50_000 - gasLimitInnerTxs = 150_000 - - gasLimitRelayedTx = * len(inner_transactions) + - gasLimitRelayedTx = 50_000 * 3 + 150_000 - gasLimitRelayedTx = 300_000 -``` - It would look like: ```rust RelayedV3Transaction { - Sender: - Receiver: - Value: 0 - GasLimit: * len(InnerTransactions) + sum() - InnerTransactions: []Transaction { - { - "nonce": , - "value": , - "receiver": , - "sender": , - "gasLimit": , - "data": , - "relayer": , - }, - { - "nonce": , - "value": , - "receiver": , - "sender": , - "gasLimit": , - "data": , - "relayer": , - }, - ... - } + Sender: + Receiver: + Value: + GasLimit: + + * length(txData) + Relayer: + RelayerSignature: + Signature: } ``` Therefore, in order to build such a transaction, one has to follow the next steps: - -- create the inner transactions. Make sure that: - - all inner transactions have the `relayer` field set to the address that would pay the gas - - all inner transactions senders are in **the same shard** with the relayer - - in case there are multiple inner transactions from the same sender, the transactions are in the order of the execution, with increasing correct nonces, starting from the current sender's nonce - - all inner transactions are valid and signed -- create the relayed transactions: - - the receiver of the relayed transactions is the relayer - - value must be 0 and data field empty - - add all inner transactions on the `innerTransactions` field - - compute the gas limit: `move balance cost * number of inner transactions + sum of all inner transactions gas limits` + - set the `relayer` field to the address that would pay the gas + - add the extra base cost for the relayed operation + - add sender's signature + - add relayer's signature :::note -1. If the relayed transaction v3 is guarded, the cost of the guarded transaction will be consumed only once, not for each inner transaction. -2. There are situations where inner transactions are initially accepted, but before their execution, the underlying state changes (due to the execution of other transactions), rendering some or all of these transactions invalid. In such cases, the relayer will still incur gas costs (pays the fee), even though these inner transactions produce no effects. +1. For a guarded relayed transaction, the guarded operation fee will also be consumed from the relayer. +2. Relayer must be different from guardian, in case of guarded sender. +3. Guarded relayers are not allowed. ::: ### Example -Here's an example of a relayed v3 transaction. Its intent is: -- 2 sc calls of method `add@01` of a previously deployed adder contract -- 1 move balance +Here's an example of a relayed v3 transaction. Its intent is to call the `add` method of a previously deployed adder contract, with parameter `01` ```json { "nonce": 0, "value": "0", - "receiver": "erd1dcad0dlle658mggthhpvaypjag2et25yk3c2r7p9gjqkgqpxtukqcqakt0", - "sender": "erd1dcad0dlle658mggthhpvaypjag2et25yk3c2r7p9gjqkgqpxtukqcqakt0", + "receiver": "erd1qqqqqqqqqqqqqpgqeunf87ar9nqeey5ssvpqwe74ehmztx74qtxqs63nmx", + "sender": "erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx", "gasPrice": 1000000000, - "gasLimit": 10200000, + "gasLimit": 5000000, "signature": "...", "chainID": "T", "version": 2, - "innerTransactions": [ - { - "nonce": 1, - "value": "0", - "receiver": "erd1qqqqqqqqqqqqqpgq3tssqmcde5w6626mkrm9cehcqgquwmvwl0jq3umv7s", - "sender": "erd1ws52y4t8pmwx9zcuwg0swxymxkg6dwsfpcf3qxmsjvzjtmwkl0jqpn44dn", - "gasPrice": 1000000000, - "gasLimit": 5000000, - "data": "YWRkQDAx", - "signature": "...", - "chainID": "T", - "version": 2, - "relayer": "erd1dcad0dlle658mggthhpvaypjag2et25yk3c2r7p9gjqkgqpxtukqcqakt0" - }, - { - "nonce": 2, - "value": "0", - "receiver": "erd1qqqqqqqqqqqqqpgq3tssqmcde5w6626mkrm9cehcqgquwmvwl0jq3umv7s", - "sender": "erd1ws52y4t8pmwx9zcuwg0swxymxkg6dwsfpcf3qxmsjvzjtmwkl0jqpn44dn", - "gasPrice": 1000000000, - "gasLimit": 5000000, - "data": "YWRkQDAx", - "signature": "...", - "chainID": "T", - "version": 2, - "relayer": "erd1dcad0dlle658mggthhpvaypjag2et25yk3c2r7p9gjqkgqpxtukqcqakt0" - }, - { - "nonce": 0, - "value": "1000000000000000000", - "receiver": "erd1v7p7uefggz04qst7fzd8hwrl95v03g5uh5fj9vka6ydmdguqy6ws28at85", - "sender": "erd1xfr34s4yft7pk4gf8mt7a2kkfz4z2f3rvuy9pwlgkeymue8pcfkqfxv2mv", - "gasPrice": 1000000000, - "gasLimit": 50000, - "signature": "...", - "chainID": "T", - "version": 2, - "relayer": "erd1dcad0dlle658mggthhpvaypjag2et25yk3c2r7p9gjqkgqpxtukqcqakt0" - } - ] + "relayer": "erd1qyu5wthldzr8wx5c9ucg8kjagg0jfs53s8nr3zpz3hypefsdd8ssycr6th", + "relayerSignature": "..." } ``` diff --git a/docs/sdk-and-tools/sdk-py/mxpy-cli.md b/docs/sdk-and-tools/sdk-py/mxpy-cli.md index 94c1d581..3b5e34a5 100644 --- a/docs/sdk-and-tools/sdk-py/mxpy-cli.md +++ b/docs/sdk-and-tools/sdk-py/mxpy-cli.md @@ -530,35 +530,58 @@ If your address is guarded by another wallet, you'll still need to provide the ` [comment]: # (mx-context-auto) -## Relayed V3 transactions +## Relayed transactions V3 Relayed transactions are transactions with the fee paid by a so-called relayer. In other words, if a relayer is willing to pay for a transaction, it is not mandatory for the sender to have any EGLD for fees. To learn more about relayed transactions check out [this page](/developers/relayed-transactions/). -In this section we'll see how we can send `Relayed V3` transactions using `mxpy`. For a more detailed look on `Relayed V3` transactions, take a look [here](/developers/relayed-transactions/#relayed-transactions-version-3). For these kind of transactions a new transaction field has been introduced, called `innerTransactions`. In this example we'll see how we can create both the inner transactions and the relayed transaction. +In this section we'll see how we can send `Relayed V3` transactions using `mxpy`. For a more detailed look on `Relayed V3` transactions, take a look [here](/developers/relayed-transactions/#relayed-transactions-version-3). For these kind of transactions two new transaction fields were introduced, `relayer` and `relayerSignature`. In this example we'll see how we can create the relayed transaction. -### Creating the inner transactions +For this, a new command `mxpy tx relay` has been added. The command can be used to relay a previously signed transaction. The saved transaction can be loaded from a file using the `--infile` argument. -We can simply create the inner transactions the same way we did above, by using the `mxpy tx new` command. The only difference is that we'll have to provide an additional argument called `--inner-transactions-outfile`, which represents the file where the inner transactions are saved to be later used by the relayer. To keep it simple, we'll send 1 EGLD from Alice to Bob, and Carol will be the relayer. To create the EGLD transfer transaction from Alice to Bob, we run the following command: +There are two options when creating the relayed transaction: +1. Create the inner transaction separately. (Sender signature and relayer signature are added in different steps.) +2. Create directly the relayed transaction. (Both signatures are added in one step.) + +### Creating the inner transaction + +The inner transaction is any regular transaction, with the following notes: +- relayer address must be added +- extra 50000(base cost) gas must be added for the relayed operation. For more details on how the gas is computed, check out [this page](/developers/relayed-transactions/#relayed-transactions-version-3). + +This can be generated through `mxpy tx new` command. A new argument `--relayer` has been added for this feature. ```sh mxpy tx new --pem ~/multiversx-sdk/testwallets/latest/users/alice.pem --recall-nonce \ --receiver erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx \ - --gas-limit 50000 --value 1000000000000000000 \ + --gas-limit 100000 --value 1000000000000000000 \ --proxy https://devnet-gateway.multiversx.com --chain D \ - --relayer erd1k2s324ww2g0yj38qn2ch2jwctdy8mnfxep94q9arncc6xecg3xaq6mjse8 - --inner-transactions-outfile inner_transactions.json + --relayer erd1k2s324ww2g0yj38qn2ch2jwctdy8mnfxep94q9arncc6xecg3xaq6mjse8 \ + --outfile inner_tx.json ``` -After creating the inner transaction, we are ready to create the relayed transaction. We have to keep in mind that for `Relayed V3` transactions, the receiver has to be the same as the relayer, in our case, Carol. Another requirement is that the relayed transaction has to have enough gas. The gas is computed by multiplying the base cost (50_000) with the number of inner transactions plus the gasLimit for each inner transaction. For more details on how the gas is computed, check out [this page](/developers/relayed-transactions/#relayed-transactions-version-3). +After creating the inner transaction, we are ready to create the relayed transaction. We have to keep in mind that for `Relayed V3` transactions. + +### Creating the relayed transaction We can create the relayed transaction by running the following command: ```sh -mxpy tx new --pem ~/multiversx-sdk/testwallets/latest/users/carol.pem --recall-nonce \ - --receiver erd1k2s324ww2g0yj38qn2ch2jwctdy8mnfxep94q9arncc6xecg3xaq6mjse8 \ - --gas-limit 1000000 --value 0 \ +mxpy tx relay --relayer-pem ~/multiversx-sdk/testwallets/latest/users/carol.pem \ + --proxy https://devnet-gateway.multiversx.com --chain D \ + --infile inner_tx.json \ + --send +``` + +### Creating the relayed transaction in one step + +This can be done through `mxpy tx new` command, as follows: +```sh +mxpy tx new --pem ~/multiversx-sdk/testwallets/latest/users/alice.pem --recall-nonce \ + --receiver erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx \ + --relayer-pem ~/multiversx-sdk/testwallets/latest/users/carol.pem \ + --gas-limit 100000 --value 1000000000000000000 \ --proxy https://devnet-gateway.multiversx.com --chain D \ - --inner-transactions inner_transactions.json \ + --relayer erd1k2s324ww2g0yj38qn2ch2jwctdy8mnfxep94q9arncc6xecg3xaq6mjse8 \ --send ``` From 518927cd226898f9bb13d1b88796920d2535b4fe Mon Sep 17 00:00:00 2001 From: Sorin Stanculeanu Date: Thu, 5 Dec 2024 15:31:23 +0200 Subject: [PATCH 2/6] fixes after review --- docs/sdk-and-tools/sdk-py/mxpy-cli.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/sdk-and-tools/sdk-py/mxpy-cli.md b/docs/sdk-and-tools/sdk-py/mxpy-cli.md index 3b5e34a5..14961a17 100644 --- a/docs/sdk-and-tools/sdk-py/mxpy-cli.md +++ b/docs/sdk-and-tools/sdk-py/mxpy-cli.md @@ -559,7 +559,7 @@ mxpy tx new --pem ~/multiversx-sdk/testwallets/latest/users/alice.pem --recall-n --outfile inner_tx.json ``` -After creating the inner transaction, we are ready to create the relayed transaction. We have to keep in mind that for `Relayed V3` transactions. +After creating the inner transaction, we are ready to create the relayed transaction. ### Creating the relayed transaction @@ -578,10 +578,10 @@ This can be done through `mxpy tx new` command, as follows: ```sh mxpy tx new --pem ~/multiversx-sdk/testwallets/latest/users/alice.pem --recall-nonce \ --receiver erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx \ + --relayer erd1k2s324ww2g0yj38qn2ch2jwctdy8mnfxep94q9arncc6xecg3xaq6mjse8 \ --relayer-pem ~/multiversx-sdk/testwallets/latest/users/carol.pem \ --gas-limit 100000 --value 1000000000000000000 \ --proxy https://devnet-gateway.multiversx.com --chain D \ - --relayer erd1k2s324ww2g0yj38qn2ch2jwctdy8mnfxep94q9arncc6xecg3xaq6mjse8 \ --send ``` From 0a95ed52dbdcef1e26568fa473d1b004555c64c0 Mon Sep 17 00:00:00 2001 From: Sorin Stanculeanu Date: Thu, 5 Dec 2024 15:32:58 +0200 Subject: [PATCH 3/6] removed note for dynft --- docs/tokens/nft-tokens.mdx | 3 --- 1 file changed, 3 deletions(-) diff --git a/docs/tokens/nft-tokens.mdx b/docs/tokens/nft-tokens.mdx index 27f75929..c97674ee 100644 --- a/docs/tokens/nft-tokens.mdx +++ b/docs/tokens/nft-tokens.mdx @@ -15,9 +15,6 @@ import TableWrapper from "@site/src/components/TableWrapper"; MultiversX NFTs(non-fungible tokens) are a breed of digital assets that are revolutionizing the world of art, collectibles, and more. These NFTs are unique, one-of-a-kind tokens that are built on blockchain technology, allowing for secure ownership and transfer of these assets. With MultiversX NFTs, every token is assigned a unique identification code(ticker) and metadata that distinguishes it from every other token, making each NFT truly one-of-a-kind. Read the full page for a comprehensive guide on how to brand, issue, transfer, assign roles and many other features, for both NFTs and SFTs. -:::note -Features related to dynamic NFTs are not yet available on **Mainnet**. See [Spica Protocol Upgrade](https://governance.multiversx.com/proposal/erd1qqqqqqqqqqqqqpgq4qvrwlr2e6ld50f3qfc94am38p8298kthg4s3f0vfn/1). -::: [comment]: # (mx-context-auto) From ada0c984d0dc03b6fd199701d9646a3e07fefa35 Mon Sep 17 00:00:00 2001 From: Sorin Stanculeanu Date: Mon, 9 Dec 2024 14:47:22 +0200 Subject: [PATCH 4/6] fixes after review --- docs/developers/relayed-transactions.md | 3 ++- docs/sdk-and-tools/sdk-py/mxpy-cli.md | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/docs/developers/relayed-transactions.md b/docs/developers/relayed-transactions.md index 2a6095f2..3060317a 100644 --- a/docs/developers/relayed-transactions.md +++ b/docs/developers/relayed-transactions.md @@ -257,7 +257,7 @@ Relayed transactions v3 feature comes with a change on the entire transaction st - `relayer`, which is the relayer address that will pay the fees. - `relayerSignature`, the signature of the relayer that proves the agreement of the relayer. -That being said, relayed transactions v3 will look and behave very similar to a regular transaction, the only difference being the gas consumption from the relayer. So the consuming data field of the old relayed transactions versions was removed. +That being said, relayed transactions v3 will look and behave very similar to a regular transaction, the only difference being the gas consumption from the relayer. It is no longer needed to specify the user transaction in the data field. In terms of gas limit computation, an extra base cost will be consumed. Let's consider the following example: relayed transaction with inner transaction of type move balance, that also has a data field `test` of length 4. ```js @@ -306,6 +306,7 @@ Here's an example of a relayed v3 transaction. Its intent is to call the `add` m "value": "0", "receiver": "erd1qqqqqqqqqqqqqpgqeunf87ar9nqeey5ssvpqwe74ehmztx74qtxqs63nmx", "sender": "erd1spyavw0956vq68xj8y4tenjpq2wd5a9p2c6j8gsz7ztyrnpxrruqzu66jx", + "data": "YWRkQDAx", "gasPrice": 1000000000, "gasLimit": 5000000, "signature": "...", diff --git a/docs/sdk-and-tools/sdk-py/mxpy-cli.md b/docs/sdk-and-tools/sdk-py/mxpy-cli.md index 14961a17..4cb528e3 100644 --- a/docs/sdk-and-tools/sdk-py/mxpy-cli.md +++ b/docs/sdk-and-tools/sdk-py/mxpy-cli.md @@ -539,8 +539,8 @@ In this section we'll see how we can send `Relayed V3` transactions using `mxpy` For this, a new command `mxpy tx relay` has been added. The command can be used to relay a previously signed transaction. The saved transaction can be loaded from a file using the `--infile` argument. There are two options when creating the relayed transaction: -1. Create the inner transaction separately. (Sender signature and relayer signature are added in different steps.) -2. Create directly the relayed transaction. (Both signatures are added in one step.) +1. Create the relayed transaction +2. Add the signatures (sender and relayer) ### Creating the inner transaction From e42af777652ff62dbee8e8134b20c62fb6629240 Mon Sep 17 00:00:00 2001 From: Sorin Stanculeanu Date: Mon, 9 Dec 2024 14:55:48 +0200 Subject: [PATCH 5/6] clarifications --- docs/sdk-and-tools/sdk-py/mxpy-cli.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/sdk-and-tools/sdk-py/mxpy-cli.md b/docs/sdk-and-tools/sdk-py/mxpy-cli.md index 4cb528e3..1aa633cc 100644 --- a/docs/sdk-and-tools/sdk-py/mxpy-cli.md +++ b/docs/sdk-and-tools/sdk-py/mxpy-cli.md @@ -539,14 +539,14 @@ In this section we'll see how we can send `Relayed V3` transactions using `mxpy` For this, a new command `mxpy tx relay` has been added. The command can be used to relay a previously signed transaction. The saved transaction can be loaded from a file using the `--infile` argument. There are two options when creating the relayed transaction: -1. Create the relayed transaction -2. Add the signatures (sender and relayer) +1. Create the relayed transaction separately. (Sender signature and relayer signature are added by different entities.) +2. Create the complete relayed transaction. (Both signatures are added by the same entity.) ### Creating the inner transaction The inner transaction is any regular transaction, with the following notes: - relayer address must be added -- extra 50000(base cost) gas must be added for the relayed operation. For more details on how the gas is computed, check out [this page](/developers/relayed-transactions/#relayed-transactions-version-3). +- extra 50000 (base cost) gas must be added for the relayed operation. For more details on how the gas is computed, check out [this page](/developers/relayed-transactions/#relayed-transactions-version-3). This can be generated through `mxpy tx new` command. A new argument `--relayer` has been added for this feature. From 83f17603de2c8f04812a7b13fccd71bd88def09c Mon Sep 17 00:00:00 2001 From: BiancaIalangi Date: Tue, 10 Dec 2024 20:25:54 +0200 Subject: [PATCH 6/6] fixed links in tx-migration --- docs/developers/transactions/tx-migration.md | 140 +++++++++---------- 1 file changed, 66 insertions(+), 74 deletions(-) diff --git a/docs/developers/transactions/tx-migration.md b/docs/developers/transactions/tx-migration.md index e0c8dec4..ac1c88be 100644 --- a/docs/developers/transactions/tx-migration.md +++ b/docs/developers/transactions/tx-migration.md @@ -5,14 +5,14 @@ title: Migration [comment]: # (mx-abstract) -There is an older syntax for producing contract calls, detailed [here](tx-legacy-calls). It is already in use in many projects. +There is an older syntax for producing contract calls, detailed [here](./tx-legacy-calls.md). It is already in use in many projects. Upgrading to framework version 0.49.0 is almost completely backwards compatible, but the new syntax is nicer and more reliable, so we encourage everyone to migrate. This will be a migration guide, as well as some frequently encountered pitfalls. :::caution -Even though the syntax is backwards compatible, the implementation of the [old syntax](tx-legacy-calls) has been replaced. +Even though the syntax is backwards compatible, the implementation of the [old syntax](./tx-legacy-calls.md) has been replaced. To the best of our knowledge, all code should continue to behave the same. However, if you upgrade beyond 0.49.0, please make sure to **test your smart contract fully** once again, even if you do not change a single line of code in your code base. @@ -71,7 +71,7 @@ The solution in this case is simple: replace `Proxy` with `ProxyTo` in code. ## Replace `#[derive(TypeAbi)]` with `#[type_abi]` -To use the new proxies, one must first [generate](tx-proxies#how-to-generate) them. The proxy is designed to be self-contained, so unless configured otherwise, it will also output a copy of the contract types involved in the ABI. +To use the new proxies, one must first [generate](./tx-proxies.md#how-to-generate) them. The proxy is designed to be self-contained, so unless configured otherwise, it will also output a copy of the contract types involved in the ABI. No methods of these types are copied, but the annotations are important most of the time, so they need to be copied too. These types will need the encode/decode annotations, as well as `Clone`, `Eq`, etc. @@ -81,14 +81,11 @@ The solution is to have another annotation, called `#[type_abi]` **before** the Currently, `#[type_abi]` takes no arguments and works the same way as `#[derive(TypeAbi)]`, but it might be extended in the future. -This is yet the case, but `#[derive(TypeAbi)]` might become deprecated at some point in the future, after most projects will have been migrate. - - [comment]: # (mx-context-auto) ## Generate the new proxies -Just like for a new project, you will need to [generate](tx-proxies#how-to-generate) the new proxies and embed them in your project. +Just like for a new project, you will need to [generate](./tx-proxies.md#how-to-generate) the new proxies and embed them in your project. [comment]: # (mx-context-auto) @@ -98,53 +95,51 @@ Just like for a new project, you will need to [generate](tx-proxies#how-to-gener You might have this kind of syntax in your contract. You can easily find it by searching in your project for `#[proxy]` or `.contract(`. ```rust title="Variant A" - #[proxy] - fn vault_proxy(&self) -> vault::Proxy; - - #[endpoint] - fn do_call(&self, to: ManagedAddress, args: MultiValueEncoded) { - self.vault_proxy() - .contract(to) - .echo_arguments(args) - .async_call() - .with_callback(self.callbacks().echo_args_callback()) - .call_and_exit(); - } +#[proxy] +fn vault_proxy(&self) -> vault::Proxy; + +#[endpoint] +fn do_call(&self, to: ManagedAddress, args: MultiValueEncoded) { + self.vault_proxy() + .contract(to) + .echo_arguments(args) + .async_call() + .with_callback(self.callbacks().echo_args_callback()) + .call_and_exit(); +} ``` ```rust title="Variant B" - #[proxy] - fn vault_proxy(&self, sc_address: ManagedAddress) -> vault::Proxy; - - #[endpoint] - fn do_call(&self, to: ManagedAddress, args: MultiValueEncoded) { - self.vault_proxy(to) - .echo_arguments(args) - .async_call() - .with_callback(self.callbacks().echo_args_callback()) - .call_and_exit(); - } - - +#[proxy] +fn vault_proxy(&self, sc_address: ManagedAddress) -> vault::Proxy; + +#[endpoint] +fn do_call(&self, to: ManagedAddress, args: MultiValueEncoded) { + self.vault_proxy(to) + .echo_arguments(args) + .async_call() + .with_callback(self.callbacks().echo_args_callback()) + .call_and_exit(); +} ``` ```rust title="Replace by" - #[endpoint] - fn do_call(&self, to: ManagedAddress, args: MultiValueEncoded) { - self.tx() - .to(&to) - .typed(vault_proxy::VaultProxy) - .echo_arguments(args) - .async_call() - .with_callback(self.callbacks().echo_args_callback()) - .call_and_exit(); - } +#[endpoint] +fn do_call(&self, to: ManagedAddress, args: MultiValueEncoded) { + self.tx() + .to(&to) + .typed(vault_proxy::VaultProxy) + .echo_arguments(args) + .async_call() + .with_callback(self.callbacks().echo_args_callback()) + .call_and_exit(); +} ``` Both variants above should be replaced by this pattern. :::info -The new proxies no longer have a recipient field in them. The [recipient (to) field](tx-to) is completely independent. It is set the same way for transactions with or without proxies. +The new proxies no longer have a recipient field in them. The [recipient (to) field](./tx-to.md) is completely independent. It is set the same way for transactions with or without proxies. This feature has proven not worth the complication, we are happy to see it go. ::: @@ -168,22 +163,19 @@ A solution is planned for the near future. In case you want to migrate to the unified syntax and you cannot, or do not want to get rid of the old proxies, this is an alternative transitional syntax: ```rust title="Transitional variant" - #[proxy] - fn vault_proxy(&self, sc_address: ManagedAddress) -> vault::Proxy; - - #[endpoint] - fn do_call(&self, to: ManagedAddress, args: MultiValueEncoded) { - self.tx() - .legacy_proxy_call(self.vault_proxy(to).echo_arguments(args)) - .async_call() - .with_callback(self.callbacks().echo_args_callback()) - .call_and_exit(); - } +#[proxy] +fn vault_proxy(&self, sc_address: ManagedAddress) -> vault::Proxy; + +#[endpoint] +fn do_call(&self, to: ManagedAddress, args: MultiValueEncoded) { + self.tx() + .legacy_proxy_call(self.vault_proxy(to).echo_arguments(args)) + .async_call() + .with_callback(self.callbacks().echo_args_callback()) + .call_and_exit(); +} ``` - - - [comment]: # (mx-context-auto) ## (Optional) Remove contract dependencies @@ -206,23 +198,23 @@ To achieve backwards compatibility, all the old methods were kept (even though t We did not yet deprecate the old ones, but we encourage everyone to switch to the new ones. They have shorter names and tend to be more expressive. -| Old method | New method | Comments | -| ---------- | ---------- | -----| -| `.with_egld_transfer(amount)` | `.egld(amount)` | | -| `.with_esdt_transfer((token, nonce, amount))` | `.esdt((token, nonce, amount))`
or
`.single_esdt(&token, nonce, &amount)` | `single_esdt` can deal with references, instead of taking owned objects. | -| `.with_multi_token_transfer(p)` | `.payment(p)` | `payment` is universal. | -| `.with_egld_or_single_esdt_transfer(p)` | `.payment(p)` | Method `payment` is universal. | -| `.with_gas_limi(gas)` | `.gas(gas)` | | -| `.with_extra_gas_for_callback(gas)` | `.gas_for_callback(gas)` | Method `payment` is universal. | -| `.async_call()` | - | Does nothing, can be removed with no consequences. | -| `.async_call_promise()` | - | Does nothing, can be removed with no consequences. | -| `.with_callback(cb)` | `.callback(cb)` | | -| `.deploy_contract(code, code_metadata)` | `.code(code)`
`.code_metadata(code_metadata)`
`.sync_call()` | Also add result handlers for decoding the result. | -| `.deploy_from_source(address, code_metadata)` | `.from_source(code)`
`.code_metadata(code_metadata) .sync_call()` | Also add result handlers for decoding the result. | -| `.upgrade_contract(code, code_metadata)` | `.code(code) .code_metadata(code_metadata) .upgrade_async_call_and_exit()` | Upgrades are async calls. | -| `.upgrade_from_source(address, code_metadata)` | `.from_source(code)`
`.code_metadata(code_metadata)`
`.upgrade_async_call_and_exit()` | Upgrades are async calls. | -| `.execute_on_dest_context()` | `.sync_call()` | Also add result handlers for decoding the result. | -| `.execute_on_dest_context`
`_with_back_transfers()` | `.returns(ReturnsBackTransfers)`
`.sync_call()` | Add additional result handlers for decoding the result. | +| Old method | New method | Comments | +| -------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------ | +| `.with_egld_transfer(amount)` | `.egld(amount)` | | +| `.with_esdt_transfer((token, nonce, amount))` | `.esdt((token, nonce, amount))`
or
`.single_esdt(&token, nonce, &amount)` | `single_esdt` can deal with references, instead of taking owned objects. | +| `.with_multi_token_transfer(p)` | `.payment(p)` | `payment` is universal. | +| `.with_egld_or_single_esdt_transfer(p)` | `.payment(p)` | Method `payment` is universal. | +| `.with_gas_limi(gas)` | `.gas(gas)` | | +| `.with_extra_gas_for_callback(gas)` | `.gas_for_callback(gas)` | Method `payment` is universal. | +| `.async_call()` | - | Does nothing, can be removed with no consequences. | +| `.async_call_promise()` | - | Does nothing, can be removed with no consequences. | +| `.with_callback(cb)` | `.callback(cb)` | | +| `.deploy_contract(code, code_metadata)` | `.code(code)`
`.code_metadata(code_metadata)`
`.sync_call()` | Also add result handlers for decoding the result. | +| `.deploy_from_source(address, code_metadata)` | `.from_source(code)`
`.code_metadata(code_metadata) .sync_call()` | Also add result handlers for decoding the result. | +| `.upgrade_contract(code, code_metadata)` | `.code(code) .code_metadata(code_metadata) .upgrade_async_call_and_exit()` | Upgrades are async calls. | +| `.upgrade_from_source(address, code_metadata)` | `.from_source(code)`
`.code_metadata(code_metadata)`
`.upgrade_async_call_and_exit()` | Upgrades are async calls. | +| `.execute_on_dest_context()` | `.sync_call()` | Also add result handlers for decoding the result. | +| `.execute_on_dest_context`
`_with_back_transfers()` | `.returns(ReturnsBackTransfers)`
`.sync_call()` | Add additional result handlers for decoding the result. |