From 851c7504991f01d43983828910ad2639302b368e Mon Sep 17 00:00:00 2001
From: Novus Nota <68142933+novusnota@users.noreply.github.com>
Date: Mon, 25 Mar 2024 14:09:16 +0100
Subject: [PATCH] fix/feat: More information on sending messages

* Clean-up in `/book/message-mode`
* Re-write of `/book/send`
* More examples on sending messages in `/book/cookbook`
---
 pages/book/cookbook.mdx     | 43 +++++++++++++++++++-
 pages/book/message-mode.mdx | 38 +++++++++---------
 pages/book/send.mdx         | 79 +++++++++++++++++++++++++------------
 3 files changed, 114 insertions(+), 46 deletions(-)

diff --git a/pages/book/cookbook.mdx b/pages/book/cookbook.mdx
index fed13fa2..631625a5 100644
--- a/pages/book/cookbook.mdx
+++ b/pages/book/cookbook.mdx
@@ -316,10 +316,19 @@ let areCellsNotEqual: Bool = a.hash() != b.hash(); // false
 
 ## Sending messages
 
+### How to make a basic reply
+
+```tact
+receive() {
+    self.reply("Hello, World!".asComment()); // asComment converts a String to a Cell with a comment
+}
+```
+
 ### How to send a simple message
 
 ```tact
 send(SendParameters{
+    bounce: true, // default
     to: destinationAddress,
     value: ton("0.01"), // attached amount of Tons to send
     body: "Hello from Tact!".asComment() // comment (optional)
@@ -335,10 +344,40 @@ send(SendParameters{
     to: ctx.sender,
     value: 0,
     mode: SendRemainingBalance, // or mode: 128
-    bounce: true
+    body: "Hello from Tact!".asComment() // comment (optional)
 });
 ```
 
+### How to send a message with the remaining value
+
+If we want to make a reply to the same sender, we can use the mode `SendRemainingValue{:tact}` (i.e. `mode: 64{:tact}`), which carries all the remaining value of the inbound message in addition to the value initially indicated in the new message.
+
+```tact
+receive() {
+    send(SendParameters{
+        to: sender(),
+        value: 0,
+        mode: SendRemainingValue,
+        body: "Hello from Tact!".asComment() // comment (optional)
+    });
+}
+```
+
+It's often useful to add the `SendIgnoreErrors{:tact}` flag too, in order to ignore any errors arising while processing this message during the action phaseL
+
+```tact
+receive() {
+    send(SendParameters{
+        to: sender(),
+        value: 0,
+        mode: SendRemainingValue + SendIgnoreErrors,
+        body: "Hello from Tact!".asComment() // comment (optional)
+    });
+}
+```
+
+The latter example is identical to using a [`.reply(){:tact}` function](#how-to-make-a-basic-reply).
+
 <Callout>
 
   **Useful links:**\
@@ -535,4 +574,4 @@ let itemAddress: Address = contractAddress(self.getNftItemInit(itemIndex));
   [Tact collection and item contracts example](https://github.com/howardpen9/nft-template-in-tact/blob/tutorial/sources/contract.tact)\
   [FunC collection and item contracts example](https://github.com/Cosmodude/TAP/tree/main/contracts)
 
-</Callout>
\ No newline at end of file
+</Callout>
diff --git a/pages/book/message-mode.mdx b/pages/book/message-mode.mdx
index a1dc2b5f..3be31118 100644
--- a/pages/book/message-mode.mdx
+++ b/pages/book/message-mode.mdx
@@ -2,34 +2,34 @@ import { Callout } from 'nextra/components'
 
 # Message `mode`
 
-As you might've noticed, messages are sent with the `mode` param of a struct `SendParameters`. It's an Int value, which is combined from base modes and optional flags, which are also Int values.
+As it was previously mentioned, messages are sent with the `mode` param of a struct `SendParameters{:tact}`. It's an [`Int{:tact}`][int] value, which is combined from base modes and optional flags, which are also [`Int{:tact}`][int] values.
 
-It's possible to use raw Int values and manually provide them for the `mode`, but for your convenience there's a set of constants which you may use to construct the compound `mode` with ease. Take a look at the following tables for more information on base modes and optional flags.
+It's possible to use raw [`Int{:tact}`][int] values and manually provide them for the `mode`, but for your convenience there's a set of constants which you may use to construct the compound `mode` with ease. Take a look at the following tables for more information on base modes and optional flags.
 
 ## Base modes
 
-Mode value | Constant name        | Description
----------: | :------------------- | -----------------------------------------------------------------------------------------------------------------------
-$0$        | -                    | Ordinary message (default).
-$64$       | SendRemainingValue   | Carry all the remaining value of the inbound message in addition to the value initially indicated in the new message.
-$128$      | SendRemainingBalance | Carry all the remaining balance of the current smart contract instead of the value originally indicated in the message.
+Mode value | Constant name                 | Description
+---------: | :---------------------------- | -----------
+$0$        | -                             | Ordinary message (default).
+$64$       | `SendRemainingValue{:tact}`   | Carry all the remaining value of the inbound message in addition to the value initially indicated in the new message.
+$128$      | `SendRemainingBalance{:tact}` | Carry all the remaining balance of the current smart contract instead of the value originally indicated in the message.
 
 ## Optional flags
 
-Flag value | Constant name          | Description
----------: | :--------------------- | ----------------------------------------------------------------------------------------------------------------------
-$+1$       | SendPayGasSeparately   | Pay forward fees separately from the message value.
-$+2$       | SendIgnoreErrors       | Ignore any errors arising while processing this message during the action phase.
-$+16$      | SendBounceIfActionFail | Bounce transaction in case of any errors during action phase. Has no effect if flag $+2$, SendIgnoreErrors is used.
-$+32$      | SendDestroyIfZero      | Current account must be destroyed if its resulting balance is zero (often used with mode $128$, SendRemainingBalance).
+Flag value | Constant name                   | Description
+---------: | :------------------------------ | -----------
+$+1$       | `SendPayGasSeparately{:tact}`   | Pay forward fees separately from the message value.
+$+2$       | `SendIgnoreErrors{:tact}`       | Ignore any errors arising while processing this message during the action phase.
+$+16$      | `SendBounceIfActionFail{:tact}` | Bounce transaction in case of any errors during action phase. Has no effect if flag $+2$, `SendIgnoreErrors{:tact}` is used.
+$+32$      | `SendDestroyIfZero{:tact}`      | Current account must be destroyed if its resulting balance is zero (often used with mode $128$, `SendRemainingBalance{:tact}`).
 
 ## Combining modes with flags
 
-To make the Int value for `mode` field of SendParameters, you just have to combine base modes with optional flags by adding them together as numbers.
+To make the [`Int{:tact}`][int] value for `mode` field of SendParameters, you just have to combine base modes with optional flags by adding them together as numbers.
 
-For example, if you want to send a regular message and pay transfer fees separately, use the mode $0$ (default) and a flag $+1$ to get `mode` $= 1$, which is equal to just use SendPayGasSeparately constant.
+For example, if you want to send a regular message and pay transfer fees separately, use the mode $0$ (default) and a flag $+1$ to get `mode` $= 1$, which is equal to just use `SendPayGasSeparately{:tact}` constant.
 
-Alternatively, if you want to send the whole contract balance and destroy it immediately, use the mode $128$ and flag $+32$ to get `mode` $= 160$, which is equal to SendRemainingBalance + SendDestroyIfZero.
+Alternatively, if you want to send the whole contract balance and destroy it immediately, use the mode $128$ and flag $+32$ to get `mode` $= 160$, which is equal to `SendRemainingBalance{:tact}` + `SendDestroyIfZero{:tact}`.
 
 Here's how the latter example would look in code:
 
@@ -45,5 +45,7 @@ send(SendParameters{
 ```
 
 <Callout>
-NOTE: There can be only one base mode, but number of optional flags may vary: you can use them all, none or just some.
-</Callout>
\ No newline at end of file
+  NOTE: There can be only one [base mode](#base-modes), but number of [optional flags](#optional-flags) may vary: you can use them all, none or just some.
+</Callout>
+
+[int]: /book/integers
diff --git a/pages/book/send.mdx b/pages/book/send.mdx
index 54103fd0..b122c4e5 100644
--- a/pages/book/send.mdx
+++ b/pages/book/send.mdx
@@ -1,54 +1,77 @@
 # Sending messages
 
-TON blockchain is a message-based one to communicate with other contracts you need to send messages. 
+TON blockchain is message-based — to communicate with other contracts and to deploy new ones you need to send messages.
 
-The message consists of:
-* `value` in TON - the amount of TON you want to send with the message. This value is used to cover gas fees on the receiver side.
-* `bounce` - if set to `true` (default) then the message will be bounced back to the sender if the receiver contract doesn't exist or wasn't able to process the message.
-* `code` and `data` - init package, useful for deployments
-* `body` - message body as `Cell`
-* `mode` - an 8-bit flag that configures how to send a message
+Messages in Tact are composed using a built-in [Struct](/book/structs-and-messages#structs) `SendParameters{:tact}`, which consists of:
+
+Field    | Type                  | Description
+:------- | :-------------------- | :----------
+`bounce` | [`Bool{:tact}`][p]    | When set to `true` (default) message bounces back to the sender if the receiver contract doesn't exist or wasn't able to process the message.
+`to`     | [`Address{:tact}`][p] | Receiver internal [`Address{:tact}`][p] in TON blockchain.
+`value`  | [`Int{:tact}`][int]   | The amount of Toncoins you want to send with the message. This value is used to cover gas fees on the receiver side.
+`mode`   | [`Int{:tact}`][int]   | An 8-bit value that configures how to send a message, defaults to $0$. See: [Message `mode`](/book/message-mode).
+`body`   | [`Cell?{:tact}`][p]   | [Optional][opt] message body as a [`Cell{:tact}`][p]
+`code`   | [`Cell?{:tact}`][p]   | [Optional][opt] initial code of the contract (the compiled bytecode)
+`data`   | [`Cell?{:tact}`][p]   | [Optional][opt] initial data of the contract (arguments of [`init(){:tact}` function](/book/contracts#init-function) of the contract)
+
+Fields `code` and `data` are what's called an [init package](/book/expressions#initof), which is used in deployments of new contracts.
 
 ## Send simple reply
 
 The simplest message is a reply to the incoming message returning all excess value of a message:
 
 ```tact
-self.reply("Hello, World!".asComment()); // asComment converts string to a Cell with a comment
+receive() {
+    self.reply("Hello, World!".asComment()); // asComment converts a String to a Cell with a comment
+}
 ```
 
 ## Send message
 
-If you need more advanced logic you can use the `send` function directly.
+If you need more advanced logic you can use the `send(){:tact}` function and `SendParameters{:tact}` [Struct](/book/structs-and-messages#structs) directly.
+
+In fact, the previous example with [`.reply(){:tact}`](#send-simple-reply) can be made using the following call to `send(){:tact}` function:
 
-This example sends a message to the `to` address with a `value` of 1 TON and the `body` of a comment with a string "Hello, World!".
+```tact
+receive() {
+    send(SendParameters{
+        // bounce is set to true by default
+        to: sender(), // sending message back to the sender
+        value: 0, // don't add Toncoins to the message...
+        mode: SendRemainingValue + SendIgnoreErrors, // ...except for ones received from the sender due to SendRemainingValue
+        body: "Hello, World".asComment(); // asComment converts a String to a Cell with a comment
+    });
+}
+```
 
-`SendIgnoreErrors` means that even when an error occurs during message sending next messages would be sent anyway. **No error during the sending phase would revert a transaction.**
+Another example sends a message to the specified [`Address{:tact}`][p] with a `value` of $1$ TON and the `body` of a comment with a [`String{:tact}`][p] `"Hello, World!"{:tact}`:
 
 ```tact
-let to: Address = ...;
+let recipient: Address = ...;
 let value: Int = ton("1");
 send(SendParameters{
-    to: to,
-    value: value, 
-    mode: SendIgnoreErrors, 
-    bounce: true, 
+    // bounce is set to true by default
+    to: recipient,
+    value: value,
+    mode: SendIgnoreErrors, // will send the message despite any errors
     body: "Hello, World!".asComment()
 });
 ```
 
+The [optional flag](/book/message-mode#optional-flags) `SendIgnoreErrors{:tact}` means that even when an error occurs during message sending next messages would be sent anyway. **No error during the sending phase would revert a transaction.**
+
 ## Send typed message
 
 To send a binary typed message you can use the following code:
 
 ```tact
-let to: Address = ...;
+let recipient: Address = ...;
 let value: Int = ton("1");
 send(SendParameters{
-    to: to,
-    value: value, 
-    mode: SendIgnoreErrors, 
-    bounce: true, 
+    // bounce is set to true by default
+    to: recipient,
+    value: value,
+    mode: SendIgnoreErrors, // don't stop in case of errors
     body: SomeMessage{arg1: 123, arg2: 1234}.toCell()
 });
 ```
@@ -62,12 +85,16 @@ let init: StateInit = initOf SecondContract(arg1, arg2);
 let address: Address = contractAddress(init);
 let value: Int = ton("1");
 send(SendParameters{
+    // bounce is set to true by default
     to: address,
-    value: value, 
-    mode: SendIgnoreErrors, 
-    bounce: true, 
+    value: value,
+    mode: SendIgnoreErrors, // don't stop in case of errors
     code: init.code,
     data: init.data,
-    body: "Hello, World!".asComment()
+    body: "Hello, World!".asComment()  // not necessary, can be omitted
 });
-```
\ No newline at end of file
+```
+
+[p]: /book/types#primitive-types
+[int]: /book/integers
+[opt]: /book/optionals