@ton/sandbox 0.29.0 → 0.31.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,21 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [0.31.0] - 2025-05-20
9
+
10
+ ### Added
11
+
12
+ - Added methods to collect metrics of contracts
13
+ - Added `@ton/sandbox/jest-environment` and `@ton/sandbox/jest-reporter` to write metric snapshots from test run results
14
+ - Added contract method ABI auto-mapping mechanism for detailed benchmark metrics
15
+ - Added methods to generate delta reports from metrics of contracts
16
+
17
+ ## [0.30.0] - 2025-05-12
18
+
19
+ ### Changed
20
+
21
+ - Updated config
22
+
8
23
  ## [0.29.0] - 2025-04-30
9
24
 
10
25
  ### Changed
@@ -377,4 +392,4 @@ type LogsVerbosity = {
377
392
 
378
393
  ### Removed
379
394
 
380
- - Changed `blockchain.pushMessage`, `blockchain.processQueue`, `blockchain.runQueue` to be private
395
+ - Changed `blockchain.pushMessage`, `blockchain.processQueue`, `blockchain.runQueue` to be private
package/README.md CHANGED
@@ -15,6 +15,7 @@ The key difference of this package from [ton-contract-executor](https://github.c
15
15
  * [Cross contract tests](#cross-contract-tests)
16
16
  * [Testing key points](#testing-key-points)
17
17
  * [Test examples](#test-examples)
18
+ * [Benchmark contracts](#benchmark-contracts)
18
19
  * [Sandbox pitfalls](#sandbox-pitfalls)
19
20
  * [Viewing logs](#viewing-logs)
20
21
  * [Setting smart contract state directly](#setting-smart-contract-state-directly)
@@ -290,6 +291,109 @@ Learn more from examples:
290
291
  * [FunC Test Examples](https://docs.ton.org/develop/smart-contracts/examples#examples-of-tests-for-smart-contracts)
291
292
  * [Tact Test Examples](docs/tact-testing-examples.md)
292
293
 
294
+ ## Benchmark contracts
295
+
296
+ The `@ton/sandbox` package provides `@ton/sandbox/jest-environment` and `@ton/sandbox/jest-reporter` built-in support for benchmarking smart contract behavior during tests, including tracking gas usage, cell size, opcode execution, and action phases.
297
+ This is especially useful for performance analysis, gas optimization, and regression checks on contract logic.
298
+
299
+ > ℹ️ See also: [Collect metric API](docs/collect-metric-api.md) for low-level control and manual snapshots.
300
+
301
+ ### Features
302
+
303
+ * Automatic metric collection from all transactions triggered during tests
304
+ * Snapshot reporting with contract-level filters
305
+ * Integration with [blueprint](https://github.com/ton-org/blueprint#benchmark-contracts)
306
+
307
+ ### Setup in `jest.config.ts`
308
+
309
+ ```ts
310
+ import type { Config } from 'jest';
311
+
312
+ const config: Config = {
313
+ preset: 'ts-jest',
314
+ testEnvironment: '@ton/sandbox/jest-environment',
315
+ globalSetup: './jest.setup.ts',
316
+ testPathIgnorePatterns: ['/node_modules/', '/dist/'],
317
+ reporters: [
318
+ 'default',
319
+ ['@ton/sandbox/jest-reporter', {
320
+ // options
321
+ snapshotDir: '.snapshot', // output folder for benchmark reports, default: '.snapshot'
322
+ contractDatabase: 'contract.abi.json', // path or json a map of known contracts, see Collect metric API, default: 'contract.abi.json'
323
+ reportName: 'gas-report', // report name, default: 'gas-report'
324
+ depthCompare: 2, // comparison depth, default: 2
325
+ removeRawResult: true, // remove raw metric file, default: true
326
+ contractExcludes: [ // exclude specific contracts from snapshot, default: []
327
+ 'TreasuryContract',
328
+ ],
329
+ }],
330
+ ],
331
+ };
332
+
333
+ export default config;
334
+ ```
335
+
336
+ ### How to run benchmarks
337
+
338
+ To collect and save snapshot metrics:
339
+
340
+ ```bash
341
+ BENCH_NEW="some" npx jest
342
+ # or
343
+ npx blueprint snapshot --label "some"
344
+ ```
345
+
346
+ This will:
347
+
348
+ * Run your tests
349
+ * Collect contract execution metrics
350
+ * Save a snapshot in `.snapshot/<timestamp>.json`
351
+
352
+ To compare with a previous snapshot:
353
+
354
+ ```bash
355
+ BENCH_DIFF=true npx jest
356
+ # or
357
+ npx blueprint test --gas-report
358
+ ```
359
+
360
+ ### Or setup in `gas-report.config.ts`
361
+
362
+ ```ts
363
+ import config from './jest.config';
364
+
365
+ config.testNamePattern = '^DescribeName .* - test name$'
366
+ config.testEnvironment = '@ton/sandbox/jest-environment'
367
+ config.reporters = [
368
+ ['@ton/sandbox/jest-reporter', {
369
+ contractDatabase: 'abi.json',
370
+ contractExcludes: [
371
+ 'TreasuryContract',
372
+ ],
373
+ }],
374
+ ]
375
+ export default config;
376
+ ```
377
+
378
+ **Collect metric and get report:**
379
+
380
+ ```bash
381
+ npx blueprint snapshot --label "some label" -- --config gas-report.config.ts
382
+ npx blueprint test --gas-report -- --config gas-report.config.ts
383
+ ```
384
+
385
+ ### Output structure
386
+
387
+ By default, the reporter generates:
388
+
389
+ ```
390
+ .project-root/
391
+ ├── .snapshot/
392
+ │ └── 4200000000000.json // timestamped snapshot file
393
+ ├── .sandbox-metric-raw.jsonl // raw metric log (auto-deleted by default)
394
+ ├── contract.abi.json // map of known contracts, see Collect metric API
395
+ └── gas-report.json // aggregate report in json format
396
+ ```
293
397
 
294
398
  ## Sandbox pitfalls
295
399
 
@@ -13,6 +13,7 @@ const AsyncLock_1 = require("../utils/AsyncLock");
13
13
  const message_1 = require("../utils/message");
14
14
  const slimConfig_1 = require("../config/slimConfig");
15
15
  const testTreasurySubwalletId_1 = require("../utils/testTreasurySubwalletId");
16
+ const collectMetric_1 = require("../metric/collectMetric");
16
17
  const CREATE_WALLETS_PREFIX = 'CREATE_WALLETS';
17
18
  function createWalletsSeed(idx) {
18
19
  return `${CREATE_WALLETS_PREFIX}${idx}`;
@@ -452,25 +453,25 @@ class Blockchain {
452
453
  }
453
454
  const value = target[prop];
454
455
  if (typeof prop === 'string' && typeof value === 'function') {
456
+ const ctx = {
457
+ contract,
458
+ methodName: prop,
459
+ };
455
460
  if (prop.startsWith('get')) {
456
461
  return (...args) => value.apply(target, [provider, ...args]);
457
462
  }
458
463
  else if (prop.startsWith('send')) {
459
464
  return async (...args) => {
460
- const ret = value.apply(target, [provider, ...args]);
465
+ let ret = value.apply(target, [provider, ...args]);
461
466
  if (ret instanceof Promise) {
462
- const r = await ret;
463
- return {
464
- ...await blkch.runQueue(),
465
- result: r,
466
- };
467
- }
468
- else {
469
- return {
470
- ...await blkch.runQueue(),
471
- result: ret,
472
- };
467
+ ret = await ret;
473
468
  }
469
+ const out = {
470
+ ...await blkch.runQueue(),
471
+ result: ret,
472
+ };
473
+ await (0, collectMetric_1.collectMetric)(blkch, ctx, out);
474
+ return out;
474
475
  };
475
476
  }
476
477
  }