Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(docs/stdlib): split and reorder Core libraries #2391

Merged
merged 9 commits into from
Mar 15, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 21 additions & 2 deletions .github/workflows/tact-docs-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ on:
"review_requested",
]
branches: ["main"]
# Only start the workflow if anything inside the docs has changed
paths: ["docs/**"]
# Only start the workflow if anything inside the docs or std/internal has changed
paths: ["docs/**", "src/stdlib/stdlib/std/internal/**"]

# Allows to run this workflow manually from the Actions tab
workflow_dispatch:
Expand Down Expand Up @@ -67,6 +67,25 @@ jobs:
fail: true
failIfEmpty: false

# That way, when building the docs in the next step,
# their link checker will be able to validate the links in stdlib
- name: Save a file with all the links in stdlib
if: runner.os == 'Linux'
run: |
stdlib_path="src/stdlib/stdlib/std/internal"
linkfile='std-internal-link-test.mdx'
pushd "$stdlib_path"
echo -e '---\ntitle: "std/internal link test"\n---\n' > "$linkfile"
grep 'https://docs.tact.*$' *.tact >> "$linkfile"
# remove possible brackets, since they can interfere
sed -E 's|(\[\|\])||g' -i "$linkfile"
# remove some punctuation characters after the links
sed -E 's|(https://docs.tact-lang.org.*)[.,;]$|\1|g' -i "$linkfile"
# proceed with replacements
sed -E 's|https://docs.tact-lang.org(.*)$|[link](\1)|g' -i "$linkfile"
popd
mv "${stdlib_path}/${linkfile}" docs/src/content/docs/

- name: Build the site
working-directory: docs
run: yarn build
3 changes: 2 additions & 1 deletion cspell.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,8 @@
"\\b[xB]\\{[a-fA-F0-9]*_?\\}", // binary literals in Fift-asm
"\\b0[xX][a-fA-F0-9_]*\\b", // hexadecimal numbers
"\\b(?:address|crc32|cell|slice|rawSlice)\\(\".+?\"\\)", // some comptime functions
"ince Tact " // regex in RELEASE.md
"ince Tact ", // regex in RELEASE.md
"core-contextstate"
],
"flagWords": [],
"ignorePaths": [
Expand Down
2 changes: 2 additions & 0 deletions dev-docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Docs

- Removed the "gas-expensive" badge from `checkSignature()` and `checkDataSignature()` functions and added a caution note when they do become expensive (from 11th call): PR [#2380](https://github.com/tact-lang/tact/pull/2380)
- Fixed descriptions of `Slice.asString()` and `String.asSlice()` functions: PR [#2391](https://github.com/tact-lang/tact/pull/2391)
- Split Core libraries in the reference: `core-common` and `core-advanced` were removed, and their contents distributed across other libraries; `core-crypto`, `core-contextstate`, `core-send`, `core-gas`, and `core-addresses` were introduced: PR [#2391](https://github.com/tact-lang/tact/pull/2391)

### Release contributors

Expand Down
15 changes: 10 additions & 5 deletions docs/astro.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -256,14 +256,17 @@ export default defineConfig({
link: 'ref/core-base#',
},
{ slug: 'ref/core-base' },
{ slug: 'ref/core-common' },
{ slug: 'ref/core-send' },
{ slug: 'ref/core-contextstate' },
{ slug: 'ref/core-comptime' },
{ slug: 'ref/core-cells' },
{ slug: 'ref/core-addresses' },
{ slug: 'ref/core-strings' },
{ slug: 'ref/core-debug' },
{ slug: 'ref/core-random' },
{ slug: 'ref/core-gas' },
{ slug: 'ref/core-crypto' },
{ slug: 'ref/core-math' },
{ slug: 'ref/core-strings' },
{ slug: 'ref/core-cells' },
{ slug: 'ref/core-advanced' },
{ slug: 'ref/core-random' },
{
label: 'Standard libraries',
translations: { 'zh-CN': '标准库' },
Expand Down Expand Up @@ -322,5 +325,7 @@ export default defineConfig({
'/ecosystem/tools/jetbrains': '/ecosystem/jetbrains',
'/ecosystem/tools/vscode': '/ecosystem/vscode',
'/ecosystem/tools/misti': '/ecosystem/misti',
'/ref/core-common': '/ref/core-send',
'/ref/core-advanced': '/ref/core-contextstate',
},
});
2 changes: 1 addition & 1 deletion docs/src/content/docs/book/assembly-functions.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -426,7 +426,7 @@ The [TVM][tvm] places a couple of values onto its stack upon initialization, and

:::

Therefore, to access details such as the amount of [nanoToncoins](/book/integers#nanotoncoin) in a message or the [`Address{:tact}`][p] of the sender, it's strongly recommended to call the [`context(){:tact}`](/ref/core-common#context) or [`sender(){:tact}`](/ref/core-common#sender) functions instead of attempting to look for those values on the stack.
Therefore, to access details such as the amount of [nanoToncoins](/book/integers#nanotoncoin) in a message or the [`Address{:tact}`][p] of the sender, it's strongly recommended to call the [`context(){:tact}`](/ref/core-contextstate#context) or [`sender(){:tact}`](/ref/core-contextstate#sender) functions instead of attempting to look for those values on the stack.

### Don't rely on the order of fields in structures in the standard library {#caveats-stdlib-structures}

Expand Down
8 changes: 4 additions & 4 deletions docs/src/content/docs/book/debug.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -630,13 +630,13 @@ it('your test clause title', async () => {

## Logging via `emit` {#logging}

A [global static function](/book/functions#global-static-functions) [`emit(){:tact}`](/ref/core-common#emit) sends a message to the outer world — it doesn't have a specific recipient.
A [global static function](/book/functions#global-static-functions) [`emit(){:tact}`](/ref/core-send#emit) sends a message to the outer world — it doesn't have a specific recipient.

This function is very handy for logging and analyzing data off-chain — one just has to look at [external messages](/book/external) produced by the contract.

### Logs in local Sandbox tests {#logging-local}

When deploying in the [Sandbox][sb], you may call [`emit(){:tact}`](/ref/core-common#emit) from a [receiver function](/book/contracts#receiver-functions) and then observe the list of sent [external messages](/book/external):
When deploying in the [Sandbox][sb], you may call [`emit(){:tact}`](/ref/core-send#emit) from a [receiver function](/book/contracts#receiver-functions) and then observe the list of sent [external messages](/book/external):

```typescript {9-10}
it('emits', async () => {
Expand All @@ -656,7 +656,7 @@ it('emits', async () => {

Every transaction on TON Blockchain [contains `out_msgs`](https://docs.ton.org/develop/data-formats/transaction-layout#transaction) — a dictionary that holds the list of outgoing messages created during the transaction execution.

To see logs from [`emit(){:tact}`](/ref/core-common#emit) in that dictionary, look for external messages without a recipient. In various TON Blockchain explorers, such transactions will be marked as `external-out` with the destination specified as `-` or `empty`.
To see logs from [`emit(){:tact}`](/ref/core-send#emit) in that dictionary, look for external messages without a recipient. In various TON Blockchain explorers, such transactions will be marked as `external-out` with the destination specified as `-` or `empty`.

Note that some explorers deserialize the message body sent for you, while others don't. However, you can always [parse it yourself](#logging-parsing) locally.

Expand Down Expand Up @@ -697,7 +697,7 @@ it('emits', async () => {
});
```

Here, the `res` object would contain the list of sent [external messages](/book/external) as its `externals` field. Let's access it to parse the first message sent via a call to [`emit(){:tact}`](/ref/core-common#emit) in Tact code (or _emitted_ for short):
Here, the `res` object would contain the list of sent [external messages](/book/external) as its `externals` field. Let's access it to parse the first message sent via a call to [`emit(){:tact}`](/ref/core-send#emit) in Tact code (or _emitted_ for short):

```typescript /body/
it('emits', async () => {
Expand Down
4 changes: 2 additions & 2 deletions docs/src/content/docs/book/exit-codes.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -617,7 +617,7 @@ Here are some of the functions in Tact which can throw an error with this exit c

1. [`Int.toFloatString(digits){:tact}`](/ref/core-strings#inttofloatstring): if `digits` is not in the interval $0 < digits < 78$.

2. [`String.fromBase64(){:tact}`](/ref/core-strings#stringfrombase64) and [`Slice.fromBase64(){:tact}`](/ref/core-strings#slicefrombase64): if the given [`String{:tact}`][p] or [`Slice{:tact}`][slice] contains non-Base64 characters.
2. [`String.fromBase64(){:tact}`](/ref/core-strings#stringfrombase64) and [`Slice.fromBase64(){:tact}`](/ref/core-cells#slicefrombase64): if the given [`String{:tact}`][p] or [`Slice{:tact}`][slice] contains non-Base64 characters.

```tact
try {
Expand Down Expand Up @@ -680,7 +680,7 @@ try {

The value of type [`Address{:tact}`][p] belongs to a basechain, when its [chain ID](https://docs.ton.org/learn/overviews/addresses#workchain-id) is equal to 0.

Such check is currently only performed in the [`forceBasechain(){:tact}`](/ref/core-advanced#forcebasechain) function. If the address does not belong to a basechain, i.e., its chain ID isn't 0, the function throws an error with exit code 138: `Not a basechain address`.
Such check is currently only performed in the [`forceBasechain(){:tact}`](/ref/core-addresses#forcebasechain) function. If the address does not belong to a basechain, i.e., its chain ID isn't 0, the function throws an error with exit code 138: `Not a basechain address`.

```tact
let someBasechainAddress: Address =
Expand Down
6 changes: 3 additions & 3 deletions docs/src/content/docs/book/expressions.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ Field | Type | Description

:::note

For workchain 0, the [`Address{:tact}`][p] of the current contract obtained by calling the [`myAddress(){:tact}`](/ref/core-common#myaddress) function is identical to the one that can be obtained by calling the [`contractAddress(){:tact}`](/ref/core-common#contractaddress) function with the initial state of the current contract computed via `initOf{:tact}`:
For workchain 0, the [`Address{:tact}`][p] of the current contract obtained by calling the [`myAddress(){:tact}`](/ref/core-contextstate#myaddress) function is identical to the one that can be obtained by calling the [`contractAddress(){:tact}`](/ref/core-addresses#contractaddress) function with the initial state of the current contract computed via `initOf{:tact}`:

```tact {6}
contract TheKingPrawn {
Expand All @@ -295,7 +295,7 @@ Field | Type | Description
}
```

However, if you only need the address of the current contract at runtime and not its `StateInit{:tact}`, use the [`myAddress(){:tact}`](/ref/core-common#myaddress) function, as it consumes **significantly** less gas.
However, if you only need the address of the current contract at runtime and not its `StateInit{:tact}`, use the [`myAddress(){:tact}`](/ref/core-contextstate#myaddress) function, as it consumes **significantly** less gas.

:::

Expand All @@ -314,7 +314,7 @@ codeOf ExampleContract; // a Cell with ExampleContract code
// name of the contract
```

If `codeOf{:tact}` is used for the current contract, its result is equivalent to calling [`myCode(){:tact}`](/ref/core-advanced#mycode).
If `codeOf{:tact}` is used for the current contract, its result is equivalent to calling [`myCode(){:tact}`](/ref/core-contextstate#mycode).

```tact
contract ExampleContract {
Expand Down
12 changes: 6 additions & 6 deletions docs/src/content/docs/book/gas-best-practices.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -161,9 +161,9 @@ If your contract method does not access any of its persistent state variables, m

### Use `sender()` over `context().sender`

When you receive an internal message, you can obtain the address of the contract that has sent it. This can be done by calling the [`sender()`](/ref/core-common#sender) function or by accessing the `.sender` field of the `Context{:tact}` [struct][struct] after calling the [`context()`](/ref/core-common#context) function.
When you receive an internal message, you can obtain the address of the contract that has sent it. This can be done by calling the [`sender()`](/ref/core-contextstate#sender) function or by accessing the `.sender` field of the `Context{:tact}` [struct][struct] after calling the [`context()`](/ref/core-contextstate#context) function.

If you only need the sender's address and no additional context on the incoming message that is contained in the `Context{:tact}` struct, then use the [`sender()`](/ref/core-common#sender) function as it is less gas-consuming.
If you only need the sender's address and no additional context on the incoming message that is contained in the `Context{:tact}` struct, then use the [`sender()`](/ref/core-contextstate#sender) function as it is less gas-consuming.

```tact /sender\\(\\)/
message(MessageParameters{
Expand Down Expand Up @@ -194,9 +194,9 @@ fun example() {

Every [contract](/book/contracts) in Tact implicitly [inherits](/book/contracts#traits) the `BaseTrait{:tact}` trait, which contains a number of [internal functions](/book/contracts#internal-functions) for any contract. Those internal functions are gas-expensive for the same reasons as stated earlier.

Calls to `self.forward(){:tact}`, `self.reply(){:tact}` and `self.notify(){:tact}` can be replaced with respective calls to the [`send(){:tact}`](/ref/core-common#send) or [`message(){:tact}`](/ref/core-common#message) functions with suitable values.
Calls to `self.forward(){:tact}`, `self.reply(){:tact}` and `self.notify(){:tact}` can be replaced with respective calls to the [`send(){:tact}`](/ref/core-send#send) or [`message(){:tact}`](/ref/core-send#message) functions with suitable values.

Moreover, if all you want is to forward the remaining value back to the sender, it is best to use the [`cashback(){:tact}`](/ref/core-common#cashback) function instead of `self.notify(){:tact}` function.
Moreover, if all you want is to forward the remaining value back to the sender, it is best to use the [`cashback(){:tact}`](/ref/core-send#cashback) function instead of `self.notify(){:tact}` function.

```tact
// This
Expand Down Expand Up @@ -234,7 +234,7 @@ cashback(sender());

### Use `deploy()` function for on-chain deployments

There are many [message-sending functions](/book/send#message-sending-functions), and the [`deploy(){:tact}`](/ref/core-common#deploy) function is optimized for cheaper on-chain deployments compared to the [`send(){:tact}`](/ref/core-common#send) function.
There are many [message-sending functions](/book/send#message-sending-functions), and the [`deploy(){:tact}`](/ref/core-send#deploy) function is optimized for cheaper on-chain deployments compared to the [`send(){:tact}`](/ref/core-send#send) function.

```tact
deploy(DeployParameters{
Expand All @@ -247,7 +247,7 @@ deploy(DeployParameters{

### Use `message()` function for non-deployment messages

There are many [message-sending functions](/book/send#message-sending-functions), and the [`message(){:tact}`](/ref/core-common#message) function is optimized for cheaper non-deployment regular messages compared to the [`send(){:tact}`](/ref/core-common#send) function.
There are many [message-sending functions](/book/send#message-sending-functions), and the [`message(){:tact}`](/ref/core-send#message) function is optimized for cheaper non-deployment regular messages compared to the [`send(){:tact}`](/ref/core-send#send) function.

```tact
message(MessageParameters{
Expand Down
4 changes: 2 additions & 2 deletions docs/src/content/docs/book/message-mode.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ description: "Messages are sent with the mode param of the struct SendParameters

import { Badge } from '@astrojs/starlight/components';

As previously mentioned, messages sent via the [`send(){:tact}`](/ref/core-common#send) function utilize the `mode` parameter of the `SendParameters{:tact}` structure. The `mode` is an [`Int{:tact}`][int] value, which is combined from base modes and optional flags, which are also [`Int{:tact}`][int] values.
As previously mentioned, messages sent via the [`send(){:tact}`](/ref/core-send#send) function utilize the `mode` parameter of the `SendParameters{:tact}` structure. The `mode` is 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{:tact}`][int] values and manually provide them for the `mode`, but for your convenience there is a set of constants you may use to easily construct the compound `mode`. Take a look at the following tables for more information on base modes and optional flags.

Expand Down Expand Up @@ -68,7 +68,7 @@ Note that there can be only **one** [base mode](#base-modes), but the number of

Some [message-sending functions](/book/send#message-sending-functions) do not allow setting a mode by passing an argument. This is because their internal logic requires a specific fixed set of modes to be used instead:

* [`emit(){:tact}`](/ref/core-common#emit) sends a message with the `SendDefaultMode{:tact}` ($0$).
* [`emit(){:tact}`](/ref/core-send#emit) sends a message with the `SendDefaultMode{:tact}` ($0$).
* [`self.reply(){:tact}`](/ref/core-base#self-reply), [`self.notify(){:tact}`](/ref/core-base#self-notify), and [`self.forward(){:tact}`](/ref/core-base#self-forward) all use the `SendRemainingValue{:tact}` mode unless the [`self.storageReserve{:tact}`](/ref/core-base#self-storagereserve) constant is overridden to be greater than $0$, in which case they attempt to use the `SendRemainingBalance{:tact}` mode.

[int]: /book/integers
Expand Down
4 changes: 2 additions & 2 deletions docs/src/content/docs/book/security-best-practices.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -299,7 +299,7 @@ A message cascade can be processed over many blocks. Assume that while one messa

## Handle/Send bounced messages

Send messages with the bounce flag set to `true{:tact}`, which is the default for the [`send(){:tact}`](/ref/core-common#send) function. Messages bounce when the execution of a contract fails. You may want to handle this by rolling back the state of the contract using [`try...catch{:tact}`](/book/statements#try-catch) statements and performing additional processing depending on your logic.
Send messages with the bounce flag set to `true{:tact}`, which is the default for the [`send(){:tact}`](/ref/core-send#send) function. Messages bounce when the execution of a contract fails. You may want to handle this by rolling back the state of the contract using [`try...catch{:tact}`](/book/statements#try-catch) statements and performing additional processing depending on your logic.

##### Do's ✅

Expand Down Expand Up @@ -356,7 +356,7 @@ From the [Sending messages page](/book/send#outbound-message-processing) of the

> Each transaction on TON Blockchain consists of multiple phases. Outbound messages are evaluated in the compute phase but are **not** sent in that phase. Instead, they're queued in order of appearance for the action phase, where all actions listed in the compute phase, such as outbound messages or reserve requests, are executed.

Hence, if the compute phase fails, [registers](https://docs.ton.org/v3/documentation/tvm/tvm-overview#control-registers) `c4` (persistent data) and `c5` (actions) won't be updated. However, it is possible to manually save their state using the [`commit(){:tact}`](/ref/core-advanced/#commit) function.
Hence, if the compute phase fails, [registers](https://docs.ton.org/v3/documentation/tvm/tvm-overview#control-registers) `c4` (persistent data) and `c5` (actions) won't be updated. However, it is possible to manually save their state using the [`commit(){:tact}`](/ref/core-contextstate#commit) function.

## Return gas excesses carefully

Expand Down
Loading
Loading