### Running @ton-community/sandbox Examples - Shell Source: https://github.com/ton-org/sandbox/blob/develop/examples/README.md This snippet provides the necessary shell commands to clone the @ton-community/sandbox repository, navigate into its examples directory, and then install dependencies and execute the examples using Yarn. This setup is required because the examples are not bundled with the npm package. ```Shell git clone https://github.com/ton-community/sandbox cd sandbox/examples yarn && yarn examples ``` -------------------------------- ### Installing TON Sandbox with Yarn Source: https://github.com/ton-org/sandbox/blob/develop/README.md This command installs the @ton/sandbox package and its core dependencies (@ton/ton, @ton/core, @ton/crypto) using Yarn, a fast, reliable, and secure dependency manager. It's a prerequisite for developing and testing TON smart contracts. ```Shell yarn add @ton/sandbox @ton/ton @ton/core @ton/crypto ``` -------------------------------- ### Setting Up and Syncing Fork with Upstream Repository (Git) Source: https://github.com/ton-org/sandbox/blob/develop/CONTRIBUTING.md This snippet initializes the local repository, adds the upstream remote, fetches updates, and rebases the local main branch to synchronize with the upstream main branch. This ensures the contributor's fork is up-to-date before starting new work. ```bash cd sandbox git remote add upstream https://github.com/ton-community/sandbox.git git fetch upstream git pull --rebase upstream main ``` -------------------------------- ### Installing TON Sandbox with npm Source: https://github.com/ton-org/sandbox/blob/develop/README.md This command installs the @ton/sandbox package and its core dependencies (@ton/ton, @ton/core, @ton/crypto) using npm, the default package manager for Node.js. It's an alternative to Yarn for setting up the development environment for TON smart contracts. ```Shell npm i @ton/sandbox @ton/ton @ton/core @ton/crypto ``` -------------------------------- ### Autogenerated Tact Contract Test Structure (TypeScript) Source: https://github.com/ton-org/sandbox/blob/develop/docs/tact-testing-examples.md This snippet shows the basic structure of an autogenerated test file for a Tact contract using Blueprint. It includes `describe` and `it` blocks, and an example `expect` statement with `toHaveTransaction` for verifying deployment results. ```TypeScript import ... describe('Fireworks', () => { ... expect(deployResult.transactions).toHaveTransaction({ ... }); }); it('should deploy', async () => { // the check is done inside beforeEach // blockchain and fireworks are ready to use }); ``` -------------------------------- ### Retrieving NFT Data with Get Method in TypeScript Source: https://github.com/ton-org/sandbox/blob/develop/README.md Shows how to implement a `get` method (`getData`) in a contract wrapper (`NftItem`) to query on-chain data. It uses `provider.get` to call a smart contract's getter and parses the returned stack values into a structured `NftItemData` object. ```TypeScript import { Contract, ContractProvider } from "@ton/core"; export type NftItemData = { inited: boolean index: number collection: Address | null owner: Address | null content: Cell | null } class NftItem implements Contract { async getData(provider: ContractProvider): Promise { const { stack } = await provider.get('get_nft_data', []) return { inited: stack.readBoolean(), index: stack.readNumber(), collection: stack.readAddressOpt(), owner: stack.readAddressOpt(), content: stack.readCellOpt(), } } } ``` -------------------------------- ### Providing Random Seed for Get Methods in TON Sandbox (TypeScript) Source: https://github.com/ton-org/sandbox/blob/develop/README.md Illustrates how to provide a `randomSeed` when calling a get method on a smart contract in the TON Sandbox. Since randomness is deterministic, a specific seed can be supplied to ensure reproducible random number sequences for `RAND` opcode results. This snippet shows passing a randomly generated 32-byte buffer as the `randomSeed` option. ```TypeScript const res = await blockchain.runGetMethod(example.address, 'get_method', [], { randomSeed: randomBytes(32) } ); const stack = new TupleReader(res.stack); // read data from stack ... ``` -------------------------------- ### Storing Blockchain State Snapshot (TypeScript) Source: https://github.com/ton-org/sandbox/blob/develop/README.md This snippet demonstrates how to capture the current state of a `Blockchain` instance into a snapshot object. This is useful for saving a specific state to restore later, allowing for comparison of outcomes or quick setup for tests without re-executing long configuration sequences. The `snapshot()` method returns an object containing the entire blockchain state. ```typescript const snapshot = blockchain.snapshot() ``` -------------------------------- ### Verifying Cross-Contract Interactions in TON Sandbox Source: https://github.com/ton-org/sandbox/blob/develop/README.md This general example shows the pattern for asserting multiple transactions resulting from a cross-contract message send in the TON Sandbox. After sending a message (`main.sendMessage`), the `res` object, containing transaction information, is used with `toHaveTransaction` to verify specific transaction outcomes. ```TypeScript res = await main.sendMessage(...); expect(res).toHaveTransaction(...) // test case <...> expect(res).toHaveTransaction(...) // test case ``` -------------------------------- ### Asserting Transaction Fees in TON Blockchain (TypeScript) Source: https://github.com/ton-org/sandbox/blob/develop/docs/tact-testing-examples.md This snippet shows how to programmatically access and assert specific components of transaction fees, such as 'totalFees', 'computeFee', and 'actionFee'. It includes an example of verifying that the combined compute and action fees do not exceed a certain threshold, which is crucial for automated testing and ensuring cost efficiency. ```TypeScript it('should be executed with expected fees', async() => { const launcher = await blockchain.treasury('fireworks'); const launchResult = await fireworks.send( launcher.getSender(), { value: toNano('1'), }, { $$type: 'Launch', } ); //totalFee console.log('total fees = ', launchResult.transactions[1].totalFees); const tx1 = launchResult.transactions[1]; if (tx1.description.type !== 'generic') { throw new Error('Generic transaction expected'); } //computeFee const computeFee = tx1.description.computePhase.type === 'vm' ? tx1.description.computePhase.gasFees : undefined; console.log('computeFee = ', computeFee); //actionFee const actionFee = tx1.description.actionPhase?.totalActionFees; console.log('actionFee = ', actionFee); //The check, if Compute Phase and Action Phase fees exceed 1 TON expect(computeFee + actionFee).toBeLessThan(toNano('1')); }); ``` -------------------------------- ### Verifying Message Count in TON Transaction (TypeScript) Source: https://github.com/ton-org/sandbox/blob/develop/docs/tact-testing-examples.md This test verifies that a 'fireworks' contract sends exactly 4 outgoing messages when a 'Launch' message is sent to it. It uses 'blockchain.treasury' to get a sender and 'fireworks.send' to trigger the transaction, then asserts the 'outMessagesCount' using 'toHaveTransaction'. ```typescript it('should send 4 messages to wallet', async() => { const launcher = await blockchain.treasury('fireworks'); const launchResult = await fireworks.send( launcher.getSender(), { value: toNano('1'), }, { $$type: 'Launch', } ); expect(launchResult.transactions).toHaveTransaction({ from: launcher.address, to: fireworks.address, success: true, outMessagesCount: 4 }); }) ``` -------------------------------- ### Running Blueprint Tests (Bash) Source: https://github.com/ton-org/sandbox/blob/develop/docs/tact-testing-examples.md This command demonstrates how to execute the test suite for a Blueprint project using the `npx blueprint test` command from the terminal. ```Bash npx blueprint test ``` -------------------------------- ### Initializing Blockchain Instance in TypeScript Source: https://github.com/ton-org/sandbox/blob/develop/README.md Demonstrates how to create an instance of the `Blockchain` class using its static `create` method, which is the first step to setting up a local TON blockchain environment for testing. ```TypeScript import { Blockchain } from "@ton/sandbox"; const blockchain = await Blockchain.create() ``` -------------------------------- ### Testing Jetton Minting and Excess Return in TON Sandbox Source: https://github.com/ton-org/sandbox/blob/develop/README.md This snippet demonstrates testing a jetton minting operation. It simulates a `sendMint` call from a jetton minter and then uses `toHaveTransaction` to verify two key outcomes: the deployment of a new jetton wallet for the recipient and the return of excess funds from the new wallet back to the minter contract. ```TypeScript it('minter admin should be able to mint jettons', async () => { // can mint from deployer let initialTotalSupply = await jettonMinter.getTotalSupply(); const deployerJettonWallet = await userWallet(deployer.address); let initialJettonBalance = toNano('1000.23'); const mintResult = await jettonMinter.sendMint(deployer.getSender(), deployer.address, initialJettonBalance, toNano('0.05'), toNano('1')); expect(mintResult.transactions).toHaveTransaction({ // test transaction of deployment of a jetton wallet from: jettonMinter.address, to: deployerJettonWallet.address, deploy: true, }); expect(mintResult.transactions).toHaveTransaction({ // test transaction of excesses returned to minter from: deployerJettonWallet.address, to: jettonMinter.address }); }); ``` -------------------------------- ### Building Project and Running Tests (Yarn) Source: https://github.com/ton-org/sandbox/blob/develop/CONTRIBUTING.md This command executes the 'build' script defined in the project's 'package.json' using Yarn. The 'build' script typically compiles the project and automatically runs associated tests, ensuring code quality and functionality before a pull request. ```bash yarn build ``` -------------------------------- ### Running TON Sandbox Benchmarks with Custom Gas Report Configuration (Bash) Source: https://github.com/ton-org/sandbox/blob/develop/README.md These commands execute Blueprint snapshot or test runs, explicitly referencing a custom `gas-report.config.ts` file. This allows for more granular control over which tests are included and how metrics are collected and reported, enabling focused benchmarking scenarios. ```Bash npx blueprint snapshot --label "some label" -- --config gas-report.config.ts npx blueprint test --gas-report -- --config gas-report.config.ts ``` -------------------------------- ### Initializing Blockchain for Real Network Testing (TypeScript) Source: https://github.com/ton-org/sandbox/blob/develop/README.md This snippet demonstrates how to configure a `Blockchain` instance to interact with a real TON network using `RemoteBlockchainStorage`. It imports necessary modules from `@ton/ton`, `@ton/sandbox`, and `@orbs-network/ton-access` to establish a connection to the mainnet endpoint. When this `Blockchain` instance encounters an unknown contract, its state will be pulled directly from the specified real network, enabling testing against live contract data. ```typescript import { TonClient4 } from '@ton/ton' import { Blockchain, RemoteBlockchainStorage, wrapTonClient4ForRemote } from '@ton/sandbox' import { getHttpV4Endpoint } from '@orbs-network/ton-access' const blockchain = await Blockchain.create({ storage: new RemoteBlockchainStorage(wrapTonClient4ForRemote(new TonClient4({ endpoint: await getHttpV4Endpoint({ network: 'mainnet' }) }))) }) ``` -------------------------------- ### Running TON Sandbox Benchmarks to Collect New Snapshots (Bash) Source: https://github.com/ton-org/sandbox/blob/develop/README.md These commands execute Jest tests or Blueprint snapshot generation to collect and save new contract execution metrics. The `BENCH_NEW` environment variable or `--label` flag ensures a new snapshot is created in the specified output directory. ```Bash BENCH_NEW="some" npx jest # or npx blueprint snapshot --label "some" ``` -------------------------------- ### Collecting and Reporting Metrics with @ton/sandbox in TypeScript Source: https://github.com/ton-org/sandbox/blob/develop/docs/collect-metric-api.md This snippet demonstrates how to initialize a blockchain, create wallets, define contract ABIs using `ContractDatabase`, collect execution metrics using `createMetricStore` and `makeSnapshotMetric` for multiple snapshots, and generate a gas report using `makeGasReport` and `gasReportTable`. It illustrates the process of capturing metrics before and after specific transactions and resetting the metric store for subsequent measurements. ```TypeScript import { beginCell, toNano } from '@ton/core'; import { Blockchain, createMetricStore, makeSnapshotMetric, ContractDatabase, defaultColor, makeGasReport, gasReportTable, SnapshotMetric, resetMetricStore, } from '@ton/sandbox'; async function main() { const blockchain = await Blockchain.create(); const [alice, bob] = await blockchain.createWallets(2); // describe knowledge contracts const contractDatabase = ContractDatabase.from({ '0xd992502b94ea96e7b34e5d62ffb0c6fc73d78b3e61f11f0848fb3a1eb1afc912': 'TreasuryContract', TreasuryContract: { name: 'TreasuryContract', types: [ { name: 'ping', header: 0x70696e67, fields: [] }, { name: 'pong', header: 0x706f6e67, fields: [] }, ], receivers: [ { receiver: 'internal', message: { kind: 'typed', type: 'ping' } }, { receiver: 'internal', message: { kind: 'typed', type: 'pong' } }, ], }, }); // initialize metric store let store = createMetricStore(); const list: SnapshotMetric[] = []; // first snapshot await alice.send({ to: bob.address, value: toNano(1), body: beginCell().storeUint(0x70696e67, 32).endCell(), // "ping" }); await bob.send({ to: alice.address, value: toNano(1), body: beginCell().storeUint(0x706f6e67, 32).endCell(), // "pong" }); list.push(makeSnapshotMetric(store, { contractDatabase, label: 'first' })); // second snapshot resetMetricStore(); await alice.send({ to: bob.address, value: toNano(1), body: beginCell().storeUint(0x70696e67, 32).endCell(), // "ping" }); await bob.send({ to: alice.address, value: toNano(1), body: beginCell().storeUint(0x706f6e67, 32).endCell(), // "pong" }); list.push(makeSnapshotMetric(store, { contractDatabase })); // make report const delta = makeGasReport(list); console.log(JSON.stringify(contractDatabase.data, null, 2)); console.log(gasReportTable(delta, defaultColor)); } main().catch((error) => { console.log(error.message); }); ``` -------------------------------- ### Running TON Sandbox Benchmarks to Compare with Previous Snapshots (Bash) Source: https://github.com/ton-org/sandbox/blob/develop/README.md These commands execute Jest tests or Blueprint test runs with the `BENCH_DIFF=true` environment variable or `--gas-report` flag to compare current contract execution metrics against a previously saved snapshot. This is useful for regression checks and performance analysis. ```Bash BENCH_DIFF=true npx jest # or npx blueprint test --gas-report ``` -------------------------------- ### Committing and Pushing Changes to Fork (Git) Source: https://github.com/ton-org/sandbox/blob/develop/CONTRIBUTING.md This sequence of commands stages changes in 'SomeFile.js', commits them with a descriptive message linking to an issue, and then pushes the committed changes to the contributor's fork on the specified branch. This makes the changes available for a pull request. ```bash git add SomeFile.js git commit "fix: issue #123" git push origin fix/some-bug-#123 ``` -------------------------------- ### Adding First User to Shares (TypeScript) Source: https://github.com/ton-org/sandbox/blob/develop/docs/testing-key-points.md This test adds a `firstUser` to the distributor contract's shares dictionary. It sends an `addUser` message from the owner, verifies the transaction's success, and then asserts that the `firstUser`'s address is present in the contract's shares dictionary. ```typescript it('should add firstUser', async () => { const result = await distributor.sendAddUser(owner.getSender(), { value: toNano('0.05'), userAddress: firstUser.address, }); expect(result.transactions).toHaveTransaction({ from: owner.address, on: distributor.address, success: true, }); const shares = await distributor.getShares(); expect(shares.keys()[0]).toEqualAddress(firstUser.address); }); ``` -------------------------------- ### Configuring Jest for TON Sandbox Benchmarking (TypeScript) Source: https://github.com/ton-org/sandbox/blob/develop/README.md This configuration snippet for `jest.config.ts` integrates `@ton/sandbox/jest-environment` and `@ton/sandbox/jest-reporter` to enable automatic metric collection and snapshot reporting for smart contract tests. It defines output directories, contract database paths, report names, comparison depth, and allows excluding specific contracts from snapshots. ```TypeScript import type { Config } from 'jest'; const config: Config = { preset: 'ts-jest', testEnvironment: '@ton/sandbox/jest-environment', globalSetup: './jest.setup.ts', testPathIgnorePatterns: ['/node_modules/', '/dist/'], reporters: [ 'default', ['@ton/sandbox/jest-reporter', { // options snapshotDir: '.snapshot', // output folder for benchmark reports, default: '.snapshot' contractDatabase: 'contract.abi.json', // path or json a map of known contracts, see Collect metric API, default: 'contract.abi.json' reportName: 'gas-report', // report name, default: 'gas-report' depthCompare: 2, // comparison depth, default: 2 removeRawResult: true, // remove raw metric file, default: true contractExcludes: [ // exclude specific contracts from snapshot, default: [] 'TreasuryContract', ], }], ], }; export default config; ``` -------------------------------- ### Adding Second User to Shares (TypeScript) Source: https://github.com/ton-org/sandbox/blob/develop/docs/testing-key-points.md This test adds a `secondUser` to the distributor contract's shares dictionary. It sends an `addUser` message from the owner, verifies the transaction's success, and then asserts that the `secondUser`'s address is present in the contract's shares dictionary using `some` for verification. ```typescript it('should add secondUser', async () => { const result = await distributor.sendAddUser(owner.getSender(), { value: toNano('0.05'), userAddress: secondUser.address }); expect(result.transactions).toHaveTransaction({ from: owner.address, on: distributor.address, success: true }); const shares = await distributor.getShares(); expect( shares.keys().some((addr) => secondUser.address.equals(addr)) ).toBeTruthy(); }); ``` -------------------------------- ### Testing NFT Purchase Transactions with TON Sandbox Source: https://github.com/ton-org/sandbox/blob/develop/README.md This snippet demonstrates how to simulate an NFT purchase using the TON Sandbox. It sends a transaction from a buyer to a sale contract and then asserts that the expected transactions (e.g., fee transfers to marketplace and collection) occurred within the `buyResult.transactions` array using `toHaveTransaction` from `jest`. ```TypeScript const buyResult = await buyer.send({ to: sale.address, value: price + toNano('1'), sendMode: SendMode.PAY_GAS_SEPARATELY, }) expect(buyResult.transactions).toHaveTransaction({ from: sale.address, to: marketplace.address, value: fee, }) expect(buyResult.transactions).toHaveTransaction({ from: sale.address, to: collection.address, value: fee, }) ``` -------------------------------- ### Defining LogsVerbosity Type for TON Sandbox (TypeScript) Source: https://github.com/ton-org/sandbox/blob/develop/README.md Defines the `LogsVerbosity` and `Verbosity` types used by `Blockchain` and `SmartContract` instances in the TON Sandbox to control logging output. `LogsVerbosity` specifies whether to print logs, include blockchain logs, VM logs (with different verbosity levels), and debug logs. `Verbosity` defines the level of detail for VM logs. ```TypeScript type LogsVerbosity = { print: boolean blockchainLogs: boolean vmLogs: Verbosity debugLogs: boolean } type Verbosity = 'none' | 'vm_logs' | 'vm_logs_full' ``` -------------------------------- ### Iterating Through Transactions Step-by-Step (TypeScript) Source: https://github.com/ton-org/sandbox/blob/develop/README.md This snippet illustrates how to process transactions one by one using the `sendMessageIter` method, which returns an async iterator. This approach is beneficial for scenarios where only a subset of transactions in a long chain needs to be processed, preventing the execution of unnecessary transactions. The loop allows for custom processing of each transaction (`tx`) as it becomes available, offering fine-grained control over the execution flow. ```typescript const iter = await blockchain.sendMessageIter(testMessage) for await (const tx of iter) { // some kind of processing for tx, for example: console.log(tx) } ``` -------------------------------- ### Setting Smart Contract State Directly with setShardAccount (TypeScript) Source: https://github.com/ton-org/sandbox/blob/develop/README.md Provides the method signature for `async setShardAccount(address: Address, account: ShardAccount)`, a low-level function in the TON Sandbox. This method allows directly setting the full state of a smart contract, including its code, data, and other fields, bypassing the need for transaction execution. It's useful for testing specific contract states but requires careful use as it doesn't validate invariants. ```TypeScript async setShardAccount(address: Address, account: ShardAccount) ``` -------------------------------- ### Configuring Dedicated Gas Report for TON Sandbox Benchmarking (TypeScript) Source: https://github.com/ton-org/sandbox/blob/develop/README.md This TypeScript configuration file, `gas-report.config.ts`, extends the base Jest configuration to specifically tailor it for gas reporting. It sets a test name pattern, ensures the `@ton/sandbox/jest-environment` is used, and customizes the `jest-reporter` options for contract database and exclusions, allowing for focused metric collection. ```TypeScript import config from './jest.config'; config.testNamePattern = '^DescribeName .* - test name$' config.testEnvironment = '@ton/sandbox/jest-environment' config.reporters = [ ['@ton/sandbox/jest-reporter', { contractDatabase: 'abi.json', contractExcludes: [ 'TreasuryContract', ], }], ] export default config; ``` -------------------------------- ### Retrieving Shares Dictionary (TypeScript) Source: https://github.com/ton-org/sandbox/blob/develop/docs/testing-key-points.md This test verifies that the `getShares` method of the `distributor` contract returns an empty shares dictionary initially. It calls the method and asserts that the length of the keys in the returned dictionary is zero, indicating no users have been added yet. ```typescript it('should get shares dict', async () => { const shares = await distributor.getShares(); expect(shares.keys().length).toEqual(0); }); ``` -------------------------------- ### Restoring Blockchain State from Snapshot (TypeScript) Source: https://github.com/ton-org/sandbox/blob/develop/README.md This snippet shows how to restore a previously saved `Blockchain` state using a snapshot. The `loadFrom()` method asynchronously applies the state contained in the `snapshot` object to the current `Blockchain` instance, reverting it to the exact state it was in when the snapshot was created. This includes all contract states, network configuration, and internal parameters. ```typescript await blockchain.loadFrom(snapshot) ``` -------------------------------- ### Testing Contract Execution Success in TON Sandbox Source: https://github.com/ton-org/sandbox/blob/develop/README.md This test snippet demonstrates how to perform an action on a TON smart contract, capture the transaction result, and assert its success using `@ton/test-utils`. It also shows how to print transaction fees for debugging purposes. ```TypeScript it('should execute with success', async () => { const res = await main.sendMessage(sender.getSender(), toNano('0.05')); expect(res.transactions).toHaveTransaction({ from: main.address, success: true }); printTransactionFees(res.transactions); }); ``` -------------------------------- ### Creating a New Feature or Bugfix Branch (Git) Source: https://github.com/ton-org/sandbox/blob/develop/CONTRIBUTING.md This command creates and switches to a new Git branch, typically named following a convention like 'fix/some-bug-#123' for bug fixes or 'feat/some-feat' for new features. The issue number postfix helps link the branch to a specific issue. ```bash git checkout -b fix/some-bug-#123 ``` -------------------------------- ### Deploying Distributor Smart Contract (TypeScript) Source: https://github.com/ton-org/sandbox/blob/develop/docs/testing-key-points.md This test verifies the successful deployment of the `distributor` smart contract. It sends a deploy message from the `owner` and asserts that a successful deployment transaction is recorded, originating from the owner's address and targeting the distributor's address. ```typescript it('should deploy', async () => { const result = await distributor.sendDeploy(owner.getSender(), toNano('0.05')); expect(result.transactions).toHaveTransaction({ from: owner.address, on: distributor.address, deploy: true, success: true }); }); ``` -------------------------------- ### Configuring ABI Auto-mapping with ContractDatabase.from() in TypeScript Source: https://github.com/ton-org/sandbox/blob/develop/docs/collect-metric-api.md This snippet demonstrates how to configure automatic resolution of method and contract names using `ContractDatabase.from()`. It maps `CodeHash` or `ContractName` to `ContractABI` instances, allowing for aliases. This configuration is passed to `makeSnapshotMetric` for benchmarking purposes. ```TypeScript makeSnapshotMetric('label', store, { contractDatabase: ContractDatabase.from({ '0xCodeHashv': {...ContractABI}, // map CodeHash and ABI_1 'ContractName': {...ContractABI}, // map ContractName and ABI_2 '0xCodeHashN1': '0xCodeHash', // aliase for ABI_1 '0xCodeHashN2': 'ContractName', // aliase for ABI_2 }) }); ``` -------------------------------- ### Testing Money Distribution to 255 Users in TON TypeScript Source: https://github.com/ton-org/sandbox/blob/develop/docs/testing-key-points.md This test case verifies the contract's ability to successfully distribute money to 255 users without exceeding the 255 out-action limit, which would cause the action phase to fail. It utilizes `printTransactionFees` for debugging transaction costs and `filterTransactions` to confirm the exact number of transfer transactions. ```typescript it('should share money to 255 users', async () => { const result = await distributor.sendShareCoins(owner.getSender(), { value: toNano('1000') }); expect(result.transactions).toHaveTransaction({ from: owner.address, on: distributor.address, success: true }); printTransactionFees(result.transactions); const transferTransaction = filterTransactions(result.transactions, { op: 0x0 }); expect(transferTransaction.length).toEqual(255); }); ``` -------------------------------- ### Calculating and Asserting Storage Fees in TON Sandbox Source: https://github.com/ton-org/sandbox/blob/develop/README.md This test snippet illustrates how to measure and verify storage fees accrued over time in the TON Sandbox. It manipulates the blockchain's current time (`blockchain.now`) to simulate a year's passage and then sends messages to a contract (`main`) to observe and assert that the `storageFeesCollected` for a specific transaction remain below a certain threshold (1 TON). ```TypeScript it('should storage fees cost less than 1 TON', async () => { const time1 = Math.floor(Date.now() / 1000); // current local unix time const time2 = time1 + 365 * 24 * 60 * 60; // offset for a year blockchain.now = time1; // set current time const res1 = await main.sendMessage(sender.getSender(), toNano('0.05')); // preview of fees printTransactionFees(res1.transactions); blockchain.now = time2; // set current time const res2 = await main.sendMessage(sender.getSender(), toNano('0.05')); // preview of fees printTransactionFees(res2.transactions); const tx2 = res2.transactions[1]; // extract the transaction that executed in a year if (tx2.description.type !== 'generic') { throw new Error('Generic transaction expected'); } // Check that the storagePhase fees are less than 1 TON over the course of a year expect(tx2.description.storagePhase?.storageFeesCollected).toBeLessThanOrEqual(toNano('1')); }); ``` -------------------------------- ### Printing Transaction Fees in TON Blockchain (TypeScript) Source: https://github.com/ton-org/sandbox/blob/develop/docs/tact-testing-examples.md This snippet demonstrates how to send a transaction and then use the 'printTransactionFees' utility function to output a detailed breakdown of all transaction fees involved in the transaction chain. This is useful for optimizing contract performance by providing visibility into fee consumption. ```TypeScript it('should be executed and print fees', async() => { const launcher = await blockchain.treasury('fireworks'); const launchResult = await fireworks.send( launcher.getSender(), { value: toNano('1'), }, { $$type: 'Launch', } ); console.log(printTransactionFees(launchResult.transactions)); }); ``` -------------------------------- ### Testing Transaction Success for Tact Contract (TypeScript) Source: https://github.com/ton-org/sandbox/blob/develop/docs/tact-testing-examples.md This test verifies that a transaction to launch fireworks is successful. It sends 1 TON with a 'Launch' message to the contract and asserts that the transaction's `from`, `to`, and `success` fields are as expected using the `toHaveTransaction` matcher. ```TypeScript it('should launch fireworks', async () => { const launcher = await blockchain.treasury('fireworks'); console.log('launcher = ', launcher.address); console.log('Fireworks = ', fireworks.address); const launchResult = await fireworks.send( launcher.getSender(), { value: toNano('1'), }, { $$type: 'Launch', } ); expect(launchResult.transactions).toHaveTransaction({ from: launcher.address, to: fireworks.address, success: true, }); }); ``` -------------------------------- ### Sending Internal Messages with NftItem Contract in TypeScript Source: https://github.com/ton-org/sandbox/blob/develop/README.md Illustrates how to implement a `send` method (`sendTransfer`) within a contract wrapper (`NftItem`) to send internal messages. It uses `provider.internal` to construct and send a transfer message, demonstrating how `ContractProvider` is automatically supplied. ```TypeScript import { Address, beginCell, Cell, Contract, ContractProvider, Sender, toNano, Builder } from "@ton/core"; class NftItem implements Contract { async sendTransfer(provider: ContractProvider, via: Sender, params: { value?: bigint to: Address responseTo?: Address forwardAmount?: bigint forwardBody?: Cell | Builder }) { await provider.internal(via, { value: params.value ?? toNano('0.05'), body: beginCell() .storeUint(0x5fcc3d14, 32) // op .storeUint(0, 64) // query id .storeAddress(params.to) .storeAddress(params.responseTo) .storeBit(false) // custom payload .storeCoins(params.forwardAmount ?? 0n) .storeMaybeRef(params.forwardBody) .endCell() }) } } ``` -------------------------------- ### Sharing Coins to Multiple Users (TypeScript) Source: https://github.com/ton-org/sandbox/blob/develop/docs/testing-key-points.md This test verifies the distribution of coins to multiple users. It sends a `shareCoins` message, asserts that the transaction is successful with two outgoing messages, and confirms that both `firstUser` and `secondUser` receive transactions with equal values from the distributor. ```typescript it('should share coins to 2 users', async () => { const result = await distributor.sendShareCoins(owner.getSender(), { value: toNano('10') }); expect(result.transactions).toHaveTransaction({ from: owner.address, on: distributor.address, success: true, outMessagesCount: 2 }); expect(result.transactions).toHaveTransaction({ from: distributor.address, on: firstUser.address, op: 0x0, success: true }); expect(result.transactions).toHaveTransaction({ from: distributor.address, on: secondUser.address, op: 0x0, success: true }); const firstUserTransaction = findTransactionRequired(result.transactions, { on: firstUser.address }); const secondUserTransaction = findTransactionRequired(result.transactions, { on: secondUser.address }); expect(flattenTransaction(firstUserTransaction).value).toEqual(flattenTransaction(secondUserTransaction).value); }); ``` -------------------------------- ### Manually Updating Library Cells in TON Sandbox (TypeScript) Source: https://github.com/ton-org/sandbox/blob/develop/README.md Demonstrates how to manually update library cells in the TON Sandbox. Due to emulation limitations, `SETLIBCODE` and `CHANGELIB` opcodes do not automatically update library cells, requiring direct manipulation of the `blockchain.libs` property. This snippet compiles a contract, creates a dictionary of library cells, and then sets it on the blockchain instance. ```TypeScript const blockchain = await Blockchain.create(); const code = await compile('Contract'); // consist of a hash of a lib cell and its representation const libsDict = Dictionary.empty(Dictionary.Keys.Buffer(32), Dictionary.Values.Cell()); libsDict.set(code.hash(), code); // manualy set libs blockchain.libs = beginCell().storeDictDirect(libsDict).endCell(); ``` -------------------------------- ### Retrieving Contract Owner (TypeScript) Source: https://github.com/ton-org/sandbox/blob/develop/docs/testing-key-points.md This test checks if the `getOwner` method of the `distributor` contract correctly returns the owner's address. It calls the method and then uses `toEqualAddress` to compare the returned address with the expected owner's address. ```typescript it('should get owner', async () => { const ownerFromContract = await distributor.getOwner(); expect(ownerFromContract).toEqualAddress(owner.address); }); ``` -------------------------------- ### Sharing Coins to Single User (TypeScript) Source: https://github.com/ton-org/sandbox/blob/develop/docs/testing-key-points.md This test verifies the functionality of sharing coins to a single user. It sends a `shareCoins` message from the owner, asserting that the transaction is successful and results in one outgoing message to the `firstUser` with a specific operation code. ```typescript it('should share coins to one user', async () => { const result = await distributor.sendShareCoins(owner.getSender(), { value: toNano('10'), }); expect(result.transactions).toHaveTransaction({ from: owner.address, on: distributor.address, outMessagesCount: 1, success: true }); expect(result.transactions).toHaveTransaction({ from: distributor.address, on: firstUser.address, op: 0x0, success: true }); }); ``` -------------------------------- ### Setting Global Log Verbosity in TON Sandbox (TypeScript) Source: https://github.com/ton-org/sandbox/blob/develop/README.md Demonstrates how to set the global logging verbosity for the `Blockchain` instance using the `blockchain.verbosity` setter. Unlike per-address overrides, this method requires specifying all properties of the `LogsVerbosity` type, affecting all contracts unless explicitly overridden. ```TypeScript blockchain.verbosity = { blockchainLogs: true, vmLogs: 'none', debugLogs: false, } ``` -------------------------------- ### FunC Owner Check Function with Impure Specifier Source: https://github.com/ton-org/sandbox/blob/develop/docs/testing-key-points.md This FunC function `throw_unless_owner` checks if the provided address matches the contract's stored owner. The `impure` specifier is crucial because the function throws an exception; without it, the compiler might optimize away the call, leading to potential security vulnerabilities. ```func () throw_unless_owner(slice address) impure inline { throw_unless(err::must_be_owner, equal_slice_bits(address, storage::owner)); } ``` -------------------------------- ### Testing Contract Destruction After Launch (TypeScript) Source: https://github.com/ton-org/sandbox/blob/develop/docs/tact-testing-examples.md This test checks if the Tact contract is destroyed after a successful 'Launch' transaction. It sends a 'Launch' message and then asserts the `endStatus` as 'non-existing' and `destroyed` as `true` using the `toHaveTransaction` matcher. ```TypeScript it('should destroy after launching', async () => { const launcher = await blockchain.treasury('fireworks'); const launchResult = await fireworks.send( launcher.getSender(), { value: toNano('1'), }, { $$type: 'Launch', } ); expect(launchResult.transactions).toHaveTransaction({ from: launcher.address, to: fireworks.address, success: true, endStatus: 'non-existing', destroyed: true }); }); ``` -------------------------------- ### Testing Message Operation Code for Tact Contract (TypeScript) Source: https://github.com/ton-org/sandbox/blob/develop/docs/tact-testing-examples.md This test verifies the operation code (op code) of both incoming and outgoing messages. It asserts that the 'Launch' message has the expected op code `0xa911b47f` and the response message from the contract has a comment op code `0`. ```TypeScript it('should be correct Launch op code for the launching', async () => { const launcher = await blockchain.treasury('fireworks'); const launchResult = await fireworks.send( launcher.getSender(), { value: toNano('1'), }, { $$type: 'Launch', } ); expect(launchResult.transactions).toHaveTransaction({ from: launcher.address, to: fireworks.address, success: true, op: 0xa911b47f // 'Launch' op code }); expect(launchResult.transactions).toHaveTransaction({ from: fireworks.address, to: launcher.address, success: true, op: 0 // 0x00000000 - comment op code }); }); ``` -------------------------------- ### Verifying Multi-Message Payloads with Comments in TON (TypeScript) Source: https://github.com/ton-org/sandbox/blob/develop/docs/tact-testing-examples.md This test ensures that the 'fireworks' contract correctly sends multiple messages, each containing a specific comment payload. It sends a 'Launch' message and then asserts the presence of four distinct outgoing transactions, each with a 'body' containing a 'Cell' built with 'beginCell().storeUint(0,32).storeStringTail(...)'. ```typescript it('fireworks contract should send msgs with comments', async() => { const launcher = await blockchain.treasury('fireworks'); const launchResult = await fireworks.send( launcher.getSender(), { value: toNano('1'), }, { $$type: 'Launch', } ); expect(launchResult.transactions).toHaveTransaction({ from: fireworks.address, to: launcher.address, success: true, body: beginCell().storeUint(0,32).storeStringTail("send mode = 0").endCell() // 0x00000000 comment opcode and encoded comment }); expect(launchResult.transactions).toHaveTransaction({ from: fireworks.address, to: launcher.address, success: true, body: beginCell().storeUint(0,32).storeStringTail("send mode = 1").endCell() }); expect(launchResult.transactions).toHaveTransaction({ from: fireworks.address, to: launcher.address, success: true, body: beginCell().storeUint(0,32).storeStringTail("send mode = 2").endCell() }); expect(launchResult.transactions).toHaveTransaction({ from: fireworks.address, to: launcher.address, success: true, body: beginCell().storeUint(0,32).storeStringTail("send mode = 128 + 32").endCell() }); }) ``` -------------------------------- ### Testing Maximum User Addition Limit in TON TypeScript Source: https://github.com/ton-org/sandbox/blob/develop/docs/testing-key-points.md This set of tests verifies the contract's behavior when approaching and exceeding the 255 out-action limit. The first test successfully adds 255 users, while the second test attempts to add a 256th user, expecting it to fail with `ExitCode.SHARES_SIZE_EXCEEDED_LIMIT`, confirming the contract's adherence to the action phase limit. ```typescript it('should add 255 users', async () => { for (let i = 0; i < 255; ++i) { const userAddress = randomAddress(); const result = await distributor.sendAddUser(owner.getSender(), { value: toNano('0.5'), userAddress, }); expect(result.transactions).toHaveTransaction({ from: owner.address, on: distributor.address, success: true }); } }); it('should not add one more user', async () => { const userAddress = randomAddress(); const result = await distributor.sendAddUser(owner.getSender(), { value: toNano('0.5'), userAddress, }); expect(result.transactions).toHaveTransaction({ from: owner.address, on: distributor.address, success: false, exitCode: ExitCode.SHARES_SIZE_EXCEEDED_LIMIT }); }); ``` -------------------------------- ### Testing Unauthorized User Addition in TON TypeScript Source: https://github.com/ton-org/sandbox/blob/develop/docs/testing-key-points.md This test case verifies that only the contract owner can successfully add a user. It attempts to call the `sendAddUser` function from a non-owner address and asserts that the transaction fails with `ExitCode.MUST_BE_OWNER`, ensuring proper access control mechanisms are in place. ```typescript it('should not add user as not owner', async () => { const notOwner = await blockchain.treasury(`not-owner`); const result = await distributor.sendAddUser(notOwner.getSender(), { value: toNano('0.5'), userAddress: randomAddress(), }); expect(result.transactions).toHaveTransaction({ from: notOwner.address, on: distributor.address, success: false, exitCode: ExitCode.MUST_BE_OWNER, }); }); ``` -------------------------------- ### Overriding Log Verbosity for a Specific Contract in TON Sandbox (TypeScript) Source: https://github.com/ton-org/sandbox/blob/develop/README.md Shows how to override the logging verbosity for a specific smart contract address using `blockchain.setVerbosityForAddress`. This allows granular control over which logs (e.g., blockchain logs, VM logs) are printed for a particular contract, while other settings like `debugLogs` might still inherit from the global `Blockchain` instance. ```TypeScript await blockchain.setVerbosityForAddress(targetAddress, { blockchainLogs: true, vmLogs: 'vm_logs', }) ``` -------------------------------- ### Defining SnapshotMetric Type in TypeScript Source: https://github.com/ton-org/sandbox/blob/develop/docs/collect-metric-api.md This type definition outlines the structure of a `SnapshotMetric` object, which encapsulates a collection of unique `Metric` objects along with a user-defined `label` and a `createdAt` timestamp. It serves as a comprehensive record of collected contract execution data at a specific point in time. ```TypeScript type SnapshotMetric = { label: string; createdAt: Date; items: Metric[]; } ``` -------------------------------- ### Defining Metric Type for Contract Execution Data in TypeScript Source: https://github.com/ton-org/sandbox/blob/develop/docs/collect-metric-api.md This type definition details the structure of a `Metric` object, capturing granular data about individual contract executions. It includes information such as the contract address, code hash, state usage (cells and bits for code and data), method names, receiver types, opCode, and detailed information from transaction phases (compute and action), as well as message sizes for inbound and outbound messages. ```TypeScript type Metric = { // the name of the current test (if available in Jest context) testName?: string // address of contract in user friendly format address: string // hex-formatted hash of contract code codeHash?: `0x${string}` // total cells and bits usage of the contract's code and data state: { code: { cells: number bits: number } data: { cells: number bits: number } } contractName?: string methodName?: string receiver?: 'internal' | 'external-in' | 'external-out' opCode: `0x${string}` // information from transaction phases execute: { compute: { type: string success?: boolean gasUsed?: number exitCode?: number vmSteps?: number }; action?: { success: boolean totalActions: number skippedActions: number resultCode: number totalFwdFees?: number totalActionFees: number totalMessageSize: { cells: number bits: number } } } // total cells and bits usage of inbound and outbound messages message: { in: { cells: number bits: number } out: { cells: number bits: number } } } ``` -------------------------------- ### Excluding Contracts from Metric Snapshots in TypeScript Source: https://github.com/ton-org/sandbox/blob/develop/docs/collect-metric-api.md This snippet illustrates how to use the `contractExcludes` option within the `makeSnapshotMetric` function. By providing an array of contract names, users can prevent specific contracts from being included in the generated metric snapshot, allowing for more focused analysis on relevant contract interactions. ```TypeScript makeSnapshotMetric('label', store, { contractExcludes: [ 'ContractName1', 'ContractName2', ], }); ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.