diff --git a/lerna.json b/lerna.json index f08b7c7f..0b73d97a 100644 --- a/lerna.json +++ b/lerna.json @@ -3,7 +3,7 @@ "packages": [ "packages/*" ], - "version": "1.44.3", + "version": "1.44.4", "command": { "version": { "message": "Release" diff --git a/packages/cli/package-lock.json b/packages/cli/package-lock.json index 21457735..f50aafc3 100644 --- a/packages/cli/package-lock.json +++ b/packages/cli/package-lock.json @@ -1,17 +1,17 @@ { "name": "@eversdk/cli", - "version": "1.44.3", + "version": "1.44.4", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@eversdk/cli", - "version": "1.44.3", + "version": "1.44.4", "license": "Apache-2.0", "dependencies": { "@eversdk/appkit": "^0.3.8", - "@eversdk/core": "^1.44.3", - "@eversdk/lib-node": "^1.44.3", + "@eversdk/core": "^1.44.4", + "@eversdk/lib-node": "^1.44.4", "commander": "^10.0.0", "dotenv": "^16.0.3", "everdev": "^1.7.0", diff --git a/packages/cli/package.json b/packages/cli/package.json index f52e84ac..bd568af9 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -1,6 +1,6 @@ { "name": "@eversdk/cli", - "version": "1.44.3", + "version": "1.44.4", "description": "Evercloud CLI", "homepage": "https://everx.dev/", "repository": { @@ -53,8 +53,8 @@ ], "dependencies": { "@eversdk/appkit": "^0.3.8", - "@eversdk/core": "^1.44.3", - "@eversdk/lib-node": "^1.44.3", + "@eversdk/core": "^1.44.4", + "@eversdk/lib-node": "^1.44.4", "commander": "^10.0.0", "dotenv": "^16.0.3", "everdev": "^1.7.0", diff --git a/packages/core/package.json b/packages/core/package.json index f156eb15..4b638251 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@eversdk/core", - "version": "1.44.3", + "version": "1.44.4", "description": "TON Client for Java Script", "main": "dist/index.js", "types": "dist/index.d.ts", diff --git a/packages/core/src/version.ts b/packages/core/src/version.ts index cc3c5305..3f900be6 100644 --- a/packages/core/src/version.ts +++ b/packages/core/src/version.ts @@ -1 +1 @@ -export const packageVersion = "1.44.3"; +export const packageVersion = "1.44.4"; diff --git a/packages/lib-node/lib/Cargo.toml b/packages/lib-node/lib/Cargo.toml index 47bdba98..58c43ced 100644 --- a/packages/lib-node/lib/Cargo.toml +++ b/packages/lib-node/lib/Cargo.toml @@ -10,7 +10,7 @@ crate-type = [ 'staticlib' ] [dependencies] libc = '0.2' -ton_client = { git = 'https://github.com/tonlabs/ever-sdk.git', tag = '1.44.3' } +ton_client = { git = 'https://github.com/tonlabs/ever-sdk.git', tag = '1.44.4' } [profile.release] lto = true diff --git a/packages/lib-node/package.json b/packages/lib-node/package.json index 4439f81c..b5da55ab 100644 --- a/packages/lib-node/package.json +++ b/packages/lib-node/package.json @@ -1,6 +1,6 @@ { "name": "@eversdk/lib-node", - "version": "1.44.3", + "version": "1.44.4", "description": "TON Client NodeJs AddOn", "repository": { "type": "git", diff --git a/packages/lib-react-native-jsi/package.json b/packages/lib-react-native-jsi/package.json index 4b347a66..07db4436 100644 --- a/packages/lib-react-native-jsi/package.json +++ b/packages/lib-react-native-jsi/package.json @@ -1,6 +1,6 @@ { "name": "@eversdk/lib-react-native-jsi", - "version": "1.44.3", + "version": "1.44.4", "description": "TON Client React Native JSI Module", "main": "lib/commonjs/index", "module": "lib/module/index", diff --git a/packages/lib-react-native/android/lib/Cargo.toml b/packages/lib-react-native/android/lib/Cargo.toml index c2ebea40..f6b6a359 100644 --- a/packages/lib-react-native/android/lib/Cargo.toml +++ b/packages/lib-react-native/android/lib/Cargo.toml @@ -11,7 +11,7 @@ crate-type = [ 'cdylib' ] [dependencies] lazy_static = '1.4.0' jni = { default-features = false, version = '0.12.0' } -ton_client = { git = 'https://github.com/tonlabs/ever-sdk.git', tag = '1.44.3' } +ton_client = { git = 'https://github.com/tonlabs/ever-sdk.git', tag = '1.44.4' } openssl = { features = [ 'vendored' ], version = '0.10' } [profile.release] diff --git a/packages/lib-react-native/ios/lib/Cargo.toml b/packages/lib-react-native/ios/lib/Cargo.toml index 9547eb21..1a5960c8 100644 --- a/packages/lib-react-native/ios/lib/Cargo.toml +++ b/packages/lib-react-native/ios/lib/Cargo.toml @@ -10,7 +10,7 @@ crate-type = [ 'staticlib' ] [dependencies] libc = '0.2' -ton_client = { git = 'https://github.com/tonlabs/ever-sdk.git', tag = '1.44.3' } +ton_client = { git = 'https://github.com/tonlabs/ever-sdk.git', tag = '1.44.4' } [profile.release] lto = true diff --git a/packages/lib-react-native/package.json b/packages/lib-react-native/package.json index d850523e..fb5ba09c 100644 --- a/packages/lib-react-native/package.json +++ b/packages/lib-react-native/package.json @@ -1,6 +1,6 @@ { "name": "@eversdk/lib-react-native", - "version": "1.44.3", + "version": "1.44.4", "description": "TON Client React Native Module", "main": "index.js", "repository": { diff --git a/packages/lib-web/lib/Cargo.toml b/packages/lib-web/lib/Cargo.toml index c268b1e6..70009208 100644 --- a/packages/lib-web/lib/Cargo.toml +++ b/packages/lib-web/lib/Cargo.toml @@ -28,7 +28,7 @@ lazy_static = '1.4.0' # just to fix building of rand for WASM: getrandom = { default-features = false, features = [ 'js' ], version = '0.2.2' } -ton_client = { default-features = false, features = [ 'wasm' ], git = 'https://github.com/tonlabs/ever-sdk.git', tag = '1.44.3' } +ton_client = { default-features = false, features = [ 'wasm' ], git = 'https://github.com/tonlabs/ever-sdk.git', tag = '1.44.4' } [dependencies.web-sys] version = '0.3.57' diff --git a/packages/lib-web/package.json b/packages/lib-web/package.json index f319e52c..3cbc0931 100644 --- a/packages/lib-web/package.json +++ b/packages/lib-web/package.json @@ -1,6 +1,6 @@ { "name": "@eversdk/lib-web", - "version": "1.44.3", + "version": "1.44.4", "description": "TON Client WASM module for browsers", "main": "index.js", "repository": { diff --git a/packages/tests-node/package.json b/packages/tests-node/package.json index 66aacfec..8afe06e8 100644 --- a/packages/tests-node/package.json +++ b/packages/tests-node/package.json @@ -1,6 +1,6 @@ { "name": "@eversdk/tests-node", - "version": "1.44.3", + "version": "1.44.4", "private": true, "description": "TON Client Tests runner on NodeJs", "main": "index.js", diff --git a/packages/tests-react-native-jsi/package.json b/packages/tests-react-native-jsi/package.json index d503a435..2a96c43f 100644 --- a/packages/tests-react-native-jsi/package.json +++ b/packages/tests-react-native-jsi/package.json @@ -1,6 +1,6 @@ { "name": "@eversdk/tests-react-native-jsi", - "version": "1.44.3", + "version": "1.44.4", "private": true, "main": "index.js", "browser": true, diff --git a/packages/tests-react-native/package.json b/packages/tests-react-native/package.json index 83335c22..217935c5 100644 --- a/packages/tests-react-native/package.json +++ b/packages/tests-react-native/package.json @@ -1,6 +1,6 @@ { "name": "@eversdk/tests-react-native", - "version": "1.44.3", + "version": "1.44.4", "private": true, "main": "index.js", "browser": true, diff --git a/packages/tests-web/package.json b/packages/tests-web/package.json index 3ce251b7..c5961de4 100644 --- a/packages/tests-web/package.json +++ b/packages/tests-web/package.json @@ -1,6 +1,6 @@ { "name": "@eversdk/tests-web", - "version": "1.44.3", + "version": "1.44.4", "private": true, "description": "TON Client WASM module tests runner", "scripts": { diff --git a/packages/tests/package.json b/packages/tests/package.json index f3ff83ce..ad3c85bb 100644 --- a/packages/tests/package.json +++ b/packages/tests/package.json @@ -1,6 +1,6 @@ { "name": "@eversdk/tests", - "version": "1.44.3", + "version": "1.44.4", "private": true, "description": "TON Client Tests", "main": "dist/index.js", diff --git a/packages/tests/src/account.ts b/packages/tests/src/account.ts index 5cc9a629..374b9ee9 100644 --- a/packages/tests/src/account.ts +++ b/packages/tests/src/account.ts @@ -1,167 +1,192 @@ -import {TonClient} from "@eversdk/core"; -import { - Abi, accountForExecutorAccount, - ParamsOfEncodeMessage, - ResultOfProcessMessage, - ResultOfRunExecutor, - Signer, -} from "@eversdk/core"; - -export type AccountDeployParams = { - tvc: string, initFunctionName?: string, - initFunctionInput?: any, - initData?: any, -} - -export class AccountError extends Error { -} - -export class Account { - readonly client: TonClient; - readonly abi: Abi; - readonly signer: Signer; - - private readonly deployParams: AccountDeployParams | null; - private address: string | null; - private cachedBoc: string | null; - private cachedBocLt: string | null; - private minExpectedLt: string; - - // private cachedParsed: any | null; - - constructor( - client: TonClient, - abi: Abi, - signer: Signer, - addressOrDeploy: string | AccountDeployParams, - ) { - this.client = client; - this.abi = abi; - this.signer = signer; - if (typeof addressOrDeploy === "string") { - this.address = addressOrDeploy; - this.deployParams = null; - } else { - this.address = null; - this.deployParams = addressOrDeploy; - } - this.cachedBoc = null; - this.cachedBocLt = null; - this.minExpectedLt = "0x0"; - } - - async getAddress(): Promise { - let address = this.address; - if (!address) { - const deployParams = this.getParamsOfDeployMessage(); - address = (await this.client.abi.encode_message(deployParams)).address; - this.address = address; - } - return address; - } - - getParamsOfDeployMessage(): ParamsOfEncodeMessage { - const params = this.deployParams; - if (!params) { - throw this.errorDeployParamsRequired(); - } - return { - abi: this.abi, - signer: this.signer, - deploy_set: { - tvc: params.tvc, - initial_data: params.initData, - }, - call_set: params.initFunctionName - ? { - function_name: params.initFunctionName, - input: params.initFunctionInput, - } - : undefined, - }; - } - - async deploy(): Promise { - const deployParams = this.getParamsOfDeployMessage(); - this.address = (await this.client.abi.encode_message(deployParams)).address; - const result = await this.client.processing.process_message({ - message_encode_params: deployParams, - send_events: false, - }); - this.setMinExpectedLt(result.transaction["lt"]); - return result; - } - - async run(functionName: string, input?: any): Promise { - return await this.client.processing.process_message({ - message_encode_params: { - address: await this.getAddress(), - abi: this.abi, - signer: this.signer, - call_set: { - function_name: functionName, - input, - }, - }, - send_events: false, - }); - } - - async runLocal(functionName: string, input: any): Promise { - const message = await this.client.abi.encode_message({ - abi: this.abi, - signer: this.signer, - call_set: { - function_name: functionName, - input, - }, - }); - const result = await this.client.tvm.run_executor({ - account: accountForExecutorAccount(await this.boc()), - abi: this.abi, - message: message.message, - }); - if (result.account) { - this.cachedBoc = result.account; - } - return result; - } - - setMinExpectedLt(minExpectedLt: string) { - if (this.cachedBocLt && Number(minExpectedLt) > Number(this.cachedBocLt)) { - this.dropCachedData() - } - this.minExpectedLt = minExpectedLt; - } - - dropCachedData() { - this.cachedBoc = null; - } - - async boc(): Promise { - if (this.cachedBoc) { - return this.cachedBoc; - } - const { boc, last_trans_lt } = (await this.client.net.wait_for_collection({ - collection: "accounts", - filter: { - id: {eq: this.address}, - last_trans_lt: {ge: this.minExpectedLt}, - }, - result: "boc last_trans_lt", - })).result; - this.cachedBoc = boc; - this.cachedBocLt = last_trans_lt; - return boc; - } - - async getAccount(): Promise { - return (await this.client.boc.parse_account({ - boc: await this.boc(), - })).parsed; - } - - private errorDeployParamsRequired(): AccountError { - return new AccountError(`Deploy params required. `); - } -} +import {TonClient} from "@eversdk/core"; +import { + Abi, accountForExecutorAccount, + ParamsOfEncodeMessage, + ResultOfProcessMessage, + ResultOfRunExecutor, + Signer, +} from "@eversdk/core"; + +export const MAX_WAIT_TIME = 40_000; // 40 sec + +export type AccountDeployParams = { + tvc: string, initFunctionName?: string, + initFunctionInput?: any, + initData?: any, +} + +export class AccountError extends Error { +} + +export class Account { + readonly client: TonClient; + readonly abi: Abi; + readonly signer: Signer; + + private readonly deployParams: AccountDeployParams | null; + private address: string | null; + private cachedBoc: string | null; + private cachedBocLt: string | null; + private minExpectedLt: string; + + // private cachedParsed: any | null; + + constructor( + client: TonClient, + abi: Abi, + signer: Signer, + addressOrDeploy: string | AccountDeployParams, + ) { + this.client = client; + this.abi = abi; + this.signer = signer; + if (typeof addressOrDeploy === "string") { + this.address = addressOrDeploy; + this.deployParams = null; + } else { + this.address = null; + this.deployParams = addressOrDeploy; + } + this.cachedBoc = null; + this.cachedBocLt = null; + this.minExpectedLt = "0x0"; + } + + async getAddress(): Promise { + let address = this.address; + if (!address) { + const deployParams = this.getParamsOfDeployMessage(); + address = (await this.client.abi.encode_message(deployParams)).address; + this.address = address; + } + return address; + } + + getParamsOfDeployMessage(): ParamsOfEncodeMessage { + const params = this.deployParams; + if (!params) { + throw this.errorDeployParamsRequired(); + } + return { + abi: this.abi, + signer: this.signer, + deploy_set: { + tvc: params.tvc, + initial_data: params.initData, + }, + call_set: params.initFunctionName + ? { + function_name: params.initFunctionName, + input: params.initFunctionInput, + } + : undefined, + }; + } + + async deploy(): Promise { + const deployParams = this.getParamsOfDeployMessage(); + this.address = (await this.client.abi.encode_message(deployParams)).address; + const result = await this.client.processing.process_message({ + message_encode_params: deployParams, + send_events: false, + }); + this.setMinExpectedLt(result.transaction["lt"]); + return result; + } + + async run(functionName: string, input?: any): Promise { + return await this.client.processing.process_message({ + message_encode_params: { + address: await this.getAddress(), + abi: this.abi, + signer: this.signer, + call_set: { + function_name: functionName, + input, + }, + }, + send_events: false, + }); + } + + async runLocal(functionName: string, input: any): Promise { + const message = await this.client.abi.encode_message({ + abi: this.abi, + signer: this.signer, + call_set: { + function_name: functionName, + input, + }, + }); + const result = await this.client.tvm.run_executor({ + account: accountForExecutorAccount(await this.boc()), + abi: this.abi, + message: message.message, + }); + if (result.account) { + this.cachedBoc = result.account; + } + return result; + } + + setMinExpectedLt(minExpectedLt: string) { + if (this.cachedBocLt && Number(minExpectedLt) > Number(this.cachedBocLt)) { + this.dropCachedData() + } + this.minExpectedLt = minExpectedLt; + } + + dropCachedData() { + this.cachedBoc = null; + } + + async boc(): Promise { + if (this.cachedBoc) { + return this.cachedBoc; + } + const query = ` + query($address:String!) { + blockchain { + account( + address: $address + ) { + info { + boc + last_trans_lt + } + } + } + }`; + const variables = {address: this.address}; + let last_trans_lt; + let boc; + let delay = 0 + const timeLimit = Date.now() + MAX_WAIT_TIME // 40 sec + while (!(last_trans_lt >= this.minExpectedLt) && (Date.now() < timeLimit)) { + if (delay > 0) { + await new Promise(resolve => setTimeout(resolve, delay)); + if (delay < 5000) { + delay += 1000 + } + } else { + delay = 1000 + } + const { result } = await this.client.net.query({ query, variables }); + boc = result.data.blockchain.account.info.boc; + last_trans_lt = result.data.blockchain.account.info.last_trans_lt; + } + this.cachedBoc = boc; + this.cachedBocLt = last_trans_lt; + return boc; + } + + async getAccount(): Promise { + return (await this.client.boc.parse_account({ + boc: await this.boc(), + })).parsed; + } + + private errorDeployParamsRequired(): AccountError { + return new AccountError(`Deploy params required. `); + } +} diff --git a/packages/tests/src/givers.ts b/packages/tests/src/givers.ts index f3b2b633..0dee8c98 100644 --- a/packages/tests/src/givers.ts +++ b/packages/tests/src/givers.ts @@ -1,220 +1,220 @@ -/* - * Copyright 2018-2020 TON Labs LTD. - * - * Licensed under the SOFTWARE EVALUATION License (the "License"); you may not use - * this file except in compliance with the License. - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific TON DEV software governing permissions and - * limitations under the License. - * - */ - -// noinspection SpellCheckingInspection -import { - abiContract, - KeyPair, - signerKeys, - TonClient, -} from "@eversdk/core"; -import {ContractPackage} from "./contracts"; - -export function getEnv(name: string): any { - const globalEval = eval; - try { - return globalEval(`process.env.${name}`); - } catch { - return undefined; - } -} - -export type GiverVersions = "v2" | "v3" - -export function getDefaultGiverContract(type: GiverVersions): ContractPackage { - try { - return { v2: DefaultGiverContract, v3: GiverV3Contract }[type] - } catch (e) { - throw Error(`Giver type '${type}' unknown`) - } -} - -export async function getDefaultGiverKeys(client: TonClient): Promise { - const definedSecret = getEnv("TON_GIVER_SECRET"); - if (definedSecret) { - const definedKeys = await client.crypto.nacl_sign_keypair_from_secret_key({ - secret: definedSecret, - }); - definedKeys.secret = definedKeys.secret.substring(0, 64); - return definedKeys; - } - return { - "public": "2ada2e65ab8eeab09490e3521415f45b6e42df9c760a639bcf53957550b25a16", - "secret": "172af540e43a524763dd53b26a066d472a97c4de37d5498170564510608250c3", - }; -} - -export async function getDefaultGiverAddress(client: TonClient, keys: KeyPair, giver: ContractPackage): Promise { - const definedAddress = getEnv("TON_GIVER_ADDRESS"); - if (definedAddress) { - return definedAddress; - } - return (await client.abi.encode_message({ - abi: abiContract(giver.abi), - deploy_set: { - tvc: giver.tvc ?? "", - }, - signer: signerKeys(keys), - })).address; -} - -export const DefaultGiverContract: ContractPackage = { - abi: { - "ABI version": 2, - header: ["time", "expire"], - functions: [ - { - name: "sendTransaction", - inputs: [ - { - "name": "dest", - "type": "address", - }, - { - "name": "value", - "type": "uint128", - }, - { - "name": "bounce", - "type": "bool", - }, - ], - outputs: [], - }, - { - name: "getMessages", - inputs: [], - outputs: [ - { - components: [ - { - name: "hash", - type: "uint256", - }, - { - name: "expireAt", - type: "uint64", - }, - ], - name: "messages", - type: "tuple[]", - }, - ], - }, - { - name: "upgrade", - inputs: [ - { - name: "newcode", - type: "cell", - }, - ], - outputs: [], - }, - { - name: "constructor", - inputs: [], - outputs: [], - }, - ], - data: [], - events: [], - }, - tvc: "te6ccgECIAEAA6YAAgE0BgEBAcACAgPPIAUDAQHeBAAD0CAAQdgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAIm/wD0pCAiwAGS9KDhiu1TWDD0oQkHAQr0pCD0oQgAAAIBIA0KAQL/CwH+fyHtRNAg10nCAZ/T/9MA9AX4an/4Yfhm+GKOG/QFbfhqcAGAQPQO8r3XC//4YnD4Y3D4Zn/4YeLTAAGOEoECANcYIPkBWPhCIPhl+RDyqN4j+EUgbpIwcN74Qrry4GUh0z/THzQg+CO88rki+QAg+EqBAQD0DiCRMd7y0Gb4AAwANiD4SiPIyz9ZgQEA9EP4al8E0x8B8AH4R27yfAIBIBQOAgFYEg8BCbjomPxQEAHW+EFujhLtRNDT/9MA9AX4an/4Yfhm+GLe0XBtbwL4SoEBAPSGlQHXCz9/k3BwcOKRII4yXzPIIs8L/yHPCz8xMQFvIiGkA1mAIPRDbwI0IvhKgQEA9HyVAdcLP3+TcHBw4gI1MzHoXwMhwP8RAJiOLiPQ0wH6QDAxyM+HIM6NBAAAAAAAAAAAAAAAAA90TH4ozxYhbyICyx/0AMlx+wDeMMD/jhL4QsjL//hGzwsA+EoB9ADJ7VTef/hnAQm5Fqvn8BMAtvhBbo427UTQINdJwgGf0//TAPQF+Gp/+GH4Zvhijhv0BW34anABgED0DvK91wv/+GJw+GNw+GZ/+GHi3vhG8nNx+GbR+AD4QsjL//hGzwsA+EoB9ADJ7VR/+GcCASAYFQEJuxXvk1gWAbb4QW6OEu1E0NP/0wD0Bfhqf/hh+Gb4Yt76QNcNf5XU0dDTf9/XDACV1NHQ0gDf0VRxIMjPhYDKAHPPQM4B+gKAa89AyXP7APhKgQEA9IaVAdcLP3+TcHBw4pEgFwCEjigh+CO7myL4SoEBAPRbMPhq3iL4SoEBAPR8lQHXCz9/k3BwcOICNTMx6F8G+ELIy//4Rs8LAPhKAfQAye1Uf/hnAgEgGxkBCbjkYYdQGgC++EFujhLtRNDT/9MA9AX4an/4Yfhm+GLe1NH4RSBukjBw3vhCuvLgZfgA+ELIy//4Rs8LAPhKAfQAye1U+A8g+wQg0O0e7VPwAjD4QsjL//hGzwsA+EoB9ADJ7VR/+GcCAtoeHAEBSB0ALPhCyMv/+EbPCwD4SgH0AMntVPgP8gABAUgfAFhwItDWAjHSADDcIccA3CHXDR/yvFMR3cEEIoIQ/////byx8nwB8AH4R27yfA==", -}; - -export const GiverV3Contract: ContractPackage = { - abi: { - "ABI version": 2, - "version": "2.3", - "header": [ - "time", - "expire" - ], - "functions": [ - { - "name": "sendTransaction", - "inputs": [ - { - "name": "dest", - "type": "address" - }, - { - "name": "value", - "type": "uint128" - }, - { - "name": "bounce", - "type": "bool" - } - ], - "outputs": [] - }, - { - "name": "getMessages", - "inputs": [], - "outputs": [ - { - "components": [ - { - "name": "hash", - "type": "uint256" - }, - { - "name": "expireAt", - "type": "uint32" - } - ], - "name": "messages", - "type": "tuple[]" - } - ] - }, - { - "name": "upgrade", - "inputs": [ - { - "name": "newcode", - "type": "cell" - } - ], - "outputs": [] - }, - { - "name": "constructor", - "inputs": [], - "outputs": [] - } - ], - "data": [], - "events": [], - "fields": [ - { - "name": "_pubkey", - "type": "uint256" - }, - { - "name": "_constructorFlag", - "type": "bool" - }, - { - "name": "m_messages", - "type": "map(uint256,uint32)" - } - ] - }, - tvc: "te6ccgECFwEAAwAAAgE0AwEBAcACAEPQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgBCSK7VMg4wMgwP/jAiDA/uMC8gsTBgUEAAAC3O1E0NdJwwH4ZiHbPNMAAY4XgwjXGCD4KMjOzsn5AFj4QiD4ZfkQ8qjeI/hFIG6SMHDe+EK68uBlIfkBItM/0x81MSD4I7zyuSH4SoMH9A5voTHy0Gb4ACH4SiLIyx9Zgwf0Q/hqXwPTHwHbPPI8CQcDSu1E0NdJwwH4ZiLQ1wsDqTgA3CHHAOMCIdcNH/K8IeMDAds88jwSEgcEUCCCEBcjDDq64wIgghAXMr/DuuMCIIIQMV75NbrjAiCCEGi1Xz+64wIPDAoIAiIw+EJu4wD4RvJz0fgA2zzyAAkWAUTtRNDXScIBjhdw7UTQ9AVt+GqAQPQO8r3XC//4YnD4Y+MNEQM8MPhG8uBM+EJu4wAhk9TR0N76QNN/0gDR2zzbPPIAEQsWAL5UcSDIz4WAygDPhEDOAfoCgGvPQMlz+wBw+Eoggwf0hpUgWNcLH5NtXyDikyJus44qJMId4wgkpDX4I7uaIPhKgwf0WzD4at5TEoMH9HyVIFjXCx+TbV8g4mwj4xhfCAN0MPhG8uBM+EJu4wDR2zwhjiIj0NMB+kAwMcjPhyDOghCXMr/DzwuBAW8iAssf9ADJcPsAkTDi4wDyABENFgGOcG1vAvhKIIMH9IaVIFjXCx+TbV8g4pMibrOOqFR0EG8C2zwBbyIhpFUggCD0Q28CNVMjgwf0fJUgWNcLH5NtXyDibDPoXwQOABBvIgHIy//LHwMmMPhG8uBM+EJu4wDU0ds82zzyABEQFgFq+EUgbpIwcN74Qrry4GX4ANs8+A8g+wTQIIs4rbNYxwWT103Q3tdM0O0e7VOCECyo3u/tQ9gWAB7tRNDT/9MAMfQE0fhq+GIACvhG8uBMAhD0pCD0vfLAThUUABRzb2wgMC42Ni4wARagLKje79s8+A/yABYAHPhK+ELIy//Pg/QAye1U", -}; - -export const giverRequestAmount = 500_000_000; +/* + * Copyright 2018-2020 TON Labs LTD. + * + * Licensed under the SOFTWARE EVALUATION License (the "License"); you may not use + * this file except in compliance with the License. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific TON DEV software governing permissions and + * limitations under the License. + * + */ + +// noinspection SpellCheckingInspection +import { + abiContract, + KeyPair, + signerKeys, + TonClient, +} from "@eversdk/core"; +import {ContractPackage} from "./contracts"; + +export function getEnv(name: string): any { + const globalEval = eval; + try { + return globalEval(`process.env.${name}`); + } catch { + return undefined; + } +} + +export type GiverVersions = "v2" | "v3" + +export function getDefaultGiverContract(type: GiverVersions): ContractPackage { + try { + return { v2: DefaultGiverContract, v3: GiverV3Contract }[type] + } catch (e) { + throw Error(`Giver type '${type}' unknown`) + } +} + +export async function getDefaultGiverKeys(client: TonClient): Promise { + const definedSecret = getEnv("TON_GIVER_SECRET"); + if (definedSecret) { + const definedKeys = await client.crypto.nacl_sign_keypair_from_secret_key({ + secret: definedSecret, + }); + definedKeys.secret = definedKeys.secret.substring(0, 64); + return definedKeys; + } + return { + "public": "2ada2e65ab8eeab09490e3521415f45b6e42df9c760a639bcf53957550b25a16", + "secret": "172af540e43a524763dd53b26a066d472a97c4de37d5498170564510608250c3", + }; +} + +export async function getDefaultGiverAddress(client: TonClient, keys: KeyPair, giver: ContractPackage): Promise { + const definedAddress = getEnv("TON_GIVER_ADDRESS"); + if (definedAddress) { + return definedAddress; + } + return (await client.abi.encode_message({ + abi: abiContract(giver.abi), + deploy_set: { + tvc: giver.tvc ?? "", + }, + signer: signerKeys(keys), + })).address; +} + +export const DefaultGiverContract: ContractPackage = { + abi: { + "ABI version": 2, + header: ["time", "expire"], + functions: [ + { + name: "sendTransaction", + inputs: [ + { + "name": "dest", + "type": "address", + }, + { + "name": "value", + "type": "uint128", + }, + { + "name": "bounce", + "type": "bool", + }, + ], + outputs: [], + }, + { + name: "getMessages", + inputs: [], + outputs: [ + { + components: [ + { + name: "hash", + type: "uint256", + }, + { + name: "expireAt", + type: "uint64", + }, + ], + name: "messages", + type: "tuple[]", + }, + ], + }, + { + name: "upgrade", + inputs: [ + { + name: "newcode", + type: "cell", + }, + ], + outputs: [], + }, + { + name: "constructor", + inputs: [], + outputs: [], + }, + ], + data: [], + events: [], + }, + tvc: "te6ccgECIAEAA6YAAgE0BgEBAcACAgPPIAUDAQHeBAAD0CAAQdgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAIm/wD0pCAiwAGS9KDhiu1TWDD0oQkHAQr0pCD0oQgAAAIBIA0KAQL/CwH+fyHtRNAg10nCAZ/T/9MA9AX4an/4Yfhm+GKOG/QFbfhqcAGAQPQO8r3XC//4YnD4Y3D4Zn/4YeLTAAGOEoECANcYIPkBWPhCIPhl+RDyqN4j+EUgbpIwcN74Qrry4GUh0z/THzQg+CO88rki+QAg+EqBAQD0DiCRMd7y0Gb4AAwANiD4SiPIyz9ZgQEA9EP4al8E0x8B8AH4R27yfAIBIBQOAgFYEg8BCbjomPxQEAHW+EFujhLtRNDT/9MA9AX4an/4Yfhm+GLe0XBtbwL4SoEBAPSGlQHXCz9/k3BwcOKRII4yXzPIIs8L/yHPCz8xMQFvIiGkA1mAIPRDbwI0IvhKgQEA9HyVAdcLP3+TcHBw4gI1MzHoXwMhwP8RAJiOLiPQ0wH6QDAxyM+HIM6NBAAAAAAAAAAAAAAAAA90TH4ozxYhbyICyx/0AMlx+wDeMMD/jhL4QsjL//hGzwsA+EoB9ADJ7VTef/hnAQm5Fqvn8BMAtvhBbo427UTQINdJwgGf0//TAPQF+Gp/+GH4Zvhijhv0BW34anABgED0DvK91wv/+GJw+GNw+GZ/+GHi3vhG8nNx+GbR+AD4QsjL//hGzwsA+EoB9ADJ7VR/+GcCASAYFQEJuxXvk1gWAbb4QW6OEu1E0NP/0wD0Bfhqf/hh+Gb4Yt76QNcNf5XU0dDTf9/XDACV1NHQ0gDf0VRxIMjPhYDKAHPPQM4B+gKAa89AyXP7APhKgQEA9IaVAdcLP3+TcHBw4pEgFwCEjigh+CO7myL4SoEBAPRbMPhq3iL4SoEBAPR8lQHXCz9/k3BwcOICNTMx6F8G+ELIy//4Rs8LAPhKAfQAye1Uf/hnAgEgGxkBCbjkYYdQGgC++EFujhLtRNDT/9MA9AX4an/4Yfhm+GLe1NH4RSBukjBw3vhCuvLgZfgA+ELIy//4Rs8LAPhKAfQAye1U+A8g+wQg0O0e7VPwAjD4QsjL//hGzwsA+EoB9ADJ7VR/+GcCAtoeHAEBSB0ALPhCyMv/+EbPCwD4SgH0AMntVPgP8gABAUgfAFhwItDWAjHSADDcIccA3CHXDR/yvFMR3cEEIoIQ/////byx8nwB8AH4R27yfA==", +}; + +export const GiverV3Contract: ContractPackage = { + abi: { + "ABI version": 2, + "version": "2.3", + "header": [ + "time", + "expire" + ], + "functions": [ + { + "name": "sendTransaction", + "inputs": [ + { + "name": "dest", + "type": "address" + }, + { + "name": "value", + "type": "uint128" + }, + { + "name": "bounce", + "type": "bool" + } + ], + "outputs": [] + }, + { + "name": "getMessages", + "inputs": [], + "outputs": [ + { + "components": [ + { + "name": "hash", + "type": "uint256" + }, + { + "name": "expireAt", + "type": "uint32" + } + ], + "name": "messages", + "type": "tuple[]" + } + ] + }, + { + "name": "upgrade", + "inputs": [ + { + "name": "newcode", + "type": "cell" + } + ], + "outputs": [] + }, + { + "name": "constructor", + "inputs": [], + "outputs": [] + } + ], + "data": [], + "events": [], + "fields": [ + { + "name": "_pubkey", + "type": "uint256" + }, + { + "name": "_constructorFlag", + "type": "bool" + }, + { + "name": "m_messages", + "type": "map(uint256,uint32)" + } + ] + }, + tvc: "te6ccgECFwEAAwAAAgE0AwEBAcACAEPQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgBCSK7VMg4wMgwP/jAiDA/uMC8gsTBgUEAAAC3O1E0NdJwwH4ZiHbPNMAAY4XgwjXGCD4KMjOzsn5AFj4QiD4ZfkQ8qjeI/hFIG6SMHDe+EK68uBlIfkBItM/0x81MSD4I7zyuSH4SoMH9A5voTHy0Gb4ACH4SiLIyx9Zgwf0Q/hqXwPTHwHbPPI8CQcDSu1E0NdJwwH4ZiLQ1wsDqTgA3CHHAOMCIdcNH/K8IeMDAds88jwSEgcEUCCCEBcjDDq64wIgghAXMr/DuuMCIIIQMV75NbrjAiCCEGi1Xz+64wIPDAoIAiIw+EJu4wD4RvJz0fgA2zzyAAkWAUTtRNDXScIBjhdw7UTQ9AVt+GqAQPQO8r3XC//4YnD4Y+MNEQM8MPhG8uBM+EJu4wAhk9TR0N76QNN/0gDR2zzbPPIAEQsWAL5UcSDIz4WAygDPhEDOAfoCgGvPQMlz+wBw+Eoggwf0hpUgWNcLH5NtXyDikyJus44qJMId4wgkpDX4I7uaIPhKgwf0WzD4at5TEoMH9HyVIFjXCx+TbV8g4mwj4xhfCAN0MPhG8uBM+EJu4wDR2zwhjiIj0NMB+kAwMcjPhyDOghCXMr/DzwuBAW8iAssf9ADJcPsAkTDi4wDyABENFgGOcG1vAvhKIIMH9IaVIFjXCx+TbV8g4pMibrOOqFR0EG8C2zwBbyIhpFUggCD0Q28CNVMjgwf0fJUgWNcLH5NtXyDibDPoXwQOABBvIgHIy//LHwMmMPhG8uBM+EJu4wDU0ds82zzyABEQFgFq+EUgbpIwcN74Qrry4GX4ANs8+A8g+wTQIIs4rbNYxwWT103Q3tdM0O0e7VOCECyo3u/tQ9gWAB7tRNDT/9MAMfQE0fhq+GIACvhG8uBMAhD0pCD0vfLAThUUABRzb2wgMC42Ni4wARagLKje79s8+A/yABYAHPhK+ELIy//Pg/QAye1U", +}; + +export const giverRequestAmount = 100_000_000; // old value was 0.5 diff --git a/packages/tests/src/runner.ts b/packages/tests/src/runner.ts index 0b528120..3e150c40 100644 --- a/packages/tests/src/runner.ts +++ b/packages/tests/src/runner.ts @@ -1,288 +1,288 @@ -/* - * Copyright 2018-2020 TON Labs LTD. - * - * Licensed under the SOFTWARE EVALUATION License (the "License"); you may not use - * this file except in compliance with the License. - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific TON DEV software governing permissions and - * limitations under the License. - * - */ - -import { - abiContract, - ClientConfig, - ResultOfProcessMessage, - Signer, - signerKeys, - TonClient, -} from "@eversdk/core"; - -import { - getDefaultGiverAddress, - getDefaultGiverContract, - getDefaultGiverKeys, - getEnv, - giverRequestAmount, -} from "./givers"; -import { jest } from "./jest"; -import { Account } from "./account"; -import { ContractPackage } from "./contracts"; -import { TestEntry } from "jest-circus"; - -function resolveConfig(): ClientConfig { - return { - abi: { - message_expiration_timeout: 5000, - message_expiration_timeout_grow_factor: 1, - }, - network: { - message_retries_count: 10, - endpoints: [`${process.env.TON_NETWORK_ADDRESS || "http://localhost"}`], - }, - }; -} - -export type TestRunnerLog = (...args: any[]) => void; - -export type TestRunnerOptions = { - filter?: (test: TestEntry) => boolean, - log?: TestRunnerLog, -} - -export class TestsRunner { - static setTimeout: (f: () => void, ms: number) => void = () => { - }; - static log: (...args: any[]) => void = (..._args: any[]) => { - }; - static exit: (code: number) => void = (_code) => { - }; - config = resolveConfig(); - - private client: TonClient | null = null; - private giver: Account | null = null; - private deployedAccounts: Account[] = []; - - static async run( - onStateChange: (state: TestsRunningState) => void, - options?: TestRunnerOptions | TestRunnerLog, - ) { - const resolvedOptions: TestRunnerOptions = - options === undefined - ? {} - : (typeof options === "function" ? { - log: options, - } : options); - - function errorToJson(error: any) { - const json: { [key: string]: any } = {}; - Object.entries(error).forEach(([key, value]) => { - json[key] = value; - }); - if (error.message && !json.message) { - json.message = error.message; - } - if (Object.keys(json).length === 0) { - json.message = error.toString(); - } - return json; - } - - const log = resolvedOptions.log ?? TestsRunner.log; - try { - jest.setTimeout(300000); - const client = runner.getClient(); - - const state: TestsRunningState = { - version: (await client.client.version()).version, - passed: 0, - failed: 0, - finished: false, - }; - onStateChange(state); - - jest.addEventHandler((event: any) => { - if (event.name === "test_start") { - log(`[TEST_START] ${JSON.stringify({ - name: event.test.name, - })}`); - } else if (event.name === "test_success") { - state.passed += 1; - log(`[TEST_SUCCESS] ${JSON.stringify({ - name: event.test.name, - })}`); - } else if (event.name === "test_failure") { - state.failed += 1; - log(`[TEST_FAILURE] ${JSON.stringify({ - name: event.test.name, - errors: event.test.errors && event.test.errors.map(errorToJson), - })}`); - } else { - return; - } - onStateChange(state); - }); - onStateChange(state); - const testFilter = resolvedOptions.filter; - if (testFilter) { - const { rootDescribeBlock } = jest.getState(); - rootDescribeBlock.tests = rootDescribeBlock.tests.filter(testFilter); - } - - const results = await jest.run(); - results.forEach((result) => { - result.errors = result.errors.map((e) => { - return e.toString().replace(/\n\s+at\s+.*/gi, ""); - }); - }); - log(`[TEST_COMPLETE] ${JSON.stringify(results)}`); - state.finished = true; - onStateChange(state); - } catch (error) { - log(">>>", error); - } - } - - getClient(): TonClient { - if (!this.client) { - this.client = new TonClient(this.config); - } - return this.client; - } - - async getGiver(): Promise { - if (this.giver) { - return this.giver; - } - const client = this.getClient(); - const giverContract = getDefaultGiverContract(getEnv("EVERCLOUD_GIVER_TYPE") ?? "v2"); - const giverKeys = await getDefaultGiverKeys(client); - const giver = new Account( - client, - abiContract(giverContract.abi), - signerKeys(giverKeys), - await getDefaultGiverAddress(client, giverKeys, giverContract), - ); - this.giver = giver; - const accounts = (await client.net.query_collection({ - collection: "accounts", - filter: { - id: { eq: await giver.getAddress() }, - }, - result: "acc_type balance", - })).result; - - if (accounts.length === 0) { - throw new Error(`Giver wallet does not exist. Send some grams to ${await giver.getAddress()}`); - } - const account = accounts[0]; - if (!account.balance || Number(account.balance) < giverRequestAmount) { - throw new Error(`Giver has no money. Send some grams to ${await giver.getAddress()}`); - } - if (account.acc_type !== 1) { - throw new Error(`Giver has not deployed.`); - } - return giver; - } - - async getAccount( - packages: { [abiVersion: number]: ContractPackage }, - abiVersion: any, - signer?: Signer, - initFunctionInput?: any, - initData?: any, - ): Promise { - const pkg: ContractPackage | undefined = packages[Number(abiVersion) as ABIVersion]; - if (!pkg) { - throw new Error(`Missing required contract with ABI v${abiVersion}`); - } - return new Account( - this.getClient(), - abiContract(pkg.abi), - signer ?? signerKeys(await this.getClient().crypto.generate_random_sign_keys()) - , { - tvc: pkg.tvc, - initFunctionName: "constructor", - initFunctionInput, - initData, - }, - ); - } - - async sendGramsTo(account: string, amount: number = giverRequestAmount): Promise { - let result: ResultOfProcessMessage; - const giver = await this.getGiver(); - result = await giver.run("sendTransaction", { - dest: account, - value: amount, - bounce: false, - }); - await this.waitFor(giver.client, "accounts", "id", account); - await this.waitForMessageProcessed(giver.client, result.transaction.in_msg); - for (const boc of result.out_messages) { - const msg = (await giver.client.boc.parse_message({ boc })).parsed; - if (msg.msg_type === 0) { - await this.waitForMessageProcessed(giver.client, msg.id); - } - } - } - - private async waitForMessageProcessed(client: TonClient, message: string) { - await this.waitFor(client, "transactions", "in_msg", message); - await this.waitFor(client, "messages", "id", message); - } - - private async waitFor(client: TonClient, collection: string, field: string, value: string) { - await client.net.wait_for_collection({ - collection, - filter: { - [field]: { eq: value }, - }, - result: "id", - }); - } - - async deploy(account: Account): Promise { - await this.sendGramsTo(await account.getAddress(), giverRequestAmount); - this.deployedAccounts.push(account); - await account.deploy(); - } - - async done() { - const giver = this.giver; - if (giver) { - for (const account of runner.deployedAccounts) { - try { - await account.run("sendAllMoney", { dest_addr: await giver.getAddress() }); - } catch (e) { - // ignore exception - } - } - await new Promise(resolve => TestsRunner.setTimeout(resolve as any, 1000)); - } - if (this.client) { - this.client.close(); - } - } -} - -export const runner = new TestsRunner(); -export const ABIVersions = [1, 2]; -export type ABIVersion = 1 | 2; - -export type TestsRunningState = { - version: string, - passed: number, - failed: number, - finished: boolean, -} - -export const zeroRunningState: TestsRunningState = { - version: "", - passed: 0, - failed: 0, - finished: false, -}; +/* + * Copyright 2018-2020 TON Labs LTD. + * + * Licensed under the SOFTWARE EVALUATION License (the "License"); you may not use + * this file except in compliance with the License. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific TON DEV software governing permissions and + * limitations under the License. + * + */ + +import { + abiContract, + ClientConfig, + ResultOfProcessMessage, + Signer, + signerKeys, + TonClient, +} from "@eversdk/core"; + +import { + getDefaultGiverAddress, + getDefaultGiverContract, + getDefaultGiverKeys, + getEnv, + giverRequestAmount, +} from "./givers"; +import { jest } from "./jest"; +import { Account } from "./account"; +import { ContractPackage } from "./contracts"; +import { TestEntry } from "jest-circus"; + +function resolveConfig(): ClientConfig { + return { + abi: { + message_expiration_timeout: 5000, + message_expiration_timeout_grow_factor: 1, + }, + network: { + message_retries_count: 10, + endpoints: [`${process.env.TON_NETWORK_ADDRESS || "http://localhost"}`], + }, + }; +} + +export type TestRunnerLog = (...args: any[]) => void; + +export type TestRunnerOptions = { + filter?: (test: TestEntry) => boolean, + log?: TestRunnerLog, +} + +export class TestsRunner { + static setTimeout: (f: () => void, ms: number) => void = () => { + }; + static log: (...args: any[]) => void = (..._args: any[]) => { + }; + static exit: (code: number) => void = (_code) => { + }; + config = resolveConfig(); + + private client: TonClient | null = null; + private giver: Account | null = null; + private deployedAccounts: Account[] = []; + + static async run( + onStateChange: (state: TestsRunningState) => void, + options?: TestRunnerOptions | TestRunnerLog, + ) { + const resolvedOptions: TestRunnerOptions = + options === undefined + ? {} + : (typeof options === "function" ? { + log: options, + } : options); + + function errorToJson(error: any) { + const json: { [key: string]: any } = {}; + Object.entries(error).forEach(([key, value]) => { + json[key] = value; + }); + if (error.message && !json.message) { + json.message = error.message; + } + if (Object.keys(json).length === 0) { + json.message = error.toString(); + } + return json; + } + + const log = resolvedOptions.log ?? TestsRunner.log; + try { + jest.setTimeout(300000); + const client = runner.getClient(); + + const state: TestsRunningState = { + version: (await client.client.version()).version, + passed: 0, + failed: 0, + finished: false, + }; + onStateChange(state); + + jest.addEventHandler((event: any) => { + if (event.name === "test_start") { + log(`[TEST_START] ${JSON.stringify({ + name: event.test.name, + })}`); + } else if (event.name === "test_success") { + state.passed += 1; + log(`[TEST_SUCCESS] ${JSON.stringify({ + name: event.test.name, + })}`); + } else if (event.name === "test_failure") { + state.failed += 1; + log(`[TEST_FAILURE] ${JSON.stringify({ + name: event.test.name, + errors: event.test.errors && event.test.errors.map(errorToJson), + })}`); + } else { + return; + } + onStateChange(state); + }); + onStateChange(state); + const testFilter = resolvedOptions.filter; + if (testFilter) { + const { rootDescribeBlock } = jest.getState(); + rootDescribeBlock.tests = rootDescribeBlock.tests.filter(testFilter); + } + + const results = await jest.run(); + results.forEach((result) => { + result.errors = result.errors.map((e) => { + return e.toString().replace(/\n\s+at\s+.*/gi, ""); + }); + }); + log(`[TEST_COMPLETE] ${JSON.stringify(results)}`); + state.finished = true; + onStateChange(state); + } catch (error) { + log(">>>", error); + } + } + + getClient(): TonClient { + if (!this.client) { + this.client = new TonClient(this.config); + } + return this.client; + } + + async getGiver(): Promise { + if (this.giver) { + return this.giver; + } + const client = this.getClient(); + const giverContract = getDefaultGiverContract(getEnv("EVERCLOUD_GIVER_TYPE") ?? "v2"); + const giverKeys = await getDefaultGiverKeys(client); + const giver = new Account( + client, + abiContract(giverContract.abi), + signerKeys(giverKeys), + await getDefaultGiverAddress(client, giverKeys, giverContract), + ); + this.giver = giver; + const accounts = (await client.net.query_collection({ + collection: "accounts", + filter: { + id: { eq: await giver.getAddress() }, + }, + result: "acc_type balance", + })).result; + + if (accounts.length === 0) { + throw new Error(`Giver wallet does not exist. Send some grams to ${await giver.getAddress()}`); + } + const account = accounts[0]; + if (!account.balance || Number(account.balance) < giverRequestAmount) { + throw new Error(`Giver has no money. Send some grams to ${await giver.getAddress()}`); + } + if (account.acc_type !== 1) { + throw new Error(`Giver has not deployed.`); + } + return giver; + } + + async getAccount( + packages: { [abiVersion: number]: ContractPackage }, + abiVersion: any, + signer?: Signer, + initFunctionInput?: any, + initData?: any, + ): Promise { + const pkg: ContractPackage | undefined = packages[Number(abiVersion) as ABIVersion]; + if (!pkg) { + throw new Error(`Missing required contract with ABI v${abiVersion}`); + } + return new Account( + this.getClient(), + abiContract(pkg.abi), + signer ?? signerKeys(await this.getClient().crypto.generate_random_sign_keys()) + , { + tvc: pkg.tvc, + initFunctionName: "constructor", + initFunctionInput, + initData, + }, + ); + } + + async sendGramsTo(account: string, amount: number = giverRequestAmount): Promise { + let result: ResultOfProcessMessage; + const giver = await this.getGiver(); + result = await giver.run("sendTransaction", { + dest: account, + value: amount, + bounce: false, + }); + await this.waitFor(giver.client, "accounts", "id", account); + await this.waitForMessageProcessed(giver.client, result.transaction.in_msg); + for (const boc of result.out_messages) { + const msg = (await giver.client.boc.parse_message({ boc })).parsed; + if (msg.msg_type === 0) { + await this.waitForMessageProcessed(giver.client, msg.id); + } + } + } + + private async waitForMessageProcessed(client: TonClient, message: string) { + await this.waitFor(client, "transactions", "in_msg", message); + await this.waitFor(client, "messages", "id", message); + } + + private async waitFor(client: TonClient, collection: string, field: string, value: string) { + await client.net.wait_for_collection({ + collection, + filter: { + [field]: { eq: value }, + }, + result: "id", + }); + } + + async deploy(account: Account): Promise { + await this.sendGramsTo(await account.getAddress(), giverRequestAmount); + this.deployedAccounts.push(account); + await account.deploy(); + } + + async done() { + const giver = this.giver; + if (giver) { + for (const account of runner.deployedAccounts) { + try { + await account.run("sendAllMoney", { dest_addr: await giver.getAddress() }); + } catch (e) { + // ignore exception + } + } + await new Promise(resolve => TestsRunner.setTimeout(resolve as any, 1000)); + } + if (this.client) { + this.client.close(); + } + } +} + +export const runner = new TestsRunner(); +export const ABIVersions = [2]; // drop AbiVersion 1 it's too old for support +export type ABIVersion = 1 | 2; + +export type TestsRunningState = { + version: string, + passed: number, + failed: number, + finished: boolean, +} + +export const zeroRunningState: TestsRunningState = { + version: "", + passed: 0, + failed: 0, + finished: false, +};