@ton/sandbox 0.11.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.
Files changed (44) hide show
  1. package/CHANGELOG.md +221 -0
  2. package/LICENSE +21 -0
  3. package/README.md +214 -0
  4. package/dist/blockchain/Blockchain.d.ts +120 -0
  5. package/dist/blockchain/Blockchain.js +327 -0
  6. package/dist/blockchain/BlockchainContractProvider.d.ts +30 -0
  7. package/dist/blockchain/BlockchainContractProvider.js +90 -0
  8. package/dist/blockchain/BlockchainSender.d.ts +9 -0
  9. package/dist/blockchain/BlockchainSender.js +29 -0
  10. package/dist/blockchain/BlockchainStorage.d.ts +64 -0
  11. package/dist/blockchain/BlockchainStorage.js +105 -0
  12. package/dist/blockchain/SmartContract.d.ts +93 -0
  13. package/dist/blockchain/SmartContract.js +289 -0
  14. package/dist/config/defaultConfig.d.ts +2 -0
  15. package/dist/config/defaultConfig.js +5 -0
  16. package/dist/config/slimConfig.d.ts +2 -0
  17. package/dist/config/slimConfig.js +5 -0
  18. package/dist/event/Event.d.ts +19 -0
  19. package/dist/event/Event.js +46 -0
  20. package/dist/executor/Executor.d.ts +90 -0
  21. package/dist/executor/Executor.js +208 -0
  22. package/dist/executor/emulator-emscripten.js +21 -0
  23. package/dist/executor/emulator-emscripten.wasm.js +1 -0
  24. package/dist/index.d.ts +12 -0
  25. package/dist/index.js +31 -0
  26. package/dist/treasury/Treasury.d.ts +23 -0
  27. package/dist/treasury/Treasury.js +82 -0
  28. package/dist/utils/AsyncLock.d.ts +6 -0
  29. package/dist/utils/AsyncLock.js +48 -0
  30. package/dist/utils/base64.d.ts +1 -0
  31. package/dist/utils/base64.js +42 -0
  32. package/dist/utils/crc16.d.ts +2 -0
  33. package/dist/utils/crc16.js +49 -0
  34. package/dist/utils/message.d.ts +15 -0
  35. package/dist/utils/message.js +24 -0
  36. package/dist/utils/prettyLogTransaction.d.ts +3 -0
  37. package/dist/utils/prettyLogTransaction.js +25 -0
  38. package/dist/utils/printTransactionFees.d.ts +3 -0
  39. package/dist/utils/printTransactionFees.js +63 -0
  40. package/dist/utils/selector.d.ts +1 -0
  41. package/dist/utils/selector.js +19 -0
  42. package/dist/utils/testTreasurySubwalletId.d.ts +1 -0
  43. package/dist/utils/testTreasurySubwalletId.js +9 -0
  44. package/package.json +38 -0
package/CHANGELOG.md ADDED
@@ -0,0 +1,221 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [0.11.0] - 2023-05-11
9
+
10
+ ### Added
11
+
12
+ - Added the ability to emulate ticktock transactions. There are 3 ways to do that: `blockchain.runTickTock(Address | Address[], TickOrTock, MessageParams?)`, `smartContract.runTickTock(TickOrTock, MessageParams?)`, or you can change `ContractProvider` in your wrapper classes to be `SandboxContractProvider` and invoke `tickTock(TickOrTock)` on it. `TickOrTock` is a union type `'tick' | 'tock'`
13
+ - Added new verbosity levels: `'vm_logs_location'` (same as `'vm_logs'` but also display code cell hash and offset), `'vm_logs_gas'` (same as `'vm_logs_location'` but also display gas remaining), `'vm_logs_verbose'` (same as `'vm_logs_full'` but display stack values in a more verbose way)
14
+
15
+ ### Changed
16
+
17
+ - Changed emulator WASM binary
18
+
19
+ ## [0.10.0] - 2023-05-04
20
+
21
+ ### Changed
22
+
23
+ - Changed emulator WASM binary
24
+ - Changed treasury code
25
+
26
+ ### Fixed
27
+
28
+ - Fixed certain interactions between snapshots and treasuries
29
+
30
+ ## [0.9.0] - 2023-04-27
31
+
32
+ ### Added
33
+
34
+ - Added `printTransactionFees` helper for easier calculation of fees of different operations
35
+ - Added `blockchain.snapshot`, `blockchain.loadFrom`, `smartContract.snapshot`, `smartContract.loadFrom` methods to create state snapshots of the respective objects and restore from them at a later point in time. They return and accept new types, `BlockchainSnapshot` and `SmartContractSnapshot`
36
+
37
+ ## [0.8.0] - 2023-04-07
38
+
39
+ This release contains a breaking change.
40
+
41
+ ### Added
42
+
43
+ - Added `blockchain.createWallets` method which accepts a number `n` and optional `TreasuryParams`. It creates `n` treasuries and returns them as an array
44
+
45
+ ### Changed
46
+
47
+ - `RemoteBlockchainStorage` now requires a `RemoteBlockchainStorageClient` instead of `TonClient4`. There is a helper function, `wrapTonClient4ForRemote`, to wrap a `TonClient4` into `RemoteBlockchainStorageClient`. This is a breaking change
48
+ - Updated default config
49
+ - `Blockchain.create` now accepts an optional `BlockchainConfig = Cell | 'default' | 'slim'` as the config. If nothing or `'default'` is specified, the default config is used, if `'slim'` is specified, the slim config is used (it is much smaller than the default config, which improves performance), if a `Cell` is passed, then it is used as the config
50
+
51
+ ### Removed
52
+
53
+ - Removed ton as a peer dependency
54
+
55
+ ## [0.7.0] - 2023-03-27
56
+
57
+ ### Added
58
+
59
+ - Added `externals: ExternalOut[]` field to `BlockchainTransaction` and `SendMessageResult`. `ExternalOut` is a specialized type for external out messages compatible with `Message` from ton-core
60
+
61
+ ### Changed
62
+
63
+ - Get methods now throw a specialized error type `GetMethodError` when exit code is not 0
64
+ - Smart contracts now throw a specialized error type `TimeError` when trying to run a transaction at a unix timestamp that is less than the unix timestamp of the last transaction
65
+ - Get methods now return `gasUsed` and `logs` from the `ContractProvider` on opened contracts
66
+
67
+ ### Other
68
+
69
+ - Consecutive transaction emulations have been optimized
70
+
71
+ ## [0.6.1] - 2023-03-16
72
+
73
+ ### Fixed
74
+
75
+ - Fixed `blockchain.now` override for get methods in opened contracts
76
+
77
+ ## [0.6.0] - 2023-03-13
78
+
79
+ ### Added
80
+
81
+ - Added `treasury.getBalance` method
82
+ - Added `blockchain.now` getter and setter to override current unix time as seen during contract execution (both transactions and get methods). Note that this is unix timestamp, not JS timestamp, so you need to use `Math.floor(Date.now() / 1000)` instead of `Date.now()` to set current time
83
+
84
+ ### Changed
85
+
86
+ - `RemoteBlockchainStorage` constructor now accepts a second optional parameter, `blockSeqno?: number`. If passed, all accounts will be pulled from that block number instead of the latest one
87
+
88
+ ## [0.5.1] - 2023-03-02
89
+
90
+ ### Changed
91
+
92
+ - Changed ton and ton-core dev and peer dependencies to versions 13.4.1 and 0.48.0 respectively
93
+
94
+ ### Fixed
95
+
96
+ - Fixed typos in `SendMode.PAY_GAS_SEPARATLY` (missing E) from ton-core
97
+
98
+ ## [0.5.0] - 2023-02-22
99
+
100
+ This release contains multiple breaking changes.
101
+
102
+ ### Added
103
+
104
+ - Added `blockchain.libs: Cell | undefined` getter and setter for global libraries dictionary (as a `Cell`)
105
+
106
+ ### Changed
107
+
108
+ - `blockchain.treasury` now accepts an optional `TreasuryParams` argument (see below for definition) instead of the old optional `workchain?: number` argument. This is a breaking change
109
+ ```typescript
110
+ export type TreasuryParams = Partial<{
111
+ workchain: number
112
+ predeploy: boolean
113
+ balance: bigint
114
+ resetBalanceIfZero: boolean
115
+ }>
116
+ ```
117
+ - `OpenedContract` was renamed to `SandboxContract`. This is a breaking change
118
+ - `LogsVerbosity` now has a new field, `print: boolean` (defaults to `true` on the `Blockchain` instance), which controls whether to `console.log` any logs at all (both from transactions and get methods). This is a breaking change
119
+ - `smartContract.get` and `blockchain.runGetMethod` now return `GetMethodResult` (see below for definition). The differences from the previous return type are as follows:
120
+ - `logs` renamed to `vmLogs`. This is a breaking change
121
+ - `gasUsed` is now of type `bigint`. This is a breaking change
122
+ - `blockchainLogs: string` and `debugLogs: string` were added
123
+ ```typescript
124
+ export type GetMethodResult = {
125
+ stack: TupleItem[]
126
+ stackReader: TupleReader
127
+ exitCode: number
128
+ gasUsed: bigint
129
+ blockchainLogs: string
130
+ vmLogs: string
131
+ debugLogs: string
132
+ }
133
+ ```
134
+ - Properties `storage` and `messageQueue` on `Blockchain` are now protected. This is a breaking change
135
+ - All properties and methods of `Blockchain` that were private are now protected to improve extensibility. Note that any invariants expected by `Blockchain` must be upheld
136
+ - `blockchain.sendMessage` and `smartContract.receiveMessage` now accept an optional `MessageParams` argument (see below for definition). These parameters are used for every transaction in the chain in case of `blockchain.sendMessage`
137
+ ```typescript
138
+ export type MessageParams = Partial<{
139
+ now: number
140
+ randomSeed: Buffer
141
+ ignoreChksig: boolean
142
+ }>
143
+ ```
144
+ - `blockchain.runGetMethod` and `smartContract.get` now accept an optional `GetMethodParams` argument (see below for definition)
145
+ ```typescript
146
+ export type GetMethodParams = Partial<{
147
+ now: number
148
+ randomSeed: Buffer
149
+ gasLimit: bigint
150
+ }>
151
+ ```
152
+ - `SendMessageResult` now has `transactions: BlockchainTransaction[]` instead of `transactions: Transaction[]`. Definition of `BlockchainTransaction`:
153
+ ```typescript
154
+ export type BlockchainTransaction = Transaction & {
155
+ blockchainLogs: string
156
+ vmLogs: string
157
+ debugLogs: string
158
+ events: Event[]
159
+ parent?: BlockchainTransaction
160
+ children: BlockchainTransaction[]
161
+ }
162
+ ```
163
+ - `smartContract.receiveMessage` now returns `SmartContractTransaction` (see below for definition)
164
+ ```typescript
165
+ export type SmartContractTransaction = Transaction & {
166
+ blockchainLogs: string
167
+ vmLogs: string
168
+ debugLogs: string
169
+ }
170
+ ```
171
+ - Emulator WASM binary has been updated
172
+
173
+ ### Fixed
174
+
175
+ - Fixed empty message bodies in bounced messages. This fix is contained in the emulator WASM binary
176
+
177
+ ## [0.4.0] - 2023-02-09
178
+
179
+ ### Changed
180
+
181
+ - Treasuries obtained by `blockchain.treasury` calls are now initialized during this call and will no longer produce an extra transaction when first sending a message
182
+ - Transaction processing loop now prefetches contracts, which should provide a performance boost in some scenarios
183
+
184
+ ## [0.3.0] - 2023-02-05
185
+
186
+ ### Changed
187
+
188
+ - `Blockchain` and `SmartContract` now use `LogsVerbosity` (see below for definition) as the verbosity type, which allows for more control over what kinds of logs are printed. Logs from TVM debug primitives are now enabled by default, again. (You can disable them globally by setting verbosity with `debugLogs: false` on the `Blockchain` instance)
189
+
190
+ Definition of `LogsVerbosity`:
191
+ ```typescript
192
+ type LogsVerbosity = {
193
+ blockchainLogs: boolean
194
+ vmLogs: Verbosity
195
+ debugLogs: boolean
196
+ }
197
+ ```
198
+
199
+ ## [0.2.2] - 2023-02-03
200
+
201
+ ### Added
202
+
203
+ - Added `blockchain.runGetMethod(address, method, stack)` to run a get method on the specified address
204
+ - Added `blockchain.setShardAccount(address, account)` to directly set the state of smart contracts
205
+ - Added `account: ShardAccount` getter and setter to `SmartContract`
206
+ - Exported helper methods `createEmptyShardAccount`, `createShardAccount` for use with `blockchain.setShardAccount` and `smartContract.account` setter
207
+ - Added the ability to pass `Cell`s into `blockchain.sendMessage`
208
+
209
+ ### Changed
210
+
211
+ - Removed unnecessary `async` modifiers from `smartContract.receiveMessage` and `smartContract.get`
212
+ - Logs from TVM debug primitives (for example, `DUMP` and `STRDUMP` with corresponding FunC functions `~dump()` and `~strdump()`) now respect the `verbosity` parameter and will only work when it is not `none`
213
+ - Logs from TVM debug primitives are now printed using a single `console.log` call per one TVM execution to avoid cluttering the terminal during unit tests
214
+
215
+ ### Fixed
216
+
217
+ - Fixed potential race conditions between execution of different transaction chains on the same `Blockchain` instance by use of an `AsyncLock`
218
+
219
+ ### Removed
220
+
221
+ - Changed `blockchain.pushMessage`, `blockchain.processQueue`, `blockchain.runQueue` to be private
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2022 Ton Tech
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,214 @@
1
+ # Sandbox
2
+
3
+ This package allows you to emulate arbitrary TON smart contracts, send messages to them and run get methods on them as if they were deployed on a real network.
4
+
5
+ The key difference of this package from [ton-contract-executor](https://github.com/ton-community/ton-contract-executor) is the fact that the latter only emulates the compute phase of the contract - it does not know about any other phases and thus does not know anything about fees and balances (in a sense that it does not know whether a contract's balance will be enough to process all the out messages that it produces). On the other hand, this package emulates all the phases of a contract, and as a result, the emulation is much closer to what would happen in a real network.
6
+
7
+ ## Installation
8
+
9
+ Requires node 16 or higher.
10
+
11
+ ```
12
+ yarn add @ton/sandbox ton @ton/core ton-crypto
13
+ ```
14
+ or
15
+ ```
16
+ npm i @ton/sandbox ton @ton/core ton-crypto
17
+ ```
18
+
19
+ ## Usage
20
+
21
+ To use this package, you need to create an instance of the `Blockchain` class using the static method `Blockchain.create` as follows:
22
+ ```typescript
23
+ import { Blockchain } from "@ton/sandbox";
24
+
25
+ const blockchain = await Blockchain.create()
26
+ ```
27
+
28
+ After that, you can use the low level methods on Blockchain (such as sendMessage) to emulate any messages that you want, but the recommended way to use it is to write wrappers for your contract using the `Contract` interface from `ton-core`. Then you can use `blockchain.openContract` on instances of such contracts, and they will be wrapped in a Proxy that will supply a `ContractProvider` as a first argument to all its methods starting with either `get` or `send`. Also all `send` methods will get Promisified and will return results of running the blockchain message queue along with the original method's result in the `result` field.
29
+
30
+ A good example of this is the [treasury contract](/src/treasury/Treasury.ts) that is basically a built-in highload wallet meant to help you write tests for your systems of smart contracts. When `blockchain.treasury` is called, an instance of `TreasuryContract` is created and `blockchain.openContract` is called to "open" it. After that, when you call `treasury.send`, `Blockchain` automatically supplies the first `provider` argument.
31
+
32
+ For your own contracts, you can draw inspiration from the contracts in the [examples](/examples/) - all of them use the `provider.internal` method to send internal messages using the treasuries passed in from the unit test file.
33
+ Here is an excerpt of that from [NftItem.ts](/examples/contracts/NftItem.ts):
34
+ ```typescript
35
+ import { Address, beginCell, Cell, Contract, ContractProvider, Sender, toNano, Builder } from "ton-core";
36
+
37
+ class NftItem implements Contract {
38
+ async sendTransfer(provider: ContractProvider, via: Sender, params: {
39
+ value?: bigint
40
+ to: Address
41
+ responseTo?: Address
42
+ forwardAmount?: bigint
43
+ forwardBody?: Cell | Builder
44
+ }) {
45
+ await provider.internal(via, {
46
+ value: params.value ?? toNano('0.05'),
47
+ body: beginCell()
48
+ .storeUint(0x5fcc3d14, 32) // op
49
+ .storeUint(0, 64) // query id
50
+ .storeAddress(params.to)
51
+ .storeAddress(params.responseTo)
52
+ .storeBit(false) // custom payload
53
+ .storeCoins(params.forwardAmount ?? 0n)
54
+ .storeMaybeRef(params.forwardBody)
55
+ .endCell()
56
+ })
57
+ }
58
+ }
59
+ ```
60
+
61
+ When you call `nftItem.sendTransfer(treasury.getSender(), { to: recipient })` (with `nftItem` being an "opened" instance of `NftItem`), an external message to the wallet represented by `treasury` will be pushed onto the message queue, then processed, generating an internal message to the NFT contract.
62
+
63
+ Here is another excerpt that shows the way to interact with get methods from wrappers:
64
+ ```typescript
65
+ import { Contract, ContractProvider } from "ton-core";
66
+
67
+ export type NftItemData = {
68
+ inited: boolean
69
+ index: number
70
+ collection: Address | null
71
+ owner: Address | null
72
+ content: Cell | null
73
+ }
74
+
75
+ class NftItem implements Contract {
76
+ async getData(provider: ContractProvider): Promise<NftItemData> {
77
+ const { stack } = await provider.get('get_nft_data', [])
78
+ return {
79
+ inited: stack.readBoolean(),
80
+ index: stack.readNumber(),
81
+ collection: stack.readAddressOpt(),
82
+ owner: stack.readAddressOpt(),
83
+ content: stack.readCellOpt(),
84
+ }
85
+ }
86
+ }
87
+ ```
88
+
89
+ When you call `nftItem.getData()` (note that just like in the `sendTransfer` method, you don't need to supply the `provider` argument - it's done for you on "opened" instances), the `provider` will query the smart contract contained in blockchain and parse the data according to the code. Note that unlike the `send` methods, `get` methods on "opened" instances will return the original result as-is to the caller.
90
+
91
+ Notes:
92
+ - All of the methods of contracts that you want to "open" that start with `get` or `send` **NEED** to accept `provider: ContractProvider` as a first argument (even if not used) due to how the wrapper works.
93
+ - You can open any contract at any address, even if it is not yet deployed or was deployed by a "parent" opened contract. The only requirement is that the `address` field (required by the `Contract` interface) is the address of the contract that you want to open, and that `init` is present if you want to deploy using methods on the opened instance (in other cases, `init` is not necessary).
94
+ - Ideally, at most one call to **either** `provider.internal` or `provider.external` should be made within a `send` method. Otherwise, you may get hard to interpret (but generally speaking correct) results.
95
+ - No calls to `provider.external` or `provider.internal` should be made within `get` methods. Otherwise, you will get weird and wrong results in the following `send` methods of any contract.
96
+
97
+ ## Writing tests
98
+
99
+ You can install additional `@ton/test-utils` package by running `yarn add @ton/test-utils -D` or `npm i --save-dev @ton/test-utils` (with `.toHaveTransaction` for jest or `.transaction` or `.to.have.transaction` for chai matcher) to add additional helpers for ease of testing. Don't forget to import them in your unit test files though!
100
+
101
+ Here is an excerpt of how it's used in the NFT collection example mentioned above:
102
+ ```typescript
103
+ const buyResult = await buyer.send({
104
+ to: sale.address,
105
+ value: price + toNano('1'),
106
+ sendMode: SendMode.PAY_GAS_SEPARATELY,
107
+ })
108
+
109
+ expect(buyResult.transactions).toHaveTransaction({
110
+ from: sale.address,
111
+ to: marketplace.address,
112
+ value: fee,
113
+ })
114
+ expect(buyResult.transactions).toHaveTransaction({
115
+ from: sale.address,
116
+ to: collection.address,
117
+ value: fee,
118
+ })
119
+ ```
120
+ (in that example `jest` is used)
121
+
122
+ The matcher supports the following fields:
123
+ ```typescript
124
+ export type FlatTransaction = {
125
+ from?: Address
126
+ to: Address
127
+ value?: bigint
128
+ body: Cell
129
+ initData?: Cell
130
+ initCode?: Cell
131
+ deploy: boolean
132
+ lt: bigint
133
+ now: number
134
+ outMessagesCount: number
135
+ oldStatus: AccountStatus
136
+ endStatus: AccountStatus
137
+ totalFees?: bigint
138
+ aborted?: boolean
139
+ destroyed?: boolean
140
+ exitCode?: number
141
+ success?: boolean
142
+ }
143
+ ```
144
+
145
+ But you can omit those you're not interested in, and you can also pass in functions accepting those types returning booleans (`true` meaning good) to check for example number ranges, message opcodes, etc. Note however that if a field is optional (like `from?: Address`), then the function needs to accept the optional type, too.
146
+
147
+ ### Viewing logs
148
+
149
+ `Blockchain` and `SmartContract` use `LogsVerbosity` to determine what kinds of logs to print. Here is the definition:
150
+ ```typescript
151
+ type LogsVerbosity = {
152
+ print: boolean
153
+ blockchainLogs: boolean
154
+ vmLogs: Verbosity
155
+ debugLogs: boolean
156
+ }
157
+
158
+ type Verbosity = 'none' | 'vm_logs' | 'vm_logs_full'
159
+ ```
160
+
161
+ Setting verbosity on `SmartContract`s works like an override with respect to what is set on `Blockchain`.
162
+
163
+ `debugLogs` is enabled by default on the `Blockchain` instance (so every `SmartContract` that does not have `debugLogs` overridden will print debug logs), other kinds of logs are turned off.
164
+
165
+ `print` determines whether to `console.log` all the non-empty logs (if set to `false`, logs will be collected but will only be exposed in the return values of methods on `Blockchain` and `SmartContract`, and not printed to console), defaults to `true` on the `Blockchain` instance.
166
+
167
+ `'vm_logs'` prints the log of every instruction that was executed, `'vm_logs_full'` also includes code cell hashes, locations, and stack information for every instruction executed.
168
+
169
+ To override verbosity on a specific contract, use `await blockchain.setVerbosityForAddress(targetAddress, verbosity)`, for example:
170
+ ```typescript
171
+ await blockchain.setVerbosityForAddress(targetAddress, {
172
+ blockchainLogs: true,
173
+ vmLogs: 'vm_logs',
174
+ })
175
+ ```
176
+ After that, the target contract will be using `debugLogs` from the `Blockchain` instance to determine whether to print debug logs, but will always print VM logs and blockchain logs.
177
+
178
+ To set global verbosity, use the `blockchain.verbosity` setter, for example:
179
+ ```typescript
180
+ blockchain.verbosity = {
181
+ blockchainLogs: true,
182
+ vmLogs: 'none',
183
+ debugLogs: false,
184
+ }
185
+ ```
186
+ Note that unlike with `setVerbosityForAddress`, with this setter you have to specify all the values from `LogsVerbosity`.
187
+
188
+ ### Setting smart contract state directly
189
+
190
+ If you want to test some behavior on a contract if it had specific code, data, and other state fields, but do not want to execute all the required transactions for that, you can directly set the full state of the contract as it is stored in sandbox by using this method on the `Blockchain` instance:
191
+ ```
192
+ async setShardAccount(address: Address, account: ShardAccount)
193
+ ```
194
+ There are 2 helpers exported from sandbox that can help you create the `ShardAccount` from the common properties: `createEmptyShardAccount` and `createShardAccount`.
195
+
196
+ Note that this is a low-level function and does not check any invariants, such as that the address passed as the argument matches the one that is present in the `ShardAccount`, meaning it is possible to break stuff if you're not careful when using it.
197
+
198
+ ### Network/Block configuration
199
+
200
+ By default, this package will use its [stored network configuration](src/config/defaultConfig.ts) to emulate messages. However, you can set any configuration you want when creating the `Blockchain` instance by passing the configuration cell in the optional `params` argument in the `config` field.
201
+
202
+ ## Contributors
203
+
204
+ Special thanks to [@dungeon-master-666](https://github.com/dungeon-master-666) for their C++ code of the emulator.
205
+
206
+ Special thanks to [@TrueCarry](https://github.com/truecarry) for their help with performance and other suggestions.
207
+
208
+ ## License
209
+
210
+ This package is released under the [MIT License](LICENSE).
211
+
212
+ ## Donations
213
+
214
+ TON - `EQAQR1d1Q4NaE5EefwUMdrr1QvXg-8mDB0XI2-fwDBD0nYxC`
@@ -0,0 +1,120 @@
1
+ import { Address, Cell, Message, Transaction, ContractProvider, Contract, Sender, ShardAccount, TupleItem, ExternalAddress, StateInit } from "ton-core";
2
+ import { Executor, TickOrTock } from "../executor/Executor";
3
+ import { BlockchainStorage } from "./BlockchainStorage";
4
+ import { Event } from "../event/Event";
5
+ import { SandboxContractProvider } from "./BlockchainContractProvider";
6
+ import { TreasuryContract } from "../treasury/Treasury";
7
+ import { GetMethodParams, LogsVerbosity, MessageParams, SmartContract, SmartContractSnapshot, Verbosity } from "./SmartContract";
8
+ import { AsyncLock } from "../utils/AsyncLock";
9
+ export type ExternalOutInfo = {
10
+ type: 'external-out';
11
+ src: Address;
12
+ dest?: ExternalAddress;
13
+ createdAt: number;
14
+ createdLt: bigint;
15
+ };
16
+ export type ExternalOut = {
17
+ info: ExternalOutInfo;
18
+ init?: StateInit;
19
+ body: Cell;
20
+ };
21
+ export type BlockchainTransaction = Transaction & {
22
+ blockchainLogs: string;
23
+ vmLogs: string;
24
+ debugLogs: string;
25
+ events: Event[];
26
+ parent?: BlockchainTransaction;
27
+ children: BlockchainTransaction[];
28
+ externals: ExternalOut[];
29
+ };
30
+ export type SendMessageResult = {
31
+ transactions: BlockchainTransaction[];
32
+ events: Event[];
33
+ externals: ExternalOut[];
34
+ };
35
+ type ExtendsContractProvider<T> = T extends ContractProvider ? true : (T extends SandboxContractProvider ? true : false);
36
+ export type SandboxContract<F> = {
37
+ [P in keyof F]: P extends `get${string}` ? (F[P] extends (x: infer CP, ...args: infer P) => infer R ? (ExtendsContractProvider<CP> extends true ? (...args: P) => R : never) : never) : (P extends `send${string}` ? (F[P] extends (x: infer CP, ...args: infer P) => infer R ? (ExtendsContractProvider<CP> extends true ? (...args: P) => Promise<SendMessageResult & {
38
+ result: R extends Promise<infer PR> ? PR : R;
39
+ }> : never) : never) : F[P]);
40
+ };
41
+ export type PendingMessage = (({
42
+ type: 'message';
43
+ } & Message) | ({
44
+ type: 'ticktock';
45
+ which: TickOrTock;
46
+ on: Address;
47
+ })) & {
48
+ parentTransaction?: BlockchainTransaction;
49
+ };
50
+ export type TreasuryParams = Partial<{
51
+ workchain: number;
52
+ predeploy: boolean;
53
+ balance: bigint;
54
+ resetBalanceIfZero: boolean;
55
+ }>;
56
+ export type BlockchainConfig = Cell | 'default' | 'slim';
57
+ export type BlockchainSnapshot = {
58
+ contracts: SmartContractSnapshot[];
59
+ networkConfig: string;
60
+ lt: bigint;
61
+ time?: number;
62
+ verbosity: LogsVerbosity;
63
+ libs?: Cell;
64
+ nextCreateWalletIndex: number;
65
+ };
66
+ export declare class Blockchain {
67
+ protected storage: BlockchainStorage;
68
+ protected networkConfig: string;
69
+ protected currentLt: bigint;
70
+ protected currentTime?: number;
71
+ protected messageQueue: PendingMessage[];
72
+ protected logsVerbosity: LogsVerbosity;
73
+ protected globalLibs?: Cell;
74
+ protected lock: AsyncLock;
75
+ protected contractFetches: Map<string, Promise<SmartContract>>;
76
+ protected nextCreateWalletIndex: number;
77
+ readonly executor: Executor;
78
+ snapshot(): BlockchainSnapshot;
79
+ loadFrom(snapshot: BlockchainSnapshot): Promise<void>;
80
+ get now(): number | undefined;
81
+ set now(now: number | undefined);
82
+ get lt(): bigint;
83
+ protected constructor(opts: {
84
+ executor: Executor;
85
+ config?: BlockchainConfig;
86
+ storage: BlockchainStorage;
87
+ });
88
+ get config(): Cell;
89
+ get configBase64(): string;
90
+ sendMessage(message: Message | Cell, params?: MessageParams): Promise<SendMessageResult>;
91
+ runTickTock(on: Address | Address[], which: TickOrTock, params?: MessageParams): Promise<SendMessageResult>;
92
+ runGetMethod(address: Address, method: number | string, stack?: TupleItem[], params?: GetMethodParams): Promise<import("./SmartContract").GetMethodResult>;
93
+ protected pushMessage(message: Message | Cell): Promise<void>;
94
+ protected pushTickTock(on: Address, which: TickOrTock): Promise<void>;
95
+ protected runQueue(params?: MessageParams): Promise<SendMessageResult>;
96
+ protected processQueue(params?: MessageParams): Promise<BlockchainTransaction[]>;
97
+ provider(address: Address, init?: {
98
+ code: Cell;
99
+ data: Cell;
100
+ }): ContractProvider;
101
+ sender(address: Address): Sender;
102
+ protected treasuryParamsToMapKey(workchain: number, seed: string): string;
103
+ treasury(seed: string, params?: TreasuryParams): Promise<SandboxContract<TreasuryContract>>;
104
+ createWallets(n: number, params?: TreasuryParams): Promise<SandboxContract<TreasuryContract>[]>;
105
+ openContract<T extends Contract>(contract: T): SandboxContract<T>;
106
+ protected startFetchingContract(address: Address): Promise<SmartContract>;
107
+ getContract(address: Address): Promise<SmartContract>;
108
+ get verbosity(): LogsVerbosity;
109
+ set verbosity(value: LogsVerbosity);
110
+ setVerbosityForAddress(address: Address, verbosity: Partial<LogsVerbosity> | Verbosity | undefined): Promise<void>;
111
+ setConfig(config: BlockchainConfig): void;
112
+ setShardAccount(address: Address, account: ShardAccount): Promise<void>;
113
+ get libs(): Cell | undefined;
114
+ set libs(value: Cell | undefined);
115
+ static create(opts?: {
116
+ config?: BlockchainConfig;
117
+ storage?: BlockchainStorage;
118
+ }): Promise<Blockchain>;
119
+ }
120
+ export {};