import { Address, Cell, Message, ContractProvider, Contract, Sender, ShardAccount, TupleItem, ExternalAddress, StateInit, OpenedContract } from '@ton/core'; import { IExecutor, Executor, TickOrTock, PrevBlocksInfo } from '../executor/Executor'; import { BlockchainStorage } from './BlockchainStorage'; import { Event } from '../event/Event'; import { SandboxContractProvider } from './BlockchainContractProvider'; import { TreasuryContract } from '../treasury/Treasury'; import { GetMethodParams, GetMethodResult, LogsVerbosity, MessageParams, SmartContract, SmartContractTransaction, Verbosity } from './SmartContract'; import { ContractsMeta } from '../meta/ContractsMeta'; import { Coverage } from '../coverage'; import { MessageQueueManager } from './MessageQueueManager'; import { AsyncLock } from '../utils/AsyncLock'; import { BlockchainSnapshot } from './BlockchainSnapshot'; import { IUIConnector } from '../ui/connection/UIConnector'; import { WebSocketConnectionOptions } from '../ui/connection/websocket/types'; import { IUIManager } from '../ui/UIManager'; export type ExternalOutInfo = { type: 'external-out'; src: Address; dest?: ExternalAddress; createdAt: number; createdLt: bigint; }; export type ExternalOut = { info: ExternalOutInfo; init?: StateInit; body: Cell; }; export type BlockchainTransaction = SmartContractTransaction & { events: Event[]; parent?: BlockchainTransaction; children: BlockchainTransaction[]; externals: ExternalOut[]; mode?: number; }; /** * @type SendMessageResult Represents the result of sending a message. * @property {BlockchainTransaction[]} transactions Array of blockchain transactions. * @property {Event[]} events Array of blockchain events. * @property {ExternalOut[]} externals - Array of external messages. */ export type SendMessageResult = { transactions: BlockchainTransaction[]; events: Event[]; externals: ExternalOut[]; }; type ExtendsContractProvider = T extends ContractProvider ? true : T extends SandboxContractProvider ? true : false; export declare const SANDBOX_CONTRACT_SYMBOL: unique symbol; /** * @type SandboxContract Represents a sandbox contract. * @template F Type parameter representing the original contract object. */ export type SandboxContract = { [P in keyof F]: P extends `${'get' | 'is'}${string}` ? F[P] extends (x: infer CP, ...args: infer P) => infer R ? ExtendsContractProvider extends true ? (...args: P) => R : never : never : P extends `send${string}` ? F[P] extends (x: infer CP, ...args: infer P) => infer R ? ExtendsContractProvider extends true ? (...args: P) => Promise ? PR : R; }> : never : never : F[P]; }; /** * Provide way to check if contract is in sandbox environment. * @param contract Any open contract * @throws Error if contract not a sandbox contract */ export declare function toSandboxContract(contract: OpenedContract): SandboxContract; export type PendingMessage = (({ type: 'message'; callStack?: string; mode?: number; } & Message) | { type: 'ticktock'; which: TickOrTock; on: Address; }) & { parentTransaction?: BlockchainTransaction; }; /** * @type TreasuryParams Parameters for configuring a treasury contract. * @property {number} workchain The workchain ID of the treasury. * @property {boolean} predeploy If set the treasury will be deployed on the moment of creation. * @property {bigint} balance Initial balance of the treasury. If omitted 1_000_000 is used. * @property {boolean} resetBalanceIfZero If set and treasury balance is zero on moment of calling method it reset balance to {@link balance}. */ export type TreasuryParams = Partial<{ workchain: number; predeploy: boolean; balance: bigint; resetBalanceIfZero: boolean; }>; export type BlockchainConfig = Cell | 'default' | 'slim'; export type SendMessageIterParams = MessageParams & { allowParallel?: boolean; }; export type UIOptions = { enabled?: boolean; connector?: IUIConnector; } & WebSocketConnectionOptions; export declare class Blockchain { protected lock: AsyncLock; protected storage: BlockchainStorage; protected networkConfig: string; protected currentLt: bigint; protected currentTime?: number; protected logsVerbosity: LogsVerbosity; protected globalLibs?: Cell; protected contractFetches: Map>; protected nextCreateWalletIndex: number; protected shouldRecordStorage: boolean; protected meta?: ContractsMeta; protected prevBlocksInfo?: PrevBlocksInfo; protected randomSeed?: Buffer; protected shouldDebug: boolean; protected autoDeployLibs: boolean; protected transactions: BlockchainTransaction[]; protected defaultQueueManager: MessageQueueManager; protected uiManager: IUIManager; protected collectCoverage: boolean; protected readonly coverageTransactions: BlockchainTransaction[][]; protected readonly coverageGetMethodResults: GetMethodResult[]; readonly executor: IExecutor; protected debuggerExecutor?: Executor; getDebuggerExecutor(): Promise; /** * Saves snapshot of current blockchain. * @example * const snapshot = blockchain.snapshot(); * // some operations * await blockchain.loadFrom(snapshot); // restores blockchain state */ snapshot(): BlockchainSnapshot; /** * Restores blockchain state from snapshot. * Usage provided in {@link Blockchain#snapshot}. * * @param snapshot Snapshot of blockchain */ loadFrom(snapshot: BlockchainSnapshot): Promise; get recordStorage(): boolean; /** * If set to `true`, [BlockchainTransaction]{@link BlockchainTransaction} will have `oldStorage` and `newStorage` fields. * * Note that enabling this flag will disable a certain optimization, which will slow down contract emulation * * @param v */ set recordStorage(v: boolean); get autoDeployLibraries(): boolean; set autoDeployLibraries(value: boolean); get debug(): boolean; set debug(value: boolean); /** * @returns Current time in blockchain */ get now(): number | undefined; /** * Updates Current time in blockchain. * @param now UNIX time to set */ set now(now: number | undefined); /** * @returns Current logical time in blockchain */ get lt(): bigint; protected constructor(opts: { executor: IExecutor; config?: BlockchainConfig; storage: BlockchainStorage; meta?: ContractsMeta; autoDeployLibs?: boolean; uiOptions?: UIOptions; }); protected createUiManager(opts?: UIOptions): IUIManager; protected createQueueManager(): MessageQueueManager; /** * @returns Config used in blockchain. */ get config(): Cell; /** * @returns Config used in blockchain in base64 format. */ get configBase64(): string; /** * @returns Current PrevBlocksInfo */ get prevBlocks(): PrevBlocksInfo | undefined; /** * Sets PrevBlocksInfo. * @param value PrevBlocksInfo to set */ set prevBlocks(value: PrevBlocksInfo | undefined); /** * @returns The current random seed */ get random(): Buffer | undefined; /** * Sets the random seed * @param value A Buffer containing the new random seed */ set random(value: Buffer | undefined); /** * Generates and sets a new random seed using secure random bytes. */ randomize(): Promise; /** * Emulates the result of sending a message to this Blockchain. Emulates the whole chain of transactions before returning the result. Each transaction increases lt by 1000000. * * @param message Message to send * @param params Optional params * @returns Result of queue processing * * @example * const result = await blockchain.sendMessage(internal({ * from: sender.address, * to: address, * value: toNano('1'), * body: beginCell().storeUint(0, 32).endCell(), * })); */ sendMessage(message: Message | Cell, params?: MessageParams): Promise; /** * Starts emulating the result of sending a message to this Blockchain (refer to {@link sendMessage}). Each iterator call emulates one transaction, so the whole chain is not emulated immediately, unlike in {@link sendMessage}. * * @param message Message to send * @param params Optional params * @param params.allowParallel - When `true`, allows many consequential executions of this method. Useful for emulating interactions based on transaction order (MITM). * When `false` (default), only one execution of transactions is allowed. * @returns Async iterable of {@link BlockchainTransaction} * * @example * const message = internal({ * from: sender.address, * to: address, * value: toNano('1'), * body: beginCell().storeUint(0, 32).endCell(), * }); * for await (const tx of await blockchain.sendMessageIter(message, { randomSeed: crypto.randomBytes(32) })) { * // process transaction * } */ sendMessageIter(message: Message | Cell, params?: SendMessageIterParams): Promise & AsyncIterable>; /** * Runs tick or tock transaction. * * @param on Address or addresses to run tick-tock * @param which Type of transaction (tick or tock) * @param [params] Params to run tick tock transaction * @returns Result of tick-tock transaction * * @example * let res = await blockchain.runTickTock(address, 'tock'); */ runTickTock(on: Address | Address[], which: TickOrTock, params?: MessageParams): Promise; /** * Runs get method on contract. * * @param address Address or addresses to run get method * @param method MethodId or method name to run * @param stack Method params * @param [params] Params to run get method * @returns Result of get method * * @example * const { stackReader } = await blockchain.runGetMethod(address, 'get_now', [], { * now: 2, * }); * const now = res.stackReader.readNumber(); */ runGetMethod(address: Address, method: number | string, stack?: TupleItem[], params?: GetMethodParams): Promise; /** * Retrieves transactions for the specified address. Transactions are ordered from newest to oldest. * * If both `lt` and `hash` are provided, the result will include transactions up to and including the one matching them. * * @param {Address} address - The address to retrieve transactions for. * @param opts - Options to fetch transactions * @param [opts.lt] - Logical time of the transaction to start from. Must be used together with `hash`. * @param [opts.hash] - Hash of the transaction to start from. Must be used together with `lt`. * @param [opts.limit] - Maximum number of transactions to return. * * @returns {Promise} Promise resolving to an array of transactions involving the given address. * * @throws {Error} If both `lt` and `hash` are provided but no matching transaction is found. * * @example * const transactions = await blockchain.getTransactions(Address.parse(...), { * lt: '1234567890', * hash: 'abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890', * limit: 10 * }); */ getTransactions(address: Address, opts?: { limit?: number; lt?: string | bigint; hash?: string | Buffer; }): Promise; protected increaseLt(): void; /** * Creates new {@link ContractProvider} for contract address. * * @param address Address to create contract provider for * @param init Initial state of contract * * @example * const contractProvider = blockchain.provider(address, init); */ provider(address: Address, init?: StateInit | null): ContractProvider; /** * Creates {@link Sender} for address. * * Note, that this sender pushes internal messages to Blockchain directly. * No value is deducted from sender address, all the values are set to defaults. Use for test purposes only. * * @example * const sender = this.sender(address); * await contract.send(sender, ...); * * @param address Address to create sender for */ sender(address: Address): Sender; protected treasuryParamsToMapKey(workchain: number, seed: string): string; /** * Creates treasury wallet contract. This wallet is used as alternative to wallet smart contract. * * @param {string} seed Initial seed for treasury. If the same seed is used to create a treasury, then these treasuries will be identical * @param {TreasuryParams} params Params for treasury creation. See {@link TreasuryParams} for more information. * * @example * const wallet = await blockchain.treasury('wallet') * await wallet.send({ * to: someAddress, * value: toNano('0.5'), * }); */ treasury(seed: string, params?: TreasuryParams): Promise>; /** * Bulk variant of {@link treasury}. * @param n Number of wallets to create * @param params Params for treasury creation. See {@link TreasuryParams} for more information. * @returns Array of opened treasury contracts * * @example * const [wallet1, wallet2, wallet3] = await blockchain.createWallets(3); */ createWallets(n: number, params?: TreasuryParams): Promise[]>; /** * Opens contract. Returns proxy that substitutes the blockchain Provider in methods starting with get and set. * * @param contract Contract to open. * @param name Name of the contract. * * @example * const contract = blockchain.openContract(new Contract(address)); */ openContract(contract: T, name?: string): SandboxContract; protected startFetchingContract(address: Address): Promise; /** * Retrieves {@link SmartContract} from {@link BlockchainStorage}. * @param address Address of contract to get */ getContract(address: Address): Promise; /** * @returns {LogsVerbosity} level */ get verbosity(): LogsVerbosity; /** * Updates logs verbosity level. * @param {LogsVerbosity} value */ set verbosity(value: LogsVerbosity); /** * Updates logs verbosity level for address. */ setVerbosityForAddress(address: Address, verbosity: Partial | Verbosity | undefined): Promise; /** * Updates blockchain config * * @param {BlockchainConfig} config - Custom config in Cell format, or predefined `default` | `slim` */ setConfig(config: BlockchainConfig): void; setShardAccount(address: Address, account: ShardAccount): Promise; /** * Retrieves global libs cell */ get libs(): Cell | undefined; /** * Update global blockchain libs. * * @param value Cell in libs format: Dictionary * * @example * const code = await compile('Contract'); * * const libsDict = Dictionary.empty(Dictionary.Keys.Buffer(32), Dictionary.Values.Cell()); * libsDict.set(code.hash(), code); * * blockchain.libs = beginCell().storeDictDirect(libsDict).endCell(); */ set libs(value: Cell | undefined); /** * Enable coverage collection. * * @param enable if false, disable coverage collection */ enableCoverage(enable?: boolean): void; /** * Returns coverage analysis for the specified contract. * Coverage is collected at the TVM assembly instruction level from all executed transactions and get method calls. * * @param contract Contract to analyze coverage for * @returns Coverage object with detailed coverage data * @throws Error if the contract has no code * @throws Error if verbose VM logs are not enabled (blockchain.verbosity.vmLogs !== "vm_logs_verbose") * * @example * // Enable coverage collection * blockchain.enableCoverage(); * * // Execute contract methods * await contract.send(sender, { value: toNano('1') }, 'increment'); * * // Get coverage analysis * const coverage = blockchain.coverage(contract); * const summary = coverage?.summary(); * console.log(`Coverage: ${summary?.coveragePercentage?.toFixed(2)}%`); * * // Generate HTML report * const htmlReport = coverage?.report("html"); * await fs.writeFile("coverage.html", htmlReport); */ coverage(contract: Contract): Coverage | undefined; protected registerTxsForCoverage(txs: BlockchainTransaction[]): void; protected registerGetMethodForCoverage(get: GetMethodResult): void; /** * Returns coverage analysis for the specified code cell. * This method allows analyzing coverage for code cells directly, with optional address filtering. * * @param code Cell containing contract code to analyze * @param address Optional contract address to filter transactions by. * If provided, only transactions from this address will be analyzed * @returns Coverage object with detailed coverage data * @throws Error if verbose VM logs are not enabled (blockchain.verbosity.vmLogs !== "vm_logs_verbose") * * @example * blockchain.enableCoverage(); * // Analyze coverage for a specific code cell * const coverage = blockchain.coverageForCell(codeCell, contractAddress); * * // Analyze coverage for code without address filtering * const allCoverage = blockchain.coverageForCell(codeCell); * * console.log(coverage?.summary()); */ coverageForCell(code: Cell, address?: Address): Coverage | undefined; /** * Creates instance of sandbox blockchain. * * @param [opts.executor] Custom contract executor. If omitted {@link Executor} is used. * @param [opts.config] Config used in blockchain. If omitted {@link defaultConfig} is used. * @param [opts.storage] Contracts storage used for blockchain. If omitted {@link LocalBlockchainStorage} is used. * @param [opts.meta] Optional contracts metadata provider. If not provided, {@link @ton/test-utils.contractsMeta} will be used to accumulate contracts metadata. * @param [opts.autoDeployLibs] Optional flag. If set to true, libraries will be collected automatically * @param [opts.uiOptions] Optional object to configure the UI connector. * @example * const blockchain = await Blockchain.create({ config: 'slim' }); * * @example Remote storage * let client = new TonClient4({ * endpoint: 'https://mainnet-v4.tonhubapi.com' * }) * * let blockchain = await Blockchain.create({ * storage: new RemoteBlockchainStorage(wrapTonClient4ForRemote(client), 34892000) * }); */ static create(opts?: { executor?: IExecutor; config?: BlockchainConfig; storage?: BlockchainStorage; meta?: ContractsMeta; autoDeployLibs?: boolean; uiOptions?: UIOptions; }): Promise; } export {};