diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml index dc09a0be9..4a9401577 100644 --- a/.github/workflows/linter.yml +++ b/.github/workflows/linter.yml @@ -2,6 +2,7 @@ name: 💅 Linting suite env: HUSKY: 0 + NODE_VERSION: 20 on: pull_request: @@ -30,7 +31,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: 20 + node-version: ${{ env.NODE_VERSION }} cache: "npm" - name: Install dependencies @@ -62,7 +63,7 @@ jobs: echo npx remark --no-stdout --quiet --frail --silently-ignore $(echo -e "${ALL_CHANGED_FILES[@]}" | tr '\n' ' ') - - name: ${{ steps.check-fmt.conclusion == 'failure' && '👀' }} How to fix the formatting? See these suggestions! + - name: ${{ steps.check-fmt.conclusion == 'failure' && '👀 How to fix the formatting? See these suggestions!' || '...' }} env: ALL_CHANGED_FILES: ${{ steps.changed-files.outputs.all_changed_files }} if: failure() @@ -93,7 +94,7 @@ jobs: - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: 20 + node-version: ${{ env.NODE_VERSION }} cache: "npm" - name: Install dependencies @@ -107,3 +108,41 @@ jobs: with: check_dot_files: explicit suggestions: true + + redirects-check: + name: "Redirects" + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup Node.js + uses: actions/setup-node@v4 + with: + node-version: ${{ env.NODE_VERSION }} + cache: "npm" + + - name: Install dependencies + run: | + corepack enable + npm ci + + - name: Check uniqueness of redirect sources in docs.json + if: ${{ !cancelled() }} + run: node scripts/check-redirects.mjs unique + + - name: Check existence of redirect destinations in docs.json + if: ${{ !cancelled() }} + run: node scripts/check-redirects.mjs exist + + - name: Check redirects against the previous TON Documentation + if: ${{ !cancelled() }} + run: node scripts/check-redirects.mjs previous + + # NOTE: Re-enable before the release, + # see: https://github.com/ton-org/docs/issues/39 + # - name: Check redirects against the upstream docs.json structure + # if: ${{ !cancelled() }} + # run: node scripts/check-redirects.mjs upstream diff --git a/docs.json b/docs.json index 6b5c28223..aa711d6f2 100644 --- a/docs.json +++ b/docs.json @@ -232,7 +232,6 @@ "payments/overview", "payments/toncoin", "payments/jettons" - ] }, { @@ -593,1091 +592,1478 @@ "redirects": [ { "source": "/v3/concepts/dive-into-ton/introduction", - "destination": "/pending/discover/pending/dive-into-ton-introduction" + "destination": "/", + "permanent": true }, { "source": "/v3/concepts/dive-into-ton/ton-ecosystem/wallet-apps", - "destination": "/pending/discover/tools/wallets" + "destination": "/ecosystem/wallet-apps/overview", + "permanent": true }, { "source": "/v3/concepts/dive-into-ton/ton-ecosystem/explorers-in-ton", - "destination": "/pending/discover/tools/explorers" + "destination": "/ecosystem/explorers/overview", + "permanent": true }, { - "source": "/v3/concepts/dive-into-ton/ton-ecosystem/nft", - "destination": "TODO-NFT-use-cases-into-customer-docs-or-cookbook-with-examples" + "source": "/v3/concepts/dive-into-ton/ton-ecosystem/blockchain-tech", + "destination": "/services/overview", + "permanent": true }, { - "source": "/v3/concepts/dive-into-ton/ton-blockchain/blockchain-of-blockchains", - "destination": "TODO-backport-changes" + "source": "/v3/concepts/dive-into-ton/ton-blockchain/overview", + "destination": "/start-here", + "permanent": true }, { - "source": "/v3/concepts/dive-into-ton/ton-blockchain/smart-contract-addresses", - "destination": "/pending/reference/blockchain/accounts/addresses" + "source": "/v3/concepts/dive-into-ton/ton-blockchain/asynchrony", + "destination": "/start-here", + "permanent": true }, { - "source": "/v3/concepts/dive-into-ton/ton-blockchain/cells-as-data-storage", - "destination": "/pending/discover/ton-fundamentals/cells" + "source": "/v3/concepts/dive-into-ton/ton-blockchain/sharding", + "destination": "/start-here", + "permanent": true }, { - "source": "/v3/concepts/dive-into-ton/ton-blockchain/ton-networking", - "destination": "TODO-rather-useless-might-be-edited-into-fundamentals" + "source": "/v3/concepts/dive-into-ton/ton-blockchain/accounts", + "destination": "/start-here", + "permanent": true }, { - "source": "/v3/concepts/dive-into-ton/ton-blockchain/sharding", - "destination": "/pending/discover/ton-fundamentals/sharding" + "source": "/v3/concepts/dive-into-ton/ton-blockchain/addresses", + "destination": "/start-here", + "permanent": true + }, + { + "source": "/v3/concepts/dive-into-ton/ton-blockchain/smart-contracts", + "destination": "/start-here", + "permanent": true + }, + { + "source": "/v3/concepts/dive-into-ton/ton-blockchain/operations", + "destination": "/start-here", + "permanent": true + }, + { + "source": "/v3/concepts/dive-into-ton/ton-blockchain/ton-virtual-machine", + "destination": "/start-here", + "permanent": true }, { - "source": "/v3/concepts/dive-into-ton/ton-blockchain/blockchain-comparison", - "destination": "/pending/discover/differences/common" + "source": "/v3/concepts/dive-into-ton/ton-blockchain/cells", + "destination": "/start-here", + "permanent": true }, { - "source": "/v3/concepts/dive-into-ton/ton-blockchain/security-measures", - "destination": "/pending/discover/security-audits" + "source": "/v3/concepts/dive-into-ton/ton-blockchain/nodes", + "destination": "/start-here", + "permanent": true }, { - "source": "/v3/concepts/dive-into-ton/go-from-ethereum/blockchain-services", - "destination": "/pending/discover/differences/ethereum" + "source": "/v3/concepts/dive-into-ton/ton-blockchain/network", + "destination": "/start-here", + "permanent": true }, { "source": "/v3/concepts/dive-into-ton/go-from-ethereum/difference-of-blockchains", - "destination": "/pending/discover/differences/ethereum" + "destination": "/from-ethereum", + "permanent": true }, { "source": "/v3/concepts/dive-into-ton/go-from-ethereum/solidity-vs-func", - "destination": "/pending/discover/differences/ethereum" + "destination": "/from-ethereum", + "permanent": true }, { "source": "/v3/concepts/dive-into-ton/go-from-ethereum/tvm-vs-evm", - "destination": "/pending/discover/differences/ethereum" + "destination": "/from-ethereum", + "permanent": true + }, + { + "source": "/v3/concepts/dive-into-ton/go-from-ethereum/blockchain-comparison", + "destination": "/from-ethereum", + "permanent": true + }, + { + "source": "/v3/concepts/security-measures", + "destination": "https://github.com/ton-org/docs/issues/1106", + "permanent": true }, { "source": "/v3/concepts/educational-resources", - "destination": "/pending/discover/education" + "destination": "/more-tutorials", + "permanent": true }, { "source": "/v3/concepts/glossary", - "destination": "/pending/discover/blockchain-basics/glossary" + "destination": "/foundations/glossary", + "permanent": true }, { - "source": "/v3/guidelines/quick-start/:slug*", - "destination": "/pending/build/quick-start/tutorial-TODO-all-inner-guidelines/quick-start" + "source": "/v3/documentation/introduction", + "destination": "/", + "permanent": true }, { - "source": "/v3/guidelines/get-started-with-ton", - "destination": "/pending/build/quick-start/tutorial" + "source": "/v3/documentation/smart-contracts/overview", + "destination": "/contract-dev/first-smart-contract", + "permanent": true }, { - "source": "/guidelines/hello-world", - "destination": "/pending/build/quick-start/tutorial" + "source": "/v3/documentation/smart-contracts/getting-started/javascript", + "destination": "/contract-dev/blueprint/overview", + "permanent": true }, { - "source": "/guidelines/smat-contracts-guidelines", - "destination": "/pending/build/on-chain" + "source": "/v3/documentation/smart-contracts/getting-started/ide-plugins", + "destination": "/contract-dev/ide/overview", + "permanent": true }, { - "source": "/v3/guidelines/smart-contracts/guidelines", - "destination": "/pending/build/on-chain" + "source": "/v3/documentation/smart-contracts/getting-started/testnet", + "destination": "https://github.com/ton-org/docs/issues/51", + "permanent": true }, { - "source": "/v3/guidelines/smart-contracts/get-methods", - "destination": "/pending/build/off-chain/web3/get-methods" + "source": "/v3/documentation/smart-contracts/addresses/address", + "destination": "/foundations/addresses/overview", + "permanent": true }, { - "source": "/v3/guidelines/smart-contracts/fee-calculation", - "destination": "/pending/build/on-chain/fees" + "source": "/v3/documentation/smart-contracts/addresses/address-formats", + "destination": "/foundations/addresses/formats", + "permanent": true }, { - "source": "/guidelines/testing", - "destination": "/pending/build/on-chain/testing" + "source": "/v3/documentation/smart-contracts/addresses/address-states", + "destination": "/foundations/status", + "permanent": true }, { - "source": "/v3/guidelines/smart-contracts/testing/overview", - "destination": "/pending/build/on-chain/testing" + "source": "/v3/documentation/smart-contracts/message-management/messages-and-transactions", + "destination": "/foundations/messages/overview", + "permanent": true }, { - "source": "/v3/guidelines/smart-contracts/testing/blueprint-config", - "destination": "/pending/build/on-chain/testing" + "source": "/v3/documentation/smart-contracts/message-management/sending-messages", + "destination": "https://github.com/ton-org/docs/issues/44", + "permanent": true }, { - "source": "/v3/guidelines/smart-contracts/testing/writing-test-examples", - "destination": "/pending/build/on-chain/testing/exit-codes" + "source": "/v3/documentation/smart-contracts/message-management/internal-messages", + "destination": "/foundations/messages/internal", + "permanent": true }, { - "source": "/v3/guidelines/smart-contracts/testing/collect-contract-gas-metric", - "destination": "/pending/build/on-chain/testing/gas-consumption" + "source": "/v3/documentation/smart-contracts/message-management/external-messages", + "destination": "https://github.com/ton-org/docs/issues/44", + "permanent": true }, { - "source": "/guidelines/security-measures", - "destination": "/pending/build/on-chain/security" + "source": "/v3/documentation/smart-contracts/message-management/non-bounceable-messages", + "destination": "https://github.com/ton-org/docs/issues/1086", + "permanent": true }, { - "source": "/v3/guidelines/smart-contracts/security/overview", - "destination": "/pending/build/on-chain/security" + "source": "/v3/documentation/smart-contracts/message-management/message-modes-cookbook", + "destination": "https://github.com/ton-org/docs/issues/703", + "permanent": true }, { - "source": "/v3/guidelines/smart-contracts/security/common-vulnerabilities", - "destination": "/pending/build/on-chain/security/best-practices" + "source": "/v3/documentation/smart-contracts/message-management/ecosystem-messages-layout", + "destination": "https://github.com/ton-org/docs/issues/44", + "permanent": true }, { - "source": "/v3/guidelines/smart-contracts/security/secure-programming", - "destination": "/pending/build/on-chain/security/best-practices" + "source": "/v3/documentation/smart-contracts/transaction-fees/fees", + "destination": "/contract-dev/gas", + "permanent": true }, { - "source": "/v3/guidelines/smart-contracts/security/things-to-focus", - "destination": "/pending/build/on-chain/security/best-practices" + "source": "/v3/documentation/smart-contracts/transaction-fees/fees-low-level", + "destination": "/foundations/fees", + "permanent": true }, { - "source": "/v3/guidelines/smart-contracts/security/ton-hack-challenge-1", - "destination": "/pending/build/on-chain/security/hack-challenges" + "source": "/v3/documentation/smart-contracts/transaction-fees/accept-message-effects", + "destination": "https://github.com/ton-org/docs/issues/1104", + "permanent": true }, { - "source": "/v3/guidelines/smart-contracts/security/random-number-generation", - "destination": "/pending/build/on-chain/security/best-practices" + "source": "/v3/documentation/smart-contracts/transaction-fees/forward-fees", + "destination": "/foundations/fees#forward-fee", + "permanent": true }, { - "source": "/v3/guidelines/smart-contracts/security/random", - "destination": "/pending/build/on-chain/security/best-practices" + "source": "/v3/documentation/smart-contracts/shards/shards-intro", + "destination": "/foundations/shards", + "permanent": true }, { - "source": "/guidelines/how-to", - "destination": "/pending/build/on-chain/standard-smart-contracts" + "source": "/v3/documentation/smart-contracts/shards/infinity-sharding-paradigm", + "destination": "/foundations/shards", + "permanent": true }, { - "source": "/guidelines/compile-from-sources", - "destination": "/pending/build/on-chain/legacy-examples" + "source": "/v3/documentation/smart-contracts/limits", + "destination": "/foundations/limits", + "permanent": true }, { - "source": "/v3/guidelines/smart-contracts/howto/compile/compilation-instructions", - "destination": "/pending/build/on-chain/legacy-examples" + "source": "/v3/documentation/smart-contracts/contracts-specs/wallet-contracts", + "destination": "/standard/wallets/comparison", + "permanent": true }, { - "source": "/v3/guidelines/smart-contracts/howto/compile/instructions-low-memory", - "destination": "/pending/build/on-chain/legacy-examples" + "source": "/v3/documentation/smart-contracts/contracts-specs/highload-wallet", + "destination": "/standard/wallets/highload/overview", + "permanent": true }, { - "source": "/v3/guidelines/smart-contracts/howto/multisig", - "destination": "/pending/build/on-chain/legacy-examples" + "source": "/v3/documentation/smart-contracts/contracts-specs/vesting-contract", + "destination": "/standard/vesting", + "permanent": true }, { - "source": "/v3/guidelines/smart-contracts/howto/multisig-js", - "destination": "/pending/build/on-chain/legacy-examples" + "source": "/v3/documentation/smart-contracts/contracts-specs/governance", + "destination": "/foundations/system", + "permanent": true }, { - "source": "/v3/guidelines/smart-contracts/howto/airdrop-claim-best-practice", - "destination": "/pending/build/on-chain/standard-smart-contracts/airdrop" + "source": "/v3/documentation/smart-contracts/contracts-specs/nominator-pool", + "destination": "https://github.com/ton-org/docs/issues/107", + "permanent": true }, { - "source": "/v3/guidelines/smart-contracts/howto/shard-optimization", - "destination": "/pending/build/on-chain/contract-dev/sharding" + "source": "/v3/documentation/smart-contracts/contracts-specs/single-nominator-pool", + "destination": "https://github.com/ton-org/docs/issues/107", + "permanent": true }, { - "source": "/v3/guidelines/smart-contracts/howto/wallet", - "destination": "/pending/build/on-chain/standard-smart-contracts/wallet" + "source": "/v3/documentation/smart-contracts/contracts-specs/precompiled-contracts", + "destination": "/foundations/precompiled", + "permanent": true }, { - "source": "/v3/guidelines/smart-contracts/howto/nominator-pool", - "destination": "/participate/nominator-pool" + "source": "/v3/documentation/smart-contracts/contracts-specs/examples", + "destination": "/more-tutorials", + "permanent": true }, { - "source": "/v3/guidelines/smart-contracts/howto/single-nominator-pool", - "destination": "/participate/nominator-pool" + "source": "/v3/documentation/smart-contracts/tolk/overview", + "destination": "/languages/tolk", + "permanent": true }, { - "source": "/guidelines/dapps", - "destination": "/pending/build/off-chain" + "source": "/v3/documentation/smart-contracts/tolk/environment-setup", + "destination": "/languages/tolk", + "permanent": true }, { - "source": "/v3/guidelines/dapps/overview", - "destination": "/pending/build/off-chain" + "source": "/v3/documentation/smart-contracts/tolk/counter-smart-contract", + "destination": "/languages/tolk", + "permanent": true }, { - "source": "/v3/guidelines/dapps/cookbook", - "destination": "/pending/build/off-chain" + "source": "/v3/documentation/smart-contracts/tolk/language-guide", + "destination": "/languages/tolk", + "permanent": true }, { - "source": "/v3/guidelines/dapps/transactions/overview", - "destination": "/pending/discover/ton-fundamentals/transactions" + "source": "/v3/documentation/smart-contracts/tolk/tolk-vs-func/in-short", + "destination": "/languages/tolk", + "permanent": true }, { - "source": "/v3/guidelines/dapps/transactions/foundations-of-blockchain", - "destination": "TODO-might-go-to-Discover" + "source": "/v3/documentation/smart-contracts/tolk/tolk-vs-func/in-detail", + "destination": "/languages/tolk", + "permanent": true }, { - "source": "/v3/guidelines/dapps/transactions/message-driven-execution", - "destination": "/pending/discover/ton-fundamentals/messages" + "source": "/v3/documentation/smart-contracts/tolk/tolk-vs-func/mutability", + "destination": "/languages/tolk", + "permanent": true }, { - "source": "/v3/guidelines/dapps/transactions/hash-based-tracking", - "destination": "TODO" + "source": "/v3/documentation/smart-contracts/tolk/tolk-vs-func/stdlib", + "destination": "/languages/tolk", + "permanent": true }, { - "source": "/v3/guidelines/dapps/transactions/api-based-retrieval", - "destination": "TODO" + "source": "/v3/documentation/smart-contracts/tolk/tolk-vs-func/pack-to-from-cells", + "destination": "/languages/tolk", + "permanent": true }, { - "source": "/v3/guidelines/dapps/transactions/explore-transactions", - "destination": "TODO" + "source": "/v3/documentation/smart-contracts/tolk/tolk-vs-func/create-message", + "destination": "/languages/tolk", + "permanent": true }, { - "source": "/guidelines/api-sdk", - "destination": "/pending/discover/tools/sdks" + "source": "/v3/documentation/smart-contracts/tolk/tolk-vs-func/lazy-loading", + "destination": "/languages/tolk", + "permanent": true }, { - "source": "/v3/guidelines/dapps/apis-sdks/overview", - "destination": "/pending/discover/tools/sdks" + "source": "/v3/documentation/smart-contracts/tolk/changelog", + "destination": "/languages/tolk", + "permanent": true }, { - "source": "/v3/guidelines/dapps/apis-sdks/sdk", - "destination": "/pending/discover/tools/sdks" + "source": "/v3/documentation/smart-contracts/func/overview", + "destination": "/languages/func", + "permanent": true }, { - "source": "/v3/guidelines/dapps/apis-sdks/api-types", - "destination": "/pending/discover/apis" + "source": "/v3/documentation/smart-contracts/func/cookbook", + "destination": "/languages/func/cookbook", + "permanent": true }, { - "source": "/v3/guidelines/dapps/apis-sdks/ton-http-apis", - "destination": "/pending/discover/apis" + "source": "/v3/documentation/smart-contracts/func/docs/types", + "destination": "/languages/func/types", + "permanent": true }, { - "source": "/v3/guidelines/dapps/apis-sdks/ton-adnl-apis", - "destination": "/pending/discover/apis" + "source": "/v3/documentation/smart-contracts/func/docs/comments", + "destination": "/languages/func/comments", + "permanent": true }, { - "source": "/guidelines/tutorials-and-examples", - "destination": "/pending/build/off-chain/web3" + "source": "/v3/documentation/smart-contracts/func/docs/literals_identifiers", + "destination": "/languages/func/literals", + "permanent": true }, { - "source": "/v3/guidelines/dapps/tutorials/jetton-airdrop", - "destination": "TODO" + "source": "/v3/documentation/smart-contracts/func/docs/functions", + "destination": "/languages/func/functions", + "permanent": true }, { - "source": "/v3/guidelines/dapps/apis-sdks/api-keys", - "destination": "TODO-how-to-get-ton-center-API-key" + "source": "/v3/documentation/smart-contracts/func/docs/global_variables", + "destination": "/languages/func/global-variables", + "permanent": true }, { - "source": "/v3/guidelines/dapps/apis-sdks/getblock-ton-api", - "destination": "TODO-http-api-by-GetBlock" + "source": "/v3/documentation/smart-contracts/func/docs/compiler_directives", + "destination": "/languages/func/compiler-directives", + "permanent": true }, { - "source": "/v3/guidelines/dapps/tutorials/nft-minting-guide", - "destination": "TODO" + "source": "/v3/documentation/smart-contracts/func/docs/statements", + "destination": "/languages/func/statements", + "permanent": true }, { - "source": "/v3/guidelines/dapps/tutorials/mint-your-first-token", - "destination": "TODO" + "source": "/v3/documentation/smart-contracts/func/docs/builtins", + "destination": "/languages/func/built-ins", + "permanent": true }, { - "source": "/v3/guidelines/dapps/tutorials/zero-knowledge-proofs", - "destination": "TODO" + "source": "/v3/documentation/smart-contracts/func/docs/dictionaries", + "destination": "/languages/func/dictionaries", + "permanent": true }, { - "source": "/v3/guidelines/dapps/tutorials/web3-game-example", - "destination": "TODO-in-complete-examples" + "source": "/v3/documentation/smart-contracts/func/docs/stdlib", + "destination": "/languages/func/stdlib", + "permanent": true }, { - "source": "/guidelines/tg-bot-examples", - "destination": "/pending/build/off-chain/telegram-bots" + "source": "/v3/documentation/smart-contracts/func/libraries", + "destination": "/languages/func/libraries", + "permanent": true }, { - "source": "/v3/guidelines/dapps/tutorials/telegram-bot-examples/accept-payments-in-a-telegram-bot", - "destination": "/pending/build/off-chain/telegram-bots/ton-store" + "source": "/v3/documentation/smart-contracts/func/changelog", + "destination": "/languages/func/changelog", + "permanent": true }, { - "source": "/v3/guidelines/dapps/tutorials/telegram-bot-examples/accept-payments-in-a-telegram-bot-2", - "destination": "/pending/build/off-chain/telegram-bots/ton-balance" + "source": "/v3/documentation/smart-contracts/fift/overview", + "destination": "/languages/fift", + "permanent": true }, { - "source": "/v3/guidelines/dapps/tutorials/telegram-bot-examples/accept-payments-in-a-telegram-bot-js", - "destination": "TODO-burgers-and-ice-cream" + "source": "/v3/documentation/smart-contracts/fift/fift-and-tvm-assembly", + "destination": "/languages/fift/fift-and-tvm-assembly", + "permanent": true }, { - "source": "/guidelines/tma", - "destination": "/pending/build/off-chain/telegram-mini-apps" + "source": "/v3/documentation/smart-contracts/fift/fift-deep-dive", + "destination": "/languages/fift/deep-dive", + "permanent": true }, { - "source": "/v3/guidelines/dapps/tma/overview", - "destination": "/pending/build/off-chain/telegram-mini-apps" + "source": "/v3/documentation/smart-contracts/tact", + "destination": "/languages/tact", + "permanent": true }, { - "source": "/guidelines/tma-guidelines", - "destination": "/pending/build/off-chain/telegram-mini-apps" + "source": "/v3/documentation/dapps/dapps-overview", + "destination": "/", + "permanent": true }, { - "source": "/v3/guidelines/dapps/tma/guidelines/testing-apps", - "destination": "/pending/build/off-chain/telegram-mini-apps" + "source": "/v3/documentation/dapps/assets/toncoin", + "destination": "/standard/wallets/how-it-works", + "permanent": true }, { - "source": "/v3/guidelines/dapps/tma/guidelines/publishing", - "destination": "/pending/build/off-chain/telegram-mini-apps" + "source": "/v3/documentation/dapps/assets/jetton", + "destination": "/standard/tokens/jettons/overview", + "permanent": true }, { - "source": "/v3/guidelines/dapps/tma/guidelines/monetization", - "destination": "/pending/build/off-chain/telegram-mini-apps" + "source": "/v3/documentation/dapps/assets/nft", + "destination": "/standard/tokens/nft/overview", + "permanent": true }, { - "source": "/v3/guidelines/dapps/tma/guidelines/tips-and-tricks", - "destination": "/pending/build/off-chain/telegram-mini-apps" + "source": "/v3/documentation/dapps/assets/nft-2.0", + "destination": "/standard/tokens/nft/nft-2.0", + "permanent": true }, { - "source": "/guidelines/tma-tutorials-and-examples", - "destination": "/pending/build/off-chain/telegram-mini-apps" + "source": "/v3/documentation/dapps/assets/usdt", + "destination": "https://github.com/ton-org/docs/issues/191", + "permanent": true }, { - "source": "/v3/guidelines/dapps/tma/tutorials/step-by-step-guide", - "destination": "/pending/build/off-chain/telegram-mini-apps" + "source": "/v3/documentation/dapps/assets/extra-currencies", + "destination": "https://github.com/ton-org/docs/issues/1107", + "permanent": true }, { - "source": "/v3/guidelines/dapps/tma/tutorials/app-examples", - "destination": "/pending/build/off-chain/telegram-mini-apps" + "source": "/v3/documentation/dapps/assets/overview", + "destination": "/standard/tokens/overview", + "permanent": true }, { - "source": "/v3/guidelines/dapps/tma/tutorials/design-guidelines", - "destination": "/pending/build/off-chain/telegram-mini-apps" + "source": "/v3/documentation/dapps/defi/nft", + "destination": "/standard/tokens/nft/overview", + "permanent": true }, { - "source": "/v3/guidelines/dapps/tma/notcoin", - "destination": "TODO-low-value" + "source": "/v3/documentation/dapps/defi/subscriptions", + "destination": "https://github.com/ton-org/docs/issues/1108", + "permanent": true }, { - "source": "/v3/guidelines/dapps/tma/grants", - "destination": "TODO-low-value" + "source": "/v3/documentation/dapps/defi/ton-payments", + "destination": "/services/payment", + "permanent": true }, { - "source": "/guidelines/advanced-asset-processing", - "destination": "/pending/build/off-chain/web3" + "source": "/v3/documentation/infra/oracles/overview", + "destination": "/ecosystem/oracles/overview", + "permanent": true }, { - "source": "/v3/guidelines/dapps/asset-processing/payments-processing", - "destination": "/pending/build/off-chain/web3/toncoin" + "source": "/v3/documentation/infra/oracles/pyth", + "destination": "/ecosystem/oracles/pyth", + "permanent": true }, { - "source": "/v3/guidelines/dapps/asset-processing/jettons", - "destination": "/pending/build/off-chain/standard-smart-contracts/jetton" + "source": "/v3/documentation/infra/oracles/redstone", + "destination": "/ecosystem/oracles/redstone", + "permanent": true }, { - "source": "/v3/guidelines/dapps/asset-processing/mintless-jettons", - "destination": "/pending/build/off-chain/standard-smart-contracts/mintless-jetton" + "source": "/v3/documentation/nodes/overview", + "destination": "/ecosystem/node/overview", + "permanent": true }, { - "source": "/v3/guidelines/dapps/asset-processing/compressed-nfts", - "destination": "/pending/build/off-chain/standard-smart-contracts/compressed-nft" + "source": "/v3/documentation/nodes/validation/collators", + "destination": "/ecosystem/node/mytonctrl/collator", + "permanent": true }, { - "source": "/v3/guidelines/dapps/asset-processing/mass-mint-tools", - "destination": "TODO-more-likely-to-be-part-of-Discover-or-Overview" + "source": "/v3/documentation/nodes/validation/staking-incentives", + "destination": "/ecosystem/node/mytonctrl/liquid_staking", + "permanent": true }, { - "source": "/guidelines/nft-processing", - "destination": "/pending/build/off-chain/standard-smart-contracts/nft" + "source": "/v3/documentation/dapps/proofs", + "destination": "/foundations/proofs/overview", + "permanent": true }, { - "source": "/v3/guidelines/dapps/asset-processing/nft-processing/nfts", - "destination": "/pending/build/off-chain/standard-smart-contracts/nft" + "source": "/v3/documentation/dapps/basic-proofing-concepts", + "destination": "/foundations/proofs/overview", + "permanent": true }, { - "source": "/v3/guidelines/dapps/asset-processing/nft-processing/metadata-parsing", - "destination": "/pending/build/off-chain/standard-smart-contracts/nft" + "source": "/v3/documentation/nodes/mytonctrl/overview", + "destination": "/ecosystem/node/mytonctrl/overview", + "permanent": true }, { - "source": "/guidelines/nodes-guidelines", - "destination": "/participate" + "source": "/v3/documentation/nodes/mytonctrl/commands", + "destination": "/ecosystem/node/mytonctrl/overview", + "permanent": true }, { - "source": "/v3/guidelines/nodes/overview", - "destination": "/participate" + "source": "/v3/documentation/nodes/mytonctrl/status", + "destination": "/ecosystem/node/setup-mytonctrl#verify-services-and-synchronization", + "permanent": true }, { - "source": "/guidelines/running-nodes", - "destination": "/participate" + "source": "/v3/documentation/nodes/mytonctrl/errors", + "destination": "/ecosystem/node/setup-mytonctrl#troubleshooting-imports", + "permanent": true }, { - "source": "/v3/guidelines/nodes/running-nodes/archive-node", - "destination": "/participate/nodes/archive-node" + "source": "/v3/documentation/infra/bridges/toncoin", + "destination": "/ecosystem/bridges", + "permanent": true }, { - "source": "/v3/guidelines/nodes/running-nodes/full-node", - "destination": "/participate/nodes/full-node" + "source": "/v3/documentation/infra/bridges/toncoin-addresses", + "destination": "/ecosystem/bridges", + "permanent": true }, { - "source": "/v3/guidelines/nodes/running-nodes/liteserver-node", - "destination": "/participate/nodes/liteserver-node" + "source": "/v3/documentation/network/global-config", + "destination": "/ecosystem/node/setup-mytonctrl", + "permanent": true }, { - "source": "/v3/guidelines/nodes/running-nodes/validator-node", - "destination": "/participate/nodes/validator-node" + "source": "/v3/documentation/network/config-params/overview", + "destination": "/foundations/config", + "permanent": true }, { - "source": "/v3/guidelines/nodes/running-nodes/staking-with-nominator-pools", - "destination": "/participate/nominator-pool" + "source": "/v3/documentation/network/config-params/update", + "destination": "/foundations/system#config", + "permanent": true }, { - "source": "/v3/guidelines/nodes/running-nodes/run-mytonctrl-docker", - "destination": "/participate" + "source": "/v3/documentation/network/config-params/extra-currency", + "destination": "https://github.com/ton-org/docs/issues/1107", + "permanent": true }, { - "source": "/v3/guidelines/nodes/running-nodes/running-a-local-ton", - "destination": "/pending/build/local-blockchain" + "source": "/v3/documentation/network/protocols/adnl/overview", + "destination": "https://github.com/ton-org/docs/issues/1035", + "permanent": true }, { - "source": "/v3/guidelines/nodes/running-nodes/secure-guidelines", - "destination": "/participate/nodes/security" + "source": "/v3/documentation/network/protocols/adnl/low-level", + "destination": "https://github.com/ton-org/docs/issues/1035", + "permanent": true }, { - "source": "/guidelines/maintenance-guidelines", - "destination": "TODO-this-and-the-rest-of-guidelines" + "source": "/v3/documentation/network/protocols/adnl/tcp", + "destination": "https://github.com/ton-org/docs/issues/1035", + "permanent": true }, { - "source": "/guidelines/ton-connect", - "destination": "TODO" + "source": "/v3/documentation/network/protocols/adnl/udp", + "destination": "https://github.com/ton-org/docs/issues/1035", + "permanent": true }, { - "source": "/v3/guidelines/ton-connect/overview", - "destination": "TODO-same-as-before" + "source": "/v3/documentation/network/protocols/dht/overview", + "destination": "/foundations/network", + "permanent": true }, { - "source": "/v3/guidelines/ton-connect/quick-start", - "destination": "TODO" + "source": "/v3/documentation/network/protocols/dht/deep-dive", + "destination": "/foundations/network", + "permanent": true }, { - "source": "/guidelines/dapp-guide", - "destination": "TODO" + "source": "/v3/documentation/network/protocols/rldp", + "destination": "/foundations/network", + "permanent": true }, { - "source": "/v3/guidelines/ton-connect/creating-manifest", - "destination": "TODO" + "source": "/v3/documentation/network/protocols/overlay", + "destination": "/ecosystem/node/mytonctrl/custom_overlays", + "permanent": true }, { - "source": "/guidelines/install-ton-connect", - "destination": "TODO" + "source": "/v3/documentation/data-formats/tlb/overview", + "destination": "/languages/TL-B/overview", + "permanent": true }, { - "source": "/v3/guidelines/ton-connect/frameworks/react", - "destination": "TODO" + "source": "/v3/documentation/data-formats/tlb/types", + "destination": "/languages/TL-B/syntax-and-semantics", + "permanent": true }, { - "source": "/v3/guidelines/ton-connect/frameworks/web", - "destination": "TODO" + "source": "/v3/documentation/data-formats/tlb/crc32", + "destination": "https://en.wikipedia.org/wiki/Cyclic_redundancy_check", + "permanent": true }, { - "source": "/v3/guidelines/ton-connect/frameworks/python", - "destination": "TODO" + "source": "/v3/documentation/data-formats/tlb/tools", + "destination": "/languages/TL-B/tooling", + "permanent": true }, { - "source": "/v3/guidelines/ton-connect/verifying-signed-in-users", - "destination": "TODO" + "source": "/v3/documentation/data-formats/layout/messages", + "destination": "/foundations/messages/overview", + "permanent": true }, { - "source": "/guidelines/cookbook", - "destination": "TODO" + "source": "/v3/documentation/data-formats/layout/transactions", + "destination": "/foundations/phases", + "permanent": true }, { - "source": "/v3/guidelines/ton-connect/cookbook/cells", - "destination": "TODO-message-body" + "source": "/v3/documentation/data-formats/layout/blocks", + "destination": "/foundations/blocks", + "permanent": true }, { - "source": "/v3/guidelines/ton-connect/cookbook/ton-transfer", - "destination": "TODO" + "source": "/v3/documentation/data-formats/cells/overview", + "destination": "/foundations/serialization/cells", + "permanent": true }, { - "source": "/v3/guidelines/ton-connect/cookbook/jetton-transfer", - "destination": "TODO" + "source": "/v3/documentation/data-formats/cells/exotic", + "destination": "/foundations/serialization/cells#kinds-of-cells", + "permanent": true }, { - "source": "/v3/guidelines/ton-connect/cookbook/nft-transfer", - "destination": "TODO" + "source": "/v3/documentation/data-formats/cells/library", + "destination": "/foundations/serialization/library", + "permanent": true }, { - "source": "/v3/guidelines/ton-connect/guidelines/transaction-by-external-message", - "destination": "TODO" + "source": "/v3/documentation/data-formats/cells/serialization", + "destination": "/foundations/serialization/boc", + "permanent": true }, { - "source": "/v3/guidelines/ton-connect/wallet", - "destination": "TODO" + "source": "/v3/documentation/data-formats/tl", + "destination": "https://core.telegram.org/mtproto/TL", + "permanent": true }, { - "source": "/v3/guidelines/ton-connect/guidelines/developers", - "destination": "TODO" + "source": "/v3/documentation/tvm/overview", + "destination": "/tvm/overview", + "permanent": true }, { - "source": "/guidelines/advanced", - "destination": "TODO-with-two-external-links" + "source": "/v3/documentation/tvm/initialization", + "destination": "/tvm/initialization", + "permanent": true }, { - "source": "/guidelines/business", - "destination": "TODO" + "source": "/v3/documentation/tvm/exit-codes", + "destination": "/tvm/exit-codes", + "permanent": true }, { - "source": "/v3/guidelines/ton-connect/business/ton-connect-for-business", - "destination": "TODO-should-be-same-as-before" + "source": "/v3/documentation/tvm/instructions", + "destination": "/tvm/instructions", + "permanent": true }, { - "source": "/v3/guidelines/ton-connect/business/ton-connect-for-security", - "destination": "TODO" + "source": "/v3/documentation/tvm/specification/runvm", + "destination": "https://github.com/ton-org/docs/issues/22", + "permanent": true }, { - "source": "/guidelines/web3-guidelines", - "destination": "TODO" + "source": "/v3/documentation/tvm/changelog/tvm-upgrade-2025-02", + "destination": "/tvm/changelog", + "permanent": true }, { - "source": "/v3/guidelines/web3/overview", - "destination": "TODO-should-be-same" + "source": "/v3/documentation/tvm/changelog/tvm-upgrade-2024-04", + "destination": "/tvm/changelog", + "permanent": true }, { - "source": "/guidelines/ton-dns", - "destination": "TODO" + "source": "/v3/documentation/tvm/changelog/tvm-upgrade-2023-07", + "destination": "/tvm/changelog", + "permanent": true }, { - "source": "/v3/guidelines/web3/ton-dns/subresolvers", - "destination": "TODO" + "source": "/v3/documentation/whitepapers/overview", + "destination": "/foundations/whitepapers/overview#overview", + "permanent": true }, { - "source": "/guidelines/proxy-and-sites", - "destination": "TODO" + "source": "/v3/documentation/faq", + "destination": "/get-support", + "permanent": true }, { - "source": "/v3/guidelines/web3/ton-proxy-sites/how-to-run-ton-site", - "destination": "TODO" + "source": "/v3/guidelines/quick-start/getting-started", + "destination": "/contract-dev/first-smart-contract", + "permanent": true }, { - "source": "/v3/guidelines/web3/ton-proxy-sites/ton-sites-for-applications", - "destination": "TODO" + "source": "/v3/guidelines/quick-start/blockchain-interaction/reading-from-network", + "destination": "/contract-dev/first-smart-contract", + "permanent": true }, { - "source": "/v3/guidelines/web3/ton-proxy-sites/connect-with-ton-proxy", - "destination": "TODO" + "source": "/v3/guidelines/quick-start/blockchain-interaction/writing-to-network", + "destination": "/contract-dev/first-smart-contract", + "permanent": true }, { - "source": "/v3/guidelines/web3/ton-proxy-sites/how-to-open-any-ton-site", - "destination": "TODO" + "source": "/v3/guidelines/quick-start/developing-smart-contracts/setup-environment", + "destination": "/contract-dev/first-smart-contract", + "permanent": true }, { - "source": "/v3/guidelines/web3/ton-proxy-sites/site-and-domain-management", - "destination": "TODO" + "source": "/v3/guidelines/quick-start/developing-smart-contracts/func-tolk-folder/blueprint-sdk-overview", + "destination": "/contract-dev/first-smart-contract", + "permanent": true }, { - "source": "/v3/guidelines/web3/ton-proxy-sites/running-your-own-ton-proxy", - "destination": "TODO" + "source": "/v3/guidelines/quick-start/developing-smart-contracts/func-tolk-folder/storage-and-get-methods", + "destination": "/contract-dev/first-smart-contract", + "permanent": true }, { - "source": "/guidelines/ton-storage", - "destination": "TODO" + "source": "/v3/guidelines/quick-start/developing-smart-contracts/func-tolk-folder/processing-messages", + "destination": "/contract-dev/first-smart-contract", + "permanent": true }, { - "source": "/v3/guidelines/web3/ton-storage/storage-daemon", - "destination": "TODO" + "source": "/v3/guidelines/quick-start/developing-smart-contracts/func-tolk-folder/deploying-to-network", + "destination": "/contract-dev/first-smart-contract", + "permanent": true }, { - "source": "/v3/guidelines/web3/ton-storage/storage-provider", - "destination": "TODO" + "source": "/v3/guidelines/quick-start/developing-smart-contracts/tact-folder/tact-blueprint-sdk-overview", + "destination": "/contract-dev/first-smart-contract", + "permanent": true }, { - "source": "/v3/guidelines/web3/ton-storage/storage-faq", - "destination": "TODO" + "source": "/v3/guidelines/quick-start/developing-smart-contracts/tact-folder/tact-storage-and-get-methods", + "destination": "/contract-dev/first-smart-contract", + "permanent": true }, { - "source": "/v3/documentation/ton-documentation", - "destination": "/" + "source": "/v3/guidelines/quick-start/developing-smart-contracts/tact-folder/tact-deploying-to-network", + "destination": "/contract-dev/first-smart-contract", + "permanent": true }, { - "source": "/v3/documentation/faq", - "destination": "/pending/discover" + "source": "/v3/guidelines/get-started-with-ton", + "destination": "/contract-dev/first-smart-contract", + "permanent": true }, { - "source": "/v3/documentation/smart-contracts/overview", - "destination": "/pending/reference/blockchain/standard-smart-contracts" + "source": "/guidelines/hello-world", + "destination": "/contract-dev/first-smart-contract", + "permanent": true }, { - "source": "/v3/documentation/smart-contracts/addresses", - "destination": "/pending/reference/blockchain/accounts/addresses" + "source": "/guidelines/smat-contracts-guidelines", + "destination": "/contract-dev/debug", + "permanent": true }, { - "source": "/v3/documentation/smart-contracts/getting-started/javascript", - "destination": "/pending/build/setup" + "source": "/v3/guidelines/smart-contracts/guidelines", + "destination": "/contract-dev/debug", + "permanent": true }, { - "source": "/v3/documentation/smart-contracts/getting-started/ide-plugins", - "destination": "/pending/build/setup" + "source": "/v3/guidelines/smart-contracts/get-methods", + "destination": "/contract-dev/blueprint/deploy#executing-get-methods", + "permanent": true }, { - "source": "/v3/documentation/smart-contracts/getting-started/testnet", - "destination": "/pending/reference/blockchain/network/testnet" + "source": "/v3/guidelines/smart-contracts/fee-calculation", + "destination": "/foundations/fees", + "permanent": true }, { - "source": "/v3/documentation/smart-contracts/contracts-specs/wallet-contracts", - "destination": "/pending/reference/blockchain/standard-smart-contracts/wallets" + "source": "/guidelines/testing", + "destination": "/contract-dev/testing/overview", + "permanent": true }, { - "source": "/v3/documentation/smart-contracts/contracts-specs/highload-wallet", - "destination": "/pending/reference/blockchain/standard-smart-contracts/highload-wallets" + "source": "/v3/guidelines/smart-contracts/testing/overview", + "destination": "/contract-dev/testing/overview", + "permanent": true }, { - "source": "/v3/documentation/smart-contracts/contracts-specs/vesting-contract", - "destination": "/pending/reference/blockchain/standard-smart-contracts/wallets/vesting" + "source": "/v3/guidelines/smart-contracts/testing/blueprint-config", + "destination": "/contract-dev/blueprint/config", + "permanent": true }, { - "source": "/v3/documentation/smart-contracts/contracts-specs/governance", - "destination": "/pending/reference/blockchain/standard-smart-contracts/core/governance" + "source": "/v3/guidelines/smart-contracts/testing/writing-test-examples", + "destination": "/contract-dev/testing/overview", + "permanent": true }, { - "source": "/v3/documentation/smart-contracts/contracts-specs/nominator-pool", - "destination": "/pending/reference/blockchain/standard-smart-contracts/core/nominator-pool" + "source": "/v3/guidelines/smart-contracts/testing/collect-contract-gas-metric", + "destination": "/contract-dev/blueprint/benchmarks", + "permanent": true }, { - "source": "/v3/documentation/smart-contracts/contracts-specs/single-nominator-pool", - "destination": "/pending/reference/blockchain/standard-smart-contracts/core/nominator-pool" + "source": "/guidelines/security-measures", + "destination": "/contract-dev/security", + "permanent": true }, { - "source": "/v3/documentation/smart-contracts/contracts-specs/precompiled-contracts", - "destination": "/pending/reference/blockchain/standard-smart-contracts/core/precompiled" + "source": "/v3/guidelines/smart-contracts/security/overview", + "destination": "/contract-dev/security", + "permanent": true }, { - "source": "/v3/documentation/smart-contracts/contracts-specs/examples", - "destination": "/pending/reference/blockchain/standard-smart-contracts" + "source": "/v3/guidelines/smart-contracts/security/common-vulnerabilities", + "destination": "/contract-dev/security", + "permanent": true }, { - "source": "/v3/documentation/smart-contracts/limits", - "destination": "/pending/reference/blockchain/limits" + "source": "/v3/guidelines/smart-contracts/security/secure-programming", + "destination": "/contract-dev/security", + "permanent": true }, { - "source": "/v3/documentation/smart-contracts/message-management/messages-and-transactions", - "destination": "TODO" + "source": "/v3/guidelines/smart-contracts/security/things-to-focus", + "destination": "/contract-dev/security", + "permanent": true }, { - "source": "/v3/documentation/smart-contracts/message-management/sending-messages", - "destination": "TODO" + "source": "/v3/guidelines/smart-contracts/security/ton-hack-challenge-1", + "destination": "https://github.com/ton-blockchain/hack-challenge-1", + "permanent": true }, { - "source": "/v3/documentation/smart-contracts/message-management/internal-messages", - "destination": "TODO" + "source": "/v3/guidelines/smart-contracts/security/random-number-generation", + "destination": "/contract-dev/random", + "permanent": true }, { - "source": "/v3/documentation/smart-contracts/message-management/external-messages", - "destination": "TODO" + "source": "/v3/guidelines/smart-contracts/security/random", + "destination": "/contract-dev/random", + "permanent": true }, { - "source": "/v3/documentation/smart-contracts/message-management/non-bounceable-messages", - "destination": "TODO" + "source": "/guidelines/how-to", + "destination": "/", + "permanent": true }, { - "source": "/v3/documentation/smart-contracts/message-management/message-modes-cookbook", - "destination": "TODO" + "source": "/guidelines/compile-from-sources", + "destination": "https://github.com/ton-blockchain/ton#build-ton-blockchain", + "permanent": true }, { - "source": "/v3/documentation/smart-contracts/message-management/ecosystem-messages-layout", - "destination": "TODO" + "source": "/v3/guidelines/smart-contracts/howto/compile/compilation-instructions", + "destination": "https://github.com/ton-blockchain/ton#build-ton-blockchain", + "permanent": true }, { - "source": "/v3/documentation/smart-contracts/transaction-fees/fees", - "destination": "/pending/reference/blockchain/fees" + "source": "/v3/guidelines/smart-contracts/howto/compile/instructions-low-memory", + "destination": "https://github.com/ton-blockchain/ton#build-ton-blockchain", + "permanent": true }, { - "source": "/v3/documentation/smart-contracts/transaction-fees/fees-low-level", - "destination": "/pending/reference/blockchain/fees" + "source": "/v3/guidelines/smart-contracts/howto/multisig", + "destination": "/standard/wallets/multisig", + "permanent": true }, { - "source": "/v3/documentation/smart-contracts/transaction-fees/accept-message-effects", - "destination": "/pending/reference/blockchain/fees" + "source": "/v3/guidelines/smart-contracts/howto/multisig-js", + "destination": "/standard/wallets/multisig", + "permanent": true }, { - "source": "/v3/documentation/smart-contracts/transaction-fees/forward-fees", - "destination": "/pending/reference/blockchain/fees" + "source": "/v3/guidelines/smart-contracts/howto/airdrop-claim-best-practice", + "destination": "/standard/tokens/airdrop", + "permanent": true }, { - "source": "/v3/documentation/smart-contracts/shards/shards-intro", - "destination": "/pending/reference/blockchain/sharding" + "source": "/v3/guidelines/smart-contracts/howto/shard-optimization", + "destination": "/contract-dev/contract-sharding", + "permanent": true }, { - "source": "/v3/documentation/smart-contracts/shards/infinity-sharding-paradigm", - "destination": "/pending/reference/blockchain/sharding" + "source": "/v3/guidelines/smart-contracts/howto/wallet", + "destination": "/standard/wallets/how-it-works", + "permanent": true }, { - "source": "/v3/documentation/smart-contracts/tact", - "destination": "/pending/reference/blockchain/standard-smart-contracts" + "source": "/v3/guidelines/smart-contracts/howto/nominator-pool", + "destination": "/ecosystem/node/mytonctrl/pools", + "permanent": true }, { - "source": "/v3/documentation/smart-contracts/tolk/overview", - "destination": "/pending/reference/tolk" + "source": "/v3/guidelines/smart-contracts/howto/single-nominator-pool", + "destination": "/ecosystem/node/mytonctrl/pools", + "permanent": true }, { - "source": "/v3/documentation/smart-contracts/tolk/environment-setup", - "destination": "/pending/reference/tolk" + "source": "/guidelines/dapps", + "destination": "/", + "permanent": true }, { - "source": "/v3/documentation/smart-contracts/tolk/counter-smart-contract", - "destination": "/pending/reference/tolk" + "source": "/v3/guidelines/dapps/overview", + "destination": "/", + "permanent": true }, { - "source": "/v3/documentation/smart-contracts/tolk/language-guide", - "destination": "/pending/reference/tolk" + "source": "/v3/guidelines/dapps/cookbook", + "destination": "/", + "permanent": true }, { - "source": "/v3/documentation/smart-contracts/tolk/tolk-vs-func/in-short", - "destination": "/pending/reference/tolk" + "source": "/v3/guidelines/dapps/transactions/overview", + "destination": "/foundations/overview", + "permanent": true }, { - "source": "/v3/documentation/smart-contracts/tolk/tolk-vs-func/in-detail", - "destination": "/pending/reference/tolk" + "source": "/v3/guidelines/dapps/transactions/foundations-of-blockchain", + "destination": "/foundations/overview", + "permanent": true }, { - "source": "/v3/documentation/smart-contracts/tolk/tolk-vs-func/mutability", - "destination": "/pending/reference/tolk" + "source": "/v3/guidelines/dapps/transactions/message-driven-execution", + "destination": "/foundations/overview", + "permanent": true }, { - "source": "/v3/documentation/smart-contracts/tolk/tolk-vs-func/stdlib", - "destination": "/pending/reference/tolk" + "source": "/v3/guidelines/dapps/transactions/hash-based-tracking", + "destination": "/ecosystem/api/overview", + "permanent": true }, { - "source": "/v3/documentation/smart-contracts/tolk/tolk-vs-func/pack-to-from-cells", - "destination": "/pending/reference/tolk" + "source": "/v3/guidelines/dapps/transactions/api-based-retrieval", + "destination": "/ecosystem/api/overview", + "permanent": true }, { - "source": "/v3/documentation/smart-contracts/tolk/tolk-vs-func/create-message", - "destination": "/pending/reference/tolk" + "source": "/v3/guidelines/dapps/transactions/explore-transactions", + "destination": "/foundations/overview", + "permanent": true }, { - "source": "/v3/documentation/smart-contracts/tolk/tolk-vs-func/lazy-loading", - "destination": "/pending/reference/tolk" + "source": "/guidelines/api-sdk", + "destination": "/ecosystem/api/overview", + "permanent": true }, { - "source": "/v3/documentation/smart-contracts/tolk/changelog", - "destination": "/pending/changelog/tolk" + "source": "/v3/guidelines/dapps/apis-sdks/overview", + "destination": "/ecosystem/api/overview", + "permanent": true }, { - "source": "/v3/documentation/smart-contracts/func/overview", - "destination": "/pending/reference/blockchain/standard-smart-contracts" + "source": "/v3/guidelines/dapps/apis-sdks/api-types", + "destination": "/ecosystem/api/overview", + "permanent": true }, { - "source": "/v3/documentation/smart-contracts/func/cookbook", - "destination": "/pending/reference/blockchain/legacy/func/cookbook" + "source": "/v3/guidelines/dapps/apis-sdks/sdk", + "destination": "/ecosystem/sdks", + "permanent": true }, { - "source": "/v3/documentation/smart-contracts/func/docs/types", - "destination": "/pending/reference/blockchain/legacy/func/types" + "source": "/v3/guidelines/dapps/apis-sdks/ton-adnl-apis", + "destination": "https://github.com/ton-org/docs/issues/1035", + "permanent": true }, { - "source": "/v3/documentation/smart-contracts/func/docs/comments", - "destination": "/pending/reference/blockchain/legacy/func/comments" + "source": "/v3/guidelines/dapps/apis-sdks/analytics-and-data", + "destination": "/ecosystem/analytics#analytics-and-data-providers", + "permanent": true }, { - "source": "/v3/documentation/smart-contracts/func/docs/literals_identifiers", - "destination": "/pending/reference/blockchain/legacy/func/literals" + "source": "/guidelines/tutorials-and-examples", + "destination": "/standard/overview", + "permanent": true }, { - "source": "/v3/documentation/smart-contracts/func/docs/functions", - "destination": "/pending/reference/blockchain/legacy/func/functions" + "source": "/v3/guidelines/dapps/tutorials/jetton-airdrop", + "destination": "/standard/tokens/airdrop", + "permanent": true }, { - "source": "/v3/documentation/smart-contracts/func/docs/global_variables", - "destination": "/pending/reference/blockchain/legacy/func/global-variables" + "source": "/v3/guidelines/dapps/apis-sdks/api-keys", + "destination": "/ecosystem/api/toncenter/get-api-key", + "permanent": true }, { - "source": "/v3/documentation/smart-contracts/func/docs/compiler_directives", - "destination": "/pending/reference/blockchain/legacy/func/compiler-directives" + "source": "/v3/guidelines/dapps/apis-sdks/getblock-ton-api", + "destination": "/ecosystem/api/toncenter/overview", + "permanent": true }, { - "source": "/v3/documentation/smart-contracts/func/docs/statements", - "destination": "/pending/reference/blockchain/legacy/func/statements" + "source": "/v3/guidelines/dapps/tutorials/nft-minting-guide", + "destination": "https://github.com/ton-org/docs/issues/586", + "permanent": true }, { - "source": "/v3/documentation/smart-contracts/func/docs/builtins", - "destination": "/pending/reference/blockchain/legacy/func/build-ins" + "source": "/v3/guidelines/dapps/tutorials/mint-your-first-token", + "destination": "/standard/tokens/jettons/mint", + "permanent": true }, { - "source": "/v3/documentation/smart-contracts/func/docs/dictionaries", - "destination": "/pending/reference/blockchain/legacy/func/dictionaries" + "source": "/v3/guidelines/dapps/tutorials/zero-knowledge-proofs", + "destination": "https://github.com/ton-org/docs/issues/111", + "permanent": true }, { - "source": "/v3/documentation/smart-contracts/func/docs/stdlib", - "destination": "/pending/reference/blockchain/legacy/func/stdlib" + "source": "/v3/guidelines/dapps/tutorials/web3-game-example", + "destination": "https://github.com/ton-org/docs/issues/91", + "permanent": true }, { - "source": "/v3/documentation/smart-contracts/func/libraries", - "destination": "/pending/reference/blockchain/legacy/func/libraries" + "source": "/guidelines/tg-bot-examples", + "destination": "https://github.com/ton-org/docs/issues/87", + "permanent": true }, { - "source": "/v3/documentation/smart-contracts/func/changelog", - "destination": "/pending/changelog/func" + "source": "/v3/guidelines/dapps/tutorials/telegram-bot-examples/accept-payments-in-a-telegram-bot", + "destination": "https://github.com/ton-org/docs/issues/87", + "permanent": true }, { - "source": "/v3/documentation/smart-contracts/fift/overview", - "destination": "/language/fift" + "source": "/v3/guidelines/dapps/tutorials/telegram-bot-examples/accept-payments-in-a-telegram-bot-2", + "destination": "https://github.com/ton-org/docs/issues/87", + "permanent": true }, { - "source": "/v3/documentation/smart-contracts/fift/fift-and-tvm-assembly", - "destination": "/language/fift/fift-and-tvm-assembly" + "source": "/v3/guidelines/dapps/tutorials/telegram-bot-examples/accept-payments-in-a-telegram-bot-js", + "destination": "https://github.com/ton-org/docs/issues/87", + "permanent": true }, { - "source": "/v3/documentation/smart-contracts/fift/fift-deep-dive", - "destination": "/language/fift/deep-dive" + "source": "/guidelines/tma", + "destination": "/ecosystem/tma/overview", + "permanent": true }, { - "source": "/v3/documentation/dapps/dapps-overview", - "destination": "TODO" + "source": "/v3/guidelines/dapps/tma/overview", + "destination": "/ecosystem/tma/overview", + "permanent": true }, { - "source": "/v3/documentation/dapps/defi/coins", - "destination": "TODO" + "source": "/guidelines/tma-guidelines", + "destination": "/ecosystem/tma/overview", + "permanent": true }, { - "source": "/v3/documentation/dapps/defi/tokens", - "destination": "TODO" + "source": "/v3/guidelines/dapps/tma/guidelines/testing-apps", + "destination": "/ecosystem/tma/overview", + "permanent": true }, { - "source": "/v3/documentation/dapps/defi/nft", - "destination": "TODO" + "source": "/v3/guidelines/dapps/tma/guidelines/publishing", + "destination": "/ecosystem/tma/overview", + "permanent": true }, { - "source": "/v3/documentation/dapps/defi/subscriptions", - "destination": "TODO" + "source": "/v3/guidelines/dapps/tma/guidelines/monetization", + "destination": "/ecosystem/tma/overview", + "permanent": true }, { - "source": "/v3/documentation/dapps/defi/ton-payments", - "destination": "TODO" + "source": "/v3/guidelines/dapps/tma/guidelines/tips-and-tricks", + "destination": "/ecosystem/tma/overview", + "permanent": true }, { - "source": "/v3/documentation/dapps/assets/overview", - "destination": "TODO" + "source": "/guidelines/tma-tutorials-and-examples", + "destination": "/ecosystem/tma/overview", + "permanent": true }, { - "source": "/v3/documentation/dapps/assets/usdt", - "destination": "TODO" + "source": "/v3/guidelines/dapps/tma/tutorials/step-by-step-guide", + "destination": "/ecosystem/tma/overview", + "permanent": true }, { - "source": "/v3/documentation/dapps/oracles/about_blockchain_oracles", - "destination": "/pending/discover/oracles" + "source": "/v3/guidelines/dapps/tma/tutorials/app-examples", + "destination": "/ecosystem/tma/overview", + "permanent": true }, { - "source": "/v3/documentation/dapps/oracles/pyth", - "destination": "/pending/discover/oracles" + "source": "/v3/guidelines/dapps/tma/tutorials/design-guidelines", + "destination": "/ecosystem/tma/overview", + "permanent": true }, { - "source": "/v3/documentation/dapps/oracles/red_stone", - "destination": "/pending/discover/oracles" + "source": "/guidelines/advanced-asset-processing", + "destination": "/payments/overview", + "permanent": true }, { - "source": "/v3/documentation/infra/nodes/node-types", - "destination": "/pending/reference/blockchain/nodes" + "source": "/v3/guidelines/dapps/asset-processing/payments-processing", + "destination": "/payments/overview", + "permanent": true }, { - "source": "/v3/documentation/infra/nodes/mytonctrl/mytonctrl-overview", - "destination": "/pending/reference/blockchain/nodes" + "source": "/v3/guidelines/dapps/asset-processing/jettons", + "destination": "/standard/tokens/jettons/overview", + "permanent": true }, { - "source": "/v3/documentation/infra/nodes/mytonctrl/mytonctrl-status", - "destination": "/pending/reference/blockchain/nodes" + "source": "/v3/guidelines/dapps/asset-processing/mintless-jettons", + "destination": "/standard/tokens/jettons/mintless/overview", + "permanent": true }, { - "source": "/v3/documentation/infra/nodes/mytonctrl/mytonctrl-errors", - "destination": "/pending/reference/blockchain/nodes" + "source": "/v3/guidelines/dapps/asset-processing/compressed-nfts", + "destination": "/standard/tokens/nft/cNFT-how-it-works", + "permanent": true }, { - "source": "/v3/documentation/infra/nodes/node-commands", - "destination": "/pending/reference/blockchain/nodes" + "source": "/v3/guidelines/dapps/asset-processing/mass-mint-tools", + "destination": "/standard/tokens/nft/overview", + "permanent": true }, { - "source": "/v3/documentation/infra/nodes/validation/staking-incentives", - "destination": "TODO" + "source": "/guidelines/nft-processing", + "destination": "/standard/tokens/nft/overview", + "permanent": true }, { - "source": "/v3/documentation/infra/nodes/validation/collators", - "destination": "TODO" + "source": "/v3/guidelines/dapps/asset-processing/nft-processing/nfts", + "destination": "/standard/tokens/nft/overview", + "permanent": true }, { - "source": "/v3/documentation/infra/minter-flow", - "destination": "TODO" + "source": "/v3/guidelines/dapps/asset-processing/nft-processing/metadata-parsing", + "destination": "/standard/tokens/nft/how-to-get-metadata", + "permanent": true }, { - "source": "/v3/documentation/infra/crosschain/overview", - "destination": "/pending/discover/bridges" + "source": "/guidelines/nodes-guidelines", + "destination": "/ecosystem/node/overview", + "permanent": true }, { - "source": "/v3/documentation/infra/crosschain/bridge-addresses", - "destination": "/pending/discover/bridges" + "source": "/v3/guidelines/nodes/overview", + "destination": "/ecosystem/node/overview", + "permanent": true }, { - "source": "/v3/documentation/network/configs/network-configs", - "destination": "/pending/reference/blockchain/config" + "source": "/guidelines/running-nodes", + "destination": "/ecosystem/node/overview", + "permanent": true }, { - "source": "/v3/documentation/network/configs/blockchain-configs", - "destination": "/pending/reference/blockchain/config" + "source": "/v3/guidelines/nodes/running-nodes/archive-node", + "destination": "/ecosystem/node/overview", + "permanent": true }, { - "source": "/v3/documentation/network/configs/config-params", - "destination": "/pending/reference/blockchain/config" + "source": "/v3/guidelines/nodes/running-nodes/full-node", + "destination": "/ecosystem/node/overview", + "permanent": true }, { - "source": "/v3/documentation/network/protocols/adnl/overview", - "destination": "/pending/reference/blockchain/network/adnl" + "source": "/v3/guidelines/nodes/running-nodes/liteserver-node", + "destination": "/ecosystem/node/overview", + "permanent": true }, { - "source": "/v3/documentation/network/protocols/adnl/low-level-adnl", - "destination": "/pending/reference/blockchain/network/adnl" + "source": "/v3/guidelines/nodes/running-nodes/validator-node", + "destination": "/ecosystem/node/overview", + "permanent": true }, { - "source": "/v3/documentation/network/protocols/adnl/adnl-tcp", - "destination": "/pending/reference/blockchain/network/adnl" + "source": "/v3/guidelines/nodes/running-nodes/collators-validators", + "destination": "/ecosystem/node/overview", + "permanent": true }, { - "source": "/v3/documentation/network/protocols/adnl/adnl-udp", - "destination": "/pending/reference/blockchain/network/adnl" + "source": "/v3/guidelines/nodes/running-nodes/staking-with-nominator-pools", + "destination": "https://github.com/ton-org/docs/issues/1000", + "permanent": true }, { - "source": "/v3/documentation/network/protocols/dht/ton-dht", - "destination": "/pending/reference/blockchain/network/dht" + "source": "/v3/guidelines/nodes/running-nodes/run-mytonctrl-docker", + "destination": "/ecosystem/node/setup-mytonctrl", + "permanent": true }, { - "source": "/v3/documentation/network/protocols/dht/dht-deep-dive", - "destination": "/pending/reference/blockchain/network/dht" + "source": "/v3/guidelines/nodes/running-nodes/running-a-local-ton", + "destination": "/ecosystem/node/setup-mylocalton", + "permanent": true }, { - "source": "/v3/documentation/network/protocols/rldp", - "destination": "/pending/reference/blockchain/network/rldp" + "source": "/v3/guidelines/nodes/running-nodes/secure-guidelines", + "destination": "/ecosystem/node/overview", + "permanent": true }, { - "source": "/v3/documentation/network/protocols/overlay", - "destination": "/pending/reference/blockchain/network/overlay-subnets" + "source": "/guidelines/maintenance-guidelines", + "destination": "/ecosystem/node/overview", + "permanent": true }, { - "source": "/v3/documentation/data-formats/tlb/tl-b-language", - "destination": "/pending/reference/serialization/tlb" + "source": "/v3/guidelines/nodes/maintenance-guidelines/mytonctrl-backup-restore", + "destination": "/ecosystem/node/overview", + "permanent": true }, { - "source": "/v3/documentation/data-formats/tlb/cell-boc", - "destination": "/pending/reference/serialization/boc" + "source": "/v3/guidelines/nodes/maintenance-guidelines/mytonctrl-validator-standby", + "destination": "/ecosystem/node/overview", + "permanent": true }, { - "source": "/v3/documentation/data-formats/tlb/exotic-cells", - "destination": "/pending/reference/serialization/cells" + "source": "/v3/guidelines/nodes/maintenance-guidelines/mytonctrl-private-alerting", + "destination": "/ecosystem/node/overview", + "permanent": true }, { - "source": "/v3/documentation/data-formats/tlb/library-cells", - "destination": "/pending/reference/serialization/cells" + "source": "/v3/guidelines/nodes/maintenance-guidelines/mytonctrl-prometheus", + "destination": "/ecosystem/node/overview", + "permanent": true }, { - "source": "/v3/documentation/data-formats/tlb/proofs", - "destination": "TODO" + "source": "/v3/guidelines/nodes/maintenance-guidelines/mytonctrl-remote-controller", + "destination": "/ecosystem/node/overview", + "permanent": true }, { - "source": "/v3/documentation/data-formats/tlb/basic-proofing-concepts", - "destination": "/pending/reference/serialization/proofs/basic" + "source": "/v3/guidelines/nodes/custom-overlays", + "destination": "/ecosystem/node/overview", + "permanent": true }, { - "source": "/v3/documentation/data-formats/tlb/tl-b-types", - "destination": "/pending/reference/serialization/tlb-builtins" + "source": "/v3/guidelines/nodes/nodes-troubleshooting", + "destination": "/ecosystem/node/overview", + "permanent": true }, { - "source": "/v3/documentation/data-formats/tlb/canonical-cell-serialization", - "destination": "/pending/reference/serialization/canonical" + "source": "/v3/guidelines/nodes/node-maintenance-and-security", + "destination": "/ecosystem/node/overview", + "permanent": true }, { - "source": "/v3/documentation/data-formats/tlb/msg-tlb", - "destination": "/pending/reference/serialization/tlb-schemas/message" + "source": "/v3/guidelines/nodes/monitoring/performance-monitoring", + "destination": "/ecosystem/node/overview", + "permanent": true }, { - "source": "/v3/documentation/data-formats/tlb/block-layout", - "destination": "/pending/reference/serialization/tlb-schemas/block" + "source": "/v3/guidelines/nodes/persistent-states", + "destination": "/ecosystem/node/overview", + "permanent": true }, { - "source": "/v3/documentation/data-formats/tlb/transaction-layout", - "destination": "/pending/reference/serialization/tlb-schemas/transaction" + "source": "/v3/guidelines/nodes/faq", + "destination": "/ecosystem/node/overview", + "permanent": true }, { - "source": "/v3/documentation/data-formats/tlb/crc32", - "destination": "/pending/reference/serialization/tlb" + "source": "/guidelines/ton-connect", + "destination": "/ecosystem/ton-connect", + "permanent": true }, { - "source": "/v3/documentation/data-formats/tlb/tlb-ide", - "destination": "/pending/discover/tools/editors" + "source": "/v3/guidelines/ton-connect/overview", + "destination": "/ecosystem/ton-connect", + "permanent": true }, { - "source": "/v3/documentation/data-formats/tlb/tlb-tools", - "destination": "/pending/discover/tools/sdks" + "source": "/v3/guidelines/ton-connect/quick-start", + "destination": "/ecosystem/ton-connect/dapp", + "permanent": true }, { - "source": "/v3/documentation/data-formats/tl", - "destination": "/pending/reference/blockchain/network/tl" + "source": "/guidelines/dapp-guide", + "destination": "/ecosystem/ton-connect/dapp", + "permanent": true }, { - "source": "/v3/documentation/tvm/tvm-overview", - "destination": "/pending/reference/tvm" + "source": "/v3/guidelines/ton-connect/creating-manifest", + "destination": "/ecosystem/ton-connect/manifest", + "permanent": true }, { - "source": "/v3/documentation/tvm/tvm-initialization", - "destination": "/pending/reference/tvm/init" + "source": "/guidelines/install-ton-connect", + "destination": "/ecosystem/ton-connect/dapp", + "permanent": true }, { - "source": "/v3/documentation/tvm/tvm-exit-codes", - "destination": "/pending/reference/tvm/exit-codes" + "source": "/v3/guidelines/ton-connect/frameworks/react", + "destination": "/ecosystem/ton-connect/dapp", + "permanent": true }, { - "source": "/v3/documentation/tvm/instructions", - "destination": "/pending/reference/tvm/instructions" + "source": "/v3/guidelines/ton-connect/frameworks/web", + "destination": "/ecosystem/ton-connect/dapp", + "permanent": true }, { - "source": "/v3/documentation/tvm/specification/runvm", - "destination": "/pending/reference/tvm/runvm" + "source": "/v3/guidelines/ton-connect/frameworks/python", + "destination": "/ecosystem/ton-connect/dapp", + "permanent": true }, { - "source": "/v3/documentation/tvm/changelog/tvm-upgrade-2025-02", - "destination": "/pending/changelog/tvm" + "source": "/v3/guidelines/ton-connect/verifying-signed-in-users", + "destination": "https://github.com/ton-org/docs/issues/90", + "permanent": true }, { - "source": "/v3/documentation/tvm/changelog/tvm-upgrade-2024-04", - "destination": "/pending/changelog/tvm" + "source": "/guidelines/cookbook", + "destination": "/ecosystem/ton-connect/dapp", + "permanent": true }, { - "source": "/v3/documentation/tvm/changelog/tvm-upgrade-2023-07", - "destination": "/pending/changelog/tvm" + "source": "/v3/guidelines/ton-connect/cookbook/cells", + "destination": "/ecosystem/ton-connect", + "permanent": true }, { - "source": "/v3/documentation/whitepapers/overview", - "destination": "/pending/reference/blockchain/legacy/whitepapers" + "source": "/v3/guidelines/ton-connect/cookbook/ton-transfer", + "destination": "/ecosystem/ton-connect/dapps/send-toncoin", + "permanent": true + }, + { + "source": "/v3/guidelines/ton-connect/cookbook/jetton-transfer", + "destination": "/ecosystem/ton-connect/dapps/send-jetton", + "permanent": true + }, + { + "source": "/v3/guidelines/ton-connect/cookbook/nft-transfer", + "destination": "/ecosystem/ton-connect/dapps/send-nft", + "permanent": true + }, + { + "source": "/v3/guidelines/ton-connect/guidelines/transaction-by-external-message", + "destination": "/ecosystem/ton-connect/message-lookup", + "permanent": true + }, + { + "source": "/v3/guidelines/ton-connect/wallet", + "destination": "/ecosystem/ton-connect/wallet", + "permanent": true + }, + { + "source": "/v3/guidelines/ton-connect/guidelines/developers", + "destination": "/ecosystem/ton-connect", + "permanent": true + }, + { + "source": "/guidelines/advanced", + "destination": "/ecosystem/ton-connect", + "permanent": true + }, + { + "source": "/guidelines/web3-guidelines", + "destination": "/services/overview", + "permanent": true + }, + { + "source": "/v3/guidelines/web3/overview", + "destination": "/services/overview", + "permanent": true }, { - "source": "/ton.pdf", - "destination": "/resources/pdfs/ton.pdf" + "source": "/guidelines/ton-dns", + "destination": "/services/dns", + "permanent": true }, { - "source": "/tvm.pdf", - "destination": "/resources/pdfs/tvm.pdf" + "source": "/v3/guidelines/web3/ton-dns/dns", + "destination": "/services/dns", + "permanent": true }, { - "source": "/tblkch.pdf", - "destination": "/resources/pdfs/tblkch.pdf" + "source": "/v3/guidelines/web3/ton-dns/subresolvers", + "destination": "/services/dns", + "permanent": true }, { - "source": "/catchain.pdf", - "destination": "/resources/pdfs/catchain.pdf" + "source": "/guidelines/proxy-and-sites", + "destination": "/services/sites", + "permanent": true + }, + { + "source": "/v3/guidelines/web3/ton-proxy-sites/how-to-run-ton-site", + "destination": "/services/sites", + "permanent": true + }, + { + "source": "/v3/guidelines/web3/ton-proxy-sites/ton-sites-for-applications", + "destination": "/services/sites", + "permanent": true + }, + { + "source": "/v3/guidelines/web3/ton-proxy-sites/connect-with-ton-proxy", + "destination": "/services/proxy", + "permanent": true + }, + { + "source": "/v3/guidelines/web3/ton-proxy-sites/how-to-open-any-ton-site", + "destination": "/services/sites", + "permanent": true + }, + { + "source": "/v3/guidelines/web3/ton-proxy-sites/site-and-domain-management", + "destination": "/services/sites", + "permanent": true + }, + { + "source": "/v3/guidelines/web3/ton-proxy-sites/running-your-own-ton-proxy", + "destination": "/services/proxy", + "permanent": true + }, + { + "source": "/guidelines/ton-storage", + "destination": "/services/storage", + "permanent": true + }, + { + "source": "/v3/guidelines/web3/ton-storage/storage-daemon", + "destination": "/services/storage", + "permanent": true + }, + { + "source": "/v3/guidelines/web3/ton-storage/storage-provider", + "destination": "/services/storage", + "permanent": true + }, + { + "source": "/v3/guidelines/web3/ton-storage/storage-faq", + "destination": "/services/storage", + "permanent": true }, { - "source": "/fiftbase.pdf", - "destination": "/resources/pdfs/fiftbase.pdf" + "source": "/v3/contribute/README", + "destination": "/contribute", + "permanent": true }, { "source": "/v3/contribute", - "destination": "/contribute" + "destination": "/contribute", + "permanent": true }, { "source": "/v3/contribute/style-guide", - "destination": "/contribute/style-guide" + "destination": "/contribute/style-guide", + "permanent": true }, { "source": "/v3/contribute/content-standardization", - "destination": "/contribute" + "destination": "/contribute", + "permanent": true }, { "source": "/v3/contribute/typography", - "destination": "/contribute" + "destination": "/contribute", + "permanent": true }, { "source": "/v3/contribute/localization-program/translation-style-guide", - "destination": "/contribute" + "destination": "/contribute", + "permanent": true }, { "source": "/v3/contribute/maintainers", - "destination": "/contribute" + "destination": "/contribute", + "permanent": true } ] -} \ No newline at end of file +} diff --git a/foundations/config.mdx b/foundations/config.mdx index f32510c52..67962b2e6 100644 --- a/foundations/config.mdx +++ b/foundations/config.mdx @@ -630,8 +630,8 @@ This parameter relates to bridges for wrapping tokens from other networks into t After thoroughly reviewing this article, it is highly recommended that you dedicate time to a more in-depth study of the following documents: - The original descriptions are present, but they may be limited, in the documents: - - [The Open Network Whitepaper](https://ton.org/whitepaper.pdf) - - [Telegram Open Network Blockchain](/tblkch.pdf) + - [The Open Network Whitepaper](/foundations/whitepapers/ton) + - [Telegram Open Network Blockchain](/foundations/whitepapers/tblkch) - Source code: - [mc-config.h](https://github.com/ton-blockchain/ton/blob/fc9542f5e223140fcca833c189f77b1a5ae2e184/crypto/block/mc-config.h) diff --git a/package-lock.json b/package-lock.json index ed25095fc..579126a98 100644 --- a/package-lock.json +++ b/package-lock.json @@ -7,7 +7,7 @@ "name": "ton-docs", "dependencies": { "cspell": "^9.2.1", - "mint": "^4.2.184", + "mint": "^4.2.186", "remark-cli": "^12.0.1", "remark-frontmatter": "^5.0.0", "remark-gfm": "^4.0.1", @@ -569,9 +569,9 @@ } }, "node_modules/@emnapi/runtime": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.6.0.tgz", - "integrity": "sha512-obtUmAHTMjll499P+D9A3axeJFlhdjOWdKUNs/U6QIGT7V5RjcUW1xToAzjvmgTSQhDbYn/NwfTRoJcQ2rNBxA==", + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.7.0.tgz", + "integrity": "sha512-oAYoQnCYaQZKVS53Fq23ceWMRxq5EhQsE0x0RdQ55jT7wagMu5k+fS39v1fiSLrtrLQlXwVINenqhLMtTrV/1Q==", "optional": true, "dependencies": { "tslib": "^2.4.0" @@ -1456,16 +1456,16 @@ } }, "node_modules/@mintlify/cli": { - "version": "4.0.788", - "resolved": "https://registry.npmjs.org/@mintlify/cli/-/cli-4.0.788.tgz", - "integrity": "sha512-zeaeRWNdAVFBCRuMJP0RPBAZpxsvn/KXAZI++OaIbKxqNvzOnR5ETJEpe5kon1FA7iWRri5dmAYYls43IF5YIw==", + "version": "4.0.790", + "resolved": "https://registry.npmjs.org/@mintlify/cli/-/cli-4.0.790.tgz", + "integrity": "sha512-7konpbPsrSkbwaON28ESEbOPv2PlS48c1WojNyuJkBygJ+CS84JX6vrs1ua+hBChneaJ8n3dF2ry3Tgwc/yUvA==", "dependencies": { "@inquirer/prompts": "^7.9.0", - "@mintlify/common": "1.0.590", - "@mintlify/link-rot": "3.0.731", + "@mintlify/common": "1.0.592", + "@mintlify/link-rot": "3.0.733", "@mintlify/models": "0.0.238", - "@mintlify/prebuild": "1.0.718", - "@mintlify/previewing": "4.0.767", + "@mintlify/prebuild": "1.0.720", + "@mintlify/previewing": "4.0.769", "@mintlify/validation": "0.1.513", "adm-zip": "^0.5.10", "chalk": "^5.2.0", @@ -1492,9 +1492,9 @@ } }, "node_modules/@mintlify/common": { - "version": "1.0.590", - "resolved": "https://registry.npmjs.org/@mintlify/common/-/common-1.0.590.tgz", - "integrity": "sha512-SAMHb5kVltFVULJXMdMLsyE2mnf0hQ7GK/MTO14fsuXGqtFSxh9pwlJOHcqgQ5OLYy31K/VGq5DNzniumLB3Qg==", + "version": "1.0.592", + "resolved": "https://registry.npmjs.org/@mintlify/common/-/common-1.0.592.tgz", + "integrity": "sha512-TLNTpESw9Is4/nXr6NlU6y6+ShJVYdD83tp2PhF0rBDca+uPQZpwNcj+RuvcBMVJZ57DuiPmoaH0wx7evw6Bug==", "dependencies": { "@asyncapi/parser": "^3.4.0", "@mintlify/mdx": "^3.0.1", @@ -1661,13 +1661,13 @@ } }, "node_modules/@mintlify/link-rot": { - "version": "3.0.731", - "resolved": "https://registry.npmjs.org/@mintlify/link-rot/-/link-rot-3.0.731.tgz", - "integrity": "sha512-cdBKhH2qgUpDJn2rAvnZOnpSHcZit3x8kME5KDTj2iYBvbx+8XaMvyGvK2fFSJKL4PAcLISoEsUC7oNOqW9a2A==", + "version": "3.0.733", + "resolved": "https://registry.npmjs.org/@mintlify/link-rot/-/link-rot-3.0.733.tgz", + "integrity": "sha512-o7w01O3sPv2nyetruEcMlFhj4irBHfZj0vTCabex0iSK7VVSe035IIKB1dk6OcSTIyAlgtPWQ3CUfonATvzv8Q==", "dependencies": { - "@mintlify/common": "1.0.590", - "@mintlify/prebuild": "1.0.718", - "@mintlify/previewing": "4.0.767", + "@mintlify/common": "1.0.592", + "@mintlify/prebuild": "1.0.720", + "@mintlify/previewing": "4.0.769", "@mintlify/validation": "0.1.513", "fs-extra": "^11.1.0", "unist-util-visit": "^4.1.1" @@ -1765,13 +1765,13 @@ } }, "node_modules/@mintlify/prebuild": { - "version": "1.0.718", - "resolved": "https://registry.npmjs.org/@mintlify/prebuild/-/prebuild-1.0.718.tgz", - "integrity": "sha512-aojZrNh9KvFalj2ICiwdhhepxz0Z1CtPYZc8LkyU1MCXimzrsFCS9zhmcEbd3bQ2wZJc3GwQCthW2CA12P6TZg==", + "version": "1.0.720", + "resolved": "https://registry.npmjs.org/@mintlify/prebuild/-/prebuild-1.0.720.tgz", + "integrity": "sha512-QdOXR65Hd9Yx29TqeePHY3xQtY7r02rd7gc7m4RVacjRG568LRWLBKWEbfPtoOPrpJjVgaQfEoEsPk4Xqzu59w==", "dependencies": { - "@mintlify/common": "1.0.590", + "@mintlify/common": "1.0.592", "@mintlify/openapi-parser": "^0.0.8", - "@mintlify/scraping": "4.0.450", + "@mintlify/scraping": "4.0.452", "@mintlify/validation": "0.1.513", "chalk": "^5.3.0", "favicons": "^7.2.0", @@ -1831,12 +1831,12 @@ } }, "node_modules/@mintlify/previewing": { - "version": "4.0.767", - "resolved": "https://registry.npmjs.org/@mintlify/previewing/-/previewing-4.0.767.tgz", - "integrity": "sha512-7j2VPhK/HRNgTC+92jd/2neIdL6rEXJ961+890F8pCfJA1SQgkBoo9fbsrF8Q8eXOMD2QMYCz8Tdj306/4QITQ==", + "version": "4.0.769", + "resolved": "https://registry.npmjs.org/@mintlify/previewing/-/previewing-4.0.769.tgz", + "integrity": "sha512-LKnNaZGZ9LEhZPn/COKx9vYum4I8m1cl8j++9ywNysYAVYcOMDokXxYgixvVKcbC+hJ4xSgtPH9lWJwBumMaow==", "dependencies": { - "@mintlify/common": "1.0.590", - "@mintlify/prebuild": "1.0.718", + "@mintlify/common": "1.0.592", + "@mintlify/prebuild": "1.0.720", "@mintlify/validation": "0.1.513", "better-opn": "^3.0.2", "chalk": "^5.1.0", @@ -1906,11 +1906,11 @@ } }, "node_modules/@mintlify/scraping": { - "version": "4.0.450", - "resolved": "https://registry.npmjs.org/@mintlify/scraping/-/scraping-4.0.450.tgz", - "integrity": "sha512-Ft9X9Oh76WdGDJPxKz9sIMOvXMsFSmKWe0zO5aKlZgj17QKhunstnsWCqjBP2kbswYFHrePyupcQOO6xLmJ5vA==", + "version": "4.0.452", + "resolved": "https://registry.npmjs.org/@mintlify/scraping/-/scraping-4.0.452.tgz", + "integrity": "sha512-jjOUkWaSGdIjkxxx/HQnaVdboGaBgmjOgpR5WjJcfALDc2JJH9oxwwmEgt0dt6EAZkhvuFRbSVtpH71aR2dZ5w==", "dependencies": { - "@mintlify/common": "1.0.590", + "@mintlify/common": "1.0.592", "@mintlify/openapi-parser": "^0.0.8", "fs-extra": "^11.1.1", "hast-util-to-mdast": "^10.1.0", @@ -3471,9 +3471,9 @@ } }, "node_modules/ansi-escapes": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.1.1.tgz", - "integrity": "sha512-Zhl0ErHcSRUaVfGUeUdDuLgpkEo8KIFjB4Y9uAc46ScOpdDiU1Dbyplh7qWJeJ/ZHpbyMSM26+X3BySgnIz40Q==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.2.0.tgz", + "integrity": "sha512-g6LhBsl+GBPRWGWsBtutpzBYuIIdBkLEvad5C/va/74Db018+5TZiyA26cZJAr3Rft5lprVqOIPxf5Vid6tqAw==", "dependencies": { "environment": "^1.0.0" }, @@ -3694,9 +3694,9 @@ } }, "node_modules/axios": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.1.tgz", - "integrity": "sha512-hU4EGxxt+j7TQijx1oYdAjw4xuIp1wRQSsbMFwSthCWeBQur1eF+qJ5iQ5sN3Tw8YRzQNKb8jszgBdMDVqwJcw==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz", + "integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==", "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.4", @@ -3807,9 +3807,9 @@ } }, "node_modules/bare-url": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/bare-url/-/bare-url-2.3.1.tgz", - "integrity": "sha512-v2yl0TnaZTdEnelkKtXZGnotiV6qATBlnNuUMrHl6v9Lmmrh9mw9RYyImPU7/4RahumSwQS1k2oKXcRfXcbjJw==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/bare-url/-/bare-url-2.3.2.tgz", + "integrity": "sha512-ZMq4gd9ngV5aTMa5p9+UfY0b3skwhHELaDkhEHetMdX0LRkW9kzaym4oo/Eh+Ghm0CCDuMTsRIGM/ytUc1ZYmw==", "optional": true, "dependencies": { "bare-path": "^3.0.0" @@ -7085,9 +7085,9 @@ } }, "node_modules/inline-style-parser": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.4.tgz", - "integrity": "sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==" + "version": "0.2.6", + "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.6.tgz", + "integrity": "sha512-gtGXVaBdl5mAes3rPcMedEBm12ibjt1kDMFfheul1wUAOVEJW60voNdMVzVkfLN06O7ZaD/rxhfKgtlgtTbMjg==" }, "node_modules/inquirer": { "version": "12.10.0", @@ -9129,11 +9129,11 @@ } }, "node_modules/mint": { - "version": "4.2.184", - "resolved": "https://registry.npmjs.org/mint/-/mint-4.2.184.tgz", - "integrity": "sha512-NPMRTQsi9PuPfOcLcvCDxOU3yBcdOl+2PK9iY767OFAFo20GVwoWfhdCJNXUnwV0H4uvR0kZcfFrs0sEbwMm9g==", + "version": "4.2.186", + "resolved": "https://registry.npmjs.org/mint/-/mint-4.2.186.tgz", + "integrity": "sha512-PJK7B5Y878bFrwkxyBhQ95gwrLcfT6LtvANJ83R6B7uQxaFYzUArMx1/OUSLQzbu9t9lGlWSEywE8OkIsoOmVg==", "dependencies": { - "@mintlify/cli": "4.0.788" + "@mintlify/cli": "4.0.790" }, "bin": { "mint": "index.js", @@ -10976,9 +10976,9 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" }, "node_modules/sax": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", - "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==" + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.3.tgz", + "integrity": "sha512-yqYn1JhPczigF94DMS+shiDMjDowYO6y9+wB/4WgO0Y19jWYk0lQ4tuG5KI7kj4FTp1wxPj5IFfcrz/s1c3jjQ==" }, "node_modules/scheduler": { "version": "0.26.0", @@ -11766,19 +11766,19 @@ } }, "node_modules/style-to-js": { - "version": "1.1.18", - "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.18.tgz", - "integrity": "sha512-JFPn62D4kJaPTnhFUI244MThx+FEGbi+9dw1b9yBBQ+1CZpV7QAT8kUtJ7b7EUNdHajjF/0x8fT+16oLJoojLg==", + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.19.tgz", + "integrity": "sha512-Ev+SgeqiNGT1ufsXyVC5RrJRXdrkRJ1Gol9Qw7Pb72YCKJXrBvP0ckZhBeVSrw2m06DJpei2528uIpjMb4TsoQ==", "dependencies": { - "style-to-object": "1.0.11" + "style-to-object": "1.0.12" } }, "node_modules/style-to-object": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.11.tgz", - "integrity": "sha512-5A560JmXr7wDyGLK12Nq/EYS38VkGlglVzkis1JEdbGWSnbQIEhZzTJhzURXN5/8WwwFCs/f/VVcmkTppbXLow==", + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.12.tgz", + "integrity": "sha512-ddJqYnoT4t97QvN2C95bCgt+m7AAgXjVnkk/jxAfmp7EAB8nnqqZYEbMd3em7/vEomDb2LAQKAy1RFfv41mdNw==", "dependencies": { - "inline-style-parser": "0.2.4" + "inline-style-parser": "0.2.6" } }, "node_modules/sucrase": { diff --git a/package.json b/package.json index 8b2c31a7d..87eee3512 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,7 @@ "start:no-open": "mint dev --no-open", "check:openapi": "mint openapi-check ecosystem/api/toncenter/v2.json && mint openapi-check ecosystem/api/toncenter/v3.yaml", "check:links": "mint broken-links", - "check:redirects": "echo 'https://github.com/ton-org/docs/issues/123'", + "check:redirects": "node scripts/check-redirects.mjs", "check:fs": "echo 'https://github.com/ton-org/docs/issues/167'", "check:fmt": "remark . -e mdx,md --no-stdout --quiet --frail", "check:spell": "cspell --no-progress --show-suggestions .", @@ -22,7 +22,7 @@ }, "dependencies": { "cspell": "^9.2.1", - "mint": "^4.2.184", + "mint": "^4.2.186", "remark-cli": "^12.0.1", "remark-frontmatter": "^5.0.0", "remark-gfm": "^4.0.1", diff --git a/scripts/check-redirects.mjs b/scripts/check-redirects.mjs new file mode 100644 index 000000000..a93e3cdb6 --- /dev/null +++ b/scripts/check-redirects.mjs @@ -0,0 +1,342 @@ +/*─────────────────────────────────────────────────────────────────────────────╗ +│ IMPORTANT: │ +│ Run this script from the root of the docs, not from the scripts directory! │ +╞══════════════════════════════════════════════════════════════════════════════╡ +│ The script can check: │ +│ 1. Redirects against the previous TON Documentation URLs │ +│ 2. Redirects against the upstream docs.json structure │ +│ │ +│ By default, it checks both, but to only check either specify │ +│ `previous` or `upstream` as a command-line argument, respectively. │ +│ │ +│ For example, this command will run the 1st check only: │ +│ $ node scripts/check-redirects.mjs previous │ +╚─────────────────────────────────────────────────────────────────────────────*/ + +// Node.js +import { existsSync, mkdtempSync, rmSync, readFileSync } from 'node:fs'; +import { join } from 'node:path'; +import { tmpdir } from 'node:os'; +import { spawnSync } from 'node:child_process'; + +// Common utils +import { + ansiYellow, + composeSuccess, + composeWarning, + composeError, + composeErrorList, + prefixWithSlash, + getNavLinksSet, + getRedirects, +} from './common.mjs'; + +/** + * Types + * @typedef {import('./common.mjs').DocsConfig} DocsConfig + * @typedef {import('./common.mjs').Sidebars} Sidebars + * @typedef {import('./common.mjs').SidebarItem} SidebarItem + * @typedef {{ok: true} | {ok: false; error: string}} CheckResult + */ + +/** + * Check that all sources in the redirects array are unique, + * don't point to themselves, and don't override the existing structure paths + * + * @param config {Readonly} Local docs.json configuration + * @return {CheckResult} + */ +const checkUnique = (config) => { + const redirects = getRedirects(config); + const redirectSources = redirects.map((it) => it.source); + const duplicates = redirectSources.filter((source, index) => redirectSources.indexOf(source) !== index); + if (duplicates.length !== 0) { + return { + ok: false, + error: composeErrorList( + 'Found duplicate sources in the redirects array:', + duplicates, + 'Redirect sources in docs.json must be unique!', + ), + }; + } + /** @param src {string} */ + const fmt = (src) => prefixWithSlash(src).replace(/#.*$/, '').replace(/\?.*$/, ''); + const loops = redirects.filter((it) => fmt(it.source) == fmt(it.destination)).map((it) => it.source); + if (loops.length !== 0) { + return { + ok: false, + error: composeErrorList( + 'Found sources that lead to themselves, i.e., circular references:', + loops, + 'Redirect sources in docs.json must not self-reference in destinations!', + ), + } + } + const navLinks = getNavLinksSet(config); + const navOverrides = redirectSources.filter((it) => navLinks.has(fmt(it))); + if (navOverrides.length !== 0) { + return { + ok: false, + error: composeErrorList( + 'Found sources that override pages in the docs.json structure:', + navOverrides, + 'Redirect sources in docs.json must not replace existing paths!', + ), + } + } + // Otherwise + return { ok: true }; +}; + +/** + * Check that all destinations in the redirects array point to existing files + * + * @param config {Readonly} Local docs.json configuration + * @return {CheckResult} + */ +const checkExist = (config) => { + const uniqDestinations = [...new Set(getRedirects(config).map((it) => it.destination))]; + let todoDestsExist = false; + let repoIssuesDestsExist = false; + const missingDests = uniqDestinations.filter((it) => { + if (it.startsWith('http')) { + if (it.includes('github.com/ton-org/docs/issues')) { + repoIssuesDestsExist = true; + } + return false; + } + if (it.startsWith('TODO')) { + todoDestsExist = true; + return false; + } + const rel = it.replace(/^\/+/, '').replace(/#.*$/, '').replace(/\?.*$/, ''); + return [rel === '' ? `index.mdx` : `${rel}/index.mdx`, `${rel}.mdx`, `${rel}`].some(existsSync) === false; + }); + if (repoIssuesDestsExist) { + console.log(composeWarning('Found GitHub issue destinations!')); + } + if (todoDestsExist) { + console.log(composeWarning('Found TODO-prefixed destinations!')); + } + if (missingDests.length !== 0) { + return { + ok: false, + error: composeErrorList( + 'Nonexistent destinations found:', + missingDests, + 'Some redirect destinations in docs.json do not exist!', + ), + }; + } + // Otherwise + return { ok: true }; +}; + +/** + * Check redirects against the previous TON Documentation URLs. + * Ensures that old routes point to new files or even anchors. + * + * @param td {string} Temporary directory path + * @param config {Readonly} Parsed docs.json configuration + * @return {Promise} + */ +const checkPrevious = async (td, config) => { + // 1. Clone previous TON Docs in a temporary directory + // in order to obtain the sidebars.js module + const tonDocsPath = join(td, 'ton-docs'); + const cloneRes = spawnSync('git', ['clone', '--depth=1', 'https://github.com/ton-community/ton-docs', tonDocsPath], { + encoding: 'utf8', + timeout: 1_000 * 60 * 10, + }); + if (cloneRes.status != 0) { + return { + ok: false, + error: `${cloneRes.error ?? cloneRes.stdout}`, + }; + } + + // 2. Process sidebars.js and extract all URLs + const sidebarsPath = join(tonDocsPath, 'sidebars.js'); + if (!existsSync(sidebarsPath)) { + return { + ok: false, + error: composeError(`sidebars.js was not found in ${tonDocsPath}`), + }; + } + /** @type Readonly */ + const sidebarsModule = Object.freeze((await import(sidebarsPath)).default); + const sidebarsKeys = Object.keys(sidebarsModule); + /** @type string[] */ + const prevLinks = []; + sidebarsKeys.forEach((key) => { + const sidebar = sidebarsModule[key]; + /** @param sb {SidebarItem} */ + const processItem = (sb) => { + if (typeof sb === 'string') { + prevLinks.push(prefixWithSlash(sb)); + return; + } + switch (sb.type) { + case 'doc': + case 'ref': + prevLinks.push(prefixWithSlash(sb.id)); + break; + case 'link': + if (sb.href.startsWith('/') || !sb.href.startsWith('http')) { + prevLinks.push(prefixWithSlash(sb.href)); + } + break; + case 'category': + if (sb.link) { + if (sb.link.type === 'doc') { + prevLinks.push(prefixWithSlash(sb.link.id)); + } else if (sb.link.type === 'generated-index' && sb.link.slug) { + prevLinks.push(prefixWithSlash(sb.link.slug)); + } + } + sb.items.forEach(processItem); + break; + case 'autogenerated': + case 'html': + default: + break; + } + }; + sidebar.forEach(processItem); + }); + + // 3. Process docs.json and compare its structure and redirects to old links + const currLinks = getNavLinksSet(config); + const prevOnlyLinks = prevLinks.filter((it) => !currLinks.has(it)); + if (prevOnlyLinks.length === 0) { + return { ok: true }; + } + + const redirectSources = getRedirects(config).map((it) => it.source); + const missingSources = prevOnlyLinks.filter( + (it) => + [it, it.replace(/\/index$/, ''), it.replace(/\/README$/, '')].some((variant) => + redirectSources.includes(variant), + ) === false, + ); + if (missingSources.length !== 0) { + return { + ok: false, + error: composeErrorList( + 'Missing pages or redirects for the following URLs:', + missingSources, + 'Some URLS in the previous TON Documentation do not have corresponding pages or redirect sources in the local docs.json!', + ), + }; + } + + // Otherwise + return { ok: true }; +}; + +/** + * Check redirects against the upstream docs.json structure. + * Ensures that changes made to docs.json in the PR + * provide necessary redirects in case local links + * deviated from the links on the main branch. + * + * @param localConfig {Readonly} Local docs.json configuration + * @return {Promise} + */ +const checkUpstream = async (localConfig) => { + const response = await fetch('https://raw.githubusercontent.com/ton-org/docs/refs/heads/main/docs.json'); + + /** @type {DocsConfig} */ + const upstreamConfig = Object.freeze(await response.json()); + const upstreamNavLinks = getNavLinksSet(upstreamConfig); + const localNavLinks = getNavLinksSet(localConfig); + + const upstreamOnlyLinks = [...upstreamNavLinks].filter((it) => !localNavLinks.has(it)); + if (upstreamOnlyLinks.length === 0) { + return { ok: true }; + } + + const redirectSources = getRedirects(localConfig).map((it) => it.source); + const missingSources = upstreamOnlyLinks.filter( + (it) => !redirectSources.includes(it) && !redirectSources.includes(it.replace(/\/index$/, '')), + ); + if (missingSources.length !== 0) { + return { + ok: false, + error: composeErrorList( + 'Missing pages or redirects for the following upstream URLs:', + missingSources, + `Local docs.json does not have corresponding pages or redirect sources for some URLs in the upstream docs.json!\n${ansiYellow('Possible fix:')} merge the main branch into the current one to keep docs.json up to date, or add new redirects to account for removed or renamed pages.`, + ), + }; + } + + // Otherwise + return { ok: true }; +}; + +const main = async () => { + /** @type {Readonly} */ + const config = Object.freeze(JSON.parse(readFileSync('./docs.json', 'utf8'))); + console.log(); // intentional break + + // Creating the temporary directory + const td = mkdtempSync(join(tmpdir(), 'td')); + + // Running either one check or all checks + const rawArgs = process.argv.slice(2); + const argUnique = rawArgs.includes('unique'); // all sources are unique + const argExist = rawArgs.includes('exist'); // all destinations exist + const argPrevious = rawArgs.includes('previous'); // sources cover previous TON Docs + const argUpstream = rawArgs.includes('upstream'); // sources cover upstream docs.json structure + const args = [argUnique, argExist, argPrevious, argUpstream]; + const shouldRunAll = args.every((it) => it) || args.every((it) => !it); + let errored = false; + + /** + * @param res {CheckResult} + * @param rawSuccessMsg {string} + */ + const handleCheckResult = (res, rawSuccessMsg) => { + if (!res.ok) { + errored = true; + console.log(res.error); + } else { + console.log(composeSuccess(rawSuccessMsg)); + }; + if (shouldRunAll) { + console.log(); // intentional break + } + } + + if (shouldRunAll || argUnique) { + console.log('🏁 Checking the uniqueness of redirect sources in docs.json...'); + handleCheckResult(checkUnique(config), 'All sources are unique.'); + } + + if (shouldRunAll || argExist) { + console.log('🏁 Checking the existence of redirect destinations in docs.json...'); + handleCheckResult(checkExist(config), 'All destinations exist.'); + } + + if (shouldRunAll || argPrevious) { + console.log('🏁 Checking redirects against the previous TON Documentation...'); + handleCheckResult(await checkPrevious(td, config), 'Full coverage.'); + } + + if (shouldRunAll || argUpstream) { + console.log('🏁 Checking redirects against the upstream docs.json structure...'); + handleCheckResult(await checkUpstream(config), 'Full coverage.'); + } + + // Removing the temporary directory + rmSync(td, { recursive: true }); + + // In case of errors, exit with code 1 + if (errored) { + process.exit(1); + } +}; + +await main(); diff --git a/scripts/common.mjs b/scripts/common.mjs new file mode 100644 index 000000000..36ef0ec71 --- /dev/null +++ b/scripts/common.mjs @@ -0,0 +1,162 @@ +/** + * Mintlify + * @typedef {import('../node_modules/@mintlify/validation').DocsConfig} DocsConfig + */ + +/** + * Docusaurus + * @typedef {import('./docusaurus-sidebars-types.d.ts').SidebarsConfig} Sidebars + * @typedef {import('./docusaurus-sidebars-types.d.ts').SidebarItemConfig} SidebarItem + * @typedef {import('./docusaurus-sidebars-types.d.ts').SidebarItemDoc} ItemDoc + * @typedef {import('./docusaurus-sidebars-types.d.ts').SidebarItemLink} ItemLink + * @typedef {import('./docusaurus-sidebars-types.d.ts').SidebarItemCategoryBase} ItemCat + */ + +/** @param src {string} */ +export function ansiRed(src) { + return `\x1b[31m${src}\x1b[0m`; +} + +/** @param src {string} */ +export function ansiBoldRed(src) { + return `\x1b[1;31m${src}\x1b[0m`; +} + +/** @param src {string} */ +export function ansiGreen(src) { + return `\x1b[32m${src}\x1b[0m`; +} + +/** @param src {string} */ +export function ansiBoldGreen(src) { + return `\x1b[1;32m${src}\x1b[0m`; +} + +/** @param src {string} */ +export function ansiYellow(src) { + return `\x1b[33m${src}\x1b[0m`; +} + +/** @param src {string} */ +export function ansiBoldYellow(src) { + return `\x1b[1;33m${src}\x1b[0m`; +} + +/** @param src {string} */ +export function ansiBold(src) { + return `\x1b[1m${src}\x1b[0m`; +} + +/** + * Forms a string with the following contents: + * + * ``` + * brief: + * - list[0] + * - list[1] + * - ... + * - list[n - 1] + * + * Error: msg + * ``` + * + * @param brief {string} Brief description of list items + * @param list {string[]} List of inline error messages + * @param msg {string} Complete description of the error message + */ +export function composeErrorList(brief, list, msg) { + return [ansiRed(brief), '- ' + list.join('\n- '), `\n${ansiRed('Error:')} ${msg}`].join('\n'); +} + +/** @param msg {string} */ +export function composeError(msg) { + return `${ansiRed('Error:')} ${msg}`; +} + +/** @param msg {string} */ +export function composeWarning(msg) { + return `${ansiYellow('Warning:')} ${msg}`; +} + +/** @param msg {string} */ +export function composeSuccess(msg) { + return `${ansiGreen('Success:')} ${msg}`; +} + +/** @param src {string} */ +export function prefixWithSlash(src) { + return '/' + src.replace(/^\/+/, ''); +} + +/** + * Get navigation links from the docs.json configuration. + * Notice that each link is prefixed by a single slash / + * regardless if it was present originally. + * + * @param config {DocsConfig} + * @returns {string[]} + */ +export function getNavLinks(config) { + /** @type {string[]} */ + const links = []; + /** @param page {any} */ + const processPage = (page) => { + switch (typeof page) { + case 'string': { + links.push(prefixWithSlash(page)); + break; + } + case 'object': { + if (page?.pages) { + page['pages'].forEach(processPage); + } + break; + } + default: + break; + } + }; + // @ts-ignore + config.navigation?.pages.forEach(processPage); + return links; +} + +/** + * Get navigation links from the docs.json configuration as a Set. + * Notice that each link is prefixed by a single slash / + * regardless if it was present originally. + * + * @param config {DocsConfig} + * @returns {ReadonlySet} + */ +export function getNavLinksSet(config) { + return Object.freeze(new Set(getNavLinks(config))); +} + +/** + * Get redirect objects from the docs.json configuration. + * + * @typedef {{ + * source: string; + * destination: string; + * permanent?: boolean | undefined + * }} Redirect + * @param config {DocsConfig} + * @returns {Redirect[]} + */ +export function getRedirects(config) { + if (!config.redirects) { + return []; + } + return config.redirects; +} + +/** + * Get redirect objects from the docs.json configuration as a Set. + * + * @param config {DocsConfig} + * @returns {ReadonlySet} + */ +export function getRedirectsSet(config) { + return Object.freeze(new Set(getRedirects(config))); +} diff --git a/scripts/docusaurus-sidebars-types.d.ts b/scripts/docusaurus-sidebars-types.d.ts new file mode 100644 index 000000000..a6f1cdba5 --- /dev/null +++ b/scripts/docusaurus-sidebars-types.d.ts @@ -0,0 +1,113 @@ +/** + * Copyright (c) Facebook, Inc. and its affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of: https://github.com/facebook/docusaurus + */ + +type Optional = Omit & + Partial>; + +type Expand = { [P in keyof T]: T[P] }; + +export type SidebarItemBase = { + key?: string; + className?: string; + customProps?: { [key: string]: unknown }; +}; + +export type SidebarItemDoc = SidebarItemBase & { + type: "doc" | "ref"; + label?: string; + id: string; + /** + * This is an internal marker set during the sidebar normalization process. + * Docs with labels defined in the config need to be translated with JSON. + * Otherwise, it's preferable to translate the MDX doc title or front matter. + */ + translatable?: true; +}; + +export type SidebarItemHtml = SidebarItemBase & { + type: "html"; + value: string; + defaultStyle?: boolean; +}; + +export type SidebarItemLink = SidebarItemBase & { + type: "link"; + href: string; + label: string; + autoAddBaseUrl?: boolean; + description?: string; +}; + +export type SidebarItemAutogenerated = SidebarItemBase & { + type: "autogenerated"; + dirName: string; +}; + +type SidebarItemCategoryBase = SidebarItemBase & { + type: "category"; + label: string; + collapsed: boolean; + collapsible: boolean; + description?: string; +}; + +export type SidebarItemCategoryLinkDoc = { type: "doc"; id: string }; + +export type SidebarItemCategoryLinkGeneratedIndexConfig = { + type: "generated-index"; + slug?: string; + title?: string; + description?: string; + image?: string; + keywords?: string | readonly string[]; +}; +export type SidebarItemCategoryLinkGeneratedIndex = { + type: "generated-index"; + slug: string; + permalink: string; + title?: string; + description?: string; + image?: string; + keywords?: string | readonly string[]; +}; + +export type SidebarItemCategoryLinkConfig = + | SidebarItemCategoryLinkDoc + | SidebarItemCategoryLinkGeneratedIndexConfig; + +export type SidebarItemCategoryLink = + | SidebarItemCategoryLinkDoc + | SidebarItemCategoryLinkGeneratedIndex; + +// The user-given configuration in sidebars.js, before normalization +export type SidebarItemCategoryConfig = Expand< + Optional & { + // items: SidebarCategoriesShorthand | SidebarItemConfig[]; + items: SidebarItemConfig[]; + link?: SidebarItemCategoryLinkConfig; + } +>; + +export type SidebarCategoriesShorthand = { + [sidebarCategory: string]: SidebarCategoriesShorthand | SidebarItemConfig[]; +}; + +export type SidebarItemConfig = + | Omit + | SidebarItemHtml + | SidebarItemLink + | SidebarItemAutogenerated + | SidebarItemCategoryConfig + | string + | SidebarCategoriesShorthand; + +// export type SidebarConfig = SidebarCategoriesShorthand | SidebarItemConfig[]; +export type SidebarConfig = SidebarItemConfig[]; + +export type SidebarsConfig = { + [sidebarId: string]: SidebarConfig; +}; diff --git a/standard/wallets/preprocessed-v2/interact.mdx b/standard/wallets/preprocessed-v2/interact.mdx index 86addb8a7..2705ce039 100644 --- a/standard/wallets/preprocessed-v2/interact.mdx +++ b/standard/wallets/preprocessed-v2/interact.mdx @@ -104,7 +104,7 @@ import { Wallet, walletCode } from './wrappers/PreprocessedWalletV2'; // Compiled contract code (BOC) const CODE = walletCode; // Already included in the wrapper -const client = new TonClient({ +const client = new TonClient({ endpoint: 'https://testnet.toncenter.com/api/v2/jsonRPC', // This is TESTNET endpoint // apiKey: 'your-api-key' // Optional: get from @tonapibot or @tontestnetapibot });