diff --git a/.eslintrc.cjs b/.eslintrc.cjs new file mode 100644 index 000000000..68a908342 --- /dev/null +++ b/.eslintrc.cjs @@ -0,0 +1,26 @@ +module.exports = { + root: true, + env: { + es2021: true, + node: true, + }, + overrides: [ + { + files: ["./**/*.ts", "./**/*.js"], + extends: [ + "eslint:recommended", + "plugin:@typescript-eslint/recommended", + "prettier", + ], + parser: "@typescript-eslint/parser", + parserOptions: { + ecmaVersion: "latest", + sourceType: "module", + project: ["./tsconfig.json", "./**/{t,j}sconfig.json"], + }, + plugins: ["@typescript-eslint"], + }, + ], + ignorePatterns: ["./**/node_modules", "node_modules", "./**/lib", "lib"], + rules: {}, +}; diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 9993b3b85..c3debeb60 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -1,5 +1,5 @@ name: Build -on: +on: pull_request: push: branches: diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index 5f0ab3844..b12360888 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -1,5 +1,5 @@ name: Examples -on: +on: pull_request: push: branches: @@ -39,4 +39,4 @@ jobs: - name: status-message run: cd examples && yarn build:status-message && yarn test:status-message - name: parking-lot - run: cd examples && yarn build:parking-lot && yarn test:parking-lot \ No newline at end of file + run: cd examples && yarn build:parking-lot && yarn test:parking-lot diff --git a/.github/workflows/unit-test.yml b/.github/workflows/unit-test.yml index 091dde193..bb7e0c78d 100644 --- a/.github/workflows/unit-test.yml +++ b/.github/workflows/unit-test.yml @@ -1,5 +1,5 @@ name: Unit tests -on: +on: pull_request: push: branches: diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 000000000..83dbaee65 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,3 @@ +node_modules +lib + diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index 9a6c5006d..d503f2f6f 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -14,22 +14,22 @@ appearance, race, religion, or sexual identity and orientation. Examples of behavior that contributes to creating a positive environment include: -* Using welcoming and inclusive language -* Being respectful of differing viewpoints and experiences -* Gracefully accepting constructive criticism -* Focusing on what is best for the community -* Showing empathy towards other community members +- Using welcoming and inclusive language +- Being respectful of differing viewpoints and experiences +- Gracefully accepting constructive criticism +- Focusing on what is best for the community +- Showing empathy towards other community members Examples of unacceptable behavior by participants include: -* The use of sexualized language or imagery and unwelcome sexual attention or - advances -* Trolling, insulting/derogatory comments, and personal or political attacks -* Public or private harassment -* Publishing others' private information, such as a physical or electronic - address, without explicit permission -* Other conduct which could reasonably be considered inappropriate in a - professional setting +- The use of sexualized language or imagery and unwelcome sexual attention or + advances +- Trolling, insulting/derogatory comments, and personal or political attacks +- Public or private harassment +- Publishing others' private information, such as a physical or electronic + address, without explicit permission +- Other conduct which could reasonably be considered inappropriate in a + professional setting ## Our Responsibilities diff --git a/README.md b/README.md index 9bbc9d2ce..8771126ff 100644 --- a/README.md +++ b/README.md @@ -11,6 +11,7 @@ This will scaffold a basic template for you 😎 Learn more in our [Quick Start guide](https://docs.near.org/develop/quickstart-guide). ## Running Examples + There are a couple of contract examples in the project: - [Clean contract state](https://github.com/near/near-sdk-js/tree/develop/examples/src/clean-state.js) @@ -30,6 +31,7 @@ To build all examples, run `yarn build` in `examples/`. To test all examples, ru To deploy and call a contract on a NEAR node, use near-cli's `near deploy` and `near call`. ## Test + We recommend to use near-workspaces to write tests for your smart contracts. See any of the examples for how tests are setup and written. ## Error Handling in NEAR-SDK-JS @@ -38,23 +40,21 @@ If you want to indicate an error happened and fail the transaction, just throw a When your JS code or library throws an error, uncaught, the transaction will also fail with GuestPanic error, with the error message and stacktrace. -When call host function with inappropriate type, means incorrect number of arguments or arg is not expected type: - - if arguments less than params, remaining argument are set as 'undefined' - - if arguments more than params, remaining argument are ignored - - if argument is different than the required type, it'll be coerced to required type - - if argument is different than the required type but cannot be coerced, will throw runtime type error, also with message and stacktrace +When call host function with inappropriate type, means incorrect number of arguments or arg is not expected type: - if arguments less than params, remaining argument are set as 'undefined' - if arguments more than params, remaining argument are ignored - if argument is different than the required type, it'll be coerced to required type - if argument is different than the required type but cannot be coerced, will throw runtime type error, also with message and stacktrace ## NEAR-SDK-JS API Reference All NEAR blockchain provided functionality (host functions) are defined in `src/api.ts` and exported as `near`. You can use them by: + ```js -import {near} from 'near-sdk-js' +import { near } from "near-sdk-js"; // near.. e.g.: -let signer = near.signerAccountId() +let signer = near.signerAccountId(); ``` To use nightly host functions, such as `altBn128G1Sum`, your contract need to be built with nightly enabled. Use: + ``` export NEAR_NIGHTLY=1 yarn build @@ -63,10 +63,11 @@ yarn build ### About Type NEAR-SDK-JS is written in TypeScript, so every API function has a type specified by signature that looks familiar to JavaScript/TypeScript Developers. Two types in the signature need a special attention: + - Most of the API take `bigint` instead of Number as type. This because JavaScript Number cannot hold 64 bit and 128 bit integer without losing precision. - `Bytes` in both arguments and return represent a byte buffer, internally it's a JavaScript String Object. Any binary data `0x00-0xff` is stored as the char '\x00-\xff'. This is because QuickJS doesn't have Uint8Array in C API. - - To ensure correctness, every `Bytes` argument need to be pass in with the `bytes()` function to runtime type check it's indeed a `Bytes`. - - If `Bytes` is too long that `bytes()` can cause gas limit problem, such as in factory contract, represents the content of contract to be deployed. In this case you can precheck and guarantee the correctness of the content and use without `bytes()`. + - To ensure correctness, every `Bytes` argument need to be pass in with the `bytes()` function to runtime type check it's indeed a `Bytes`. + - If `Bytes` is too long that `bytes()` can cause gas limit problem, such as in factory contract, represents the content of contract to be deployed. In this case you can precheck and guarantee the correctness of the content and use without `bytes()`. ### Context API @@ -84,6 +85,7 @@ function storageUsage(): bigint ``` ### Economics API + ``` function accountBalance(): bigint; function accountLockedBalance(): bigint; @@ -94,7 +96,6 @@ function usedGas(): bigint; ### Math API - ``` function randomSeed(): Bytes; function sha256(value: Bytes): Bytes; @@ -106,7 +107,6 @@ function ecrecover(hash: Bytes, sign: Bytes, v: bigint, malleability_flag: bigin ### Miscellaneous API - ``` function valueReturn(value: Bytes); function panic(msg?: string); @@ -175,6 +175,7 @@ function altBn128PairingCheck(value: Bytes): bigint; ``` ### NearBindgen and other decorators + You can write a simple smart contract by only using low-level APIs, such as `near.input()`, `near.storageRead()`, etc. In this case, the API of your contract will consist of all the exported JS functions. You can find an example of such a contract [here](https://github.com/near/near-sdk-js/blob/develop/examples/src/counter-lowlevel.js). But if you want to build a more complex contracts with ease, you can use decorators from this SDK that will handle serialization, deserialization, and other boilerplate operations for you. @@ -186,6 +187,7 @@ Your class must have a `constructor()`. You will not be able to call it, which i The simplest example of the contract that follows all these rules can be found [here](https://github.com/near/near-sdk-js/blob/develop/examples/src/status-message.js) `NearBindgen` decorator can accept `requireInit parameter`. + ```JS @NearBindgen({ requireInit: true }) class YourContract { @@ -201,13 +203,14 @@ In order to initialize the contract, you need to add functions flagged with `@in `privateFunction: true` can restrict access to this function to the contract itself. -`payableFunction: true` will allow the function to accept payments (deposit). Without this flag, it will panic if any deposit was provided. - +`payableFunction: true` will allow the function to accept payments (deposit). Without this flag, it will panic if any deposit was provided. ### Collections + A few useful on-chain persistent collections are provided. All keys, values and elements are of type `Bytes`. #### Vector + Vector is an iterable implementation of vector that stores its content on the trie. Usage: ```js @@ -238,7 +241,7 @@ someMethod() { let first = this.v.get(0) // remove, move the last element to the given index - this.v.swapRemove(0) + this.v.swapRemove(0) // replace this.v.replace(1, 'jkl') @@ -264,7 +267,9 @@ someMethod() { ``` #### LookupMap + LookupMap is an non-iterable implementation of a map that stores its content directly on the trie. It's like a big hash map, but on trie. Usage: + ```js import {LookupMap} from 'near-sdk-js' @@ -296,7 +301,7 @@ someMethod() { let value = this.m.get('abc') // remove - this.m.remove('def') + this.m.remove('def') // replace this.m.set('ghi', 'ddd') @@ -304,7 +309,9 @@ someMethod() { ``` #### LookupSet + LookupSet is an non-iterable implementation of a set that stores its content directly on the trie. It's like LookupMap, but it only stores whether the value presents. Usage: + ```js import {LookupSet} from 'near-sdk-js' @@ -338,7 +345,9 @@ someMethod() { ``` #### UnorderedMap + UnorderedMap is an iterable implementation of a map that stores its content directly on the trie. Usage: + ```js import {UnorderedMap} from 'near-sdk-js' @@ -369,7 +378,7 @@ someMethod() { let value = this.m.get('abc') // remove - this.m.remove('def') + this.m.remove('def') // replace this.m.set('ghi', 'ddd') @@ -392,7 +401,9 @@ someMethod() { ``` #### UnorderedSet + UnorderedSet is an iterable implementation of a set that stores its content directly on the trie. It's like UnorderedMap but it only stores whether the value presents. Usage: + ```js import {UnorderedSet} from 'near-sdk-js' @@ -442,40 +453,50 @@ someMethod() { ``` ### Highlevel Promise APIs -Within a contract class that decorated by `@Nearbindgen`, you can work a high level JavaScript class, called `NearPromise`. It's equivalently expressive as promise batch APIs but much shorter to write and can be chained like a JavaScript Promise. + +Within a contract class that decorated by `@Nearbindgen`, you can work a high level JavaScript class, called `NearPromise`. It's equivalently expressive as promise batch APIs but much shorter to write and can be chained like a JavaScript Promise. In a `@call` method, you can return either a JavaScript value or a `NearPromise` object. In the later case, `@NearBindgen` will automatically `promiseReturn` it for you. Usage: + ```js // create new promise -import {NearPromise, near} from 'near-sdk-js' -import { PublicKey } from 'near-sdk-js/lib/types' +import { NearPromise, near } from "near-sdk-js"; +import { PublicKey } from "near-sdk-js/lib/types"; -let promise = NearPromise.new('account-to-run-promise') +let promise = NearPromise.new("account-to-run-promise"); // possible promise actions, choose and chain what you need: -promise.createAccount() - .transfer(1_000_000_000_000_000_000_000_000_000_000_000_000n) - .addFullAccessKey(new PublicKey(near.signerAccountPk())) - .addAccessKey(new PublicKey(near.signerAccountPk()), 250000000000000000000000n, // allowance - 'receiver_account_id', 'allowed_function_names') - .stake(100000000000000000000000000000n, new PublicKey(near.signerAccountPk())) - .deployContract(includeBytes('path/to/contract.wasm')) - .functionCall('callee_contract_account_id', inputArgs, - 0, // amount - 2 * Math.pow(10, 13), // gas - ) - .functionCallWeight( - 'callee_contract_account_id', inputArgs, - 0, // amount - 2 * Math.pow(10, 13), // gas - 1, // weight - ) - .deleteKey(new PublicKey(near.signerAccountPk())) - .deleteAccount('beneficial_account_id') - -return promise +promise + .createAccount() + .transfer(1_000_000_000_000_000_000_000_000_000_000_000_000n) + .addFullAccessKey(new PublicKey(near.signerAccountPk())) + .addAccessKey( + new PublicKey(near.signerAccountPk()), + 250000000000000000000000n, // allowance + "receiver_account_id", + "allowed_function_names" + ) + .stake(100000000000000000000000000000n, new PublicKey(near.signerAccountPk())) + .deployContract(includeBytes("path/to/contract.wasm")) + .functionCall( + "callee_contract_account_id", + inputArgs, + 0, // amount + 2 * Math.pow(10, 13) // gas + ) + .functionCallWeight( + "callee_contract_account_id", + inputArgs, + 0, // amount + 2 * Math.pow(10, 13), // gas + 1 // weight + ) + .deleteKey(new PublicKey(near.signerAccountPk())) + .deleteAccount("beneficial_account_id"); + +return promise; ``` In the case of deploy contract, `includeBytes` is a helpful build-time util. You can include the content of a wasm contract, by using `includeBytes('path/to/contract.wasm')`. @@ -483,11 +504,12 @@ In the case of deploy contract, `includeBytes` is a helpful build-time util. You In the case of `addFullAccessKey`, `addAccessKey` and `stake`, it takes a `PublicKey` object, you can find more details about it in the Types sections below. Besides above APIs to build something on top of an API, you can also chain promises with `.then` and `.and`, they're equivalent to promiseThen, promiseAnd: + ```js // assume promise, promise2 and promise3 are create with above APIs, with several actions added like above. -promise.and(promise2).then(promise3) // promiseAnd of [promise_id, promise2_id], then promiseThen(promise_and_id, promise3_id) +promise.and(promise2).then(promise3); // promiseAnd of [promise_id, promise2_id], then promiseThen(promise_and_id, promise3_id) -return promise +return promise; ``` ### Types @@ -495,14 +517,19 @@ return promise NEAR-SDK-JS also includes type defintions that are equivalent to that in Rust SDK / nearcore. You can browse them in near-sdk-js/src/types. Most of them are just type alias to Bytes and bigint. #### Public Key -Public Key is representing a NEAR account's public key in a JavaScript class. You can either initiate a Public Key from binary data, or from a human readable string. + +Public Key is representing a NEAR account's public key in a JavaScript class. You can either initiate a Public Key from binary data, or from a human readable string. The binary data is in the same format as nearcore, but encoded in bytes. That's one byte to represent the curve type of the public key, either ed25519 (`\x00`), or secp256k1 ('\x01'), follows by the curve-specific public key data in bytes. Examples: ```js -new PublicKey(near.signerAccountPk()) -new PublicKey("\x00\xeb\x7f\x5f\x11\xd1\x08\x1f\xe0\xd2\x24\xc5\x67\x36\x21\xad\xcb\x97\xd5\x13\xff\xa8\x5e\x55\xbc\x2b\x74\x4f\x0d\xb1\xe9\xf8\x1f") -new PublicKey("\x01\xf2\x56\xc6\xe6\xc8\x0b\x21\x3f\x2a\xa0\xb0\x17\x44\x23\x5d\x51\x5c\x59\x44\x35\xbe\x65\x1b\x15\x88\x3a\x10\xdd\x47\x2f\xa6\x46\xce\x62\xea\xf3\x67\x0d\xc5\xcb\x91\x00\xa0\xca\x2a\x55\xb2\xc1\x47\xc1\xe9\xa3\x8c\xe4\x28\x87\x8e\x7d\x46\xe1\xfb\x71\x4a\x99") +new PublicKey(near.signerAccountPk()); +new PublicKey( + "\x00\xeb\x7f\x5f\x11\xd1\x08\x1f\xe0\xd2\x24\xc5\x67\x36\x21\xad\xcb\x97\xd5\x13\xff\xa8\x5e\x55\xbc\x2b\x74\x4f\x0d\xb1\xe9\xf8\x1f" +); +new PublicKey( + "\x01\xf2\x56\xc6\xe6\xc8\x0b\x21\x3f\x2a\xa0\xb0\x17\x44\x23\x5d\x51\x5c\x59\x44\x35\xbe\x65\x1b\x15\x88\x3a\x10\xdd\x47\x2f\xa6\x46\xce\x62\xea\xf3\x67\x0d\xc5\xcb\x91\x00\xa0\xca\x2a\x55\xb2\xc1\x47\xc1\xe9\xa3\x8c\xe4\x28\x87\x8e\x7d\x46\xe1\xfb\x71\x4a\x99" +); ``` The human readable form is `ed25519:` or `secp256k1:` following base58-encoded public key. And initialize the Public Key with `PublicKey.fromString`: @@ -512,4 +539,4 @@ PublicKey.fromString('ed25519:DXkVZkHd7WUUejCK7i74uAoZWy1w9AZqshhTHxhmqHuB`) PublicKey.fromString('secp256k1:5r22SrjrDvgY3wdQsnjgxkeAbU1VcM71FYvALEQWihjM3Xk4Be1CpETTqFccChQr4iJwDroSDVmgaWZv2AcXvYeL`) ``` -Once a PublicKey object is created, it can be used in high level promise APIs that takes a public key, such as `addFullAccessKey`, `addAccessKey` and `stake`. \ No newline at end of file +Once a PublicKey object is created, it can be used in high level promise APIs that takes a public key, such as `addFullAccessKey`, `addAccessKey` and `stake`. diff --git a/cli/cli.js b/cli/cli.js index a87385e77..9a8124f3c 100755 --- a/cli/cli.js +++ b/cli/cli.js @@ -1,146 +1,163 @@ #!/usr/bin/env node -import fs from 'fs/promises' -import path from 'path'; +import fs from "fs/promises"; +import path from "path"; -import yargs from 'yargs' -import { hideBin } from 'yargs/helpers' +import yargs from "yargs"; +import { hideBin } from "yargs/helpers"; -import { nodeResolve } from '@rollup/plugin-node-resolve'; -import sourcemaps from 'rollup-plugin-sourcemaps'; -import { babel } from '@rollup/plugin-babel'; -import { rollup } from 'rollup'; +import { nodeResolve } from "@rollup/plugin-node-resolve"; +import sourcemaps from "rollup-plugin-sourcemaps"; +import { babel } from "@rollup/plugin-babel"; +import { rollup } from "rollup"; -import { executeCommand } from './utils.js'; +import { executeCommand } from "./utils.js"; const PROJECT_DIR = process.cwd(); -const NEAR_SDK_JS = 'node_modules/near-sdk-js'; -const TSC = 'node_modules/.bin/tsc'; +const NEAR_SDK_JS = "node_modules/near-sdk-js"; +const TSC = "node_modules/.bin/tsc"; const QJSC_DIR = `${NEAR_SDK_JS}/cli/deps/quickjs`; const QJSC = `${NEAR_SDK_JS}/cli/deps/qjsc`; yargs(hideBin(process.argv)) - .scriptName('near-sdk-js') - .usage('$0 [args]') - .command('build [source] [target]', 'Build NEAR JS Smart-contract', (yargs) => { - yargs - .positional('source', { - type: 'string', - default: 'src/index.js', - describe: 'Contract to build' - }) - .positional('target', { - type: 'string', - default: 'build/contract.wasm', - describe: 'Target file path and name' - }) - }, build) - .help() - .argv + .scriptName("near-sdk-js") + .usage("$0 [args]") + .command( + "build [source] [target]", + "Build NEAR JS Smart-contract", + (yargs) => { + yargs + .positional("source", { + type: "string", + default: "src/index.js", + describe: "Contract to build", + }) + .positional("target", { + type: "string", + default: "build/contract.wasm", + describe: "Target file path and name", + }); + }, + build + ) + .help().argv; async function build(argv) { - const SOURCE_FILE_WITH_PATH = argv.source; - const SOURCE_EXT = argv.source.split('.').pop(); - const TARGET_DIR = path.dirname(argv.target); - const TARGET_EXT = argv.target.split('.').pop(); - const TARGET_FILE_NAME = path.basename(argv.target, `.${TARGET_EXT}`); + const SOURCE_FILE_WITH_PATH = argv.source; + const SOURCE_EXT = argv.source.split(".").pop(); + const TARGET_DIR = path.dirname(argv.target); + const TARGET_EXT = argv.target.split(".").pop(); + const TARGET_FILE_NAME = path.basename(argv.target, `.${TARGET_EXT}`); - if (!["wasm"].includes(TARGET_EXT)) { - throw new Error(`Unsupported target ${TARGET_EXT}, make sure target ends with .wasm`); - } + if (!["wasm"].includes(TARGET_EXT)) { + throw new Error( + `Unsupported target ${TARGET_EXT}, make sure target ends with .wasm` + ); + } - const ROLLUP_TARGET = `${TARGET_DIR}/${TARGET_FILE_NAME}.js`; - const QJSC_TARGET = `${TARGET_DIR}/${TARGET_FILE_NAME}.h`; - const CONTRACT_TARGET = `${TARGET_DIR}/${TARGET_FILE_NAME}.wasm`; + const ROLLUP_TARGET = `${TARGET_DIR}/${TARGET_FILE_NAME}.js`; + const QJSC_TARGET = `${TARGET_DIR}/${TARGET_FILE_NAME}.h`; + const CONTRACT_TARGET = `${TARGET_DIR}/${TARGET_FILE_NAME}.wasm`; - console.log(`Building ${SOURCE_FILE_WITH_PATH} contract...`); + console.log(`Building ${SOURCE_FILE_WITH_PATH} contract...`); - if (SOURCE_EXT === 'ts') { - await checkTsBuildWithTsc(SOURCE_FILE_WITH_PATH); - } + if (SOURCE_EXT === "ts") { + await checkTsBuildWithTsc(SOURCE_FILE_WITH_PATH); + } - console.log(`Creating ${TARGET_DIR} directory...`); - await executeCommand(`mkdir -p ${TARGET_DIR}`); + console.log(`Creating ${TARGET_DIR} directory...`); + await executeCommand(`mkdir -p ${TARGET_DIR}`); - await createJsFileWithRullup(SOURCE_FILE_WITH_PATH, ROLLUP_TARGET); + await createJsFileWithRullup(SOURCE_FILE_WITH_PATH, ROLLUP_TARGET); - await createHeaderFileWithQjsc(ROLLUP_TARGET, QJSC_TARGET); + await createHeaderFileWithQjsc(ROLLUP_TARGET, QJSC_TARGET); - await createMethodsHeaderFile(ROLLUP_TARGET); - await createWasmContract(QJSC_TARGET, CONTRACT_TARGET); - await wasiStubContract(CONTRACT_TARGET); + await createMethodsHeaderFile(ROLLUP_TARGET); + await createWasmContract(QJSC_TARGET, CONTRACT_TARGET); + await wasiStubContract(CONTRACT_TARGET); } async function checkTsBuildWithTsc(sourceFileWithPath) { - console.log(`check TypeScript build of ${sourceFileWithPath} with tsc`) - await executeCommand(`${TSC} --noEmit --experimentalDecorators --target es2020 --moduleResolution node ${sourceFileWithPath}`); + console.log(`check TypeScript build of ${sourceFileWithPath} with tsc`); + await executeCommand( + `${TSC} --noEmit --experimentalDecorators --target es2020 --moduleResolution node ${sourceFileWithPath}` + ); } // Common build function async function createJsFileWithRullup(sourceFileWithPath, rollupTarget) { - console.log(`Creating ${rollupTarget} file with Rollup...`); - const bundle = await rollup({ - input: sourceFileWithPath, - plugins: [ - nodeResolve({ - extensions: ['.js', '.ts'] - }), - sourcemaps(), - // commonjs(), - babel({ babelHelpers: 'bundled', extensions: ['.ts', '.js', '.jsx', '.es6', '.es', '.mjs'] }) - ], - }); - - await bundle.write({ - sourcemap: true, - file: rollupTarget, - format: 'es' - }); + console.log(`Creating ${rollupTarget} file with Rollup...`); + const bundle = await rollup({ + input: sourceFileWithPath, + plugins: [ + nodeResolve({ + extensions: [".js", ".ts"], + }), + sourcemaps(), + // commonjs(), + babel({ + babelHelpers: "bundled", + extensions: [".ts", ".js", ".jsx", ".es6", ".es", ".mjs"], + }), + ], + }); + + await bundle.write({ + sourcemap: true, + file: rollupTarget, + format: "es", + }); } async function createHeaderFileWithQjsc(rollupTarget, qjscTarget) { - console.log(`Creating ${qjscTarget} file with QJSC...`); - await executeCommand(`${QJSC} -c -m -o ${qjscTarget} -N code ${rollupTarget}`); + console.log(`Creating ${qjscTarget} file with QJSC...`); + await executeCommand( + `${QJSC} -c -m -o ${qjscTarget} -N code ${rollupTarget}` + ); } async function createMethodsHeaderFile(rollupTarget) { - console.log(`Genereting methods.h file`); - let source = rollupTarget; - const buildPath = path.dirname(source); - console.log(rollupTarget) - let mod = await import(`${PROJECT_DIR}/${rollupTarget}`); - let exportNames = Object.keys(mod); - let methods = ''; - for (let name of exportNames) { - methods += `DEFINE_NEAR_METHOD(${name})\n`; - } - await fs.writeFile(`${buildPath}/methods.h`, methods); + console.log(`Genereting methods.h file`); + let source = rollupTarget; + const buildPath = path.dirname(source); + console.log(rollupTarget); + let mod = await import(`${PROJECT_DIR}/${rollupTarget}`); + let exportNames = Object.keys(mod); + let methods = ""; + for (let name of exportNames) { + methods += `DEFINE_NEAR_METHOD(${name})\n`; + } + await fs.writeFile(`${buildPath}/methods.h`, methods); } async function createWasmContract(qjscTarget, contractTarget) { - console.log(`Creating ${contractTarget} contract...`); - const WASI_SDK_PATH = `${NEAR_SDK_JS}/cli/deps/wasi-sdk`; - - const CC = `${WASI_SDK_PATH}/bin/clang --sysroot=${WASI_SDK_PATH}/share/wasi-sysroot` - let DEFS = `-D_GNU_SOURCE '-DCONFIG_VERSION="2021-03-27"' -DCONFIG_BIGNUM` - if (process.env.NEAR_NIGHTLY) { - DEFS = DEFS + ' -DNIGHTLY' - } - const INCLUDES = `-I${QJSC_DIR} -I.` - const ORIGINAL_BUILDER_PATH = `${NEAR_SDK_JS}/cli/builder/builder.c`; - const NEW_BUILDER_PATH = `${path.dirname(contractTarget)}/builder.c` - const SOURCES = `${NEW_BUILDER_PATH} ${QJSC_DIR}/quickjs.c ${QJSC_DIR}/libregexp.c ${QJSC_DIR}/libunicode.c ${QJSC_DIR}/cutils.c ${QJSC_DIR}/quickjs-libc-min.c ${QJSC_DIR}/libbf.c`; - const LIBS = `-lm` - - // copying builder.c file to the build folder - await executeCommand(`cp ${ORIGINAL_BUILDER_PATH} ${NEW_BUILDER_PATH}`); - await executeCommand(`mv ${qjscTarget} build/code.h`); - - await executeCommand(`${CC} --target=wasm32-wasi -nostartfiles -Oz -flto ${DEFS} ${INCLUDES} ${SOURCES} ${LIBS} -Wl,--no-entry -Wl,--allow-undefined -Wl,-z,stack-size=${256 * 1024} -Wl,--lto-O3 -o ${contractTarget}`); + console.log(`Creating ${contractTarget} contract...`); + const WASI_SDK_PATH = `${NEAR_SDK_JS}/cli/deps/wasi-sdk`; + + const CC = `${WASI_SDK_PATH}/bin/clang --sysroot=${WASI_SDK_PATH}/share/wasi-sysroot`; + let DEFS = `-D_GNU_SOURCE '-DCONFIG_VERSION="2021-03-27"' -DCONFIG_BIGNUM`; + if (process.env.NEAR_NIGHTLY) { + DEFS = DEFS + " -DNIGHTLY"; + } + const INCLUDES = `-I${QJSC_DIR} -I.`; + const ORIGINAL_BUILDER_PATH = `${NEAR_SDK_JS}/cli/builder/builder.c`; + const NEW_BUILDER_PATH = `${path.dirname(contractTarget)}/builder.c`; + const SOURCES = `${NEW_BUILDER_PATH} ${QJSC_DIR}/quickjs.c ${QJSC_DIR}/libregexp.c ${QJSC_DIR}/libunicode.c ${QJSC_DIR}/cutils.c ${QJSC_DIR}/quickjs-libc-min.c ${QJSC_DIR}/libbf.c`; + const LIBS = `-lm`; + + // copying builder.c file to the build folder + await executeCommand(`cp ${ORIGINAL_BUILDER_PATH} ${NEW_BUILDER_PATH}`); + await executeCommand(`mv ${qjscTarget} build/code.h`); + + await executeCommand( + `${CC} --target=wasm32-wasi -nostartfiles -Oz -flto ${DEFS} ${INCLUDES} ${SOURCES} ${LIBS} -Wl,--no-entry -Wl,--allow-undefined -Wl,-z,stack-size=${ + 256 * 1024 + } -Wl,--lto-O3 -o ${contractTarget}` + ); } async function wasiStubContract(contractTarget) { - console.log(`Executing wasi-stub...`); - const WASI_STUB = `${NEAR_SDK_JS}/cli/deps/binaryen/wasi-stub/run.sh`; - await executeCommand(`${WASI_STUB} ${contractTarget} >/dev/null`); + console.log(`Executing wasi-stub...`); + const WASI_STUB = `${NEAR_SDK_JS}/cli/deps/binaryen/wasi-stub/run.sh`; + await executeCommand(`${WASI_STUB} ${contractTarget} >/dev/null`); } diff --git a/cli/post-install.js b/cli/post-install.js index 557f4785e..7411952d7 100644 --- a/cli/post-install.js +++ b/cli/post-install.js @@ -1,70 +1,86 @@ -import { executeCommand } from './utils.js'; +import { executeCommand } from "./utils.js"; async function download(url) { - await executeCommand(`curl -LOf ${url}`); + await executeCommand(`curl -LOf ${url}`); } -const OS = await executeCommand('uname -s', true); -const ARCH = await executeCommand('uname -m', true); +const OS = await executeCommand("uname -s", true); +const ARCH = await executeCommand("uname -m", true); -if (OS !== 'Linux' && OS !== 'Darwin') { - console.error(`OS ${OS} is not supported at the moment`); - process.exit(1); +if (OS !== "Linux" && OS !== "Darwin") { + console.error(`OS ${OS} is not supported at the moment`); + process.exit(1); } -if (ARCH !== 'x86_64' && ARCH !== 'arm64') { - console.error(` ${ARCH} architecture is unsapported at the moment`); - process.exit(1); +if (ARCH !== "x86_64" && ARCH !== "arm64") { + console.error(` ${ARCH} architecture is unsapported at the moment`); + process.exit(1); } -console.log('Installing wasi-stub...'); +console.log("Installing wasi-stub..."); const BINARYEN_VERSION = `0.1.10`; const BINARYEN_VERSION_TAG = `v${BINARYEN_VERSION}`; -const BINARYEN_SYSTEM_NAME = OS === 'Linux' ? 'Linux' : OS === 'Darwin' ? 'macOS' : 'other'; -const BINARYEN_ARCH_NAME = ARCH === 'x86_64' ? 'X64' : ARCH === 'arm64' ? 'arm64' : 'other'; +const BINARYEN_SYSTEM_NAME = + OS === "Linux" ? "Linux" : OS === "Darwin" ? "macOS" : "other"; +const BINARYEN_ARCH_NAME = + ARCH === "x86_64" ? "X64" : ARCH === "arm64" ? "arm64" : "other"; const BINARYEN_TAR_NAME = `binaryen-${BINARYEN_SYSTEM_NAME}-${BINARYEN_ARCH_NAME}.tar.gz`; -await download(`https://github.com/near/binaryen/releases/download/${BINARYEN_VERSION_TAG}/${BINARYEN_TAR_NAME}`); -await executeCommand(`mkdir -p binaryen && tar xvf ${BINARYEN_TAR_NAME} --directory binaryen`); +await download( + `https://github.com/near/binaryen/releases/download/${BINARYEN_VERSION_TAG}/${BINARYEN_TAR_NAME}` +); +await executeCommand( + `mkdir -p binaryen && tar xvf ${BINARYEN_TAR_NAME} --directory binaryen` +); await executeCommand(`rm ${BINARYEN_TAR_NAME}`); -console.log('Installing QuickJS...'); +console.log("Installing QuickJS..."); const QUICK_JS_VERSION = `0.1.1`; const QUICK_JS_VERSION_TAG = `v${QUICK_JS_VERSION}`; -const QUICK_JS_SYSTEM_NAME = OS === 'Linux' ? 'Linux' : OS === 'Darwin' ? 'macOS' : 'other'; -const QUICK_JS_ARCH_NAME = ARCH === 'x86_64' ? 'X64' : ARCH === 'arm64' ? 'arm64' : 'other'; -const QUICK_JS_TAR_NAME = `${QUICK_JS_VERSION_TAG}.tar.gz` -const QUICK_JS_DOWNLOADED_FOLDER_NAME = `quickjs-${QUICK_JS_VERSION}` -const QUICK_JS_TARGET_FOLDER_NAME = 'quickjs'; -const QUICK_JS_DOWNLOADED_NAME = `qjsc-${QUICK_JS_SYSTEM_NAME}-${QUICK_JS_ARCH_NAME}` -const QUICK_JS_TARGET_NAME = 'qjsc'; +const QUICK_JS_SYSTEM_NAME = + OS === "Linux" ? "Linux" : OS === "Darwin" ? "macOS" : "other"; +const QUICK_JS_ARCH_NAME = + ARCH === "x86_64" ? "X64" : ARCH === "arm64" ? "arm64" : "other"; +const QUICK_JS_TAR_NAME = `${QUICK_JS_VERSION_TAG}.tar.gz`; +const QUICK_JS_DOWNLOADED_FOLDER_NAME = `quickjs-${QUICK_JS_VERSION}`; +const QUICK_JS_TARGET_FOLDER_NAME = "quickjs"; +const QUICK_JS_DOWNLOADED_NAME = `qjsc-${QUICK_JS_SYSTEM_NAME}-${QUICK_JS_ARCH_NAME}`; +const QUICK_JS_TARGET_NAME = "qjsc"; // Download QuickJS -await download(`https://github.com/near/quickjs/releases/download/${QUICK_JS_VERSION_TAG}/qjsc-${QUICK_JS_SYSTEM_NAME}-${QUICK_JS_ARCH_NAME}`); -await download(`https://github.com/near/quickjs/archive/refs/tags/${QUICK_JS_VERSION_TAG}.tar.gz`); +await download( + `https://github.com/near/quickjs/releases/download/${QUICK_JS_VERSION_TAG}/qjsc-${QUICK_JS_SYSTEM_NAME}-${QUICK_JS_ARCH_NAME}` +); +await download( + `https://github.com/near/quickjs/archive/refs/tags/${QUICK_JS_VERSION_TAG}.tar.gz` +); // Extract QuickJS await executeCommand(`tar xvf ${QUICK_JS_TAR_NAME}`); // Delete .tar file await executeCommand(`rm ${QUICK_JS_TAR_NAME}`); // Delete version from folder name -await executeCommand(`mv ${QUICK_JS_DOWNLOADED_FOLDER_NAME} ${QUICK_JS_TARGET_FOLDER_NAME}`); +await executeCommand( + `mv ${QUICK_JS_DOWNLOADED_FOLDER_NAME} ${QUICK_JS_TARGET_FOLDER_NAME}` +); // Rename qjsc file await executeCommand(`mv ${QUICK_JS_DOWNLOADED_NAME} ${QUICK_JS_TARGET_NAME}`); // chmod qjsc await executeCommand(`chmod 777 ${QUICK_JS_TARGET_NAME}`); -console.log('Installing wasi-sdk...'); +console.log("Installing wasi-sdk..."); const WASI_SDK_MAJOR_VER = 11; const WASI_SDK_MINOR_VER = 0; -const WASI_SDK_DOWNLOADED_FOLDER_NAME = `wasi-sdk-${WASI_SDK_MAJOR_VER}.${WASI_SDK_MINOR_VER}` -const WASI_SDK_SYSTEM_NAME = OS === 'Linux' ? 'linux' : OS === 'Darwin' ? 'macos' : 'other'; -const WASI_SDK_TAR_NAME = `${WASI_SDK_DOWNLOADED_FOLDER_NAME}-${WASI_SDK_SYSTEM_NAME}.tar.gz` +const WASI_SDK_DOWNLOADED_FOLDER_NAME = `wasi-sdk-${WASI_SDK_MAJOR_VER}.${WASI_SDK_MINOR_VER}`; +const WASI_SDK_SYSTEM_NAME = + OS === "Linux" ? "linux" : OS === "Darwin" ? "macos" : "other"; +const WASI_SDK_TAR_NAME = `${WASI_SDK_DOWNLOADED_FOLDER_NAME}-${WASI_SDK_SYSTEM_NAME}.tar.gz`; // Download WASI SDK -await download(`https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${WASI_SDK_MAJOR_VER}/${WASI_SDK_TAR_NAME}`); +await download( + `https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${WASI_SDK_MAJOR_VER}/${WASI_SDK_TAR_NAME}` +); // Extract WASI SDK await executeCommand(`tar xvf ${WASI_SDK_TAR_NAME}`); // Delete .tar file await executeCommand(`rm ${WASI_SDK_TAR_NAME}`); // Delete version from folder name await executeCommand(`mv ${WASI_SDK_DOWNLOADED_FOLDER_NAME} wasi-sdk`); - diff --git a/cli/save_bytecode.js b/cli/save_bytecode.js index 97fec0b82..4f3f6aab5 100644 --- a/cli/save_bytecode.js +++ b/cli/save_bytecode.js @@ -1,23 +1,22 @@ -import fs from 'fs/promises' -import path from 'path' - +import fs from "fs/promises"; +import path from "path"; //TODO: execute it in js env async function main() { - let source = path.resolve(process.argv[process.argv.length-2]) - let target = path.resolve(process.argv[process.argv.length-1]) - let code = await fs.readFile(source, 'utf-8') - let lines = code.split('\n') - let codes = [] - for (let line of lines) { - if (line.indexOf('0x') >= 0) { - let nums = line.trim() - nums = nums.slice(0, nums.length - 1).split(', ') - codes.push(nums.map(Number)) - } + let source = path.resolve(process.argv[process.argv.length - 2]); + let target = path.resolve(process.argv[process.argv.length - 1]); + let code = await fs.readFile(source, "utf-8"); + let lines = code.split("\n"); + let codes = []; + for (let line of lines) { + if (line.indexOf("0x") >= 0) { + let nums = line.trim(); + nums = nums.slice(0, nums.length - 1).split(", "); + codes.push(nums.map(Number)); } - let bytecode = Buffer.concat(codes.map(Buffer.from)) - await fs.writeFile(target, bytecode.toString('base64')) + } + let bytecode = Buffer.concat(codes.map(Buffer.from)); + await fs.writeFile(target, bytecode.toString("base64")); } -main() \ No newline at end of file +main(); diff --git a/cli/utils.js b/cli/utils.js index 37b29fc23..4014ea265 100644 --- a/cli/utils.js +++ b/cli/utils.js @@ -1,23 +1,23 @@ -import { exec as exec_ } from 'child_process'; -import { promisify } from 'util'; +import { exec as exec_ } from "child_process"; +import { promisify } from "util"; const exec = promisify(exec_); export async function executeCommand(command, silent = false) { - console.log(command); - const { error, stdout, stderr } = await exec(command); + console.log(command); + const { error, stdout, stderr } = await exec(command); - if (error) { - console.log(error); - process.exit(1); - } - if (stderr && !silent) { - console.error(stderr); - } + if (error) { + console.log(error); + process.exit(1); + } + if (stderr && !silent) { + console.error(stderr); + } - if (silent) { - return stdout.trim(); - } else { - console.log(stdout); - } -} \ No newline at end of file + if (silent) { + return stdout.trim(); + } else { + console.log(stdout); + } +} diff --git a/cli/wasm_to_bytes.js b/cli/wasm_to_bytes.js index 109683da2..f40ca81ac 100644 --- a/cli/wasm_to_bytes.js +++ b/cli/wasm_to_bytes.js @@ -1,5 +1,5 @@ -import fs from 'fs/promises' -import path from 'path' +import fs from "fs/promises"; +import path from "path"; // used for deploy code in contract with near.promiseBatchActionDeployContract. // Usage: @@ -8,14 +8,14 @@ import path from 'path' // near.promiseBatchActionDeployContract(promsieId, '') // Note, do not use `bytes()` type check here, which is too expensive for this long bytes and will exceed gas limit. async function main() { - let source = path.resolve(process.argv[process.argv.length-2]) - let target = path.resolve(process.argv[process.argv.length-1]) - let code = await fs.readFile(source) - let result = ''; - for (let e of code) { - result += '\\x' + e.toString(16).padStart(2, '0') - } - await fs.writeFile(target, result) + let source = path.resolve(process.argv[process.argv.length - 2]); + let target = path.resolve(process.argv[process.argv.length - 1]); + let code = await fs.readFile(source); + let result = ""; + for (let e of code) { + result += "\\x" + e.toString(16).padStart(2, "0"); + } + await fs.writeFile(target, result); } -main() \ No newline at end of file +main(); diff --git a/examples/__tests__/test-clean-state.ava.js b/examples/__tests__/test-clean-state.ava.js index 31f5e07c4..b46630f08 100644 --- a/examples/__tests__/test-clean-state.ava.js +++ b/examples/__tests__/test-clean-state.ava.js @@ -1,36 +1,36 @@ -import { Worker } from 'near-workspaces'; -import test from 'ava'; +import { Worker } from "near-workspaces"; +import test from "ava"; -test.beforeEach(async t => { - // Init the worker and start a Sandbox server - const worker = await Worker.init(); +test.beforeEach(async (t) => { + // Init the worker and start a Sandbox server + const worker = await Worker.init(); - // Prepare sandbox for tests, create accounts, deploy contracts, etx. - const root = worker.rootAccount; + // Prepare sandbox for tests, create accounts, deploy contracts, etx. + const root = worker.rootAccount; - // Deploy the clean-state contract. - const cleanState = await root.devDeploy('./build/clean-state.wasm'); + // Deploy the clean-state contract. + const cleanState = await root.devDeploy("./build/clean-state.wasm"); - // Save state for test runs, it is unique for each test - t.context.worker = worker; - t.context.accounts = { - root, - cleanState, - }; + // Save state for test runs, it is unique for each test + t.context.worker = worker; + t.context.accounts = { + root, + cleanState, + }; }); -test.afterEach.always(async t => { - await t.context.worker.tearDown().catch(error => { - console.log('Failed tear down the worker:', error); - }); +test.afterEach.always(async (t) => { + await t.context.worker.tearDown().catch((error) => { + console.log("Failed tear down the worker:", error); + }); }); -test('Clean state after storing', async t => { - const { root, cleanState } = t.context.accounts; - await root.call(cleanState, 'put', { key: '1', value: 1 }); - const value1 = await cleanState.view('get', { key: '1' }); - t.is(value1, '1'); - await cleanState.call(cleanState, 'clean', { keys: ['1'] }); - const value2 = await cleanState.view('get', { key: '1' }); - t.is(value2, null); +test("Clean state after storing", async (t) => { + const { root, cleanState } = t.context.accounts; + await root.call(cleanState, "put", { key: "1", value: 1 }); + const value1 = await cleanState.view("get", { key: "1" }); + t.is(value1, "1"); + await cleanState.call(cleanState, "clean", { keys: ["1"] }); + const value2 = await cleanState.view("get", { key: "1" }); + t.is(value2, null); }); diff --git a/examples/__tests__/test-counter.ava.js b/examples/__tests__/test-counter.ava.js index 8a6964809..b8a94a0f6 100644 --- a/examples/__tests__/test-counter.ava.js +++ b/examples/__tests__/test-counter.ava.js @@ -1,65 +1,69 @@ -import { Worker } from 'near-workspaces'; -import test from 'ava'; +import { Worker } from "near-workspaces"; +import test from "ava"; -test.beforeEach(async t => { - // Init the worker and start a Sandbox server - const worker = await Worker.init(); +test.beforeEach(async (t) => { + // Init the worker and start a Sandbox server + const worker = await Worker.init(); - // Prepare sandbox for tests, create accounts, deploy contracts, etc. - const root = worker.rootAccount; + // Prepare sandbox for tests, create accounts, deploy contracts, etc. + const root = worker.rootAccount; - // Deploy the counter contract. - const counter = await root.devDeploy( - process.env['COUNTER_LOWLEVEL'] ? - './build/counter-lowlevel.wasm' : - (process.env['COUNTER_TS'] ? './build/counter-ts.wasm' : './build/counter.wasm') - ); + // Deploy the counter contract. + const counter = await root.devDeploy( + process.env["COUNTER_LOWLEVEL"] + ? "./build/counter-lowlevel.wasm" + : process.env["COUNTER_TS"] + ? "./build/counter-ts.wasm" + : "./build/counter.wasm" + ); + // Test users + const ali = await root.createSubAccount("ali"); + const bob = await root.createSubAccount("bob"); - // Test users - const ali = await root.createSubAccount('ali'); - const bob = await root.createSubAccount('bob'); - - // Save state for test runs - t.context.worker = worker; - t.context.accounts = { root, counter, ali, bob }; + // Save state for test runs + t.context.worker = worker; + t.context.accounts = { root, counter, ali, bob }; }); // If the environment is reused, use test.after to replace test.afterEach -test.afterEach.always(async t => { - await t.context.worker.tearDown().catch(error => { - console.log('Failed to tear down the worker:', error); - }); +test.afterEach.always(async (t) => { + await t.context.worker.tearDown().catch((error) => { + console.log("Failed to tear down the worker:", error); + }); }); -test('Initial count is 0', async t => { - const { counter } = t.context.accounts; - const result = await counter.view('getCount', {}); - t.is(result, 0); +test("Initial count is 0", async (t) => { + const { counter } = t.context.accounts; + const result = await counter.view("getCount", {}); + t.is(result, 0); }); -test('Increase works', async t => { - const { counter, ali, bob } = t.context.accounts; - await ali.call(counter, 'increase', {}); +test("Increase works", async (t) => { + const { counter, ali, bob } = t.context.accounts; + await ali.call(counter, "increase", {}); - let result = await counter.view('getCount', {}); - t.is(result, 1); + let result = await counter.view("getCount", {}); + t.is(result, 1); - await bob.call(counter, 'increase', { n: 4 }); - result = await counter.view('getCount', {}); - t.is(result, 5); + await bob.call(counter, "increase", { n: 4 }); + result = await counter.view("getCount", {}); + t.is(result, 5); }); -test('Decrease works', async t => { - const { counter, ali, bob } = t.context.accounts; - await ali.call(counter, 'decrease', {}); +test("Decrease works", async (t) => { + const { counter, ali, bob } = t.context.accounts; + await ali.call(counter, "decrease", {}); - let result = await counter.view('getCount', {}); - t.is(result, -1); + let result = await counter.view("getCount", {}); + t.is(result, -1); - let dec = await bob.callRaw(counter, 'decrease', { n: 4 }); - // ensure imported log does work, not silent failure - t.is(dec.result.receipts_outcome[0].outcome.logs[0], "Counter decreased to -5") - result = await counter.view('getCount', {}); - t.is(result, -5); -}); \ No newline at end of file + let dec = await bob.callRaw(counter, "decrease", { n: 4 }); + // ensure imported log does work, not silent failure + t.is( + dec.result.receipts_outcome[0].outcome.logs[0], + "Counter decreased to -5" + ); + result = await counter.view("getCount", {}); + t.is(result, -5); +}); diff --git a/examples/__tests__/test-cross-contract-call.ava.js b/examples/__tests__/test-cross-contract-call.ava.js index 4b3666984..55308c930 100644 --- a/examples/__tests__/test-cross-contract-call.ava.js +++ b/examples/__tests__/test-cross-contract-call.ava.js @@ -1,79 +1,81 @@ -import { Worker } from 'near-workspaces'; -import test from 'ava'; +import { Worker } from "near-workspaces"; +import test from "ava"; -test.beforeEach(async t => { - // Init the worker and start a Sandbox server - const worker = await Worker.init(); +test.beforeEach(async (t) => { + // Init the worker and start a Sandbox server + const worker = await Worker.init(); - // Prepare sandbox for tests, create accounts, deploy contracts, etx. - const root = worker.rootAccount; + // Prepare sandbox for tests, create accounts, deploy contracts, etx. + const root = worker.rootAccount; - // Deploy status-message the contract. - const statusMessage = await root.devDeploy( - './build/status-message.wasm', - ); + // Deploy status-message the contract. + const statusMessage = await root.devDeploy("./build/status-message.wasm"); - // Deploy the onCall contract. - const onCall = await root.devDeploy( - './build/cross-contract-call.wasm', - ); + // Deploy the onCall contract. + const onCall = await root.devDeploy("./build/cross-contract-call.wasm"); - // Init the contract - await onCall.call(onCall, 'init', { statusMessageContract: statusMessage.accountId }); + // Init the contract + await onCall.call(onCall, "init", { + statusMessageContract: statusMessage.accountId, + }); - // Create test accounts - const ali = await root.createSubAccount('ali'); - const bob = await root.createSubAccount('bob'); + // Create test accounts + const ali = await root.createSubAccount("ali"); + const bob = await root.createSubAccount("bob"); - // Save state for test runs, it is unique for each test - t.context.worker = worker; - t.context.accounts = { - root, - statusMessage, - onCall, - ali, - bob, - }; + // Save state for test runs, it is unique for each test + t.context.worker = worker; + t.context.accounts = { + root, + statusMessage, + onCall, + ali, + bob, + }; }); -test.afterEach.always(async t => { - await t.context.worker.tearDown().catch(error => { - console.log('Failed tear down the worker:', error); - }); +test.afterEach.always(async (t) => { + await t.context.worker.tearDown().catch((error) => { + console.log("Failed tear down the worker:", error); + }); }); -test('Nobody is on-call in the beginning', async t => { - const { onCall } = t.context.accounts; - const result = await onCall.view('person_on_call', {}); - t.is(result, 'undefined'); +test("Nobody is on-call in the beginning", async (t) => { + const { onCall } = t.context.accounts; + const result = await onCall.view("person_on_call", {}); + t.is(result, "undefined"); }); -test('Person can be set on-call if AVAILABLE', async t => { - const { ali, bob, onCall, statusMessage } = t.context.accounts; +test("Person can be set on-call if AVAILABLE", async (t) => { + const { ali, bob, onCall, statusMessage } = t.context.accounts; - // Ali set her status as AVAILABLE - await ali.call(statusMessage, 'set_status', { message: 'AVAILABLE' }); - // Bob sets Ali on-call - await bob.call(onCall, 'set_person_on_call', { accountId: ali.accountId }, { gas: 120000000000000 }); + // Ali set her status as AVAILABLE + await ali.call(statusMessage, "set_status", { message: "AVAILABLE" }); + // Bob sets Ali on-call + await bob.call( + onCall, + "set_person_on_call", + { accountId: ali.accountId }, + { gas: 120000000000000 } + ); - // Check that Ali is on-call - t.is( - await onCall.view('person_on_call', {}), - ali.accountId - ); + // Check that Ali is on-call + t.is(await onCall.view("person_on_call", {}), ali.accountId); }); -test('Person can NOT be set on-call if UNAVAILABLE', async t => { - const { ali, bob, onCall, statusMessage } = t.context.accounts; +test("Person can NOT be set on-call if UNAVAILABLE", async (t) => { + const { ali, bob, onCall, statusMessage } = t.context.accounts; - // Ali set her status as AVAILABLE - await ali.call(statusMessage, 'set_status', { message: 'UNAVAILABLE' }); - // Bob tries to sets Ali on-call - await bob.call(onCall, 'set_person_on_call', { accountId: ali.accountId }, { gas: 120000000000000 }); + // Ali set her status as AVAILABLE + await ali.call(statusMessage, "set_status", { message: "UNAVAILABLE" }); + // Bob tries to sets Ali on-call + await bob.call( + onCall, + "set_person_on_call", + { accountId: ali.accountId }, + { gas: 120000000000000 } + ); - // Check that Ali is NOT on-call - t.not( - await onCall.view('person_on_call', {}), - ali.accountId - ); + // Check that Ali is NOT on-call + t.not(await onCall.view("person_on_call", {}), ali.accountId); }); diff --git a/examples/__tests__/test-fungible-token-lockable.ava.js b/examples/__tests__/test-fungible-token-lockable.ava.js index 5481f8b23..2caa29b3f 100644 --- a/examples/__tests__/test-fungible-token-lockable.ava.js +++ b/examples/__tests__/test-fungible-token-lockable.ava.js @@ -1,123 +1,217 @@ -import { Worker } from 'near-workspaces'; -import test from 'ava'; - -test.beforeEach(async t => { - // Init the worker and start a Sandbox server - const worker = await Worker.init(); - - // Prepare sandbox for tests, create accounts, deploy contracts, etx. - const root = worker.rootAccount; - - // Deploy the lockable-ft contract. - const lockableFt = await root.devDeploy( - './build/fungible-token-lockable.wasm', - ); - - // Init the contract - await lockableFt.call(lockableFt, 'init', { prefix: 'prefix', totalSupply: 10000 }); - - // Test users - const ali = await root.createSubAccount('ali'); - const bob = await root.createSubAccount('bob'); - - // Save state for test runs - t.context.worker = worker; - t.context.accounts = { root, lockableFt, ali, bob }; +import { Worker } from "near-workspaces"; +import test from "ava"; + +test.beforeEach(async (t) => { + // Init the worker and start a Sandbox server + const worker = await Worker.init(); + + // Prepare sandbox for tests, create accounts, deploy contracts, etx. + const root = worker.rootAccount; + + // Deploy the lockable-ft contract. + const lockableFt = await root.devDeploy( + "./build/fungible-token-lockable.wasm" + ); + + // Init the contract + await lockableFt.call(lockableFt, "init", { + prefix: "prefix", + totalSupply: 10000, + }); + + // Test users + const ali = await root.createSubAccount("ali"); + const bob = await root.createSubAccount("bob"); + + // Save state for test runs + t.context.worker = worker; + t.context.accounts = { root, lockableFt, ali, bob }; }); -test.afterEach.always(async t => { - await t.context.worker.tearDown().catch(error => { - console.log('Failed to tear down the worker:', error); - }); +test.afterEach.always(async (t) => { + await t.context.worker.tearDown().catch((error) => { + console.log("Failed to tear down the worker:", error); + }); }); -test('Owner initial details', async t => { - const { lockableFt } = t.context.accounts; - const totalSupply = await lockableFt.view('getTotalSupply', {}); - t.is(totalSupply, 10000); - const totalBalance = await lockableFt.view('getTotalBalance', { ownerId: lockableFt.accountId }); - t.is(totalBalance, 10000); - const unlockedBalance = await lockableFt.view('getUnlockedBalance', { ownerId: lockableFt.accountId }); - t.is(unlockedBalance, 10000); - const allowance = await lockableFt.view('getAllowance', { ownerId: lockableFt.accountId, escrowAccountId: lockableFt.accountId }); - t.is(allowance, 0); - const lockedBalance = await lockableFt.view('getLockedBalance', { ownerId: lockableFt.accountId, escrowAccountId: lockableFt.accountId }); - t.is(lockedBalance, 0); +test("Owner initial details", async (t) => { + const { lockableFt } = t.context.accounts; + const totalSupply = await lockableFt.view("getTotalSupply", {}); + t.is(totalSupply, 10000); + const totalBalance = await lockableFt.view("getTotalBalance", { + ownerId: lockableFt.accountId, + }); + t.is(totalBalance, 10000); + const unlockedBalance = await lockableFt.view("getUnlockedBalance", { + ownerId: lockableFt.accountId, + }); + t.is(unlockedBalance, 10000); + const allowance = await lockableFt.view("getAllowance", { + ownerId: lockableFt.accountId, + escrowAccountId: lockableFt.accountId, + }); + t.is(allowance, 0); + const lockedBalance = await lockableFt.view("getLockedBalance", { + ownerId: lockableFt.accountId, + escrowAccountId: lockableFt.accountId, + }); + t.is(lockedBalance, 0); }); -test('Set allowance', async t => { - const { lockableFt, ali } = t.context.accounts; - await lockableFt.call(lockableFt, 'setAllowance', { escrowAccountId: ali.accountId, allowance: 100 }); - const aliAllowance = await lockableFt.view('getAllowance', { ownerId: lockableFt.accountId, escrowAccountId: ali.accountId }); - t.is(aliAllowance, 100); - const contractAllowance = await lockableFt.view('getAllowance', { ownerId: lockableFt.accountId, escrowAccountId: lockableFt.accountId }); - t.is(contractAllowance, 0); +test("Set allowance", async (t) => { + const { lockableFt, ali } = t.context.accounts; + await lockableFt.call(lockableFt, "setAllowance", { + escrowAccountId: ali.accountId, + allowance: 100, + }); + const aliAllowance = await lockableFt.view("getAllowance", { + ownerId: lockableFt.accountId, + escrowAccountId: ali.accountId, + }); + t.is(aliAllowance, 100); + const contractAllowance = await lockableFt.view("getAllowance", { + ownerId: lockableFt.accountId, + escrowAccountId: lockableFt.accountId, + }); + t.is(contractAllowance, 0); }); -test('Fail to set allowance for oneself', async t => { - const { lockableFt } = t.context.accounts; - const error = await t.throwsAsync(() => lockableFt.call(lockableFt, 'setAllowance', { escrowAccountId: lockableFt.accountId, allowance: 100 })); - t.assert(error.message.includes(`Can't set allowance for yourself`)); +test("Fail to set allowance for oneself", async (t) => { + const { lockableFt } = t.context.accounts; + const error = await t.throwsAsync(() => + lockableFt.call(lockableFt, "setAllowance", { + escrowAccountId: lockableFt.accountId, + allowance: 100, + }) + ); + t.assert(error.message.includes(`Can't set allowance for yourself`)); }); -test('Lock owner', async t => { - const { lockableFt } = t.context.accounts; - await lockableFt.call(lockableFt, 'lock', { ownerId: lockableFt.accountId, lockAmount: 100 }); - const unlockedBalance = await lockableFt.view('getUnlockedBalance', { ownerId: lockableFt.accountId }); - t.is(unlockedBalance, 9900); - const allowance = await lockableFt.view('getAllowance', { ownerId: lockableFt.accountId, escrowAccountId: lockableFt.accountId }); - t.is(allowance, 0); - const lockedBalance = await lockableFt.view('getLockedBalance', { ownerId: lockableFt.accountId, escrowAccountId: lockableFt.accountId }); - t.is(lockedBalance, 100); +test("Lock owner", async (t) => { + const { lockableFt } = t.context.accounts; + await lockableFt.call(lockableFt, "lock", { + ownerId: lockableFt.accountId, + lockAmount: 100, + }); + const unlockedBalance = await lockableFt.view("getUnlockedBalance", { + ownerId: lockableFt.accountId, + }); + t.is(unlockedBalance, 9900); + const allowance = await lockableFt.view("getAllowance", { + ownerId: lockableFt.accountId, + escrowAccountId: lockableFt.accountId, + }); + t.is(allowance, 0); + const lockedBalance = await lockableFt.view("getLockedBalance", { + ownerId: lockableFt.accountId, + escrowAccountId: lockableFt.accountId, + }); + t.is(lockedBalance, 100); }); -test('Lock failures', async t => { - const { lockableFt, ali } = t.context.accounts; - const error1 = await t.throwsAsync(() => lockableFt.call(lockableFt, 'lock', { ownerId: lockableFt.accountId, lockAmount: 0 })); - t.assert(error1.message.includes(`Can't lock 0 or less tokens`)); - - const error2 = await t.throwsAsync(() => lockableFt.call(lockableFt, 'lock', { ownerId: lockableFt.accountId, lockAmount: 10001 })); - t.assert(error2.message.includes(`Not enough unlocked balance`)); - - const error3 = await t.throwsAsync(() => ali.call(lockableFt, 'lock', { ownerId: lockableFt.accountId, lockAmount: 10 })); - t.assert(error3.message.includes(`Not enough allowance`)); +test("Lock failures", async (t) => { + const { lockableFt, ali } = t.context.accounts; + const error1 = await t.throwsAsync(() => + lockableFt.call(lockableFt, "lock", { + ownerId: lockableFt.accountId, + lockAmount: 0, + }) + ); + t.assert(error1.message.includes(`Can't lock 0 or less tokens`)); + + const error2 = await t.throwsAsync(() => + lockableFt.call(lockableFt, "lock", { + ownerId: lockableFt.accountId, + lockAmount: 10001, + }) + ); + t.assert(error2.message.includes(`Not enough unlocked balance`)); + + const error3 = await t.throwsAsync(() => + ali.call(lockableFt, "lock", { + ownerId: lockableFt.accountId, + lockAmount: 10, + }) + ); + t.assert(error3.message.includes(`Not enough allowance`)); }); -test('Unlock owner', async t => { - const { lockableFt } = t.context.accounts; - await lockableFt.call(lockableFt, 'lock', { ownerId: lockableFt.accountId, lockAmount: 100 }); - await lockableFt.call(lockableFt, 'unlock', { ownerId: lockableFt.accountId, unlockAmount: 100 }); - const unlockedBalance = await lockableFt.view('getUnlockedBalance', { ownerId: lockableFt.accountId }); - t.is(unlockedBalance, 10000); - const allowance = await lockableFt.view('getAllowance', { ownerId: lockableFt.accountId, escrowAccountId: lockableFt.accountId }); - t.is(allowance, 0); - const lockedBalance = await lockableFt.view('getLockedBalance', { ownerId: lockableFt.accountId, escrowAccountId: lockableFt.accountId }); - t.is(lockedBalance, 0); +test("Unlock owner", async (t) => { + const { lockableFt } = t.context.accounts; + await lockableFt.call(lockableFt, "lock", { + ownerId: lockableFt.accountId, + lockAmount: 100, + }); + await lockableFt.call(lockableFt, "unlock", { + ownerId: lockableFt.accountId, + unlockAmount: 100, + }); + const unlockedBalance = await lockableFt.view("getUnlockedBalance", { + ownerId: lockableFt.accountId, + }); + t.is(unlockedBalance, 10000); + const allowance = await lockableFt.view("getAllowance", { + ownerId: lockableFt.accountId, + escrowAccountId: lockableFt.accountId, + }); + t.is(allowance, 0); + const lockedBalance = await lockableFt.view("getLockedBalance", { + ownerId: lockableFt.accountId, + escrowAccountId: lockableFt.accountId, + }); + t.is(lockedBalance, 0); }); -test('Unlock failures', async t => { - const { lockableFt } = t.context.accounts; - const error1 = await t.throwsAsync(() => lockableFt.call(lockableFt, 'unlock', { ownerId: lockableFt.accountId, unlockAmount: 0 })); - t.assert(error1.message.includes(`Can't unlock 0 or less tokens`)); - - const error2 = await t.throwsAsync(() => lockableFt.call(lockableFt, 'unlock', { ownerId: lockableFt.accountId, unlockAmount: 1 })); - t.assert(error2.message.includes(`Not enough locked tokens`)); +test("Unlock failures", async (t) => { + const { lockableFt } = t.context.accounts; + const error1 = await t.throwsAsync(() => + lockableFt.call(lockableFt, "unlock", { + ownerId: lockableFt.accountId, + unlockAmount: 0, + }) + ); + t.assert(error1.message.includes(`Can't unlock 0 or less tokens`)); + + const error2 = await t.throwsAsync(() => + lockableFt.call(lockableFt, "unlock", { + ownerId: lockableFt.accountId, + unlockAmount: 1, + }) + ); + t.assert(error2.message.includes(`Not enough locked tokens`)); }); -test('Simple transfer', async t => { - const { lockableFt, ali } = t.context.accounts; - await lockableFt.call(lockableFt, 'transfer', { newOwnerId: ali.accountId, amount: 100 }); - const ownerUnlockedBalance = await lockableFt.view('getUnlockedBalance', { ownerId: lockableFt.accountId }); - t.is(ownerUnlockedBalance, 9900); - const aliUnlockedBalance = await lockableFt.view('getUnlockedBalance', { ownerId: ali.accountId }); - t.is(aliUnlockedBalance, 100); +test("Simple transfer", async (t) => { + const { lockableFt, ali } = t.context.accounts; + await lockableFt.call(lockableFt, "transfer", { + newOwnerId: ali.accountId, + amount: 100, + }); + const ownerUnlockedBalance = await lockableFt.view("getUnlockedBalance", { + ownerId: lockableFt.accountId, + }); + t.is(ownerUnlockedBalance, 9900); + const aliUnlockedBalance = await lockableFt.view("getUnlockedBalance", { + ownerId: ali.accountId, + }); + t.is(aliUnlockedBalance, 100); }); -test('Transfer failures', async t => { - const { lockableFt, ali } = t.context.accounts; - const error1 = await t.throwsAsync(() => lockableFt.call(lockableFt, 'transfer', { newOwnerId: ali.accountId, amount: 0 })); - t.assert(error1.message.includes(`Can't transfer 0 or less tokens`)); - - const error2 = await t.throwsAsync(() => lockableFt.call(lockableFt, 'transfer', { newOwnerId: ali.accountId, amount: 10001 })); - t.assert(error2.message.includes(`Not enough unlocked balance`)); +test("Transfer failures", async (t) => { + const { lockableFt, ali } = t.context.accounts; + const error1 = await t.throwsAsync(() => + lockableFt.call(lockableFt, "transfer", { + newOwnerId: ali.accountId, + amount: 0, + }) + ); + t.assert(error1.message.includes(`Can't transfer 0 or less tokens`)); + + const error2 = await t.throwsAsync(() => + lockableFt.call(lockableFt, "transfer", { + newOwnerId: ali.accountId, + amount: 10001, + }) + ); + t.assert(error2.message.includes(`Not enough unlocked balance`)); }); diff --git a/examples/__tests__/test-fungible-token.ava.js b/examples/__tests__/test-fungible-token.ava.js index 7cab26dee..df56887b5 100644 --- a/examples/__tests__/test-fungible-token.ava.js +++ b/examples/__tests__/test-fungible-token.ava.js @@ -1,71 +1,88 @@ -import { Worker } from 'near-workspaces'; -import test from 'ava'; +import { Worker } from "near-workspaces"; +import test from "ava"; test.beforeEach(async (t) => { - // Init the worker and start a Sandbox server - const worker = await Worker.init(); + // Init the worker and start a Sandbox server + const worker = await Worker.init(); - // Prepare sandbox for tests, create accounts, deploy contracts, etx. - const root = worker.rootAccount; + // Prepare sandbox for tests, create accounts, deploy contracts, etx. + const root = worker.rootAccount; - // Deploy the ft contract. - const ft = await root.devDeploy( - './build/fungible-token.wasm', - ); - const xcc = await root.devDeploy( - './build/fungible-token-helper.wasm', - ); + // Deploy the ft contract. + const ft = await root.devDeploy("./build/fungible-token.wasm"); + const xcc = await root.devDeploy("./build/fungible-token-helper.wasm"); - // Init the contracts - await ft.call(ft, 'init', { prefix: 'a', totalSupply: '1000' }); + // Init the contracts + await ft.call(ft, "init", { prefix: "a", totalSupply: "1000" }); - // Create test accounts - const ali = await root.createSubAccount('ali'); - const bob = await root.createSubAccount('bob'); + // Create test accounts + const ali = await root.createSubAccount("ali"); + const bob = await root.createSubAccount("bob"); - // Save state for test runs, it is unique for each test - t.context.worker = worker; - t.context.accounts = { root, ft, ali, bob, xcc }; + // Save state for test runs, it is unique for each test + t.context.worker = worker; + t.context.accounts = { root, ft, ali, bob, xcc }; }); -test.afterEach.always(async t => { - await t.context.worker.tearDown().catch(error => { - console.log('Failed tear down the worker:', error); - }); +test.afterEach.always(async (t) => { + await t.context.worker.tearDown().catch((error) => { + console.log("Failed tear down the worker:", error); + }); }); -test('Owner has all balance in the beginning', async t => { - const { ft } = t.context.accounts; - const result = await ft.view('ftBalanceOf', { accountId: ft.accountId }); - t.is(result, '1000'); +test("Owner has all balance in the beginning", async (t) => { + const { ft } = t.context.accounts; + const result = await ft.view("ftBalanceOf", { accountId: ft.accountId }); + t.is(result, "1000"); }); -test('Can transfer if balance is sufficient', async t => { - const { ali, ft } = t.context.accounts; +test("Can transfer if balance is sufficient", async (t) => { + const { ali, ft } = t.context.accounts; - await ft.call(ft, 'ftTransfer', { receiverId: ali.accountId, amount: '100' }); - const aliBalance = await ft.view('ftBalanceOf', { accountId: ali.accountId }); - t.is(aliBalance, '100'); - const ownerBalance = await ft.view('ftBalanceOf', { accountId: ft.accountId }); - t.is(ownerBalance, '900'); + await ft.call(ft, "ftTransfer", { receiverId: ali.accountId, amount: "100" }); + const aliBalance = await ft.view("ftBalanceOf", { accountId: ali.accountId }); + t.is(aliBalance, "100"); + const ownerBalance = await ft.view("ftBalanceOf", { + accountId: ft.accountId, + }); + t.is(ownerBalance, "900"); }); -test('Cannot transfer if balance is not sufficient', async t => { - const { ali, bob, ft } = t.context.accounts; - try { - await ali.call(ft, 'ftTransfer', { receiverId: bob.accountId, amount: '100' }); - } catch (e) { - t.assert(e.toString().indexOf('Smart contract panicked: assertion failed: The account doesn\'t have enough balance') >= 0); - } +test("Cannot transfer if balance is not sufficient", async (t) => { + const { ali, bob, ft } = t.context.accounts; + try { + await ali.call(ft, "ftTransfer", { + receiverId: bob.accountId, + amount: "100", + }); + } catch (e) { + t.assert( + e + .toString() + .indexOf( + "Smart contract panicked: assertion failed: The account doesn't have enough balance" + ) >= 0 + ); + } }); -test('Cross contract transfer', async (t) => { - const { xcc, ft } = t.context.accounts; - await ft.call(ft, 'ftTransferCall', { receiverId: xcc.accountId, amount: '900', memo: null, msg: 'test msg' }, { gas: 200000000000000 }); - const aliBalance = await ft.view('ftBalanceOf', { accountId: xcc.accountId }); - t.is(aliBalance, '900'); - const aliSubContractData = await xcc.view('getContractData'); - t.is(aliSubContractData, `[900 from ${ft.accountId} to ${xcc.accountId}] test msg `); - const ownerBalance = await ft.view('ftBalanceOf', { accountId: ft.accountId }); - t.is(ownerBalance, '100'); +test("Cross contract transfer", async (t) => { + const { xcc, ft } = t.context.accounts; + await ft.call( + ft, + "ftTransferCall", + { receiverId: xcc.accountId, amount: "900", memo: null, msg: "test msg" }, + { gas: 200000000000000 } + ); + const aliBalance = await ft.view("ftBalanceOf", { accountId: xcc.accountId }); + t.is(aliBalance, "900"); + const aliSubContractData = await xcc.view("getContractData"); + t.is( + aliSubContractData, + `[900 from ${ft.accountId} to ${xcc.accountId}] test msg ` + ); + const ownerBalance = await ft.view("ftBalanceOf", { + accountId: ft.accountId, + }); + t.is(ownerBalance, "100"); }); diff --git a/examples/__tests__/test-non-fungible-token.ava.js b/examples/__tests__/test-non-fungible-token.ava.js index 6f8970506..4f215a672 100644 --- a/examples/__tests__/test-non-fungible-token.ava.js +++ b/examples/__tests__/test-non-fungible-token.ava.js @@ -1,86 +1,129 @@ -import { Worker } from 'near-workspaces'; -import test from 'ava'; - -test.beforeEach(async t => { - // Init the worker and start a Sandbox server - const worker = await Worker.init(); - - // Prepare sandbox for tests, create accounts, deploy contracts, etx. - const root = worker.rootAccount; - - // Deploy the nft contract. - const nft = await root.devDeploy( - './build/non-fungible-token.wasm', - ); - - // Init the contract - await nft.call(nft, 'init', { owner_id: nft.accountId, owner_by_id_prefix: 'a' }); - - // Deploy the tokenReceiver contract. - const tokenReceiver = await root.devDeploy( - './build/non-fungible-token-receiver.wasm', - ); - - // Init the contract - await tokenReceiver.call(tokenReceiver, 'init', { nonFungibleTokenAccountId: nft.accountId }); - - // Mint an NFT - let tokenId = 'my-cool-nft'; - await nft.call(nft, 'nftMint', { token_id: tokenId, token_owner_id: nft.accountId }); - - - // Create test accounts - const ali = await root.createSubAccount('ali'); - const bob = await root.createSubAccount('bob'); - - // Save state for test runs, it is unique for each test - t.context.worker = worker; - t.context.accounts = { root, nft, tokenReceiver, tokenId, ali, bob }; +import { Worker } from "near-workspaces"; +import test from "ava"; + +test.beforeEach(async (t) => { + // Init the worker and start a Sandbox server + const worker = await Worker.init(); + + // Prepare sandbox for tests, create accounts, deploy contracts, etx. + const root = worker.rootAccount; + + // Deploy the nft contract. + const nft = await root.devDeploy("./build/non-fungible-token.wasm"); + + // Init the contract + await nft.call(nft, "init", { + owner_id: nft.accountId, + owner_by_id_prefix: "a", + }); + + // Deploy the tokenReceiver contract. + const tokenReceiver = await root.devDeploy( + "./build/non-fungible-token-receiver.wasm" + ); + + // Init the contract + await tokenReceiver.call(tokenReceiver, "init", { + nonFungibleTokenAccountId: nft.accountId, + }); + + // Mint an NFT + let tokenId = "my-cool-nft"; + await nft.call(nft, "nftMint", { + token_id: tokenId, + token_owner_id: nft.accountId, + }); + + // Create test accounts + const ali = await root.createSubAccount("ali"); + const bob = await root.createSubAccount("bob"); + + // Save state for test runs, it is unique for each test + t.context.worker = worker; + t.context.accounts = { root, nft, tokenReceiver, tokenId, ali, bob }; }); -test.afterEach.always(async t => { - await t.context.worker.tearDown().catch(error => { - console.log('Failed tear down the worker:', error); - }); +test.afterEach.always(async (t) => { + await t.context.worker.tearDown().catch((error) => { + console.log("Failed tear down the worker:", error); + }); }); -test('Owner has the NFT in the beginning', async t => { - const { nft, tokenId } = t.context.accounts; - const result = await nft.view('nftToken', { token_id: tokenId }); - t.deepEqual(result, { owner_id: nft.accountId, token_id: tokenId }); +test("Owner has the NFT in the beginning", async (t) => { + const { nft, tokenId } = t.context.accounts; + const result = await nft.view("nftToken", { token_id: tokenId }); + t.deepEqual(result, { owner_id: nft.accountId, token_id: tokenId }); }); -test('Simple transfer', async t => { - const { nft, tokenId, ali } = t.context.accounts; - await nft.call(nft, 'nftTransfer', { receiver_id: ali.accountId, token_id: tokenId }); - const result = await nft.view('nftToken', { token_id: tokenId }); - t.deepEqual(result, { owner_id: ali.accountId, token_id: tokenId }); +test("Simple transfer", async (t) => { + const { nft, tokenId, ali } = t.context.accounts; + await nft.call(nft, "nftTransfer", { + receiver_id: ali.accountId, + token_id: tokenId, + }); + const result = await nft.view("nftToken", { token_id: tokenId }); + t.deepEqual(result, { owner_id: ali.accountId, token_id: tokenId }); }); -test('Transfer failures', async t => { - const { nft, tokenId, ali } = t.context.accounts; - const error1 = await t.throwsAsync(() => ali.call(nft, 'nftTransfer', { receiver_id: nft.accountId, token_id: 'non-existent-id' })); - t.assert(error1.message.includes(`Token not found`)); - - const error2 = await t.throwsAsync(() => ali.call(nft, 'nftTransfer', { receiver_id: nft.accountId, token_id: tokenId })); - t.assert(error2.message.includes(`Sender must be the current owner`)); - - const error3 = await t.throwsAsync(() => nft.call(nft, 'nftTransfer', { receiver_id: nft.accountId, token_id: tokenId })); - t.assert(error3.message.includes(`Current and next owner must differ`)); +test("Transfer failures", async (t) => { + const { nft, tokenId, ali } = t.context.accounts; + const error1 = await t.throwsAsync(() => + ali.call(nft, "nftTransfer", { + receiver_id: nft.accountId, + token_id: "non-existent-id", + }) + ); + t.assert(error1.message.includes(`Token not found`)); + + const error2 = await t.throwsAsync(() => + ali.call(nft, "nftTransfer", { + receiver_id: nft.accountId, + token_id: tokenId, + }) + ); + t.assert(error2.message.includes(`Sender must be the current owner`)); + + const error3 = await t.throwsAsync(() => + nft.call(nft, "nftTransfer", { + receiver_id: nft.accountId, + token_id: tokenId, + }) + ); + t.assert(error3.message.includes(`Current and next owner must differ`)); }); -test('Transfer call where receiver returns the token', async t => { - const { nft, tokenReceiver, tokenId } = t.context.accounts; - await nft.call( - nft, - 'nftTransferCall', { receiver_id: tokenReceiver.accountId, token_id: tokenId, approval_id: null, memo: null, msg: 'return-it-now' }, { gas: '120000000000000' }); - const result = await nft.view('nftToken', { token_id: tokenId }); - t.deepEqual(result, { owner_id: nft.accountId, token_id: tokenId }); +test("Transfer call where receiver returns the token", async (t) => { + const { nft, tokenReceiver, tokenId } = t.context.accounts; + await nft.call( + nft, + "nftTransferCall", + { + receiver_id: tokenReceiver.accountId, + token_id: tokenId, + approval_id: null, + memo: null, + msg: "return-it-now", + }, + { gas: "120000000000000" } + ); + const result = await nft.view("nftToken", { token_id: tokenId }); + t.deepEqual(result, { owner_id: nft.accountId, token_id: tokenId }); }); -test('Transfer call where receiver keeps the token', async t => { - const { nft, tokenReceiver, tokenId } = t.context.accounts; - await nft.call(nft, 'nftTransferCall', { receiver_id: tokenReceiver.accountId, token_id: tokenId, approval_id: null, memo: null, msg: 'keep-it-now' }, { gas: '120000000000000' }); - const result = await nft.view('nftToken', { token_id: tokenId }); - t.deepEqual(result, { owner_id: tokenReceiver.accountId, token_id: tokenId }); +test("Transfer call where receiver keeps the token", async (t) => { + const { nft, tokenReceiver, tokenId } = t.context.accounts; + await nft.call( + nft, + "nftTransferCall", + { + receiver_id: tokenReceiver.accountId, + token_id: tokenId, + approval_id: null, + memo: null, + msg: "keep-it-now", + }, + { gas: "120000000000000" } + ); + const result = await nft.view("nftToken", { token_id: tokenId }); + t.deepEqual(result, { owner_id: tokenReceiver.accountId, token_id: tokenId }); }); diff --git a/examples/__tests__/test-parking-lot.ava.js b/examples/__tests__/test-parking-lot.ava.js index af1d3b3a4..acc86394b 100644 --- a/examples/__tests__/test-parking-lot.ava.js +++ b/examples/__tests__/test-parking-lot.ava.js @@ -1,50 +1,44 @@ -import { Worker } from 'near-workspaces'; -import test from 'ava'; +import { Worker } from "near-workspaces"; +import test from "ava"; -test.beforeEach(async t => { - const worker = await Worker.init(); - const root = worker.rootAccount; +test.beforeEach(async (t) => { + const worker = await Worker.init(); + const root = worker.rootAccount; - const parkingLot = await root.devDeploy( - 'build/parking-lot.wasm', - ); + const parkingLot = await root.devDeploy("build/parking-lot.wasm"); + const ali = await root.createSubAccount("ali"); - const ali = await root.createSubAccount('ali'); - - t.context.worker = worker; - t.context.accounts = { root, parkingLot, ali }; + t.context.worker = worker; + t.context.accounts = { root, parkingLot, ali }; }); -test.afterEach.always(async t => { - await t.context.worker.tearDown().catch(error => { - console.log('Failed to tear down the worker:', error); - }); +test.afterEach.always(async (t) => { + await t.context.worker.tearDown().catch((error) => { + console.log("Failed to tear down the worker:", error); + }); }); -test('No BMW in the beginning', async t => { - const { parkingLot } = t.context.accounts; +test("No BMW in the beginning", async (t) => { + const { parkingLot } = t.context.accounts; - t.is( - await parkingLot.view('getCarSpecs', { name: 'BMW' }), - null - ); + t.is(await parkingLot.view("getCarSpecs", { name: "BMW" }), null); }); -test('Can run the car after adding it', async t => { - const { ali, parkingLot } = t.context.accounts; +test("Can run the car after adding it", async (t) => { + const { ali, parkingLot } = t.context.accounts; - const bmwSpecs = { - id: 1, - color: 'Black', - price: 100500, - engineHp: 500, - }; + const bmwSpecs = { + id: 1, + color: "Black", + price: 100500, + engineHp: 500, + }; - await ali.call(parkingLot, 'addCar', { - name: 'BMW', - ...bmwSpecs - }); + await ali.call(parkingLot, "addCar", { + name: "BMW", + ...bmwSpecs, + }); - t.is(await parkingLot.view('runCar', {name: 'BMW'}), 'boom'); + t.is(await parkingLot.view("runCar", { name: "BMW" }), "boom"); }); diff --git a/examples/__tests__/test-status-message-collections.ava.js b/examples/__tests__/test-status-message-collections.ava.js index ab1ba23a0..e50f28143 100644 --- a/examples/__tests__/test-status-message-collections.ava.js +++ b/examples/__tests__/test-status-message-collections.ava.js @@ -1,82 +1,84 @@ -import { Worker } from 'near-workspaces'; -import test from 'ava'; +import { Worker } from "near-workspaces"; +import test from "ava"; -test.beforeEach(async t => { - // Init the worker and start a Sandbox server - const worker = await Worker.init(); +test.beforeEach(async (t) => { + // Init the worker and start a Sandbox server + const worker = await Worker.init(); - // Prepare sandbox for tests, create accounts, deploy contracts, etx. - const root = worker.rootAccount; + // Prepare sandbox for tests, create accounts, deploy contracts, etx. + const root = worker.rootAccount; - // Deploy the statis-message contract. - const statusMessage = await root.devDeploy( - './build/status-message-collections.wasm', - ); + // Deploy the statis-message contract. + const statusMessage = await root.devDeploy( + "./build/status-message-collections.wasm" + ); + // Test users + const ali = await root.createSubAccount("ali"); + const bob = await root.createSubAccount("bob"); + const carl = await root.createSubAccount("carl"); - // Test users - const ali = await root.createSubAccount('ali'); - const bob = await root.createSubAccount('bob'); - const carl = await root.createSubAccount('carl'); - - // Save state for test runs - t.context.worker = worker; - t.context.accounts = { root, statusMessage, ali, bob, carl }; + // Save state for test runs + t.context.worker = worker; + t.context.accounts = { root, statusMessage, ali, bob, carl }; }); -test.afterEach.always(async t => { - await t.context.worker.tearDown().catch(error => { - console.log('Failed to tear down the worker:', error); - }); +test.afterEach.always(async (t) => { + await t.context.worker.tearDown().catch((error) => { + console.log("Failed to tear down the worker:", error); + }); }); -test('Root gets null status', async t => { - const { root, statusMessage } = t.context.accounts; - const result = await statusMessage.view('get_status', { account_id: root.accountId }); - t.is(result, null); +test("Root gets null status", async (t) => { + const { root, statusMessage } = t.context.accounts; + const result = await statusMessage.view("get_status", { + account_id: root.accountId, + }); + t.is(result, null); }); -test('Ali sets then gets status', async t => { - const { ali, statusMessage } = t.context.accounts; - await ali.call(statusMessage, 'set_status', { message: 'hello' }); +test("Ali sets then gets status", async (t) => { + const { ali, statusMessage } = t.context.accounts; + await ali.call(statusMessage, "set_status", { message: "hello" }); - t.is( - await statusMessage.view('get_status', { account_id: ali.accountId }), - 'hello' - ); + t.is( + await statusMessage.view("get_status", { account_id: ali.accountId }), + "hello" + ); }); -test('Bob and Carl have different statuses', async t => { - const { statusMessage, bob, carl } = t.context.accounts; - await bob.call(statusMessage, 'set_status', { message: 'hello' }); - await carl.call(statusMessage, 'set_status', { message: 'world' }); - - const bobStatus = await statusMessage.view('get_status', { account_id: bob.accountId }); - const carlStatus = await statusMessage.view('get_status', { account_id: carl.accountId }); - t.is(bobStatus, 'hello'); - t.is(carlStatus, 'world'); +test("Bob and Carl have different statuses", async (t) => { + const { statusMessage, bob, carl } = t.context.accounts; + await bob.call(statusMessage, "set_status", { message: "hello" }); + await carl.call(statusMessage, "set_status", { message: "world" }); + + const bobStatus = await statusMessage.view("get_status", { + account_id: bob.accountId, + }); + const carlStatus = await statusMessage.view("get_status", { + account_id: carl.accountId, + }); + t.is(bobStatus, "hello"); + t.is(carlStatus, "world"); }); -test('Get statuses from the contract', async t => { - const { statusMessage, bob, carl } = t.context.accounts; - await bob.call(statusMessage, 'set_status', { message: 'hello' }); - await carl.call(statusMessage, 'set_status', { message: 'world' }); +test("Get statuses from the contract", async (t) => { + const { statusMessage, bob, carl } = t.context.accounts; + await bob.call(statusMessage, "set_status", { message: "hello" }); + await carl.call(statusMessage, "set_status", { message: "world" }); - const statuses = await statusMessage.view('get_all_statuses', {}); - t.deepEqual(statuses, [[bob.accountId, 'hello'], [carl.accountId, 'world']]); + const statuses = await statusMessage.view("get_all_statuses", {}); + t.deepEqual(statuses, [ + [bob.accountId, "hello"], + [carl.accountId, "world"], + ]); }); -test('message has stored by someone', async t => { - const { ali, statusMessage } = t.context.accounts; - await ali.call(statusMessage, 'set_status', { message: 'hello' }); +test("message has stored by someone", async (t) => { + const { ali, statusMessage } = t.context.accounts; + await ali.call(statusMessage, "set_status", { message: "hello" }); - t.is( - await statusMessage.view('has_status', { message: 'hello' }), - true - ); + t.is(await statusMessage.view("has_status", { message: "hello" }), true); - t.is( - await statusMessage.view('has_status', { message: 'world' }), - false - ); -}); \ No newline at end of file + t.is(await statusMessage.view("has_status", { message: "world" }), false); +}); diff --git a/examples/__tests__/test-status-message.ava.js b/examples/__tests__/test-status-message.ava.js index 9310cf02e..618a9734d 100644 --- a/examples/__tests__/test-status-message.ava.js +++ b/examples/__tests__/test-status-message.ava.js @@ -1,57 +1,61 @@ -import { Worker } from 'near-workspaces'; -import test from 'ava'; - -test.before(async t => { - // Init the worker and start a Sandbox server - const worker = await Worker.init(); - - // Prepare sandbox for tests, create accounts, deploy contracts, etx. - const root = worker.rootAccount; - - // Deploy the contract. - const statusMessage = await root.devDeploy( - './build/status-message.wasm', - ); - - // Create test users - const ali = await root.createSubAccount('ali'); - const bob = await root.createSubAccount('bob'); - const carl = await root.createSubAccount('carl'); - - // Save state for test runs - t.context.worker = worker; - t.context.accounts = { root, statusMessage, ali, bob, carl }; +import { Worker } from "near-workspaces"; +import test from "ava"; + +test.before(async (t) => { + // Init the worker and start a Sandbox server + const worker = await Worker.init(); + + // Prepare sandbox for tests, create accounts, deploy contracts, etx. + const root = worker.rootAccount; + + // Deploy the contract. + const statusMessage = await root.devDeploy("./build/status-message.wasm"); + + // Create test users + const ali = await root.createSubAccount("ali"); + const bob = await root.createSubAccount("bob"); + const carl = await root.createSubAccount("carl"); + + // Save state for test runs + t.context.worker = worker; + t.context.accounts = { root, statusMessage, ali, bob, carl }; }); -test.after.always(async t => { - await t.context.worker.tearDown().catch(error => { - console.log('Failed to tear down the worker:', error); - }); +test.after.always(async (t) => { + await t.context.worker.tearDown().catch((error) => { + console.log("Failed to tear down the worker:", error); + }); }); -test('Root gets null status', async t => { - const { statusMessage, root } = t.context.accounts; - const result = await statusMessage.view('get_status', { account_id: root.accountId }); - t.is(result, null); +test("Root gets null status", async (t) => { + const { statusMessage, root } = t.context.accounts; + const result = await statusMessage.view("get_status", { + account_id: root.accountId, + }); + t.is(result, null); }); -test('Ali sets then gets status', async t => { - const { ali, statusMessage } = t.context.accounts; - await ali.call(statusMessage, 'set_status', { message: 'hello' }); +test("Ali sets then gets status", async (t) => { + const { ali, statusMessage } = t.context.accounts; + await ali.call(statusMessage, "set_status", { message: "hello" }); - t.is( - await statusMessage.view('get_status', { account_id: ali.accountId }), - 'hello' - ); + t.is( + await statusMessage.view("get_status", { account_id: ali.accountId }), + "hello" + ); }); -test('Bob and Carl have different statuses', async t => { - const { statusMessage, bob, carl } = t.context.accounts; - await bob.call(statusMessage, 'set_status', { message: 'hello' }); - await carl.call(statusMessage, 'set_status', { message: 'world' }); - - const bobStatus = await statusMessage.view('get_status', { account_id: bob.accountId }); - const carlStatus = await statusMessage.view('get_status', { account_id: carl.accountId }); - t.is(bobStatus, 'hello'); - t.is(carlStatus, 'world'); +test("Bob and Carl have different statuses", async (t) => { + const { statusMessage, bob, carl } = t.context.accounts; + await bob.call(statusMessage, "set_status", { message: "hello" }); + await carl.call(statusMessage, "set_status", { message: "world" }); + + const bobStatus = await statusMessage.view("get_status", { + account_id: bob.accountId, + }); + const carlStatus = await statusMessage.view("get_status", { + account_id: carl.accountId, + }); + t.is(bobStatus, "hello"); + t.is(carlStatus, "world"); }); diff --git a/examples/ava.config.cjs b/examples/ava.config.cjs index a100daf68..d5a8c029f 100644 --- a/examples/ava.config.cjs +++ b/examples/ava.config.cjs @@ -1,8 +1,8 @@ -require('util').inspect.defaultOptions.depth = 5; // Increase AVA's printing depth +require("util").inspect.defaultOptions.depth = 5; // Increase AVA's printing depth module.exports = { - timeout: '300000', - files: ['**/*.ava.js'], + timeout: "300000", + files: ["**/*.ava.js"], failWithoutAssertions: false, - extensions: ['js'], + extensions: ["js"], }; diff --git a/examples/babel.config.json b/examples/babel.config.json index d01c909c1..e1d155602 100644 --- a/examples/babel.config.json +++ b/examples/babel.config.json @@ -2,7 +2,7 @@ "plugins": [ "near-sdk-js/lib/build-tools/include-bytes", "near-sdk-js/lib/build-tools/near-bindgen-exporter", - ["@babel/plugin-proposal-decorators", {"version": "legacy"}] + ["@babel/plugin-proposal-decorators", { "version": "legacy" }] ], "presets": ["@babel/preset-typescript"] } diff --git a/examples/jsconfig.json b/examples/jsconfig.json index d49b02077..a6d618635 100644 --- a/examples/jsconfig.json +++ b/examples/jsconfig.json @@ -1,8 +1,6 @@ { - "compilerOptions": { - "experimentalDecorators": true, - }, - "exclude": [ - "node_modules" - ], -} \ No newline at end of file + "compilerOptions": { + "experimentalDecorators": true + }, + "exclude": ["node_modules"] +} diff --git a/examples/src/clean-state.js b/examples/src/clean-state.js index cb9600675..4257450ee 100644 --- a/examples/src/clean-state.js +++ b/examples/src/clean-state.js @@ -1,20 +1,19 @@ -import { NearBindgen, call, view, near } from 'near-sdk-js' +import { NearBindgen, call, view, near } from "near-sdk-js"; @NearBindgen({}) class CleanState { - @call({}) - clean({ keys }) { - keys.forEach(key => near.storageRemove(key)) - } + @call({}) + clean({ keys }) { + keys.forEach((key) => near.storageRemove(key)); + } - @call({}) - put({ key, value }) { - near.storageWrite(key, value) - } + @call({}) + put({ key, value }) { + near.storageWrite(key, value); + } - @view({}) - get({ key }) { - - return near.storageRead(key) - } + @view({}) + get({ key }) { + return near.storageRead(key); + } } diff --git a/examples/src/counter-lowlevel.js b/examples/src/counter-lowlevel.js index c750eb712..f01249ad2 100644 --- a/examples/src/counter-lowlevel.js +++ b/examples/src/counter-lowlevel.js @@ -1,46 +1,46 @@ // This contract implements exact same functionality as counter.js, but only use low level APIs -import { near } from 'near-sdk-js' +import { near } from "near-sdk-js"; export function init() { - let argsRaw = near.input() - let args = JSON.parse(argsRaw || "{}") - let initial = args.initial || 0 - let count = initial - let state = JSON.stringify({ count }) - near.storageWrite('STATE', state) + let argsRaw = near.input(); + let args = JSON.parse(argsRaw || "{}"); + let initial = args.initial || 0; + let count = initial; + let state = JSON.stringify({ count }); + near.storageWrite("STATE", state); } function deserialize() { - let state = near.storageRead("STATE") - if (state) { - return JSON.parse(state) - } else { - return { count: 0 } - } + let state = near.storageRead("STATE"); + if (state) { + return JSON.parse(state); + } else { + return { count: 0 }; + } } export function getCount() { - let state = deserialize() - let count = state.count - near.valueReturn(JSON.stringify(count)) + let state = deserialize(); + let count = state.count; + near.valueReturn(JSON.stringify(count)); } export function increase() { - let argsRaw = near.input() - let args = JSON.parse(argsRaw || "{}") - let n = args.n || 1 - let state = deserialize() - state.count += n - near.log(`Counter increased to ${state.count}`) - near.storageWrite('STATE', JSON.stringify(state)) + let argsRaw = near.input(); + let args = JSON.parse(argsRaw || "{}"); + let n = args.n || 1; + let state = deserialize(); + state.count += n; + near.log(`Counter increased to ${state.count}`); + near.storageWrite("STATE", JSON.stringify(state)); } export function decrease() { - let argsRaw = near.input() - let args = JSON.parse(argsRaw || "{}") - let n = args.n || 1 - let state = deserialize() - state.count -= n - near.log(`Counter decreased to ${state.count}`) - near.storageWrite('STATE', JSON.stringify(state)) + let argsRaw = near.input(); + let args = JSON.parse(argsRaw || "{}"); + let n = args.n || 1; + let state = deserialize(); + state.count -= n; + near.log(`Counter decreased to ${state.count}`); + near.storageWrite("STATE", JSON.stringify(state)); } diff --git a/examples/src/counter.js b/examples/src/counter.js index 1f898a985..92dc70da5 100644 --- a/examples/src/counter.js +++ b/examples/src/counter.js @@ -1,33 +1,32 @@ -import { NearBindgen, near, call, view, initialize } from 'near-sdk-js' -import { isUndefined } from 'lodash-es' +import { NearBindgen, near, call, view, initialize } from "near-sdk-js"; +import { isUndefined } from "lodash-es"; @NearBindgen({}) class Counter { - constructor() { - this.count = 0 - } + constructor() { + this.count = 0; + } - @call({}) - increase({ n = 1 }) { - this.count += n - near.log(`Counter increased to ${this.count}`) - } + @call({}) + increase({ n = 1 }) { + this.count += n; + near.log(`Counter increased to ${this.count}`); + } - @call({}) - decrease({ n }) { - // you can use default argument `n=1` too - // this is to illustrate a npm dependency: lodash can be used - if (isUndefined(n)) { - this.count -= 1 - } else { - this.count -= n - } - near.log(`Counter decreased to ${this.count}`) + @call({}) + decrease({ n }) { + // you can use default argument `n=1` too + // this is to illustrate a npm dependency: lodash can be used + if (isUndefined(n)) { + this.count -= 1; + } else { + this.count -= n; } + near.log(`Counter decreased to ${this.count}`); + } - @view({}) - getCount() { - return this.count - } + @view({}) + getCount() { + return this.count; + } } - diff --git a/examples/src/counter.ts b/examples/src/counter.ts index 9ab98cb63..97830aea8 100644 --- a/examples/src/counter.ts +++ b/examples/src/counter.ts @@ -1,33 +1,32 @@ -import { NearBindgen, near, call, view, initialize } from 'near-sdk-js' -import { isUndefined } from 'lodash-es' -import { log } from './log' +import { NearBindgen, near, call, view, initialize } from "near-sdk-js"; +import { isUndefined } from "lodash-es"; +import { log } from "./log"; @NearBindgen({}) class Counter { - count: number = 0; + count = 0; - @call({}) - increase({ n = 1 }: { n: number }) { - this.count += n - near.log(`Counter increased to ${this.count}`) - } + @call({}) + increase({ n = 1 }: { n: number }) { + this.count += n; + near.log(`Counter increased to ${this.count}`); + } - @call({}) - decrease({ n }: { n: number }) { - // you can use default argument `n=1` too - // this is to illustrate a npm dependency: lodash can be used - if (isUndefined(n)) { - this.count -= 1 - } else { - this.count -= n - } - // this is to illustrate import a local ts module - log(`Counter decreased to ${this.count}`) + @call({}) + decrease({ n }: { n: number }) { + // you can use default argument `n=1` too + // this is to illustrate a npm dependency: lodash can be used + if (isUndefined(n)) { + this.count -= 1; + } else { + this.count -= n; } + // this is to illustrate import a local ts module + log(`Counter decreased to ${this.count}`); + } - @view({}) - getCount(): number { - return this.count - } + @view({}) + getCount(): number { + return this.count; + } } - diff --git a/examples/src/cross-contract-call.js b/examples/src/cross-contract-call.js index 40388903d..4e60aad91 100644 --- a/examples/src/cross-contract-call.js +++ b/examples/src/cross-contract-call.js @@ -1,42 +1,55 @@ -import { NearBindgen, call, view, initialize, near, bytes } from 'near-sdk-js' +import { NearBindgen, call, view, initialize, near, bytes } from "near-sdk-js"; @NearBindgen({ requireInit: true }) class OnCall { - constructor() { - this.personOnCall = '' - this.statusMessageContract = '' - } + constructor() { + this.personOnCall = ""; + this.statusMessageContract = ""; + } - @initialize({}) - init({ statusMessageContract }) { - this.personOnCall = "undefined" - this.statusMessageContract = statusMessageContract - } + @initialize({}) + init({ statusMessageContract }) { + this.personOnCall = "undefined"; + this.statusMessageContract = statusMessageContract; + } - @call({}) - set_person_on_call({ accountId }) { - near.log(`Trying to set ${accountId} on-call`) - const promise = near.promiseBatchCreate(this.statusMessageContract) - near.promiseBatchActionFunctionCall(promise, 'get_status', bytes(JSON.stringify({ account_id: accountId })), 0, 30000000000000) - near.promiseThen(promise, near.currentAccountId(), '_set_person_on_call_private', bytes(JSON.stringify({ accountId: accountId })), 0, 30000000000000); - } + @call({}) + set_person_on_call({ accountId }) { + near.log(`Trying to set ${accountId} on-call`); + const promise = near.promiseBatchCreate(this.statusMessageContract); + near.promiseBatchActionFunctionCall( + promise, + "get_status", + bytes(JSON.stringify({ account_id: accountId })), + 0, + 30000000000000 + ); + near.promiseThen( + promise, + near.currentAccountId(), + "_set_person_on_call_private", + bytes(JSON.stringify({ accountId: accountId })), + 0, + 30000000000000 + ); + } - @call({ privateFunction: true }) - _set_person_on_call_private({ accountId }) { - near.log(`_set_person_on_call_private called, accountId ${accountId}`) - const status = JSON.parse(near.promiseResult(0)) - near.log(`${accountId} status is ${status}`) - if (status === 'AVAILABLE') { - this.personOnCall = accountId - near.log(`${accountId} set on-call`) - } else { - near.log(`${accountId} can not be set on-call`) - } + @call({ privateFunction: true }) + _set_person_on_call_private({ accountId }) { + near.log(`_set_person_on_call_private called, accountId ${accountId}`); + const status = JSON.parse(near.promiseResult(0)); + near.log(`${accountId} status is ${status}`); + if (status === "AVAILABLE") { + this.personOnCall = accountId; + near.log(`${accountId} set on-call`); + } else { + near.log(`${accountId} can not be set on-call`); } + } - @view({}) - person_on_call() { - near.log(`Returning person on-call: ${this.personOnCall}`) - return this.personOnCall - } + @view({}) + person_on_call() { + near.log(`Returning person on-call: ${this.personOnCall}`); + return this.personOnCall; + } } diff --git a/examples/src/fungible-token-helper.js b/examples/src/fungible-token-helper.js index fd2bc18a1..05f420781 100644 --- a/examples/src/fungible-token-helper.js +++ b/examples/src/fungible-token-helper.js @@ -2,18 +2,18 @@ import { NearBindgen, call, view } from "near-sdk-js"; @NearBindgen({}) class FungibleTokenHelper { - constructor() { - this.data = ""; - } + constructor() { + this.data = ""; + } - @call({}) - ftOnTransfer({ senderId, amount, msg, receiverId }) { - const concatString = `[${amount} from ${senderId} to ${receiverId}] ${msg} `; - this.data = this.data.concat("", concatString); - } + @call({}) + ftOnTransfer({ senderId, amount, msg, receiverId }) { + const concatString = `[${amount} from ${senderId} to ${receiverId}] ${msg} `; + this.data = this.data.concat("", concatString); + } - @view({}) - getContractData() { - return this.data; - } -} \ No newline at end of file + @view({}) + getContractData() { + return this.data; + } +} diff --git a/examples/src/fungible-token-lockable.js b/examples/src/fungible-token-lockable.js index 9b3c36d44..9aa1ae399 100644 --- a/examples/src/fungible-token-lockable.js +++ b/examples/src/fungible-token-lockable.js @@ -1,229 +1,241 @@ import { - NearBindgen, - call, - view, - initialize, - near, - LookupMap, -} from 'near-sdk-js' + NearBindgen, + call, + view, + initialize, + near, + LookupMap, +} from "near-sdk-js"; class Account { - constructor(balance, allowances, lockedBalances) { - this.balance = balance // Current unlocked balance - this.allowances = allowances // Allowed account to the allowance amount - this.lockedBalances = lockedBalances // Allowed account to locked balance - } - - setAllowance(escrowAccountId, allowance) { - if (allowance > 0) { - this.allowances[escrowAccountId] = allowance - } else if (allowance === 0) { - delete this.allowances[escrowAccountId] - } else { - throw Error("Allowance can't be negative") - } - } - - getAllowance(escrowAccountId) { - return this.allowances[escrowAccountId] || 0 - } - - setLockedBalance(escrowAccountId, lockedBalance) { - if (lockedBalance > 0) { - this.lockedBalances[escrowAccountId] = lockedBalance - } else if (lockedBalance === 0) { - delete this.lockedBalances[escrowAccountId] - } else { - throw Error("Locked balance cannot be negative") - } - } - - getLockedBalance(escrowAccountId) { - return this.lockedBalances[escrowAccountId] || 0 - } - - totalBalance() { - let totalLockedBalance = - Object.values(this.lockedBalances).reduce((acc, val) => acc + val, 0) - return this.balance + totalLockedBalance - } + constructor(balance, allowances, lockedBalances) { + this.balance = balance; // Current unlocked balance + this.allowances = allowances; // Allowed account to the allowance amount + this.lockedBalances = lockedBalances; // Allowed account to locked balance + } + + setAllowance(escrowAccountId, allowance) { + if (allowance > 0) { + this.allowances[escrowAccountId] = allowance; + } else if (allowance === 0) { + delete this.allowances[escrowAccountId]; + } else { + throw Error("Allowance can't be negative"); + } + } + + getAllowance(escrowAccountId) { + return this.allowances[escrowAccountId] || 0; + } + + setLockedBalance(escrowAccountId, lockedBalance) { + if (lockedBalance > 0) { + this.lockedBalances[escrowAccountId] = lockedBalance; + } else if (lockedBalance === 0) { + delete this.lockedBalances[escrowAccountId]; + } else { + throw Error("Locked balance cannot be negative"); + } + } + + getLockedBalance(escrowAccountId) { + return this.lockedBalances[escrowAccountId] || 0; + } + + totalBalance() { + let totalLockedBalance = Object.values(this.lockedBalances).reduce( + (acc, val) => acc + val, + 0 + ); + return this.balance + totalLockedBalance; + } } @NearBindgen({ initRequired: true }) class LockableFungibleToken { - constructor() { - this.accounts = new LookupMap('a') // Account ID -> Account mapping - this.totalSupply = 0 // Total supply of the all tokens - } - - @initialize({}) - init({ prefix, totalSupply }) { - this.accounts = new LookupMap(prefix) - this.totalSupply = totalSupply - let ownerId = near.signerAccountId() - let ownerAccount = this.getAccount(ownerId) - ownerAccount.balance = this.totalSupply - this.setAccount(ownerId, ownerAccount) - } - - getAccount(ownerId) { - let account = this.accounts.get(ownerId) - if (account === null) { - return new Account(0, {}, {}) - } - return new Account(account.balance, account.allowances, account.lockedBalances) - } - - setAccount(accountId, account) { - this.accounts.set(accountId, account) - } - - @call({}) - setAllowance({ escrowAccountId, allowance }) { - let ownerId = near.predecessorAccountId() - if (escrowAccountId === ownerId) { - throw Error("Can't set allowance for yourself") - } - let account = this.getAccount(ownerId) - let lockedBalance = account.getLockedBalance(escrowAccountId) - if (lockedBalance > allowance) { - throw Error("The new allowance can't be less than the amount of locked tokens") - } - - account.setAllowance(escrowAccountId, allowance - lockedBalance) - this.setAccount(ownerId, account) - } - - @call({}) - lock({ ownerId, lockAmount }) { - if (lockAmount <= 0) { - throw Error("Can't lock 0 or less tokens") - } - let escrowAccountId = near.predecessorAccountId() - let account = this.getAccount(ownerId) - + constructor() { + this.accounts = new LookupMap("a"); // Account ID -> Account mapping + this.totalSupply = 0; // Total supply of the all tokens + } + + @initialize({}) + init({ prefix, totalSupply }) { + this.accounts = new LookupMap(prefix); + this.totalSupply = totalSupply; + let ownerId = near.signerAccountId(); + let ownerAccount = this.getAccount(ownerId); + ownerAccount.balance = this.totalSupply; + this.setAccount(ownerId, ownerAccount); + } + + getAccount(ownerId) { + let account = this.accounts.get(ownerId); + if (account === null) { + return new Account(0, {}, {}); + } + return new Account( + account.balance, + account.allowances, + account.lockedBalances + ); + } + + setAccount(accountId, account) { + this.accounts.set(accountId, account); + } + + @call({}) + setAllowance({ escrowAccountId, allowance }) { + let ownerId = near.predecessorAccountId(); + if (escrowAccountId === ownerId) { + throw Error("Can't set allowance for yourself"); + } + let account = this.getAccount(ownerId); + let lockedBalance = account.getLockedBalance(escrowAccountId); + if (lockedBalance > allowance) { + throw Error( + "The new allowance can't be less than the amount of locked tokens" + ); + } + + account.setAllowance(escrowAccountId, allowance - lockedBalance); + this.setAccount(ownerId, account); + } + + @call({}) + lock({ ownerId, lockAmount }) { + if (lockAmount <= 0) { + throw Error("Can't lock 0 or less tokens"); + } + let escrowAccountId = near.predecessorAccountId(); + let account = this.getAccount(ownerId); + + // Checking and updating unlocked balance + if (account.balance < lockAmount) { + throw Error("Not enough unlocked balance"); + } + account.balance -= lockAmount; + + // If locking by escrow, need to check and update the allowance. + if (escrowAccountId !== ownerId) { + let allowance = account.getAllowance(escrowAccountId); + if (allowance < lockAmount) { + throw Error("Not enough allowance"); + } + account.setAllowance(escrowAccountId, allowance - lockAmount); + } + + // Updating total lock balance + let lockedBalance = account.getLockedBalance(escrowAccountId); + account.setLockedBalance(escrowAccountId, lockedBalance + lockAmount); + + this.setAccount(ownerId, account); + } + + @call({}) + unlock({ ownerId, unlockAmount }) { + if (unlockAmount <= 0) { + throw Error("Can't unlock 0 or less tokens"); + } + let escrowAccountId = near.predecessorAccountId(); + let account = this.getAccount(ownerId); + + // Checking and updating locked balance + let lockedBalance = account.getLockedBalance(escrowAccountId); + if (lockedBalance < unlockAmount) { + throw Error("Not enough locked tokens"); + } + account.setLockedBalance(escrowAccountId, lockedBalance - unlockAmount); + + // If unlocking by escrow, need to update allowance. + if (escrowAccountId !== ownerId) { + let allowance = account.getAllowance(escrowAccountId); + account.setAllowance(escrowAccountId, allowance + unlockAmount); + } + + // Updating unlocked balance + account.balance += unlockAmount; + + this.setAccount(ownerId, account); + } + + @call({}) + transferFrom({ ownerId, newOwnerId, amount }) { + if (amount <= 0) { + throw Error("Can't transfer 0 or less tokens"); + } + let escrowAccountId = near.predecessorAccountId(); + let account = this.getAccount(ownerId); + + // Checking and updating locked balance + let lockedBalance = account.getLockedBalance(escrowAccountId); + var remainingAmount; + if (lockedBalance >= amount) { + account.setLockedBalance(escrowAccountId, lockedBalance - amount); + remainingAmount = 0; + } else { + account.setLockedBalance(escrowAccountId, 0); + remainingAmount = amount - lockedBalance; + } + + // If there is remaining balance after the locked balance, we try to use unlocked tokens. + if (remainingAmount > 0) { + // Checking and updating unlocked balance + if (account.balance < remainingAmount) { + throw Error("Not enough unlocked balance"); + } + account.balance -= remainingAmount; + + // If transferring by escrow, need to check and update allowance. + if (escrowAccountId !== ownerId) { + let allowance = account.getAllowance(escrowAccountId); // Checking and updating unlocked balance - if (account.balance < lockAmount) { - throw Error("Not enough unlocked balance") - } - account.balance -= lockAmount - - // If locking by escrow, need to check and update the allowance. - if (escrowAccountId !== ownerId) { - let allowance = account.getAllowance(escrowAccountId) - if (allowance < lockAmount) { - throw Error("Not enough allowance") - } - account.setAllowance(escrowAccountId, allowance - lockAmount) - } - - // Updating total lock balance - let lockedBalance = account.getLockedBalance(escrowAccountId) - account.setLockedBalance(escrowAccountId, lockedBalance + lockAmount) - - this.setAccount(ownerId, account) - } - - @call({}) - unlock({ ownerId, unlockAmount }) { - if (unlockAmount <= 0) { - throw Error("Can't unlock 0 or less tokens") - } - let escrowAccountId = near.predecessorAccountId() - let account = this.getAccount(ownerId) - - // Checking and updating locked balance - let lockedBalance = account.getLockedBalance(escrowAccountId) - if (lockedBalance < unlockAmount) { - throw Error("Not enough locked tokens") - } - account.setLockedBalance(escrowAccountId, lockedBalance - unlockAmount) - - // If unlocking by escrow, need to update allowance. - if (escrowAccountId !== ownerId) { - let allowance = account.getAllowance(escrowAccountId) - account.setAllowance(escrowAccountId, allowance + unlockAmount) - } - - // Updating unlocked balance - account.balance += unlockAmount - - this.setAccount(ownerId, account) - } - - @call({}) - transferFrom({ ownerId, newOwnerId, amount }) { - if (amount <= 0) { - throw Error("Can't transfer 0 or less tokens") - } - let escrowAccountId = near.predecessorAccountId() - let account = this.getAccount(ownerId) - - // Checking and updating locked balance - let lockedBalance = account.getLockedBalance(escrowAccountId) - var remainingAmount - if (lockedBalance >= amount) { - account.setLockedBalance(escrowAccountId, lockedBalance - amount) - remainingAmount = 0 - } else { - account.setLockedBalance(escrowAccountId, 0) - remainingAmount = amount - lockedBalance - } - - // If there is remaining balance after the locked balance, we try to use unlocked tokens. - if (remainingAmount > 0) { - // Checking and updating unlocked balance - if (account.balance < remainingAmount) { - throw Error("Not enough unlocked balance") - } - account.balance -= remainingAmount - - // If transferring by escrow, need to check and update allowance. - if (escrowAccountId !== ownerId) { - let allowance = account.getAllowance(escrowAccountId) - // Checking and updating unlocked balance - if (allowance < remainingAmount) { - throw Error("Not enough allowance") - } - account.setAllowance(escrowAccountId, allowance - remainingAmount) - } + if (allowance < remainingAmount) { + throw Error("Not enough allowance"); } - - this.setAccount(ownerId, account) - - // Deposit amount to the new owner - let newAccount = this.getAccount(newOwnerId) - newAccount.balance += amount - this.setAccount(newOwnerId, newAccount) - } - - @call({}) - transfer({ newOwnerId, amount }) { - this.transferFrom({ ownerId: near.predecessorAccountId(), newOwnerId, amount }) - } - - @view({}) - getTotalSupply() { - return this.totalSupply - } - - @view({}) - getTotalBalance({ ownerId }) { - return this.getAccount(ownerId).totalBalance() - } - - @view({}) - getUnlockedBalance({ ownerId }) { - return this.getAccount(ownerId).balance - } - - @view({}) - getAllowance({ ownerId, escrowAccountId }) { - return this.getAccount(ownerId).getAllowance(escrowAccountId) - } - - @view({}) - getLockedBalance({ ownerId, escrowAccountId }) { - return this.getAccount(ownerId).getLockedBalance(escrowAccountId) - } + account.setAllowance(escrowAccountId, allowance - remainingAmount); + } + } + + this.setAccount(ownerId, account); + + // Deposit amount to the new owner + let newAccount = this.getAccount(newOwnerId); + newAccount.balance += amount; + this.setAccount(newOwnerId, newAccount); + } + + @call({}) + transfer({ newOwnerId, amount }) { + this.transferFrom({ + ownerId: near.predecessorAccountId(), + newOwnerId, + amount, + }); + } + + @view({}) + getTotalSupply() { + return this.totalSupply; + } + + @view({}) + getTotalBalance({ ownerId }) { + return this.getAccount(ownerId).totalBalance(); + } + + @view({}) + getUnlockedBalance({ ownerId }) { + return this.getAccount(ownerId).balance; + } + + @view({}) + getAllowance({ ownerId, escrowAccountId }) { + return this.getAccount(ownerId).getAllowance(escrowAccountId); + } + + @view({}) + getLockedBalance({ ownerId, escrowAccountId }) { + return this.getAccount(ownerId).getLockedBalance(escrowAccountId); + } } diff --git a/examples/src/fungible-token.js b/examples/src/fungible-token.js index 0cb6be8dc..08cb587f1 100644 --- a/examples/src/fungible-token.js +++ b/examples/src/fungible-token.js @@ -1,77 +1,87 @@ import { - NearBindgen, - call, - view, - initialize, - near, - LookupMap, - assert -} from 'near-sdk-js' - + NearBindgen, + call, + view, + initialize, + near, + LookupMap, + assert, +} from "near-sdk-js"; @NearBindgen({ initRequired: true }) class FungibleToken { - constructor() { - this.accounts = new LookupMap('a') - this.totalSupply = 0 - } + constructor() { + this.accounts = new LookupMap("a"); + this.totalSupply = 0; + } - @initialize({}) - init({ prefix, totalSupply }) { - this.accounts = new LookupMap(prefix) - this.totalSupply = totalSupply - this.accounts.set(near.signerAccountId(), this.totalSupply) - // In a real world Fungible Token contract, storage management is required to denfense drain-storage attack - } + @initialize({}) + init({ prefix, totalSupply }) { + this.accounts = new LookupMap(prefix); + this.totalSupply = totalSupply; + this.accounts.set(near.signerAccountId(), this.totalSupply); + // In a real world Fungible Token contract, storage management is required to denfense drain-storage attack + } - internalDeposit({ accountId, amount }) { - let balance = this.accounts.get(accountId) || '0' - let newBalance = BigInt(balance) + BigInt(amount) - this.accounts.set(accountId, newBalance.toString()) - this.totalSupply = (BigInt(this.totalSupply) + BigInt(amount)).toString() - } + internalDeposit({ accountId, amount }) { + let balance = this.accounts.get(accountId) || "0"; + let newBalance = BigInt(balance) + BigInt(amount); + this.accounts.set(accountId, newBalance.toString()); + this.totalSupply = (BigInt(this.totalSupply) + BigInt(amount)).toString(); + } - internalWithdraw({ accountId, amount }) { - let balance = this.accounts.get(accountId) || '0' - let newBalance = BigInt(balance) - BigInt(amount) - assert(newBalance >= 0n, "The account doesn't have enough balance") - this.accounts.set(accountId, newBalance.toString()) - let newSupply = BigInt(this.totalSupply) - BigInt(amount) - assert(newSupply >= 0n, "Total supply overflow") - this.totalSupply = newSupply.toString() - } + internalWithdraw({ accountId, amount }) { + let balance = this.accounts.get(accountId) || "0"; + let newBalance = BigInt(balance) - BigInt(amount); + assert(newBalance >= 0n, "The account doesn't have enough balance"); + this.accounts.set(accountId, newBalance.toString()); + let newSupply = BigInt(this.totalSupply) - BigInt(amount); + assert(newSupply >= 0n, "Total supply overflow"); + this.totalSupply = newSupply.toString(); + } - internalTransfer({ senderId, receiverId, amount, memo }) { - assert(senderId != receiverId, "Sender and receiver should be different") - let amountInt = BigInt(amount) - assert(amountInt > 0n, "The amount should be a positive number") - this.internalWithdraw({ accountId: senderId, amount }) - this.internalDeposit({ accountId: receiverId, amount }) - } + internalTransfer({ senderId, receiverId, amount, memo }) { + assert(senderId != receiverId, "Sender and receiver should be different"); + let amountInt = BigInt(amount); + assert(amountInt > 0n, "The amount should be a positive number"); + this.internalWithdraw({ accountId: senderId, amount }); + this.internalDeposit({ accountId: receiverId, amount }); + } - @call({}) - ftTransfer({ receiverId, amount, memo }) { - let senderId = near.predecessorAccountId() - this.internalTransfer({ senderId, receiverId, amount, memo }) - } + @call({}) + ftTransfer({ receiverId, amount, memo }) { + let senderId = near.predecessorAccountId(); + this.internalTransfer({ senderId, receiverId, amount, memo }); + } - @call({}) - ftTransferCall({ receiverId, amount, memo, msg }) { - let senderId = near.predecessorAccountId() - this.internalTransfer({ senderId, receiverId, amount, memo }); - const promise = near.promiseBatchCreate(receiverId); - const params = { senderId: senderId, amount: amount, msg: msg, receiverId: receiverId }; - near.promiseBatchActionFunctionCall(promise, 'ftOnTransfer', JSON.stringify(params), 0, 30000000000000); - return near.promiseReturn(); - } + @call({}) + ftTransferCall({ receiverId, amount, memo, msg }) { + let senderId = near.predecessorAccountId(); + this.internalTransfer({ senderId, receiverId, amount, memo }); + const promise = near.promiseBatchCreate(receiverId); + const params = { + senderId: senderId, + amount: amount, + msg: msg, + receiverId: receiverId, + }; + near.promiseBatchActionFunctionCall( + promise, + "ftOnTransfer", + JSON.stringify(params), + 0, + 30000000000000 + ); + return near.promiseReturn(); + } - @view({}) - ftTotalSupply() { - return this.totalSupply - } + @view({}) + ftTotalSupply() { + return this.totalSupply; + } - @view({}) - ftBalanceOf({ accountId }) { - return this.accounts.get(accountId) || '0' - } + @view({}) + ftBalanceOf({ accountId }) { + return this.accounts.get(accountId) || "0"; + } } diff --git a/examples/src/log.ts b/examples/src/log.ts index dfeb319f0..924c1e827 100644 --- a/examples/src/log.ts +++ b/examples/src/log.ts @@ -1,5 +1,5 @@ -import {near} from 'near-sdk-js' +import { near } from "near-sdk-js"; export function log(msg: any) { - near.log(msg) -} \ No newline at end of file + near.log(msg); +} diff --git a/examples/src/non-fungible-token-receiver.js b/examples/src/non-fungible-token-receiver.js index a7e57571a..7e2a29a2a 100644 --- a/examples/src/non-fungible-token-receiver.js +++ b/examples/src/non-fungible-token-receiver.js @@ -1,31 +1,33 @@ -import { NearBindgen, call, near, assert, initialize } from 'near-sdk-js' +import { NearBindgen, call, near, assert, initialize } from "near-sdk-js"; @NearBindgen({ requireInit: true }) class NftContract { - constructor() { - this.nonFungibleTokenAccountId = '' - } + constructor() { + this.nonFungibleTokenAccountId = ""; + } - @initialize({}) - init({ nonFungibleTokenAccountId }) { - this.nonFungibleTokenAccountId = nonFungibleTokenAccountId - } + @initialize({}) + init({ nonFungibleTokenAccountId }) { + this.nonFungibleTokenAccountId = nonFungibleTokenAccountId; + } - @call({}) - nftOnTransfer({ senderId, previousOwnerId, tokenId, msg }) { - near.log(`nftOnTransfer called, params: senderId: ${senderId}, previousOwnerId: ${previousOwnerId}, tokenId: ${tokenId}, msg: ${msg}`) - assert( - near.predecessorAccountId() === this.nonFungibleTokenAccountId, - "Only supports the one non-fungible token contract" - ) - if (msg === "return-it-now") { - near.log(`Returning ${tokenId} to ${senderId}`) - return false - } else if (msg === "keep-it-now") { - near.log(`Keep ${tokenId}`) - return true - } else { - throw Error("unsupported msg") - } + @call({}) + nftOnTransfer({ senderId, previousOwnerId, tokenId, msg }) { + near.log( + `nftOnTransfer called, params: senderId: ${senderId}, previousOwnerId: ${previousOwnerId}, tokenId: ${tokenId}, msg: ${msg}` + ); + assert( + near.predecessorAccountId() === this.nonFungibleTokenAccountId, + "Only supports the one non-fungible token contract" + ); + if (msg === "return-it-now") { + near.log(`Returning ${tokenId} to ${senderId}`); + return false; + } else if (msg === "keep-it-now") { + near.log(`Keep ${tokenId}`); + return true; + } else { + throw Error("unsupported msg"); } + } } diff --git a/examples/src/non-fungible-token.js b/examples/src/non-fungible-token.js index b9fb45c4f..b0c6120da 100644 --- a/examples/src/non-fungible-token.js +++ b/examples/src/non-fungible-token.js @@ -1,90 +1,147 @@ -import { NearBindgen, call, view, initialize, near, LookupMap, bytes, assert } from 'near-sdk-js' +import { + NearBindgen, + call, + view, + initialize, + near, + LookupMap, + bytes, + assert, +} from "near-sdk-js"; class Token { - constructor(token_id, owner_id) { - this.token_id = token_id; - this.owner_id = owner_id; - } + constructor(token_id, owner_id) { + this.token_id = token_id; + this.owner_id = owner_id; + } } @NearBindgen({ requireInit: true }) class NftContract { - constructor() { - this.owner_id = '' - this.owner_by_id = new LookupMap('a') - } - - @initialize({}) - init({ owner_id, owner_by_id_prefix }) { - this.owner_id = owner_id - this.owner_by_id = new LookupMap(owner_by_id_prefix) - } - - internalTransfer({ sender_id, receiver_id, token_id, approval_id, memo }) { - let owner_id = this.owner_by_id.get(token_id) - - assert(owner_id !== null, "Token not found") - assert(sender_id === owner_id, "Sender must be the current owner") - assert(owner_id !== receiver_id, "Current and next owner must differ") - - this.owner_by_id.set(token_id, receiver_id) - - return owner_id + constructor() { + this.owner_id = ""; + this.owner_by_id = new LookupMap("a"); + } + + @initialize({}) + init({ owner_id, owner_by_id_prefix }) { + this.owner_id = owner_id; + this.owner_by_id = new LookupMap(owner_by_id_prefix); + } + + internalTransfer({ sender_id, receiver_id, token_id, approval_id, memo }) { + let owner_id = this.owner_by_id.get(token_id); + + assert(owner_id !== null, "Token not found"); + assert(sender_id === owner_id, "Sender must be the current owner"); + assert(owner_id !== receiver_id, "Current and next owner must differ"); + + this.owner_by_id.set(token_id, receiver_id); + + return owner_id; + } + + @call({}) + nftTransfer({ receiver_id, token_id, approval_id, memo }) { + let sender_id = near.predecessorAccountId(); + this.internalTransfer({ + sender_id, + receiver_id, + token_id, + approval_id, + memo, + }); + } + + @call({}) + nftTransferCall({ receiver_id, token_id, approval_id, memo, msg }) { + near.log( + `nftTransferCall called, receiver_id ${receiver_id}, token_id ${token_id}` + ); + let sender_id = near.predecessorAccountId(); + let old_owner_id = this.internalTransfer({ + sender_id, + receiver_id, + token_id, + approval_id, + memo, + }); + + const promise = near.promiseBatchCreate(receiver_id); + near.promiseBatchActionFunctionCall( + promise, + "nftOnTransfer", + bytes( + JSON.stringify({ + senderId: sender_id, + previousOwnerId: old_owner_id, + tokenId: token_id, + msg: msg, + }) + ), + 0, + 30000000000000 + ); + near.promiseThen( + promise, + near.currentAccountId(), + "_nftResolveTransfer", + bytes(JSON.stringify({ sender_id, receiver_id, token_id })), + 0, + 30000000000000 + ); + } + + @call({ privateFunction: true }) + _nftResolveTransfer({ sender_id, receiver_id, token_id }) { + near.log( + `_nftResolveTransfer called, receiver_id ${receiver_id}, token_id ${token_id}` + ); + const isTokenTransfered = JSON.parse(near.promiseResult(0)); + near.log( + `${token_id} ${ + isTokenTransfered ? "was transfered" : "was NOT transfered" + }` + ); + + if (!isTokenTransfered) { + near.log(`Returning ${token_id} to ${receiver_id}`); + const currentOwner = this.owner_by_id.get(token_id); + if (currentOwner === receiver_id) { + this.internalTransfer({ + sender_id: receiver_id, + receiver_id: sender_id, + token_id: token_id, + approval_id: null, + memo: null, + }); + near.log(`${token_id} returned to ${sender_id}`); + return; + } + near.log( + `Failed to return ${token_id}. It was burned or not owned by ${receiver_id} now.` + ); } + } - @call({}) - nftTransfer({ receiver_id, token_id, approval_id, memo }) { - let sender_id = near.predecessorAccountId() - this.internalTransfer({ sender_id, receiver_id, token_id, approval_id, memo }) - } - - @call({}) - nftTransferCall({ receiver_id, token_id, approval_id, memo, msg }) { - near.log(`nftTransferCall called, receiver_id ${receiver_id}, token_id ${token_id}`) - let sender_id = near.predecessorAccountId() - let old_owner_id = this.internalTransfer({ sender_id, receiver_id, token_id, approval_id, memo }) - - const promise = near.promiseBatchCreate(receiver_id) - near.promiseBatchActionFunctionCall(promise, 'nftOnTransfer', bytes(JSON.stringify({ senderId: sender_id, previousOwnerId: old_owner_id, tokenId: token_id, msg: msg })), 0, 30000000000000) - near.promiseThen(promise, near.currentAccountId(), '_nftResolveTransfer', bytes(JSON.stringify({ sender_id, receiver_id, token_id })), 0, 30000000000000); - } + @call({}) + nftMint({ token_id, token_owner_id, token_metadata }) { + let sender_id = near.predecessorAccountId(); + assert(sender_id === this.owner_id, "Unauthorized"); + assert(this.owner_by_id.get(token_id) === null, "Token ID must be unique"); - @call({ privateFunction: true }) - _nftResolveTransfer({ sender_id, receiver_id, token_id }) { - near.log(`_nftResolveTransfer called, receiver_id ${receiver_id}, token_id ${token_id}`) - const isTokenTransfered = JSON.parse(near.promiseResult(0)) - near.log(`${token_id} ${isTokenTransfered ? 'was transfered' : 'was NOT transfered'}`) - - if (!isTokenTransfered) { - near.log(`Returning ${token_id} to ${receiver_id}`) - const currentOwner = this.owner_by_id.get(token_id) - if (currentOwner === receiver_id) { - this.internalTransfer({ sender_id: receiver_id, receiver_id: sender_id, token_id: token_id, approval_id: null, memo: null }) - near.log(`${token_id} returned to ${sender_id}`) - return - } - near.log(`Failed to return ${token_id}. It was burned or not owned by ${receiver_id} now.`) - } - } - - @call({}) - nftMint({ token_id, token_owner_id, token_metadata }) { - let sender_id = near.predecessorAccountId() - assert(sender_id === this.owner_id, "Unauthorized") - assert(this.owner_by_id.get(token_id) === null, "Token ID must be unique") + this.owner_by_id.set(token_id, token_owner_id); - this.owner_by_id.set(token_id, token_owner_id) + return new Token(token_id, token_owner_id); + } - return new Token(token_id, token_owner_id) + @view({}) + nftToken({ token_id }) { + let owner_id = this.owner_by_id.get(token_id); + if (owner_id === null) { + return null; } - @view({}) - nftToken({ token_id }) { - let owner_id = this.owner_by_id.get(token_id) - if (owner_id === null) { - return null - } - - return new Token(token_id, owner_id) - } + return new Token(token_id, owner_id); + } } diff --git a/examples/src/parking-lot.ts b/examples/src/parking-lot.ts index effa2b72b..c74010fb7 100644 --- a/examples/src/parking-lot.ts +++ b/examples/src/parking-lot.ts @@ -1,70 +1,82 @@ -import { NearBindgen, near, call, view, LookupMap } from 'near-sdk-js' +import { NearBindgen, near, call, view, LookupMap } from "near-sdk-js"; class CarSpecs { - id: number; - color: string; - price: number; - engine: Engine; + id: number; + color: string; + price: number; + engine: Engine; - constructor(id: number, color: string, price: number, engine: Engine) { - this.id = id; - this.color = color; - this.price = price; - this.engine = engine; - } + constructor(id: number, color: string, price: number, engine: Engine) { + this.id = id; + this.color = color; + this.price = price; + this.engine = engine; + } } class Engine { - hp: number; + hp: number; - constructor(hp: number) { - this.hp = hp; - } + constructor(hp: number) { + this.hp = hp; + } - run(): string { - if (this.hp > 400) { - return "boom" - } else { - return "zoom" - } + run(): string { + if (this.hp > 400) { + return "boom"; + } else { + return "zoom"; } + } } @NearBindgen({}) class ParkingLot { - cars: LookupMap; - constructor() { - this.cars = new LookupMap('a'); - } + cars: LookupMap; + constructor() { + this.cars = new LookupMap("a"); + } - @call({}) - addCar({ name, id, color, price, engineHp }: { name: string, id: number, color: string, price: number, engineHp: number }) { - // args can be json arguments only, they cannot be of a JS/TS class like following, unless override NearContract.deserializeArgs method. - // addCar({ name, specs }: { name: string, specs: CarSpecs }) { - let engine = new Engine(engineHp) - let car = new CarSpecs(id, color, price, engine); - near.log(`addCar() called, name: ${name}, specs: ${JSON.stringify(car)}`) - this.cars.set(name, car) - } + @call({}) + addCar({ + name, + id, + color, + price, + engineHp, + }: { + name: string; + id: number; + color: string; + price: number; + engineHp: number; + }) { + // args can be json arguments only, they cannot be of a JS/TS class like following, unless override NearContract.deserializeArgs method. + // addCar({ name, specs }: { name: string, specs: CarSpecs }) { + const engine = new Engine(engineHp); + const car = new CarSpecs(id, color, price, engine); + near.log(`addCar() called, name: ${name}, specs: ${JSON.stringify(car)}`); + this.cars.set(name, car); + } - @call({}) - removeCar({ name }: { name: string }) { - near.log(`removeCar() called, name: ${name}`) - this.cars.remove(name) - } + @call({}) + removeCar({ name }: { name: string }) { + near.log(`removeCar() called, name: ${name}`); + this.cars.remove(name); + } - @view({}) - getCarSpecs({ name }: { name: string }) { - near.log(`getCarSpecs() called, name: ${name}`) - return this.cars.get(name) - } + @view({}) + getCarSpecs({ name }: { name: string }) { + near.log(`getCarSpecs() called, name: ${name}`); + return this.cars.get(name); + } - @view({}) - runCar({ name }: { name: string }) { - /* We are getting plain carSpecs object from the storage. + @view({}) + runCar({ name }: { name: string }) { + /* We are getting plain carSpecs object from the storage. It needs to be converted to the class object in order to execute engine.run() function.*/ - let carSpecs = this.cars.get(name) as CarSpecs; - let engine = new Engine(carSpecs.engine.hp) - return engine.run() - } -} \ No newline at end of file + const carSpecs = this.cars.get(name) as CarSpecs; + const engine = new Engine(carSpecs.engine.hp); + return engine.run(); + } +} diff --git a/examples/src/status-message-collections.js b/examples/src/status-message-collections.js index f84dddfee..9c196223a 100644 --- a/examples/src/status-message-collections.js +++ b/examples/src/status-message-collections.js @@ -1,36 +1,42 @@ -import { NearBindgen, call, view, near, LookupSet, UnorderedMap } from 'near-sdk-js' +import { + NearBindgen, + call, + view, + near, + LookupSet, + UnorderedMap, +} from "near-sdk-js"; @NearBindgen({}) class StatusMessage { - constructor() { - this.records = new UnorderedMap('a') - this.uniqueValues = new LookupSet('b') - } + constructor() { + this.records = new UnorderedMap("a"); + this.uniqueValues = new LookupSet("b"); + } - @call({}) - set_status({ message }) { - let account_id = near.signerAccountId() - near.log(`${account_id} set_status with message ${message}`) - this.records.set(account_id, message) - this.uniqueValues.set(message) - } + @call({}) + set_status({ message }) { + let account_id = near.signerAccountId(); + near.log(`${account_id} set_status with message ${message}`); + this.records.set(account_id, message); + this.uniqueValues.set(message); + } - @view({}) - get_status({ account_id }) { - near.log(`get_status for account_id ${account_id}`) - return this.records.get(account_id) - } + @view({}) + get_status({ account_id }) { + near.log(`get_status for account_id ${account_id}`); + return this.records.get(account_id); + } - @view({}) - has_status({ message }) { - // used for test LookupMap - return this.uniqueValues.contains(message) - } + @view({}) + has_status({ message }) { + // used for test LookupMap + return this.uniqueValues.contains(message); + } - @view({}) - get_all_statuses() { - // used for test UnorderedMap - return this.records.toArray() - } + @view({}) + get_all_statuses() { + // used for test UnorderedMap + return this.records.toArray(); + } } - diff --git a/examples/src/status-message.js b/examples/src/status-message.js index 7ec2168fa..a9c99d9e9 100644 --- a/examples/src/status-message.js +++ b/examples/src/status-message.js @@ -1,22 +1,21 @@ -import { NearBindgen, call, view, near } from 'near-sdk-js' +import { NearBindgen, call, view, near } from "near-sdk-js"; @NearBindgen({}) class StatusMessage { - constructor() { - this.records = {} - } + constructor() { + this.records = {}; + } - @call({}) - set_status({ message }) { - let account_id = near.signerAccountId() - near.log(`${account_id} set_status with message ${message}`) - this.records[account_id] = message - } + @call({}) + set_status({ message }) { + let account_id = near.signerAccountId(); + near.log(`${account_id} set_status with message ${message}`); + this.records[account_id] = message; + } - @view({}) - get_status({ account_id }) { - near.log(`get_status for account_id ${account_id}`) - return this.records[account_id] || null - } + @view({}) + get_status({ account_id }) { + near.log(`get_status for account_id ${account_id}`); + return this.records[account_id] || null; + } } - diff --git a/examples/tsconfig.json b/examples/tsconfig.json index 34d7bd188..c68670ab7 100644 --- a/examples/tsconfig.json +++ b/examples/tsconfig.json @@ -1,10 +1,8 @@ { - "compilerOptions": { - "experimentalDecorators": true, - "target": "es2020", - "noEmit": true - }, - "exclude": [ - "node_modules" - ], -} \ No newline at end of file + "compilerOptions": { + "experimentalDecorators": true, + "target": "es2020", + "noEmit": true + }, + "exclude": ["node_modules"] +} diff --git a/examples/yarn.lock b/examples/yarn.lock index 13b0a4b73..39e61403f 100644 --- a/examples/yarn.lock +++ b/examples/yarn.lock @@ -610,11 +610,6 @@ base-x@^3.0.2: dependencies: safe-buffer "^5.0.1" -base-x@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/base-x/-/base-x-4.0.0.tgz#d0e3b7753450c73f8ad2389b5c018a4af7b2224a" - integrity sha512-FuwxlW4H5kh37X/oW59pwTzzTKRzfrrQwhmyspRM7swOEZcHtDZSCt45U6oKgtuFE+WYPblePMVIPR4RZrh/hw== - base64url@^3.0.1: version "3.0.1" resolved "https://registry.npmjs.org/base64url/-/base64url-3.0.1.tgz" @@ -690,13 +685,6 @@ bs58@^4.0.0, bs58@^4.0.1: dependencies: base-x "^3.0.2" -bs58@^5.0.0: - version "5.0.0" - resolved "https://registry.yarnpkg.com/bs58/-/bs58-5.0.0.tgz#865575b4d13c09ea2a84622df6c8cbeb54ffc279" - integrity sha512-r+ihvQJvahgYT50JD05dyJNKlmmSlMoOGwn1lCcEzanPglg7TxYjioQUYehQ9mAR/+hOSd2jRc/Z2y5UxBymvQ== - dependencies: - base-x "^4.0.0" - builtin-modules@^3.0.0: version "3.3.0" resolved "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz#cae62812b89801e9656336e46223e030386be7b6" @@ -1620,7 +1608,7 @@ near-sandbox@^0.0.13: tar "^6.1.0" "near-sdk-js@file:..": - version "0.4.0-5" + version "0.5.0-1" dependencies: "@babel/core" "^7.17.5" "@babel/plugin-proposal-decorators" "^7.17.2" @@ -1629,7 +1617,6 @@ near-sandbox@^0.0.13: "@rollup/plugin-commonjs" "^21.0.1" "@rollup/plugin-node-resolve" "^13.1.1" "@scure/base" "^1.1.1" - bs58 "^5.0.0" rollup "^2.61.1" rollup-plugin-sourcemaps "^0.6.3" yargs "^17.5.1" diff --git a/lib/api.js b/lib/api.js index e28e19504..149dfbed2 100644 --- a/lib/api.js +++ b/lib/api.js @@ -3,9 +3,9 @@ const U64_MAX = 2n ** 64n - 1n; const EVICTED_REGISTER = U64_MAX - 1n; export function log(...params) { env.log(`${params - .map(x => x === undefined ? 'undefined' : x) // Stringify undefined - .map(x => typeof (x) === 'object' ? JSON.stringify(x) : x) // Convert Objects to strings - .join(' ')}` // Convert to string + .map((x) => (x === undefined ? "undefined" : x)) // Stringify undefined + .map((x) => (typeof x === "object" ? JSON.stringify(x) : x)) // Convert Objects to strings + .join(" ")}` // Convert to string ); } export function signerAccountId() { @@ -62,7 +62,7 @@ export function ripemd160(value) { return env.read_register(0); } export function ecrecover(hash, sig, v, malleabilityFlag) { - let ret = env.ecrecover(hash, sig, v, malleabilityFlag, 0); + const ret = env.ecrecover(hash, sig, v, malleabilityFlag, 0); if (ret === 0n) { return null; } @@ -79,7 +79,7 @@ export function logUtf16(msg) { env.log_utf16(msg); } export function storageRead(key) { - let ret = env.storage_read(key, 0); + const ret = env.storage_read(key, 0); if (ret === 1n) { return env.read_register(0); } @@ -88,7 +88,7 @@ export function storageRead(key) { } } export function storageHasKey(key) { - let ret = env.storage_has_key(key); + const ret = env.storage_has_key(key); if (ret === 1n) { return true; } @@ -111,7 +111,7 @@ export function altBn128G1Sum(value) { return env.read_register(0); } export function altBn128PairingCheck(value) { - let ret = env.alt_bn128_pairing_check(value); + const ret = env.alt_bn128_pairing_check(value); if (ret === 1n) { return true; } @@ -191,27 +191,30 @@ export function promiseResultsCount() { return env.promise_results_count(); } export function promiseResult(resultIdx) { - let status = env.promise_result(resultIdx, 0); + const status = env.promise_result(resultIdx, 0); if (status == PromiseResult.Successful) { return env.read_register(0); } else { - throw Error(`Promise result ${status == PromiseResult.Failed ? "Failed" : - status == PromiseResult.NotReady ? "NotReady" : status}`); + throw Error(`Promise result ${status == PromiseResult.Failed + ? "Failed" + : status == PromiseResult.NotReady + ? "NotReady" + : status}`); } } export function promiseReturn(promiseIdx) { env.promise_return(promiseIdx); } export function storageWrite(key, value) { - let exist = env.storage_write(key, value, EVICTED_REGISTER); + const exist = env.storage_write(key, value, EVICTED_REGISTER); if (exist === 1n) { return true; } return false; } export function storageRemove(key) { - let exist = env.storage_remove(key, EVICTED_REGISTER); + const exist = env.storage_remove(key, EVICTED_REGISTER); if (exist === 1n) { return true; } diff --git a/lib/build-tools/include-bytes.js b/lib/build-tools/include-bytes.js index 265c42cd9..e0f712898 100644 --- a/lib/build-tools/include-bytes.js +++ b/lib/build-tools/include-bytes.js @@ -1,27 +1,29 @@ -import fs from 'fs'; -import path from 'path'; +import fs from "fs"; +import path from "path"; export default function ({ types: t }) { return { visitor: { CallExpression(p, state) { let name = p.node.callee.name; let args = p.node.arguments; - if (name === 'includeBytes') { + if (name === "includeBytes") { // Get the path of file var filename = this.file.opts.filename; // User settings let root = state.opts.root || path.dirname(filename); // Read binary file into bytes, so encoding is 'latin1' (each byte is 0-255, become one character) - const encoding = 'latin1'; + const encoding = "latin1"; // Require first arg to be string t.assertStringLiteral(args[0]); // Error if filename is not found - if (filename === undefined || filename === 'unknown') - throw new Error('`includeBytes` function called outside of file'); + if (filename === undefined || filename === "unknown") + throw new Error("`includeBytes` function called outside of file"); // Generate and locate the file let fileRelPath = args[0].value; // Get literal string value let filePath = path.join(root, fileRelPath); - let fileSrc = fs.readFileSync(filePath, { encoding }).toString(encoding); + let fileSrc = fs + .readFileSync(filePath, { encoding }) + .toString(encoding); p.replaceWith(t.stringLiteral(fileSrc)); } }, diff --git a/lib/build-tools/near-bindgen-exporter.js b/lib/build-tools/near-bindgen-exporter.js index 4a201dd08..bcdb704ad 100644 --- a/lib/build-tools/near-bindgen-exporter.js +++ b/lib/build-tools/near-bindgen-exporter.js @@ -4,61 +4,89 @@ export default function () { visitor: { ClassDeclaration(path) { let classNode = path.node; - if (classNode.decorators && classNode.decorators[0].expression.callee.name == 'NearBindgen') { + if (classNode.decorators && + classNode.decorators[0].expression.callee.name == "NearBindgen") { let classId = classNode.id; let contractMethods = {}; for (let child of classNode.body.body) { - if (child.type == 'ClassMethod' && child.kind == 'method' && child.decorators) { - if (child.decorators[0].expression.callee.name == 'call') { + if (child.type == "ClassMethod" && + child.kind == "method" && + child.decorators) { + if (child.decorators[0].expression.callee.name == "call") { let callMethod = child.key.name; - contractMethods[callMethod] = 'call'; + contractMethods[callMethod] = "call"; } - else if (child.decorators[0].expression.callee.name == 'view') { + else if (child.decorators[0].expression.callee.name == "view") { let viewMethod = child.key.name; - contractMethods[viewMethod] = 'view'; + contractMethods[viewMethod] = "view"; } - else if (child.decorators[0].expression.callee.name == 'initialize') { + else if (child.decorators[0].expression.callee.name == "initialize") { let initMethod = child.key.name; - contractMethods[initMethod] = 'initialize'; + contractMethods[initMethod] = "initialize"; } } } for (let method of Object.keys(contractMethods)) { path.insertAfter(t.exportNamedDeclaration(t.functionDeclaration(t.identifier(method), [], t.blockStatement([ // const _state = Counter._getState(); - t.variableDeclaration('let', [t.variableDeclarator(t.identifier('_state'), t.callExpression(t.memberExpression(classId, t.identifier('_getState')), []))]), - contractMethods[method] === 'initialize' ? - // if (_state) { throw new Error('Contract already initialized'); } - t.ifStatement(t.identifier('_state'), t.throwStatement(t.newExpression(t.identifier('Error'), [t.stringLiteral('Contract already initialized')]))) + t.variableDeclaration("let", [ + t.variableDeclarator(t.identifier("_state"), t.callExpression(t.memberExpression(classId, t.identifier("_getState")), [])), + ]), + contractMethods[method] === "initialize" + ? // if (_state) { throw new Error('Contract already initialized'); } + t.ifStatement(t.identifier("_state"), t.throwStatement(t.newExpression(t.identifier("Error"), [ + t.stringLiteral("Contract already initialized"), + ]))) : t.emptyStatement(), - contractMethods[method] === 'call' || contractMethods[method] === 'view' ? - // if (!_state) { throw new Error('Contract must be initialized'); } - t.ifStatement(t.logicalExpression('&&', t.unaryExpression('!', t.identifier('_state')), t.callExpression(t.memberExpression(classId, t.identifier('_requireInit')), [])), t.blockStatement([t.throwStatement(t.newExpression(t.identifier('Error'), [t.stringLiteral('Contract must be initialized')]))])) + contractMethods[method] === "call" || + contractMethods[method] === "view" + ? // if (!_state) { throw new Error('Contract must be initialized'); } + t.ifStatement(t.logicalExpression("&&", t.unaryExpression("!", t.identifier("_state")), t.callExpression(t.memberExpression(classId, t.identifier("_requireInit")), [])), t.blockStatement([ + t.throwStatement(t.newExpression(t.identifier("Error"), [ + t.stringLiteral("Contract must be initialized"), + ])), + ])) : t.emptyStatement(), // let _contract = Counter._create(); - t.variableDeclaration('let', [t.variableDeclarator(t.identifier('_contract'), t.callExpression(t.memberExpression(classId, t.identifier('_create')), []))]), - contractMethods[method] === 'call' || contractMethods[method] === 'view' ? - // if (_state) { Object.assign(_contract, state); } - t.ifStatement(t.identifier('_state'), t.blockStatement([t.expressionStatement(t.callExpression(t.memberExpression(classId, t.identifier('_reconstruct')), [t.identifier('_contract'), t.identifier('_state')]))])) : t.emptyStatement(), + t.variableDeclaration("let", [ + t.variableDeclarator(t.identifier("_contract"), t.callExpression(t.memberExpression(classId, t.identifier("_create")), [])), + ]), + contractMethods[method] === "call" || + contractMethods[method] === "view" + ? // if (_state) { Object.assign(_contract, state); } + t.ifStatement(t.identifier("_state"), t.blockStatement([ + t.expressionStatement(t.callExpression(t.memberExpression(classId, t.identifier("_reconstruct")), [ + t.identifier("_contract"), + t.identifier("_state"), + ])), + ])) + : t.emptyStatement(), // let _args = Counter._getArgs(); - t.variableDeclaration('let', [t.variableDeclarator(t.identifier('_args'), t.callExpression(t.memberExpression(classId, t.identifier('_getArgs')), []))]), + t.variableDeclaration("let", [ + t.variableDeclarator(t.identifier("_args"), t.callExpression(t.memberExpression(classId, t.identifier("_getArgs")), [])), + ]), // let _result = _contract.method(args); - t.variableDeclaration('let', [t.variableDeclarator(t.identifier('_result'), t.callExpression(t.memberExpression(t.identifier('_contract'), t.identifier(method)), [t.identifier('_args')]))]), - contractMethods[method] === 'initialize' || contractMethods[method] === 'call' ? - // Counter._saveToStorage(_contract); - t.expressionStatement(t.callExpression(t.memberExpression(classId, t.identifier('_saveToStorage')), [t.identifier('_contract')])) + t.variableDeclaration("let", [ + t.variableDeclarator(t.identifier("_result"), t.callExpression(t.memberExpression(t.identifier("_contract"), t.identifier(method)), [t.identifier("_args")])), + ]), + contractMethods[method] === "initialize" || + contractMethods[method] === "call" + ? // Counter._saveToStorage(_contract); + t.expressionStatement(t.callExpression(t.memberExpression(classId, t.identifier("_saveToStorage")), [t.identifier("_contract")])) : t.emptyStatement(), - // if (_result !== undefined) + // if (_result !== undefined) // if (_result && _result.constructor && _result.constructor.name === 'NearPromise') // _result.onReturn(); // else // near.valueReturn(_contract._serialize(result)); - t.ifStatement(t.binaryExpression('!==', t.identifier('_result'), t.identifier('undefined')), t.ifStatement(t.logicalExpression('&&', t.logicalExpression('&&', t.identifier('_result'), t.memberExpression(t.identifier('_result'), t.identifier('constructor'))), t.binaryExpression('===', t.memberExpression(t.memberExpression(t.identifier('_result'), t.identifier('constructor')), t.identifier('name')), t.stringLiteral('NearPromise'))), t.expressionStatement(t.callExpression(t.memberExpression(t.identifier('_result'), t.identifier('onReturn')), [])), t.expressionStatement(t.callExpression(t.memberExpression(t.identifier('env'), t.identifier('value_return')), [t.callExpression(t.memberExpression(classId, t.identifier('_serialize')), [t.identifier('_result')])])))) + t.ifStatement(t.binaryExpression("!==", t.identifier("_result"), t.identifier("undefined")), t.ifStatement(t.logicalExpression("&&", t.logicalExpression("&&", t.identifier("_result"), t.memberExpression(t.identifier("_result"), t.identifier("constructor"))), t.binaryExpression("===", t.memberExpression(t.memberExpression(t.identifier("_result"), t.identifier("constructor")), t.identifier("name")), t.stringLiteral("NearPromise"))), t.expressionStatement(t.callExpression(t.memberExpression(t.identifier("_result"), t.identifier("onReturn")), [])), t.expressionStatement(t.callExpression(t.memberExpression(t.identifier("env"), t.identifier("value_return")), [ + t.callExpression(t.memberExpression(classId, t.identifier("_serialize")), [t.identifier("_result")]), + ])))), ])))); console.log(`Babel ${method} method export done`); } } - } - } + }, + }, }; } diff --git a/lib/collections/lookup-map.d.ts b/lib/collections/lookup-map.d.ts index 0035b4ee0..337100f04 100644 --- a/lib/collections/lookup-map.d.ts +++ b/lib/collections/lookup-map.d.ts @@ -1,5 +1,5 @@ -import { GetOptions } from '../types/collections'; -import { Bytes } from '../utils'; +import { GetOptions } from "../types/collections"; +import { Bytes } from "../utils"; export declare class LookupMap { readonly keyPrefix: Bytes; constructor(keyPrefix: Bytes); diff --git a/lib/collections/lookup-map.js b/lib/collections/lookup-map.js index a9b331700..4837d0596 100644 --- a/lib/collections/lookup-map.js +++ b/lib/collections/lookup-map.js @@ -1,38 +1,40 @@ -import * as near from '../api'; +import * as near from "../api"; export class LookupMap { constructor(keyPrefix) { this.keyPrefix = keyPrefix; } containsKey(key) { - let storageKey = this.keyPrefix + JSON.stringify(key); + const storageKey = this.keyPrefix + JSON.stringify(key); return near.storageHasKey(storageKey); } get(key, options) { - let storageKey = this.keyPrefix + JSON.stringify(key); - let raw = near.storageRead(storageKey); + const storageKey = this.keyPrefix + JSON.stringify(key); + const raw = near.storageRead(storageKey); if (raw !== null) { const value = JSON.parse(raw); - return !!options?.reconstructor ? options.reconstructor(value) : value; + return options?.reconstructor + ? options.reconstructor(value) + : value; } return null; } remove(key) { - let storageKey = this.keyPrefix + JSON.stringify(key); + const storageKey = this.keyPrefix + JSON.stringify(key); if (near.storageRemove(storageKey)) { return JSON.parse(near.storageGetEvicted()); } return null; } set(key, value) { - let storageKey = this.keyPrefix + JSON.stringify(key); - let storageValue = JSON.stringify(value); + const storageKey = this.keyPrefix + JSON.stringify(key); + const storageValue = JSON.stringify(value); if (near.storageWrite(storageKey, storageValue)) { return JSON.parse(near.storageGetEvicted()); } return null; } extend(objects) { - for (let kv of objects) { + for (const kv of objects) { this.set(kv[0], kv[1]); } } diff --git a/lib/collections/lookup-set.d.ts b/lib/collections/lookup-set.d.ts index d8f3ef5e2..b60172e66 100644 --- a/lib/collections/lookup-set.d.ts +++ b/lib/collections/lookup-set.d.ts @@ -1,4 +1,4 @@ -import { Bytes } from '../utils'; +import { Bytes } from "../utils"; export declare class LookupSet { readonly keyPrefix: Bytes; constructor(keyPrefix: Bytes); diff --git a/lib/collections/lookup-set.js b/lib/collections/lookup-set.js index 9ba56dba1..a0da122e0 100644 --- a/lib/collections/lookup-set.js +++ b/lib/collections/lookup-set.js @@ -1,25 +1,25 @@ -import * as near from '../api'; +import * as near from "../api"; export class LookupSet { constructor(keyPrefix) { this.keyPrefix = keyPrefix; } contains(key) { - let storageKey = this.keyPrefix + JSON.stringify(key); + const storageKey = this.keyPrefix + JSON.stringify(key); return near.storageHasKey(storageKey); } // Returns true if the element was present in the set. remove(key) { - let storageKey = this.keyPrefix + JSON.stringify(key); + const storageKey = this.keyPrefix + JSON.stringify(key); return near.storageRemove(storageKey); } // If the set did not have this value present, `true` is returned. // If the set did have this value present, `false` is returned. set(key) { - let storageKey = this.keyPrefix + JSON.stringify(key); - return !near.storageWrite(storageKey, ''); + const storageKey = this.keyPrefix + JSON.stringify(key); + return !near.storageWrite(storageKey, ""); } extend(keys) { - for (let key of keys) { + for (const key of keys) { this.set(key); } } diff --git a/lib/collections/unordered-map.js b/lib/collections/unordered-map.js index 673723823..92ad98370 100644 --- a/lib/collections/unordered-map.js +++ b/lib/collections/unordered-map.js @@ -4,52 +4,52 @@ const ERR_INCONSISTENT_STATE = "The collection is an inconsistent state. Did pre export class UnorderedMap { constructor(prefix) { this.prefix = prefix; - this.keys = new Vector(prefix + 'u'); // intentional different prefix with old UnorderedMap - this.values = new LookupMap(prefix + 'm'); + this.keys = new Vector(prefix + "u"); // intentional different prefix with old UnorderedMap + this.values = new LookupMap(prefix + "m"); } get length() { - let keysLen = this.keys.length; + const keysLen = this.keys.length; return keysLen; } isEmpty() { - let keysIsEmpty = this.keys.isEmpty(); + const keysIsEmpty = this.keys.isEmpty(); return keysIsEmpty; } get(key, options) { - let valueAndIndex = this.values.get(key); + const valueAndIndex = this.values.get(key); if (valueAndIndex === null) { return null; } - let value = valueAndIndex[0]; - return !!options?.reconstructor ? options.reconstructor(value) : value; + const value = valueAndIndex[0]; + return options?.reconstructor ? options.reconstructor(value) : value; } set(key, value) { - let valueAndIndex = this.values.get(key); + const valueAndIndex = this.values.get(key); if (valueAndIndex !== null) { - let oldValue = valueAndIndex[0]; + const oldValue = valueAndIndex[0]; valueAndIndex[0] = value; this.values.set(key, valueAndIndex); return oldValue; } - let nextIndex = this.length; + const nextIndex = this.length; this.keys.push(key); this.values.set(key, [value, nextIndex]); return null; } remove(key) { - let oldValueAndIndex = this.values.remove(key); + const oldValueAndIndex = this.values.remove(key); if (oldValueAndIndex === null) { return null; } - let index = oldValueAndIndex[1]; + const index = oldValueAndIndex[1]; if (this.keys.swapRemove(index) === null) { throw new Error(ERR_INCONSISTENT_STATE); } // the last key is swapped to key[index], the corresponding [value, index] need update if (this.keys.length > 0 && index != this.keys.length) { // if there is still elements and it was not the last element - let swappedKey = this.keys.get(index); - let swappedValueAndIndex = this.values.get(swappedKey); + const swappedKey = this.keys.get(index); + const swappedValueAndIndex = this.values.get(swappedKey); if (swappedValueAndIndex === null) { throw new Error(ERR_INCONSISTENT_STATE); } @@ -58,15 +58,15 @@ export class UnorderedMap { return oldValueAndIndex[0]; } clear() { - for (let key of this.keys) { + for (const key of this.keys) { // Set instead of remove to avoid loading the value from storage. this.values.set(key, null); } this.keys.clear(); } toArray() { - let ret = []; - for (let v of this) { + const ret = []; + for (const v of this) { ret.push(v); } return ret; @@ -75,7 +75,7 @@ export class UnorderedMap { return new UnorderedMapIterator(this); } extend(kvs) { - for (let [k, v] of kvs) { + for (const [k, v] of kvs) { this.set(k, v); } } @@ -84,7 +84,7 @@ export class UnorderedMap { } // converting plain object to class object static reconstruct(data) { - let map = new UnorderedMap(data.prefix); + const map = new UnorderedMap(data.prefix); // reconstruct keys Vector map.keys = new Vector(data.prefix + "u"); map.keys.length = data.keys.length; @@ -99,7 +99,7 @@ class UnorderedMapIterator { this.map = unorderedMap.values; } next() { - let key = this.keys.next(); + const key = this.keys.next(); let value; if (!key.done) { value = this.map.get(key.value); diff --git a/lib/collections/unordered-set.js b/lib/collections/unordered-set.js index 581f8f5c3..e35801b21 100644 --- a/lib/collections/unordered-set.js +++ b/lib/collections/unordered-set.js @@ -3,20 +3,20 @@ import { u8ArrayToBytes, bytesToU8Array } from "../utils"; import { Vector } from "./vector"; const ERR_INCONSISTENT_STATE = "The collection is an inconsistent state. Did previous smart contract execution terminate unexpectedly?"; function serializeIndex(index) { - let data = new Uint32Array([index]); - let array = new Uint8Array(data.buffer); + const data = new Uint32Array([index]); + const array = new Uint8Array(data.buffer); return u8ArrayToBytes(array); } function deserializeIndex(rawIndex) { - let array = bytesToU8Array(rawIndex); - let data = new Uint32Array(array.buffer); + const array = bytesToU8Array(rawIndex); + const data = new Uint32Array(array.buffer); return data[0]; } export class UnorderedSet { constructor(prefix) { this.prefix = prefix; this.elementIndexPrefix = prefix + "i"; - let elementsPrefix = prefix + "e"; + const elementsPrefix = prefix + "e"; this.elements = new Vector(elementsPrefix); } get length() { @@ -26,25 +26,25 @@ export class UnorderedSet { return this.elements.isEmpty(); } contains(element) { - let indexLookup = this.elementIndexPrefix + JSON.stringify(element); + const indexLookup = this.elementIndexPrefix + JSON.stringify(element); return near.storageHasKey(indexLookup); } set(element) { - let indexLookup = this.elementIndexPrefix + JSON.stringify(element); + const indexLookup = this.elementIndexPrefix + JSON.stringify(element); if (near.storageRead(indexLookup)) { return false; } else { - let nextIndex = this.length; - let nextIndexRaw = serializeIndex(nextIndex); + const nextIndex = this.length; + const nextIndexRaw = serializeIndex(nextIndex); near.storageWrite(indexLookup, nextIndexRaw); this.elements.push(element); return true; } } remove(element) { - let indexLookup = this.elementIndexPrefix + JSON.stringify(element); - let indexRaw = near.storageRead(indexLookup); + const indexLookup = this.elementIndexPrefix + JSON.stringify(element); + const indexRaw = near.storageRead(indexLookup); if (indexRaw) { if (this.length == 1) { // If there is only one element then swap remove simply removes it without @@ -54,7 +54,7 @@ export class UnorderedSet { else { // If there is more than one element then swap remove swaps it with the last // element. - let lastElement = this.elements.get(this.length - 1); + const lastElement = this.elements.get(this.length - 1); if (!lastElement) { throw new Error(ERR_INCONSISTENT_STATE); } @@ -62,26 +62,26 @@ export class UnorderedSet { // If the removed element was the last element from keys, then we don't need to // reinsert the lookup back. if (lastElement != element) { - let lastLookupElement = this.elementIndexPrefix + JSON.stringify(lastElement); + const lastLookupElement = this.elementIndexPrefix + JSON.stringify(lastElement); near.storageWrite(lastLookupElement, indexRaw); } } - let index = deserializeIndex(indexRaw); + const index = deserializeIndex(indexRaw); this.elements.swapRemove(index); return true; } return false; } clear() { - for (let element of this.elements) { - let indexLookup = this.elementIndexPrefix + JSON.stringify(element); + for (const element of this.elements) { + const indexLookup = this.elementIndexPrefix + JSON.stringify(element); near.storageRemove(indexLookup); } this.elements.clear(); } toArray() { - let ret = []; - for (let v of this) { + const ret = []; + for (const v of this) { ret.push(v); } return ret; @@ -90,7 +90,7 @@ export class UnorderedSet { return this.elements[Symbol.iterator](); } extend(elements) { - for (let element of elements) { + for (const element of elements) { this.set(element); } } @@ -99,9 +99,9 @@ export class UnorderedSet { } // converting plain object to class object static reconstruct(data) { - let set = new UnorderedSet(data.prefix); + const set = new UnorderedSet(data.prefix); // reconstruct Vector - let elementsPrefix = data.prefix + "e"; + const elementsPrefix = data.prefix + "e"; set.elements = new Vector(elementsPrefix); set.elements.length = data.elements.length; return set; diff --git a/lib/collections/vector.d.ts b/lib/collections/vector.d.ts index 07419d9d0..a5e873992 100644 --- a/lib/collections/vector.d.ts +++ b/lib/collections/vector.d.ts @@ -1,5 +1,5 @@ import { Bytes } from "../utils"; -import { GetOptions } from '../types/collections'; +import { GetOptions } from "../types/collections"; export declare class Vector { length: number; readonly prefix: Bytes; diff --git a/lib/collections/vector.js b/lib/collections/vector.js index 17cedc66c..295ead7dd 100644 --- a/lib/collections/vector.js +++ b/lib/collections/vector.js @@ -3,9 +3,9 @@ import { u8ArrayToBytes } from "../utils"; const ERR_INDEX_OUT_OF_BOUNDS = "Index out of bounds"; const ERR_INCONSISTENT_STATE = "The collection is an inconsistent state. Did previous smart contract execution terminate unexpectedly?"; function indexToKey(prefix, index) { - let data = new Uint32Array([index]); - let array = new Uint8Array(data.buffer); - let key = u8ArrayToBytes(array); + const data = new Uint32Array([index]); + const array = new Uint8Array(data.buffer); + const key = u8ArrayToBytes(array); return prefix + key; } /// An iterable implementation of vector that stores its content on the trie. @@ -22,9 +22,11 @@ export class Vector { if (index >= this.length) { return null; } - let storageKey = indexToKey(this.prefix, index); + const storageKey = indexToKey(this.prefix, index); const value = JSON.parse(near.storageRead(storageKey)); - return !!options?.reconstructor ? options.reconstructor(value) : value; + return options?.reconstructor + ? options.reconstructor(value) + : value; } /// Removes an element from the vector and returns it in serialized form. /// The removed element is replaced by the last element of the vector. @@ -37,8 +39,8 @@ export class Vector { return this.pop(); } else { - let key = indexToKey(this.prefix, index); - let last = this.pop(); + const key = indexToKey(this.prefix, index); + const last = this.pop(); if (near.storageWrite(key, JSON.stringify(last))) { return JSON.parse(near.storageGetEvicted()); } @@ -48,7 +50,7 @@ export class Vector { } } push(element) { - let key = indexToKey(this.prefix, this.length); + const key = indexToKey(this.prefix, this.length); this.length += 1; near.storageWrite(key, JSON.stringify(element)); } @@ -57,8 +59,8 @@ export class Vector { return null; } else { - let lastIndex = this.length - 1; - let lastKey = indexToKey(this.prefix, lastIndex); + const lastIndex = this.length - 1; + const lastKey = indexToKey(this.prefix, lastIndex); this.length -= 1; if (near.storageRemove(lastKey)) { return JSON.parse(near.storageGetEvicted()); @@ -73,7 +75,7 @@ export class Vector { throw new Error(ERR_INDEX_OUT_OF_BOUNDS); } else { - let key = indexToKey(this.prefix, index); + const key = indexToKey(this.prefix, index); if (near.storageWrite(key, JSON.stringify(element))) { return JSON.parse(near.storageGetEvicted()); } @@ -83,7 +85,7 @@ export class Vector { } } extend(elements) { - for (let element of elements) { + for (const element of elements) { this.push(element); } } @@ -92,14 +94,14 @@ export class Vector { } clear() { for (let i = 0; i < this.length; i++) { - let key = indexToKey(this.prefix, i); + const key = indexToKey(this.prefix, i); near.storageRemove(key); } this.length = 0; } toArray() { - let ret = []; - for (let v of this) { + const ret = []; + for (const v of this) { ret.push(v); } return ret; @@ -109,7 +111,7 @@ export class Vector { } // converting plain object to class object static reconstruct(data) { - let vector = new Vector(data.prefix); + const vector = new Vector(data.prefix); vector.length = data.length; return vector; } @@ -121,7 +123,7 @@ export class VectorIterator { } next() { if (this.current < this.vector.length) { - let value = this.vector.get(this.current); + const value = this.vector.get(this.current); this.current += 1; return { value, done: false }; } diff --git a/lib/index.d.ts b/lib/index.d.ts index 3643c08fe..1ac8e8846 100644 --- a/lib/index.d.ts +++ b/lib/index.d.ts @@ -3,4 +3,4 @@ import * as near from "./api"; import { LookupMap, Vector, LookupSet, UnorderedMap, UnorderedSet } from "./collections"; import { bytes, Bytes, assert } from "./utils"; import { NearPromise, PromiseOrValue } from "./promise"; -export { call, view, initialize, NearBindgen, near, LookupMap, Vector, LookupSet, UnorderedMap, UnorderedSet, bytes, Bytes, assert, NearPromise, PromiseOrValue }; +export { call, view, initialize, NearBindgen, near, LookupMap, Vector, LookupSet, UnorderedMap, UnorderedSet, bytes, Bytes, assert, NearPromise, PromiseOrValue, }; diff --git a/lib/index.js b/lib/index.js index 836c2647a..bd400b381 100644 --- a/lib/index.js +++ b/lib/index.js @@ -3,4 +3,4 @@ import * as near from "./api"; import { LookupMap, Vector, LookupSet, UnorderedMap, UnorderedSet, } from "./collections"; import { bytes, assert } from "./utils"; import { NearPromise } from "./promise"; -export { call, view, initialize, NearBindgen, near, LookupMap, Vector, LookupSet, UnorderedMap, UnorderedSet, bytes, assert, NearPromise }; +export { call, view, initialize, NearBindgen, near, LookupMap, Vector, LookupSet, UnorderedMap, UnorderedSet, bytes, assert, NearPromise, }; diff --git a/lib/near-bindgen.d.ts b/lib/near-bindgen.d.ts index 67608c49d..8477c3407 100644 --- a/lib/near-bindgen.d.ts +++ b/lib/near-bindgen.d.ts @@ -1,10 +1,10 @@ export declare function initialize({}: {}): (target: Object, key: string | symbol, descriptor: TypedPropertyDescriptor) => void; -export declare function call({ privateFunction, payableFunction }: { +export declare function call({ privateFunction, payableFunction, }: { privateFunction?: boolean; payableFunction?: boolean; }): (target: Object, key: string | symbol, descriptor: TypedPropertyDescriptor) => void; export declare function view({}: {}): (target: Object, key: string | symbol, descriptor: TypedPropertyDescriptor) => void; -export declare function NearBindgen({ requireInit }: { +export declare function NearBindgen({ requireInit, }: { requireInit?: boolean; }): {}>(target: T) => { new (...args: any[]): {}; diff --git a/lib/near-bindgen.js b/lib/near-bindgen.js index 2aae629fc..83a4f49d8 100644 --- a/lib/near-bindgen.js +++ b/lib/near-bindgen.js @@ -1,13 +1,13 @@ import * as near from "./api"; export function initialize({}) { - return function (target, key, descriptor) { - }; + return function (target, key, descriptor) { }; } -export function call({ privateFunction = false, payableFunction = false }) { +export function call({ privateFunction = false, payableFunction = false, }) { return function (target, key, descriptor) { const originalMethod = descriptor.value; descriptor.value = function (...args) { - if (privateFunction && near.predecessorAccountId() !== near.currentAccountId()) { + if (privateFunction && + near.predecessorAccountId() !== near.currentAccountId()) { throw Error("Function is private"); } if (!payableFunction && near.attachedDeposit() > BigInt(0)) { @@ -18,10 +18,9 @@ export function call({ privateFunction = false, payableFunction = false }) { }; } export function view({}) { - return function (target, key, descriptor) { - }; + return function (target, key, descriptor) { }; } -export function NearBindgen({ requireInit = false }) { +export function NearBindgen({ requireInit = false, }) { return (target) => { return class extends target { static _create() { diff --git a/lib/promise.js b/lib/promise.js index f71c0010f..96a43e53c 100644 --- a/lib/promise.js +++ b/lib/promise.js @@ -118,7 +118,7 @@ class PromiseSingle { else { promise_index = near.promiseBatchCreate(this.account_id); } - for (let action of this.actions) { + for (const action of this.actions) { action.add(promise_index); } this.promise_index = promise_index; @@ -135,7 +135,7 @@ export class PromiseJoint { if (this.promise_index !== null) { return this.promise_index; } - let res = near.promiseAnd(BigInt(this.promise_a.constructRecursively()), BigInt(this.promise_b.constructRecursively())); + const res = near.promiseAnd(BigInt(this.promise_a.constructRecursively()), BigInt(this.promise_b.constructRecursively())); this.promise_index = res; return res; } @@ -146,8 +146,8 @@ export class NearPromise { this.should_return = should_return; } static new(account_id) { - let subtype = new PromiseSingle(account_id, [], null, null); - let ret = new NearPromise(subtype, false); + const subtype = new PromiseSingle(account_id, [], null, null); + const ret = new NearPromise(subtype, false); return ret; } add_action(action) { @@ -196,8 +196,8 @@ export class NearPromise { return this.add_action(new DeleteAccount(beneficiary_id)); } and(other) { - let subtype = new PromiseJoint(this, other, null); - let ret = new NearPromise(subtype, false); + const subtype = new PromiseJoint(this, other, null); + const ret = new NearPromise(subtype, false); return ret; } then(other) { @@ -217,7 +217,7 @@ export class NearPromise { return this; } constructRecursively() { - let res = this.subtype.constructRecursively(); + const res = this.subtype.constructRecursively(); if (this.should_return) { near.promiseReturn(res); } diff --git a/lib/types/index.d.ts b/lib/types/index.d.ts index 82da4d59f..a5bc193a0 100644 --- a/lib/types/index.d.ts +++ b/lib/types/index.d.ts @@ -1,9 +1,9 @@ import { AccountId } from "./account_id"; -import { BlockHeight, EpochHeight, Balance, StorageUsage } from './primitives'; +import { BlockHeight, EpochHeight, Balance, StorageUsage } from "./primitives"; import { PromiseResult, PromiseError, PromiseIndex, ReceiptIndex, IteratorIndex } from "./vm_types"; import { Gas, ONE_TERA_GAS } from "./gas"; import { PublicKey, CurveType, curveTypeFromStr, ParsePublicKeyError, InvalidLengthError, Base58Error, UnknownCurve } from "./public_key"; -export { AccountId, BlockHeight, EpochHeight, Balance, StorageUsage, PromiseResult, PromiseError, PromiseIndex, ReceiptIndex, IteratorIndex, Gas, ONE_TERA_GAS, PublicKey, CurveType, curveTypeFromStr, ParsePublicKeyError, InvalidLengthError, Base58Error, UnknownCurve }; +export { AccountId, BlockHeight, EpochHeight, Balance, StorageUsage, PromiseResult, PromiseError, PromiseIndex, ReceiptIndex, IteratorIndex, Gas, ONE_TERA_GAS, PublicKey, CurveType, curveTypeFromStr, ParsePublicKeyError, InvalidLengthError, Base58Error, UnknownCurve, }; export declare type GasWeight = bigint; export declare const ONE_YOCTO: Balance; export declare const ONE_NEAR: Balance; diff --git a/lib/types/index.js b/lib/types/index.js index 4efb790e0..b9ff465a7 100644 --- a/lib/types/index.js +++ b/lib/types/index.js @@ -1,6 +1,6 @@ -import { PromiseResult, PromiseError } from "./vm_types"; +import { PromiseResult, PromiseError, } from "./vm_types"; import { ONE_TERA_GAS } from "./gas"; -import { PublicKey, CurveType, curveTypeFromStr, ParsePublicKeyError, InvalidLengthError, Base58Error, UnknownCurve } from "./public_key"; -export { PromiseResult, PromiseError, ONE_TERA_GAS, PublicKey, CurveType, curveTypeFromStr, ParsePublicKeyError, InvalidLengthError, Base58Error, UnknownCurve }; +import { PublicKey, CurveType, curveTypeFromStr, ParsePublicKeyError, InvalidLengthError, Base58Error, UnknownCurve, } from "./public_key"; +export { PromiseResult, PromiseError, ONE_TERA_GAS, PublicKey, CurveType, curveTypeFromStr, ParsePublicKeyError, InvalidLengthError, Base58Error, UnknownCurve, }; export const ONE_YOCTO = 1n; export const ONE_NEAR = 1000000000000000000000000n; diff --git a/lib/types/public_key.js b/lib/types/public_key.js index 53b9ef22f..32a01d64f 100644 --- a/lib/types/public_key.js +++ b/lib/types/public_key.js @@ -1,5 +1,5 @@ import { bytes } from "../utils"; -import { base58 } from '@scure/base'; +import { base58 } from "@scure/base"; export var CurveType; (function (CurveType) { CurveType[CurveType["ED25519"] = 0] = "ED25519"; @@ -16,9 +16,12 @@ function data_len(c) { } } function split_key_type_data(value) { - let idx = value.indexOf(":"); + const idx = value.indexOf(":"); if (idx >= 0) { - return [curveTypeFromStr(value.substring(0, idx)), value.substring(idx + 1)]; + return [ + curveTypeFromStr(value.substring(0, idx)), + value.substring(idx + 1), + ]; } else { return [CurveType.ED25519, value]; @@ -56,8 +59,8 @@ export class UnknownCurve extends ParsePublicKeyError { export class PublicKey { constructor(data) { this.data = data; - let curve_type = data.charCodeAt(0); - let curve_len = data_len(curve_type); + const curve_type = data.charCodeAt(0); + const curve_len = data_len(curve_type); if (data.length != curve_len + 1) { throw new InvalidLengthError(data.length); } @@ -67,7 +70,7 @@ export class PublicKey { return this.data.charCodeAt(0); } static fromString(s) { - let [curve, key_data] = split_key_type_data(s); + const [curve, key_data] = split_key_type_data(s); let data; try { data = bytes(base58.decode(key_data)); diff --git a/lib/utils.js b/lib/utils.js index bc107d717..a24c31894 100644 --- a/lib/utils.js +++ b/lib/utils.js @@ -1,6 +1,6 @@ export function u8ArrayToBytes(array) { let ret = ""; - for (let e of array) { + for (const e of array) { ret += String.fromCharCode(e); } return ret; @@ -8,7 +8,7 @@ export function u8ArrayToBytes(array) { // TODO this function is a bit broken and the type can't be string // TODO for more info: https://github.com/near/near-sdk-js/issues/78 export function bytesToU8Array(bytes) { - let ret = new Uint8Array(bytes.length); + const ret = new Uint8Array(bytes.length); for (let i = 0; i < bytes.length; i++) { ret[i] = bytes.charCodeAt(i); } diff --git a/package.json b/package.json index 8bb07ecc3..22c320917 100644 --- a/package.json +++ b/package.json @@ -24,6 +24,8 @@ "build": "tsc -p ./tsconfig.json", "pretest": "yarn build", "test": "yarn test:unit && yarn test:examples", + "lint": "eslint --fix .", + "format": "prettier --write .", "test:unit": "yarn && cd tests && yarn && yarn build && yarn test && cd ..", "test:examples": "yarn && cd examples && yarn && yarn build && yarn test && cd ..", "postinstall": "cd cli && rm -rf deps && mkdir -p deps && cd deps && node ../post-install.js" @@ -52,6 +54,11 @@ "@rollup/plugin-typescript": "^8.3.2", "@types/node": "^17.0.38", "@types/rollup": "^0.54.0", + "@typescript-eslint/eslint-plugin": "^5.37.0", + "@typescript-eslint/parser": "^5.37.0", + "eslint": "^8.23.1", + "eslint-config-prettier": "^8.5.0", + "prettier": "^2.7.1", "typescript": "^4.7.2" } } diff --git a/src/api.ts b/src/api.ts index 5ab8b21b4..a4e2dd4cb 100644 --- a/src/api.ts +++ b/src/api.ts @@ -13,11 +13,12 @@ interface Env { declare let env: Env; export function log(...params: any[]) { - env.log(`${params - .map(x => x === undefined ? 'undefined' : x) // Stringify undefined - .map(x => typeof (x) === 'object' ? JSON.stringify(x) : x) // Convert Objects to strings - .join(' ')}` // Convert to string - ) + env.log( + `${params + .map((x) => (x === undefined ? "undefined" : x)) // Stringify undefined + .map((x) => (typeof x === "object" ? JSON.stringify(x) : x)) // Convert Objects to strings + .join(" ")}` // Convert to string + ); } export function signerAccountId(): string { @@ -94,7 +95,7 @@ export function ecrecover( v: number, malleabilityFlag: number ): Bytes | null { - let ret = env.ecrecover(hash, sig, v, malleabilityFlag, 0); + const ret = env.ecrecover(hash, sig, v, malleabilityFlag, 0); if (ret === 0n) { return null; } @@ -116,7 +117,7 @@ export function logUtf16(msg: Bytes) { } export function storageRead(key: Bytes): Bytes | null { - let ret = env.storage_read(key, 0); + const ret = env.storage_read(key, 0); if (ret === 1n) { return env.read_register(0); } else { @@ -125,7 +126,7 @@ export function storageRead(key: Bytes): Bytes | null { } export function storageHasKey(key: Bytes): boolean { - let ret = env.storage_has_key(key); + const ret = env.storage_has_key(key); if (ret === 1n) { return true; } else { @@ -152,7 +153,7 @@ export function altBn128G1Sum(value: Bytes): Bytes { } export function altBn128PairingCheck(value: Bytes): boolean { - let ret = env.alt_bn128_pairing_check(value); + const ret = env.alt_bn128_pairing_check(value); if (ret === 1n) { return true; } else { @@ -325,7 +326,7 @@ export function promiseBatchActionFunctionCallWeight( args: Bytes, amount: number | bigint, gas: number | bigint, - weight: number | bigint, + weight: number | bigint ) { env.promise_batch_action_function_call_weight( promiseIndex, @@ -342,13 +343,18 @@ export function promiseResultsCount(): bigint { } export function promiseResult(resultIdx: number | bigint): Bytes { - let status: PromiseResult = env.promise_result(resultIdx, 0); + const status: PromiseResult = env.promise_result(resultIdx, 0); if (status == PromiseResult.Successful) { return env.read_register(0); } else { throw Error( - `Promise result ${status == PromiseResult.Failed ? "Failed" : - status == PromiseResult.NotReady ? "NotReady" : status}` + `Promise result ${ + status == PromiseResult.Failed + ? "Failed" + : status == PromiseResult.NotReady + ? "NotReady" + : status + }` ); } } @@ -358,7 +364,7 @@ export function promiseReturn(promiseIdx: number | bigint) { } export function storageWrite(key: Bytes, value: Bytes): boolean { - let exist = env.storage_write(key, value, EVICTED_REGISTER); + const exist = env.storage_write(key, value, EVICTED_REGISTER); if (exist === 1n) { return true; } @@ -366,7 +372,7 @@ export function storageWrite(key: Bytes, value: Bytes): boolean { } export function storageRemove(key: Bytes): boolean { - let exist = env.storage_remove(key, EVICTED_REGISTER); + const exist = env.storage_remove(key, EVICTED_REGISTER); if (exist === 1n) { return true; } diff --git a/src/build-tools/include-bytes.js b/src/build-tools/include-bytes.js index 1eee0587e..5b10ef68a 100644 --- a/src/build-tools/include-bytes.js +++ b/src/build-tools/include-bytes.js @@ -1,37 +1,39 @@ -import fs from 'fs' -import path from 'path' +import fs from "fs"; +import path from "path"; export default function ({ types: t }) { return { visitor: { CallExpression(p, state) { - let name = p.node.callee.name - let args = p.node.arguments + let name = p.node.callee.name; + let args = p.node.arguments; - if (name === 'includeBytes') { + if (name === "includeBytes") { // Get the path of file - var filename = this.file.opts.filename + var filename = this.file.opts.filename; // User settings - let root = state.opts.root || path.dirname(filename) + let root = state.opts.root || path.dirname(filename); // Read binary file into bytes, so encoding is 'latin1' (each byte is 0-255, become one character) - const encoding = 'latin1' - + const encoding = "latin1"; + // Require first arg to be string - t.assertStringLiteral(args[0]) + t.assertStringLiteral(args[0]); // Error if filename is not found - if (filename === undefined || filename === 'unknown') - throw new Error('`includeBytes` function called outside of file') + if (filename === undefined || filename === "unknown") + throw new Error("`includeBytes` function called outside of file"); // Generate and locate the file - let fileRelPath = args[0].value // Get literal string value - let filePath = path.join(root, fileRelPath) - let fileSrc = fs.readFileSync(filePath, { encoding }).toString(encoding) + let fileRelPath = args[0].value; // Get literal string value + let filePath = path.join(root, fileRelPath); + let fileSrc = fs + .readFileSync(filePath, { encoding }) + .toString(encoding); - p.replaceWith(t.stringLiteral(fileSrc)) + p.replaceWith(t.stringLiteral(fileSrc)); } }, }, - } + }; } diff --git a/src/build-tools/near-bindgen-exporter.js b/src/build-tools/near-bindgen-exporter.js index f4e4335be..e5ce5cc41 100644 --- a/src/build-tools/near-bindgen-exporter.js +++ b/src/build-tools/near-bindgen-exporter.js @@ -5,65 +5,224 @@ export default function () { visitor: { ClassDeclaration(path) { let classNode = path.node; - if (classNode.decorators && classNode.decorators[0].expression.callee.name == 'NearBindgen') { + if ( + classNode.decorators && + classNode.decorators[0].expression.callee.name == "NearBindgen" + ) { let classId = classNode.id; let contractMethods = {}; for (let child of classNode.body.body) { - if (child.type == 'ClassMethod' && child.kind == 'method' && child.decorators) { - if (child.decorators[0].expression.callee.name == 'call') { + if ( + child.type == "ClassMethod" && + child.kind == "method" && + child.decorators + ) { + if (child.decorators[0].expression.callee.name == "call") { let callMethod = child.key.name; - contractMethods[callMethod] = 'call'; - } - else if (child.decorators[0].expression.callee.name == 'view') { + contractMethods[callMethod] = "call"; + } else if (child.decorators[0].expression.callee.name == "view") { let viewMethod = child.key.name; - contractMethods[viewMethod] = 'view'; - } - else if (child.decorators[0].expression.callee.name == 'initialize') { + contractMethods[viewMethod] = "view"; + } else if ( + child.decorators[0].expression.callee.name == "initialize" + ) { let initMethod = child.key.name; - contractMethods[initMethod] = 'initialize'; + contractMethods[initMethod] = "initialize"; } } } for (let method of Object.keys(contractMethods)) { - path.insertAfter(t.exportNamedDeclaration(t.functionDeclaration(t.identifier(method), [], t.blockStatement([ - // const _state = Counter._getState(); - t.variableDeclaration('let', [t.variableDeclarator(t.identifier('_state'), t.callExpression(t.memberExpression(classId, t.identifier('_getState')), []))]), - contractMethods[method] === 'initialize' ? - // if (_state) { throw new Error('Contract already initialized'); } - t.ifStatement(t.identifier('_state'), t.throwStatement(t.newExpression(t.identifier('Error'), [t.stringLiteral('Contract already initialized')]))) - : t.emptyStatement(), - contractMethods[method] === 'call' || contractMethods[method] === 'view' ? - // if (!_state) { throw new Error('Contract must be initialized'); } - t.ifStatement(t.logicalExpression('&&', t.unaryExpression('!', t.identifier('_state')), t.callExpression(t.memberExpression(classId, t.identifier('_requireInit')), [])), t.blockStatement([t.throwStatement(t.newExpression(t.identifier('Error'), [t.stringLiteral('Contract must be initialized')]))])) - : t.emptyStatement(), - // let _contract = Counter._create(); - t.variableDeclaration('let', [t.variableDeclarator(t.identifier('_contract'), t.callExpression(t.memberExpression(classId, t.identifier('_create')), []))]), - contractMethods[method] === 'call' || contractMethods[method] === 'view' ? - // if (_state) { Object.assign(_contract, state); } - t.ifStatement(t.identifier('_state'), t.blockStatement([t.expressionStatement( - t.callExpression(t.memberExpression(classId, t.identifier('_reconstruct')), [t.identifier('_contract'), t.identifier('_state')]))])) : t.emptyStatement(), - // let _args = Counter._getArgs(); - t.variableDeclaration('let', [t.variableDeclarator(t.identifier('_args'), t.callExpression(t.memberExpression(classId, t.identifier('_getArgs')), []))]), - // let _result = _contract.method(args); - t.variableDeclaration('let', [t.variableDeclarator(t.identifier('_result'), t.callExpression(t.memberExpression(t.identifier('_contract'), t.identifier(method)), [t.identifier('_args')]))]), - contractMethods[method] === 'initialize' || contractMethods[method] === 'call' ? - // Counter._saveToStorage(_contract); - t.expressionStatement(t.callExpression(t.memberExpression(classId, t.identifier('_saveToStorage')), [t.identifier('_contract')])) - : t.emptyStatement(), - // if (_result !== undefined) - // if (_result && _result.constructor && _result.constructor.name === 'NearPromise') - // _result.onReturn(); - // else - // near.valueReturn(_contract._serialize(result)); - t.ifStatement(t.binaryExpression('!==', t.identifier('_result'), t.identifier('undefined')), - t.ifStatement(t.logicalExpression('&&', t.logicalExpression('&&', t.identifier('_result'), t.memberExpression(t.identifier('_result'), t.identifier('constructor'))), - t.binaryExpression('===', t.memberExpression(t.memberExpression(t.identifier('_result'), t.identifier('constructor')), t.identifier('name')), t.stringLiteral('NearPromise'))), - t.expressionStatement(t.callExpression(t.memberExpression(t.identifier('_result'), t.identifier('onReturn')), [])), - t.expressionStatement(t.callExpression(t.memberExpression(t.identifier('env'), t.identifier('value_return')), [t.callExpression(t.memberExpression(classId, t.identifier('_serialize')), [t.identifier('_result')])]))))])))); + path.insertAfter( + t.exportNamedDeclaration( + t.functionDeclaration( + t.identifier(method), + [], + t.blockStatement([ + // const _state = Counter._getState(); + t.variableDeclaration("let", [ + t.variableDeclarator( + t.identifier("_state"), + t.callExpression( + t.memberExpression( + classId, + t.identifier("_getState") + ), + [] + ) + ), + ]), + contractMethods[method] === "initialize" + ? // if (_state) { throw new Error('Contract already initialized'); } + t.ifStatement( + t.identifier("_state"), + t.throwStatement( + t.newExpression(t.identifier("Error"), [ + t.stringLiteral("Contract already initialized"), + ]) + ) + ) + : t.emptyStatement(), + contractMethods[method] === "call" || + contractMethods[method] === "view" + ? // if (!_state) { throw new Error('Contract must be initialized'); } + t.ifStatement( + t.logicalExpression( + "&&", + t.unaryExpression("!", t.identifier("_state")), + t.callExpression( + t.memberExpression( + classId, + t.identifier("_requireInit") + ), + [] + ) + ), + t.blockStatement([ + t.throwStatement( + t.newExpression(t.identifier("Error"), [ + t.stringLiteral("Contract must be initialized"), + ]) + ), + ]) + ) + : t.emptyStatement(), + // let _contract = Counter._create(); + t.variableDeclaration("let", [ + t.variableDeclarator( + t.identifier("_contract"), + t.callExpression( + t.memberExpression(classId, t.identifier("_create")), + [] + ) + ), + ]), + contractMethods[method] === "call" || + contractMethods[method] === "view" + ? // if (_state) { Object.assign(_contract, state); } + t.ifStatement( + t.identifier("_state"), + t.blockStatement([ + t.expressionStatement( + t.callExpression( + t.memberExpression( + classId, + t.identifier("_reconstruct") + ), + [ + t.identifier("_contract"), + t.identifier("_state"), + ] + ) + ), + ]) + ) + : t.emptyStatement(), + // let _args = Counter._getArgs(); + t.variableDeclaration("let", [ + t.variableDeclarator( + t.identifier("_args"), + t.callExpression( + t.memberExpression(classId, t.identifier("_getArgs")), + [] + ) + ), + ]), + // let _result = _contract.method(args); + t.variableDeclaration("let", [ + t.variableDeclarator( + t.identifier("_result"), + t.callExpression( + t.memberExpression( + t.identifier("_contract"), + t.identifier(method) + ), + [t.identifier("_args")] + ) + ), + ]), + contractMethods[method] === "initialize" || + contractMethods[method] === "call" + ? // Counter._saveToStorage(_contract); + t.expressionStatement( + t.callExpression( + t.memberExpression( + classId, + t.identifier("_saveToStorage") + ), + [t.identifier("_contract")] + ) + ) + : t.emptyStatement(), + // if (_result !== undefined) + // if (_result && _result.constructor && _result.constructor.name === 'NearPromise') + // _result.onReturn(); + // else + // near.valueReturn(_contract._serialize(result)); + t.ifStatement( + t.binaryExpression( + "!==", + t.identifier("_result"), + t.identifier("undefined") + ), + t.ifStatement( + t.logicalExpression( + "&&", + t.logicalExpression( + "&&", + t.identifier("_result"), + t.memberExpression( + t.identifier("_result"), + t.identifier("constructor") + ) + ), + t.binaryExpression( + "===", + t.memberExpression( + t.memberExpression( + t.identifier("_result"), + t.identifier("constructor") + ), + t.identifier("name") + ), + t.stringLiteral("NearPromise") + ) + ), + t.expressionStatement( + t.callExpression( + t.memberExpression( + t.identifier("_result"), + t.identifier("onReturn") + ), + [] + ) + ), + t.expressionStatement( + t.callExpression( + t.memberExpression( + t.identifier("env"), + t.identifier("value_return") + ), + [ + t.callExpression( + t.memberExpression( + classId, + t.identifier("_serialize") + ), + [t.identifier("_result")] + ), + ] + ) + ) + ) + ), + ]) + ) + ) + ); console.log(`Babel ${method} method export done`); } } - } - } + }, + }, }; } diff --git a/src/collections/index.ts b/src/collections/index.ts index 48cf8c752..732429d69 100644 --- a/src/collections/index.ts +++ b/src/collections/index.ts @@ -4,10 +4,4 @@ import { LookupSet } from "./lookup-set"; import { UnorderedMap } from "./unordered-map"; import { UnorderedSet } from "./unordered-set"; -export { - LookupMap, - Vector, - LookupSet, - UnorderedMap, - UnorderedSet -} \ No newline at end of file +export { LookupMap, Vector, LookupSet, UnorderedMap, UnorderedSet }; diff --git a/src/collections/lookup-map.ts b/src/collections/lookup-map.ts index 298f77795..534bf3bca 100644 --- a/src/collections/lookup-map.ts +++ b/src/collections/lookup-map.ts @@ -1,58 +1,60 @@ -import * as near from '../api' -import { GetOptions } from '../types/collections'; -import { Bytes } from '../utils'; +import * as near from "../api"; +import { GetOptions } from "../types/collections"; +import { Bytes } from "../utils"; export class LookupMap { - readonly keyPrefix: Bytes; - - constructor(keyPrefix: Bytes) { - this.keyPrefix = keyPrefix - } - - containsKey(key: Bytes): boolean { - let storageKey = this.keyPrefix + JSON.stringify(key) - return near.storageHasKey(storageKey) - } - - get(key: Bytes, options?: GetOptions): DataType | null { - let storageKey = this.keyPrefix + JSON.stringify(key) - let raw = near.storageRead(storageKey) - if (raw !== null) { - const value = JSON.parse(raw) - return !!options?.reconstructor ? options.reconstructor(value) : value as DataType - } - return null - } - - remove(key: Bytes): DataType | null { - let storageKey = this.keyPrefix + JSON.stringify(key) - if (near.storageRemove(storageKey)) { - return JSON.parse(near.storageGetEvicted()) - } - return null - } - - set(key: Bytes, value: DataType): DataType | null { - let storageKey = this.keyPrefix + JSON.stringify(key) - let storageValue = JSON.stringify(value) - if (near.storageWrite(storageKey, storageValue)) { - return JSON.parse(near.storageGetEvicted()) - } - return null - } - - extend(objects: [Bytes, DataType][]) { - for (let kv of objects) { - this.set(kv[0], kv[1]) - } - } - - serialize(): string { - return JSON.stringify(this) - } - - // converting plain object to class object - static reconstruct(data: LookupMap): LookupMap { - return new LookupMap(data.keyPrefix) - } -} \ No newline at end of file + readonly keyPrefix: Bytes; + + constructor(keyPrefix: Bytes) { + this.keyPrefix = keyPrefix; + } + + containsKey(key: Bytes): boolean { + const storageKey = this.keyPrefix + JSON.stringify(key); + return near.storageHasKey(storageKey); + } + + get(key: Bytes, options?: GetOptions): DataType | null { + const storageKey = this.keyPrefix + JSON.stringify(key); + const raw = near.storageRead(storageKey); + if (raw !== null) { + const value = JSON.parse(raw); + return options?.reconstructor + ? options.reconstructor(value) + : (value as DataType); + } + return null; + } + + remove(key: Bytes): DataType | null { + const storageKey = this.keyPrefix + JSON.stringify(key); + if (near.storageRemove(storageKey)) { + return JSON.parse(near.storageGetEvicted()); + } + return null; + } + + set(key: Bytes, value: DataType): DataType | null { + const storageKey = this.keyPrefix + JSON.stringify(key); + const storageValue = JSON.stringify(value); + if (near.storageWrite(storageKey, storageValue)) { + return JSON.parse(near.storageGetEvicted()); + } + return null; + } + + extend(objects: [Bytes, DataType][]) { + for (const kv of objects) { + this.set(kv[0], kv[1]); + } + } + + serialize(): string { + return JSON.stringify(this); + } + + // converting plain object to class object + static reconstruct(data: LookupMap): LookupMap { + return new LookupMap(data.keyPrefix); + } +} diff --git a/src/collections/lookup-set.ts b/src/collections/lookup-set.ts index 777fdb3a5..5241f28c8 100644 --- a/src/collections/lookup-set.ts +++ b/src/collections/lookup-set.ts @@ -1,45 +1,43 @@ - - -import * as near from '../api' -import { Bytes } from '../utils'; +import * as near from "../api"; +import { Bytes } from "../utils"; export class LookupSet { - readonly keyPrefix: Bytes; - - constructor(keyPrefix: Bytes) { - this.keyPrefix = keyPrefix + readonly keyPrefix: Bytes; + + constructor(keyPrefix: Bytes) { + this.keyPrefix = keyPrefix; + } + + contains(key: Bytes): boolean { + const storageKey = this.keyPrefix + JSON.stringify(key); + return near.storageHasKey(storageKey); + } + + // Returns true if the element was present in the set. + remove(key: Bytes): boolean { + const storageKey = this.keyPrefix + JSON.stringify(key); + return near.storageRemove(storageKey); + } + + // If the set did not have this value present, `true` is returned. + // If the set did have this value present, `false` is returned. + set(key: Bytes): boolean { + const storageKey = this.keyPrefix + JSON.stringify(key); + return !near.storageWrite(storageKey, ""); + } + + extend(keys: Bytes[]) { + for (const key of keys) { + this.set(key); } + } - contains(key: Bytes): boolean { - let storageKey = this.keyPrefix + JSON.stringify(key) - return near.storageHasKey(storageKey) - } + serialize(): string { + return JSON.stringify(this); + } - // Returns true if the element was present in the set. - remove(key: Bytes): boolean { - let storageKey = this.keyPrefix + JSON.stringify(key) - return near.storageRemove(storageKey) - } - - // If the set did not have this value present, `true` is returned. - // If the set did have this value present, `false` is returned. - set(key: Bytes): boolean { - let storageKey = this.keyPrefix + JSON.stringify(key) - return !near.storageWrite(storageKey, '') - } - - extend(keys: Bytes[]) { - for (let key of keys) { - this.set(key) - } - } - - serialize(): string { - return JSON.stringify(this) - } - - // converting plain object to class object - static reconstruct(data: LookupSet): LookupSet { - return new LookupSet(data.keyPrefix) - } -} \ No newline at end of file + // converting plain object to class object + static reconstruct(data: LookupSet): LookupSet { + return new LookupSet(data.keyPrefix); + } +} diff --git a/src/collections/unordered-map.ts b/src/collections/unordered-map.ts index b69c55465..541967da2 100644 --- a/src/collections/unordered-map.ts +++ b/src/collections/unordered-map.ts @@ -6,7 +6,7 @@ import { GetOptions } from "../types/collections"; const ERR_INCONSISTENT_STATE = "The collection is an inconsistent state. Did previous smart contract execution terminate unexpectedly?"; -type ValueAndIndex = [value: DataType, index: number] +type ValueAndIndex = [value: DataType, index: number]; export class UnorderedMap { readonly prefix: Bytes; @@ -15,50 +15,50 @@ export class UnorderedMap { constructor(prefix: Bytes) { this.prefix = prefix; - this.keys = new Vector(prefix + 'u'); // intentional different prefix with old UnorderedMap - this.values = new LookupMap>(prefix + 'm'); + this.keys = new Vector(prefix + "u"); // intentional different prefix with old UnorderedMap + this.values = new LookupMap>(prefix + "m"); } get length() { - let keysLen = this.keys.length; + const keysLen = this.keys.length; return keysLen; } isEmpty(): boolean { - let keysIsEmpty = this.keys.isEmpty(); + const keysIsEmpty = this.keys.isEmpty(); return keysIsEmpty; } get(key: Bytes, options?: GetOptions): DataType | null { - let valueAndIndex = this.values.get(key); + const valueAndIndex = this.values.get(key); if (valueAndIndex === null) { return null; } - let value = (valueAndIndex as ValueAndIndex)[0]; - return !!options?.reconstructor ? options.reconstructor(value) : value; + const value = (valueAndIndex as ValueAndIndex)[0]; + return options?.reconstructor ? options.reconstructor(value) : value; } set(key: Bytes, value: DataType): DataType | null { - let valueAndIndex = this.values.get(key); + const valueAndIndex = this.values.get(key); if (valueAndIndex !== null) { - let oldValue = (valueAndIndex as ValueAndIndex)[0]; + const oldValue = (valueAndIndex as ValueAndIndex)[0]; (valueAndIndex as ValueAndIndex)[0] = value; - this.values.set(key, valueAndIndex) + this.values.set(key, valueAndIndex); return oldValue as DataType; } - let nextIndex = this.length; + const nextIndex = this.length; this.keys.push(key); this.values.set(key, [value, nextIndex]); return null; } remove(key: Bytes): DataType | null { - let oldValueAndIndex = this.values.remove(key); + const oldValueAndIndex = this.values.remove(key); if (oldValueAndIndex === null) { return null; } - let index = (oldValueAndIndex as ValueAndIndex)[1]; + const index = (oldValueAndIndex as ValueAndIndex)[1]; if (this.keys.swapRemove(index) === null) { throw new Error(ERR_INCONSISTENT_STATE); } @@ -66,18 +66,18 @@ export class UnorderedMap { // the last key is swapped to key[index], the corresponding [value, index] need update if (this.keys.length > 0 && index != this.keys.length) { // if there is still elements and it was not the last element - let swappedKey = this.keys.get(index) as Bytes; - let swappedValueAndIndex = this.values.get(swappedKey); + const swappedKey = this.keys.get(index) as Bytes; + const swappedValueAndIndex = this.values.get(swappedKey); if (swappedValueAndIndex === null) { - throw new Error(ERR_INCONSISTENT_STATE) + throw new Error(ERR_INCONSISTENT_STATE); } - this.values.set(swappedKey, [swappedValueAndIndex[0], index]) + this.values.set(swappedKey, [swappedValueAndIndex[0], index]); } return (oldValueAndIndex as ValueAndIndex)[0]; } clear() { - for (let key of this.keys) { + for (const key of this.keys) { // Set instead of remove to avoid loading the value from storage. this.values.set(key as Bytes, null); } @@ -85,8 +85,8 @@ export class UnorderedMap { } toArray(): [Bytes, DataType][] { - let ret = []; - for (let v of this) { + const ret = []; + for (const v of this) { ret.push(v); } return ret; @@ -97,7 +97,7 @@ export class UnorderedMap { } extend(kvs: [Bytes, DataType][]) { - for (let [k, v] of kvs) { + for (const [k, v] of kvs) { this.set(k, v); } } @@ -107,10 +107,12 @@ export class UnorderedMap { } // converting plain object to class object - static reconstruct(data: UnorderedMap): UnorderedMap { + static reconstruct( + data: UnorderedMap + ): UnorderedMap { // removing readonly modifier type MutableUnorderedMap = Mutable>; - let map = new UnorderedMap(data.prefix) as MutableUnorderedMap; + const map = new UnorderedMap(data.prefix) as MutableUnorderedMap; // reconstruct keys Vector map.keys = new Vector(data.prefix + "u"); map.keys.length = data.keys.length; @@ -130,7 +132,7 @@ class UnorderedMapIterator { } next(): { value: [unknown | null, unknown | null]; done: boolean } { - let key = this.keys.next(); + const key = this.keys.next(); let value; if (!key.done) { value = this.map.get(key.value as Bytes); diff --git a/src/collections/unordered-set.ts b/src/collections/unordered-set.ts index 78c47bf99..2b5018621 100644 --- a/src/collections/unordered-set.ts +++ b/src/collections/unordered-set.ts @@ -7,14 +7,14 @@ const ERR_INCONSISTENT_STATE = "The collection is an inconsistent state. Did previous smart contract execution terminate unexpectedly?"; function serializeIndex(index: number) { - let data = new Uint32Array([index]); - let array = new Uint8Array(data.buffer); + const data = new Uint32Array([index]); + const array = new Uint8Array(data.buffer); return u8ArrayToBytes(array); } function deserializeIndex(rawIndex: Bytes): number { - let array = bytesToU8Array(rawIndex); - let data = new Uint32Array(array.buffer); + const array = bytesToU8Array(rawIndex); + const data = new Uint32Array(array.buffer); return data[0]; } @@ -26,7 +26,7 @@ export class UnorderedSet { constructor(prefix: Bytes) { this.prefix = prefix; this.elementIndexPrefix = prefix + "i"; - let elementsPrefix = prefix + "e"; + const elementsPrefix = prefix + "e"; this.elements = new Vector(elementsPrefix); } @@ -39,17 +39,17 @@ export class UnorderedSet { } contains(element: DataType): boolean { - let indexLookup = this.elementIndexPrefix + JSON.stringify(element); + const indexLookup = this.elementIndexPrefix + JSON.stringify(element); return near.storageHasKey(indexLookup); } set(element: DataType): boolean { - let indexLookup = this.elementIndexPrefix + JSON.stringify(element); + const indexLookup = this.elementIndexPrefix + JSON.stringify(element); if (near.storageRead(indexLookup)) { return false; } else { - let nextIndex = this.length; - let nextIndexRaw = serializeIndex(nextIndex); + const nextIndex = this.length; + const nextIndexRaw = serializeIndex(nextIndex); near.storageWrite(indexLookup, nextIndexRaw); this.elements.push(element); return true; @@ -57,8 +57,8 @@ export class UnorderedSet { } remove(element: DataType): boolean { - let indexLookup = this.elementIndexPrefix + JSON.stringify(element); - let indexRaw = near.storageRead(indexLookup); + const indexLookup = this.elementIndexPrefix + JSON.stringify(element); + const indexRaw = near.storageRead(indexLookup); if (indexRaw) { if (this.length == 1) { // If there is only one element then swap remove simply removes it without @@ -67,7 +67,7 @@ export class UnorderedSet { } else { // If there is more than one element then swap remove swaps it with the last // element. - let lastElement = this.elements.get(this.length - 1); + const lastElement = this.elements.get(this.length - 1); if (!lastElement) { throw new Error(ERR_INCONSISTENT_STATE); } @@ -75,12 +75,12 @@ export class UnorderedSet { // If the removed element was the last element from keys, then we don't need to // reinsert the lookup back. if (lastElement != element) { - let lastLookupElement = + const lastLookupElement = this.elementIndexPrefix + JSON.stringify(lastElement); near.storageWrite(lastLookupElement, indexRaw); } } - let index = deserializeIndex(indexRaw); + const index = deserializeIndex(indexRaw); this.elements.swapRemove(index); return true; } @@ -88,16 +88,16 @@ export class UnorderedSet { } clear() { - for (let element of this.elements) { - let indexLookup = this.elementIndexPrefix + JSON.stringify(element); + for (const element of this.elements) { + const indexLookup = this.elementIndexPrefix + JSON.stringify(element); near.storageRemove(indexLookup); } this.elements.clear(); } toArray(): Bytes[] { - let ret = []; - for (let v of this) { + const ret = []; + for (const v of this) { ret.push(v); } return ret; @@ -108,7 +108,7 @@ export class UnorderedSet { } extend(elements: DataType[]) { - for (let element of elements) { + for (const element of elements) { this.set(element); } } @@ -118,12 +118,14 @@ export class UnorderedSet { } // converting plain object to class object - static reconstruct(data: UnorderedSet): UnorderedSet { + static reconstruct( + data: UnorderedSet + ): UnorderedSet { // removing readonly modifier type MutableUnorderedSet = Mutable>; - let set = new UnorderedSet(data.prefix) as MutableUnorderedSet; + const set = new UnorderedSet(data.prefix) as MutableUnorderedSet; // reconstruct Vector - let elementsPrefix = data.prefix + "e"; + const elementsPrefix = data.prefix + "e"; set.elements = new Vector(elementsPrefix); set.elements.length = data.elements.length; return set as UnorderedSet; diff --git a/src/collections/vector.ts b/src/collections/vector.ts index 0d566377d..672987175 100644 --- a/src/collections/vector.ts +++ b/src/collections/vector.ts @@ -1,14 +1,14 @@ import * as near from "../api"; import { Bytes, u8ArrayToBytes } from "../utils"; -import {GetOptions} from '../types/collections' +import { GetOptions } from "../types/collections"; const ERR_INDEX_OUT_OF_BOUNDS = "Index out of bounds"; const ERR_INCONSISTENT_STATE = "The collection is an inconsistent state. Did previous smart contract execution terminate unexpectedly?"; function indexToKey(prefix: Bytes, index: number): Bytes { - let data = new Uint32Array([index]); - let array = new Uint8Array(data.buffer); - let key = u8ArrayToBytes(array); + const data = new Uint32Array([index]); + const array = new Uint8Array(data.buffer); + const key = u8ArrayToBytes(array); return prefix + key; } @@ -31,9 +31,11 @@ export class Vector { if (index >= this.length) { return null; } - let storageKey = indexToKey(this.prefix, index); - const value = JSON.parse(near.storageRead(storageKey)) - return !!options?.reconstructor ? options.reconstructor(value) : value as DataType + const storageKey = indexToKey(this.prefix, index); + const value = JSON.parse(near.storageRead(storageKey)); + return options?.reconstructor + ? options.reconstructor(value) + : (value as DataType); } /// Removes an element from the vector and returns it in serialized form. @@ -45,8 +47,8 @@ export class Vector { } else if (index + 1 == this.length) { return this.pop(); } else { - let key = indexToKey(this.prefix, index); - let last = this.pop(); + const key = indexToKey(this.prefix, index); + const last = this.pop(); if (near.storageWrite(key, JSON.stringify(last))) { return JSON.parse(near.storageGetEvicted()); } else { @@ -56,7 +58,7 @@ export class Vector { } push(element: DataType) { - let key = indexToKey(this.prefix, this.length); + const key = indexToKey(this.prefix, this.length); this.length += 1; near.storageWrite(key, JSON.stringify(element)); } @@ -65,8 +67,8 @@ export class Vector { if (this.isEmpty()) { return null; } else { - let lastIndex = this.length - 1; - let lastKey = indexToKey(this.prefix, lastIndex); + const lastIndex = this.length - 1; + const lastKey = indexToKey(this.prefix, lastIndex); this.length -= 1; if (near.storageRemove(lastKey)) { return JSON.parse(near.storageGetEvicted()); @@ -80,7 +82,7 @@ export class Vector { if (index >= this.length) { throw new Error(ERR_INDEX_OUT_OF_BOUNDS); } else { - let key = indexToKey(this.prefix, index); + const key = indexToKey(this.prefix, index); if (near.storageWrite(key, JSON.stringify(element))) { return JSON.parse(near.storageGetEvicted()); } else { @@ -90,7 +92,7 @@ export class Vector { } extend(elements: DataType[]) { - for (let element of elements) { + for (const element of elements) { this.push(element); } } @@ -101,15 +103,15 @@ export class Vector { clear() { for (let i = 0; i < this.length; i++) { - let key = indexToKey(this.prefix, i); + const key = indexToKey(this.prefix, i); near.storageRemove(key); } this.length = 0; } toArray(): DataType[] { - let ret = []; - for (let v of this) { + const ret = []; + for (const v of this) { ret.push(v); } return ret; @@ -121,7 +123,7 @@ export class Vector { // converting plain object to class object static reconstruct(data: Vector): Vector { - let vector = new Vector(data.prefix); + const vector = new Vector(data.prefix); vector.length = data.length; return vector; } @@ -137,7 +139,7 @@ export class VectorIterator { next(): { value: unknown | null; done: boolean } { if (this.current < this.vector.length) { - let value = this.vector.get(this.current); + const value = this.vector.get(this.current); this.current += 1; return { value, done: false }; } diff --git a/src/index.ts b/src/index.ts index 2eef8c0b4..d8af4d0e6 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,9 +1,4 @@ -import { - call, - view, - initialize, - NearBindgen -} from "./near-bindgen"; +import { call, view, initialize, NearBindgen } from "./near-bindgen"; import * as near from "./api"; import { @@ -33,5 +28,5 @@ export { Bytes, assert, NearPromise, - PromiseOrValue + PromiseOrValue, }; diff --git a/src/near-bindgen.ts b/src/near-bindgen.ts index 543eef897..79ff4674a 100644 --- a/src/near-bindgen.ts +++ b/src/near-bindgen.ts @@ -1,72 +1,97 @@ import * as near from "./api"; -export function initialize({ }) { - return function (target: Object, key: string | symbol, descriptor: TypedPropertyDescriptor): void { - } +export function initialize({}) { + return function ( + target: Object, + key: string | symbol, + descriptor: TypedPropertyDescriptor + ): void {}; } -export function call({ privateFunction = false, payableFunction = false }: { privateFunction?: boolean, payableFunction?: boolean }) { - return function (target: Object, key: string | symbol, descriptor: TypedPropertyDescriptor): void { - const originalMethod = descriptor.value; - descriptor.value = function (...args: any[]) { - if (privateFunction && near.predecessorAccountId() !== near.currentAccountId()) { - throw Error("Function is private"); - } - if (!payableFunction && near.attachedDeposit() > BigInt(0)) { - throw Error("Function is not payable"); - } - return originalMethod.apply(this, args); - } - } +export function call({ + privateFunction = false, + payableFunction = false, +}: { + privateFunction?: boolean; + payableFunction?: boolean; +}) { + return function ( + target: Object, + key: string | symbol, + descriptor: TypedPropertyDescriptor + ): void { + const originalMethod = descriptor.value; + descriptor.value = function (...args: any[]) { + if ( + privateFunction && + near.predecessorAccountId() !== near.currentAccountId() + ) { + throw Error("Function is private"); + } + if (!payableFunction && near.attachedDeposit() > BigInt(0)) { + throw Error("Function is not payable"); + } + return originalMethod.apply(this, args); + }; + }; } -export function view({ }) { - return function (target: Object, key: string | symbol, descriptor: TypedPropertyDescriptor): void { - } +export function view({}) { + return function ( + target: Object, + key: string | symbol, + descriptor: TypedPropertyDescriptor + ): void {}; } -export function NearBindgen({ requireInit = false }: { requireInit?: boolean }) { - return (target: T) => { - return class extends target { - static _create() { - return new target(); - } - - static _getState(): Object { - const rawState = near.storageRead("STATE"); - return rawState ? this._deserialize(rawState) : null; - } +export function NearBindgen({ + requireInit = false, +}: { + requireInit?: boolean; +}) { + return (target: T) => { + return class extends target { + static _create() { + return new target(); + } - static _saveToStorage(obj: Object): void { - near.storageWrite("STATE", this._serialize(obj)); - } + static _getState(): Object { + const rawState = near.storageRead("STATE"); + return rawState ? this._deserialize(rawState) : null; + } - static _getArgs(): JSON { - return JSON.parse(near.input() || "{}"); - } + static _saveToStorage(obj: Object): void { + near.storageWrite("STATE", this._serialize(obj)); + } - static _serialize(value: Object): string { - return JSON.stringify(value); - } + static _getArgs(): JSON { + return JSON.parse(near.input() || "{}"); + } - static _deserialize(value: string): Object { - return JSON.parse(value); - } + static _serialize(value: Object): string { + return JSON.stringify(value); + } - static _reconstruct(classObject: any, plainObject: JSON) { - for (const item in classObject) { - if (classObject[item].constructor?.reconstruct !== undefined) { - classObject[item] = classObject[item].constructor.reconstruct(plainObject[item]) - } else { - classObject[item] = plainObject[item] - } - } - return classObject - } + static _deserialize(value: string): Object { + return JSON.parse(value); + } - static _requireInit(): boolean { - return requireInit; - } + static _reconstruct(classObject: any, plainObject: JSON) { + for (const item in classObject) { + if (classObject[item].constructor?.reconstruct !== undefined) { + classObject[item] = classObject[item].constructor.reconstruct( + plainObject[item] + ); + } else { + classObject[item] = plainObject[item]; + } } - } -} \ No newline at end of file + return classObject; + } + + static _requireInit(): boolean { + return requireInit; + } + }; + }; +} diff --git a/src/promise.ts b/src/promise.ts index 7de4799af..897bdeebf 100644 --- a/src/promise.ts +++ b/src/promise.ts @@ -4,225 +4,339 @@ import { Balance, PublicKey, AccountId, Gas, GasWeight } from "./types"; import { Nonce } from "./types/primitives"; export abstract class PromiseAction { - abstract add(promise_index: number | bigint): void; + abstract add(promise_index: number | bigint): void; } export class CreateAccount extends PromiseAction { - add(promise_index: number | bigint) { - near.promiseBatchActionCreateAccount(promise_index); - } + add(promise_index: number | bigint) { + near.promiseBatchActionCreateAccount(promise_index); + } } export class DeployContract extends PromiseAction { - constructor(public code: Bytes) { super() } + constructor(public code: Bytes) { + super(); + } - add(promise_index: number | bigint) { - near.promiseBatchActionDeployContract(promise_index, this.code); - } + add(promise_index: number | bigint) { + near.promiseBatchActionDeployContract(promise_index, this.code); + } } -export class FunctionCall extends PromiseAction{ - constructor(public function_name: string, public args: Bytes, public amount: Balance, public gas: Gas) { super() } - - add(promise_index: number | bigint) { - near.promiseBatchActionFunctionCall(promise_index, this.function_name, this.args, this.amount, this.gas); - } +export class FunctionCall extends PromiseAction { + constructor( + public function_name: string, + public args: Bytes, + public amount: Balance, + public gas: Gas + ) { + super(); + } + + add(promise_index: number | bigint) { + near.promiseBatchActionFunctionCall( + promise_index, + this.function_name, + this.args, + this.amount, + this.gas + ); + } } export class FunctionCallWeight extends PromiseAction { - constructor(public function_name: string, public args: Bytes, public amount: Balance, public gas: Gas, public weight: GasWeight) { super() } - - add(promise_index: number | bigint) { - near.promiseBatchActionFunctionCallWeight(promise_index, this.function_name, this.args, this.amount, this.gas, this.weight); - } + constructor( + public function_name: string, + public args: Bytes, + public amount: Balance, + public gas: Gas, + public weight: GasWeight + ) { + super(); + } + + add(promise_index: number | bigint) { + near.promiseBatchActionFunctionCallWeight( + promise_index, + this.function_name, + this.args, + this.amount, + this.gas, + this.weight + ); + } } export class Transfer extends PromiseAction { - constructor(public amount: Balance) { super() } + constructor(public amount: Balance) { + super(); + } - add(promise_index: number | bigint) { - near.promiseBatchActionTransfer(promise_index, this.amount); - } + add(promise_index: number | bigint) { + near.promiseBatchActionTransfer(promise_index, this.amount); + } } export class Stake extends PromiseAction { - constructor(public amount: Balance, public public_key: PublicKey) { super() } - - add(promise_index: number | bigint) { - near.promiseBatchActionStake(promise_index, this.amount, this.public_key.data); - } + constructor(public amount: Balance, public public_key: PublicKey) { + super(); + } + + add(promise_index: number | bigint) { + near.promiseBatchActionStake( + promise_index, + this.amount, + this.public_key.data + ); + } } export class AddFullAccessKey extends PromiseAction { - constructor(public public_key: PublicKey, public nonce: Nonce) { super() } - - add(promise_index: number | bigint) { - near.promiseBatchActionAddKeyWithFullAccess(promise_index, this.public_key.data, this.nonce); - } + constructor(public public_key: PublicKey, public nonce: Nonce) { + super(); + } + + add(promise_index: number | bigint) { + near.promiseBatchActionAddKeyWithFullAccess( + promise_index, + this.public_key.data, + this.nonce + ); + } } export class AddAccessKey extends PromiseAction { - constructor(public public_key: PublicKey, public allowance: Balance, public receiver_id: AccountId, public function_names: string, public nonce: Nonce) { super() } - - add(promise_index: number | bigint) { - near.promiseBatchActionAddKeyWithFunctionCall(promise_index, this.public_key.data, this.nonce, this.allowance, this.receiver_id, this.function_names); - } + constructor( + public public_key: PublicKey, + public allowance: Balance, + public receiver_id: AccountId, + public function_names: string, + public nonce: Nonce + ) { + super(); + } + + add(promise_index: number | bigint) { + near.promiseBatchActionAddKeyWithFunctionCall( + promise_index, + this.public_key.data, + this.nonce, + this.allowance, + this.receiver_id, + this.function_names + ); + } } export class DeleteKey extends PromiseAction { - constructor(public public_key: PublicKey) { super() } + constructor(public public_key: PublicKey) { + super(); + } - add(promise_index: number | bigint) { - near.promiseBatchActionDeleteKey(promise_index, this.public_key.data); - } + add(promise_index: number | bigint) { + near.promiseBatchActionDeleteKey(promise_index, this.public_key.data); + } } export class DeleteAccount extends PromiseAction { - constructor(public beneficiary_id: AccountId) { super() } + constructor(public beneficiary_id: AccountId) { + super(); + } - add(promise_index: number | bigint) { - near.promiseBatchActionDeleteAccount(promise_index, this.beneficiary_id); - } + add(promise_index: number | bigint) { + near.promiseBatchActionDeleteAccount(promise_index, this.beneficiary_id); + } } class PromiseSingle { - constructor(public account_id: AccountId, public actions: PromiseAction[], public after: NearPromise | null, public promise_index: number | bigint | null) { } - - constructRecursively(): number | bigint { - if (this.promise_index !== null) { - return this.promise_index; - } - let promise_index; - if (this.after) { - promise_index = near.promiseBatchThen(this.after.constructRecursively(), this.account_id) - } else { - promise_index = near.promiseBatchCreate(this.account_id); - } - for (let action of this.actions) { - action.add(promise_index); - } - this.promise_index = promise_index; - return promise_index + constructor( + public account_id: AccountId, + public actions: PromiseAction[], + public after: NearPromise | null, + public promise_index: number | bigint | null + ) {} + + constructRecursively(): number | bigint { + if (this.promise_index !== null) { + return this.promise_index; + } + let promise_index; + if (this.after) { + promise_index = near.promiseBatchThen( + this.after.constructRecursively(), + this.account_id + ); + } else { + promise_index = near.promiseBatchCreate(this.account_id); } + for (const action of this.actions) { + action.add(promise_index); + } + this.promise_index = promise_index; + return promise_index; + } } export class PromiseJoint { - constructor(public promise_a: NearPromise, public promise_b: NearPromise, public promise_index: number | bigint | null) { } - - constructRecursively(): number | bigint { - if (this.promise_index !== null) { - return this.promise_index; - } - let res = near.promiseAnd(BigInt(this.promise_a.constructRecursively()), BigInt(this.promise_b.constructRecursively())); - this.promise_index = res - return res + constructor( + public promise_a: NearPromise, + public promise_b: NearPromise, + public promise_index: number | bigint | null + ) {} + + constructRecursively(): number | bigint { + if (this.promise_index !== null) { + return this.promise_index; } + const res = near.promiseAnd( + BigInt(this.promise_a.constructRecursively()), + BigInt(this.promise_b.constructRecursively()) + ); + this.promise_index = res; + return res; + } } type PromiseSubtype = PromiseSingle | PromiseJoint; export class NearPromise { - constructor(private subtype: PromiseSubtype, private should_return: boolean) { } - - static new(account_id: AccountId): NearPromise { - let subtype = new PromiseSingle(account_id, [], null, null); - let ret = new NearPromise(subtype, false); - return ret; + constructor( + private subtype: PromiseSubtype, + private should_return: boolean + ) {} + + static new(account_id: AccountId): NearPromise { + const subtype = new PromiseSingle(account_id, [], null, null); + const ret = new NearPromise(subtype, false); + return ret; + } + + private add_action(action: PromiseAction): NearPromise { + if (this.subtype instanceof PromiseJoint) { + throw new Error("Cannot add action to a joint promise."); + } else { + this.subtype.actions.push(action); } - - private add_action(action: PromiseAction): NearPromise{ - if (this.subtype instanceof PromiseJoint) { - throw new Error("Cannot add action to a joint promise.") - } else { - this.subtype.actions.push(action); - } - return this; + return this; + } + + createAccount(): NearPromise { + return this.add_action(new CreateAccount()); + } + + deployContract(code: Bytes): NearPromise { + return this.add_action(new DeployContract(code)); + } + + functionCall( + function_name: string, + args: Bytes, + amount: Balance, + gas: Gas + ): NearPromise { + return this.add_action(new FunctionCall(function_name, args, amount, gas)); + } + + functionCallWeight( + function_name: string, + args: Bytes, + amount: Balance, + gas: Gas, + weight: GasWeight + ): NearPromise { + return this.add_action( + new FunctionCallWeight(function_name, args, amount, gas, weight) + ); + } + + transfer(amount: Balance): NearPromise { + return this.add_action(new Transfer(amount)); + } + + stake(amount: Balance, public_key: PublicKey): NearPromise { + return this.add_action(new Stake(amount, public_key)); + } + + addFullAccessKey(public_key: PublicKey): NearPromise { + return this.addFullAccessKeyWithNonce(public_key, 0n); + } + + addFullAccessKeyWithNonce(public_key: PublicKey, nonce: Nonce): NearPromise { + return this.add_action(new AddFullAccessKey(public_key, nonce)); + } + + addAccessKey( + public_key: PublicKey, + allowance: Balance, + receiver_id: AccountId, + method_names: string + ): NearPromise { + return this.addAccessKeyWithNonce( + public_key, + allowance, + receiver_id, + method_names, + 0n + ); + } + + addAccessKeyWithNonce( + public_key: PublicKey, + allowance: Balance, + receiver_id: AccountId, + method_names: string, + nonce: Nonce + ): NearPromise { + return this.add_action( + new AddAccessKey(public_key, allowance, receiver_id, method_names, nonce) + ); + } + + deleteKey(public_key: PublicKey): NearPromise { + return this.add_action(new DeleteKey(public_key)); + } + + deleteAccount(beneficiary_id: AccountId): NearPromise { + return this.add_action(new DeleteAccount(beneficiary_id)); + } + + and(other: NearPromise): NearPromise { + const subtype = new PromiseJoint(this, other, null); + const ret = new NearPromise(subtype, false); + return ret; + } + + then(other: NearPromise): NearPromise { + if (other.subtype instanceof PromiseSingle) { + if (other.subtype.after !== null) { + throw new Error( + "Cannot callback promise which is already scheduled after another" + ); + } + other.subtype.after = this; + } else { + throw new Error("Cannot callback joint promise."); } - - createAccount(): NearPromise { - return this.add_action(new CreateAccount()); + return other; + } + + asReturn(): NearPromise { + this.should_return = true; + return this; + } + + constructRecursively(): number | bigint { + const res = this.subtype.constructRecursively(); + if (this.should_return) { + near.promiseReturn(res); } + return res; + } - deployContract(code: Bytes): NearPromise { - return this.add_action(new DeployContract(code)); - } - - functionCall(function_name: string, args: Bytes, amount: Balance, gas: Gas): NearPromise { - return this.add_action(new FunctionCall(function_name, args, amount, gas)); - } - - functionCallWeight(function_name: string, args: Bytes, amount: Balance, gas: Gas, weight: GasWeight): NearPromise { - return this.add_action(new FunctionCallWeight(function_name, args, amount, gas, weight)); - } - - transfer(amount: Balance): NearPromise { - return this.add_action(new Transfer(amount)); - } - - stake(amount: Balance, public_key: PublicKey): NearPromise { - return this.add_action(new Stake(amount, public_key)); - } - - addFullAccessKey(public_key: PublicKey): NearPromise { - return this.addFullAccessKeyWithNonce(public_key, 0n) - } - - addFullAccessKeyWithNonce(public_key: PublicKey, nonce: Nonce): NearPromise { - return this.add_action(new AddFullAccessKey(public_key, nonce)); - } - - addAccessKey(public_key: PublicKey, allowance: Balance, receiver_id: AccountId, method_names: string): NearPromise { - return this.addAccessKeyWithNonce(public_key, allowance, receiver_id, method_names, 0n) - } - - addAccessKeyWithNonce(public_key: PublicKey, allowance: Balance, receiver_id: AccountId, method_names: string, nonce: Nonce): NearPromise { - return this.add_action(new AddAccessKey(public_key, allowance, receiver_id, method_names, nonce)); - } - - deleteKey(public_key: PublicKey): NearPromise { - return this.add_action(new DeleteKey(public_key)); - } - - deleteAccount(beneficiary_id: AccountId): NearPromise { - return this.add_action(new DeleteAccount(beneficiary_id)); - } - - and(other: NearPromise): NearPromise { - let subtype = new PromiseJoint(this, other, null); - let ret = new NearPromise(subtype, false); - return ret; - } - - then(other: NearPromise): NearPromise { - if (other.subtype instanceof PromiseSingle) { - if (other.subtype.after !== null) { - throw new Error("Cannot callback promise which is already scheduled after another"); - } - other.subtype.after = this; - } else { - throw new Error("Cannot callback joint promise.") - } - return other; - } - - asReturn(): NearPromise { - this.should_return = true; - return this; - } - - constructRecursively(): number | bigint { - let res = this.subtype.constructRecursively(); - if (this.should_return) { - near.promiseReturn(res); - } - return res; - } - - // Called by NearBindgen, when return object is a NearPromise instance. - onReturn() { - this.asReturn().constructRecursively(); - } + // Called by NearBindgen, when return object is a NearPromise instance. + onReturn() { + this.asReturn().constructRecursively(); + } } export type PromiseOrValue = NearPromise | T; - diff --git a/src/types/collections.ts b/src/types/collections.ts index fb727c2ff..ff7024867 100644 --- a/src/types/collections.ts +++ b/src/types/collections.ts @@ -1,3 +1,3 @@ export type GetOptions = { - reconstructor?: (value: unknown) => DataType -} \ No newline at end of file + reconstructor?: (value: unknown) => DataType; +}; diff --git a/src/types/index.ts b/src/types/index.ts index ccec78c05..9ad08288a 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -1,12 +1,45 @@ import { AccountId } from "./account_id"; -import {BlockHeight, EpochHeight, Balance, StorageUsage} from './primitives' -import { PromiseResult, PromiseError, PromiseIndex, ReceiptIndex, IteratorIndex } from "./vm_types"; +import { BlockHeight, EpochHeight, Balance, StorageUsage } from "./primitives"; +import { + PromiseResult, + PromiseError, + PromiseIndex, + ReceiptIndex, + IteratorIndex, +} from "./vm_types"; import { Gas, ONE_TERA_GAS } from "./gas"; -import { PublicKey, CurveType, curveTypeFromStr, ParsePublicKeyError, InvalidLengthError, Base58Error, UnknownCurve } from "./public_key"; +import { + PublicKey, + CurveType, + curveTypeFromStr, + ParsePublicKeyError, + InvalidLengthError, + Base58Error, + UnknownCurve, +} from "./public_key"; -export {AccountId, BlockHeight, EpochHeight, Balance, StorageUsage, PromiseResult, PromiseError, PromiseIndex, ReceiptIndex, IteratorIndex, Gas, ONE_TERA_GAS, - PublicKey, CurveType, curveTypeFromStr, ParsePublicKeyError, InvalidLengthError, Base58Error, UnknownCurve} +export { + AccountId, + BlockHeight, + EpochHeight, + Balance, + StorageUsage, + PromiseResult, + PromiseError, + PromiseIndex, + ReceiptIndex, + IteratorIndex, + Gas, + ONE_TERA_GAS, + PublicKey, + CurveType, + curveTypeFromStr, + ParsePublicKeyError, + InvalidLengthError, + Base58Error, + UnknownCurve, +}; export type GasWeight = bigint; export const ONE_YOCTO: Balance = 1n; -export const ONE_NEAR: Balance = 1_000_000_000_000_000_000_000_000n; \ No newline at end of file +export const ONE_NEAR: Balance = 1_000_000_000_000_000_000_000_000n; diff --git a/src/types/primitives.ts b/src/types/primitives.ts index 7ee3a2bee..0b2325d69 100644 --- a/src/types/primitives.ts +++ b/src/types/primitives.ts @@ -2,4 +2,4 @@ export type StorageUsage = bigint; export type BlockHeight = bigint; export type EpochHeight = bigint; export type Balance = bigint; -export type Nonce = bigint; \ No newline at end of file +export type Nonce = bigint; diff --git a/src/types/public_key.ts b/src/types/public_key.ts index 271690a26..2d6e1c2e6 100644 --- a/src/types/public_key.ts +++ b/src/types/public_key.ts @@ -1,81 +1,84 @@ import { Bytes, bytes } from "../utils"; -import { base58 } from '@scure/base'; +import { base58 } from "@scure/base"; export enum CurveType { - ED25519 = 0, - SECP256K1 = 1, + ED25519 = 0, + SECP256K1 = 1, } function data_len(c: CurveType): number { - switch (c) { - case CurveType.ED25519: - return 32; - case CurveType.SECP256K1: - return 64; - default: - throw new UnknownCurve() - } + switch (c) { + case CurveType.ED25519: + return 32; + case CurveType.SECP256K1: + return 64; + default: + throw new UnknownCurve(); + } } function split_key_type_data(value: string): [CurveType, string] { - let idx = value.indexOf(":"); - if (idx >= 0) { - return [curveTypeFromStr(value.substring(0, idx)), value.substring(idx + 1)]; - } else { - return [CurveType.ED25519, value]; - } + const idx = value.indexOf(":"); + if (idx >= 0) { + return [ + curveTypeFromStr(value.substring(0, idx)), + value.substring(idx + 1), + ]; + } else { + return [CurveType.ED25519, value]; + } } export function curveTypeFromStr(value: string): CurveType { - switch (value) { - case "ed25519": - return CurveType.ED25519; - case "secp256k1": - return CurveType.SECP256K1; - default: - throw new UnknownCurve(); - } + switch (value) { + case "ed25519": + return CurveType.ED25519; + case "secp256k1": + return CurveType.SECP256K1; + default: + throw new UnknownCurve(); + } } export class ParsePublicKeyError extends Error {} export class InvalidLengthError extends ParsePublicKeyError { - constructor(public length: number) { - super(`Invalid length: ${length}`); - } + constructor(public length: number) { + super(`Invalid length: ${length}`); + } } export class Base58Error extends ParsePublicKeyError { - constructor(public error: string) { - super(`Base58 error: ${error}`); - } + constructor(public error: string) { + super(`Base58 error: ${error}`); + } } export class UnknownCurve extends ParsePublicKeyError { - constructor() { - super("Unknown curve"); - } + constructor() { + super("Unknown curve"); + } } export class PublicKey { - constructor(public data: Bytes) { - let curve_type = data.charCodeAt(0) as CurveType - let curve_len = data_len(curve_type) - if (data.length != curve_len + 1) { - throw new InvalidLengthError(data.length) - } - this.data = data + constructor(public data: Bytes) { + const curve_type = data.charCodeAt(0) as CurveType; + const curve_len = data_len(curve_type); + if (data.length != curve_len + 1) { + throw new InvalidLengthError(data.length); } + this.data = data; + } - curveType(): CurveType { - return this.data.charCodeAt(0) as CurveType - } + curveType(): CurveType { + return this.data.charCodeAt(0) as CurveType; + } - static fromString(s: string) { - let [curve, key_data] = split_key_type_data(s); - let data: Bytes; - try { - data = bytes(base58.decode(key_data)); - } catch (err) { - throw new Base58Error(err.message); - } - return new PublicKey(String.fromCharCode(curve) + data); + static fromString(s: string) { + const [curve, key_data] = split_key_type_data(s); + let data: Bytes; + try { + data = bytes(base58.decode(key_data)); + } catch (err) { + throw new Base58Error(err.message); } -} \ No newline at end of file + return new PublicKey(String.fromCharCode(curve) + data); + } +} diff --git a/src/types/vm_types.ts b/src/types/vm_types.ts index a37cc9247..4469a1532 100644 --- a/src/types/vm_types.ts +++ b/src/types/vm_types.ts @@ -3,12 +3,12 @@ export type ReceiptIndex = bigint; export type IteratorIndex = bigint; export enum PromiseResult { - NotReady = 0, - Successful = 1, - Failed = 2, + NotReady = 0, + Successful = 1, + Failed = 2, } export enum PromiseError { - Failed, - NotReady, -} \ No newline at end of file + Failed, + NotReady, +} diff --git a/src/utils.ts b/src/utils.ts index e23174df6..5c02a7e6d 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -2,7 +2,7 @@ export type Bytes = string; export function u8ArrayToBytes(array: Uint8Array) { let ret = ""; - for (let e of array) { + for (const e of array) { ret += String.fromCharCode(e); } return ret; @@ -11,7 +11,7 @@ export function u8ArrayToBytes(array: Uint8Array) { // TODO this function is a bit broken and the type can't be string // TODO for more info: https://github.com/near/near-sdk-js/issues/78 export function bytesToU8Array(bytes: Bytes): Uint8Array { - let ret = new Uint8Array(bytes.length); + const ret = new Uint8Array(bytes.length); for (let i = 0; i < bytes.length; i++) { ret[i] = bytes.charCodeAt(i); } @@ -40,10 +40,10 @@ function checkStringIsBytes(str: string) { export function assert(b: boolean, str: string) { if (b) { - return + return; } else { - throw Error("assertion failed: " + str) + throw Error("assertion failed: " + str); } } -export type Mutable = { -readonly [P in keyof T]: T[P] }; \ No newline at end of file +export type Mutable = { -readonly [P in keyof T]: T[P] }; diff --git a/tests/README.md b/tests/README.md index 95f17681e..7805f1521 100644 --- a/tests/README.md +++ b/tests/README.md @@ -3,6 +3,7 @@ This tests the functionality of high level APIs of NEAR-SDK-JS. Currently, it directly tests all collections and indirectly tests all decorators, serialization/deserialization, utils, code generation and some important APIs. Majority of near-sdk-js can be seen as tested. # Run tests + ``` yarn yarn build @@ -11,4 +12,4 @@ yarn test # Add a new test -Create a test contract that covers the API you want to test in `src/`. Add a build command in `build.sh`. Write ava test in `__tests__`. \ No newline at end of file +Create a test contract that covers the API you want to test in `src/`. Add a build command in `build.sh`. Write ava test in `__tests__`. diff --git a/tests/__tests__/bytes.ava.js b/tests/__tests__/bytes.ava.js index af0964d6e..be711b714 100644 --- a/tests/__tests__/bytes.ava.js +++ b/tests/__tests__/bytes.ava.js @@ -1,212 +1,209 @@ -import { Worker } from 'near-workspaces'; -import test from 'ava'; - -test.beforeEach(async t => { - // Init the worker and start a Sandbox server - const worker = await Worker.init(); - - // Prepare sandbox for tests, create accounts, deploy contracts, etx. - const root = worker.rootAccount; - - // Deploy the test contract. - const bytesContract = await root.devDeploy( - 'build/bytes.wasm', - ); - // Test users - const ali = await root.createSubAccount('ali'); - - // Save state for test runs - t.context.worker = worker; - t.context.accounts = { root, bytesContract, ali }; -}); +import { Worker } from "near-workspaces"; +import test from "ava"; -test.afterEach.always(async t => { - await t.context.worker.tearDown().catch(error => { - console.log('Failed to tear down the worker:', error); - }); -}); +test.beforeEach(async (t) => { + // Init the worker and start a Sandbox server + const worker = await Worker.init(); + // Prepare sandbox for tests, create accounts, deploy contracts, etx. + const root = worker.rootAccount; -test('Log expected types work', async t => { - const { ali, bytesContract } = t.context.accounts; - - let r = await ali.callRaw(bytesContract, 'log_expected_input_tests', ''); - t.deepEqual( - r.result.receipts_outcome[0].outcome.logs, - [ - "abc", - "水", - "333", - '\x00\x01\xff', - '\xe6\xb0\xb4', - "水", - "水" - ] - ); + // Deploy the test contract. + const bytesContract = await root.devDeploy("build/bytes.wasm"); + // Test users + const ali = await root.createSubAccount("ali"); + + // Save state for test runs + t.context.worker = worker; + t.context.accounts = { root, bytesContract, ali }; }); -test('Log unexpected types not logging', async t => { - const { ali, bytesContract } = t.context.accounts; - - let r = await ali.callRaw(bytesContract, 'log_unexpected_input_tests', ''); - // logUtf8 and logUtf16 only works with bytes, trying to log it with string is unexpected and behavior is undefined - // in this specific case, it logs nothing - t.deepEqual( - r.result.receipts_outcome[0].outcome.logs, - [ - "", - "", - ] - ); +test.afterEach.always(async (t) => { + await t.context.worker.tearDown().catch((error) => { + console.log("Failed to tear down the worker:", error); + }); }); -test('Log invalid utf-8 sequence panic', async t => { - const { ali, bytesContract } = t.context.accounts; +test("Log expected types work", async (t) => { + const { ali, bytesContract } = t.context.accounts; + + let r = await ali.callRaw(bytesContract, "log_expected_input_tests", ""); + t.deepEqual(r.result.receipts_outcome[0].outcome.logs, [ + "abc", + "水", + "333", + "\x00\x01\xff", + "\xe6\xb0\xb4", + "水", + "水", + ]); +}); - let r = await ali.callRaw(bytesContract, 'log_invalid_utf8_sequence_test', ''); - // console.log(JSON.stringify(r, null, 2)) - t.deepEqual( - r.result.receipts_outcome[0].outcome.status.Failure.ActionError.kind.FunctionCallError.ExecutionError, - 'String encoding is bad UTF-8 sequence.' - ); +test("Log unexpected types not logging", async (t) => { + const { ali, bytesContract } = t.context.accounts; + + let r = await ali.callRaw(bytesContract, "log_unexpected_input_tests", ""); + // logUtf8 and logUtf16 only works with bytes, trying to log it with string is unexpected and behavior is undefined + // in this specific case, it logs nothing + t.deepEqual(r.result.receipts_outcome[0].outcome.logs, ["", ""]); }); -test('Log invalid utf-16 sequence panic', async t => { - const { ali, bytesContract } = t.context.accounts; +test("Log invalid utf-8 sequence panic", async (t) => { + const { ali, bytesContract } = t.context.accounts; + + let r = await ali.callRaw( + bytesContract, + "log_invalid_utf8_sequence_test", + "" + ); + // console.log(JSON.stringify(r, null, 2)) + t.deepEqual( + r.result.receipts_outcome[0].outcome.status.Failure.ActionError.kind + .FunctionCallError.ExecutionError, + "String encoding is bad UTF-8 sequence." + ); +}); - let r = await ali.callRaw(bytesContract, 'log_invalid_utf16_sequence_test', ''); - t.deepEqual( - r.result.receipts_outcome[0].outcome.status.Failure.ActionError.kind.FunctionCallError.ExecutionError, - 'String encoding is bad UTF-16 sequence.' - ); +test("Log invalid utf-16 sequence panic", async (t) => { + const { ali, bytesContract } = t.context.accounts; + + let r = await ali.callRaw( + bytesContract, + "log_invalid_utf16_sequence_test", + "" + ); + t.deepEqual( + r.result.receipts_outcome[0].outcome.status.Failure.ActionError.kind + .FunctionCallError.ExecutionError, + "String encoding is bad UTF-16 sequence." + ); }); function encodeStateKey(k) { - return Buffer.from(k).toString('base64') + return Buffer.from(k).toString("base64"); } -test('storage write bytes tests', async t => { - const { ali, bytesContract } = t.context.accounts; - - await ali.call(bytesContract, 'storage_write_bytes', ''); - let stateMap = new Map() - // viewState doesn't work, because it tries to convert key to utf-8 string, which is not. So we use viewStateRaw - let state = await bytesContract.viewStateRaw() - for (let {key, value} of state) { - stateMap.set(key, value) - } - - t.deepEqual( - stateMap.get(encodeStateKey('abc')), - Buffer.from('def').toString('base64') - ); - t.deepEqual( - stateMap.get(encodeStateKey([0x00, 0x01, 0xff])), - Buffer.from([0xe6, 0xb0, 0xb4]).toString('base64') - ); - t.deepEqual( - stateMap.get(encodeStateKey([0xe6, 0xb0, 0xb4])), - Buffer.from([0x00, 'a'.charCodeAt(0), 'b'.charCodeAt(0)]).toString('base64') - ); +test("storage write bytes tests", async (t) => { + const { ali, bytesContract } = t.context.accounts; + + await ali.call(bytesContract, "storage_write_bytes", ""); + let stateMap = new Map(); + // viewState doesn't work, because it tries to convert key to utf-8 string, which is not. So we use viewStateRaw + let state = await bytesContract.viewStateRaw(); + for (let { key, value } of state) { + stateMap.set(key, value); + } + + t.deepEqual( + stateMap.get(encodeStateKey("abc")), + Buffer.from("def").toString("base64") + ); + t.deepEqual( + stateMap.get(encodeStateKey([0x00, 0x01, 0xff])), + Buffer.from([0xe6, 0xb0, 0xb4]).toString("base64") + ); + t.deepEqual( + stateMap.get(encodeStateKey([0xe6, 0xb0, 0xb4])), + Buffer.from([0x00, "a".charCodeAt(0), "b".charCodeAt(0)]).toString("base64") + ); }); -test('storage write unexpected types tests', async t => { - const { ali, bytesContract } = t.context.accounts; - - await ali.call(bytesContract, 'storage_write_unexpected_input', ''); - let stateMap = new Map() - // viewState doesn't work, because it tries to convert key to utf-8 string, which is not - let state = await bytesContract.viewStateRaw() - for (let {key, value} of state) { - stateMap.set(key, value) - } - - t.deepEqual( - stateMap.get(encodeStateKey('123')), - Buffer.from('456').toString('base64') - ); - // pass in utf-8 string instead of bytes, key and value become empty - t.deepEqual( - stateMap.get(encodeStateKey([0xe6, 0xb0, 0xb4])), - undefined - ); - t.deepEqual( - stateMap.get(encodeStateKey([])), - '' - ); +test("storage write unexpected types tests", async (t) => { + const { ali, bytesContract } = t.context.accounts; + + await ali.call(bytesContract, "storage_write_unexpected_input", ""); + let stateMap = new Map(); + // viewState doesn't work, because it tries to convert key to utf-8 string, which is not + let state = await bytesContract.viewStateRaw(); + for (let { key, value } of state) { + stateMap.set(key, value); + } + + t.deepEqual( + stateMap.get(encodeStateKey("123")), + Buffer.from("456").toString("base64") + ); + // pass in utf-8 string instead of bytes, key and value become empty + t.deepEqual(stateMap.get(encodeStateKey([0xe6, 0xb0, 0xb4])), undefined); + t.deepEqual(stateMap.get(encodeStateKey([])), ""); }); -test('Storage read bytes tests', async t => { - const { ali, bytesContract } = t.context.accounts; - - await ali.call(bytesContract, 'storage_write_bytes', ''); - let r = await bytesContract.viewRaw('storage_read_ascii_bytes', ''); - console.log(r) - t.deepEqual( - r.result, - [100, 101, 102] - ); - - r = await bytesContract.viewRaw('storage_read_arbitrary_bytes_key_utf8_sequence_bytes_value', ''); - t.deepEqual( - r.result, - [0xe6, 0xb0, 0xb4] - ); - - r = await bytesContract.viewRaw('storage_read_utf8_sequence_bytes_key_arbitrary_bytes_value', ''); - t.deepEqual( - r.result, - [0x00, 'a'.charCodeAt(0), 'b'.charCodeAt(0)] - ); +test("Storage read bytes tests", async (t) => { + const { ali, bytesContract } = t.context.accounts; + + await ali.call(bytesContract, "storage_write_bytes", ""); + let r = await bytesContract.viewRaw("storage_read_ascii_bytes", ""); + console.log(r); + t.deepEqual(r.result, [100, 101, 102]); + + r = await bytesContract.viewRaw( + "storage_read_arbitrary_bytes_key_utf8_sequence_bytes_value", + "" + ); + t.deepEqual(r.result, [0xe6, 0xb0, 0xb4]); + + r = await bytesContract.viewRaw( + "storage_read_utf8_sequence_bytes_key_arbitrary_bytes_value", + "" + ); + t.deepEqual(r.result, [0x00, "a".charCodeAt(0), "b".charCodeAt(0)]); }); -test('panic tests', async t => { - const { ali, bytesContract } = t.context.accounts; - let r = await ali.callRaw(bytesContract, 'panic_test', ''); - t.assert( - r.result.receipts_outcome[0].outcome.status.Failure.ActionError.kind.FunctionCallError.ExecutionError - .match(/Smart contract panicked:*/) - ); - - r = await ali.callRaw(bytesContract, 'panic_ascii_test', ''); - t.assert( - r.result.receipts_outcome[0].outcome.status.Failure.ActionError.kind.FunctionCallError.ExecutionError - .match(/Smart contract panicked: abc*/) - ); - - r = await ali.callRaw(bytesContract, 'panic_js_number', ''); - t.assert( - r.result.receipts_outcome[0].outcome.status.Failure.ActionError.kind.FunctionCallError.ExecutionError - .match(/Smart contract panicked: 356*/) - ); - - r = await ali.callRaw(bytesContract, 'panic_js_undefined', ''); - t.assert( - r.result.receipts_outcome[0].outcome.status.Failure.ActionError.kind.FunctionCallError.ExecutionError - .match(/Smart contract panicked:*/) - ); - - r = await ali.callRaw(bytesContract, 'panic_js_null', ''); - t.assert( - r.result.receipts_outcome[0].outcome.status.Failure.ActionError.kind.FunctionCallError.ExecutionError - .match(/Smart contract panicked: null*/) - ); - - r = await ali.callRaw(bytesContract, 'panic_utf8_test', ''); - t.assert( - r.result.receipts_outcome[0].outcome.status.Failure.ActionError.kind.FunctionCallError.ExecutionError - .match(/Smart contract panicked: 水*/) - ); - - r = await ali.callRaw(bytesContract, 'panicUtf8_valid_utf8_sequence', ''); - t.assert( - r.result.receipts_outcome[0].outcome.status.Failure.ActionError.kind.FunctionCallError.ExecutionError - .match(/Smart contract panicked: 水*/) - ); - - r = await ali.callRaw(bytesContract, 'panicUtf8_invalid_utf8_sequence', ''); - t.deepEqual( - r.result.receipts_outcome[0].outcome.status.Failure.ActionError.kind.FunctionCallError.ExecutionError, - 'String encoding is bad UTF-8 sequence.' - ); -}) \ No newline at end of file +test("panic tests", async (t) => { + const { ali, bytesContract } = t.context.accounts; + let r = await ali.callRaw(bytesContract, "panic_test", ""); + t.assert( + r.result.receipts_outcome[0].outcome.status.Failure.ActionError.kind.FunctionCallError.ExecutionError.match( + /Smart contract panicked:*/ + ) + ); + + r = await ali.callRaw(bytesContract, "panic_ascii_test", ""); + t.assert( + r.result.receipts_outcome[0].outcome.status.Failure.ActionError.kind.FunctionCallError.ExecutionError.match( + /Smart contract panicked: abc*/ + ) + ); + + r = await ali.callRaw(bytesContract, "panic_js_number", ""); + t.assert( + r.result.receipts_outcome[0].outcome.status.Failure.ActionError.kind.FunctionCallError.ExecutionError.match( + /Smart contract panicked: 356*/ + ) + ); + + r = await ali.callRaw(bytesContract, "panic_js_undefined", ""); + t.assert( + r.result.receipts_outcome[0].outcome.status.Failure.ActionError.kind.FunctionCallError.ExecutionError.match( + /Smart contract panicked:*/ + ) + ); + + r = await ali.callRaw(bytesContract, "panic_js_null", ""); + t.assert( + r.result.receipts_outcome[0].outcome.status.Failure.ActionError.kind.FunctionCallError.ExecutionError.match( + /Smart contract panicked: null*/ + ) + ); + + r = await ali.callRaw(bytesContract, "panic_utf8_test", ""); + t.assert( + r.result.receipts_outcome[0].outcome.status.Failure.ActionError.kind.FunctionCallError.ExecutionError.match( + /Smart contract panicked: 水*/ + ) + ); + + r = await ali.callRaw(bytesContract, "panicUtf8_valid_utf8_sequence", ""); + t.assert( + r.result.receipts_outcome[0].outcome.status.Failure.ActionError.kind.FunctionCallError.ExecutionError.match( + /Smart contract panicked: 水*/ + ) + ); + + r = await ali.callRaw(bytesContract, "panicUtf8_invalid_utf8_sequence", ""); + t.deepEqual( + r.result.receipts_outcome[0].outcome.status.Failure.ActionError.kind + .FunctionCallError.ExecutionError, + "String encoding is bad UTF-8 sequence." + ); +}); diff --git a/tests/__tests__/decorators/near_bindgen.ava.js b/tests/__tests__/decorators/near_bindgen.ava.js index 048e813ee..be4dc2f0e 100644 --- a/tests/__tests__/decorators/near_bindgen.ava.js +++ b/tests/__tests__/decorators/near_bindgen.ava.js @@ -1,59 +1,70 @@ -import { Worker } from 'near-workspaces'; -import test from 'ava'; +import { Worker } from "near-workspaces"; +import test from "ava"; -test.beforeEach(async t => { - const worker = await Worker.init(); - const root = worker.rootAccount; +test.beforeEach(async (t) => { + const worker = await Worker.init(); + const root = worker.rootAccount; - const reqireInitFalse = await root.devDeploy('build/require_init_false.wasm'); - const reqireInitTrue = await root.devDeploy('build/require_init_true.wasm'); + const reqireInitFalse = await root.devDeploy("build/require_init_false.wasm"); + const reqireInitTrue = await root.devDeploy("build/require_init_true.wasm"); - const ali = await root.createSubAccount('ali'); + const ali = await root.createSubAccount("ali"); - t.context.worker = worker; - t.context.accounts = { - root, - reqireInitFalse, - reqireInitTrue, - ali, - }; + t.context.worker = worker; + t.context.accounts = { + root, + reqireInitFalse, + reqireInitTrue, + ali, + }; }); -test.afterEach.always(async t => { - await t.context.worker.tearDown().catch(error => { - console.log('Failed to tear down the worker:', error); - }); +test.afterEach.always(async (t) => { + await t.context.worker.tearDown().catch((error) => { + console.log("Failed to tear down the worker:", error); + }); }); -test('Uninitialized contract throw error if requireInit = true', async t => { - const { ali, reqireInitTrue } = t.context.accounts; +test("Uninitialized contract throw error if requireInit = true", async (t) => { + const { ali, reqireInitTrue } = t.context.accounts; - const callResult = await ali.callRaw(reqireInitTrue, 'setStatus', { status: 'hello' }); - t.assert(callResult.result.status.Failure.ActionError.kind.FunctionCallError.ExecutionError.includes('Contract must be initialized')); + const callResult = await ali.callRaw(reqireInitTrue, "setStatus", { + status: "hello", + }); + t.assert( + callResult.result.status.Failure.ActionError.kind.FunctionCallError.ExecutionError.includes( + "Contract must be initialized" + ) + ); - const err = await t.throwsAsync(() => reqireInitTrue.view('getStatus', {})); - t.assert(err.message.includes('Contract must be initialized')); -}) - -test('Uninitialized contract does not throw error if requireInit = false', async t => { - const { ali, reqireInitFalse } = t.context.accounts; - - await ali.callRaw(reqireInitFalse, 'setStatus', { status: 'hello' }); - - t.is(await reqireInitFalse.view('getStatus', {}), 'hello') - -}) - -test('Init function panics if called more then once', async t => { - const { ali, reqireInitTrue, reqireInitFalse } = t.context.accounts; + const err = await t.throwsAsync(() => reqireInitTrue.view("getStatus", {})); + t.assert(err.message.includes("Contract must be initialized")); +}); - await ali.call(reqireInitTrue, 'init', { status: 'hello' }); - const res1 = await ali.callRaw(reqireInitTrue, 'init', { status: 'hello' }); - t.assert(res1.result.status.Failure.ActionError.kind.FunctionCallError.ExecutionError.includes('Contract already initialized')); +test("Uninitialized contract does not throw error if requireInit = false", async (t) => { + const { ali, reqireInitFalse } = t.context.accounts; + await ali.callRaw(reqireInitFalse, "setStatus", { status: "hello" }); - await ali.call(reqireInitFalse, 'init', { status: 'hello' }); - const res2 = await ali.callRaw(reqireInitFalse, 'init', { status: 'hello' }); - t.assert(res2.result.status.Failure.ActionError.kind.FunctionCallError.ExecutionError.includes('Contract already initialized')); -}) + t.is(await reqireInitFalse.view("getStatus", {}), "hello"); +}); +test("Init function panics if called more then once", async (t) => { + const { ali, reqireInitTrue, reqireInitFalse } = t.context.accounts; + + await ali.call(reqireInitTrue, "init", { status: "hello" }); + const res1 = await ali.callRaw(reqireInitTrue, "init", { status: "hello" }); + t.assert( + res1.result.status.Failure.ActionError.kind.FunctionCallError.ExecutionError.includes( + "Contract already initialized" + ) + ); + + await ali.call(reqireInitFalse, "init", { status: "hello" }); + const res2 = await ali.callRaw(reqireInitFalse, "init", { status: "hello" }); + t.assert( + res2.result.status.Failure.ActionError.kind.FunctionCallError.ExecutionError.includes( + "Contract already initialized" + ) + ); +}); diff --git a/tests/__tests__/decorators/payable.ava.js b/tests/__tests__/decorators/payable.ava.js index 8b2833e41..f111cd53c 100644 --- a/tests/__tests__/decorators/payable.ava.js +++ b/tests/__tests__/decorators/payable.ava.js @@ -1,61 +1,89 @@ -import { Worker } from 'near-workspaces'; -import test from 'ava'; +import { Worker } from "near-workspaces"; +import test from "ava"; const DEPOSIT = 1_000_000_000; -test.beforeEach(async t => { - const worker = await Worker.init(); - const root = worker.rootAccount; +test.beforeEach(async (t) => { + const worker = await Worker.init(); + const root = worker.rootAccount; - const payableContract = await root.devDeploy('build/payable.wasm'); - const ali = await root.createSubAccount('ali'); + const payableContract = await root.devDeploy("build/payable.wasm"); + const ali = await root.createSubAccount("ali"); - t.context.worker = worker; - t.context.accounts = { - root, - payableContract, - ali, - }; + t.context.worker = worker; + t.context.accounts = { + root, + payableContract, + ali, + }; }); - -test.afterEach.always(async t => { - await t.context.worker.tearDown().catch(error => { - console.log('Failed to tear down the worker:', error); - }); +test.afterEach.always(async (t) => { + await t.context.worker.tearDown().catch((error) => { + console.log("Failed to tear down the worker:", error); + }); }); -test('payable: true functions works with deposit', async t => { - const { ali, payableContract } = t.context.accounts; - - await t.notThrowsAsync(ali.call(payableContract, 'setValueWithPayableFunction', { value: 'hello' }, { attachedDeposit: DEPOSIT })); - -}) - -test('payable: true functions works without deposit', async t => { - const { ali, payableContract } = t.context.accounts; - - await t.notThrowsAsync(ali.call(payableContract, 'setValueWithPayableFunction', { value: 'hello' })); - -}) - -test('payable: false throws if atach deposit', async t => { - const { ali, payableContract } = t.context.accounts; +test("payable: true functions works with deposit", async (t) => { + const { ali, payableContract } = t.context.accounts; + + await t.notThrowsAsync( + ali.call( + payableContract, + "setValueWithPayableFunction", + { value: "hello" }, + { attachedDeposit: DEPOSIT } + ) + ); +}); - const result = await ali.callRaw(payableContract, 'setValueWithNotPayableFunction', { value: 'hello' }, { attachedDeposit: DEPOSIT }); +test("payable: true functions works without deposit", async (t) => { + const { ali, payableContract } = t.context.accounts; - t.assert(result.result.status.Failure.ActionError.kind.FunctionCallError.ExecutionError.includes('Function is not payable')); -}) + await t.notThrowsAsync( + ali.call(payableContract, "setValueWithPayableFunction", { value: "hello" }) + ); +}); -test('payable default throws if atach deposit', async t => { - const { ali, payableContract } = t.context.accounts; +test("payable: false throws if atach deposit", async (t) => { + const { ali, payableContract } = t.context.accounts; + + const result = await ali.callRaw( + payableContract, + "setValueWithNotPayableFunction", + { value: "hello" }, + { attachedDeposit: DEPOSIT } + ); + + t.assert( + result.result.status.Failure.ActionError.kind.FunctionCallError.ExecutionError.includes( + "Function is not payable" + ) + ); +}); - const result = await ali.callRaw(payableContract, 'setValueWithNotPayableFunctionByDefault', { value: 'hello' }, { attachedDeposit: DEPOSIT }); - t.assert(result.result.status.Failure.ActionError.kind.FunctionCallError.ExecutionError.includes('Function is not payable')); -}) +test("payable default throws if atach deposit", async (t) => { + const { ali, payableContract } = t.context.accounts; + + const result = await ali.callRaw( + payableContract, + "setValueWithNotPayableFunctionByDefault", + { value: "hello" }, + { attachedDeposit: DEPOSIT } + ); + t.assert( + result.result.status.Failure.ActionError.kind.FunctionCallError.ExecutionError.includes( + "Function is not payable" + ) + ); +}); -test('payable default works without deposit', async t => { - const { ali, payableContract } = t.context.accounts; +test("payable default works without deposit", async (t) => { + const { ali, payableContract } = t.context.accounts; - await t.notThrowsAsync(ali.call(payableContract, 'setValueWithNotPayableFunctionByDefault', { value: 'hello' })); -}) + await t.notThrowsAsync( + ali.call(payableContract, "setValueWithNotPayableFunctionByDefault", { + value: "hello", + }) + ); +}); diff --git a/tests/__tests__/decorators/private.ava.js b/tests/__tests__/decorators/private.ava.js index 14f675ca5..7e8c4dd4b 100644 --- a/tests/__tests__/decorators/private.ava.js +++ b/tests/__tests__/decorators/private.ava.js @@ -1,46 +1,57 @@ -import { Worker } from 'near-workspaces'; -import test from 'ava'; - -test.beforeEach(async t => { - const worker = await Worker.init(); - const root = worker.rootAccount; - - const contract = await root.devDeploy('build/private.wasm'); - const ali = await root.createSubAccount('ali'); - - t.context.worker = worker; - t.context.accounts = { - root, - contract, - ali, - }; +import { Worker } from "near-workspaces"; +import test from "ava"; + +test.beforeEach(async (t) => { + const worker = await Worker.init(); + const root = worker.rootAccount; + + const contract = await root.devDeploy("build/private.wasm"); + const ali = await root.createSubAccount("ali"); + + t.context.worker = worker; + t.context.accounts = { + root, + contract, + ali, + }; }); - -test.afterEach.always(async t => { - await t.context.worker.tearDown().catch(error => { - console.log('Failed to tear down the worker:', error); - }); +test.afterEach.always(async (t) => { + await t.context.worker.tearDown().catch((error) => { + console.log("Failed to tear down the worker:", error); + }); }); -test('private: true throws if called from another acc', async t => { - const { ali, contract } = t.context.accounts; - - const result = await ali.callRaw(contract, 'setValueWithPrivateFunction', { value: 'hello' }); - - t.assert(result.result.status.Failure.ActionError.kind.FunctionCallError.ExecutionError.includes('Function is private')); +test("private: true throws if called from another acc", async (t) => { + const { ali, contract } = t.context.accounts; -}) + const result = await ali.callRaw(contract, "setValueWithPrivateFunction", { + value: "hello", + }); -test('private: true not throws if called from owner acc', async t => { - const { contract } = t.context.accounts; + t.assert( + result.result.status.Failure.ActionError.kind.FunctionCallError.ExecutionError.includes( + "Function is private" + ) + ); +}); - await t.notThrowsAsync(contract.call(contract, 'setValueWithNotPrivateFunction', { value: 'hello' })); +test("private: true not throws if called from owner acc", async (t) => { + const { contract } = t.context.accounts; -}) + await t.notThrowsAsync( + contract.call(contract, "setValueWithNotPrivateFunction", { + value: "hello", + }) + ); +}); -test('private: default not throws from another acc', async t => { - const { ali, contract } = t.context.accounts; +test("private: default not throws from another acc", async (t) => { + const { ali, contract } = t.context.accounts; - await t.notThrowsAsync(ali.call(contract, 'setValueWithNotPrivateFunctionByDefault', { value: 'hello' })); -}) + await t.notThrowsAsync( + ali.call(contract, "setValueWithNotPrivateFunctionByDefault", { + value: "hello", + }) + ); +}); diff --git a/tests/__tests__/function-params.ava.js b/tests/__tests__/function-params.ava.js index 01cb0555e..72dfe9d3a 100644 --- a/tests/__tests__/function-params.ava.js +++ b/tests/__tests__/function-params.ava.js @@ -1,37 +1,41 @@ -import { Worker } from 'near-workspaces'; -import test from 'ava'; +import { Worker } from "near-workspaces"; +import test from "ava"; -test.before(async t => { - // Init the worker and start a Sandbox server - const worker = await Worker.init(); +test.before(async (t) => { + // Init the worker and start a Sandbox server + const worker = await Worker.init(); - // Prepare sandbox for tests, create accounts, deploy contracts, etx. - const root = worker.rootAccount; + // Prepare sandbox for tests, create accounts, deploy contracts, etx. + const root = worker.rootAccount; - // Deploy the test contract. - const functionParamsContract = await root.devDeploy( - 'build/function-params.wasm', - ); + // Deploy the test contract. + const functionParamsContract = await root.devDeploy( + "build/function-params.wasm" + ); - // Test users - const ali = await root.createSubAccount('ali'); - const bob = await root.createSubAccount('bob'); - const carl = await root.createSubAccount('carl'); + // Test users + const ali = await root.createSubAccount("ali"); + const bob = await root.createSubAccount("bob"); + const carl = await root.createSubAccount("carl"); - // Save state for test runs - t.context.worker = worker; - t.context.accounts = { root, functionParamsContract, ali, bob, carl }; + // Save state for test runs + t.context.worker = worker; + t.context.accounts = { root, functionParamsContract, ali, bob, carl }; }); -test.after.always(async t => { - await t.context.worker.tearDown().catch(error => { - console.log('Failed to tear down the worker:', error); - }); +test.after.always(async (t) => { + await t.context.worker.tearDown().catch((error) => { + console.log("Failed to tear down the worker:", error); + }); }); -test('get current account id correct', async t => { - const { ali, functionParamsContract } = t.context.accounts; - await ali.call(functionParamsContract, 'set_values', { param1: 'newVal1', param2: 'newVal2', param3: 'newVal3' }); - let values = await functionParamsContract.view('get_values', ''); - t.deepEqual(values, { val3: 'newVal3', val2: 'newVal2', val1: 'newVal1' }); +test("get current account id correct", async (t) => { + const { ali, functionParamsContract } = t.context.accounts; + await ali.call(functionParamsContract, "set_values", { + param1: "newVal1", + param2: "newVal2", + param3: "newVal3", + }); + let values = await functionParamsContract.view("get_values", ""); + t.deepEqual(values, { val3: "newVal3", val2: "newVal2", val1: "newVal1" }); }); diff --git a/tests/__tests__/lookup-map.ava.js b/tests/__tests__/lookup-map.ava.js index 1ff0eeee2..824f674b8 100644 --- a/tests/__tests__/lookup-map.ava.js +++ b/tests/__tests__/lookup-map.ava.js @@ -1,128 +1,94 @@ -import { Worker } from 'near-workspaces'; -import test from 'ava'; +import { Worker } from "near-workspaces"; +import test from "ava"; -test.beforeEach(async t => { - // Init the worker and start a Sandbox server - const worker = await Worker.init(); +test.beforeEach(async (t) => { + // Init the worker and start a Sandbox server + const worker = await Worker.init(); - // Prepare sandbox for tests, create accounts, deploy contracts, etx. - const root = worker.rootAccount; + // Prepare sandbox for tests, create accounts, deploy contracts, etx. + const root = worker.rootAccount; - // Deploy the test contract. - const lookupMapContract = await root.devDeploy( - 'build/lookup-map.wasm', - ); + // Deploy the test contract. + const lookupMapContract = await root.devDeploy("build/lookup-map.wasm"); - // Test users - const ali = await root.createSubAccount('ali'); - const bob = await root.createSubAccount('bob'); - const carl = await root.createSubAccount('carl'); + // Test users + const ali = await root.createSubAccount("ali"); + const bob = await root.createSubAccount("bob"); + const carl = await root.createSubAccount("carl"); - // Save state for test runs - t.context.worker = worker; - t.context.accounts = { root, lookupMapContract, ali, bob, carl }; + // Save state for test runs + t.context.worker = worker; + t.context.accounts = { root, lookupMapContract, ali, bob, carl }; }); -test.afterEach.always(async t => { - await t.context.worker.tearDown().catch(error => { - console.log('Failed to tear down the worker:', error); - }); +test.afterEach.always(async (t) => { + await t.context.worker.tearDown().catch((error) => { + console.log("Failed to tear down the worker:", error); + }); }); -test('LookupMap set() get()', async t => { - const { ali, lookupMapContract } = t.context.accounts; - - t.is( - await lookupMapContract.view('get', { key: 'hello' }), - null - ); - t.is( - await lookupMapContract.view('containsKey', { key: 'hello' }), - false - ); - - await ali.call(lookupMapContract, 'set', { key: 'hello', value: 'world' }); - - t.is( - await lookupMapContract.view('get', { key: 'hello' }), - 'world' - ); - t.is( - await lookupMapContract.view('containsKey', { key: 'hello' }), - true - ); +test("LookupMap set() get()", async (t) => { + const { ali, lookupMapContract } = t.context.accounts; + + t.is(await lookupMapContract.view("get", { key: "hello" }), null); + t.is(await lookupMapContract.view("containsKey", { key: "hello" }), false); + + await ali.call(lookupMapContract, "set", { key: "hello", value: "world" }); + + t.is(await lookupMapContract.view("get", { key: "hello" }), "world"); + t.is(await lookupMapContract.view("containsKey", { key: "hello" }), true); }); +test("LookupMap update, remove", async (t) => { + const { ali, lookupMapContract } = t.context.accounts; + + await ali.call(lookupMapContract, "set", { key: "hello", value: "world" }); + await ali.call(lookupMapContract, "set", { key: "hello1", value: "world0" }); + + // update a value, len shouldn't change + await ali.call(lookupMapContract, "set", { key: "hello1", value: "world1" }); + // update should have effect + t.is(await lookupMapContract.view("get", { key: "hello1" }), "world1"); + // not update key should not changed + t.is(await lookupMapContract.view("get", { key: "hello" }), "world"); + // remove non existing element should not error + await ali.call(lookupMapContract, "remove_key", { key: "hello3" }); + // remove existing key should work + await ali.call(lookupMapContract, "remove_key", { key: "hello1" }); + t.is(await lookupMapContract.view("containsKey", { key: "hello1" }), false); + // not removed key should not affected + t.is(await lookupMapContract.view("get", { key: "hello" }), "world"); +}); -test('LookupMap update, remove', async t => { - const { ali, lookupMapContract } = t.context.accounts; - - await ali.call(lookupMapContract, 'set', { key: 'hello', value: 'world' }); - await ali.call(lookupMapContract, 'set', { key: 'hello1', value: 'world0' }); - - // update a value, len shouldn't change - await ali.call(lookupMapContract, 'set', { key: 'hello1', value: 'world1' }); - // update should have effect - t.is( - await lookupMapContract.view('get', { key: 'hello1' }), - 'world1' - ); - // not update key should not changed - t.is( - await lookupMapContract.view('get', { key: 'hello' }), - 'world' - ); - // remove non existing element should not error - await ali.call(lookupMapContract, 'remove_key', { key: 'hello3' }); - // remove existing key should work - await ali.call(lookupMapContract, 'remove_key', { key: 'hello1' }); - t.is( - await lookupMapContract.view('containsKey', { key: 'hello1' }), - false - ); - // not removed key should not affected - t.is( - await lookupMapContract.view('get', { key: 'hello' }), - 'world' - ); +test("LookupMap extend", async (t) => { + const { ali, lookupMapContract } = t.context.accounts; + + await ali.call(lookupMapContract, "extend", { + kvs: [ + ["hello", "world"], + ["hello1", "world1"], + ["hello2", "world2"], + ], + }); + t.is(await lookupMapContract.view("get", { key: "hello" }), "world"); + t.is(await lookupMapContract.view("get", { key: "hello1" }), "world1"); + t.is(await lookupMapContract.view("get", { key: "hello2" }), "world2"); }); -test('LookupMap extend', async t => { - const { ali, lookupMapContract } = t.context.accounts; - - await ali.call(lookupMapContract, 'extend', { kvs: [['hello', 'world'], ['hello1', 'world1'], ['hello2', 'world2']] }); - t.is( - await lookupMapContract.view('get', { key: 'hello' }), - 'world' - ); - t.is( - await lookupMapContract.view('get', { key: 'hello1' }), - 'world1' - ); - t.is( - await lookupMapContract.view('get', { key: 'hello2' }), - 'world2' - ); -}) - -test('LookupMap set get object', async t => { - const { ali, lookupMapContract } = t.context.accounts; - await ali.call(lookupMapContract, 'add_house', {}); - t.is( - await lookupMapContract.view('get_house', {}), - 'house house1 has 2 rooms. room room1 is 200sqft.' - ) - -}) - -test('LookupMap allows you to use the same key for the second time', async t => { - const { ali, lookupMapContract } = t.context.accounts; - - await ali.call(lookupMapContract, 'set', { key: 'hello', value: 'world' }); - await ali.call(lookupMapContract, 'set', { key: 'hello', value: 'world' }); - - t.is( - await lookupMapContract.view('get', { key: 'hello' }), - 'world' - ); -}); \ No newline at end of file +test("LookupMap set get object", async (t) => { + const { ali, lookupMapContract } = t.context.accounts; + await ali.call(lookupMapContract, "add_house", {}); + t.is( + await lookupMapContract.view("get_house", {}), + "house house1 has 2 rooms. room room1 is 200sqft." + ); +}); + +test("LookupMap allows you to use the same key for the second time", async (t) => { + const { ali, lookupMapContract } = t.context.accounts; + + await ali.call(lookupMapContract, "set", { key: "hello", value: "world" }); + await ali.call(lookupMapContract, "set", { key: "hello", value: "world" }); + + t.is(await lookupMapContract.view("get", { key: "hello" }), "world"); +}); diff --git a/tests/__tests__/lookup-set.ava.js b/tests/__tests__/lookup-set.ava.js index 4e2a2024a..3ba227e81 100644 --- a/tests/__tests__/lookup-set.ava.js +++ b/tests/__tests__/lookup-set.ava.js @@ -1,98 +1,70 @@ -import { Worker } from 'near-workspaces'; -import test from 'ava'; +import { Worker } from "near-workspaces"; +import test from "ava"; -test.beforeEach(async t => { - // Init the worker and start a Sandbox server - const worker = await Worker.init(); +test.beforeEach(async (t) => { + // Init the worker and start a Sandbox server + const worker = await Worker.init(); - // Prepare sandbox for tests, create accounts, deploy contracts, etx. - const root = worker.rootAccount; + // Prepare sandbox for tests, create accounts, deploy contracts, etx. + const root = worker.rootAccount; - // Deploy the test contract. - const lookupSetContract = await root.devDeploy( - 'build/lookup-set.wasm', - ); - // Test users - const ali = await root.createSubAccount('ali'); - const bob = await root.createSubAccount('bob'); - const carl = await root.createSubAccount('carl'); + // Deploy the test contract. + const lookupSetContract = await root.devDeploy("build/lookup-set.wasm"); + // Test users + const ali = await root.createSubAccount("ali"); + const bob = await root.createSubAccount("bob"); + const carl = await root.createSubAccount("carl"); - // Save state for test runs - t.context.worker = worker; - t.context.accounts = { root, lookupSetContract, ali, bob, carl }; + // Save state for test runs + t.context.worker = worker; + t.context.accounts = { root, lookupSetContract, ali, bob, carl }; }); -test.afterEach.always(async t => { - await t.context.worker.tearDown().catch(error => { - console.log('Failed to tear down the worker:', error); - }); +test.afterEach.always(async (t) => { + await t.context.worker.tearDown().catch((error) => { + console.log("Failed to tear down the worker:", error); + }); }); -test('LookupSet set() contains()', async t => { - const { ali, lookupSetContract } = t.context.accounts; - t.is( - await lookupSetContract.view('contains', { key: 'hello' }), - false - ); +test("LookupSet set() contains()", async (t) => { + const { ali, lookupSetContract } = t.context.accounts; + t.is(await lookupSetContract.view("contains", { key: "hello" }), false); - await ali.call(lookupSetContract, 'set', { key: 'hello' }); + await ali.call(lookupSetContract, "set", { key: "hello" }); - t.is( - await lookupSetContract.view('contains', { key: 'hello' }), - true - ); + t.is(await lookupSetContract.view("contains", { key: "hello" }), true); }); +test("LookupSet remove", async (t) => { + const { ali, lookupSetContract } = t.context.accounts; -test('LookupSet remove', async t => { - const { ali, lookupSetContract } = t.context.accounts; + await ali.call(lookupSetContract, "set", { key: "hello" }); + await ali.call(lookupSetContract, "set", { key: "hello1" }); - await ali.call(lookupSetContract, 'set', { key: 'hello' }); - await ali.call(lookupSetContract, 'set', { key: 'hello1' }); - - // remove non existing element should not error - await ali.call(lookupSetContract, 'remove_key', { key: 'hello3' }); - // remove existing key should work - await ali.call(lookupSetContract, 'remove_key', { key: 'hello1' }); - t.is( - await lookupSetContract.view('contains', { key: 'hello1' }), - false - ); - // not removed key should not affected - t.is( - await lookupSetContract.view('contains', { key: 'hello' }), - true - ); + // remove non existing element should not error + await ali.call(lookupSetContract, "remove_key", { key: "hello3" }); + // remove existing key should work + await ali.call(lookupSetContract, "remove_key", { key: "hello1" }); + t.is(await lookupSetContract.view("contains", { key: "hello1" }), false); + // not removed key should not affected + t.is(await lookupSetContract.view("contains", { key: "hello" }), true); }); -test('LookupSet extend', async t => { - const { ali, lookupSetContract } = t.context.accounts; +test("LookupSet extend", async (t) => { + const { ali, lookupSetContract } = t.context.accounts; - await ali.call(lookupSetContract, 'extend', { keys: ['hello', 'world', 'hello1'] }); - t.is( - await lookupSetContract.view('contains', { key: 'hello' }), - true - ); - t.is( - await lookupSetContract.view('contains', { key: 'hello1' }), - true - ); - t.is( - await lookupSetContract.view('contains', { key: 'world' }), - true - ); -}) + await ali.call(lookupSetContract, "extend", { + keys: ["hello", "world", "hello1"], + }); + t.is(await lookupSetContract.view("contains", { key: "hello" }), true); + t.is(await lookupSetContract.view("contains", { key: "hello1" }), true); + t.is(await lookupSetContract.view("contains", { key: "world" }), true); +}); -test('Add and check exist of object', async t => { - const { ali, lookupSetContract } = t.context.accounts; - let houseSpec = {name: "a", rooms: [{name: "bedroom", size: "300sqft"}]} - t.is( - await lookupSetContract.view('house_exist', houseSpec), - false - ); - await ali.call(lookupSetContract, 'add_house', houseSpec); - t.is( - await lookupSetContract.view('house_exist', houseSpec), - true - ); -}) \ No newline at end of file +test("Add and check exist of object", async (t) => { + const { ali, lookupSetContract } = t.context.accounts; + let houseSpec = { name: "a", rooms: [{ name: "bedroom", size: "300sqft" }] }; + t.is(await lookupSetContract.view("house_exist", houseSpec), false); + await ali.call(lookupSetContract, "add_house", houseSpec); + t.is(await lookupSetContract.view("house_exist", houseSpec), true); +}); diff --git a/tests/__tests__/test-public-key.ava.js b/tests/__tests__/test-public-key.ava.js index 36d5aa68c..198a8a4d3 100644 --- a/tests/__tests__/test-public-key.ava.js +++ b/tests/__tests__/test-public-key.ava.js @@ -1,94 +1,110 @@ -import { Worker } from 'near-workspaces'; -import test from 'ava'; +import { Worker } from "near-workspaces"; +import test from "ava"; -test.before(async t => { - // Init the worker and start a Sandbox server - const worker = await Worker.init(); +test.before(async (t) => { + // Init the worker and start a Sandbox server + const worker = await Worker.init(); - // Prepare sandbox for tests, create accounts, deploy contracts, etx. - const root = worker.rootAccount; + // Prepare sandbox for tests, create accounts, deploy contracts, etx. + const root = worker.rootAccount; - // Create and deploy test contract - const pkContract = await root.createSubAccount('pk'); - await pkContract.deploy('build/public-key.wasm'); + // Create and deploy test contract + const pkContract = await root.createSubAccount("pk"); + await pkContract.deploy("build/public-key.wasm"); - // Test users - const ali = await root.createSubAccount('ali'); - const bob = await root.createSubAccount('bob'); - const carl = await root.createSubAccount('carl'); + // Test users + const ali = await root.createSubAccount("ali"); + const bob = await root.createSubAccount("bob"); + const carl = await root.createSubAccount("carl"); + // Save state for test runs + t.context.worker = worker; + t.context.accounts = { root, pkContract, ali, bob, carl }; +}); + +test.after.always(async (t) => { + await t.context.worker.tearDown().catch((error) => { + console.log("Failed to tear down the worker:", error); + }); +}); - // Save state for test runs - t.context.worker = worker; - t.context.accounts = { root, pkContract, ali, bob, carl }; +test("add signer key should success", async (t) => { + const { ali, pkContract } = t.context.accounts; + let r = await ali.callRaw(pkContract, "test_add_signer_key", ""); + t.is(r.result.status.SuccessValue, ""); }); -test.after.always(async t => { - await t.context.worker.tearDown().catch(error => { - console.log('Failed to tear down the worker:', error); - }); +test("add ed25519 key bytes should success", async (t) => { + const { ali, pkContract } = t.context.accounts; + let r = await ali.callRaw(pkContract, "test_add_ed25519_key_bytes", ""); + t.is(r.result.status.SuccessValue, ""); }); -test('add signer key should success', async t => { - const { ali, pkContract } = t.context.accounts; - let r = await ali.callRaw(pkContract, 'test_add_signer_key', ''); - t.is(r.result.status.SuccessValue, ''); +test("add ed25519 key string should success", async (t) => { + const { ali, pkContract } = t.context.accounts; + let r = await ali.callRaw(pkContract, "test_add_ed25519_key_string", ""); + t.is(r.result.status.SuccessValue, ""); }); -test('add ed25519 key bytes should success', async t => { - const { ali, pkContract } = t.context.accounts; - let r = await ali.callRaw(pkContract, 'test_add_ed25519_key_bytes', ''); - t.is(r.result.status.SuccessValue, ''); +test("add secp256k1 key bytes should success", async (t) => { + const { bob, pkContract } = t.context.accounts; + let r = await bob.callRaw(pkContract, "test_add_secp256k1_key_bytes", ""); + t.is(r.result.status.SuccessValue, ""); }); -test('add ed25519 key string should success', async t => { - const { ali, pkContract } = t.context.accounts; - let r = await ali.callRaw(pkContract, 'test_add_ed25519_key_string', ''); - t.is(r.result.status.SuccessValue, ''); +test("add secp256k1 key string should success", async (t) => { + const { bob, pkContract } = t.context.accounts; + let r = await bob.callRaw(pkContract, "test_add_secp256k1_key_string", "", { + gas: "100 Tgas", + }); + t.is(r.result.status.SuccessValue, ""); }); -test('add secp256k1 key bytes should success', async t => { - const { bob, pkContract } = t.context.accounts; - let r = await bob.callRaw(pkContract, 'test_add_secp256k1_key_bytes', ''); - t.is(r.result.status.SuccessValue, ''); +test("add invalid key should error", async (t) => { + const { bob, pkContract } = t.context.accounts; + let r = await bob.callRaw(pkContract, "add_invalid_public_key", ""); + t.is(r.result.status.SuccessValue, undefined); + t.is( + r.result.status.Failure.ActionError.kind.FunctionCallError.ExecutionError, + "VM Logic provided an invalid public key" + ); }); -test('add secp256k1 key string should success', async t => { - const { bob, pkContract } = t.context.accounts; - let r = await bob.callRaw(pkContract, 'test_add_secp256k1_key_string', '', {gas: '100 Tgas'}); - t.is(r.result.status.SuccessValue, ''); +test("curve type check should success", async (t) => { + const { carl, pkContract } = t.context.accounts; + let r = await carl.callRaw(pkContract, "curve_type", ""); + t.is(r.result.status.SuccessValue, ""); }); -test('add invalid key should error', async t => { - const { bob, pkContract } = t.context.accounts; - let r = await bob.callRaw(pkContract, 'add_invalid_public_key', ''); - t.is(r.result.status.SuccessValue, undefined); - t.is(r.result.status.Failure.ActionError.kind.FunctionCallError.ExecutionError, 'VM Logic provided an invalid public key'); +test("create invalid curve type should fail", async (t) => { + const { carl, pkContract } = t.context.accounts; + let r = await carl.callRaw(pkContract, "create_invalid_curve_type", ""); + t.is(r.result.status.SuccessValue, undefined); + t.assert( + r.result.status.Failure.ActionError.kind.FunctionCallError.ExecutionError.startsWith( + "Smart contract panicked: Unknown curve" + ) + ); }); -test('curve type check should success', async t => { - const { carl, pkContract } = t.context.accounts; - let r = await carl.callRaw(pkContract, 'curve_type', ''); - t.is(r.result.status.SuccessValue, ''); -}) - -test('create invalid curve type should fail', async t => { - const { carl, pkContract } = t.context.accounts; - let r = await carl.callRaw(pkContract, 'create_invalid_curve_type', ''); - t.is(r.result.status.SuccessValue, undefined); - t.assert(r.result.status.Failure.ActionError.kind.FunctionCallError.ExecutionError.startsWith('Smart contract panicked: Unknown curve')); -}) - -test('create invalid length should fail', async t => { - const { carl, pkContract } = t.context.accounts; - let r = await carl.callRaw(pkContract, 'create_invalid_length', ''); - t.is(r.result.status.SuccessValue, undefined); - t.assert(r.result.status.Failure.ActionError.kind.FunctionCallError.ExecutionError.startsWith('Smart contract panicked: Invalid length')); -}) - -test('create invalid base58 should fail', async t => { - const { carl, pkContract } = t.context.accounts; - let r = await carl.callRaw(pkContract, 'create_from_invalid_base58', ''); - t.is(r.result.status.SuccessValue, undefined); - t.assert(r.result.status.Failure.ActionError.kind.FunctionCallError.ExecutionError.startsWith('Smart contract panicked: Base58 error')); -}) \ No newline at end of file +test("create invalid length should fail", async (t) => { + const { carl, pkContract } = t.context.accounts; + let r = await carl.callRaw(pkContract, "create_invalid_length", ""); + t.is(r.result.status.SuccessValue, undefined); + t.assert( + r.result.status.Failure.ActionError.kind.FunctionCallError.ExecutionError.startsWith( + "Smart contract panicked: Invalid length" + ) + ); +}); + +test("create invalid base58 should fail", async (t) => { + const { carl, pkContract } = t.context.accounts; + let r = await carl.callRaw(pkContract, "create_from_invalid_base58", ""); + t.is(r.result.status.SuccessValue, undefined); + t.assert( + r.result.status.Failure.ActionError.kind.FunctionCallError.ExecutionError.startsWith( + "Smart contract panicked: Base58 error" + ) + ); +}); diff --git a/tests/__tests__/test_context_api.ava.js b/tests/__tests__/test_context_api.ava.js index a2517d44d..7479c3cd7 100644 --- a/tests/__tests__/test_context_api.ava.js +++ b/tests/__tests__/test_context_api.ava.js @@ -1,123 +1,146 @@ -import { Worker } from 'near-workspaces'; -import test from 'ava'; +import { Worker } from "near-workspaces"; +import test from "ava"; +test.before(async (t) => { + // Init the worker and start a Sandbox server + const worker = await Worker.init(); -test.before(async t => { - // Init the worker and start a Sandbox server - const worker = await Worker.init(); + // Prepare sandbox for tests, create accounts, deploy contracts, etx. + const root = worker.rootAccount; - // Prepare sandbox for tests, create accounts, deploy contracts, etx. - const root = worker.rootAccount; + // Deploy the test contract. + const contextApiContract = await root.devDeploy("build/context_api.wasm"); - // Deploy the test contract. - const contextApiContract = await root.devDeploy( - 'build/context_api.wasm', - ); + // Test users + const ali = await root.createSubAccount("ali"); + const bob = await root.createSubAccount("bob"); + const carl = await root.createSubAccount("carl"); - // Test users - const ali = await root.createSubAccount('ali'); - const bob = await root.createSubAccount('bob'); - const carl = await root.createSubAccount('carl'); - - // Save state for test runs - t.context.worker = worker; - t.context.accounts = { root, contextApiContract, ali, bob, carl }; + // Save state for test runs + t.context.worker = worker; + t.context.accounts = { root, contextApiContract, ali, bob, carl }; }); -test.after.always(async t => { - await t.context.worker.tearDown().catch(error => { - console.log('Failed to tear down the worker:', error); - }); +test.after.always(async (t) => { + await t.context.worker.tearDown().catch((error) => { + console.log("Failed to tear down the worker:", error); + }); }); - -test('get current account id correct', async t => { - const { ali, contextApiContract } = t.context.accounts; - let r = await ali.call(contextApiContract, 'get_current_account_id', ''); - t.is(r, contextApiContract.accountId); +test("get current account id correct", async (t) => { + const { ali, contextApiContract } = t.context.accounts; + let r = await ali.call(contextApiContract, "get_current_account_id", ""); + t.is(r, contextApiContract.accountId); }); -test('get signer account id correct', async t => { - const { ali, contextApiContract } = t.context.accounts; - let r = await ali.call(contextApiContract, 'get_signer_account_id', ''); - t.is(r, ali.accountId); +test("get signer account id correct", async (t) => { + const { ali, contextApiContract } = t.context.accounts; + let r = await ali.call(contextApiContract, "get_signer_account_id", ""); + t.is(r, ali.accountId); }); -test('get predecessor account id correct', async t => { - const { ali, contextApiContract } = t.context.accounts; - let r = await ali.call(contextApiContract, 'get_predecessor_account_id', ''); - t.is(r, ali.accountId); +test("get predecessor account id correct", async (t) => { + const { ali, contextApiContract } = t.context.accounts; + let r = await ali.call(contextApiContract, "get_predecessor_account_id", ""); + t.is(r, ali.accountId); }); -test('get signer account pk correct', async t => { - const { ali, contextApiContract } = t.context.accounts; - let r = await ali.callRaw(contextApiContract, 'get_signer_account_pk', ''); - // the prefixing byte 0 indicates it's a ED25519 PublicKey, see how PublicKey is serialized in nearcore - t.deepEqual(Buffer.from(r.result.status.SuccessValue, 'base64'), Buffer.concat([Buffer.from([0]), Buffer.from((await ali.getKey(ali.accountId)).getPublicKey().data)])); +test("get signer account pk correct", async (t) => { + const { ali, contextApiContract } = t.context.accounts; + let r = await ali.callRaw(contextApiContract, "get_signer_account_pk", ""); + // the prefixing byte 0 indicates it's a ED25519 PublicKey, see how PublicKey is serialized in nearcore + t.deepEqual( + Buffer.from(r.result.status.SuccessValue, "base64"), + Buffer.concat([ + Buffer.from([0]), + Buffer.from((await ali.getKey(ali.accountId)).getPublicKey().data), + ]) + ); }); -test('get input correct', async t => { - const { bob, contextApiContract } = t.context.accounts; - let r = await bob.callRaw(contextApiContract, 'get_input', new Uint8Array([0, 1, 255])); - t.is(r.result.status.SuccessValue, Buffer.from(new Uint8Array([0, 1, 255])).toString('base64')); +test("get input correct", async (t) => { + const { bob, contextApiContract } = t.context.accounts; + let r = await bob.callRaw( + contextApiContract, + "get_input", + new Uint8Array([0, 1, 255]) + ); + t.is( + r.result.status.SuccessValue, + Buffer.from(new Uint8Array([0, 1, 255])).toString("base64") + ); }); -test('get storage usage', async t => { - const { carl, contextApiContract } = t.context.accounts; - let r = await carl.call(contextApiContract, 'get_storage_usage', '', {gas: '10 TGas'}); - t.is(r>0, true); +test("get storage usage", async (t) => { + const { carl, contextApiContract } = t.context.accounts; + let r = await carl.call(contextApiContract, "get_storage_usage", "", { + gas: "10 TGas", + }); + t.is(r > 0, true); }); -test('get block height', async t => { - const { bob, contextApiContract } = t.context.accounts; - let r = await bob.call(contextApiContract, 'get_block_height', ''); - t.is(r > 0, true); +test("get block height", async (t) => { + const { bob, contextApiContract } = t.context.accounts; + let r = await bob.call(contextApiContract, "get_block_height", ""); + t.is(r > 0, true); }); -test('get block timestamp', async t => { - let time = new Date().getTime() * 1e6; - const { bob, contextApiContract } = t.context.accounts; - let r = await bob.call(contextApiContract, 'get_block_timestamp', ''); - t.is(r > time, true); +test("get block timestamp", async (t) => { + let time = new Date().getTime() * 1e6; + const { bob, contextApiContract } = t.context.accounts; + let r = await bob.call(contextApiContract, "get_block_timestamp", ""); + t.is(r > time, true); }); -test('get epoch height', async t => { - const { bob, contextApiContract } = t.context.accounts; - let r = await bob.call(contextApiContract, 'get_epoch_height', ''); - t.is(r, 1); +test("get epoch height", async (t) => { + const { bob, contextApiContract } = t.context.accounts; + let r = await bob.call(contextApiContract, "get_epoch_height", ""); + t.is(r, 1); }); -test('get attached deposit', async t => { - const { carl, contextApiContract } = t.context.accounts; - let r = await carl.call(contextApiContract, 'get_attached_deposit', '', {attachedDeposit: 3}); - t.is(r, 3); +test("get attached deposit", async (t) => { + const { carl, contextApiContract } = t.context.accounts; + let r = await carl.call(contextApiContract, "get_attached_deposit", "", { + attachedDeposit: 3, + }); + t.is(r, 3); }); -test('get prepaid gas', async t => { - const { carl, contextApiContract } = t.context.accounts; - let r = await carl.call(contextApiContract, 'get_prepaid_gas', '', {gas: '10 TGas'}); - t.is(r, 10000000000000); +test("get prepaid gas", async (t) => { + const { carl, contextApiContract } = t.context.accounts; + let r = await carl.call(contextApiContract, "get_prepaid_gas", "", { + gas: "10 TGas", + }); + t.is(r, 10000000000000); }); -test('get used gas', async t => { - const { carl, contextApiContract } = t.context.accounts; - let r = await carl.call(contextApiContract, 'get_used_gas', '', {gas: '10 TGas'}); - t.is(r>0, true); - t.is(r<10000000000000, true); +test("get used gas", async (t) => { + const { carl, contextApiContract } = t.context.accounts; + let r = await carl.call(contextApiContract, "get_used_gas", "", { + gas: "10 TGas", + }); + t.is(r > 0, true); + t.is(r < 10000000000000, true); }); -test('get random seed', async t => { - const { carl, contextApiContract } = t.context.accounts; - let r = await carl.callRaw(contextApiContract, 'get_random_seed', ''); - t.is(Buffer.from(r.result.status.SuccessValue, 'base64').length, 32); +test("get random seed", async (t) => { + const { carl, contextApiContract } = t.context.accounts; + let r = await carl.callRaw(contextApiContract, "get_random_seed", ""); + t.is(Buffer.from(r.result.status.SuccessValue, "base64").length, 32); }); -test('get validator stake test', async t => { - const { carl, contextApiContract, root } = t.context.accounts; - let r = await carl.call(contextApiContract, 'get_validator_stake', ''); - t.is(r, 0); - r = await root.callRaw(contextApiContract, 'get_validator_stake', ''); - t.is(Buffer.from(r.result.status.SuccessValue, 'base64').toString('ascii'), '50000000000000000000000000000000'); - r = await contextApiContract.viewRaw('get_total_stake', ''); - t.is(Buffer.from(r.result).toString('ascii'), '50000000000000000000000000000000'); -}); \ No newline at end of file +test("get validator stake test", async (t) => { + const { carl, contextApiContract, root } = t.context.accounts; + let r = await carl.call(contextApiContract, "get_validator_stake", ""); + t.is(r, 0); + r = await root.callRaw(contextApiContract, "get_validator_stake", ""); + t.is( + Buffer.from(r.result.status.SuccessValue, "base64").toString("ascii"), + "50000000000000000000000000000000" + ); + r = await contextApiContract.viewRaw("get_total_stake", ""); + t.is( + Buffer.from(r.result).toString("ascii"), + "50000000000000000000000000000000" + ); +}); diff --git a/tests/__tests__/test_highlevel_promise.ava.js b/tests/__tests__/test_highlevel_promise.ava.js index d732f96ab..fa3501804 100644 --- a/tests/__tests__/test_highlevel_promise.ava.js +++ b/tests/__tests__/test_highlevel_promise.ava.js @@ -1,144 +1,233 @@ -import { Worker } from 'near-workspaces'; -import test from 'ava'; +import { Worker } from "near-workspaces"; +import test from "ava"; +test.before(async (t) => { + // Init the worker and start a Sandbox server + const worker = await Worker.init(); -test.before(async t => { - // Init the worker and start a Sandbox server - const worker = await Worker.init(); + // Prepare sandbox for tests, create accounts, deploy contracts, etx. + const root = worker.rootAccount; - // Prepare sandbox for tests, create accounts, deploy contracts, etx. - const root = worker.rootAccount; + const highlevelPromise = await root.createSubAccount("highlevel-promise", { + initialBalance: "100100N", + }); + await highlevelPromise.deploy("build/highlevel-promise.wasm"); - const highlevelPromise = await root.createSubAccount('highlevel-promise', {initialBalance: '100100N'}); - await highlevelPromise.deploy('build/highlevel-promise.wasm'); + // Create and deploy callee contract + const calleeContract = await root.createSubAccount("callee-contract"); + await calleeContract.deploy("build/promise_api.wasm"); - // Create and deploy callee contract - const calleeContract = await root.createSubAccount('callee-contract'); - await calleeContract.deploy('build/promise_api.wasm'); + // Test users + const ali = await root.createSubAccount("ali"); + const bob = await root.createSubAccount("bob"); - // Test users - const ali = await root.createSubAccount('ali'); - const bob = await root.createSubAccount('bob'); - - // Save state for test runs - t.context.worker = worker; - t.context.accounts = { root, highlevelPromise, ali, bob, calleeContract }; + // Save state for test runs + t.context.worker = worker; + t.context.accounts = { root, highlevelPromise, ali, bob, calleeContract }; }); -test.after.always(async t => { - await t.context.worker.tearDown().catch(error => { - console.log('Failed to tear down the worker:', error); - }); +test.after.always(async (t) => { + await t.context.worker.tearDown().catch((error) => { + console.log("Failed to tear down the worker:", error); + }); }); -test('highlevel promise create account, transfer', async t => { - const { bob, highlevelPromise } = t.context.accounts; - - let r = await bob.callRaw(highlevelPromise, 'test_promise_batch_create_transfer', '', {gas: '100 Tgas'}); - t.is(r.result.receipts_outcome[1].outcome.executor_id, highlevelPromise.getSubAccount('a').accountId); - t.is(r.result.receipts_outcome[1].outcome.status.SuccessValue, ''); - - let balance = await highlevelPromise.getSubAccount('a').balance() - t.is(balance.total.toString(), '10000000000000000000000000') +test("highlevel promise create account, transfer", async (t) => { + const { bob, highlevelPromise } = t.context.accounts; + + let r = await bob.callRaw( + highlevelPromise, + "test_promise_batch_create_transfer", + "", + { gas: "100 Tgas" } + ); + t.is( + r.result.receipts_outcome[1].outcome.executor_id, + highlevelPromise.getSubAccount("a").accountId + ); + t.is(r.result.receipts_outcome[1].outcome.status.SuccessValue, ""); + + let balance = await highlevelPromise.getSubAccount("a").balance(); + t.is(balance.total.toString(), "10000000000000000000000000"); }); -test('highlevel promise stake', async t => { - const { highlevelPromise } = t.context.accounts; - await highlevelPromise.callRaw(highlevelPromise, 'test_promise_batch_stake', '', {gas: '100 Tgas'}); - let balance = await highlevelPromise.balance(); - t.is(balance.staked.toString(), '100000000000000000000000000000'); +test("highlevel promise stake", async (t) => { + const { highlevelPromise } = t.context.accounts; + await highlevelPromise.callRaw( + highlevelPromise, + "test_promise_batch_stake", + "", + { gas: "100 Tgas" } + ); + let balance = await highlevelPromise.balance(); + t.is(balance.staked.toString(), "100000000000000000000000000000"); }); -test('highlevel promise add full access key', async t => { - const { bob, highlevelPromise } = t.context.accounts; - let r = await bob.callRaw(highlevelPromise, 'test_promise_add_full_access_key', '', {gas: '100 Tgas'}); - t.is(r.result.status.SuccessValue, ''); +test("highlevel promise add full access key", async (t) => { + const { bob, highlevelPromise } = t.context.accounts; + let r = await bob.callRaw( + highlevelPromise, + "test_promise_add_full_access_key", + "", + { gas: "100 Tgas" } + ); + t.is(r.result.status.SuccessValue, ""); }); -test('highlevel promise add function call key', async t => { - const { bob, highlevelPromise } = t.context.accounts; - let r = await bob.callRaw(highlevelPromise, 'test_promise_add_function_call_access_key', '', {gas: '100 Tgas'}); - t.is(r.result.status.SuccessValue, ''); +test("highlevel promise add function call key", async (t) => { + const { bob, highlevelPromise } = t.context.accounts; + let r = await bob.callRaw( + highlevelPromise, + "test_promise_add_function_call_access_key", + "", + { gas: "100 Tgas" } + ); + t.is(r.result.status.SuccessValue, ""); }); -test('highlevel promise delete account', async t => { - const { bob, highlevelPromise } = t.context.accounts; - let r = await bob.callRaw(highlevelPromise, 'test_delete_account', '', {gas: '100 Tgas'}); - t.is(r.result.status.SuccessValue, ''); - t.is(await highlevelPromise.getSubAccount('e').exists(), false); +test("highlevel promise delete account", async (t) => { + const { bob, highlevelPromise } = t.context.accounts; + let r = await bob.callRaw(highlevelPromise, "test_delete_account", "", { + gas: "100 Tgas", + }); + t.is(r.result.status.SuccessValue, ""); + t.is(await highlevelPromise.getSubAccount("e").exists(), false); }); -test('highlevel promise then', async t => { - const { ali, highlevelPromise, calleeContract } = t.context.accounts; - let r = await ali.callRaw(highlevelPromise, 'test_promise_then', '', {gas: '70 Tgas'}); - // call the callee - t.is(r.result.receipts_outcome[1].outcome.executor_id, calleeContract.accountId); - t.deepEqual(JSON.parse(Buffer.from(r.result.receipts_outcome[1].outcome.status.SuccessValue, 'base64')), { - currentAccountId: calleeContract.accountId, - signerAccountId: ali.accountId, - predecessorAccountId: highlevelPromise.accountId, - input: 'abc', - }); - - // the callback scheduled by promise_then - t.is(r.result.receipts_outcome[3].outcome.executor_id, highlevelPromise.accountId); - t.deepEqual(JSON.parse(Buffer.from(r.result.receipts_outcome[3].outcome.status.SuccessValue, 'base64')), { - currentAccountId: highlevelPromise.accountId, - signerAccountId: ali.accountId, - predecessorAccountId: highlevelPromise.accountId, - input: '{"callbackArg1":"def"}', - promiseResults: [JSON.stringify({ - currentAccountId: calleeContract.accountId, - signerAccountId: ali.accountId, - predecessorAccountId: highlevelPromise.accountId, - input: 'abc', - })], - callbackArg1: 'def' - }); +test("highlevel promise then", async (t) => { + const { ali, highlevelPromise, calleeContract } = t.context.accounts; + let r = await ali.callRaw(highlevelPromise, "test_promise_then", "", { + gas: "70 Tgas", + }); + // call the callee + t.is( + r.result.receipts_outcome[1].outcome.executor_id, + calleeContract.accountId + ); + t.deepEqual( + JSON.parse( + Buffer.from( + r.result.receipts_outcome[1].outcome.status.SuccessValue, + "base64" + ) + ), + { + currentAccountId: calleeContract.accountId, + signerAccountId: ali.accountId, + predecessorAccountId: highlevelPromise.accountId, + input: "abc", + } + ); + + // the callback scheduled by promise_then + t.is( + r.result.receipts_outcome[3].outcome.executor_id, + highlevelPromise.accountId + ); + t.deepEqual( + JSON.parse( + Buffer.from( + r.result.receipts_outcome[3].outcome.status.SuccessValue, + "base64" + ) + ), + { + currentAccountId: highlevelPromise.accountId, + signerAccountId: ali.accountId, + predecessorAccountId: highlevelPromise.accountId, + input: '{"callbackArg1":"def"}', + promiseResults: [ + JSON.stringify({ + currentAccountId: calleeContract.accountId, + signerAccountId: ali.accountId, + predecessorAccountId: highlevelPromise.accountId, + input: "abc", + }), + ], + callbackArg1: "def", + } + ); }); -test('highlevel promise and', async t => { - const { ali, highlevelPromise, calleeContract } = t.context.accounts; - let r = await ali.callRaw(highlevelPromise, 'test_promise_and', '', {gas: '150 Tgas'}); - - // console.log(JSON.stringify(r, null, 2)) - // promise and schedule to call the callee - t.is(r.result.receipts_outcome[1].outcome.executor_id, calleeContract.accountId); - t.deepEqual(JSON.parse(Buffer.from(r.result.receipts_outcome[1].outcome.status.SuccessValue, 'base64')), { - currentAccountId: calleeContract.accountId, - signerAccountId: ali.accountId, - predecessorAccountId: highlevelPromise.accountId, - input: 'abc', - }); - - // promise and schedule to call the callee, with different args - t.is(r.result.receipts_outcome[3].outcome.executor_id, calleeContract.accountId); - t.deepEqual(JSON.parse(Buffer.from(r.result.receipts_outcome[3].outcome.status.SuccessValue, 'base64')), { - currentAccountId: calleeContract.accountId, - signerAccountId: ali.accountId, - predecessorAccountId: highlevelPromise.accountId, - input: 'def', - }); - - // the callback scheduled by promise_then on the promise created by promise_and - t.is(r.result.receipts_outcome[5].outcome.executor_id, highlevelPromise.accountId); - t.deepEqual(JSON.parse(Buffer.from(r.result.receipts_outcome[5].outcome.status.SuccessValue, 'base64')), { - currentAccountId: highlevelPromise.accountId, - signerAccountId: ali.accountId, - predecessorAccountId: highlevelPromise.accountId, - input: '{"callbackArg1":"ghi"}', - promiseResults: [JSON.stringify({ - currentAccountId: calleeContract.accountId, - signerAccountId: ali.accountId, - predecessorAccountId: highlevelPromise.accountId, - input: 'abc', - }), JSON.stringify({ - currentAccountId: calleeContract.accountId, - signerAccountId: ali.accountId, - predecessorAccountId: highlevelPromise.accountId, - input: 'def', - })], - callbackArg1: 'ghi', - }); +test("highlevel promise and", async (t) => { + const { ali, highlevelPromise, calleeContract } = t.context.accounts; + let r = await ali.callRaw(highlevelPromise, "test_promise_and", "", { + gas: "150 Tgas", + }); + + // console.log(JSON.stringify(r, null, 2)) + // promise and schedule to call the callee + t.is( + r.result.receipts_outcome[1].outcome.executor_id, + calleeContract.accountId + ); + t.deepEqual( + JSON.parse( + Buffer.from( + r.result.receipts_outcome[1].outcome.status.SuccessValue, + "base64" + ) + ), + { + currentAccountId: calleeContract.accountId, + signerAccountId: ali.accountId, + predecessorAccountId: highlevelPromise.accountId, + input: "abc", + } + ); + + // promise and schedule to call the callee, with different args + t.is( + r.result.receipts_outcome[3].outcome.executor_id, + calleeContract.accountId + ); + t.deepEqual( + JSON.parse( + Buffer.from( + r.result.receipts_outcome[3].outcome.status.SuccessValue, + "base64" + ) + ), + { + currentAccountId: calleeContract.accountId, + signerAccountId: ali.accountId, + predecessorAccountId: highlevelPromise.accountId, + input: "def", + } + ); + + // the callback scheduled by promise_then on the promise created by promise_and + t.is( + r.result.receipts_outcome[5].outcome.executor_id, + highlevelPromise.accountId + ); + t.deepEqual( + JSON.parse( + Buffer.from( + r.result.receipts_outcome[5].outcome.status.SuccessValue, + "base64" + ) + ), + { + currentAccountId: highlevelPromise.accountId, + signerAccountId: ali.accountId, + predecessorAccountId: highlevelPromise.accountId, + input: '{"callbackArg1":"ghi"}', + promiseResults: [ + JSON.stringify({ + currentAccountId: calleeContract.accountId, + signerAccountId: ali.accountId, + predecessorAccountId: highlevelPromise.accountId, + input: "abc", + }), + JSON.stringify({ + currentAccountId: calleeContract.accountId, + signerAccountId: ali.accountId, + predecessorAccountId: highlevelPromise.accountId, + input: "def", + }), + ], + callbackArg1: "ghi", + } + ); }); - diff --git a/tests/__tests__/test_log_panic_api.ava.js b/tests/__tests__/test_log_panic_api.ava.js index 14a605847..70e9f9cb8 100644 --- a/tests/__tests__/test_log_panic_api.ava.js +++ b/tests/__tests__/test_log_panic_api.ava.js @@ -1,134 +1,136 @@ -import { Worker } from 'near-workspaces'; -import test from 'ava'; +import { Worker } from "near-workspaces"; +import test from "ava"; +test.before(async (t) => { + // Init the worker and start a Sandbox server + const worker = await Worker.init(); -test.before(async t => { - // Init the worker and start a Sandbox server - const worker = await Worker.init(); + // Prepare sandbox for tests, create accounts, deploy contracts, etx. + const root = worker.rootAccount; - // Prepare sandbox for tests, create accounts, deploy contracts, etx. - const root = worker.rootAccount; + // Deploy the test contract. + const testContract = await root.devDeploy("build/log_panic_api.wasm"); - // Deploy the test contract. - const testContract = await root.devDeploy( - 'build/log_panic_api.wasm', - ); + // Test users + const ali = await root.createSubAccount("ali"); - // Test users - const ali = await root.createSubAccount('ali'); - - // Save state for test runs - t.context.worker = worker; - t.context.accounts = { root, testContract, ali }; + // Save state for test runs + t.context.worker = worker; + t.context.accounts = { root, testContract, ali }; }); -test.after.always(async t => { - await t.context.worker.tearDown().catch(error => { - console.log('Failed to tear down the worker:', error); - }); +test.after.always(async (t) => { + await t.context.worker.tearDown().catch((error) => { + console.log("Failed to tear down the worker:", error); + }); }); - -test('Log expected types work', async t => { - const { ali, testContract } = t.context.accounts; - - let r = await ali.callRaw(testContract, 'log_expected_input_tests', ''); - t.deepEqual( - r.result.receipts_outcome[0].outcome.logs, - [ - "abc", - "水", - "333", - '\x00\x01\xff', - '\xe6\xb0\xb4', - "水", - "水" - ] - ); +test("Log expected types work", async (t) => { + const { ali, testContract } = t.context.accounts; + + let r = await ali.callRaw(testContract, "log_expected_input_tests", ""); + t.deepEqual(r.result.receipts_outcome[0].outcome.logs, [ + "abc", + "水", + "333", + "\x00\x01\xff", + "\xe6\xb0\xb4", + "水", + "水", + ]); }); -test('Log unexpected types not logging', async t => { - const { ali, testContract } = t.context.accounts; - - let r = await ali.callRaw(testContract, 'log_unexpected_input_tests', ''); - // logUtf8 and logUtf16 only works with bytes, trying to log it with string is unexpected and behavior is undefined - // in this specific case, it logs nothing - t.deepEqual( - r.result.receipts_outcome[0].outcome.logs, - [ - "", - "", - ] - ); +test("Log unexpected types not logging", async (t) => { + const { ali, testContract } = t.context.accounts; + + let r = await ali.callRaw(testContract, "log_unexpected_input_tests", ""); + // logUtf8 and logUtf16 only works with bytes, trying to log it with string is unexpected and behavior is undefined + // in this specific case, it logs nothing + t.deepEqual(r.result.receipts_outcome[0].outcome.logs, ["", ""]); }); -test('Log invalid utf-8 sequence panic', async t => { - const { ali, testContract } = t.context.accounts; +test("Log invalid utf-8 sequence panic", async (t) => { + const { ali, testContract } = t.context.accounts; - let r = await ali.callRaw(testContract, 'log_invalid_utf8_sequence_test', ''); - // console.log(JSON.stringify(r, null, 2)) - t.deepEqual( - r.result.receipts_outcome[0].outcome.status.Failure.ActionError.kind.FunctionCallError.ExecutionError, - 'String encoding is bad UTF-8 sequence.' - ); + let r = await ali.callRaw(testContract, "log_invalid_utf8_sequence_test", ""); + // console.log(JSON.stringify(r, null, 2)) + t.deepEqual( + r.result.receipts_outcome[0].outcome.status.Failure.ActionError.kind + .FunctionCallError.ExecutionError, + "String encoding is bad UTF-8 sequence." + ); }); -test('Log invalid utf-16 sequence panic', async t => { - const { ali, testContract } = t.context.accounts; - - let r = await ali.callRaw(testContract, 'log_invalid_utf16_sequence_test', ''); - t.deepEqual( - r.result.receipts_outcome[0].outcome.status.Failure.ActionError.kind.FunctionCallError.ExecutionError, - 'String encoding is bad UTF-16 sequence.' - ); +test("Log invalid utf-16 sequence panic", async (t) => { + const { ali, testContract } = t.context.accounts; + + let r = await ali.callRaw( + testContract, + "log_invalid_utf16_sequence_test", + "" + ); + t.deepEqual( + r.result.receipts_outcome[0].outcome.status.Failure.ActionError.kind + .FunctionCallError.ExecutionError, + "String encoding is bad UTF-16 sequence." + ); }); -test('panic tests', async t => { - const { ali, testContract } = t.context.accounts; - let r = await ali.callRaw(testContract, 'panic_test', ''); - t.assert( - r.result.receipts_outcome[0].outcome.status.Failure.ActionError.kind.FunctionCallError.ExecutionError - .match(/^Smart contract panicked:*/)); - - r = await ali.callRaw(testContract, 'panic_ascii_test', ''); - t.assert( - r.result.receipts_outcome[0].outcome.status.Failure.ActionError.kind.FunctionCallError.ExecutionError - .match(/^Smart contract panicked: abc*/) - ); - - r = await ali.callRaw(testContract, 'panic_js_number', ''); - t.assert( - r.result.receipts_outcome[0].outcome.status.Failure.ActionError.kind.FunctionCallError.ExecutionError - .match(/^Smart contract panicked: 356*/) - ); - - r = await ali.callRaw(testContract, 'panic_js_undefined', ''); - t.assert( - r.result.receipts_outcome[0].outcome.status.Failure.ActionError.kind.FunctionCallError.ExecutionError - .match(/^Smart contract panicked:*/) - ); - - r = await ali.callRaw(testContract, 'panic_js_null', ''); - t.assert( - r.result.receipts_outcome[0].outcome.status.Failure.ActionError.kind.FunctionCallError.ExecutionError - .match(/^Smart contract panicked: null*/) - ); - - r = await ali.callRaw(testContract, 'panic_utf8_test', ''); - t.assert( - r.result.receipts_outcome[0].outcome.status.Failure.ActionError.kind.FunctionCallError.ExecutionError - .match(/Smart contract panicked: 水*/) - ); - - r = await ali.callRaw(testContract, 'panicUtf8_valid_utf8_sequence', ''); - t.deepEqual( - r.result.receipts_outcome[0].outcome.status.Failure.ActionError.kind.FunctionCallError.ExecutionError, - 'Smart contract panicked: 水' - ); - - r = await ali.callRaw(testContract, 'panicUtf8_invalid_utf8_sequence', ''); - t.deepEqual( - r.result.receipts_outcome[0].outcome.status.Failure.ActionError.kind.FunctionCallError.ExecutionError, - 'String encoding is bad UTF-8 sequence.' - ); -}) \ No newline at end of file +test("panic tests", async (t) => { + const { ali, testContract } = t.context.accounts; + let r = await ali.callRaw(testContract, "panic_test", ""); + t.assert( + r.result.receipts_outcome[0].outcome.status.Failure.ActionError.kind.FunctionCallError.ExecutionError.match( + /^Smart contract panicked:*/ + ) + ); + + r = await ali.callRaw(testContract, "panic_ascii_test", ""); + t.assert( + r.result.receipts_outcome[0].outcome.status.Failure.ActionError.kind.FunctionCallError.ExecutionError.match( + /^Smart contract panicked: abc*/ + ) + ); + + r = await ali.callRaw(testContract, "panic_js_number", ""); + t.assert( + r.result.receipts_outcome[0].outcome.status.Failure.ActionError.kind.FunctionCallError.ExecutionError.match( + /^Smart contract panicked: 356*/ + ) + ); + + r = await ali.callRaw(testContract, "panic_js_undefined", ""); + t.assert( + r.result.receipts_outcome[0].outcome.status.Failure.ActionError.kind.FunctionCallError.ExecutionError.match( + /^Smart contract panicked:*/ + ) + ); + + r = await ali.callRaw(testContract, "panic_js_null", ""); + t.assert( + r.result.receipts_outcome[0].outcome.status.Failure.ActionError.kind.FunctionCallError.ExecutionError.match( + /^Smart contract panicked: null*/ + ) + ); + + r = await ali.callRaw(testContract, "panic_utf8_test", ""); + t.assert( + r.result.receipts_outcome[0].outcome.status.Failure.ActionError.kind.FunctionCallError.ExecutionError.match( + /Smart contract panicked: 水*/ + ) + ); + + r = await ali.callRaw(testContract, "panicUtf8_valid_utf8_sequence", ""); + t.deepEqual( + r.result.receipts_outcome[0].outcome.status.Failure.ActionError.kind + .FunctionCallError.ExecutionError, + "Smart contract panicked: 水" + ); + + r = await ali.callRaw(testContract, "panicUtf8_invalid_utf8_sequence", ""); + t.deepEqual( + r.result.receipts_outcome[0].outcome.status.Failure.ActionError.kind + .FunctionCallError.ExecutionError, + "String encoding is bad UTF-8 sequence." + ); +}); diff --git a/tests/__tests__/test_math_api.ava.js b/tests/__tests__/test_math_api.ava.js index 9f2fdaee4..3c287e364 100644 --- a/tests/__tests__/test_math_api.ava.js +++ b/tests/__tests__/test_math_api.ava.js @@ -1,83 +1,97 @@ -import { Worker } from 'near-workspaces'; -import test from 'ava'; +import { Worker } from "near-workspaces"; +import test from "ava"; -test.before(async t => { - // Init the worker and start a Sandbox server - const worker = await Worker.init(); +test.before(async (t) => { + // Init the worker and start a Sandbox server + const worker = await Worker.init(); - // Prepare sandbox for tests, create accounts, deploy contracts, etx. - const root = worker.rootAccount; + // Prepare sandbox for tests, create accounts, deploy contracts, etx. + const root = worker.rootAccount; - // Deploy the test contract. - const mathApiContract = await root.devDeploy( - 'build/math_api.wasm', - ); + // Deploy the test contract. + const mathApiContract = await root.devDeploy("build/math_api.wasm"); - // Test users - const ali = await root.createSubAccount('ali'); + // Test users + const ali = await root.createSubAccount("ali"); - // Save state for test runs - t.context.worker = worker; - t.context.accounts = { root, mathApiContract, ali }; + // Save state for test runs + t.context.worker = worker; + t.context.accounts = { root, mathApiContract, ali }; }); -test.after.always(async t => { - await t.context.worker.tearDown().catch(error => { - console.log('Failed to tear down the worker:', error); - }); +test.after.always(async (t) => { + await t.context.worker.tearDown().catch((error) => { + console.log("Failed to tear down the worker:", error); + }); }); - -test('sha256', async t => { - const { ali, mathApiContract } = t.context.accounts; - let r = await ali.callRaw(mathApiContract, 'test_sha256', ''); - t.deepEqual(Buffer.from(r.result.status.SuccessValue, 'base64'), Buffer.from([ - 18, 176, 115, 156, 45, 100, 241, 132, 180, 134, 77, 42, 105, 111, 199, 127, 118, 112, - 92, 255, 88, 43, 83, 147, 122, 55, 26, 36, 42, 156, 160, 158, - ])); +test("sha256", async (t) => { + const { ali, mathApiContract } = t.context.accounts; + let r = await ali.callRaw(mathApiContract, "test_sha256", ""); + t.deepEqual( + Buffer.from(r.result.status.SuccessValue, "base64"), + Buffer.from([ + 18, 176, 115, 156, 45, 100, 241, 132, 180, 134, 77, 42, 105, 111, 199, + 127, 118, 112, 92, 255, 88, 43, 83, 147, 122, 55, 26, 36, 42, 156, 160, + 158, + ]) + ); }); -test('keccak256', async t => { - const { ali, mathApiContract } = t.context.accounts; - let r = await ali.callRaw(mathApiContract, 'test_keccak256', ''); - t.deepEqual(Buffer.from(r.result.status.SuccessValue, 'base64'), Buffer.from([ - 104, 110, 58, 122, 230, 181, 215, 145, 231, 229, 49, 162, 123, 167, 177, 58, 26, 142, - 129, 173, 7, 37, 9, 26, 233, 115, 64, 102, 61, 85, 10, 159, - ])); +test("keccak256", async (t) => { + const { ali, mathApiContract } = t.context.accounts; + let r = await ali.callRaw(mathApiContract, "test_keccak256", ""); + t.deepEqual( + Buffer.from(r.result.status.SuccessValue, "base64"), + Buffer.from([ + 104, 110, 58, 122, 230, 181, 215, 145, 231, 229, 49, 162, 123, 167, 177, + 58, 26, 142, 129, 173, 7, 37, 9, 26, 233, 115, 64, 102, 61, 85, 10, 159, + ]) + ); }); -test('keccak512', async t => { - const { ali, mathApiContract } = t.context.accounts; - let r = await ali.callRaw(mathApiContract, 'test_keccak512', ''); - t.deepEqual(Buffer.from(r.result.status.SuccessValue, 'base64'), Buffer.from([ - 55, 134, 96, 137, 168, 122, 187, 95, 67, 76, 18, 122, 146, 11, 225, 106, 117, 194, 154, - 157, 48, 160, 90, 146, 104, 209, 118, 126, 222, 230, 200, 125, 48, 73, 197, 236, 123, - 173, 192, 197, 90, 153, 167, 121, 100, 88, 209, 240, 137, 86, 239, 41, 87, 128, 219, - 249, 136, 203, 220, 109, 46, 168, 234, 190 - ])); +test("keccak512", async (t) => { + const { ali, mathApiContract } = t.context.accounts; + let r = await ali.callRaw(mathApiContract, "test_keccak512", ""); + t.deepEqual( + Buffer.from(r.result.status.SuccessValue, "base64"), + Buffer.from([ + 55, 134, 96, 137, 168, 122, 187, 95, 67, 76, 18, 122, 146, 11, 225, 106, + 117, 194, 154, 157, 48, 160, 90, 146, 104, 209, 118, 126, 222, 230, 200, + 125, 48, 73, 197, 236, 123, 173, 192, 197, 90, 153, 167, 121, 100, 88, + 209, 240, 137, 86, 239, 41, 87, 128, 219, 249, 136, 203, 220, 109, 46, + 168, 234, 190, + ]) + ); }); -test('ripemd160', async t => { - const { ali, mathApiContract } = t.context.accounts; - let r = await ali.callRaw(mathApiContract, 'test_ripemd160', ''); - t.deepEqual(Buffer.from(r.result.status.SuccessValue, 'base64'), Buffer.from([ - 21, 102, 156, 115, 232, 3, 58, 215, 35, 84, 129, 30, 143, 86, 212, 104, 70, 97, 14, 225, - ])); +test("ripemd160", async (t) => { + const { ali, mathApiContract } = t.context.accounts; + let r = await ali.callRaw(mathApiContract, "test_ripemd160", ""); + t.deepEqual( + Buffer.from(r.result.status.SuccessValue, "base64"), + Buffer.from([ + 21, 102, 156, 115, 232, 3, 58, 215, 35, 84, 129, 30, 143, 86, 212, 104, + 70, 97, 14, 225, + ]) + ); }); -test('ecrecover', async t => { - const { ali, mathApiContract } = t.context.accounts; - let r = await ali.callRaw(mathApiContract, 'test_ecrecover', ''); - t.deepEqual(Buffer.from(r.result.status.SuccessValue, 'base64'), Buffer.from([ - 227, 45, 244, 40, 101, 233, 113, 53, 172, 251, 101, - 243, 186, 231, 27, 220, 134, 244, 212, 145, 80, 173, - 106, 68, 11, 111, 21, 135, 129, 9, 136, 10, 10, - 43, 38, 103, 247, 231, 37, 206, 234, 112, 198, 115, - 9, 59, 246, 118, 99, 224, 49, 38, 35, 200, 224, - 145, 177, 60, 242, 192, 241, 30, 246, 82 - ])); +test("ecrecover", async (t) => { + const { ali, mathApiContract } = t.context.accounts; + let r = await ali.callRaw(mathApiContract, "test_ecrecover", ""); + t.deepEqual( + Buffer.from(r.result.status.SuccessValue, "base64"), + Buffer.from([ + 227, 45, 244, 40, 101, 233, 113, 53, 172, 251, 101, 243, 186, 231, 27, + 220, 134, 244, 212, 145, 80, 173, 106, 68, 11, 111, 21, 135, 129, 9, 136, + 10, 10, 43, 38, 103, 247, 231, 37, 206, 234, 112, 198, 115, 9, 59, 246, + 118, 99, 224, 49, 38, 35, 200, 224, 145, 177, 60, 242, 192, 241, 30, 246, + 82, + ]) + ); }); // As of Jun 24, 2022, near-sandbox is using 97c0410de519ecaca369aaee26f0ca5eb9e7de06, in which alt_bn256 is still // under nightly protocol feature. As near-sandbox is built without nightly protocol feature, alt_bn256 operations -// cannot be tested yet \ No newline at end of file +// cannot be tested yet diff --git a/tests/__tests__/test_promise_api.ava.js b/tests/__tests__/test_promise_api.ava.js index 3dec7defe..f67d28836 100644 --- a/tests/__tests__/test_promise_api.ava.js +++ b/tests/__tests__/test_promise_api.ava.js @@ -1,190 +1,325 @@ -import { Worker } from 'near-workspaces'; -import test from 'ava'; +import { Worker } from "near-workspaces"; +import test from "ava"; +test.before(async (t) => { + // Init the worker and start a Sandbox server + const worker = await Worker.init(); -test.before(async t => { - // Init the worker and start a Sandbox server - const worker = await Worker.init(); + // Prepare sandbox for tests, create accounts, deploy contracts, etx. + const root = worker.rootAccount; - // Prepare sandbox for tests, create accounts, deploy contracts, etx. - const root = worker.rootAccount; + // Create and deploy caller contract + const callerContract = await root.createSubAccount("caller-contract"); + await callerContract.deploy("build/promise_api.wasm"); - // Create and deploy caller contract - const callerContract = await root.createSubAccount('caller-contract'); - await callerContract.deploy('build/promise_api.wasm'); + // Create and deploy callee contract + const calleeContract = await root.createSubAccount("callee-contract"); + await calleeContract.deploy("build/promise_api.wasm"); - // Create and deploy callee contract - const calleeContract = await root.createSubAccount('callee-contract'); - await calleeContract.deploy('build/promise_api.wasm'); + // Create and deploy caller2 contract + const caller2Contract = await root.createSubAccount("caller2", { + initialBalance: "100100N", + }); + await caller2Contract.deploy("build/promise_batch_api.wasm"); - // Create and deploy caller2 contract - const caller2Contract = await root.createSubAccount('caller2', {initialBalance: '100100N'}); - await caller2Contract.deploy('build/promise_batch_api.wasm'); + // Test users + const ali = await root.createSubAccount("ali"); + const bob = await root.createSubAccount("bob"); - // Test users - const ali = await root.createSubAccount('ali'); - const bob = await root.createSubAccount('bob'); - - // Save state for test runs - t.context.worker = worker; - t.context.accounts = { root, callerContract, calleeContract, ali, bob, caller2Contract }; + // Save state for test runs + t.context.worker = worker; + t.context.accounts = { + root, + callerContract, + calleeContract, + ali, + bob, + caller2Contract, + }; }); -test.after.always(async t => { - await t.context.worker.tearDown().catch(error => { - console.log('Failed to tear down the worker:', error); - }); +test.after.always(async (t) => { + await t.context.worker.tearDown().catch((error) => { + console.log("Failed to tear down the worker:", error); + }); }); -test('promise create', async t => { - const { ali, callerContract, calleeContract } = t.context.accounts; - // default is 30 TGas, sufficient when the callee contract method is trivial - let r = await ali.callRaw(callerContract, 'test_promise_create', '', {gas: '40 Tgas'}); - t.is(r.result.receipts_outcome[1].outcome.executor_id, calleeContract.accountId); - t.deepEqual(Buffer.from(r.result.receipts_outcome[1].outcome.status.SuccessValue, 'base64'), Buffer.from(JSON.stringify({ +test("promise create", async (t) => { + const { ali, callerContract, calleeContract } = t.context.accounts; + // default is 30 TGas, sufficient when the callee contract method is trivial + let r = await ali.callRaw(callerContract, "test_promise_create", "", { + gas: "40 Tgas", + }); + t.is( + r.result.receipts_outcome[1].outcome.executor_id, + calleeContract.accountId + ); + t.deepEqual( + Buffer.from( + r.result.receipts_outcome[1].outcome.status.SuccessValue, + "base64" + ), + Buffer.from( + JSON.stringify({ currentAccountId: calleeContract.accountId, signerAccountId: ali.accountId, predecessorAccountId: callerContract.accountId, - input: 'abc', - }))); + input: "abc", + }) + ) + ); }); -test('promise then', async t => { - const { ali, callerContract, calleeContract } = t.context.accounts; - let r = await ali.callRaw(callerContract, 'test_promise_then', '', {gas: '70 Tgas'}); - // console.log(JSON.stringify(r, null, 2)) - // call the callee - t.is(r.result.receipts_outcome[1].outcome.executor_id, calleeContract.accountId); - t.deepEqual(JSON.parse(Buffer.from(r.result.receipts_outcome[1].outcome.status.SuccessValue, 'base64')), { - currentAccountId: calleeContract.accountId, - signerAccountId: ali.accountId, - predecessorAccountId: callerContract.accountId, - input: 'abc', - }); +test("promise then", async (t) => { + const { ali, callerContract, calleeContract } = t.context.accounts; + let r = await ali.callRaw(callerContract, "test_promise_then", "", { + gas: "70 Tgas", + }); + // console.log(JSON.stringify(r, null, 2)) + // call the callee + t.is( + r.result.receipts_outcome[1].outcome.executor_id, + calleeContract.accountId + ); + t.deepEqual( + JSON.parse( + Buffer.from( + r.result.receipts_outcome[1].outcome.status.SuccessValue, + "base64" + ) + ), + { + currentAccountId: calleeContract.accountId, + signerAccountId: ali.accountId, + predecessorAccountId: callerContract.accountId, + input: "abc", + } + ); - // the callback scheduled by promise_then - t.is(r.result.receipts_outcome[3].outcome.executor_id, callerContract.accountId); - t.deepEqual(JSON.parse(Buffer.from(r.result.receipts_outcome[3].outcome.status.SuccessValue, 'base64')), { - currentAccountId: callerContract.accountId, - signerAccountId: ali.accountId, - predecessorAccountId: callerContract.accountId, - input: 'def', - promiseResults: [JSON.stringify({ - currentAccountId: calleeContract.accountId, - signerAccountId: ali.accountId, - predecessorAccountId: callerContract.accountId, - input: 'abc', - })] - }); + // the callback scheduled by promise_then + t.is( + r.result.receipts_outcome[3].outcome.executor_id, + callerContract.accountId + ); + t.deepEqual( + JSON.parse( + Buffer.from( + r.result.receipts_outcome[3].outcome.status.SuccessValue, + "base64" + ) + ), + { + currentAccountId: callerContract.accountId, + signerAccountId: ali.accountId, + predecessorAccountId: callerContract.accountId, + input: "def", + promiseResults: [ + JSON.stringify({ + currentAccountId: calleeContract.accountId, + signerAccountId: ali.accountId, + predecessorAccountId: callerContract.accountId, + input: "abc", + }), + ], + } + ); }); -test('promise and', async t => { - const { ali, callerContract, calleeContract } = t.context.accounts; - let r = await ali.callRaw(callerContract, 'test_promise_and', '', {gas: '150 Tgas'}); - // console.log(JSON.stringify(r, null, 2)) - // promise and schedule to call the callee - t.is(r.result.receipts_outcome[1].outcome.executor_id, calleeContract.accountId); - t.deepEqual(JSON.parse(Buffer.from(r.result.receipts_outcome[1].outcome.status.SuccessValue, 'base64')), { - currentAccountId: calleeContract.accountId, - signerAccountId: ali.accountId, - predecessorAccountId: callerContract.accountId, - input: 'abc', - }); +test("promise and", async (t) => { + const { ali, callerContract, calleeContract } = t.context.accounts; + let r = await ali.callRaw(callerContract, "test_promise_and", "", { + gas: "150 Tgas", + }); + // console.log(JSON.stringify(r, null, 2)) + // promise and schedule to call the callee + t.is( + r.result.receipts_outcome[1].outcome.executor_id, + calleeContract.accountId + ); + t.deepEqual( + JSON.parse( + Buffer.from( + r.result.receipts_outcome[1].outcome.status.SuccessValue, + "base64" + ) + ), + { + currentAccountId: calleeContract.accountId, + signerAccountId: ali.accountId, + predecessorAccountId: callerContract.accountId, + input: "abc", + } + ); - // promise and schedule to call the callee, with different args - t.is(r.result.receipts_outcome[3].outcome.executor_id, calleeContract.accountId); - t.deepEqual(JSON.parse(Buffer.from(r.result.receipts_outcome[3].outcome.status.SuccessValue, 'base64')), { - currentAccountId: calleeContract.accountId, - signerAccountId: ali.accountId, - predecessorAccountId: callerContract.accountId, - input: 'def', - }); + // promise and schedule to call the callee, with different args + t.is( + r.result.receipts_outcome[3].outcome.executor_id, + calleeContract.accountId + ); + t.deepEqual( + JSON.parse( + Buffer.from( + r.result.receipts_outcome[3].outcome.status.SuccessValue, + "base64" + ) + ), + { + currentAccountId: calleeContract.accountId, + signerAccountId: ali.accountId, + predecessorAccountId: callerContract.accountId, + input: "def", + } + ); - // the callback scheduled by promise_then on the promise created by promise_and - t.is(r.result.receipts_outcome[5].outcome.executor_id, callerContract.accountId); - t.deepEqual(JSON.parse(Buffer.from(r.result.receipts_outcome[5].outcome.status.SuccessValue, 'base64')), { - currentAccountId: callerContract.accountId, - signerAccountId: ali.accountId, - predecessorAccountId: callerContract.accountId, - input: 'ghi', - promiseResults: [JSON.stringify({ - currentAccountId: calleeContract.accountId, - signerAccountId: ali.accountId, - predecessorAccountId: callerContract.accountId, - input: 'abc', - }), JSON.stringify({ - currentAccountId: calleeContract.accountId, - signerAccountId: ali.accountId, - predecessorAccountId: callerContract.accountId, - input: 'def', - })] - }); + // the callback scheduled by promise_then on the promise created by promise_and + t.is( + r.result.receipts_outcome[5].outcome.executor_id, + callerContract.accountId + ); + t.deepEqual( + JSON.parse( + Buffer.from( + r.result.receipts_outcome[5].outcome.status.SuccessValue, + "base64" + ) + ), + { + currentAccountId: callerContract.accountId, + signerAccountId: ali.accountId, + predecessorAccountId: callerContract.accountId, + input: "ghi", + promiseResults: [ + JSON.stringify({ + currentAccountId: calleeContract.accountId, + signerAccountId: ali.accountId, + predecessorAccountId: callerContract.accountId, + input: "abc", + }), + JSON.stringify({ + currentAccountId: calleeContract.accountId, + signerAccountId: ali.accountId, + predecessorAccountId: callerContract.accountId, + input: "def", + }), + ], + } + ); }); -test('promise batch create account, transfer', async t => { - const { bob, caller2Contract } = t.context.accounts; +test("promise batch create account, transfer", async (t) => { + const { bob, caller2Contract } = t.context.accounts; - let r = await bob.callRaw(caller2Contract, 'test_promise_batch_create_transfer', '', {gas: '100 Tgas'}); - t.is(r.result.receipts_outcome[1].outcome.executor_id, caller2Contract.getSubAccount('a').accountId); - t.is(r.result.receipts_outcome[1].outcome.status.SuccessValue, ''); + let r = await bob.callRaw( + caller2Contract, + "test_promise_batch_create_transfer", + "", + { gas: "100 Tgas" } + ); + t.is( + r.result.receipts_outcome[1].outcome.executor_id, + caller2Contract.getSubAccount("a").accountId + ); + t.is(r.result.receipts_outcome[1].outcome.status.SuccessValue, ""); - let balance = await caller2Contract.getSubAccount('a').balance() - t.is(balance.total.toString(), '10000000000000000000000000') + let balance = await caller2Contract.getSubAccount("a").balance(); + t.is(balance.total.toString(), "10000000000000000000000000"); }); -test('promise batch deploy contract and call', async t => { - const { bob, caller2Contract } = t.context.accounts; - - let r = await bob.callRaw(caller2Contract, 'test_promise_batch_deploy_call', '', {gas: '200 Tgas'}); - let deployed = caller2Contract.getSubAccount('b'); - t.deepEqual(JSON.parse(Buffer.from(r.result.status.SuccessValue, 'base64')), { - currentAccountId: deployed.accountId, - signerAccountId: bob.accountId, - predecessorAccountId: caller2Contract.accountId, - input: 'abc', - }); +test("promise batch deploy contract and call", async (t) => { + const { bob, caller2Contract } = t.context.accounts; + + let r = await bob.callRaw( + caller2Contract, + "test_promise_batch_deploy_call", + "", + { gas: "200 Tgas" } + ); + let deployed = caller2Contract.getSubAccount("b"); + t.deepEqual(JSON.parse(Buffer.from(r.result.status.SuccessValue, "base64")), { + currentAccountId: deployed.accountId, + signerAccountId: bob.accountId, + predecessorAccountId: caller2Contract.accountId, + input: "abc", + }); }); -test('promise batch stake', async t => { - const { caller2Contract } = t.context.accounts; - await caller2Contract.callRaw(caller2Contract, 'test_promise_batch_stake', '', {gas: '100 Tgas'}); - let balance = await caller2Contract.balance(); - t.is(balance.staked.toString(), '100000000000000000000000000000'); +test("promise batch stake", async (t) => { + const { caller2Contract } = t.context.accounts; + await caller2Contract.callRaw( + caller2Contract, + "test_promise_batch_stake", + "", + { gas: "100 Tgas" } + ); + let balance = await caller2Contract.balance(); + t.is(balance.staked.toString(), "100000000000000000000000000000"); }); -test('promise batch add full access key', async t => { - const { bob, caller2Contract } = t.context.accounts; - let r = await bob.callRaw(caller2Contract, 'test_promise_add_full_access_key', '', {gas: '100 Tgas'}); - t.is(r.result.status.SuccessValue, ''); +test("promise batch add full access key", async (t) => { + const { bob, caller2Contract } = t.context.accounts; + let r = await bob.callRaw( + caller2Contract, + "test_promise_add_full_access_key", + "", + { gas: "100 Tgas" } + ); + t.is(r.result.status.SuccessValue, ""); }); -test('promise batch add function call key', async t => { - const { bob, caller2Contract } = t.context.accounts; - let r = await bob.callRaw(caller2Contract, 'test_promise_add_function_call_access_key', '', {gas: '100 Tgas'}); - t.is(r.result.status.SuccessValue, ''); +test("promise batch add function call key", async (t) => { + const { bob, caller2Contract } = t.context.accounts; + let r = await bob.callRaw( + caller2Contract, + "test_promise_add_function_call_access_key", + "", + { gas: "100 Tgas" } + ); + t.is(r.result.status.SuccessValue, ""); }); -test('promise delete account', async t => { - const { bob, caller2Contract } = t.context.accounts; - let r = await bob.callRaw(caller2Contract, 'test_delete_account', '', {gas: '100 Tgas'}); - t.is(r.result.status.SuccessValue, ''); - t.is(await caller2Contract.getSubAccount('e').exists(), false); +test("promise delete account", async (t) => { + const { bob, caller2Contract } = t.context.accounts; + let r = await bob.callRaw(caller2Contract, "test_delete_account", "", { + gas: "100 Tgas", + }); + t.is(r.result.status.SuccessValue, ""); + t.is(await caller2Contract.getSubAccount("e").exists(), false); }); -test('promise batch function call weight', async t => { - const { ali, caller2Contract, calleeContract } = t.context.accounts; - let r = await ali.callRaw(caller2Contract, 'test_promise_batch_call_weight', '', {gas: '100 Tgas'}); - t.assert(r.result.status.SuccessValue); +test("promise batch function call weight", async (t) => { + const { ali, caller2Contract, calleeContract } = t.context.accounts; + let r = await ali.callRaw( + caller2Contract, + "test_promise_batch_call_weight", + "", + { gas: "100 Tgas" } + ); + t.assert(r.result.status.SuccessValue); }); -test('promise batch transfer overflow', async t => { - const { bob, caller2Contract } = t.context.accounts; - let r = await bob.callRaw(caller2Contract, 'test_transfer_overflow', '', {gas: '100 Tgas'}); - t.assert(r.result.status.Failure.ActionError.kind.FunctionCallError.ExecutionError.startsWith('Smart contract panicked: Expect Uint128 for amount')); +test("promise batch transfer overflow", async (t) => { + const { bob, caller2Contract } = t.context.accounts; + let r = await bob.callRaw(caller2Contract, "test_transfer_overflow", "", { + gas: "100 Tgas", + }); + t.assert( + r.result.status.Failure.ActionError.kind.FunctionCallError.ExecutionError.startsWith( + "Smart contract panicked: Expect Uint128 for amount" + ) + ); }); -test('promise create gas overflow', async t => { - const { ali, callerContract } = t.context.accounts; - let r = await ali.callRaw(callerContract, 'test_promise_create_gas_overflow', '', {gas: '100 Tgas'}); - t.assert(r.result.status.Failure.ActionError.kind.FunctionCallError.ExecutionError.startsWith('Smart contract panicked: Expect Uint64 for gas')); +test("promise create gas overflow", async (t) => { + const { ali, callerContract } = t.context.accounts; + let r = await ali.callRaw( + callerContract, + "test_promise_create_gas_overflow", + "", + { gas: "100 Tgas" } + ); + t.assert( + r.result.status.Failure.ActionError.kind.FunctionCallError.ExecutionError.startsWith( + "Smart contract panicked: Expect Uint64 for gas" + ) + ); }); diff --git a/tests/__tests__/test_storage_api.ava.js b/tests/__tests__/test_storage_api.ava.js index 88a7d2d4c..c743db25e 100644 --- a/tests/__tests__/test_storage_api.ava.js +++ b/tests/__tests__/test_storage_api.ava.js @@ -1,65 +1,64 @@ -import { Worker } from 'near-workspaces'; -import test from 'ava'; +import { Worker } from "near-workspaces"; +import test from "ava"; -test.beforeEach(async t => { - // Use beforeEach instead of before to start from scratch state for each test - // Init the worker and start a Sandbox server - const worker = await Worker.init(); +test.beforeEach(async (t) => { + // Use beforeEach instead of before to start from scratch state for each test + // Init the worker and start a Sandbox server + const worker = await Worker.init(); - // Prepare sandbox for tests, create accounts, deploy contracts, etx. - const root = worker.rootAccount; + // Prepare sandbox for tests, create accounts, deploy contracts, etx. + const root = worker.rootAccount; - // Deploy the test contract. - const storageApiContract = await root.devDeploy( - 'build/storage_api.wasm', - ); + // Deploy the test contract. + const storageApiContract = await root.devDeploy("build/storage_api.wasm"); - // Test users - const ali = await root.createSubAccount('ali'); + // Test users + const ali = await root.createSubAccount("ali"); - // Save state for test runs - t.context.worker = worker; - t.context.accounts = { root, storageApiContract, ali }; + // Save state for test runs + t.context.worker = worker; + t.context.accounts = { root, storageApiContract, ali }; }); -test.afterEach.always(async t => { - await t.context.worker.tearDown().catch(error => { - console.log('Failed to tear down the worker:', error); - }); +test.afterEach.always(async (t) => { + await t.context.worker.tearDown().catch((error) => { + console.log("Failed to tear down the worker:", error); + }); }); +test("storage read write", async (t) => { + const { ali, storageApiContract } = t.context.accounts; -test('storage read write', async t => { - const { ali, storageApiContract } = t.context.accounts; - - let exist = await ali.call(storageApiContract, 'test_storage_write', ''); - t.is(exist, false); - let r = await storageApiContract.viewRaw('test_storage_read', ''); - t.deepEqual(r.result, [0, 1, 255]); - exist = await ali.call(storageApiContract, 'test_storage_write', ''); - t.is(exist, true); + let exist = await ali.call(storageApiContract, "test_storage_write", ""); + t.is(exist, false); + let r = await storageApiContract.viewRaw("test_storage_read", ""); + t.deepEqual(r.result, [0, 1, 255]); + exist = await ali.call(storageApiContract, "test_storage_write", ""); + t.is(exist, true); }); -test('storage remove', async t => { - const { ali, storageApiContract } = t.context.accounts; - let hasKey = await storageApiContract.view('test_storage_has_key', ''); - t.is(hasKey, false); - let exist = await ali.call(storageApiContract, 'test_storage_remove', ''); - t.is(exist, false); - - await ali.call(storageApiContract, 'test_storage_write', ''); +test("storage remove", async (t) => { + const { ali, storageApiContract } = t.context.accounts; + let hasKey = await storageApiContract.view("test_storage_has_key", ""); + t.is(hasKey, false); + let exist = await ali.call(storageApiContract, "test_storage_remove", ""); + t.is(exist, false); - hasKey = await storageApiContract.view('test_storage_has_key', ''); - t.is(hasKey, true); - exist = await ali.call(storageApiContract, 'test_storage_remove', ''); - t.is(exist, true); -}) + await ali.call(storageApiContract, "test_storage_write", ""); + hasKey = await storageApiContract.view("test_storage_has_key", ""); + t.is(hasKey, true); + exist = await ali.call(storageApiContract, "test_storage_remove", ""); + t.is(exist, true); +}); -test('storage get evicted', async t => { - const { ali, storageApiContract } = t.context.accounts; +test("storage get evicted", async (t) => { + const { ali, storageApiContract } = t.context.accounts; - let r = await ali.callRaw(storageApiContract, 'test_storage_get_evicted', ''); - console.log(JSON.stringify(r,null,2)) - t.deepEqual(Buffer.from(r.result.status.SuccessValue, 'base64'), Buffer.from([0, 1, 255])); -}); \ No newline at end of file + let r = await ali.callRaw(storageApiContract, "test_storage_get_evicted", ""); + console.log(JSON.stringify(r, null, 2)); + t.deepEqual( + Buffer.from(r.result.status.SuccessValue, "base64"), + Buffer.from([0, 1, 255]) + ); +}); diff --git a/tests/__tests__/typescript.ava.js b/tests/__tests__/typescript.ava.js index dbdf5e493..8c42842e4 100644 --- a/tests/__tests__/typescript.ava.js +++ b/tests/__tests__/typescript.ava.js @@ -1,34 +1,31 @@ -import { Worker } from 'near-workspaces'; -import test from 'ava'; +import { Worker } from "near-workspaces"; +import test from "ava"; -test.before(async t => { - // Init the worker and start a Sandbox server - const worker = await Worker.init(); +test.before(async (t) => { + // Init the worker and start a Sandbox server + const worker = await Worker.init(); - // Prepare sandbox for tests, create accounts, deploy contracts, etx. - const root = worker.rootAccount; + // Prepare sandbox for tests, create accounts, deploy contracts, etx. + const root = worker.rootAccount; - // Deploy the test contract. - const typescriptContract = await root.devDeploy( - 'build/typescript.wasm', - ); - // Test users - const ali = await root.createSubAccount('ali'); + // Deploy the test contract. + const typescriptContract = await root.devDeploy("build/typescript.wasm"); + // Test users + const ali = await root.createSubAccount("ali"); - // Save state for test runs - t.context.worker = worker; - t.context.accounts = { root, typescriptContract, ali }; + // Save state for test runs + t.context.worker = worker; + t.context.accounts = { root, typescriptContract, ali }; }); -test.after.always(async t => { - await t.context.worker.tearDown().catch(error => { - console.log('Failed to tear down the worker:', error); - }); +test.after.always(async (t) => { + await t.context.worker.tearDown().catch((error) => { + console.log("Failed to tear down the worker:", error); + }); }); - -test('bigint', async t => { - const { typescriptContract } = t.context.accounts; - let r = await typescriptContract.view('bigint', ''); - t.is(r, "3"); +test("bigint", async (t) => { + const { typescriptContract } = t.context.accounts; + let r = await typescriptContract.view("bigint", ""); + t.is(r, "3"); }); diff --git a/tests/__tests__/unordered-map.ava.js b/tests/__tests__/unordered-map.ava.js index c3e532ef1..462bfd65f 100644 --- a/tests/__tests__/unordered-map.ava.js +++ b/tests/__tests__/unordered-map.ava.js @@ -1,178 +1,152 @@ -import { Worker } from 'near-workspaces'; -import test from 'ava'; - -test.beforeEach(async t => { - // Init the worker and start a Sandbox server - const worker = await Worker.init(); - - // Prepare sandbox for tests, create accounts, deploy contracts, etx. - const root = worker.rootAccount; - - // Deploy the test contract. - const unorderedMapContract = await root.devDeploy( - 'build/unordered-map.wasm', - ); - // Test users - const ali = await root.createSubAccount('ali'); - const bob = await root.createSubAccount('bob'); - const carl = await root.createSubAccount('carl'); - - // Save state for test runs - t.context.worker = worker; - t.context.accounts = { root, unorderedMapContract, ali, bob, carl }; +import { Worker } from "near-workspaces"; +import test from "ava"; + +test.beforeEach(async (t) => { + // Init the worker and start a Sandbox server + const worker = await Worker.init(); + + // Prepare sandbox for tests, create accounts, deploy contracts, etx. + const root = worker.rootAccount; + + // Deploy the test contract. + const unorderedMapContract = await root.devDeploy("build/unordered-map.wasm"); + // Test users + const ali = await root.createSubAccount("ali"); + const bob = await root.createSubAccount("bob"); + const carl = await root.createSubAccount("carl"); + + // Save state for test runs + t.context.worker = worker; + t.context.accounts = { root, unorderedMapContract, ali, bob, carl }; }); -test.afterEach.always(async t => { - await t.context.worker.tearDown().catch(error => { - console.log('Failed to tear down the worker:', error); - }); +test.afterEach.always(async (t) => { + await t.context.worker.tearDown().catch((error) => { + console.log("Failed to tear down the worker:", error); + }); }); -test('UnorderedMap is empty by default', async t => { - const { root, unorderedMapContract } = t.context.accounts; - const result = await unorderedMapContract.view('len', {}); - t.is(result, 0); +test("UnorderedMap is empty by default", async (t) => { + const { root, unorderedMapContract } = t.context.accounts; + const result = await unorderedMapContract.view("len", {}); + t.is(result, 0); }); -test('UnorderedMap set() get()', async t => { - const { ali, unorderedMapContract } = t.context.accounts; - t.is( - await unorderedMapContract.view('get', { key: 'hello' }), - null - ); +test("UnorderedMap set() get()", async (t) => { + const { ali, unorderedMapContract } = t.context.accounts; + t.is(await unorderedMapContract.view("get", { key: "hello" }), null); - await ali.call(unorderedMapContract, 'set', { key: 'hello', value: 'world' }); + await ali.call(unorderedMapContract, "set", { key: "hello", value: "world" }); - t.is( - await unorderedMapContract.view('get', { key: 'hello' }), - 'world' - ); + t.is(await unorderedMapContract.view("get", { key: "hello" }), "world"); }); +test("UnorderedMap insert, update, len and iterate", async (t) => { + const { ali, unorderedMapContract } = t.context.accounts; + + t.is(await unorderedMapContract.view("len", {}), 0); + t.deepEqual(await unorderedMapContract.view("toArray", {}), []); + + await ali.call(unorderedMapContract, "set", { key: "hello", value: "world" }); + await ali.call(unorderedMapContract, "set", { + key: "hello1", + value: "world0", + }); + t.is(await unorderedMapContract.view("len", {}), 2); + + // update a value, len shouldn't change + await ali.call(unorderedMapContract, "set", { + key: "hello1", + value: "world1", + }); + t.is(await unorderedMapContract.view("len", {}), 2); + // update should have effect + t.is(await unorderedMapContract.view("get", { key: "hello1" }), "world1"); + + await ali.call(unorderedMapContract, "set", { + key: "hello2", + value: "world2", + }); + t.is(await unorderedMapContract.view("len", {}), 3); + + // Try to set a key with same value, len shouldn't change + await ali.call(unorderedMapContract, "set", { + key: "hello2", + value: "world2", + }); + t.is(await unorderedMapContract.view("len", {}), 3); + + t.deepEqual(await unorderedMapContract.view("toArray", {}), [ + ["hello", "world"], + ["hello1", "world1"], + ["hello2", "world2"], + ]); +}); -test('UnorderedMap insert, update, len and iterate', async t => { - const { ali, unorderedMapContract } = t.context.accounts; - - t.is( - await unorderedMapContract.view('len', {}), - 0 - ); - t.deepEqual( - await unorderedMapContract.view('toArray', {}), - [] - ); - - await ali.call(unorderedMapContract, 'set', { key: 'hello', value: 'world' }); - await ali.call(unorderedMapContract, 'set', { key: 'hello1', value: 'world0' }); - t.is( - await unorderedMapContract.view('len', {}), - 2 - ); - - // update a value, len shouldn't change - await ali.call(unorderedMapContract, 'set', { key: 'hello1', value: 'world1' }); - t.is( - await unorderedMapContract.view('len', {}), - 2 - ); - // update should have effect - t.is( - await unorderedMapContract.view('get', { key: 'hello1' }), - 'world1' - ); - - await ali.call(unorderedMapContract, 'set', { key: 'hello2', value: 'world2' }); - t.is( - await unorderedMapContract.view('len', {}), - 3 - ); - - // Try to set a key with same value, len shouldn't change - await ali.call(unorderedMapContract, 'set', { key: 'hello2', value: 'world2' }); - t.is( - await unorderedMapContract.view('len', {}), - 3 - ); - - t.deepEqual( - await unorderedMapContract.view('toArray', {}), - [['hello', 'world'], ['hello1', 'world1'], ['hello2', 'world2']] - ); +test("UnorderedMap extend, remove, clear", async (t) => { + const { ali, unorderedMapContract } = t.context.accounts; + + await ali.call(unorderedMapContract, "extend", { + kvs: [ + ["hello", "world"], + ["hello1", "world1"], + ["hello2", "world2"], + ], + }); + + t.deepEqual(await unorderedMapContract.view("toArray", {}), [ + ["hello", "world"], + ["hello1", "world1"], + ["hello2", "world2"], + ]); + + // remove non existing element should not error + await ali.call(unorderedMapContract, "remove_key", { key: "hello3" }); + t.deepEqual(await unorderedMapContract.view("toArray", {}), [ + ["hello", "world"], + ["hello1", "world1"], + ["hello2", "world2"], + ]); + + // remove not the last one should work + await ali.call(unorderedMapContract, "remove_key", { key: "hello" }); + t.deepEqual(await unorderedMapContract.view("toArray", {}), [ + ["hello2", "world2"], + ["hello1", "world1"], + ]); + + // remove the last one should work + await ali.call(unorderedMapContract, "remove_key", { key: "hello1" }); + t.deepEqual(await unorderedMapContract.view("toArray", {}), [ + ["hello2", "world2"], + ]); + + // remove when length is 1 should work + t.is(await unorderedMapContract.view("len", {}), 1); + t.is(await unorderedMapContract.view("isEmpty", {}), false); + await ali.call(unorderedMapContract, "remove_key", { key: "hello2" }); + t.deepEqual(await unorderedMapContract.view("toArray", {}), []); + t.is(await unorderedMapContract.view("isEmpty", {}), true); + + await ali.call(unorderedMapContract, "extend", { + kvs: [ + ["hello", "world"], + ["hello1", "world1"], + ["hello2", "world2"], + ], + }); + t.is(await unorderedMapContract.view("isEmpty", {}), false); + await ali.call(unorderedMapContract, "clear", {}); + + t.deepEqual(await unorderedMapContract.view("toArray", {}), []); + t.is(await unorderedMapContract.view("isEmpty", {}), true); }); -test('UnorderedMap extend, remove, clear', async t => { - const { ali, unorderedMapContract } = t.context.accounts; - - await ali.call(unorderedMapContract, 'extend', { kvs: [['hello', 'world'], ['hello1', 'world1'], ['hello2', 'world2']] }); - - t.deepEqual( - await unorderedMapContract.view('toArray', {}), - [['hello', 'world'], ['hello1', 'world1'], ['hello2', 'world2']] - ); - - // remove non existing element should not error - await ali.call(unorderedMapContract, 'remove_key', { key: 'hello3' }); - t.deepEqual( - await unorderedMapContract.view('toArray', {}), - [['hello', 'world'], ['hello1', 'world1'], ['hello2', 'world2']] - ); - - // remove not the last one should work - await ali.call(unorderedMapContract, 'remove_key', { key: 'hello' }); - t.deepEqual( - await unorderedMapContract.view('toArray', {}), - [['hello2', 'world2'], ['hello1', 'world1']] - ); - - // remove the last one should work - await ali.call(unorderedMapContract, 'remove_key', { key: 'hello1' }); - t.deepEqual( - await unorderedMapContract.view('toArray', {}), - [['hello2', 'world2']] - ); - - // remove when length is 1 should work - t.is( - await unorderedMapContract.view('len', {}), - 1 - ); - t.is( - await unorderedMapContract.view('isEmpty', {}), - false - ); - await ali.call(unorderedMapContract, 'remove_key', { key: 'hello2' }); - t.deepEqual( - await unorderedMapContract.view('toArray', {}), - [] - ); - t.is( - await unorderedMapContract.view('isEmpty', {}), - true - ); - - await ali.call(unorderedMapContract, 'extend', { kvs: [['hello', 'world'], ['hello1', 'world1'], ['hello2', 'world2']] }); - t.is( - await unorderedMapContract.view('isEmpty', {}), - false - ); - await ali.call(unorderedMapContract, 'clear', {}); - - t.deepEqual( - await unorderedMapContract.view('toArray', {}), - [] - ); - t.is( - await unorderedMapContract.view('isEmpty', {}), - true - ); -}) - -test('UnorderedMap set get object', async t => { - const { ali, unorderedMapContract } = t.context.accounts; - await ali.call(unorderedMapContract, 'add_house', {}); - t.is( - await unorderedMapContract.view('get_house', {}), - 'house house1 has 2 rooms. room room1 is 200sqft.' - ) - -}) \ No newline at end of file +test("UnorderedMap set get object", async (t) => { + const { ali, unorderedMapContract } = t.context.accounts; + await ali.call(unorderedMapContract, "add_house", {}); + t.is( + await unorderedMapContract.view("get_house", {}), + "house house1 has 2 rooms. room room1 is 200sqft." + ); +}); diff --git a/tests/__tests__/unordered-set.ava.js b/tests/__tests__/unordered-set.ava.js index a42fae7d7..89a341777 100644 --- a/tests/__tests__/unordered-set.ava.js +++ b/tests/__tests__/unordered-set.ava.js @@ -1,177 +1,130 @@ -import { Worker } from 'near-workspaces'; -import test from 'ava'; +import { Worker } from "near-workspaces"; +import test from "ava"; -test.beforeEach(async t => { - // Init the worker and start a Sandbox server - const worker = await Worker.init(); +test.beforeEach(async (t) => { + // Init the worker and start a Sandbox server + const worker = await Worker.init(); - // Prepare sandbox for tests, create accounts, deploy contracts, etx. - const root = worker.rootAccount; + // Prepare sandbox for tests, create accounts, deploy contracts, etx. + const root = worker.rootAccount; - // Deploy the test contract. - const unorderedSetContract = await root.devDeploy( - 'build/unordered-set.wasm', - ); + // Deploy the test contract. + const unorderedSetContract = await root.devDeploy("build/unordered-set.wasm"); - // Test users - const ali = await root.createSubAccount('ali'); - const bob = await root.createSubAccount('bob'); - const carl = await root.createSubAccount('carl'); + // Test users + const ali = await root.createSubAccount("ali"); + const bob = await root.createSubAccount("bob"); + const carl = await root.createSubAccount("carl"); - // Save state for test runs - t.context.worker = worker; - t.context.accounts = { root, unorderedSetContract, ali, bob, carl }; + // Save state for test runs + t.context.worker = worker; + t.context.accounts = { root, unorderedSetContract, ali, bob, carl }; }); -test.afterEach.always(async t => { - await t.context.worker.tearDown().catch(error => { - console.log('Failed to tear down the worker:', error); - }); +test.afterEach.always(async (t) => { + await t.context.worker.tearDown().catch((error) => { + console.log("Failed to tear down the worker:", error); + }); }); -test('UnorderedSet is empty by default', async t => { - const { root, unorderedSetContract } = t.context.accounts; - const result = await unorderedSetContract.view('len', {}); - t.is(result, 0); - t.is( - await unorderedSetContract.view('isEmpty', {}), - true - ); +test("UnorderedSet is empty by default", async (t) => { + const { root, unorderedSetContract } = t.context.accounts; + const result = await unorderedSetContract.view("len", {}); + t.is(result, 0); + t.is(await unorderedSetContract.view("isEmpty", {}), true); }); -test('UnorderedSet set() contains()', async t => { - const { ali, unorderedSetContract } = t.context.accounts; - t.is( - await unorderedSetContract.view('contains', { element: 'hello' }), - false - ); +test("UnorderedSet set() contains()", async (t) => { + const { ali, unorderedSetContract } = t.context.accounts; + t.is( + await unorderedSetContract.view("contains", { element: "hello" }), + false + ); - await ali.call(unorderedSetContract, 'set', { element: 'hello' }); + await ali.call(unorderedSetContract, "set", { element: "hello" }); - t.is( - await unorderedSetContract.view('contains', { element: 'hello' }), - true - ); + t.is(await unorderedSetContract.view("contains", { element: "hello" }), true); }); +test("UnorderedSet insert, len and iterate", async (t) => { + const { ali, unorderedSetContract } = t.context.accounts; -test('UnorderedSet insert, len and iterate', async t => { - const { ali, unorderedSetContract } = t.context.accounts; - - t.is( - await unorderedSetContract.view('len', {}), - 0 - ); - t.deepEqual( - await unorderedSetContract.view('toArray', {}), - [] - ); - - await ali.call(unorderedSetContract, 'set', { element: 'hello' }); - t.is( - await unorderedSetContract.view('len', {}), - 1 - ); - await ali.call(unorderedSetContract, 'set', { element: 'hello1' }); - t.is( - await unorderedSetContract.view('len', {}), - 2 - ); - - // insert the same value, len shouldn't change - await ali.call(unorderedSetContract, 'set', { element: 'hello1' }); - t.is( - await unorderedSetContract.view('len', {}), - 2 - ); - - t.deepEqual( - await unorderedSetContract.view('toArray', {}), - ['hello', 'hello1'] - ); + t.is(await unorderedSetContract.view("len", {}), 0); + t.deepEqual(await unorderedSetContract.view("toArray", {}), []); + + await ali.call(unorderedSetContract, "set", { element: "hello" }); + t.is(await unorderedSetContract.view("len", {}), 1); + await ali.call(unorderedSetContract, "set", { element: "hello1" }); + t.is(await unorderedSetContract.view("len", {}), 2); + + // insert the same value, len shouldn't change + await ali.call(unorderedSetContract, "set", { element: "hello1" }); + t.is(await unorderedSetContract.view("len", {}), 2); + + t.deepEqual(await unorderedSetContract.view("toArray", {}), [ + "hello", + "hello1", + ]); }); -test('UnorderedSet extend, remove, clear', async t => { - const { ali, unorderedSetContract } = t.context.accounts; - - await ali.callRaw(unorderedSetContract, 'extend', { elements: ['hello', 'world', 'hello1'] }); - - t.deepEqual( - await unorderedSetContract.view('toArray', {}), - ['hello', 'world', 'hello1'] - ); - - // remove non existing element should not error - await ali.call(unorderedSetContract, 'remove_key', { element: 'hello3' }); - t.deepEqual( - await unorderedSetContract.view('toArray', {}), - ['hello', 'world', 'hello1'] - ); - - // remove not the last one should work - await ali.call(unorderedSetContract, 'remove_key', { element: 'hello' }); - t.deepEqual( - await unorderedSetContract.view('toArray', {}), - ['hello1', 'world'] - ); - - // remove the last one should work - await ali.call(unorderedSetContract, 'remove_key', { element: 'world' }); - t.deepEqual( - await unorderedSetContract.view('toArray', {}), - ['hello1'] - ); - - // remove when length is 1 should work - t.is( - await unorderedSetContract.view('len', {}), - 1 - ); - t.is( - await unorderedSetContract.view('isEmpty', {}), - false - ); - await ali.call(unorderedSetContract, 'remove_key', { element: 'hello1' }); - t.deepEqual( - await unorderedSetContract.view('toArray', {}), - [] - ); - t.is( - await unorderedSetContract.view('isEmpty', {}), - true - ); - - await ali.call(unorderedSetContract, 'extend', { elements: ['hello', 'world', 'hello1'] }); - t.deepEqual( - await unorderedSetContract.view('toArray', {}), - ['hello', 'world', 'hello1'] - ); - t.is( - await unorderedSetContract.view('isEmpty', {}), - false - ); - // clear should work - await ali.call(unorderedSetContract, 'clear', {}); - t.deepEqual( - await unorderedSetContract.view('toArray', {}), - [] - ); - t.is( - await unorderedSetContract.view('isEmpty', {}), - true - ); -}) - -test('Add and check exist of object', async t => { - const { ali, unorderedSetContract } = t.context.accounts; - let houseSpec = {name: "a", rooms: [{name: "bedroom", size: "300sqft"}]} - t.is( - await unorderedSetContract.view('house_exist', houseSpec), - false - ); - await ali.call(unorderedSetContract, 'add_house', houseSpec); - t.is( - await unorderedSetContract.view('house_exist', houseSpec), - true - ); -}) \ No newline at end of file +test("UnorderedSet extend, remove, clear", async (t) => { + const { ali, unorderedSetContract } = t.context.accounts; + + await ali.callRaw(unorderedSetContract, "extend", { + elements: ["hello", "world", "hello1"], + }); + + t.deepEqual(await unorderedSetContract.view("toArray", {}), [ + "hello", + "world", + "hello1", + ]); + + // remove non existing element should not error + await ali.call(unorderedSetContract, "remove_key", { element: "hello3" }); + t.deepEqual(await unorderedSetContract.view("toArray", {}), [ + "hello", + "world", + "hello1", + ]); + + // remove not the last one should work + await ali.call(unorderedSetContract, "remove_key", { element: "hello" }); + t.deepEqual(await unorderedSetContract.view("toArray", {}), [ + "hello1", + "world", + ]); + + // remove the last one should work + await ali.call(unorderedSetContract, "remove_key", { element: "world" }); + t.deepEqual(await unorderedSetContract.view("toArray", {}), ["hello1"]); + + // remove when length is 1 should work + t.is(await unorderedSetContract.view("len", {}), 1); + t.is(await unorderedSetContract.view("isEmpty", {}), false); + await ali.call(unorderedSetContract, "remove_key", { element: "hello1" }); + t.deepEqual(await unorderedSetContract.view("toArray", {}), []); + t.is(await unorderedSetContract.view("isEmpty", {}), true); + + await ali.call(unorderedSetContract, "extend", { + elements: ["hello", "world", "hello1"], + }); + t.deepEqual(await unorderedSetContract.view("toArray", {}), [ + "hello", + "world", + "hello1", + ]); + t.is(await unorderedSetContract.view("isEmpty", {}), false); + // clear should work + await ali.call(unorderedSetContract, "clear", {}); + t.deepEqual(await unorderedSetContract.view("toArray", {}), []); + t.is(await unorderedSetContract.view("isEmpty", {}), true); +}); + +test("Add and check exist of object", async (t) => { + const { ali, unorderedSetContract } = t.context.accounts; + let houseSpec = { name: "a", rooms: [{ name: "bedroom", size: "300sqft" }] }; + t.is(await unorderedSetContract.view("house_exist", houseSpec), false); + await ali.call(unorderedSetContract, "add_house", houseSpec); + t.is(await unorderedSetContract.view("house_exist", houseSpec), true); +}); diff --git a/tests/__tests__/vector.ava.js b/tests/__tests__/vector.ava.js index d805c97ba..15fe4e2c2 100644 --- a/tests/__tests__/vector.ava.js +++ b/tests/__tests__/vector.ava.js @@ -1,165 +1,118 @@ -import { Worker } from 'near-workspaces'; -import test from 'ava'; +import { Worker } from "near-workspaces"; +import test from "ava"; -test.beforeEach(async t => { - // Init the worker and start a Sandbox server - const worker = await Worker.init(); +test.beforeEach(async (t) => { + // Init the worker and start a Sandbox server + const worker = await Worker.init(); - // Prepare sandbox for tests, create accounts, deploy contracts, etx. - const root = worker.rootAccount; + // Prepare sandbox for tests, create accounts, deploy contracts, etx. + const root = worker.rootAccount; - // Deploy the test contract. - const vectorContract = await root.devDeploy( - 'build/vector.wasm', - ); + // Deploy the test contract. + const vectorContract = await root.devDeploy("build/vector.wasm"); - // Test users - const ali = await root.createSubAccount('ali'); - const bob = await root.createSubAccount('bob'); - const carl = await root.createSubAccount('carl'); + // Test users + const ali = await root.createSubAccount("ali"); + const bob = await root.createSubAccount("bob"); + const carl = await root.createSubAccount("carl"); - // Save state for test runs - t.context.worker = worker; - t.context.accounts = { root, vectorContract, ali, bob, carl }; + // Save state for test runs + t.context.worker = worker; + t.context.accounts = { root, vectorContract, ali, bob, carl }; }); -test.afterEach.always(async t => { - await t.context.worker.tearDown().catch(error => { - console.log('Failed to tear down the worker:', error); - }); +test.afterEach.always(async (t) => { + await t.context.worker.tearDown().catch((error) => { + console.log("Failed to tear down the worker:", error); + }); }); -test('Vector is empty by default', async t => { - const { root, vectorContract } = t.context.accounts; - let result = await vectorContract.view('len', {}); - t.is(result, 0); - t.is( - await vectorContract.view('isEmpty', {}), - true - ); +test("Vector is empty by default", async (t) => { + const { root, vectorContract } = t.context.accounts; + let result = await vectorContract.view("len", {}); + t.is(result, 0); + t.is(await vectorContract.view("isEmpty", {}), true); }); -test('Vector push, get, pop, replace', async t => { - const { ali, vectorContract } = t.context.accounts; - await ali.call(vectorContract, 'push', { value: 'hello' }); - await ali.call(vectorContract, 'push', { value: 'world' }); - await ali.call(vectorContract, 'push', { value: 'aaa' }); - let result = await vectorContract.view('len', {}); - t.is(result, 3); - t.is( - await vectorContract.view('get', { index: 0 }), - 'hello' - ); - t.is( - await vectorContract.view('get', { index: 2 }), - 'aaa' - ); - t.is( - await vectorContract.view('get', { index: 3 }), - null - ); - - await ali.call(vectorContract, 'pop', {}); - result = await vectorContract.view('len', {}), - t.is(result, 2); - t.is( - await vectorContract.view('get', { index: 2 }), - null - ); - t.is( - await vectorContract.view('get', { index: 1 }), - 'world' - ); - await ali.call(vectorContract, 'replace', { index: 1, value: 'aaa' }); - t.is( - await vectorContract.view('get', { index: 1 }), - 'aaa' - ); +test("Vector push, get, pop, replace", async (t) => { + const { ali, vectorContract } = t.context.accounts; + await ali.call(vectorContract, "push", { value: "hello" }); + await ali.call(vectorContract, "push", { value: "world" }); + await ali.call(vectorContract, "push", { value: "aaa" }); + let result = await vectorContract.view("len", {}); + t.is(result, 3); + t.is(await vectorContract.view("get", { index: 0 }), "hello"); + t.is(await vectorContract.view("get", { index: 2 }), "aaa"); + t.is(await vectorContract.view("get", { index: 3 }), null); + + await ali.call(vectorContract, "pop", {}); + (result = await vectorContract.view("len", {})), t.is(result, 2); + t.is(await vectorContract.view("get", { index: 2 }), null); + t.is(await vectorContract.view("get", { index: 1 }), "world"); + await ali.call(vectorContract, "replace", { index: 1, value: "aaa" }); + t.is(await vectorContract.view("get", { index: 1 }), "aaa"); }); -test('Vector extend, toArray, swapRemove, clear', async t => { - const { ali, vectorContract } = t.context.accounts; - - await ali.call(vectorContract, 'extend', { kvs: ['hello', 'world', 'aaa'] }); - - t.deepEqual( - await vectorContract.view('toArray', {}), - ['hello', 'world', 'aaa'] - ); - - // swapRemove non existing element should error - const error1 = await t.throwsAsync(() => ali.call(vectorContract, 'swapRemove', { index: 3 })); - t.assert(error1.message.includes(`Index out of bounds`)); - t.deepEqual( - await vectorContract.view('toArray', {}), - ['hello', 'world', 'aaa'] - ); - - // swapRemove not the last one should work - await ali.call(vectorContract, 'swapRemove', { index: 0 }); - t.deepEqual( - await vectorContract.view('toArray', {}), - ['aaa', 'world'] - ); - - // swapRemove the last one should work - await ali.call(vectorContract, 'swapRemove', { index: 1 }); - t.deepEqual( - await vectorContract.view('toArray', {}), - ['aaa'] - ); - - // swapRemove when length is 1 should work - t.is( - await vectorContract.view('len', {}), - 1 - ); - t.is( - await vectorContract.view('isEmpty', {}), - false - ); - await ali.call(vectorContract, 'swapRemove', { index: 0 }); - t.deepEqual( - await vectorContract.view('toArray', {}), - [] - ); - t.is( - await vectorContract.view('isEmpty', {}), - true - ); - - await ali.call(vectorContract, 'extend', { kvs: ['hello', 'world', 'aaa'] }); - t.is( - await vectorContract.view('isEmpty', {}), - false - ); - await ali.call(vectorContract, 'clear', {}); - - t.deepEqual( - await vectorContract.view('toArray', {}), - [] - ); - t.is( - await vectorContract.view('isEmpty', {}), - true - ); -}) - -test('Vector add and get object', async t => { - const { ali, vectorContract } = t.context.accounts; - await ali.call(vectorContract, 'add_house', {}); - let result = await vectorContract.view('get_house', {}); - t.deepEqual(result, { - name: 'house1', - rooms: [ - { - name: 'room1', - size: '200sqft', - }, - { - name: 'room2', - size: '300sqft', - }, - ], - }) +test("Vector extend, toArray, swapRemove, clear", async (t) => { + const { ali, vectorContract } = t.context.accounts; + + await ali.call(vectorContract, "extend", { kvs: ["hello", "world", "aaa"] }); + + t.deepEqual(await vectorContract.view("toArray", {}), [ + "hello", + "world", + "aaa", + ]); + + // swapRemove non existing element should error + const error1 = await t.throwsAsync(() => + ali.call(vectorContract, "swapRemove", { index: 3 }) + ); + t.assert(error1.message.includes(`Index out of bounds`)); + t.deepEqual(await vectorContract.view("toArray", {}), [ + "hello", + "world", + "aaa", + ]); + + // swapRemove not the last one should work + await ali.call(vectorContract, "swapRemove", { index: 0 }); + t.deepEqual(await vectorContract.view("toArray", {}), ["aaa", "world"]); + + // swapRemove the last one should work + await ali.call(vectorContract, "swapRemove", { index: 1 }); + t.deepEqual(await vectorContract.view("toArray", {}), ["aaa"]); + + // swapRemove when length is 1 should work + t.is(await vectorContract.view("len", {}), 1); + t.is(await vectorContract.view("isEmpty", {}), false); + await ali.call(vectorContract, "swapRemove", { index: 0 }); + t.deepEqual(await vectorContract.view("toArray", {}), []); + t.is(await vectorContract.view("isEmpty", {}), true); + + await ali.call(vectorContract, "extend", { kvs: ["hello", "world", "aaa"] }); + t.is(await vectorContract.view("isEmpty", {}), false); + await ali.call(vectorContract, "clear", {}); + + t.deepEqual(await vectorContract.view("toArray", {}), []); + t.is(await vectorContract.view("isEmpty", {}), true); +}); + +test("Vector add and get object", async (t) => { + const { ali, vectorContract } = t.context.accounts; + await ali.call(vectorContract, "add_house", {}); + let result = await vectorContract.view("get_house", {}); + t.deepEqual(result, { + name: "house1", + rooms: [ + { + name: "room1", + size: "200sqft", + }, + { + name: "room2", + size: "300sqft", + }, + ], + }); }); diff --git a/tests/ava.config.cjs b/tests/ava.config.cjs index a100daf68..d5a8c029f 100644 --- a/tests/ava.config.cjs +++ b/tests/ava.config.cjs @@ -1,8 +1,8 @@ -require('util').inspect.defaultOptions.depth = 5; // Increase AVA's printing depth +require("util").inspect.defaultOptions.depth = 5; // Increase AVA's printing depth module.exports = { - timeout: '300000', - files: ['**/*.ava.js'], + timeout: "300000", + files: ["**/*.ava.js"], failWithoutAssertions: false, - extensions: ['js'], + extensions: ["js"], }; diff --git a/tests/babel.config.json b/tests/babel.config.json index d01c909c1..e1d155602 100644 --- a/tests/babel.config.json +++ b/tests/babel.config.json @@ -2,7 +2,7 @@ "plugins": [ "near-sdk-js/lib/build-tools/include-bytes", "near-sdk-js/lib/build-tools/near-bindgen-exporter", - ["@babel/plugin-proposal-decorators", {"version": "legacy"}] + ["@babel/plugin-proposal-decorators", { "version": "legacy" }] ], "presets": ["@babel/preset-typescript"] } diff --git a/tests/jsconfig.json b/tests/jsconfig.json index e4e17cc70..a6d618635 100644 --- a/tests/jsconfig.json +++ b/tests/jsconfig.json @@ -1,8 +1,6 @@ { - "compilerOptions": { - "experimentalDecorators": true - }, - "exclude": [ - "node_modules" - ] -} \ No newline at end of file + "compilerOptions": { + "experimentalDecorators": true + }, + "exclude": ["node_modules"] +} diff --git a/tests/package.json b/tests/package.json index 437911369..66b60d954 100644 --- a/tests/package.json +++ b/tests/package.json @@ -1,56 +1,56 @@ { - "name": "tests", - "version": "1.0.0", - "description": "near-sdk-js tests", - "main": "index.js", - "type": "module", - "scripts": { - "postinstall": "cd .. && yarn link && cd tests && yarn link near-sdk-js", - "build": "yarn build:context-api && yarn build:math-api && yarn build:storage-api && yarn build:log-panic-api && yarn build:promise-api && yarn build:promise-batch-api && yarn build:function-params && yarn build:lookup-map && yarn build:lookup-set && yarn build:unordered-map && yarn build:unordered-set && yarn build:vector && yarn build:bytes && yarn build:typescript && yarn build:public-key && yarn build:near-bindgen && yarn build:payable && yarn build:private && yarn build:highlevel-promise", - "build:context-api": "near-sdk-js build src/context_api.js build/context_api.wasm", - "build:math-api": "near-sdk-js build src/math_api.js build/math_api.wasm", - "build:storage-api": "near-sdk-js build src/storage_api.js build/storage_api.wasm", - "build:log-panic-api": "near-sdk-js build src/log_panic_api.js build/log_panic_api.wasm", - "build:promise-api": "near-sdk-js build src/promise_api.js build/promise_api.wasm", - "build:promise-batch-api": "near-sdk-js build src/promise_batch_api.js build/promise_batch_api.wasm", - "build:highlevel-promise": "near-sdk-js build src/highlevel-promise.js build/highlevel-promise.wasm", - "build:function-params": "near-sdk-js build src/function-params.js build/function-params.wasm", - "build:lookup-map": "near-sdk-js build src/lookup-map.js build/lookup-map.wasm", - "build:lookup-set": "near-sdk-js build src/lookup-set.js build/lookup-set.wasm", - "build:unordered-map": "near-sdk-js build src/unordered-map.js build/unordered-map.wasm", - "build:unordered-set": "near-sdk-js build src/unordered-set.js build/unordered-set.wasm", - "build:vector": "near-sdk-js build src/vector.js build/vector.wasm", - "build:bytes": "near-sdk-js build src/bytes.js build/bytes.wasm", - "build:typescript": "near-sdk-js build src/typescript.ts build/typescript.wasm", - "build:public-key": "near-sdk-js build src/public-key.js build/public-key.wasm", - "build:near-bindgen": "near-sdk-js build src/decorators/require_init_true.ts build/require_init_true.wasm && near-sdk-js build src/decorators/require_init_false.ts build/require_init_false.wasm", - "build:payable": "near-sdk-js build src/decorators/payable.ts build/payable.wasm", - "build:private": "near-sdk-js build src/decorators/private.ts build/private.wasm", - "test": "ava", - "test:context-api": "ava __tests__/test_context_api.ava.js", - "test:math-api": "ava __tests__/test_math_api.ava.js", - "test:storage-api": "ava __tests__/test_storage_api.ava.js", - "test:log-panic-api": "ava __tests__/test_log_panic_api.ava.js", - "test:promise-api": "ava __tests__/test_promise_api.ava.js", - "test:highlevel-promise": "ava __tests__/test_highlevel_promise.ava.js", - "test:function-params": "ava __tests__/function-params.ava.js", - "test:lookup-map": "ava __tests__/lookup-map.ava.js", - "test:lookup-set": "ava __tests__/lookup-set.ava.js", - "test:unordered-set": "ava __tests__/unordered-set.ava.js", - "test:unordered-map": "ava __tests__/unordered-map.ava.js", - "test:vector": "ava __tests__/vector.ava.js", - "test:bytes": "ava __tests__/bytes.ava.js", - "test:typescript": "ava __tests__/typescript.ava.js", - "test:public-key": "ava __tests__/test-public-key.ava.js", - "test:near-bindgen": "ava __tests__/decorators/near_bindgen.ava.js", - "test:payable": "ava __tests__/decorators/payable.ava.js", - "test:private": "ava __tests__/decorators/private.ava.js" - }, - "author": "Near Inc ", - "license": "Apache-2.0", - "devDependencies": { - "ava": "^4.2.0", - "near-workspaces": "3.2.1", - "typescript": "^4.7.4" - } + "name": "tests", + "version": "1.0.0", + "description": "near-sdk-js tests", + "main": "index.js", + "type": "module", + "scripts": { + "postinstall": "cd .. && yarn link && cd tests && yarn link near-sdk-js", + "build": "yarn build:context-api && yarn build:math-api && yarn build:storage-api && yarn build:log-panic-api && yarn build:promise-api && yarn build:promise-batch-api && yarn build:function-params && yarn build:lookup-map && yarn build:lookup-set && yarn build:unordered-map && yarn build:unordered-set && yarn build:vector && yarn build:bytes && yarn build:typescript && yarn build:public-key && yarn build:near-bindgen && yarn build:payable && yarn build:private && yarn build:highlevel-promise", + "build:context-api": "near-sdk-js build src/context_api.js build/context_api.wasm", + "build:math-api": "near-sdk-js build src/math_api.js build/math_api.wasm", + "build:storage-api": "near-sdk-js build src/storage_api.js build/storage_api.wasm", + "build:log-panic-api": "near-sdk-js build src/log_panic_api.js build/log_panic_api.wasm", + "build:promise-api": "near-sdk-js build src/promise_api.js build/promise_api.wasm", + "build:promise-batch-api": "near-sdk-js build src/promise_batch_api.js build/promise_batch_api.wasm", + "build:highlevel-promise": "near-sdk-js build src/highlevel-promise.js build/highlevel-promise.wasm", + "build:function-params": "near-sdk-js build src/function-params.js build/function-params.wasm", + "build:lookup-map": "near-sdk-js build src/lookup-map.js build/lookup-map.wasm", + "build:lookup-set": "near-sdk-js build src/lookup-set.js build/lookup-set.wasm", + "build:unordered-map": "near-sdk-js build src/unordered-map.js build/unordered-map.wasm", + "build:unordered-set": "near-sdk-js build src/unordered-set.js build/unordered-set.wasm", + "build:vector": "near-sdk-js build src/vector.js build/vector.wasm", + "build:bytes": "near-sdk-js build src/bytes.js build/bytes.wasm", + "build:typescript": "near-sdk-js build src/typescript.ts build/typescript.wasm", + "build:public-key": "near-sdk-js build src/public-key.js build/public-key.wasm", + "build:near-bindgen": "near-sdk-js build src/decorators/require_init_true.ts build/require_init_true.wasm && near-sdk-js build src/decorators/require_init_false.ts build/require_init_false.wasm", + "build:payable": "near-sdk-js build src/decorators/payable.ts build/payable.wasm", + "build:private": "near-sdk-js build src/decorators/private.ts build/private.wasm", + "test": "ava", + "test:context-api": "ava __tests__/test_context_api.ava.js", + "test:math-api": "ava __tests__/test_math_api.ava.js", + "test:storage-api": "ava __tests__/test_storage_api.ava.js", + "test:log-panic-api": "ava __tests__/test_log_panic_api.ava.js", + "test:promise-api": "ava __tests__/test_promise_api.ava.js", + "test:highlevel-promise": "ava __tests__/test_highlevel_promise.ava.js", + "test:function-params": "ava __tests__/function-params.ava.js", + "test:lookup-map": "ava __tests__/lookup-map.ava.js", + "test:lookup-set": "ava __tests__/lookup-set.ava.js", + "test:unordered-set": "ava __tests__/unordered-set.ava.js", + "test:unordered-map": "ava __tests__/unordered-map.ava.js", + "test:vector": "ava __tests__/vector.ava.js", + "test:bytes": "ava __tests__/bytes.ava.js", + "test:typescript": "ava __tests__/typescript.ava.js", + "test:public-key": "ava __tests__/test-public-key.ava.js", + "test:near-bindgen": "ava __tests__/decorators/near_bindgen.ava.js", + "test:payable": "ava __tests__/decorators/payable.ava.js", + "test:private": "ava __tests__/decorators/private.ava.js" + }, + "author": "Near Inc ", + "license": "Apache-2.0", + "devDependencies": { + "ava": "^4.2.0", + "near-workspaces": "3.2.1", + "typescript": "^4.7.4" + } } diff --git a/tests/src/bytes.js b/tests/src/bytes.js index 56b171805..dcfe2389c 100644 --- a/tests/src/bytes.js +++ b/tests/src/bytes.js @@ -1,89 +1,89 @@ -import {near, bytes} from 'near-sdk-js' +import { near, bytes } from "near-sdk-js"; export function log_expected_input_tests() { - // log ascii string - near.log('abc') - // log string with utf-8 chars - near.log('水') // Buffer([0xe6, 0xb0, 0xb4]) - // log number - near.log(333) - // log aribrary byte sequence - near.log(bytes('\x00\x01\xff')) - // log valid utf8 seqence - near.log(bytes('\xe6\xb0\xb4')) - - // log valid utf8 sequence - near.logUtf8(bytes('\xe6\xb0\xb4')) - // log valid utf16 sequence - near.logUtf16(bytes('\x34\x6c')) + // log ascii string + near.log("abc"); + // log string with utf-8 chars + near.log("水"); // Buffer([0xe6, 0xb0, 0xb4]) + // log number + near.log(333); + // log aribrary byte sequence + near.log(bytes("\x00\x01\xff")); + // log valid utf8 seqence + near.log(bytes("\xe6\xb0\xb4")); + + // log valid utf8 sequence + near.logUtf8(bytes("\xe6\xb0\xb4")); + // log valid utf16 sequence + near.logUtf16(bytes("\x34\x6c")); } export function log_unexpected_input_tests() { - // log non-bytes with logUtf8 - near.logUtf8('水') - // log non-bytes with logUtf16 - near.logUtf16('水') + // log non-bytes with logUtf8 + near.logUtf8("水"); + // log non-bytes with logUtf16 + near.logUtf16("水"); } export function log_invalid_utf8_sequence_test() { - near.logUtf8(bytes('\x00\x01\xff')) + near.logUtf8(bytes("\x00\x01\xff")); } export function log_invalid_utf16_sequence_test() { - near.logUtf16(bytes('\x00\x01\xff')) + near.logUtf16(bytes("\x00\x01\xff")); } export function storage_write_bytes() { - near.storageWrite(bytes('abc'), bytes('def')) - near.storageWrite(bytes('\x00\x01\xff'), bytes('\xe6\xb0\xb4')) - near.storageWrite(bytes('\xe6\xb0\xb4'), bytes('\x00ab')) + near.storageWrite(bytes("abc"), bytes("def")); + near.storageWrite(bytes("\x00\x01\xff"), bytes("\xe6\xb0\xb4")); + near.storageWrite(bytes("\xe6\xb0\xb4"), bytes("\x00ab")); } export function storage_write_unexpected_input() { - near.storageWrite('水', '水') - near.storageWrite(123, 456) + near.storageWrite("水", "水"); + near.storageWrite(123, 456); } export function storage_read_ascii_bytes() { - near.valueReturn(near.storageRead(bytes('abc'))) + near.valueReturn(near.storageRead(bytes("abc"))); } export function storage_read_arbitrary_bytes_key_utf8_sequence_bytes_value() { - near.valueReturn(near.storageRead(bytes('\x00\x01\xff'))) + near.valueReturn(near.storageRead(bytes("\x00\x01\xff"))); } export function storage_read_utf8_sequence_bytes_key_arbitrary_bytes_value() { - near.valueReturn(near.storageRead(bytes('\xe6\xb0\xb4'))) + near.valueReturn(near.storageRead(bytes("\xe6\xb0\xb4"))); } export function panic_test() { - throw Error() + throw Error(); } export function panic_ascii_test() { - throw Error('abc') + throw Error("abc"); } export function panic_js_number() { - throw Error(356) + throw Error(356); } export function panic_js_undefined() { - throw Error(undefined) + throw Error(undefined); } export function panic_js_null() { - throw Error(null) + throw Error(null); } export function panic_utf8_test() { - throw Error('水') + throw Error("水"); } export function panicUtf8_valid_utf8_sequence() { - near.panicUtf8(bytes('\xe6\xb0\xb4')) + near.panicUtf8(bytes("\xe6\xb0\xb4")); } export function panicUtf8_invalid_utf8_sequence() { - near.panicUtf8(bytes('\x00\x01\xff')) -} \ No newline at end of file + near.panicUtf8(bytes("\x00\x01\xff")); +} diff --git a/tests/src/context_api.js b/tests/src/context_api.js index 6e5e037f0..e34084ae6 100644 --- a/tests/src/context_api.js +++ b/tests/src/context_api.js @@ -1,61 +1,61 @@ -import {near} from 'near-sdk-js' +import { near } from "near-sdk-js"; export function get_current_account_id() { - near.valueReturn(near.currentAccountId()) + near.valueReturn(near.currentAccountId()); } export function get_signer_account_id() { - near.valueReturn(near.signerAccountId()) + near.valueReturn(near.signerAccountId()); } export function get_predecessor_account_id() { - near.valueReturn(near.predecessorAccountId()) + near.valueReturn(near.predecessorAccountId()); } export function get_signer_account_pk() { - near.valueReturn(near.signerAccountPk()) + near.valueReturn(near.signerAccountPk()); } export function get_input() { - near.valueReturn(near.input()) + near.valueReturn(near.input()); } export function get_storage_usage() { - near.valueReturn(near.storageUsage()) + near.valueReturn(near.storageUsage()); } export function get_block_height() { - near.valueReturn(near.blockHeight()) + near.valueReturn(near.blockHeight()); } export function get_block_timestamp() { - near.valueReturn(near.blockTimestamp()) + near.valueReturn(near.blockTimestamp()); } export function get_epoch_height() { - near.valueReturn(near.epochHeight()) + near.valueReturn(near.epochHeight()); } export function get_attached_deposit() { - near.valueReturn(near.attachedDeposit()) + near.valueReturn(near.attachedDeposit()); } export function get_prepaid_gas() { - near.valueReturn(near.prepaidGas()) + near.valueReturn(near.prepaidGas()); } export function get_used_gas() { - near.valueReturn(near.usedGas()) + near.valueReturn(near.usedGas()); } export function get_random_seed() { - near.valueReturn(near.randomSeed()) + near.valueReturn(near.randomSeed()); } export function get_validator_stake() { - near.valueReturn(near.validatorStake(near.signerAccountId())) + near.valueReturn(near.validatorStake(near.signerAccountId())); } export function get_total_stake() { - near.valueReturn(near.validatorTotalStake()) + near.valueReturn(near.validatorTotalStake()); } diff --git a/tests/src/decorators/payable.ts b/tests/src/decorators/payable.ts index d1e6d9819..d87c18923 100644 --- a/tests/src/decorators/payable.ts +++ b/tests/src/decorators/payable.ts @@ -1,38 +1,33 @@ -import { - near, - NearBindgen, - call, - view, -} from 'near-sdk-js' +import { near, NearBindgen, call, view } from "near-sdk-js"; @NearBindgen({}) class PayableTest { - value: string; + value: string; - constructor() { - this.value = ''; - } + constructor() { + this.value = ""; + } - @call({ payableFunction: true }) - setValueWithPayableFunction({ value }: { value: string }): void { - near.log(`payableFunction: ${value}`) - this.value = value; - } + @call({ payableFunction: true }) + setValueWithPayableFunction({ value }: { value: string }): void { + near.log(`payableFunction: ${value}`); + this.value = value; + } - @call({ payableFunction: false }) - setValueWithNotPayableFunction({ value }: { value: string }): void { - near.log(`notPayableFunction: ${value}`) - this.value = value; - } + @call({ payableFunction: false }) + setValueWithNotPayableFunction({ value }: { value: string }): void { + near.log(`notPayableFunction: ${value}`); + this.value = value; + } - @call({}) - setValueWithNotPayableFunctionByDefault({ value }: { value: string }): void { - near.log(`notPayableFunctionDefault: ${value}`) - this.value = value; - } + @call({}) + setValueWithNotPayableFunctionByDefault({ value }: { value: string }): void { + near.log(`notPayableFunctionDefault: ${value}`); + this.value = value; + } - @view({}) - getValue(): string { - return this.value; - } + @view({}) + getValue(): string { + return this.value; + } } diff --git a/tests/src/decorators/private.ts b/tests/src/decorators/private.ts index f3a6a9018..a6875b15e 100644 --- a/tests/src/decorators/private.ts +++ b/tests/src/decorators/private.ts @@ -1,38 +1,33 @@ -import { - near, - NearBindgen, - call, - view, -} from 'near-sdk-js' +import { near, NearBindgen, call, view } from "near-sdk-js"; @NearBindgen({}) class PrivateTest { - value: string; + value: string; - constructor() { - this.value = ''; - } + constructor() { + this.value = ""; + } - @call({ privateFunction: true }) - setValueWithPrivateFunction({ value }: { value: string }): void { - near.log(`setValueWithPrivateFunction: ${value}`) - this.value = value; - } + @call({ privateFunction: true }) + setValueWithPrivateFunction({ value }: { value: string }): void { + near.log(`setValueWithPrivateFunction: ${value}`); + this.value = value; + } - @call({ privateFunction: false }) - setValueWithNotPrivateFunction({ value }: { value: string }): void { - near.log(`setValueWithNotPrivateFunction: ${value}`) - this.value = value; - } + @call({ privateFunction: false }) + setValueWithNotPrivateFunction({ value }: { value: string }): void { + near.log(`setValueWithNotPrivateFunction: ${value}`); + this.value = value; + } - @call({}) - setValueWithNotPrivateFunctionByDefault({ value }: { value: string }): void { - near.log(`setValueWithNotPrivateFunctionByDefault: ${value}`) - this.value = value; - } + @call({}) + setValueWithNotPrivateFunctionByDefault({ value }: { value: string }): void { + near.log(`setValueWithNotPrivateFunctionByDefault: ${value}`); + this.value = value; + } - @view({}) - getValue(): string { - return this.value; - } + @view({}) + getValue(): string { + return this.value; + } } diff --git a/tests/src/decorators/require_init_false.ts b/tests/src/decorators/require_init_false.ts index a8ab954ce..181822cba 100644 --- a/tests/src/decorators/require_init_false.ts +++ b/tests/src/decorators/require_init_false.ts @@ -1,34 +1,28 @@ -import { - near, - NearBindgen, - call, - view, - initialize, -} from 'near-sdk-js' +import { near, NearBindgen, call, view, initialize } from "near-sdk-js"; @NearBindgen({ requireInit: false }) class NBTest { - status: string; + status: string; - constructor() { - this.status = ''; - } + constructor() { + this.status = ""; + } - @initialize({}) - init({ status }: { status: string }): void { - near.log(`init: ${status}`) - this.status = status; - } + @initialize({}) + init({ status }: { status: string }): void { + near.log(`init: ${status}`); + this.status = status; + } - @view({}) - getStatus(): string { - near.log(`getStatus: ${this.status}`) - return this.status; - } + @view({}) + getStatus(): string { + near.log(`getStatus: ${this.status}`); + return this.status; + } - @call({}) - setStatus({ status }: { status: string }): void { - near.log(`setStatus: ${status}`) - this.status = status; - } + @call({}) + setStatus({ status }: { status: string }): void { + near.log(`setStatus: ${status}`); + this.status = status; + } } diff --git a/tests/src/decorators/require_init_true.ts b/tests/src/decorators/require_init_true.ts index b756f5d8b..55ce0db83 100644 --- a/tests/src/decorators/require_init_true.ts +++ b/tests/src/decorators/require_init_true.ts @@ -1,36 +1,28 @@ -import { - near, - NearBindgen, - call, - view, - initialize, -} from 'near-sdk-js' +import { near, NearBindgen, call, view, initialize } from "near-sdk-js"; @NearBindgen({ requireInit: true }) class NBTest { - status: string; + status: string; - constructor() { - this.status = ''; - } + constructor() { + this.status = ""; + } - @initialize({}) - init({ status }: { status: string }): void { - near.log(`init: ${status}`) - this.status = status; - } + @initialize({}) + init({ status }: { status: string }): void { + near.log(`init: ${status}`); + this.status = status; + } - @view({}) - getStatus(): string { - near.log(`getStatus: ${this.status}`) - return this.status; - } + @view({}) + getStatus(): string { + near.log(`getStatus: ${this.status}`); + return this.status; + } - @call({}) - setStatus({ status }: { status: string }): void { - near.log(`setStatus: ${status}`) - this.status = status; - } + @call({}) + setStatus({ status }: { status: string }): void { + near.log(`setStatus: ${status}`); + this.status = status; + } } - - diff --git a/tests/src/function-params.js b/tests/src/function-params.js index b6dfa8c02..237c18c2d 100644 --- a/tests/src/function-params.js +++ b/tests/src/function-params.js @@ -1,31 +1,26 @@ -import { - NearBindgen, - call, - view, - near, -} from 'near-sdk-js' +import { NearBindgen, call, view, near } from "near-sdk-js"; /** * Simple contract to test function parameters */ @NearBindgen({}) class FunctionParamsTestContract { - constructor() { - this.val1 = 'default1'; - this.val2 = 'default2'; - this.val3 = 'default3'; - } + constructor() { + this.val1 = "default1"; + this.val2 = "default2"; + this.val3 = "default3"; + } - @call({}) - set_values({ param1, param2, param3 }) { - near.log(JSON.stringify({ param1, param2, param3 })); - this.val1 = param1; - this.val2 = param2; - this.val3 = param3; - } + @call({}) + set_values({ param1, param2, param3 }) { + near.log(JSON.stringify({ param1, param2, param3 })); + this.val1 = param1; + this.val2 = param2; + this.val3 = param3; + } - @view({}) - get_values() { - return { val3: this.val3, val2: this.val2, val1: this.val1 } - } -} \ No newline at end of file + @view({}) + get_values() { + return { val3: this.val3, val2: this.val2, val1: this.val1 }; + } +} diff --git a/tests/src/highlevel-promise.js b/tests/src/highlevel-promise.js index 702dd154d..4b6dd1d97 100644 --- a/tests/src/highlevel-promise.js +++ b/tests/src/highlevel-promise.js @@ -1,87 +1,127 @@ -import {NearBindgen, call, view, NearPromise, near, bytes} from 'near-sdk-js' -import { PublicKey } from 'near-sdk-js/lib/types'; +import { NearBindgen, call, view, NearPromise, near, bytes } from "near-sdk-js"; +import { PublicKey } from "near-sdk-js/lib/types"; function callingData() { - return { - currentAccountId: near.currentAccountId(), - signerAccountId: near.signerAccountId(), - predecessorAccountId: near.predecessorAccountId(), - input: near.input(), - } + return { + currentAccountId: near.currentAccountId(), + signerAccountId: near.signerAccountId(), + predecessorAccountId: near.predecessorAccountId(), + input: near.input(), + }; } function arrayN(n) { - return [...Array(Number(n)).keys()] + return [...Array(Number(n)).keys()]; } @NearBindgen({}) class HighlevelPromiseContract { - @call({}) - test_promise_batch_stake() { - let promise = NearPromise.new('highlevel-promise.test.near') - .stake(100000000000000000000000000000n, new PublicKey(near.signerAccountPk())) + @call({}) + test_promise_batch_stake() { + let promise = NearPromise.new("highlevel-promise.test.near").stake( + 100000000000000000000000000000n, + new PublicKey(near.signerAccountPk()) + ); + + return promise; + } + + @call({}) + test_promise_batch_create_transfer() { + let promise = NearPromise.new("a.highlevel-promise.test.near") + .createAccount() + .transfer(10000000000000000000000000n); + return promise; + } - return promise; - } + @call({}) + test_promise_add_full_access_key() { + let promise = NearPromise.new("c.highlevel-promise.test.near") + .createAccount() + .transfer(10000000000000000000000000n) + .addFullAccessKey(new PublicKey(near.signerAccountPk())); + return promise; + } - @call({}) - test_promise_batch_create_transfer() { - let promise = NearPromise.new('a.highlevel-promise.test.near') - .createAccount() - .transfer(10000000000000000000000000n) - return promise; - } + @call({}) + test_promise_add_function_call_access_key() { + let promise = NearPromise.new("d.highlevel-promise.test.near") + .createAccount() + .transfer(10000000000000000000000000n) + .addAccessKey( + new PublicKey(near.signerAccountPk()), + 250000000000000000000000n, + "highlevel-promise.test.near", + "test_promise_batch_create_transfer" + ); + return promise; + } - @call({}) - test_promise_add_full_access_key() { - let promise = NearPromise.new('c.highlevel-promise.test.near') - .createAccount() - .transfer(10000000000000000000000000n) - .addFullAccessKey(new PublicKey(near.signerAccountPk())) - return promise; - } - - @call({}) - test_promise_add_function_call_access_key() { - let promise = NearPromise.new('d.highlevel-promise.test.near') - .createAccount() - .transfer(10000000000000000000000000n) - .addAccessKey(new PublicKey(near.signerAccountPk()), 250000000000000000000000n, 'highlevel-promise.test.near', 'test_promise_batch_create_transfer') - return promise; - } + @call({}) + test_delete_account() { + let promise = NearPromise.new("e.highlevel-promise.test.near") + .createAccount() + .transfer(10000000000000000000000000n) + .deleteAccount(near.signerAccountId()); + return promise; + } - @call({}) - test_delete_account() { - let promise = NearPromise.new('e.highlevel-promise.test.near') - .createAccount() - .transfer(10000000000000000000000000n) - .deleteAccount(near.signerAccountId()) - return promise; - } + @call({}) + test_promise_then() { + let promise = NearPromise.new("callee-contract.test.near") + .functionCall( + "cross_contract_callee", + bytes("abc"), + 0, + 2 * Math.pow(10, 13) + ) + .then( + NearPromise.new("highlevel-promise.test.near").functionCall( + "cross_contract_callback", + bytes(JSON.stringify({ callbackArg1: "def" })), + 0, + 2 * Math.pow(10, 13) + ) + ); + return promise; + } - @call({}) - test_promise_then() { - let promise = NearPromise.new('callee-contract.test.near') - .functionCall('cross_contract_callee', bytes('abc'), 0, 2 * Math.pow(10, 13)) - .then(NearPromise.new('highlevel-promise.test.near').functionCall('cross_contract_callback', bytes(JSON.stringify({callbackArg1: 'def'})), 0, 2 * Math.pow(10, 13))) - return promise; - } - - @call({}) - test_promise_and() { - let promise = NearPromise.new('callee-contract.test.near') - .functionCall('cross_contract_callee', bytes('abc'), 0, 2 * Math.pow(10, 13)) - let promise2 = NearPromise.new('callee-contract.test.near') - .functionCall('cross_contract_callee', bytes('def'), 0, 2 * Math.pow(10, 13)) - let retPromise = promise.and(promise2).then( - NearPromise.new('highlevel-promise.test.near') - .functionCall('cross_contract_callback', bytes(JSON.stringify({callbackArg1: 'ghi'})), 0, 3 * Math.pow(10, 13))) + @call({}) + test_promise_and() { + let promise = NearPromise.new("callee-contract.test.near").functionCall( + "cross_contract_callee", + bytes("abc"), + 0, + 2 * Math.pow(10, 13) + ); + let promise2 = NearPromise.new("callee-contract.test.near").functionCall( + "cross_contract_callee", + bytes("def"), + 0, + 2 * Math.pow(10, 13) + ); + let retPromise = promise + .and(promise2) + .then( + NearPromise.new("highlevel-promise.test.near").functionCall( + "cross_contract_callback", + bytes(JSON.stringify({ callbackArg1: "ghi" })), + 0, + 3 * Math.pow(10, 13) + ) + ); - return retPromise; - } - - @call({}) - cross_contract_callback({callbackArg1}) { - return {...callingData(), promiseResults: arrayN(near.promiseResultsCount()).map(i => near.promiseResult(i)), callbackArg1} - } -} \ No newline at end of file + return retPromise; + } + + @call({}) + cross_contract_callback({ callbackArg1 }) { + return { + ...callingData(), + promiseResults: arrayN(near.promiseResultsCount()).map((i) => + near.promiseResult(i) + ), + callbackArg1, + }; + } +} diff --git a/tests/src/log_panic_api.js b/tests/src/log_panic_api.js index c87e5ee47..868ccd483 100644 --- a/tests/src/log_panic_api.js +++ b/tests/src/log_panic_api.js @@ -1,66 +1,66 @@ -import {near, bytes} from 'near-sdk-js' +import { near, bytes } from "near-sdk-js"; export function log_expected_input_tests() { - // log ascii string - near.log('abc') - // log string with utf-8 chars - near.log('水') - // log number - near.log(333) - // log aribrary byte sequence - near.log(bytes('\x00\x01\xff')) - // log valid utf8 seqence - near.log(bytes('\xe6\xb0\xb4')) + // log ascii string + near.log("abc"); + // log string with utf-8 chars + near.log("水"); + // log number + near.log(333); + // log aribrary byte sequence + near.log(bytes("\x00\x01\xff")); + // log valid utf8 seqence + near.log(bytes("\xe6\xb0\xb4")); - // log valid utf8 sequence - near.logUtf8(bytes('\xe6\xb0\xb4')) - // log valid utf16 sequence - near.logUtf16(bytes('\x34\x6c')) + // log valid utf8 sequence + near.logUtf8(bytes("\xe6\xb0\xb4")); + // log valid utf16 sequence + near.logUtf16(bytes("\x34\x6c")); } export function log_unexpected_input_tests() { - // log non-bytes with logUtf8 - near.logUtf8('水') - // log non-bytes with logUtf16 - near.logUtf16('水') + // log non-bytes with logUtf8 + near.logUtf8("水"); + // log non-bytes with logUtf16 + near.logUtf16("水"); } export function log_invalid_utf8_sequence_test() { - near.logUtf8(bytes('\x00\x01\xff')) + near.logUtf8(bytes("\x00\x01\xff")); } export function log_invalid_utf16_sequence_test() { - near.logUtf16(bytes('\x00\x01\xff')) + near.logUtf16(bytes("\x00\x01\xff")); } export function panic_test() { - throw Error() + throw Error(); } export function panic_ascii_test() { - throw Error('abc') + throw Error("abc"); } export function panic_js_number() { - throw Error(356) + throw Error(356); } export function panic_js_undefined() { - throw Error(undefined) + throw Error(undefined); } export function panic_js_null() { - throw Error(null) + throw Error(null); } export function panic_utf8_test() { - throw Error('水') + throw Error("水"); } export function panicUtf8_valid_utf8_sequence() { - near.panicUtf8(bytes('\xe6\xb0\xb4')) + near.panicUtf8(bytes("\xe6\xb0\xb4")); } export function panicUtf8_invalid_utf8_sequence() { - near.panicUtf8(bytes('\x00\x01\xff')) -} \ No newline at end of file + near.panicUtf8(bytes("\x00\x01\xff")); +} diff --git a/tests/src/lookup-map.js b/tests/src/lookup-map.js index b57b77b7e..af2367ce6 100644 --- a/tests/src/lookup-map.js +++ b/tests/src/lookup-map.js @@ -1,54 +1,55 @@ -import { - NearBindgen, - call, - view, - LookupMap -} from 'near-sdk-js' -import { House, Room } from './model.js'; +import { NearBindgen, call, view, LookupMap } from "near-sdk-js"; +import { House, Room } from "./model.js"; @NearBindgen({}) class LookupMapTestContract { - constructor() { - this.lookupMap = new LookupMap('a'); - } - - @view({}) - get({ key }) { - return this.lookupMap.get(key); - } - - @view({}) - containsKey({ key }) { - return this.lookupMap.containsKey(key); - } - - @call({}) - set({ key, value }) { - this.lookupMap.set(key, value); - } - - @call({}) - remove_key({ key }) { - this.lookupMap.remove(key); - } - - @call({}) - extend({ kvs }) { - this.lookupMap.extend(kvs); - } - - @call({}) - add_house() { - this.lookupMap.set('house1', new House('house1', [new Room('room1', '200sqft'), new Room('room2', '300sqft')])) - } - - @view({}) - get_house() { - const houseObject = this.lookupMap.get('house1') - // restore class object from serialized data - const house = new House(houseObject.name, houseObject.rooms) - const roomObject = house.rooms[0] - const room = new Room(roomObject.name, roomObject.size) - return house.describe() + room.describe() - } + constructor() { + this.lookupMap = new LookupMap("a"); + } + + @view({}) + get({ key }) { + return this.lookupMap.get(key); + } + + @view({}) + containsKey({ key }) { + return this.lookupMap.containsKey(key); + } + + @call({}) + set({ key, value }) { + this.lookupMap.set(key, value); + } + + @call({}) + remove_key({ key }) { + this.lookupMap.remove(key); + } + + @call({}) + extend({ kvs }) { + this.lookupMap.extend(kvs); + } + + @call({}) + add_house() { + this.lookupMap.set( + "house1", + new House("house1", [ + new Room("room1", "200sqft"), + new Room("room2", "300sqft"), + ]) + ); + } + + @view({}) + get_house() { + const houseObject = this.lookupMap.get("house1"); + // restore class object from serialized data + const house = new House(houseObject.name, houseObject.rooms); + const roomObject = house.rooms[0]; + const room = new Room(roomObject.name, roomObject.size); + return house.describe() + room.describe(); + } } diff --git a/tests/src/lookup-set.js b/tests/src/lookup-set.js index 458c3ac87..43f16ef09 100644 --- a/tests/src/lookup-set.js +++ b/tests/src/lookup-set.js @@ -1,53 +1,47 @@ -import { - NearBindgen, - call, - view, - LookupSet -} from 'near-sdk-js' -import { House, Room } from './model.js'; +import { NearBindgen, call, view, LookupSet } from "near-sdk-js"; +import { House, Room } from "./model.js"; @NearBindgen({}) class LookupSetTestContract { - constructor() { - this.lookupSet = new LookupSet('a'); + constructor() { + this.lookupSet = new LookupSet("a"); + } + + @view({}) + contains({ key }) { + return this.lookupSet.contains(key); + } + + @call({}) + set({ key }) { + this.lookupSet.set(key); + } + + @call({}) + remove_key({ key }) { + this.lookupSet.remove(key); + } + + @call({}) + extend({ keys }) { + this.lookupSet.extend(keys); + } + + @call({}) + add_house({ name, rooms }) { + let house = new House(name, []); + for (let r of rooms) { + house.rooms.push(new Room(r.name, r.size)); } - - @view({}) - contains({ key }) { - return this.lookupSet.contains(key); - } - - @call({}) - set({ key }) { - this.lookupSet.set(key); - } - - @call({}) - remove_key({ key }) { - this.lookupSet.remove(key); - } - - @call({}) - extend({ keys }) { - this.lookupSet.extend(keys); - } - - @call({}) - add_house({ name, rooms }) { - let house = new House(name, []) - for (let r of rooms) { - house.rooms.push(new Room(r.name, r.size)) - } - this.lookupSet.set(house) - } - - @view({}) - house_exist({ name, rooms }) { - let house = new House(name, []) - for (let r of rooms) { - house.rooms.push(new Room(r.name, r.size)) - } - return this.lookupSet.contains(house) + this.lookupSet.set(house); + } + + @view({}) + house_exist({ name, rooms }) { + let house = new House(name, []); + for (let r of rooms) { + house.rooms.push(new Room(r.name, r.size)); } + return this.lookupSet.contains(house); + } } - diff --git a/tests/src/math_api.js b/tests/src/math_api.js index 50d581e83..93d2d72d4 100644 --- a/tests/src/math_api.js +++ b/tests/src/math_api.js @@ -1,38 +1,39 @@ -import {near, bytes} from 'near-sdk-js' +import { near, bytes } from "near-sdk-js"; export function test_sha256() { - near.valueReturn(near.sha256(bytes("tesdsst"))) + near.valueReturn(near.sha256(bytes("tesdsst"))); } export function test_keccak256() { - near.valueReturn(near.keccak256(bytes("tesdsst"))) + near.valueReturn(near.keccak256(bytes("tesdsst"))); } export function test_keccak512() { - near.valueReturn(near.keccak512(bytes("tesdsst"))) + near.valueReturn(near.keccak512(bytes("tesdsst"))); } export function test_ripemd160() { - near.valueReturn(near.ripemd160(bytes("tesdsst"))) + near.valueReturn(near.ripemd160(bytes("tesdsst"))); } export function test_ecrecover() { - let hash = bytes(new Uint8Array([ - 206, 6, 119, 187, 48, 186, 168, 207, - 6, 124, 136, 219, 152, 17, 244, 51, - 61, 19, 27, 248, 188, 241, 47, 231, - 6, 93, 33, 29, 206, 151, 16, 8 - ])) - let sign = bytes(new Uint8Array([ - 144, 242, 123, 139, 72, 141, 176, 11, 0, 96, 103, - 150, 210, 152, 127, 106, 95, 89, 174, 98, 234, 5, - 239, 254, 132, 254, 245, 184, 176, 229, 73, 152, 74, - 105, 17, 57, 173, 87, 163, 240, 185, 6, 99, 118, - 115, 170, 47, 99, 209, 245, 92, 177, 166, 145, 153, - 212, 0, 158, 234, 35, 206, 173, 220, 147 - ])) - let v = 1 - let malleabilityFlag = 1 - let ret = near.ecrecover(hash, sign, v, malleabilityFlag) - near.valueReturn(ret) + let hash = bytes( + new Uint8Array([ + 206, 6, 119, 187, 48, 186, 168, 207, 6, 124, 136, 219, 152, 17, 244, 51, + 61, 19, 27, 248, 188, 241, 47, 231, 6, 93, 33, 29, 206, 151, 16, 8, + ]) + ); + let sign = bytes( + new Uint8Array([ + 144, 242, 123, 139, 72, 141, 176, 11, 0, 96, 103, 150, 210, 152, 127, 106, + 95, 89, 174, 98, 234, 5, 239, 254, 132, 254, 245, 184, 176, 229, 73, 152, + 74, 105, 17, 57, 173, 87, 163, 240, 185, 6, 99, 118, 115, 170, 47, 99, + 209, 245, 92, 177, 166, 145, 153, 212, 0, 158, 234, 35, 206, 173, 220, + 147, + ]) + ); + let v = 1; + let malleabilityFlag = 1; + let ret = near.ecrecover(hash, sign, v, malleabilityFlag); + near.valueReturn(ret); } diff --git a/tests/src/model.js b/tests/src/model.js index cd20f3f0c..28e4e72d8 100644 --- a/tests/src/model.js +++ b/tests/src/model.js @@ -1,21 +1,21 @@ export class House { - constructor(name, rooms) { - this.name = name - this.rooms = rooms - } + constructor(name, rooms) { + this.name = name; + this.rooms = rooms; + } - describe() { - return `house ${this.name} has ${this.rooms.length} rooms. ` - } + describe() { + return `house ${this.name} has ${this.rooms.length} rooms. `; + } } export class Room { - constructor(name, size) { - this.name = name - this.size = size - } + constructor(name, size) { + this.name = name; + this.size = size; + } - describe() { - return `room ${this.name} is ${this.size}.` - } -} \ No newline at end of file + describe() { + return `room ${this.name} is ${this.size}.`; + } +} diff --git a/tests/src/promise_api.js b/tests/src/promise_api.js index cb976942c..fadc67217 100644 --- a/tests/src/promise_api.js +++ b/tests/src/promise_api.js @@ -1,46 +1,99 @@ -import {near, bytes} from 'near-sdk-js' +import { near, bytes } from "near-sdk-js"; function arrayN(n) { - return [...Array(Number(n)).keys()] + return [...Array(Number(n)).keys()]; } function callingData() { - return { - currentAccountId: near.currentAccountId(), - signerAccountId: near.signerAccountId(), - predecessorAccountId: near.predecessorAccountId(), - input: near.input(), - } + return { + currentAccountId: near.currentAccountId(), + signerAccountId: near.signerAccountId(), + predecessorAccountId: near.predecessorAccountId(), + input: near.input(), + }; } export function cross_contract_callee() { - near.valueReturn(bytes(JSON.stringify(callingData()))) + near.valueReturn(bytes(JSON.stringify(callingData()))); } export function cross_contract_call_gas() { - near.valueReturn(bytes(near.prepaidGas().toString())) + near.valueReturn(bytes(near.prepaidGas().toString())); } export function cross_contract_callback() { - near.valueReturn(bytes(JSON.stringify({...callingData(), promiseResults: arrayN(near.promiseResultsCount()).map(i => near.promiseResult(i))}))) + near.valueReturn( + bytes( + JSON.stringify({ + ...callingData(), + promiseResults: arrayN(near.promiseResultsCount()).map((i) => + near.promiseResult(i) + ), + }) + ) + ); } export function test_promise_create() { - near.promiseCreate('callee-contract.test.near', 'cross_contract_callee', bytes('abc'), 0, 2 * Math.pow(10, 13)) + near.promiseCreate( + "callee-contract.test.near", + "cross_contract_callee", + bytes("abc"), + 0, + 2 * Math.pow(10, 13) + ); } export function test_promise_create_gas_overflow() { - near.promiseCreate('callee-contract.test.near', 'cross_contract_callee', bytes('abc'), 0, BigInt(2) ** BigInt(64)) + near.promiseCreate( + "callee-contract.test.near", + "cross_contract_callee", + bytes("abc"), + 0, + BigInt(2) ** BigInt(64) + ); } export function test_promise_then() { - let promiseId = near.promiseCreate('callee-contract.test.near', 'cross_contract_callee', bytes('abc'), 0, 2 * Math.pow(10, 13)) - near.promiseThen(promiseId, 'caller-contract.test.near', 'cross_contract_callback', bytes('def'), 0, 2 * Math.pow(10, 13)) + let promiseId = near.promiseCreate( + "callee-contract.test.near", + "cross_contract_callee", + bytes("abc"), + 0, + 2 * Math.pow(10, 13) + ); + near.promiseThen( + promiseId, + "caller-contract.test.near", + "cross_contract_callback", + bytes("def"), + 0, + 2 * Math.pow(10, 13) + ); } export function test_promise_and() { - let promiseId = near.promiseCreate('callee-contract.test.near', 'cross_contract_callee', bytes('abc'), 0, 2 * Math.pow(10, 13)) - let promiseId2 = near.promiseCreate('callee-contract.test.near', 'cross_contract_callee', bytes('def'), 0, 2 * Math.pow(10, 13)) - let promiseIdAnd = near.promiseAnd(promiseId, promiseId2) - near.promiseThen(promiseIdAnd, 'caller-contract.test.near', 'cross_contract_callback', bytes('ghi'), 0, 3 * Math.pow(10, 13)) + let promiseId = near.promiseCreate( + "callee-contract.test.near", + "cross_contract_callee", + bytes("abc"), + 0, + 2 * Math.pow(10, 13) + ); + let promiseId2 = near.promiseCreate( + "callee-contract.test.near", + "cross_contract_callee", + bytes("def"), + 0, + 2 * Math.pow(10, 13) + ); + let promiseIdAnd = near.promiseAnd(promiseId, promiseId2); + near.promiseThen( + promiseIdAnd, + "caller-contract.test.near", + "cross_contract_callback", + bytes("ghi"), + 0, + 3 * Math.pow(10, 13) + ); } diff --git a/tests/src/promise_batch_api.js b/tests/src/promise_batch_api.js index e8b25c7ed..bd0beee0a 100644 --- a/tests/src/promise_batch_api.js +++ b/tests/src/promise_batch_api.js @@ -1,62 +1,93 @@ -import {near, bytes} from 'near-sdk-js' +import { near, bytes } from "near-sdk-js"; export function test_promise_batch_stake() { - let promiseId = near.promiseBatchCreate('caller2.test.near') - near.promiseBatchActionStake(promiseId, 100000000000000000000000000000n, near.signerAccountPk()) - near.promiseReturn(promiseId) + let promiseId = near.promiseBatchCreate("caller2.test.near"); + near.promiseBatchActionStake( + promiseId, + 100000000000000000000000000000n, + near.signerAccountPk() + ); + near.promiseReturn(promiseId); } export function test_transfer_overflow() { - let promiseId = near.promiseBatchCreate('c.caller2.test.near') - near.promiseBatchActionCreateAccount(promiseId) - near.promiseBatchActionTransfer(promiseId, BigInt(2) ** BigInt(128)) - near.promiseReturn(promiseId) + let promiseId = near.promiseBatchCreate("c.caller2.test.near"); + near.promiseBatchActionCreateAccount(promiseId); + near.promiseBatchActionTransfer(promiseId, BigInt(2) ** BigInt(128)); + near.promiseReturn(promiseId); } export function test_promise_add_full_access_key() { - let promiseId = near.promiseBatchCreate('c.caller2.test.near') - near.promiseBatchActionCreateAccount(promiseId) - near.promiseBatchActionTransfer(promiseId, 10000000000000000000000000n) - near.promiseBatchActionAddKeyWithFullAccess(promiseId, near.signerAccountPk(), 1n) - near.promiseReturn(promiseId) + let promiseId = near.promiseBatchCreate("c.caller2.test.near"); + near.promiseBatchActionCreateAccount(promiseId); + near.promiseBatchActionTransfer(promiseId, 10000000000000000000000000n); + near.promiseBatchActionAddKeyWithFullAccess( + promiseId, + near.signerAccountPk(), + 1n + ); + near.promiseReturn(promiseId); } export function test_delete_account() { - let promiseId = near.promiseBatchCreate('e.caller2.test.near') - near.promiseBatchActionCreateAccount(promiseId) - near.promiseBatchActionTransfer(promiseId, 10000000000000000000000000n) - near.promiseBatchActionDeleteAccount(promiseId, near.signerAccountId()) - near.promiseReturn(promiseId) + let promiseId = near.promiseBatchCreate("e.caller2.test.near"); + near.promiseBatchActionCreateAccount(promiseId); + near.promiseBatchActionTransfer(promiseId, 10000000000000000000000000n); + near.promiseBatchActionDeleteAccount(promiseId, near.signerAccountId()); + near.promiseReturn(promiseId); } export function test_promise_add_function_call_access_key() { - let promiseId = near.promiseBatchCreate('d.caller2.test.near') - near.promiseBatchActionCreateAccount(promiseId) - near.promiseBatchActionTransfer(promiseId, 10000000000000000000000000n) - near.promiseBatchActionAddKeyWithFunctionCall(promiseId, near.signerAccountPk(), 1n, 250000000000000000000000n, 'caller2.test.near', 'test_promise_batch_create_transfer') - near.promiseReturn(promiseId) + let promiseId = near.promiseBatchCreate("d.caller2.test.near"); + near.promiseBatchActionCreateAccount(promiseId); + near.promiseBatchActionTransfer(promiseId, 10000000000000000000000000n); + near.promiseBatchActionAddKeyWithFunctionCall( + promiseId, + near.signerAccountPk(), + 1n, + 250000000000000000000000n, + "caller2.test.near", + "test_promise_batch_create_transfer" + ); + near.promiseReturn(promiseId); } export function test_promise_batch_create_transfer() { - let promiseId = near.promiseBatchCreate('a.caller2.test.near') - near.promiseBatchActionCreateAccount(promiseId) - near.promiseBatchActionTransfer(promiseId, 10000000000000000000000000n) - near.promiseReturn(promiseId) + let promiseId = near.promiseBatchCreate("a.caller2.test.near"); + near.promiseBatchActionCreateAccount(promiseId); + near.promiseBatchActionTransfer(promiseId, 10000000000000000000000000n); + near.promiseReturn(promiseId); } export function test_promise_batch_call_weight() { - let promiseId = near.promiseBatchCreate('callee-contract.test.near') - near.promiseBatchActionFunctionCallWeight(promiseId, 'cross_contract_call_gas', bytes('abc'), 0, 0, 1) - near.promiseReturn(promiseId) + let promiseId = near.promiseBatchCreate("callee-contract.test.near"); + near.promiseBatchActionFunctionCallWeight( + promiseId, + "cross_contract_call_gas", + bytes("abc"), + 0, + 0, + 1 + ); + near.promiseReturn(promiseId); } export function test_promise_batch_deploy_call() { - let promiseId = near.promiseBatchCreate('b.caller2.test.near') - near.promiseBatchActionCreateAccount(promiseId) - near.promiseBatchActionTransfer(promiseId, 10000000000000000000000000n) - // deploy content of promise_api.wasm to `b.caller2.test.near` - // Note, we do not use `bytes()`, it's too expensive for long bytes and exceed gas limit - near.promiseBatchActionDeployContract(promiseId, includeBytes('../build/promise_api.wasm')) - near.promiseBatchActionFunctionCall(promiseId, 'cross_contract_callee', bytes('abc'), 0, 2 * Math.pow(10, 13)) - near.promiseReturn(promiseId) + let promiseId = near.promiseBatchCreate("b.caller2.test.near"); + near.promiseBatchActionCreateAccount(promiseId); + near.promiseBatchActionTransfer(promiseId, 10000000000000000000000000n); + // deploy content of promise_api.wasm to `b.caller2.test.near` + // Note, we do not use `bytes()`, it's too expensive for long bytes and exceed gas limit + near.promiseBatchActionDeployContract( + promiseId, + includeBytes("../build/promise_api.wasm") + ); + near.promiseBatchActionFunctionCall( + promiseId, + "cross_contract_callee", + bytes("abc"), + 0, + 2 * Math.pow(10, 13) + ); + near.promiseReturn(promiseId); } diff --git a/tests/src/public-key.js b/tests/src/public-key.js index 43f68d86e..46822f9ed 100644 --- a/tests/src/public-key.js +++ b/tests/src/public-key.js @@ -1,76 +1,86 @@ -import {near, bytes, types} from 'near-sdk-js' -import {CurveType, PublicKey} from 'near-sdk-js/lib/types' -import {assert} from 'near-sdk-js/lib/utils' +import { near, bytes, types } from "near-sdk-js"; +import { CurveType, PublicKey } from "near-sdk-js/lib/types"; +import { assert } from "near-sdk-js/lib/utils"; function runtime_validate_public_key(prefix, public_key) { - let promiseId = near.promiseBatchCreate(prefix + '.pk.test.near') - near.promiseBatchActionCreateAccount(promiseId) - near.promiseBatchActionTransfer(promiseId, 10000000000000000000000000n) - near.promiseBatchActionAddKeyWithFullAccess(promiseId, public_key, 1n) - near.promiseReturn(promiseId) + let promiseId = near.promiseBatchCreate(prefix + ".pk.test.near"); + near.promiseBatchActionCreateAccount(promiseId); + near.promiseBatchActionTransfer(promiseId, 10000000000000000000000000n); + near.promiseBatchActionAddKeyWithFullAccess(promiseId, public_key, 1n); + near.promiseReturn(promiseId); } export function test_add_signer_key() { - runtime_validate_public_key('aa', near.signerAccountPk()) + runtime_validate_public_key("aa", near.signerAccountPk()); } export function test_add_ed25519_key_bytes() { - let pk = new PublicKey(bytes(new Uint8Array([ + let pk = new PublicKey( + bytes( + new Uint8Array([ // CurveType.ED25519 = 0 0, // ED25519 PublicKey data - 186, 44, 216, 49, 157, 48, 151, 47, - 23, 244, 137, 69, 78, 150, 54, 42, - 30, 248, 110, 26, 205, 18, 137, 154, - 10, 208, 26, 183, 65, 166, 223, 18 - ]))) - runtime_validate_public_key('a', pk.data) + 186, 44, 216, 49, 157, 48, 151, 47, 23, 244, 137, 69, 78, 150, 54, 42, + 30, 248, 110, 26, 205, 18, 137, 154, 10, 208, 26, 183, 65, 166, 223, 18, + ]) + ) + ); + runtime_validate_public_key("a", pk.data); } export function test_add_ed25519_key_string() { - let k = 'ed25519:DXkVZkHd7WUUejCK7i74uAoZWy1w9AZqshhTHxhmqHuB' - let pk = PublicKey.fromString(k) - runtime_validate_public_key('b', pk.data) + let k = "ed25519:DXkVZkHd7WUUejCK7i74uAoZWy1w9AZqshhTHxhmqHuB"; + let pk = PublicKey.fromString(k); + runtime_validate_public_key("b", pk.data); } export function test_add_secp256k1_key_bytes() { - let pk = new PublicKey(bytes(new Uint8Array([ - // CurveType.SECP256K1 = 1 - 1, - // SECP256K1 PublicKey data - 242, 86, 198, 230, 200, 11, 33, 63, 42, 160, 176, - 23, 68, 35, 93, 81, 92, 89, 68, 53, 190, 101, - 27, 21, 136, 58, 16, 221, 71, 47, 166, 70, 206, - 98, 234, 243, 103, 13, 197, 203, 145, 0, 160, 202, - 42, 85, 178, 193, 71, 193, 233, 163, 140, 228, 40, - 135, 142, 125, 70, 225, 251, 113, 74, 153 - ] - ))) - runtime_validate_public_key('c', pk.data) + let pk = new PublicKey( + bytes( + new Uint8Array([ + // CurveType.SECP256K1 = 1 + 1, + // SECP256K1 PublicKey data + 242, 86, 198, 230, 200, 11, 33, 63, 42, 160, 176, 23, 68, 35, 93, 81, + 92, 89, 68, 53, 190, 101, 27, 21, 136, 58, 16, 221, 71, 47, 166, 70, + 206, 98, 234, 243, 103, 13, 197, 203, 145, 0, 160, 202, 42, 85, 178, + 193, 71, 193, 233, 163, 140, 228, 40, 135, 142, 125, 70, 225, 251, 113, + 74, 153, + ]) + ) + ); + runtime_validate_public_key("c", pk.data); } export function test_add_secp256k1_key_string() { - let k = 'secp256k1:5r22SrjrDvgY3wdQsnjgxkeAbU1VcM71FYvALEQWihjM3Xk4Be1CpETTqFccChQr4iJwDroSDVmgaWZv2AcXvYeL' - let pk = PublicKey.fromString(k) - runtime_validate_public_key('d', pk.data) + let k = + "secp256k1:5r22SrjrDvgY3wdQsnjgxkeAbU1VcM71FYvALEQWihjM3Xk4Be1CpETTqFccChQr4iJwDroSDVmgaWZv2AcXvYeL"; + let pk = PublicKey.fromString(k); + runtime_validate_public_key("d", pk.data); } export function add_invalid_public_key() { - runtime_validate_public_key('e', bytes(new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]))) + runtime_validate_public_key( + "e", + bytes(new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])) + ); } export function curve_type() { - assert(new PublicKey(near.signerAccountPk()).curveType() == CurveType.ED25519) + assert( + new PublicKey(near.signerAccountPk()).curveType() == CurveType.ED25519 + ); } export function create_invalid_curve_type() { - new PublicKey(bytes(new Uint8Array([2, 1]))) + new PublicKey(bytes(new Uint8Array([2, 1]))); } export function create_invalid_length() { - new PublicKey(bytes(new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]))) + new PublicKey(bytes(new Uint8Array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9]))); } export function create_from_invalid_base58() { - PublicKey.fromString('ed25519:!@#$%^&*') -} \ No newline at end of file + PublicKey.fromString("ed25519:!@#$%^&*"); +} diff --git a/tests/src/storage_api.js b/tests/src/storage_api.js index 38f80837f..238257e83 100644 --- a/tests/src/storage_api.js +++ b/tests/src/storage_api.js @@ -1,23 +1,25 @@ -import {near, bytes} from 'near-sdk-js' +import { near, bytes } from "near-sdk-js"; export function test_storage_write() { - near.valueReturn(near.storageWrite(bytes("\x00tesdsst\xff"), bytes("\x00\x01\xff"))) + near.valueReturn( + near.storageWrite(bytes("\x00tesdsst\xff"), bytes("\x00\x01\xff")) + ); } export function test_storage_read() { - near.valueReturn(near.storageRead(bytes("\x00tesdsst\xff"))) + near.valueReturn(near.storageRead(bytes("\x00tesdsst\xff"))); } export function test_storage_remove() { - near.valueReturn(near.storageRemove(bytes("\x00tesdsst\xff"))) + near.valueReturn(near.storageRemove(bytes("\x00tesdsst\xff"))); } export function test_storage_has_key() { - near.valueReturn(near.storageHasKey(bytes("\x00tesdsst\xff"))) + near.valueReturn(near.storageHasKey(bytes("\x00tesdsst\xff"))); } export function test_storage_get_evicted() { - near.storageWrite(bytes("\x00tesdsst\xff"), bytes("\x00\x01\xff")) - near.storageWrite(bytes("\x00tesdsst\xff"), bytes("\x03\x01\xee")) - near.valueReturn(near.storageGetEvicted()) + near.storageWrite(bytes("\x00tesdsst\xff"), bytes("\x00\x01\xff")); + near.storageWrite(bytes("\x00tesdsst\xff"), bytes("\x03\x01\xee")); + near.valueReturn(near.storageGetEvicted()); } diff --git a/tests/src/typescript.ts b/tests/src/typescript.ts index f9478cace..b0347a53c 100644 --- a/tests/src/typescript.ts +++ b/tests/src/typescript.ts @@ -1,13 +1,10 @@ -import { - NearBindgen, - view, -} from 'near-sdk-js' +import { NearBindgen, view } from "near-sdk-js"; @NearBindgen({}) class TypeScriptTestContract { - @view({}) - bigint() { - // JSON.stringify cannot seriaize a BigInt, need manually toString - return (1n + 2n).toString() - } -} \ No newline at end of file + @view({}) + bigint() { + // JSON.stringify cannot seriaize a BigInt, need manually toString + return (1n + 2n).toString(); + } +} diff --git a/tests/src/unordered-map.js b/tests/src/unordered-map.js index 444e1e5da..b4528816e 100644 --- a/tests/src/unordered-map.js +++ b/tests/src/unordered-map.js @@ -1,68 +1,73 @@ -import { - NearBindgen, - call, - view, - UnorderedMap, - near, -} from 'near-sdk-js' -import { House, Room } from './model.js'; +import { NearBindgen, call, view, UnorderedMap, near } from "near-sdk-js"; +import { House, Room } from "./model.js"; @NearBindgen({}) class UnorderedMapTestContract { - constructor() { - this.unorderedMap = new UnorderedMap('a'); - } + constructor() { + this.unorderedMap = new UnorderedMap("a"); + } - @view({}) - len() { - return this.unorderedMap.length; - } + @view({}) + len() { + return this.unorderedMap.length; + } - @view({}) - isEmpty() { - return this.unorderedMap.isEmpty(); - } + @view({}) + isEmpty() { + return this.unorderedMap.isEmpty(); + } - @view({}) - get({ key }) { - return this.unorderedMap.get(key); - } + @view({}) + get({ key }) { + return this.unorderedMap.get(key); + } - @call({}) - set({ key, value }) { - this.unorderedMap.set(key, value); - } + @call({}) + set({ key, value }) { + this.unorderedMap.set(key, value); + } - @call({}) - remove_key({ key }) { - this.unorderedMap.remove(key); - } + @call({}) + remove_key({ key }) { + this.unorderedMap.remove(key); + } - @call({}) - clear() { - this.unorderedMap.clear(); - } + @call({}) + clear() { + this.unorderedMap.clear(); + } - @view({}) - toArray() { - return this.unorderedMap.toArray(); - } + @view({}) + toArray() { + return this.unorderedMap.toArray(); + } - @call({}) - extend({ kvs }) { - this.unorderedMap.extend(kvs); - } + @call({}) + extend({ kvs }) { + this.unorderedMap.extend(kvs); + } - @call({}) - add_house() { - this.unorderedMap.set('house1', new House('house1', [new Room('room1', '200sqft'), new Room('room2', '300sqft')])) - } + @call({}) + add_house() { + this.unorderedMap.set( + "house1", + new House("house1", [ + new Room("room1", "200sqft"), + new Room("room2", "300sqft"), + ]) + ); + } - @view({}) - get_house() { - const house = this.unorderedMap.get('house1', {reconstructor: (rawHouse) => new House(rawHouse.name, rawHouse.rooms.map((rawRoom) => new Room(rawRoom.name, rawRoom.size)))}) - const room = house.rooms[0] - return house.describe() + room.describe() - } + @view({}) + get_house() { + const house = this.unorderedMap.get("house1", { + reconstructor: (rawHouse) => + new House( + rawHouse.name, + rawHouse.rooms.map((rawRoom) => new Room(rawRoom.name, rawRoom.size)) + ), + }); + const room = house.rooms[0]; + return house.describe() + room.describe(); + } } - diff --git a/tests/src/unordered-set.js b/tests/src/unordered-set.js index b7500c111..4392fff50 100644 --- a/tests/src/unordered-set.js +++ b/tests/src/unordered-set.js @@ -1,74 +1,68 @@ -import { - NearBindgen, - call, - view, - UnorderedSet, -} from 'near-sdk-js' -import { House, Room } from './model.js'; +import { NearBindgen, call, view, UnorderedSet } from "near-sdk-js"; +import { House, Room } from "./model.js"; @NearBindgen({}) class UnorderedSetTestContract { - constructor() { - this.unorderedSet = new UnorderedSet('a'); - } + constructor() { + this.unorderedSet = new UnorderedSet("a"); + } - @view({}) - len() { - return this.unorderedSet.length; - } + @view({}) + len() { + return this.unorderedSet.length; + } - @view({}) - isEmpty() { - return this.unorderedSet.isEmpty(); - } + @view({}) + isEmpty() { + return this.unorderedSet.isEmpty(); + } - @view({}) - contains({ element }) { - return this.unorderedSet.contains(element); - } + @view({}) + contains({ element }) { + return this.unorderedSet.contains(element); + } - @call({}) - set({ element }) { - this.unorderedSet.set(element); - } + @call({}) + set({ element }) { + this.unorderedSet.set(element); + } - @call({}) - remove_key({ element }) { - this.unorderedSet.remove(element); - } + @call({}) + remove_key({ element }) { + this.unorderedSet.remove(element); + } - @call({}) - clear() { - this.unorderedSet.clear(); - } + @call({}) + clear() { + this.unorderedSet.clear(); + } - @view({}) - toArray() { - const res = this.unorderedSet.toArray(); - return res; - } + @view({}) + toArray() { + const res = this.unorderedSet.toArray(); + return res; + } - @call({}) - extend({ elements }) { - this.unorderedSet.extend(elements); - } + @call({}) + extend({ elements }) { + this.unorderedSet.extend(elements); + } - @call({}) - add_house({ name, rooms }) { - let house = new House(name, []) - for (let r of rooms) { - house.rooms.push(new Room(r.name, r.size)) - } - this.unorderedSet.set(house) + @call({}) + add_house({ name, rooms }) { + let house = new House(name, []); + for (let r of rooms) { + house.rooms.push(new Room(r.name, r.size)); } + this.unorderedSet.set(house); + } - @view({}) - house_exist({ name, rooms }) { - let house = new House(name, []) - for (let r of rooms) { - house.rooms.push(new Room(r.name, r.size)) - } - return this.unorderedSet.contains(house) + @view({}) + house_exist({ name, rooms }) { + let house = new House(name, []); + for (let r of rooms) { + house.rooms.push(new Room(r.name, r.size)); } + return this.unorderedSet.contains(house); + } } - diff --git a/tests/src/vector.js b/tests/src/vector.js index ef1570554..b46b94315 100644 --- a/tests/src/vector.js +++ b/tests/src/vector.js @@ -1,75 +1,74 @@ -import { - NearBindgen, - call, - view, - Vector -} from 'near-sdk-js' -import {House, Room} from './model.js'; +import { NearBindgen, call, view, Vector } from "near-sdk-js"; +import { House, Room } from "./model.js"; @NearBindgen({}) class VectorTestContract { - constructor() { - this.vector = new Vector('a'); - } + constructor() { + this.vector = new Vector("a"); + } - @view({}) - len() { - return this.vector.length; - } + @view({}) + len() { + return this.vector.length; + } - @view({}) - isEmpty() { - return this.vector.isEmpty(); - } + @view({}) + isEmpty() { + return this.vector.isEmpty(); + } - @view({}) - get({index}) { - return this.vector.get(index); - } + @view({}) + get({ index }) { + return this.vector.get(index); + } - @call({}) - push({value}) { - this.vector.push(value); - } + @call({}) + push({ value }) { + this.vector.push(value); + } - @call({}) - pop() { - this.vector.pop(); - } + @call({}) + pop() { + this.vector.pop(); + } - @call({}) - clear() { - this.vector.clear(); - } + @call({}) + clear() { + this.vector.clear(); + } - @view({}) - toArray() { - return this.vector.toArray(); - } + @view({}) + toArray() { + return this.vector.toArray(); + } - @call({}) - extend({kvs}) { - this.vector.extend(kvs); - } + @call({}) + extend({ kvs }) { + this.vector.extend(kvs); + } - @call({}) - replace({index, value}) { - this.vector.replace(index, value); - } + @call({}) + replace({ index, value }) { + this.vector.replace(index, value); + } - @call({}) - swapRemove({index}) { - this.vector.swapRemove(index); - } + @call({}) + swapRemove({ index }) { + this.vector.swapRemove(index); + } - @call({}) - add_house() { - this.vector.push(new House('house1', [new Room('room1', '200sqft'), new Room('room2', '300sqft')])); - } + @call({}) + add_house() { + this.vector.push( + new House("house1", [ + new Room("room1", "200sqft"), + new Room("room2", "300sqft"), + ]) + ); + } - @view({}) - get_house() { - return this.vector.get(0); - } + @view({}) + get_house() { + return this.vector.get(0); + } } - diff --git a/tests/tsconfig.json b/tests/tsconfig.json index 34d7bd188..1b0512668 100644 --- a/tests/tsconfig.json +++ b/tests/tsconfig.json @@ -1,10 +1,9 @@ { - "compilerOptions": { - "experimentalDecorators": true, - "target": "es2020", - "noEmit": true - }, - "exclude": [ - "node_modules" - ], -} \ No newline at end of file + "compilerOptions": { + "moduleResolution": "node", + "experimentalDecorators": true, + "target": "es2020", + "noEmit": true + }, + "exclude": ["node_modules"] +} diff --git a/tsconfig.json b/tsconfig.json index 5c55b069b..0ac6bfdeb 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,32 +1,28 @@ { - "compilerOptions": { - "esModuleInterop": true, - "lib": [ - "es2015", - "esnext", - "dom" - ], - "module": "esnext", - "target": "es2020", - "moduleResolution": "node", - "alwaysStrict": true, - "outDir": "./lib", - "declaration": true, - "preserveSymlinks": true, - "preserveWatchOutput": true, - "pretty": false, - "forceConsistentCasingInFileNames": true, - "noFallthroughCasesInSwitch": true, - "noImplicitAny": false, - "noImplicitReturns": true, - "noUnusedLocals": true, - "experimentalDecorators": true, - "resolveJsonModule": true, - "allowJs": true, - }, - "files": [ - "src/index.ts", - "src/build-tools/near-bindgen-exporter.js", - "src/build-tools/include-bytes.js", - ] -} \ No newline at end of file + "compilerOptions": { + "esModuleInterop": true, + "lib": ["es2015", "esnext", "dom"], + "module": "esnext", + "target": "es2020", + "moduleResolution": "node", + "alwaysStrict": true, + "outDir": "./lib", + "declaration": true, + "preserveSymlinks": true, + "preserveWatchOutput": true, + "pretty": false, + "forceConsistentCasingInFileNames": true, + "noFallthroughCasesInSwitch": true, + "noImplicitAny": false, + "noImplicitReturns": true, + "noUnusedLocals": true, + "experimentalDecorators": true, + "resolveJsonModule": true, + "allowJs": true + }, + "files": [ + "src/index.ts", + "src/build-tools/near-bindgen-exporter.js", + "src/build-tools/include-bytes.js" + ] +} diff --git a/yarn.lock b/yarn.lock index f331fc3d3..def95a287 100644 --- a/yarn.lock +++ b/yarn.lock @@ -429,6 +429,45 @@ "@babel/helper-validator-identifier" "^7.18.6" to-fast-properties "^2.0.0" +"@eslint/eslintrc@^1.3.2": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-1.3.2.tgz#58b69582f3b7271d8fa67fe5251767a5b38ea356" + integrity sha512-AXYd23w1S/bv3fTs3Lz0vjiYemS08jWkI3hYyS9I1ry+0f+Yjs1wm+sU0BS8qDOPrBIkp4qHYC16I8uVtpLajQ== + dependencies: + ajv "^6.12.4" + debug "^4.3.2" + espree "^9.4.0" + globals "^13.15.0" + ignore "^5.2.0" + import-fresh "^3.2.1" + js-yaml "^4.1.0" + minimatch "^3.1.2" + strip-json-comments "^3.1.1" + +"@humanwhocodes/config-array@^0.10.4": + version "0.10.4" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.10.4.tgz#01e7366e57d2ad104feea63e72248f22015c520c" + integrity sha512-mXAIHxZT3Vcpg83opl1wGlVZ9xydbfZO3r5YfRSH6Gpp2J/PfdBP0wbDa2sO6/qRbcalpoevVyW6A/fI6LfeMw== + dependencies: + "@humanwhocodes/object-schema" "^1.2.1" + debug "^4.1.1" + minimatch "^3.0.4" + +"@humanwhocodes/gitignore-to-minimatch@^1.0.2": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@humanwhocodes/gitignore-to-minimatch/-/gitignore-to-minimatch-1.0.2.tgz#316b0a63b91c10e53f242efb4ace5c3b34e8728d" + integrity sha512-rSqmMJDdLFUsyxR6FMtD00nfQKKLFb1kv+qBbOVKqErvloEIJLo5bDTJTQNTYgeyp78JsA7u/NPi5jT1GR/MuA== + +"@humanwhocodes/module-importer@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" + integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== + +"@humanwhocodes/object-schema@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz#b520529ec21d8e5945a1851dfd1c32e94e39ff45" + integrity sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA== + "@jridgewell/gen-mapping@^0.1.0": version "0.1.1" resolved "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz" @@ -483,6 +522,27 @@ "@jridgewell/resolve-uri" "^3.0.3" "@jridgewell/sourcemap-codec" "^1.4.10" +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + "@rollup/plugin-babel@^5.3.1": version "5.3.1" resolved "https://registry.npmjs.org/@rollup/plugin-babel/-/plugin-babel-5.3.1.tgz" @@ -543,6 +603,11 @@ resolved "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz" integrity sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw== +"@types/json-schema@^7.0.9": + version "7.0.11" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" + integrity sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ== + "@types/node@*": version "17.0.34" resolved "https://registry.npmjs.org/@types/node/-/node-17.0.34.tgz" @@ -567,6 +632,107 @@ dependencies: rollup "*" +"@typescript-eslint/eslint-plugin@^5.37.0": + version "5.37.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.37.0.tgz#5ccdd5d9004120f28fc6e717fb4b5c9bddcfbc04" + integrity sha512-Fde6W0IafXktz1UlnhGkrrmnnGpAo1kyX7dnyHHVrmwJOn72Oqm3eYtddrpOwwel2W8PAK9F3pIL5S+lfoM0og== + dependencies: + "@typescript-eslint/scope-manager" "5.37.0" + "@typescript-eslint/type-utils" "5.37.0" + "@typescript-eslint/utils" "5.37.0" + debug "^4.3.4" + functional-red-black-tree "^1.0.1" + ignore "^5.2.0" + regexpp "^3.2.0" + semver "^7.3.7" + tsutils "^3.21.0" + +"@typescript-eslint/parser@^5.37.0": + version "5.37.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-5.37.0.tgz#c382077973f3a4ede7453fb14cadcad3970cbf3b" + integrity sha512-01VzI/ipYKuaG5PkE5+qyJ6m02fVALmMPY3Qq5BHflDx3y4VobbLdHQkSMg9VPRS4KdNt4oYTMaomFoHonBGAw== + dependencies: + "@typescript-eslint/scope-manager" "5.37.0" + "@typescript-eslint/types" "5.37.0" + "@typescript-eslint/typescript-estree" "5.37.0" + debug "^4.3.4" + +"@typescript-eslint/scope-manager@5.37.0": + version "5.37.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.37.0.tgz#044980e4f1516a774a418dafe701a483a6c9f9ca" + integrity sha512-F67MqrmSXGd/eZnujjtkPgBQzgespu/iCZ+54Ok9X5tALb9L2v3G+QBSoWkXG0p3lcTJsL+iXz5eLUEdSiJU9Q== + dependencies: + "@typescript-eslint/types" "5.37.0" + "@typescript-eslint/visitor-keys" "5.37.0" + +"@typescript-eslint/type-utils@5.37.0": + version "5.37.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-5.37.0.tgz#43ed2f567ada49d7e33a6e4b6f9babd060445fe5" + integrity sha512-BSx/O0Z0SXOF5tY0bNTBcDEKz2Ec20GVYvq/H/XNKiUorUFilH7NPbFUuiiyzWaSdN3PA8JV0OvYx0gH/5aFAQ== + dependencies: + "@typescript-eslint/typescript-estree" "5.37.0" + "@typescript-eslint/utils" "5.37.0" + debug "^4.3.4" + tsutils "^3.21.0" + +"@typescript-eslint/types@5.37.0": + version "5.37.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.37.0.tgz#09e4870a5f3af7af3f84e08d792644a87d232261" + integrity sha512-3frIJiTa5+tCb2iqR/bf7XwU20lnU05r/sgPJnRpwvfZaqCJBrl8Q/mw9vr3NrNdB/XtVyMA0eppRMMBqdJ1bA== + +"@typescript-eslint/typescript-estree@5.37.0": + version "5.37.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.37.0.tgz#956dcf5c98363bcb97bdd5463a0a86072ff79355" + integrity sha512-JkFoFIt/cx59iqEDSgIGnQpCTRv96MQnXCYvJi7QhBC24uyuzbD8wVbajMB1b9x4I0octYFJ3OwjAwNqk1AjDA== + dependencies: + "@typescript-eslint/types" "5.37.0" + "@typescript-eslint/visitor-keys" "5.37.0" + debug "^4.3.4" + globby "^11.1.0" + is-glob "^4.0.3" + semver "^7.3.7" + tsutils "^3.21.0" + +"@typescript-eslint/utils@5.37.0": + version "5.37.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.37.0.tgz#7784cb8e91390c4f90ccaffd24a0cf9874df81b2" + integrity sha512-jUEJoQrWbZhmikbcWSMDuUSxEE7ID2W/QCV/uz10WtQqfOuKZUqFGjqLJ+qhDd17rjgp+QJPqTdPIBWwoob2NQ== + dependencies: + "@types/json-schema" "^7.0.9" + "@typescript-eslint/scope-manager" "5.37.0" + "@typescript-eslint/types" "5.37.0" + "@typescript-eslint/typescript-estree" "5.37.0" + eslint-scope "^5.1.1" + eslint-utils "^3.0.0" + +"@typescript-eslint/visitor-keys@5.37.0": + version "5.37.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.37.0.tgz#7b72dd343295ea11e89b624995abc7103c554eee" + integrity sha512-Hp7rT4cENBPIzMwrlehLW/28EVCOcE9U1Z1BQTc8EA8v5qpr7GRGuG+U58V5tTY48zvUOA3KHvw3rA8tY9fbdA== + dependencies: + "@typescript-eslint/types" "5.37.0" + eslint-visitor-keys "^3.3.0" + +acorn-jsx@^5.3.2: + version "5.3.2" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== + +acorn@^8.8.0: + version "8.8.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.0.tgz#88c0187620435c7f6015803f5539dae05a9dbea8" + integrity sha512-QOxyigPVrpZ2GXT+PFyZTl6TtOFc5egxHIP9IlQ+RbupQuX4RkT/Bee4/kQuC02Xkzg84JcT7oLYtDIQxp+v7w== + +ajv@^6.10.0, ajv@^6.12.4: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + dependencies: + fast-deep-equal "^3.1.1" + fast-json-stable-stringify "^2.0.0" + json-schema-traverse "^0.4.1" + uri-js "^4.2.2" + ansi-regex@^5.0.1: version "5.0.1" resolved "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz" @@ -579,13 +745,23 @@ ansi-styles@^3.2.1: dependencies: color-convert "^1.9.0" -ansi-styles@^4.0.0: +ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.3.0" resolved "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz" integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== dependencies: color-convert "^2.0.1" +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + atob@^2.1.2: version "2.1.2" resolved "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz" @@ -604,6 +780,13 @@ brace-expansion@^1.1.7: balanced-match "^1.0.0" concat-map "0.0.1" +braces@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + browserslist@^4.20.2: version "4.20.3" resolved "https://registry.npmjs.org/browserslist/-/browserslist-4.20.3.tgz" @@ -620,6 +803,11 @@ builtin-modules@^3.0.0: resolved "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz" integrity sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw== +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + caniuse-lite@^1.0.30001332: version "1.0.30001339" resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001339.tgz" @@ -634,6 +822,14 @@ chalk@^2.0.0: escape-string-regexp "^1.0.5" supports-color "^5.3.0" +chalk@^4.0.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + charcodes@^0.2.0: version "0.2.0" resolved "https://registry.npmjs.org/charcodes/-/charcodes-0.2.0.tgz" @@ -689,7 +885,16 @@ convert-source-map@^1.7.0: dependencies: safe-buffer "~5.1.1" -debug@^4.1.0: +cross-spawn@^7.0.2: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.4: version "4.3.4" resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -701,11 +906,30 @@ decode-uri-component@^0.2.0: resolved "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.0.tgz" integrity sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU= +deep-is@^0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== + deepmerge@^4.2.2: version "4.2.2" resolved "https://registry.npmjs.org/deepmerge/-/deepmerge-4.2.2.tgz" integrity sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg== +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + +doctrine@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== + dependencies: + esutils "^2.0.2" + electron-to-chromium@^1.4.118: version "1.4.137" resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.137.tgz" @@ -726,6 +950,127 @@ escape-string-regexp@^1.0.5: resolved "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz" integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +eslint-config-prettier@^8.5.0: + version "8.5.0" + resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.5.0.tgz#5a81680ec934beca02c7b1a61cf8ca34b66feab1" + integrity sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q== + +eslint-scope@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== + dependencies: + esrecurse "^4.3.0" + estraverse "^4.1.1" + +eslint-scope@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.1.1.tgz#fff34894c2f65e5226d3041ac480b4513a163642" + integrity sha512-QKQM/UXpIiHcLqJ5AOyIW7XZmzjkzQXYE54n1++wb0u9V/abW3l9uQnxX8Z5Xd18xyKIMTUAyQ0k1e8pz6LUrw== + dependencies: + esrecurse "^4.3.0" + estraverse "^5.2.0" + +eslint-utils@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/eslint-utils/-/eslint-utils-3.0.0.tgz#8aebaface7345bb33559db0a1f13a1d2d48c3672" + integrity sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA== + dependencies: + eslint-visitor-keys "^2.0.0" + +eslint-visitor-keys@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz#f65328259305927392c938ed44eb0a5c9b2bd303" + integrity sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw== + +eslint-visitor-keys@^3.3.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.3.0.tgz#f6480fa6b1f30efe2d1968aa8ac745b862469826" + integrity sha512-mQ+suqKJVyeuwGYHAdjMFqjCyfl8+Ldnxuyp3ldiMBFKkvytrXUZWaiPCEav8qDHKty44bD+qV1IP4T+w+xXRA== + +eslint@^8.23.1: + version "8.23.1" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.23.1.tgz#cfd7b3f7fdd07db8d16b4ac0516a29c8d8dca5dc" + integrity sha512-w7C1IXCc6fNqjpuYd0yPlcTKKmHlHHktRkzmBPZ+7cvNBQuiNjx0xaMTjAJGCafJhQkrFJooREv0CtrVzmHwqg== + dependencies: + "@eslint/eslintrc" "^1.3.2" + "@humanwhocodes/config-array" "^0.10.4" + "@humanwhocodes/gitignore-to-minimatch" "^1.0.2" + "@humanwhocodes/module-importer" "^1.0.1" + ajv "^6.10.0" + chalk "^4.0.0" + cross-spawn "^7.0.2" + debug "^4.3.2" + doctrine "^3.0.0" + escape-string-regexp "^4.0.0" + eslint-scope "^7.1.1" + eslint-utils "^3.0.0" + eslint-visitor-keys "^3.3.0" + espree "^9.4.0" + esquery "^1.4.0" + esutils "^2.0.2" + fast-deep-equal "^3.1.3" + file-entry-cache "^6.0.1" + find-up "^5.0.0" + glob-parent "^6.0.1" + globals "^13.15.0" + globby "^11.1.0" + grapheme-splitter "^1.0.4" + ignore "^5.2.0" + import-fresh "^3.0.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + js-sdsl "^4.1.4" + js-yaml "^4.1.0" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.4.1" + lodash.merge "^4.6.2" + minimatch "^3.1.2" + natural-compare "^1.4.0" + optionator "^0.9.1" + regexpp "^3.2.0" + strip-ansi "^6.0.1" + strip-json-comments "^3.1.0" + text-table "^0.2.0" + +espree@^9.4.0: + version "9.4.0" + resolved "https://registry.yarnpkg.com/espree/-/espree-9.4.0.tgz#cd4bc3d6e9336c433265fc0aa016fc1aaf182f8a" + integrity sha512-DQmnRpLj7f6TgN/NYb0MTzJXL+vJF9h3pHy4JhCIs3zwcgez8xmGg3sXHcEO97BrmO2OSvCwMdfdlyl+E9KjOw== + dependencies: + acorn "^8.8.0" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^3.3.0" + +esquery@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.4.0.tgz#2148ffc38b82e8c7057dfed48425b3e61f0f24a5" + integrity sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w== + dependencies: + estraverse "^5.1.0" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +estraverse@^5.1.0, estraverse@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + estree-walker@^1.0.1: version "1.0.1" resolved "https://registry.npmjs.org/estree-walker/-/estree-walker-1.0.1.tgz" @@ -736,6 +1081,79 @@ estree-walker@^2.0.1: resolved "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz" integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w== +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-glob@^3.2.9: + version "3.2.12" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80" + integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.4" + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fast-levenshtein@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== + +fastq@^1.6.0: + version "1.13.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.13.0.tgz#616760f88a7526bdfc596b7cab8c18938c36b98c" + integrity sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw== + dependencies: + reusify "^1.0.4" + +file-entry-cache@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" + integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== + dependencies: + flat-cache "^3.0.4" + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +flat-cache@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" + integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== + dependencies: + flatted "^3.1.0" + rimraf "^3.0.2" + +flatted@^3.1.0: + version "3.2.7" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787" + integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ== + fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz" @@ -751,6 +1169,11 @@ function-bind@^1.1.1: resolved "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== +functional-red-black-tree@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz#1b0ab3bd553b2a0d6399d29c0e3ea0b252078327" + integrity sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g== + gensync@^1.0.0-beta.2: version "1.0.0-beta.2" resolved "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz" @@ -761,7 +1184,21 @@ get-caller-file@^2.0.5: resolved "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== -glob@^7.1.6: +glob-parent@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob-parent@^6.0.1: + version "6.0.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" + integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== + dependencies: + is-glob "^4.0.3" + +glob@^7.1.3, glob@^7.1.6: version "7.2.3" resolved "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz" integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== @@ -778,11 +1215,40 @@ globals@^11.1.0: resolved "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== +globals@^13.15.0: + version "13.17.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.17.0.tgz#902eb1e680a41da93945adbdcb5a9f361ba69bd4" + integrity sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw== + dependencies: + type-fest "^0.20.2" + +globby@^11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" + integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== + dependencies: + array-union "^2.1.0" + dir-glob "^3.0.1" + fast-glob "^3.2.9" + ignore "^5.2.0" + merge2 "^1.4.1" + slash "^3.0.0" + +grapheme-splitter@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/grapheme-splitter/-/grapheme-splitter-1.0.4.tgz#9cf3a665c6247479896834af35cf1dbb4400767e" + integrity sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ== + has-flag@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz" integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + has@^1.0.3: version "1.0.3" resolved "https://registry.npmjs.org/has/-/has-1.0.3.tgz" @@ -790,6 +1256,24 @@ has@^1.0.3: dependencies: function-bind "^1.1.1" +ignore@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.0.tgz#6d3bac8fa7fe0d45d9f9be7bac2fc279577e345a" + integrity sha512-CmxgYGiEPCLhfLnpPp1MoRmifwEIOgjcHXxOBjv7mY96c+eWScsOP9c112ZyLdWHi0FxHjI+4uVhKYp/gcdRmQ== + +import-fresh@^3.0.0, import-fresh@^3.2.1: + version "3.3.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== + inflight@^1.0.4: version "1.0.6" resolved "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz" @@ -817,16 +1301,33 @@ is-core-module@^2.8.1: dependencies: has "^1.0.3" +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + is-fullwidth-code-point@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + is-module@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz" integrity sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE= +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + is-reference@^1.2.1: version "1.2.1" resolved "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz" @@ -834,21 +1335,75 @@ is-reference@^1.2.1: dependencies: "@types/estree" "*" +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +js-sdsl@^4.1.4: + version "4.1.4" + resolved "https://registry.yarnpkg.com/js-sdsl/-/js-sdsl-4.1.4.tgz#78793c90f80e8430b7d8dc94515b6c77d98a26a6" + integrity sha512-Y2/yD55y5jteOAmY50JbUZYwk3CP3wnLPEZnlR1w9oKhITrBEtAxwuWKebFf8hMrPMgbYwFoWK/lH2sBkErELw== + js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== +js-yaml@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + jsesc@^2.5.1: version "2.5.2" resolved "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz" integrity sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA== +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== + json5@^2.2.1: version "2.2.1" resolved "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz" integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA== +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +lodash.merge@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + magic-string@^0.25.7: version "0.25.9" resolved "https://registry.npmjs.org/magic-string/-/magic-string-0.25.9.tgz" @@ -856,7 +1411,20 @@ magic-string@^0.25.7: dependencies: sourcemap-codec "^1.4.8" -minimatch@^3.1.1: +merge2@^1.3.0, merge2@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +micromatch@^4.0.4: + version "4.0.5" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" + integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== + dependencies: + braces "^3.0.2" + picomatch "^2.3.1" + +minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2: version "3.1.2" resolved "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz" integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== @@ -868,6 +1436,11 @@ ms@2.1.2: resolved "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz" integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== + node-releases@^2.0.3: version "2.0.4" resolved "https://registry.npmjs.org/node-releases/-/node-releases-2.0.4.tgz" @@ -880,31 +1453,109 @@ once@^1.3.0: dependencies: wrappy "1" +optionator@^0.9.1: + version "0.9.1" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.1.tgz#4f236a6373dae0566a6d43e1326674f50c291499" + integrity sha512-74RlY5FCnhq4jRxVUPKDaRwrVNXMqsGsiW6AJw4XK8hmtm10wC0ypZBLw5IIp85NZMr91+qd1RvvENwg7jjRFw== + dependencies: + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + word-wrap "^1.2.3" + +p-limit@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + path-is-absolute@^1.0.0: version "1.0.1" resolved "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz" integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + path-parse@^1.0.7: version "1.0.7" resolved "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz" integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + picocolors@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz" integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== -picomatch@^2.2.2: +picomatch@^2.2.2, picomatch@^2.3.1: version "2.3.1" resolved "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + +prettier@^2.7.1: + version "2.7.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.7.1.tgz#e235806850d057f97bb08368a4f7d899f7760c64" + integrity sha512-ujppO+MkdPqoVINuDFDRLClm7D78qbDt0/NR+wp5FqEZOoTNAjPHWj17QRhu7geIHJfcNhRk1XVQmF8Bp3ye+g== + +punycode@^2.1.0: + version "2.1.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" + integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +regexpp@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/regexpp/-/regexpp-3.2.0.tgz#0425a2768d8f23bad70ca4b90461fa2f1213e1b2" + integrity sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg== + require-directory@^2.1.1: version "2.1.1" resolved "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz" integrity sha1-jGStX9MNqxyXbiNE/+f3kqam30I= +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + resolve@^1.17.0, resolve@^1.19.0: version "1.22.0" resolved "https://registry.npmjs.org/resolve/-/resolve-1.22.0.tgz" @@ -914,6 +1565,18 @@ resolve@^1.17.0, resolve@^1.19.0: path-parse "^1.0.7" supports-preserve-symlinks-flag "^1.0.0" +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + rollup-plugin-sourcemaps@^0.6.3: version "0.6.3" resolved "https://registry.npmjs.org/rollup-plugin-sourcemaps/-/rollup-plugin-sourcemaps-0.6.3.tgz" @@ -936,6 +1599,13 @@ rollup@^2.61.1: optionalDependencies: fsevents "~2.3.2" +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + safe-buffer@~5.1.1: version "5.1.2" resolved "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz" @@ -946,6 +1616,30 @@ semver@^6.3.0: resolved "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz" integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== +semver@^7.3.7: + version "7.3.7" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.7.tgz#12c5b649afdbf9049707796e22a4028814ce523f" + integrity sha512-QlYTucUYOews+WeEujDoEGziz4K6c47V/Bd+LjSSYcA94p+DmINdf7ncaUinThfvZyu13lN9OY1XDxt8C0Tw0g== + dependencies: + lru-cache "^6.0.0" + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + source-map-resolve@^0.6.0: version "0.6.0" resolved "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.6.0.tgz" @@ -975,6 +1669,11 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1: dependencies: ansi-regex "^5.0.1" +strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + supports-color@^5.3.0: version "5.5.0" resolved "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz" @@ -982,21 +1681,83 @@ supports-color@^5.3.0: dependencies: has-flag "^3.0.0" +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + supports-preserve-symlinks-flag@^1.0.0: version "1.0.0" resolved "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz" integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== + to-fast-properties@^2.0.0: version "2.0.0" resolved "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz" integrity sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4= +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +tslib@^1.8.1: + version "1.14.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== + +tsutils@^3.21.0: + version "3.21.0" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" + integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== + dependencies: + tslib "^1.8.1" + +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + +type-fest@^0.20.2: + version "0.20.2" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" + integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== + typescript@^4.7.2: version "4.7.4" resolved "https://registry.npmjs.org/typescript/-/typescript-4.7.4.tgz#1a88596d1cf47d59507a1bcdfb5b9dfe4d488235" integrity sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ== +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +word-wrap@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.3.tgz#610636f6b1f703891bd34771ccb17fb93b47079c" + integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ== + wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz" @@ -1016,6 +1777,11 @@ y18n@^5.0.5: resolved "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz" integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + yargs-parser@^21.0.0: version "21.0.1" resolved "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.0.1.tgz" @@ -1032,4 +1798,9 @@ yargs@^17.5.1: require-directory "^2.1.1" string-width "^4.2.3" y18n "^5.0.5" - yargs-parser "^21.0.0" \ No newline at end of file + yargs-parser "^21.0.0" + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==