diff --git a/.gitignore b/.gitignore index 50a0a84644..942f790185 100644 --- a/.gitignore +++ b/.gitignore @@ -55,7 +55,12 @@ lerna-debug.log* !.vscode/extensions.json # Allure -**allure-results/ +#Allure results and artifacts +**/allure-results/ +**/e2e/artifacts/ +**/playbook/artifacts* +**/playbook/cache* +**/buffer/*.txt # App hyperchain config hyperchain.config.json diff --git a/package-lock.json b/package-lock.json index 921ce2562c..2989769945 100644 --- a/package-lock.json +++ b/package-lock.json @@ -6084,6 +6084,16 @@ "@openzeppelin/contracts-upgradeable": "4.6.0" } }, + "node_modules/@matterlabs/zksync-contracts": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/@matterlabs/zksync-contracts/-/zksync-contracts-0.6.1.tgz", + "integrity": "sha512-+hucLw4DhGmTmQlXOTEtpboYCaOm/X2VJcWmnW4abNcOgQXEHX+mTxQrxEfPjIZT0ZE6z5FTUrOK9+RgUZwBMQ==", + "dev": true, + "peerDependencies": { + "@openzeppelin/contracts": "4.6.0", + "@openzeppelin/contracts-upgradeable": "4.6.0" + } + }, "node_modules/@mdx-js/loader": { "version": "1.6.22", "resolved": "https://registry.npmjs.org/@mdx-js/loader/-/loader-1.6.22.tgz", @@ -7076,6 +7086,7 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", + "deprecated": "Upgrade to ethereum-cryptography@2.0 for security and reduced package size", "dev": true, "dependencies": { "@types/pbkdf2": "^3.0.0", @@ -7192,6 +7203,7 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", + "deprecated": "Upgrade to ethereum-cryptography@2.0 for security and reduced package size", "dev": true, "dependencies": { "@types/pbkdf2": "^3.0.0", @@ -7242,6 +7254,7 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", + "deprecated": "Upgrade to ethereum-cryptography@2.0 for security and reduced package size", "dev": true, "dependencies": { "@types/pbkdf2": "^3.0.0", @@ -7322,6 +7335,7 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", + "deprecated": "Upgrade to ethereum-cryptography@2.0 for security and reduced package size", "dev": true, "dependencies": { "@types/pbkdf2": "^3.0.0", @@ -7472,6 +7486,7 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", + "deprecated": "Upgrade to ethereum-cryptography@2.0 for security and reduced package size", "dev": true, "dependencies": { "@types/pbkdf2": "^3.0.0", @@ -7580,6 +7595,7 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", + "deprecated": "Upgrade to ethereum-cryptography@2.0 for security and reduced package size", "dev": true, "dependencies": { "@types/pbkdf2": "^3.0.0", @@ -7672,6 +7688,7 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", + "deprecated": "Upgrade to ethereum-cryptography@2.0 for security and reduced package size", "dev": true, "dependencies": { "@types/pbkdf2": "^3.0.0", @@ -7749,6 +7766,7 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", + "deprecated": "Upgrade to ethereum-cryptography@2.0 for security and reduced package size", "dev": true, "dependencies": { "@types/pbkdf2": "^3.0.0", @@ -7796,6 +7814,7 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", + "deprecated": "Upgrade to ethereum-cryptography@2.0 for security and reduced package size", "dev": true, "dependencies": { "@types/pbkdf2": "^3.0.0", @@ -9621,6 +9640,77 @@ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", "dev": true }, + "node_modules/@sentry/node": { + "version": "7.73.0", + "resolved": "https://registry.npmjs.org/@sentry/node/-/node-7.73.0.tgz", + "integrity": "sha512-i50bRfmgkRRx0XXUbg9jGD/RuznDJxJXc4rBILhoJuhl+BjRIaoXA3ayplfJn8JLZxsNh75uJaCq4IUK70SORw==", + "dev": true, + "dependencies": { + "@sentry/types": "5.30.0", + "@sentry/utils": "5.30.0", + "tslib": "^1.9.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@sentry/hub/node_modules/@sentry/types": { + "version": "5.30.0", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-5.30.0.tgz", + "integrity": "sha512-R8xOqlSTZ+htqrfteCWU5Nk0CDN5ApUTvrlvBuiH1DyP6czDZ4ktbZB0hAgBlVcK0U+qpD3ag3Tqqpa5Q67rPw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@sentry/hub/node_modules/@sentry/utils": { + "version": "5.30.0", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-5.30.0.tgz", + "integrity": "sha512-zaYmoH0NWWtvnJjC9/CBseXMtKHm/tm40sz3YfJRxeQjyzRqNQPgivpd9R/oDJCYj999mzdW382p/qi2ypjLww==", + "dev": true, + "dependencies": { + "@sentry/types": "5.30.0", + "tslib": "^1.9.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@sentry/hub/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/@sentry/minimal": { + "version": "5.30.0", + "resolved": "https://registry.npmjs.org/@sentry/minimal/-/minimal-5.30.0.tgz", + "integrity": "sha512-BwWb/owZKtkDX+Sc4zCSTNcvZUq7YcH3uAVlmh/gtR9rmUvbzAA3ewLuB3myi4wWRAMEtny6+J/FN/x+2wn9Xw==", + "dev": true, + "dependencies": { + "@sentry/hub": "5.30.0", + "@sentry/types": "5.30.0", + "tslib": "^1.9.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@sentry/minimal/node_modules/@sentry/types": { + "version": "5.30.0", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-5.30.0.tgz", + "integrity": "sha512-R8xOqlSTZ+htqrfteCWU5Nk0CDN5ApUTvrlvBuiH1DyP6czDZ4ktbZB0hAgBlVcK0U+qpD3ag3Tqqpa5Q67rPw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/@sentry/minimal/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, "node_modules/@sentry/node": { "version": "7.75.1", "resolved": "https://registry.npmjs.org/@sentry/node/-/node-7.75.1.tgz", @@ -18589,9 +18679,9 @@ } }, "node_modules/@types/bn.js": { - "version": "5.1.5", - "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.5.tgz", - "integrity": "sha512-V46N0zwKRF5Q00AZ6hWtN0T8gGmDUaUzLWQvHFo5yThtVwK/VCenFY3wXVbOvNfajEpsTfQM4IN9k/d6gUVX3A==", + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/@types/bn.js/-/bn.js-5.1.2.tgz", + "integrity": "sha512-dkpZu0szUtn9UXTmw+e0AJFd4D2XAxDnsCLdc05SfqpqzPEBft8eQr8uaFitfo/dUUOZERaLec2hHMG87A4Dxg==", "dev": true, "dependencies": { "@types/node": "*" @@ -18884,6 +18974,12 @@ "integrity": "sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw==", "dev": true }, + "node_modules/@types/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/@types/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-ssE3Vlrys7sdIzs5LOxCzTVMsU7i9oa/IaW92wF32JFb3CVczqOkru2xspuKczHEbG3nvmPY7IFqVmGGHdNbYw==", + "dev": true + }, "node_modules/@types/mdast": { "version": "3.0.14", "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.14.tgz", @@ -18964,14 +19060,19 @@ } }, "node_modules/@types/pbkdf2": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@types/pbkdf2/-/pbkdf2-3.1.2.tgz", - "integrity": "sha512-uRwJqmiXmh9++aSu1VNEn3iIxWOhd8AHXNSdlaLfdAAdSTY9jYVeGWnzejM3dvrkbqE3/hyQkQQ29IFATEGlew==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/@types/pbkdf2/-/pbkdf2-3.1.0.tgz", + "integrity": "sha512-Cf63Rv7jCQ0LaL8tNXmEyqTHuIJxRdlS5vMh1mj5voN4+QFhVZnlZruezqpWYDiJ8UTzhP0VmeLXCmBk66YrMQ==", "dev": true, "dependencies": { "@types/node": "*" } }, + "node_modules/@types/prettier": { + "version": "2.7.3", + "resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz", + "integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==" + }, "node_modules/@types/pretty-hrtime": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/@types/pretty-hrtime/-/pretty-hrtime-1.0.2.tgz", @@ -19045,9 +19146,9 @@ "dev": true }, "node_modules/@types/secp256k1": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.6.tgz", - "integrity": "sha512-hHxJU6PAEUn0TP4S/ZOzuTUvJWuZ6eIKeNKb5RBpODvSl6hp1Wrw4s7ATY50rklRCScUDpHzVA/DQdSjJ3UoYQ==", + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/secp256k1/-/secp256k1-4.0.4.tgz", + "integrity": "sha512-oN0PFsYxDZnX/qSJ5S5OwaEDTYfekhvaM5vqui2bu1AA39pKofmgL104Q29KiOXizXS2yLjSzc5YdTyMKdcy4A==", "dev": true, "dependencies": { "@types/node": "*" @@ -25025,6 +25126,7 @@ "version": "29.7.0", "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "dev": true, "dependencies": { "@jest/types": "^29.6.3", "chalk": "^4.0.0", @@ -25041,359 +25143,1200 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/create-jest/node_modules/ansi-styles": { - "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" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/create-jest/node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/create-jest/node_modules/jest-util": { + "node_modules/create-jest/node_modules/@jest/console": { "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", - "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "dev": true, "dependencies": { "@jest/types": "^29.6.3", "@types/node": "*", "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "graceful-fs": "^4.2.9", - "picomatch": "^2.2.3" + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" }, "engines": { "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/create-jest/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "node_modules/create-jest/node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "dev": true, "dependencies": { - "has-flag": "^4.0.0" + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/create-require": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", - "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", - "devOptional": true - }, - "node_modules/cross-spawn": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", - "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "node_modules/create-jest/node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "dev": true, "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" }, "engines": { - "node": ">= 8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/crypto-browserify": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", - "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "node_modules/create-jest/node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", "dev": true, "dependencies": { - "browserify-cipher": "^1.0.0", - "browserify-sign": "^4.0.0", - "create-ecdh": "^4.0.0", - "create-hash": "^1.1.0", - "create-hmac": "^1.1.0", - "diffie-hellman": "^5.0.0", - "inherits": "^2.0.1", - "pbkdf2": "^3.0.3", - "public-encrypt": "^4.0.0", - "randombytes": "^2.0.0", - "randomfill": "^1.0.3" + "jest-get-type": "^29.6.3" }, "engines": { - "node": "*" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/crypto-random-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", - "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", + "node_modules/create-jest/node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/css-loader": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-3.6.0.tgz", - "integrity": "sha512-M5lSukoWi1If8dhQAUCvj4H8vUt3vOnwbQBH9DdTm/s4Ym2B/3dPMtYZeJmq7Q3S3Pa+I94DcZ7pc9bP14cWIQ==", + "node_modules/create-jest/node_modules/@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", "dev": true, "dependencies": { - "camelcase": "^5.3.1", - "cssesc": "^3.0.0", - "icss-utils": "^4.1.1", - "loader-utils": "^1.2.3", - "normalize-path": "^3.0.0", - "postcss": "^7.0.32", - "postcss-modules-extract-imports": "^2.0.0", - "postcss-modules-local-by-default": "^3.0.2", - "postcss-modules-scope": "^2.2.0", - "postcss-modules-values": "^3.0.0", - "postcss-value-parser": "^4.1.0", - "schema-utils": "^2.7.0", - "semver": "^6.3.0" + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" }, "engines": { - "node": ">= 8.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - }, - "peerDependencies": { - "webpack": "^4.0.0 || ^5.0.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/css-loader/node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "node_modules/create-jest/node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", "dev": true, + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, "engines": { - "node": ">=6" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/css-loader/node_modules/picocolors": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", - "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", - "dev": true - }, - "node_modules/css-loader/node_modules/postcss": { - "version": "7.0.39", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", - "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "node_modules/create-jest/node_modules/@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", "dev": true, "dependencies": { - "picocolors": "^0.2.1", - "source-map": "^0.6.1" + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" }, "engines": { - "node": ">=6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/css-loader/node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "node_modules/create-jest/node_modules/@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/css-select": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", - "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "node_modules/create-jest/node_modules/@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", "dev": true, "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.0.1", - "domhandler": "^4.3.1", - "domutils": "^2.8.0", - "nth-check": "^2.0.1" + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/css-what": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", - "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", - "dev": true, "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "node_modules/create-jest/node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", "dev": true, - "bin": { - "cssesc": "bin/cssesc" + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" }, "engines": { - "node": ">=4" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/cssom": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz", - "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==", - "dev": true - }, - "node_modules/cssstyle": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", - "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", + "node_modules/create-jest/node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", "dev": true, "dependencies": { - "cssom": "~0.3.6" + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" }, "engines": { - "node": ">=8" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/cssstyle/node_modules/cssom": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", - "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", - "dev": true - }, - "node_modules/csstype": { - "version": "2.6.21", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.21.tgz", - "integrity": "sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==" - }, - "node_modules/cyclist": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.2.tgz", - "integrity": "sha512-0sVXIohTfLqVIW3kb/0n6IiWF3Ifj5nm2XaSrLq2DI6fKIGa2fYAZdk917rUneaeLVpYfFcyXE2ft0fe3remsA==", + "node_modules/create-jest/node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", "dev": true }, - "node_modules/dargs": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz", - "integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==", + "node_modules/create-jest/node_modules/@sinonjs/commons": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", + "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", "dev": true, - "engines": { - "node": ">=8" + "dependencies": { + "type-detect": "4.0.8" } }, - "node_modules/data-fetcher": { - "resolved": "packages/data-fetcher", - "link": true - }, - "node_modules/data-urls": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-3.0.2.tgz", - "integrity": "sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==", + "node_modules/create-jest/node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", "dev": true, "dependencies": { - "abab": "^2.0.6", - "whatwg-mimetype": "^3.0.0", - "whatwg-url": "^11.0.0" - }, - "engines": { - "node": ">=12" + "@sinonjs/commons": "^3.0.0" } }, - "node_modules/data-urls/node_modules/whatwg-url": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", - "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", + "node_modules/create-jest/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "dependencies": { - "tr46": "^3.0.0", - "webidl-conversions": "^7.0.0" + "color-convert": "^2.0.1" }, "engines": { - "node": ">=12" - } - }, - "node_modules/date-fns": { - "version": "2.28.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.28.0.tgz", - "integrity": "sha512-8d35hViGYx/QH0icHYCeLmsLmMUheMmTyV9Fcm6gvNwdw31yXXH+O85sOBJ+OLnLQMKZowvpKb6FgMIQjcpvQw==", - "engines": { - "node": ">=0.11" + "node": ">=8" }, "funding": { - "type": "opencollective", - "url": "https://opencollective.com/date-fns" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/dateformat": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", - "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", + "node_modules/create-jest/node_modules/babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", "dev": true, + "dependencies": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, "engines": { - "node": "*" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" } }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "node_modules/create-jest/node_modules/babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "dev": true, "dependencies": { - "ms": "2.1.2" + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" }, "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "node_modules/decamelize": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", - "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "node_modules/create-jest/node_modules/babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", "dev": true, + "dependencies": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + }, "engines": { - "node": ">=0.10.0" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, - "node_modules/decamelize-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", - "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", + "node_modules/create-jest/node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "dependencies": { - "decamelize": "^1.1.0", - "map-obj": "^1.0.0" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/create-jest/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "node_modules/create-jest/node_modules/dedent": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", + "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", + "dev": true, + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/create-jest/node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/create-jest/node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/create-jest/node_modules/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "dev": true, + "dependencies": { + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/create-jest/node_modules/jest-circus": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^1.0.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/create-jest/node_modules/jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/create-jest/node_modules/jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/create-jest/node_modules/jest-docblock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", + "dev": true, + "dependencies": { + "detect-newline": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/create-jest/node_modules/jest-each": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/create-jest/node_modules/jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/create-jest/node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/create-jest/node_modules/jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/create-jest/node_modules/jest-leak-detector": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", + "dev": true, + "dependencies": { + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/create-jest/node_modules/jest-matcher-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/create-jest/node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/create-jest/node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/create-jest/node_modules/jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/create-jest/node_modules/jest-resolve": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/create-jest/node_modules/jest-runner": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", + "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/create-jest/node_modules/jest-runtime": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/create-jest/node_modules/jest-snapshot": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "natural-compare": "^1.4.0", + "pretty-format": "^29.7.0", + "semver": "^7.5.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/create-jest/node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/create-jest/node_modules/jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/create-jest/node_modules/jest-watcher": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "dev": true, + "dependencies": { + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", + "string-length": "^4.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/create-jest/node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dev": true, + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/create-jest/node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/create-jest/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/create-jest/node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/create-jest/node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/create-jest/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true + }, + "node_modules/create-jest/node_modules/resolve.exports": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", + "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/create-jest/node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/create-jest/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/create-jest/node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/create-jest/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/create-jest/node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "devOptional": true + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/crypto-browserify": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz", + "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==", + "dev": true, + "dependencies": { + "browserify-cipher": "^1.0.0", + "browserify-sign": "^4.0.0", + "create-ecdh": "^4.0.0", + "create-hash": "^1.1.0", + "create-hmac": "^1.1.0", + "diffie-hellman": "^5.0.0", + "inherits": "^2.0.1", + "pbkdf2": "^3.0.3", + "public-encrypt": "^4.0.0", + "randombytes": "^2.0.0", + "randomfill": "^1.0.3" + }, + "engines": { + "node": "*" + } + }, + "node_modules/crypto-random-string": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-2.0.0.tgz", + "integrity": "sha512-v1plID3y9r/lPhviJ1wrXpLeyUIGAZ2SHNYTEapm7/8A9nLPoyvVp3RK/EPFqn5kEznyWgYZNsRtYYIWbuG8KA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/css-loader": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-3.6.0.tgz", + "integrity": "sha512-M5lSukoWi1If8dhQAUCvj4H8vUt3vOnwbQBH9DdTm/s4Ym2B/3dPMtYZeJmq7Q3S3Pa+I94DcZ7pc9bP14cWIQ==", + "dev": true, + "dependencies": { + "camelcase": "^5.3.1", + "cssesc": "^3.0.0", + "icss-utils": "^4.1.1", + "loader-utils": "^1.2.3", + "normalize-path": "^3.0.0", + "postcss": "^7.0.32", + "postcss-modules-extract-imports": "^2.0.0", + "postcss-modules-local-by-default": "^3.0.2", + "postcss-modules-scope": "^2.2.0", + "postcss-modules-values": "^3.0.0", + "postcss-value-parser": "^4.1.0", + "schema-utils": "^2.7.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">= 8.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^4.0.0 || ^5.0.0" + } + }, + "node_modules/css-loader/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/css-loader/node_modules/picocolors": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz", + "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==", + "dev": true + }, + "node_modules/css-loader/node_modules/postcss": { + "version": "7.0.39", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz", + "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==", + "dev": true, + "dependencies": { + "picocolors": "^0.2.1", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=6.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + } + }, + "node_modules/css-loader/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "dev": true, + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "dev": true, + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cssom": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz", + "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==", + "dev": true + }, + "node_modules/cssstyle": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/cssstyle/-/cssstyle-2.3.0.tgz", + "integrity": "sha512-AZL67abkUzIuvcHqk7c09cezpGNcxUxU4Ioi/05xHk4DQeTkWmGYftIE6ctU6AEt+Gn4n1lDStOtj7FKycP71A==", + "dev": true, + "dependencies": { + "cssom": "~0.3.6" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cssstyle/node_modules/cssom": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.3.8.tgz", + "integrity": "sha512-b0tGHbfegbhPJpxpiBPU2sCkigAqtM9O121le6bbOlgyV+NyGyCmVfJ6QW9eRjz8CpNfWEOYBIMIGRYkLwsIYg==", + "dev": true + }, + "node_modules/csstype": { + "version": "2.6.21", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.21.tgz", + "integrity": "sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w==" + }, + "node_modules/cyclist": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.2.tgz", + "integrity": "sha512-0sVXIohTfLqVIW3kb/0n6IiWF3Ifj5nm2XaSrLq2DI6fKIGa2fYAZdk917rUneaeLVpYfFcyXE2ft0fe3remsA==", + "dev": true + }, + "node_modules/dargs": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz", + "integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/data-fetcher": { + "resolved": "packages/data-fetcher", + "link": true + }, + "node_modules/data-urls": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/data-urls/-/data-urls-3.0.2.tgz", + "integrity": "sha512-Jy/tj3ldjZJo63sVAvg6LHt2mHvl4V6AgRAmNDtLdm7faqtsx+aJG42rsyCo9JCoRVKwPFzKlIPx3DIibwSIaQ==", + "dev": true, + "dependencies": { + "abab": "^2.0.6", + "whatwg-mimetype": "^3.0.0", + "whatwg-url": "^11.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/data-urls/node_modules/whatwg-url": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", + "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", + "dev": true, + "dependencies": { + "tr46": "^3.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/date-fns": { + "version": "2.28.0", + "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.28.0.tgz", + "integrity": "sha512-8d35hViGYx/QH0icHYCeLmsLmMUheMmTyV9Fcm6gvNwdw31yXXH+O85sOBJ+OLnLQMKZowvpKb6FgMIQjcpvQw==", + "engines": { + "node": ">=0.11" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/date-fns" + } + }, + "node_modules/dateformat": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", + "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decamelize-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", + "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", + "dev": true, + "dependencies": { + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/decamelize-keys/node_modules/map-obj": { @@ -27605,6 +28548,7 @@ "version": "0.1.3", "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-0.1.3.tgz", "integrity": "sha512-w8/4x1SGGzc+tO97TASLja6SLd3fRIK2tLVcV2Gx4IB21hE19atll5Cq9o3d0ZmAYC/8aw0ipieTSiekAea4SQ==", + "deprecated": "Upgrade to ethereum-cryptography@2.0 for security and reduced package size", "dev": true, "dependencies": { "@types/pbkdf2": "^3.0.0", @@ -29642,9 +30586,9 @@ } }, "node_modules/hardhat": { - "version": "2.19.1", - "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.19.1.tgz", - "integrity": "sha512-bsWa63g1GB78ZyMN08WLhFElLPA+J+pShuKD1BFO2+88g3l+BL3R07vj9deIi9dMbssxgE714Gof1dBEDGqnCw==", + "version": "2.18.0", + "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.18.0.tgz", + "integrity": "sha512-Com3SPFgk6v73LlE3rypuh32DYxOWvNbVBm5xfPUEzGVEW54Fcc4j3Uq7j6COj7S8Jc27uNihLFsveHYM0YJkQ==", "dev": true, "dependencies": { "@ethersproject/abi": "^5.1.2", @@ -30008,6 +30952,294 @@ } } }, + "node_modules/has": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.4.tgz", + "integrity": "sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/hardhat/node_modules/@sentry/node": { + "version": "5.30.0", + "resolved": "https://registry.npmjs.org/@sentry/node/-/node-5.30.0.tgz", + "integrity": "sha512-Br5oyVBF0fZo6ZS9bxbJZG4ApAjRqAnqFFurMVJJdunNb80brh7a5Qva2kjhm+U6r9NJAB5OmDyPkA1Qnt+QVg==", + "dev": true, + "dependencies": { + "@sentry/core": "5.30.0", + "@sentry/hub": "5.30.0", + "@sentry/tracing": "5.30.0", + "@sentry/types": "5.30.0", + "@sentry/utils": "5.30.0", + "cookie": "^0.4.1", + "https-proxy-agent": "^5.0.0", + "lru_map": "^0.3.3", + "tslib": "^1.9.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/hardhat/node_modules/@sentry/tracing": { + "version": "5.30.0", + "resolved": "https://registry.npmjs.org/@sentry/tracing/-/tracing-5.30.0.tgz", + "integrity": "sha512-dUFowCr0AIMwiLD7Fs314Mdzcug+gBVo/+NCMyDw8tFxJkwWAKl7Qa2OZxLQ0ZHjakcj1hNKfCQJ9rhyfOl4Aw==", + "dev": true, + "dependencies": { + "@sentry/hub": "5.30.0", + "@sentry/minimal": "5.30.0", + "@sentry/types": "5.30.0", + "@sentry/utils": "5.30.0", + "tslib": "^1.9.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/hardhat/node_modules/@sentry/types": { + "version": "5.30.0", + "resolved": "https://registry.npmjs.org/@sentry/types/-/types-5.30.0.tgz", + "integrity": "sha512-R8xOqlSTZ+htqrfteCWU5Nk0CDN5ApUTvrlvBuiH1DyP6czDZ4ktbZB0hAgBlVcK0U+qpD3ag3Tqqpa5Q67rPw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/hardhat/node_modules/@sentry/utils": { + "version": "5.30.0", + "resolved": "https://registry.npmjs.org/@sentry/utils/-/utils-5.30.0.tgz", + "integrity": "sha512-zaYmoH0NWWtvnJjC9/CBseXMtKHm/tm40sz3YfJRxeQjyzRqNQPgivpd9R/oDJCYj999mzdW382p/qi2ypjLww==", + "dev": true, + "dependencies": { + "@sentry/types": "5.30.0", + "tslib": "^1.9.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/hardhat/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "dev": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/hardhat/node_modules/ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "dev": true + }, + "node_modules/hardhat/node_modules/cookie": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.2.tgz", + "integrity": "sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/hardhat/node_modules/find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha512-NWzkk0jSJtTt08+FBFMvXoeZnOJD+jTtsRmBYbAIzJdX6l7dLgR7CTubCM5/eDdPUBvLCeVasP1brfVR/9/EZQ==", + "dev": true, + "dependencies": { + "locate-path": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/hardhat/node_modules/fs-extra": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz", + "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/hardhat/node_modules/glob": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", + "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/hardhat/node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", + "dev": true, + "dependencies": { + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/hardhat/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "dev": true, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/hardhat/node_modules/locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha512-NCI2kiDkyR7VeEKm27Kda/iQHyKJe1Bu0FlTbYp3CqJu+9IFe9bLyAjMxf5ZDDbEg+iMPzB5zYyUTSm8wVTKmA==", + "dev": true, + "dependencies": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/hardhat/node_modules/p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "dependencies": { + "p-try": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/hardhat/node_modules/p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha512-nQja7m7gSKuewoVRen45CtVfODR3crN3goVQ0DDZ9N3yHxgpkuBhZqsaiotSQRrADUrne346peY7kT3TSACykg==", + "dev": true, + "dependencies": { + "p-limit": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/hardhat/node_modules/p-map": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", + "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", + "dev": true, + "dependencies": { + "aggregate-error": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/hardhat/node_modules/p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha512-U1etNYuMJoIz3ZXSrrySFjsXQTWOx2/jdi86L+2pRvph/qMKL6sbcCYdH23fqsbm8TH2Gn0OybpT4eSFlCVHww==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/hardhat/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/hardhat/node_modules/resolve": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.17.0.tgz", + "integrity": "sha512-ic+7JYiV8Vi2yzQGFWOkiZD5Z9z7O2Zhm9XMaTxdJExKasieFCr+yXZ/WmXsckHiKl12ar0y6XiXDx3m4RHn1w==", + "dev": true, + "dependencies": { + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hardhat/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/hardhat/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/hardhat/node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/hardhat/node_modules/ws": { + "version": "7.5.9", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.9.tgz", + "integrity": "sha512-F+P9Jil7UiSKSkppIiD94dN07AwvFixvLIj1Og1Rl9GGMuNipJnV9JzjD6XuqmAeiswGvUmNLjr5cFuXwNS77Q==", + "dev": true, + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, "node_modules/has-ansi": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-4.0.1.tgz", @@ -44772,6 +46004,7 @@ "version": "6.0.4", "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.0.4.tgz", "integrity": "sha512-LA0Y9kxMYv47GIPJy6MI84fqTd2HmYZI83W/kM/SkKfDlajnZYfmXFTxkbY+xSBPkLJxltMa9hIkmdc29eguMA==", + "dev": true, "funding": [ { "type": "individual", @@ -53971,11 +55204,42 @@ "jest-resolve": "^29.5.0" } }, - "node_modules/ts-jest/node_modules/ansi-styles": { + "node_modules/ts-jest-resolver/node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/ts-jest-resolver/node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/ts-jest-resolver/node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==" + }, + "node_modules/ts-jest-resolver/node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -53986,11 +55250,10 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/ts-jest/node_modules/chalk": { + "node_modules/ts-jest-resolver/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" @@ -54002,11 +55265,69 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/ts-jest/node_modules/jest-util": { + "node_modules/ts-jest-resolver/node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/ts-jest-resolver/node_modules/jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/ts-jest-resolver/node_modules/jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/ts-jest-resolver/node_modules/jest-resolve": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", + "dependencies": { + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/ts-jest-resolver/node_modules/jest-util": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", - "dev": true, "dependencies": { "@jest/types": "^29.6.3", "@types/node": "*", @@ -54019,6 +55340,98 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "node_modules/ts-jest-resolver/node_modules/jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "dependencies": { + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/ts-jest-resolver/node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/ts-jest-resolver/node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/ts-jest-resolver/node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/ts-jest-resolver/node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", + "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ts-jest-resolver/node_modules/react-is": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + }, + "node_modules/ts-jest-resolver/node_modules/resolve.exports": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", + "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", + "engines": { + "node": ">=10" + } + }, + "node_modules/ts-jest-resolver/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/ts-jest/node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -58348,6 +59761,143 @@ "@ethersproject/strings": "^5.7.0" } }, + "packages/integration-tests/node_modules/@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "packages/integration-tests/node_modules/@jest/core": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "packages/integration-tests/node_modules/@jest/core/node_modules/jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "packages/integration-tests/node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "dev": true, + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "packages/integration-tests/node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "dev": true, + "dependencies": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "packages/integration-tests/node_modules/@jest/expect-utils": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", @@ -58360,6 +59910,180 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "packages/integration-tests/node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "packages/integration-tests/node_modules/@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "packages/integration-tests/node_modules/@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "dev": true, + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "packages/integration-tests/node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "dev": true, + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "packages/integration-tests/node_modules/@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "dev": true, + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "packages/integration-tests/node_modules/@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "packages/integration-tests/node_modules/@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "dev": true, + "dependencies": { + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "packages/integration-tests/node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "packages/integration-tests/node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "dev": true, + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "packages/integration-tests/node_modules/@matterlabs/hardhat-zksync-deploy": { "version": "0.6.5", "resolved": "https://registry.npmjs.org/@matterlabs/hardhat-zksync-deploy/-/hardhat-zksync-deploy-0.6.5.tgz", @@ -58390,32 +60114,108 @@ "semver": "^7.5.1" }, "peerDependencies": { - "hardhat": "^2.14.0" + "hardhat": "^2.14.0" + } + }, + "packages/integration-tests/node_modules/@playwright/test": { + "version": "1.38.1", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.38.1.tgz", + "integrity": "sha512-NqRp8XMwj3AK+zKLbZShl0r/9wKgzqI/527bkptKXomtuo+dOjU9NdMASQ8DNC9z9zLOMbG53T4eihYr3XR+BQ==", + "dev": true, + "dependencies": { + "playwright": "1.38.1" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=16" + } + }, + "packages/integration-tests/node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "dev": true + }, + "packages/integration-tests/node_modules/@sinonjs/commons": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.0.tgz", + "integrity": "sha512-jXBtWAF4vmdNmZgD5FoKsVLv3rPgDnLgPbU84LIJ3otV44vJlDRokVng5v8NFJdCf/da9legHcKaRuZs4L7faA==", + "dev": true, + "dependencies": { + "type-detect": "4.0.8" + } + }, + "packages/integration-tests/node_modules/@sinonjs/fake-timers": { + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", + "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", + "dev": true, + "dependencies": { + "@sinonjs/commons": "^3.0.0" + } + }, + "packages/integration-tests/node_modules/@types/jest": { + "version": "29.5.5", + "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.5.tgz", + "integrity": "sha512-ebylz2hnsWR9mYvmBFbXJXr+33UPc4+ZdxyDXh5w0FlPBTfCVN3wPL+kuOiQt3xvrK419v7XWeAs+AeOksafXg==", + "dev": true, + "dependencies": { + "expect": "^29.0.0", + "pretty-format": "^29.0.0" + } + }, + "packages/integration-tests/node_modules/babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "dev": true, + "dependencies": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" } }, - "packages/integration-tests/node_modules/@playwright/test": { - "version": "1.40.0", - "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.40.0.tgz", - "integrity": "sha512-PdW+kn4eV99iP5gxWNSDQCbhMaDVej+RXL5xr6t04nbKLCBwYtA046t7ofoczHOm8u6c+45hpDKQVZqtqwkeQg==", + "packages/integration-tests/node_modules/babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", "dev": true, "dependencies": { - "playwright": "1.40.0" - }, - "bin": { - "playwright": "cli.js" + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" }, "engines": { - "node": ">=16" + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, - "packages/integration-tests/node_modules/@types/jest": { - "version": "29.5.10", - "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.10.tgz", - "integrity": "sha512-tE4yxKEphEyxj9s4inideLHktW/x6DwesIwWZ9NN1FKf9zbJYsnhBoA9vrHA/IuIOKwPa5PcFBNV4lpMIOEzyQ==", + "packages/integration-tests/node_modules/babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", "dev": true, "dependencies": { - "expect": "^29.0.0", - "pretty-format": "^29.0.0" + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" } }, "packages/integration-tests/node_modules/chalk": { @@ -58449,6 +60249,26 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "packages/integration-tests/node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true + }, + "packages/integration-tests/node_modules/dedent": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.1.tgz", + "integrity": "sha512-+LxW+KLWxu3HW3M2w2ympwtqPrqYRzU8fqi6Fhd18fBALe15blJPI/I4+UHveMVG6lJqB4JNd4UG0S5cnVHwIg==", + "dev": true, + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, "packages/integration-tests/node_modules/diff-sequences": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", @@ -58458,6 +60278,18 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "packages/integration-tests/node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, "packages/integration-tests/node_modules/ethers": { "version": "5.7.2", "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.7.2.tgz", @@ -58536,6 +60368,22 @@ "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, + "packages/integration-tests/node_modules/istanbul-lib-instrument": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.1.tgz", + "integrity": "sha512-EAMEJBsYuyyztxMxW3g7ugGPkrZsV57v0Hmv3mm1uQsmB+QnZuepg731CRaIgeUVSdmsTngOkSnauNF8p7FIhA==", + "dev": true, + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=10" + } + }, "packages/integration-tests/node_modules/jest": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", @@ -58562,6 +60410,129 @@ } } }, + "packages/integration-tests/node_modules/jest-changed-files": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", + "dev": true, + "dependencies": { + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "packages/integration-tests/node_modules/jest-circus": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^1.0.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "packages/integration-tests/node_modules/jest-cli": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", + "dev": true, + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "create-jest": "^29.7.0", + "exit": "^0.1.2", + "import-local": "^3.0.2", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "yargs": "^17.3.1" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "packages/integration-tests/node_modules/jest-cli/node_modules/jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, "packages/integration-tests/node_modules/jest-diff": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", @@ -58577,6 +60548,51 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "packages/integration-tests/node_modules/jest-docblock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", + "dev": true, + "dependencies": { + "detect-newline": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "packages/integration-tests/node_modules/jest-each": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "packages/integration-tests/node_modules/jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "packages/integration-tests/node_modules/jest-get-type": { "version": "29.6.3", "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", @@ -58586,6 +60602,44 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "packages/integration-tests/node_modules/jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "packages/integration-tests/node_modules/jest-leak-detector": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", + "dev": true, + "dependencies": { + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "packages/integration-tests/node_modules/jest-matcher-utils": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", @@ -58621,6 +60675,158 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "packages/integration-tests/node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "packages/integration-tests/node_modules/jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "dev": true, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "packages/integration-tests/node_modules/jest-resolve": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "packages/integration-tests/node_modules/jest-resolve-dependencies": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", + "dev": true, + "dependencies": { + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "packages/integration-tests/node_modules/jest-runner": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", + "dev": true, + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "packages/integration-tests/node_modules/jest-runtime": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "dev": true, + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "packages/integration-tests/node_modules/jest-snapshot": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", + "dev": true, + "dependencies": { + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "natural-compare": "^1.4.0", + "pretty-format": "^29.7.0", + "semver": "^7.5.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, "packages/integration-tests/node_modules/jest-util": { "version": "29.7.0", "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", @@ -58638,6 +60844,72 @@ "node": "^14.15.0 || ^16.10.0 || >=18.0.0" } }, + "packages/integration-tests/node_modules/jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "dev": true, + "dependencies": { + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "packages/integration-tests/node_modules/jest-watcher": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "dev": true, + "dependencies": { + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", + "string-length": "^4.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "packages/integration-tests/node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "dev": true, + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "packages/integration-tests/node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, "packages/integration-tests/node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", @@ -58651,12 +60923,12 @@ } }, "packages/integration-tests/node_modules/playwright": { - "version": "1.40.0", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.40.0.tgz", - "integrity": "sha512-gyHAgQjiDf1m34Xpwzaqb76KgfzYrhK7iih+2IzcOCoZWr/8ZqmdBw+t0RU85ZmfJMgtgAiNtBQ/KS2325INXw==", + "version": "1.38.1", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.38.1.tgz", + "integrity": "sha512-oRMSJmZrOu1FP5iu3UrCx8JEFRIMxLDM0c/3o4bpzU5Tz97BypefWf7TuTNPWeCe279TPal5RtPPZ+9lW/Qkow==", "dev": true, "dependencies": { - "playwright-core": "1.40.0" + "playwright-core": "1.38.1" }, "bin": { "playwright": "cli.js" @@ -58669,9 +60941,9 @@ } }, "packages/integration-tests/node_modules/playwright-core": { - "version": "1.40.0", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.40.0.tgz", - "integrity": "sha512-fvKewVJpGeca8t0ipM56jkVSU6Eo0RmFvQ/MaCQNDYm+sdvKkMBBWTE1FdeMqIdumRaXXjZChWHvIzCGM/tA/Q==", + "version": "1.38.1", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.38.1.tgz", + "integrity": "sha512-tQqNFUKa3OfMf4b2jQ7aGLB8o9bS3bOY0yMEtldtC2+spf8QXG9zvXLTXUeRsoNuxEYMgLYR+NXfAa1rjKRcrg==", "dev": true, "bin": { "playwright-core": "cli.js" @@ -58700,6 +60972,15 @@ "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", "dev": true }, + "packages/integration-tests/node_modules/resolve.exports": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz", + "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "packages/integration-tests/node_modules/semver": { "version": "7.5.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", @@ -58715,6 +60996,25 @@ "node": ">=10" } }, + "packages/integration-tests/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "packages/integration-tests/node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, "packages/integration-tests/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -58798,9 +61098,9 @@ "dev": true }, "packages/integration-tests/node_modules/zksync-web3": { - "version": "0.14.4", - "resolved": "https://registry.npmjs.org/zksync-web3/-/zksync-web3-0.14.4.tgz", - "integrity": "sha512-kYehMD/S6Uhe1g434UnaMN+sBr9nQm23Ywn0EUP5BfQCsbjcr3ORuS68PosZw8xUTu3pac7G6YMSnNHk+fwzvg==", + "version": "0.14.3", + "resolved": "https://registry.npmjs.org/zksync-web3/-/zksync-web3-0.14.3.tgz", + "integrity": "sha512-hT72th4AnqyLW1d5Jlv8N2B/qhEnl2NePK2A3org7tAa24niem/UAaHMkEvmWI3SF9waYUPtqAtjpf+yvQ9zvQ==", "dev": true, "peerDependencies": { "ethers": "^5.7.0" diff --git a/packages/integration-tests/README.md b/packages/integration-tests/README.md index 5f3eab4dce..748dbf5059 100644 --- a/packages/integration-tests/README.md +++ b/packages/integration-tests/README.md @@ -8,15 +8,6 @@ Based on Jest.io/TypeScript/TDD. npm install ``` -## Setting up env variables - -- Create `.env` file in the `integration-tests/src/playbook/` package folder and copy paste `.env.example` content in there. -``` -cp .env.example packages/integration-tests/src/playbook/.env -``` - -- Add your private wallet key to `WALLET_PRIVATE_KEY=` By default we use `richWalletPrivateKey` private key in `integration-tests/src/playbook/utils/getWallet.ts` from `integration-tests/src/entities.ts`. - ## Preparing a local environment Make sure you have `Docker` installed. Before running the tests you need to spin up a local environment (use `docker-compose.yaml` from the root directory): diff --git a/packages/integration-tests/jest.config.json b/packages/integration-tests/jest.config.json index 6657349178..d6589b6ee7 100644 --- a/packages/integration-tests/jest.config.json +++ b/packages/integration-tests/jest.config.json @@ -1,6 +1,5 @@ { "moduleFileExtensions": ["js", "json", "ts"], - "globalSetup": "/tests/hooks/global.ts", "rootDir": ".", "testEnvironment": "node", "testRegex": ".test.ts$", diff --git a/packages/integration-tests/package.json b/packages/integration-tests/package.json index 24ee6ad63a..71f17b519a 100644 --- a/packages/integration-tests/package.json +++ b/packages/integration-tests/package.json @@ -9,7 +9,7 @@ "license": "MIT", "scripts": { "postinstall": "cd src/playbook && npm install", - "integration-test:api": "jest --verbose", + "integration-test:api": "jest --verbose --testPathPattern=tokens.test.ts && jest --verbose --testPathPattern=deposit.test.ts && jest --verbose --testPathPattern=common && jest --verbose --testPathPattern=transactions", "integration-test:ui": "npx playwright test", "block-explorer:start": "docker-compose up", "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-pattern 'repos' --ignore-pattern 'git add .'" diff --git a/packages/integration-tests/src/config.ts b/packages/integration-tests/src/config.ts index ca7034d8ec..543bdd9509 100644 --- a/packages/integration-tests/src/config.ts +++ b/packages/integration-tests/src/config.ts @@ -1,8 +1,8 @@ import { Wallets } from "./entities"; export const localConfig = { - gasLimit: { gasLimit: 10000000 }, - l2GasLimit: 10000000, + gasLimit: { gasLimit: 8000000 }, + l2GasLimit: 8000000, L1Network: "http://localhost:8545", L2Network: "http://localhost:3050", privateKey: Wallets.richWalletPrivateKey, diff --git a/packages/integration-tests/src/entities.ts b/packages/integration-tests/src/entities.ts index 83b391a60f..f0f4d545c5 100644 --- a/packages/integration-tests/src/entities.ts +++ b/packages/integration-tests/src/entities.ts @@ -7,7 +7,6 @@ export enum Buffer { L2 = "./buffer/L2.txt", L2deposited = "./buffer/L2deposited.txt", paymaster = "./buffer/paymaster.txt", - paymasterDeployTx = "./buffer/paymasterDeployTx.txt", paymasterTx = "./buffer/paymasterTx.txt", addressMultiTransferETH = "./buffer/multiTransferETH.txt", txMultiTransferETH = "./buffer/txMultiTransferETH.txt", @@ -20,12 +19,6 @@ export enum Buffer { txMultiCallCaller = "./buffer/txMultiCallCaller.txt", txMultiCallRoot = "./buffer/txmultiCallRoot.txt", txUseMultiCallContracts = "./buffer/txUseMultiCallContracts.txt", - txEthTransfer = "./buffer/txEthTransfer.txt", - txERC20Withdraw = "./buffer/txERC20Withdraw.txt", - txERC20WithdrawOtherAddress = "./buffer/txERC20WithdrawOtherAddress.txt", - txEthWithdraw = "./buffer/txEthWithdraw.txt", - txEthWithdrawOtherAddress = "./buffer/txEthWithdrawOtherAddress.txt", - txERC20Transfer = "./buffer/txERC20Transfer.txt", emptyWalletPrivateKey = "./buffer/emptyWalletPrivateKey.txt", emptyWalletAddress = "./buffer/emptyWalletAddress.txt", failedState = "./buffer/failedState.txt", diff --git a/packages/integration-tests/src/playbook/deploy/deploy-paymaster.ts b/packages/integration-tests/src/playbook/deploy/deploy-paymaster.ts index 468e7cc9d5..a8148f5b33 100644 --- a/packages/integration-tests/src/playbook/deploy/deploy-paymaster.ts +++ b/packages/integration-tests/src/playbook/deploy/deploy-paymaster.ts @@ -31,7 +31,6 @@ export default async function (hre: HardhatRuntimeEnvironment) { const deployTransaction = await paymaster.deployTransaction; console.log(`Paymaster deploy transaction: ${deployTransaction.hash}`); - await fs.writeFile(Buffer.paymasterDeployTx, deployTransaction.hash); await ( await deployer.zkWallet.sendTransaction({ diff --git a/packages/integration-tests/src/playbook/hardhat.config.ts b/packages/integration-tests/src/playbook/hardhat.config.ts index f5ad2af733..ce93c51cdc 100644 --- a/packages/integration-tests/src/playbook/hardhat.config.ts +++ b/packages/integration-tests/src/playbook/hardhat.config.ts @@ -4,7 +4,6 @@ require("dotenv").config({ path: __dirname + "/.env" }); import "@matterlabs/hardhat-zksync-deploy"; import "@matterlabs/hardhat-zksync-solc"; import "@nomiclabs/hardhat-ethers"; - import { localConfig } from "../config"; import type { HardhatUserConfig } from "hardhat/types"; diff --git a/packages/integration-tests/src/playbook/scenarios/transfers/transferERC20.ts b/packages/integration-tests/src/playbook/scenarios/transfers/transferERC20.ts index 13a1ab0ed3..44316badf4 100644 --- a/packages/integration-tests/src/playbook/scenarios/transfers/transferERC20.ts +++ b/packages/integration-tests/src/playbook/scenarios/transfers/transferERC20.ts @@ -1,9 +1,8 @@ import * as ethers from "ethers"; -import { promises as fs } from "fs"; import * as zksync from "zksync-web3"; import { localConfig } from "../../../config"; -import { Buffer, Logger, Wallets } from "../../../entities"; +import { Logger, Wallets } from "../../../entities"; import { Helper } from "../../../helper"; export const transferERC20 = async function (sum: string, tokenAddress: string, tokenName?: string /*, units = 18*/) { @@ -12,8 +11,6 @@ export const transferERC20 = async function (sum: string, tokenAddress: string, const ethProvider = ethers.getDefaultProvider(localConfig.L1Network); const syncWallet = new zksync.Wallet(localConfig.privateKey, syncProvider, ethProvider); const syncWallet2 = new zksync.Wallet(Wallets.secondWalletPrivateKey, syncProvider, ethProvider); - const playbookRoot = "src/playbook/"; - const bufferFile = playbookRoot + Buffer.txEthTransfer; const transfer = await syncWallet.transfer({ to: syncWallet2.address, @@ -24,7 +21,6 @@ export const transferERC20 = async function (sum: string, tokenAddress: string, const txHash = transfer.hash; await helper.txHashLogger(Logger.transfer, txHash, tokenName); - await fs.writeFile(bufferFile, txHash); return txHash; }; diff --git a/packages/integration-tests/src/playbook/scenarios/transfers/transferETH.ts b/packages/integration-tests/src/playbook/scenarios/transfers/transferETH.ts index fdd21c6e51..b6d801eb97 100644 --- a/packages/integration-tests/src/playbook/scenarios/transfers/transferETH.ts +++ b/packages/integration-tests/src/playbook/scenarios/transfers/transferETH.ts @@ -1,9 +1,8 @@ import * as ethers from "ethers"; -import { promises as fs } from "fs"; import * as zksync from "zksync-web3"; import { localConfig } from "../../../config"; -import { Buffer, Logger, Wallets } from "../../../entities"; +import { Logger, Wallets } from "../../../entities"; import { Helper } from "../../../helper"; export const transferEth = async function (sum = "0.000009", address: string = Wallets.mainWalletPrivateKey) { @@ -12,8 +11,6 @@ export const transferEth = async function (sum = "0.000009", address: string = W const ethProvider = ethers.getDefaultProvider(localConfig.L1Network); const syncWallet = new zksync.Wallet(localConfig.privateKey, syncProvider, ethProvider); const syncWallet2 = new zksync.Wallet(address, syncProvider, ethProvider); - const playbookRoot = "src/playbook/"; - const bufferFile = playbookRoot + Buffer.txEthTransfer; const transfer = await syncWallet.transfer({ to: syncWallet2.address, @@ -23,7 +20,6 @@ export const transferEth = async function (sum = "0.000009", address: string = W const txHash = transfer.hash; await helper.txHashLogger(Logger.transfer, txHash, "ETH"); - await fs.writeFile(bufferFile, txHash); return txHash; }; diff --git a/packages/integration-tests/src/playbook/scenarios/transfers/transferFailedState.ts b/packages/integration-tests/src/playbook/scenarios/transfers/transferFailedState.ts index c798cf6a61..77bf391107 100644 --- a/packages/integration-tests/src/playbook/scenarios/transfers/transferFailedState.ts +++ b/packages/integration-tests/src/playbook/scenarios/transfers/transferFailedState.ts @@ -1,9 +1,8 @@ import * as ethers from "ethers"; -import { promises as fs } from "fs"; import * as zksync from "zksync-web3"; import { localConfig } from "../../../config"; -import { Buffer, Logger } from "../../../entities"; +import { Logger } from "../../../entities"; import { Helper } from "../../../helper"; export const transferFailedState = async function (tokenAddress: string, tokenName?: string) { @@ -12,8 +11,6 @@ export const transferFailedState = async function (tokenAddress: string, tokenNa const ethProvider = ethers.getDefaultProvider(localConfig.L1Network); const syncWallet = new zksync.Wallet(localConfig.privateKey, syncProvider, ethProvider); const amount = ethers.utils.parseEther("1.0"); - const playbookRoot = "src/playbook/"; - const bufferFile = playbookRoot + Buffer.failedState; const transfer = await syncWallet.transfer({ to: "0x0000000000000000000000000000000000000000", @@ -24,7 +21,6 @@ export const transferFailedState = async function (tokenAddress: string, tokenNa const txHash = transfer.hash; await helper.txHashLogger(Logger.txFailedState, txHash, tokenName); - await fs.writeFile(bufferFile, txHash); return txHash; }; diff --git a/packages/integration-tests/src/playbook/scenarios/withdrawal/withdrawERC20.ts b/packages/integration-tests/src/playbook/scenarios/withdrawal/withdrawERC20.ts index 7bcb910033..27d498dda3 100644 --- a/packages/integration-tests/src/playbook/scenarios/withdrawal/withdrawERC20.ts +++ b/packages/integration-tests/src/playbook/scenarios/withdrawal/withdrawERC20.ts @@ -1,9 +1,8 @@ import * as ethers from "ethers"; -import { promises as fs } from "fs"; import * as zksync from "zksync-web3"; import { localConfig } from "../../../config"; -import { Buffer, Logger, Wallets } from "../../../entities"; +import { Logger, Wallets } from "../../../entities"; import { Helper } from "../../../helper"; export const withdrawERC20 = async function (tokenAddress: string, sum = "0.2") { @@ -12,8 +11,6 @@ export const withdrawERC20 = async function (tokenAddress: string, sum = "0.2") const ethProvider = ethers.getDefaultProvider(localConfig.L1Network); const syncWallet = new zksync.Wallet(localConfig.privateKey, syncProvider, ethProvider); const bridges = await syncProvider.getDefaultBridgeAddresses(); - const playbookRoot = "src/playbook/"; - const bufferFile = playbookRoot + Buffer.txERC20Withdraw; const balance = await syncWallet.getBalance(tokenAddress); @@ -24,7 +21,7 @@ export const withdrawERC20 = async function (tokenAddress: string, sum = "0.2") amount: ethers.utils.parseEther(sum), token: tokenAddress, bridgeAddress: bridges.erc20L2, - // overrides: localConfig.gasLimit, + overrides: localConfig.gasLimit, }); const txHash = withdrawL2.hash; @@ -37,7 +34,6 @@ export const withdrawERC20 = async function (tokenAddress: string, sum = "0.2") console.log(`Your balance is ${balanceAfter.toString()}`); await helper.txHashLogger(Logger.withdraw, txHash, "Custom token"); - await fs.writeFile(bufferFile, txHash); return txHash; }; diff --git a/packages/integration-tests/src/playbook/scenarios/withdrawal/withdrawERC20toOtherAddress.ts b/packages/integration-tests/src/playbook/scenarios/withdrawal/withdrawERC20toOtherAddress.ts index cf377733b6..ab92a9c326 100644 --- a/packages/integration-tests/src/playbook/scenarios/withdrawal/withdrawERC20toOtherAddress.ts +++ b/packages/integration-tests/src/playbook/scenarios/withdrawal/withdrawERC20toOtherAddress.ts @@ -1,9 +1,8 @@ import * as ethers from "ethers"; -import { promises as fs } from "fs"; import * as zksync from "zksync-web3"; import { localConfig } from "../../../config"; -import { Buffer, Logger, Wallets } from "../../../entities"; +import { Logger, Wallets } from "../../../entities"; import { Helper } from "../../../helper"; export const withdrawERC20toOtherAddress = async function (tokenAddress: string, sum = "0.2") { @@ -12,8 +11,6 @@ export const withdrawERC20toOtherAddress = async function (tokenAddress: string, const ethProvider = ethers.getDefaultProvider(localConfig.L1Network); const syncWallet = new zksync.Wallet(localConfig.privateKey, syncProvider, ethProvider); const bridges = await syncProvider.getDefaultBridgeAddresses(); - const playbookRoot = "src/playbook/"; - const bufferFile = playbookRoot + Buffer.txERC20WithdrawOtherAddress; const balance = await syncWallet.getBalance(tokenAddress); @@ -37,7 +34,6 @@ export const withdrawERC20toOtherAddress = async function (tokenAddress: string, console.log(`Your balance is ${balanceAfter.toString()}`); await helper.txHashLogger(Logger.withdraw, txHash, "Custom token"); - await fs.writeFile(bufferFile, txHash); return txHash; }; diff --git a/packages/integration-tests/src/playbook/scenarios/withdrawal/withdrawETH.ts b/packages/integration-tests/src/playbook/scenarios/withdrawal/withdrawETH.ts index 5c2598a6d6..b5daeaa52f 100644 --- a/packages/integration-tests/src/playbook/scenarios/withdrawal/withdrawETH.ts +++ b/packages/integration-tests/src/playbook/scenarios/withdrawal/withdrawETH.ts @@ -1,9 +1,8 @@ import * as ethers from "ethers"; -import { promises as fs } from "fs"; import * as zksync from "zksync-web3"; import { localConfig } from "../../../config"; -import { Buffer, Logger } from "../../../entities"; +import { Logger } from "../../../entities"; import { Helper } from "../../../helper"; export const withdrawETH = async function (sum = "0.000009") { @@ -11,8 +10,6 @@ export const withdrawETH = async function (sum = "0.000009") { const syncProvider = new zksync.Provider(localConfig.L2Network); const ethProvider = ethers.getDefaultProvider(localConfig.L1Network); const syncWallet = new zksync.Wallet(localConfig.privateKey, syncProvider, ethProvider); - const playbookRoot = "src/playbook/"; - const bufferFile = playbookRoot + Buffer.txEthWithdraw; const withdrawL2 = await syncWallet.withdraw({ token: zksync.utils.ETH_ADDRESS, @@ -23,7 +20,6 @@ export const withdrawETH = async function (sum = "0.000009") { await withdrawL2.waitFinalize(); await helper.txHashLogger(Logger.withdraw, txHash, "ETH"); - await fs.writeFile(bufferFile, txHash); return txHash; }; diff --git a/packages/integration-tests/src/playbook/scenarios/withdrawal/withdrawETHtoOtherAddress.ts b/packages/integration-tests/src/playbook/scenarios/withdrawal/withdrawETHtoOtherAddress.ts index 6adde5510c..53c217110c 100644 --- a/packages/integration-tests/src/playbook/scenarios/withdrawal/withdrawETHtoOtherAddress.ts +++ b/packages/integration-tests/src/playbook/scenarios/withdrawal/withdrawETHtoOtherAddress.ts @@ -1,9 +1,8 @@ import * as ethers from "ethers"; -import { promises as fs } from "fs"; import * as zksync from "zksync-web3"; import { localConfig } from "../../../config"; -import { Buffer, Logger, Wallets } from "../../../entities"; +import { Logger, Wallets } from "../../../entities"; import { Helper } from "../../../helper"; export const withdrawETHtoOtherAddress = async function (sum = "0.000009") { @@ -11,8 +10,6 @@ export const withdrawETHtoOtherAddress = async function (sum = "0.000009") { const syncProvider = new zksync.Provider(localConfig.L2Network); const ethProvider = ethers.getDefaultProvider(localConfig.L1Network); const syncWallet = new zksync.Wallet(localConfig.privateKey, syncProvider, ethProvider); - const playbookRoot = "src/playbook/"; - const bufferFile = playbookRoot + Buffer.txEthWithdrawOtherAddress; const withdrawL2 = await syncWallet.withdraw({ token: zksync.utils.ETH_ADDRESS, @@ -24,7 +21,6 @@ export const withdrawETHtoOtherAddress = async function (sum = "0.000009") { await withdrawL2.waitFinalize(); await helper.txHashLogger(Logger.withdraw, txHash, "ETH"); - await fs.writeFile(bufferFile, txHash); return txHash; }; diff --git a/packages/integration-tests/src/playbook/utils/getWallet.ts b/packages/integration-tests/src/playbook/utils/getWallet.ts index c956b5148e..5d2dec285e 100644 --- a/packages/integration-tests/src/playbook/utils/getWallet.ts +++ b/packages/integration-tests/src/playbook/utils/getWallet.ts @@ -1,16 +1,17 @@ import { getDefaultProvider, utils } from "ethers"; import { Provider, Wallet } from "zksync-web3"; -import { Wallets } from "../../entities"; - // eslint-disable-next-line @typescript-eslint/no-explicit-any export default async function (hre: any) { const syncProvider = new Provider(hre.config.networks.zkSyncLocal.url); const ethProvider = getDefaultProvider(hre.config.networks.zkSyncLocal.ethNetwork); - const walletPrivateKey = process.env.WALLET_PRIVATE_KEY || Wallets.richWalletPrivateKey; + + if (!process.env.WALLET_PRIVATE_KEY) { + throw new Error("WALLET_PRIVATE_KEY env variable is not set"); + } // Initialize the wallet. - const wallet = new Wallet(walletPrivateKey as string, syncProvider, ethProvider); + const wallet = new Wallet(process.env.WALLET_PRIVATE_KEY as string, syncProvider, ethProvider); console.log(`Deploying using wallet: ${wallet.address}`); // Wallet ETH balance diff --git a/packages/integration-tests/tests/api/before-all/deposit.test.ts b/packages/integration-tests/tests/api/before-all/deposit.test.ts new file mode 100644 index 0000000000..daaf5367f6 --- /dev/null +++ b/packages/integration-tests/tests/api/before-all/deposit.test.ts @@ -0,0 +1,31 @@ +import { localConfig } from "../../../src/config"; +import { Buffer } from "../../../src/entities"; +import { Logger } from "../../../src/entities"; +import { Helper } from "../../../src/helper"; +import { Playbook } from "../../../src/playbook/playbook"; + +describe("Deposit", () => { + const playbook = new Playbook(); + const helper = new Helper(); + const bufferRoute = "src/playbook/"; + + let result: string; + let token: string; + jest.setTimeout(localConfig.extendedTimeout); + + //@id633 + it("Make a deposit with 0.0000001 ETH ", async () => { + result = await playbook.depositETH("0.0000001"); + await expect(result).not.toBeUndefined(); + await expect(result.includes(Logger.txHashStartsWith)).toBe(true); + }); + + //@id638 + it("Make a deposit with the Custom token ", async () => { + const bufferFile = bufferRoute + Buffer.L1; + token = await helper.getStringFromFile(bufferFile); + result = await playbook.depositERC20("100", token, 18); + await expect(result).not.toBeUndefined(); + await expect(result.includes(Logger.txHashStartsWith)).toBe(true); + }); +}); diff --git a/packages/integration-tests/tests/api/before-all/tokens.test.ts b/packages/integration-tests/tests/api/before-all/tokens.test.ts new file mode 100644 index 0000000000..9f2aee8dca --- /dev/null +++ b/packages/integration-tests/tests/api/before-all/tokens.test.ts @@ -0,0 +1,48 @@ +import * as request from "supertest"; +import { setTimeout } from "timers/promises"; + +import { environment } from "../../../src/config"; +import { localConfig } from "../../../src/config"; +import { Logger, Token } from "../../../src/entities"; +import { Playbook } from "../../../src/playbook/playbook"; + +describe("Tokens", () => { + jest.setTimeout(localConfig.standardTimeout); + + let deployedToken: string; + + describe("Deploy/check the custom ERC20 tokens", () => { + const playbook = new Playbook(); + + //@id603 + it("Deploy custom ERC20 token to L2", async () => { + deployedToken = await playbook.deployERC20toL2(); + expect(deployedToken).toContain(Logger.txHashStartsWith); + }); + + //@id1456 + it("Verify deployed to L2 custom token via /tokens/{tokenAddress}", async () => { + await setTimeout(localConfig.extendedPause); //works unstable without timeout + const apiRoute = `/tokens/${deployedToken}`; + + return request(environment.blockExplorerAPI) + .get(apiRoute) + .expect(200) + .expect((res) => + expect(res.body).toStrictEqual({ + l2Address: deployedToken, + l1Address: null, + symbol: Token.customL2TokenSymbol, + name: Token.customL2TokenName, + decimals: Token.customL2TokenDecimals, + }) + ); + }); + + //@id657 + it("Deploy custom ERC20 token to L1", async () => { + deployedToken = await playbook.deployERC20toL1(); + expect(deployedToken).toContain(Logger.txHashStartsWith); + }); + }); +}); diff --git a/packages/integration-tests/tests/api/common/endpoints.test.ts b/packages/integration-tests/tests/api/common/endpoints.test.ts new file mode 100644 index 0000000000..187d0418ce --- /dev/null +++ b/packages/integration-tests/tests/api/common/endpoints.test.ts @@ -0,0 +1,185 @@ +import * as request from "supertest"; +import { setTimeout } from "timers/promises"; + +import { environment, localConfig } from "../../../src/config"; +import { Buffer } from "../../../src/entities"; +import { Helper } from "../../../src/helper"; + +describe("Endpoints", () => { + const helper = new Helper(); + const bufferRoute = "src/playbook/"; + + jest.setTimeout(localConfig.extendedTimeout); + + describe("/stats", () => { + //@id1515 + it("Verify the response via /stats", async () => { + const apiRoute = `/stats`; + + await setTimeout(localConfig.standardPause); //works unstable without timeout + + return request(environment.blockExplorerAPI) + .get(apiRoute) + .expect(200) + .expect((res) => expect(typeof res.body.lastSealedBatch).toStrictEqual("number")) + .expect((res) => expect(typeof res.body.lastVerifiedBatch).toStrictEqual("number")) + .expect((res) => expect(typeof res.body.lastSealedBlock).toStrictEqual("number")) + .expect((res) => expect(typeof res.body.lastVerifiedBlock).toStrictEqual("number")) + .expect((res) => expect(typeof res.body.totalTransactions).toStrictEqual("number")); + }); + }); + + describe("/tokens", () => { + //@id1508 + it("Verify the response via /tokens", async () => { + const l2DepositedToken = await helper.getStringFromFile(bufferRoute + Buffer.L2deposited); + const l1Token = await helper.getStringFromFile(bufferRoute + Buffer.L1); + const l2Token = await helper.getStringFromFile(bufferRoute + Buffer.L2); + + const apiRoute = `/tokens`; + + await setTimeout(localConfig.standardPause); //works unstable without timeout + + return request(environment.blockExplorerAPI) + .get(apiRoute) + .expect(200) + .expect((res) => expect(Array.isArray(res.body.items)).toStrictEqual(true)) + .expect((res) => + expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ l2Address: l2DepositedToken })) + ) + .expect((res) => expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ l1Address: l1Token }))) + .expect((res) => expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ symbol: "L1" }))) + .expect((res) => expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ name: "L1 ERC20 token" }))) + .expect((res) => expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ decimals: 18 }))) + .expect((res) => expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ l2Address: l2Token }))) + .expect((res) => expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ l1Address: null }))) + .expect((res) => expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ symbol: "L2" }))) + .expect((res) => expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ name: "L2 ERC20 token" }))) + .expect((res) => expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ decimals: 18 }))) + .expect((res) => expect(typeof res.body.meta.totalItems).toStrictEqual("number")) + .expect((res) => expect(typeof res.body.meta.itemCount).toStrictEqual("number")) + .expect((res) => expect(typeof res.body.meta.itemsPerPage).toStrictEqual("number")) + .expect((res) => expect(typeof res.body.meta.totalPages).toStrictEqual("number")) + .expect((res) => expect(typeof res.body.meta.currentPage).toStrictEqual("number")) + .expect((res) => expect(res.body.links.first).toStrictEqual("tokens?limit=10")) + .expect((res) => expect(res.body.links.previous).toStrictEqual("")) + .expect((res) => expect(typeof res.body.links.next).toStrictEqual("string")) + .expect((res) => expect(typeof res.body.links.last).toStrictEqual("string")); + }); + }); + + describe("/batches", () => { + //@id1513 + it("Verify the response via /batches", async () => { + const apiRoute = `/batches`; + + await setTimeout(localConfig.standardPause); //works unstable without timeout + + return request(environment.blockExplorerAPI) + .get(apiRoute) + .expect(200) + .expect((res) => expect(Array.isArray(res.body.items)).toStrictEqual(true)) + .expect((res) => expect(res.body.items.length).toBeGreaterThanOrEqual(1)) + .expect((res) => expect(typeof res.body.meta.totalItems).toStrictEqual("number")) + .expect((res) => expect(typeof res.body.meta.itemCount).toStrictEqual("number")) + .expect((res) => expect(typeof res.body.meta.itemsPerPage).toStrictEqual("number")) + .expect((res) => expect(typeof res.body.meta.totalPages).toStrictEqual("number")) + .expect((res) => expect(typeof res.body.meta.currentPage).toStrictEqual("number")) + .expect((res) => expect(typeof res.body.links.first).toStrictEqual("string")) + .expect((res) => expect(typeof res.body.links.previous).toStrictEqual("string")) + .expect((res) => expect(typeof res.body.links.next).toStrictEqual("string")) + .expect((res) => expect(typeof res.body.links.last).toStrictEqual("string")); + }); + + //@id1514 + it("Verify the response via /batches/{batchNumber}", async () => { + const batches = await request(environment.blockExplorerAPI).get("/batches"); + + const batchNumber = batches.body.items[0].number; + + const apiRoute = `/batches/${batchNumber}`; + + await setTimeout(localConfig.standardPause); //works unstable without timeout + + return request(environment.blockExplorerAPI) + .get(apiRoute) + .expect(200) + .expect((res) => expect(res.body.number).toStrictEqual(batchNumber)) + .expect((res) => expect(typeof res.body.timestamp).toStrictEqual("string")) + .expect((res) => expect(typeof res.body.rootHash).toStrictEqual("string")) + .expect((res) => expect(typeof res.body.executedAt).toStrictEqual("string")) + .expect((res) => expect(typeof res.body.l1TxCount).toStrictEqual("number")) + .expect((res) => expect(typeof res.body.l2TxCount).toStrictEqual("number")) + .expect((res) => expect(typeof res.body.commitTxHash).toStrictEqual("string")) + .expect((res) => expect(typeof res.body.committedAt).toStrictEqual("string")) + .expect((res) => expect(typeof res.body.proveTxHash).toStrictEqual("string")) + .expect((res) => expect(typeof res.body.provenAt).toStrictEqual("string")) + .expect((res) => expect(typeof res.body.executeTxHash).toStrictEqual("string")) + .expect((res) => expect(typeof res.body.l1GasPrice).toStrictEqual("string")) + .expect((res) => expect(typeof res.body.l2FairGasPrice).toStrictEqual("string")) + .expect((res) => expect(typeof res.body.size).toStrictEqual("number")) + .expect((res) => expect(res.body.status).toStrictEqual("verified")); + }); + }); + + describe("/blocks", () => { + //@id1511 + it("Verify the response via /blocks", async () => { + const apiRoute = `/blocks`; + + await setTimeout(localConfig.extendedPause); //works unstable without timeout + + return request(environment.blockExplorerAPI) + .get(apiRoute) + .expect(200) + .expect((res) => expect(Array.isArray(res.body.items)).toStrictEqual(true)) + .expect((res) => expect(res.body.items.length).toBeGreaterThan(1)) + .expect((res) => expect(typeof res.body.meta.totalItems).toStrictEqual("number")) + .expect((res) => expect(typeof res.body.meta.itemCount).toStrictEqual("number")) + .expect((res) => expect(typeof res.body.meta.itemsPerPage).toStrictEqual("number")) + .expect((res) => expect(typeof res.body.meta.totalPages).toStrictEqual("number")) + .expect((res) => expect(typeof res.body.meta.currentPage).toStrictEqual("number")) + .expect((res) => expect(typeof res.body.links.first).toStrictEqual("string")) + .expect((res) => expect(typeof res.body.links.previous).toStrictEqual("string")) + .expect((res) => expect(typeof res.body.links.next).toStrictEqual("string")) + .expect((res) => expect(typeof res.body.links.last).toStrictEqual("string")); + }); + + //@id1512 + it("Verify the response via /blocks/{/blockNumber}", async () => { + const blocks = await request(environment.blockExplorerAPI).get("/blocks"); + + const blockNumber = blocks.body.items[0].number; + + const apiRoute = `/blocks/${blockNumber}`; + + await setTimeout(localConfig.extendedPause); //works unstable without timeout + + return ( + request(environment.blockExplorerAPI) + .get(apiRoute) + .expect(200) + .expect((res) => expect(res.body.number).toStrictEqual(blockNumber)) + .expect((res) => expect(typeof res.body.hash).toStrictEqual("string")) + .expect((res) => expect(typeof res.body.timestamp).toStrictEqual("string")) + .expect((res) => expect(typeof res.body.gasUsed).toStrictEqual("string")) + .expect((res) => expect(typeof res.body.l1BatchNumber).toStrictEqual("number")) + .expect((res) => expect(typeof res.body.l1TxCount).toStrictEqual("number")) + .expect((res) => expect(typeof res.body.l2TxCount).toStrictEqual("number")) + .expect((res) => expect(typeof res.body.parentHash).toStrictEqual("string")) + .expect((res) => expect(typeof res.body.gasLimit).toStrictEqual("string")) + .expect((res) => expect(typeof res.body.baseFeePerGas).toStrictEqual("string")) + .expect((res) => expect(typeof res.body.extraData).toStrictEqual("string")) + .expect((res) => expect(typeof res.body.size).toStrictEqual("number")) + .expect((res) => expect(typeof res.body.status).toStrictEqual("string")) + .expect((res) => expect(typeof res.body.isL1BatchSealed).toStrictEqual("boolean")) + .expect((res) => expect(typeof res.body.commitTxHash).toStrictEqual("string")) + // .expect((res) => expect(typeof res.body.commitTxHash).toStrictEqual("string")) //unstable on a CI + .expect((res) => expect(typeof res.body.proveTxHash).toStrictEqual("string")) + .expect((res) => expect(typeof res.body.committedAt).toStrictEqual("string")) + .expect((res) => expect(typeof res.body.executedAt).toStrictEqual("string")) + .expect((res) => expect(typeof res.body.provenAt).toStrictEqual("string")) + ); + }); + }); +}); diff --git a/packages/integration-tests/tests/api/common/nft.test.ts b/packages/integration-tests/tests/api/common/nft.test.ts new file mode 100644 index 0000000000..ed6271a478 --- /dev/null +++ b/packages/integration-tests/tests/api/common/nft.test.ts @@ -0,0 +1,54 @@ +import * as request from "supertest"; +import { setTimeout } from "timers/promises"; + +import { environment } from "../../../src/config"; +import { localConfig } from "../../../src/config"; +import { Logger } from "../../../src/entities"; +import { Playbook } from "../../../src/playbook/playbook"; + +describe("NFTs", () => { + jest.setTimeout(localConfig.standardTimeout); + + let deployedToken: string; + + describe("Deploy/check the NFT", () => { + jest.setTimeout(localConfig.standardTimeout); + const playbook = new Playbook(); + + //@id672 + it("Deploy the NFT to L1", async () => { + deployedToken = await playbook.deployNFTtoL1(); + expect(deployedToken).toContain(Logger.txHashStartsWith); + }); + + //@id671 + it("Deploy the NFT to L2", async () => { + deployedToken = await playbook.deployNFTtoL2(); + expect(deployedToken).toContain(Logger.txHashStartsWith); + }); + + //@id1457 + it("Verify deployed to L2 NFT via /address/{address}", async () => { + await setTimeout(localConfig.extendedPause); + const apiRoute = `/address/${deployedToken}`; + + return request(environment.blockExplorerAPI) + .get(apiRoute) + .expect(200) + .expect((res) => + expect(res.body).toEqual( + expect.objectContaining({ + type: "contract", + address: deployedToken, + balances: { + [`${deployedToken}`]: { + balance: "1", + token: null, + }, + }, + }) + ) + ); + }); + }); +}); diff --git a/packages/integration-tests/tests/api/common/transfers.test.ts b/packages/integration-tests/tests/api/common/transfers.test.ts new file mode 100644 index 0000000000..2f4bb9b1d0 --- /dev/null +++ b/packages/integration-tests/tests/api/common/transfers.test.ts @@ -0,0 +1,59 @@ +import * as request from "supertest"; +import { setTimeout } from "timers/promises"; + +import { environment } from "../../../src/config"; +import { localConfig } from "../../../src/config"; +import { Buffer, Wallets } from "../../../src/entities"; +import { Helper } from "../../../src/helper"; +import { Playbook } from "../../../src/playbook/playbook"; + +describe("Transfer", () => { + jest.setTimeout(localConfig.standardTimeout); + const helper = new Helper(); + const playbook = new Playbook(); + const bufferFile = "src/playbook/" + Buffer.L2; + let txHashEth: string; + let txHashCust: string; + let token: string; + + beforeAll(async () => { + token = await helper.getStringFromFile(bufferFile); + txHashEth = await playbook.transferETH("0.000001"); + txHashCust = await playbook.transferERC20("0.01", token, "L2"); + + return [txHashCust, txHashEth]; + }); + + //@id1447 + it("Verify transfer ETH L2-L2 via /transactions/{transactionHash}/transfers", async () => { + const apiRoute = `/transactions/${txHashEth}/transfers`; + await setTimeout(localConfig.standardPause); + + return request(environment.blockExplorerAPI) + .get(apiRoute) + .expect(200) + .expect((res) => expect(res.body.items[1].from).toBe(Wallets.richWalletAddress)) + .expect((res) => expect(res.body.items[1].to).toBe(Wallets.mainWalletAddress)) + .expect((res) => expect(res.body.items[1].transactionHash).toBe(txHashEth)) + .expect((res) => expect(res.body.items[1].amount).toBe("1000000000000")) + .expect((res) => expect(res.body.items[1].type).toBe("transfer")); + }); + + //@id1448 + it("Verify the custom ERC20 token transfer via /tokens/{address}/transfers", async () => { + const apiRoute = `/tokens/${token}/transfers?page=1&limit=10`; + token = await helper.getStringFromFile(bufferFile); + + await setTimeout(localConfig.standardPause); //works unstable without timeout + + return request(environment.blockExplorerAPI) + .get(apiRoute) + .expect(200) + .expect((res) => expect(res.body.items[0].amount).toBe("10000000000000000")) + .expect((res) => expect(res.body.items[0].from).toBe(Wallets.richWalletAddress)) + .expect((res) => expect(res.body.items[0].to).toBe(Wallets.secondWalletAddress)) + .expect((res) => expect(res.body.items[0].token).toEqual(expect.objectContaining({ l2Address: token }))) + .expect((res) => expect(res.body.items[0]).toEqual(expect.objectContaining({ transactionHash: txHashCust }))) + .expect((res) => expect(res.body.items[0]).toEqual(expect.objectContaining({ type: "transfer" }))); + }); +}); diff --git a/packages/integration-tests/tests/api/common/withdrawal.test.ts b/packages/integration-tests/tests/api/common/withdrawal.test.ts new file mode 100644 index 0000000000..68e716b0ee --- /dev/null +++ b/packages/integration-tests/tests/api/common/withdrawal.test.ts @@ -0,0 +1,345 @@ +import * as request from "supertest"; +import { setTimeout } from "timers/promises"; + +import { environment, localConfig } from "../../../src/config"; +import { Buffer, Token, Wallets } from "../../../src/entities"; +import { Logger } from "../../../src/entities"; +import { Helper } from "../../../src/helper"; +import { Playbook } from "../../../src/playbook/playbook"; + +describe("Withdrawal", () => { + const playbook = new Playbook(); + const helper = new Helper(); + const playbookRoot = "src/playbook"; + const l2Token = playbookRoot + "/" + Buffer.L2deposited; + const l1Token = playbookRoot + "/" + Buffer.L1; + + let result: string; + jest.setTimeout(localConfig.extendedTimeout); + + describe("Withdrawal ETH to the own address", () => { + //@id639 + it("Make a withdrawal to the own address with 0.0000001 ETH ", async () => { + result = await playbook.withdrawETH(); + await expect(result).not.toBeUndefined(); + await expect(result.includes(Logger.txHashStartsWith)).toBe(true); + }); + + //@id1458 + it("Verify the ETH withdrawal via /transactions/{transactionHash}", async () => { + await setTimeout(localConfig.standardPause); //works unstable without timeout + const apiRoute = `/transactions/${result}`; + + return request(environment.blockExplorerAPI) + .get(apiRoute) + .expect(200) + .expect((res) => expect(res.body.hash).toBe(result)) + .expect((res) => expect(res.body.to).toBe("0x000000000000000000000000000000000000800A")) + .expect((res) => expect(res.body.from).toBe(Wallets.richWalletAddress)) + .expect((res) => expect(res.body.value).toBe("9000000000000")); + }); + + //@id1459 + it("Verify the ETH withdrawal via /transactions/{transactionHash}/transfers", async () => { + await setTimeout(localConfig.standardPause); //works unstable without timeout + const apiRoute = `/transactions/${result}/transfers`; + + return request(environment.blockExplorerAPI) + .get(apiRoute) + .expect(200) + .expect((res) => + expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ from: Wallets.richWalletAddress })) + ) + .expect((res) => + expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ to: Token.ETHER_PULL_Address })) + ) + .expect((res) => expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ transactionHash: result }))) + .expect((res) => expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ type: "fee" }))) + .expect((res) => + expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ from: Wallets.richWalletAddress })) + ) + .expect((res) => + expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ to: Token.ETHER_ERC20_Address })) + ) + .expect((res) => expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ transactionHash: result }))) + .expect((res) => expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ amount: "9000000000000" }))) + .expect((res) => expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ type: "transfer" }))) + .expect((res) => + expect(res.body.items[2]).toStrictEqual(expect.objectContaining({ from: Wallets.richWalletAddress })) + ) + .expect((res) => + expect(res.body.items[2]).toStrictEqual(expect.objectContaining({ to: Wallets.richWalletAddress })) + ) + .expect((res) => expect(res.body.items[2]).toStrictEqual(expect.objectContaining({ transactionHash: result }))) + .expect((res) => expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ amount: "9000000000000" }))) + .expect((res) => expect(res.body.items[2]).toStrictEqual(expect.objectContaining({ type: "withdrawal" }))) + .expect((res) => + expect(res.body.items[3]).toStrictEqual(expect.objectContaining({ from: Token.ETHER_PULL_Address })) + ) + .expect((res) => + expect(res.body.items[3]).toStrictEqual(expect.objectContaining({ to: Wallets.richWalletAddress })) + ) + .expect((res) => expect(res.body.items[3]).toStrictEqual(expect.objectContaining({ transactionHash: result }))) + .expect((res) => expect(res.body.items[3]).toStrictEqual(expect.objectContaining({ type: "refund" }))); + }); + }); + + describe("Withdrawal ETH to the other address", () => { + //@id640 + it("Make a withdrawal to the other address with 0.0000001 ETH ", async () => { + result = await playbook.withdrawETHtoOtherAddress(); + await expect(result).not.toBeUndefined(); + await expect(result.includes(Logger.txHashStartsWith)).toBe(true); + }); + + //@id1460 + it("Verify the ETH withdrawal to the other address via /transactions/{transactionHash}", async () => { + await setTimeout(localConfig.standardPause); //works unstable without timeout + const apiRoute = `/transactions/${result}`; + + return request(environment.blockExplorerAPI) + .get(apiRoute) + .expect(200) + .expect((res) => expect(res.body.hash).toBe(result)) + .expect((res) => expect(res.body.to).toBe("0x000000000000000000000000000000000000800A")) + .expect((res) => expect(res.body.from).toBe(Wallets.richWalletAddress)) + .expect((res) => expect(res.body.value).toBe("9000000000000")); + }); + + //@id1461 + it("Verify the ETH withdrawal to the other address via /transactions/{transactionHash}/transfers", async () => { + await setTimeout(localConfig.standardPause); //works unstable without timeout + const apiRoute = `/transactions/${result}/transfers`; + + return request(environment.blockExplorerAPI) + .get(apiRoute) + .expect(200) + .expect((res) => + expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ from: Wallets.richWalletAddress })) + ) + .expect((res) => + expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ to: Token.ETHER_PULL_Address })) + ) + .expect((res) => expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ transactionHash: result }))) + .expect((res) => expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ type: "fee" }))) + .expect((res) => + expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ from: Wallets.richWalletAddress })) + ) + .expect((res) => + expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ to: Token.ETHER_ERC20_Address })) + ) + .expect((res) => expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ transactionHash: result }))) + .expect((res) => expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ amount: "9000000000000" }))) + .expect((res) => expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ type: "transfer" }))) + .expect((res) => + expect(res.body.items[2]).toStrictEqual(expect.objectContaining({ from: Wallets.richWalletAddress })) + ) + .expect((res) => + expect(res.body.items[2]).toStrictEqual(expect.objectContaining({ to: Wallets.mainWalletAddress })) + ) + .expect((res) => expect(res.body.items[2]).toStrictEqual(expect.objectContaining({ transactionHash: result }))) + .expect((res) => expect(res.body.items[2]).toStrictEqual(expect.objectContaining({ amount: "9000000000000" }))) + .expect((res) => expect(res.body.items[2]).toStrictEqual(expect.objectContaining({ type: "withdrawal" }))) + .expect((res) => + expect(res.body.items[3]).toStrictEqual(expect.objectContaining({ from: Token.ETHER_PULL_Address })) + ) + .expect((res) => + expect(res.body.items[3]).toStrictEqual(expect.objectContaining({ to: Wallets.richWalletAddress })) + ) + .expect((res) => expect(res.body.items[3]).toStrictEqual(expect.objectContaining({ transactionHash: result }))) + .expect((res) => expect(res.body.items[3]).toStrictEqual(expect.objectContaining({ type: "refund" }))); + }); + }); + + describe("Withdrawal the custom token to the own address", () => { + //@id641 + it("Make the custom token withdrawal to the own address", async () => { + const customToken = await helper.getStringFromFile(l2Token); + result = await playbook.withdrawERC20(customToken); + await expect(result).not.toBeUndefined(); + await expect(result.includes(Logger.txHashStartsWith)).toBe(true); + }); + + //@id1462 + it("Verify the custom token withdrawal via /transactions/{transactionHash}", async () => { + await setTimeout(localConfig.standardPause); //works unstable without timeout + const apiRoute = `/transactions/${result}`; + + return request(environment.blockExplorerAPI) + .get(apiRoute) + .expect(200) + .expect((res) => expect(res.body.hash).toBe(result)) + .expect((res) => expect(res.body.from).toBe(Wallets.richWalletAddress)); + }); + + //@id1463 + it("Verify the custom token withdrawal via /transactions/{transactionHash}/transfers", async () => { + await setTimeout(localConfig.standardPause); //works unstable without timeout + const customTokenL2 = await helper.getStringFromFile(l2Token); + const customTokenL1 = await helper.getStringFromFile(l1Token); + const apiRoute = `/transactions/${result}/transfers`; + + return request(environment.blockExplorerAPI) + .get(apiRoute) + .expect(200) + .expect((res) => + expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ from: Wallets.richWalletAddress })) + ) + .expect((res) => + expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ to: Token.ETHER_PULL_Address })) + ) + .expect((res) => expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ transactionHash: result }))) + .expect((res) => expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ type: "fee" }))) + .expect((res) => + expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ from: Wallets.richWalletAddress })) + ) + .expect((res) => expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ to: Token.ETHER_Address }))) + .expect((res) => expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ transactionHash: result }))) + .expect((res) => + expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ amount: "200000000000000000" })) + ) + .expect((res) => expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ type: "transfer" }))) + .expect((res) => + expect(res.body.items[1]).toStrictEqual( + expect.objectContaining({ + token: { + l2Address: customTokenL2, + l1Address: customTokenL1, + symbol: "L1", + name: "L1 ERC20 token", + decimals: 18, + }, + }) + ) + ) + .expect((res) => + expect(res.body.items[2]).toStrictEqual(expect.objectContaining({ from: Wallets.richWalletAddress })) + ) + .expect((res) => + expect(res.body.items[2]).toStrictEqual(expect.objectContaining({ to: Wallets.richWalletAddress })) + ) + .expect((res) => expect(res.body.items[2]).toStrictEqual(expect.objectContaining({ transactionHash: result }))) + .expect((res) => + expect(res.body.items[2]).toStrictEqual(expect.objectContaining({ amount: "200000000000000000" })) + ) + .expect((res) => expect(res.body.items[2]).toStrictEqual(expect.objectContaining({ type: "withdrawal" }))) + .expect((res) => + expect(res.body.items[1]).toStrictEqual( + expect.objectContaining({ + token: { + l2Address: customTokenL2, + l1Address: customTokenL1, + symbol: "L1", + name: "L1 ERC20 token", + decimals: 18, + }, + }) + ) + ) + .expect((res) => + expect(res.body.items[3]).toStrictEqual(expect.objectContaining({ from: Token.ETHER_PULL_Address })) + ) + .expect((res) => + expect(res.body.items[3]).toStrictEqual(expect.objectContaining({ to: Wallets.richWalletAddress })) + ) + .expect((res) => expect(res.body.items[3]).toStrictEqual(expect.objectContaining({ transactionHash: result }))) + .expect((res) => expect(res.body.items[3]).toStrictEqual(expect.objectContaining({ type: "refund" }))); + }); + }); + + describe("Withdrawal the custom token to the other address", () => { + //@id643 + it("Make the custom token withdrawal to the other address", async () => { + const customToken = await helper.getStringFromFile(l2Token); + result = await playbook.withdrawERC20toOtherAddress(customToken); + await expect(result).not.toBeUndefined(); + await expect(result.includes(Logger.txHashStartsWith)).toBe(true); + }); + + //@id1462 + it("Verify the custom token withdrawal via /transactions/{transactionHash}", async () => { + await setTimeout(localConfig.standardPause); //works unstable without timeout + const apiRoute = `/transactions/${result}`; + + return request(environment.blockExplorerAPI) + .get(apiRoute) + .expect(200) + .expect((res) => expect(res.body.hash).toBe(result)) + .expect((res) => expect(res.body.from).toBe(Wallets.richWalletAddress)); + }); + + //@id1463 + it("Verify the custom token withdrawal via /transactions/{transactionHash}/transfers", async () => { + await setTimeout(localConfig.standardPause); //works unstable without timeout + const customTokenL2 = await helper.getStringFromFile(l2Token); + const customTokenL1 = await helper.getStringFromFile(l1Token); + const apiRoute = `/transactions/${result}/transfers`; + + return request(environment.blockExplorerAPI) + .get(apiRoute) + .expect(200) + .expect((res) => + expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ from: Wallets.richWalletAddress })) + ) + .expect((res) => + expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ to: Token.ETHER_PULL_Address })) + ) + .expect((res) => expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ transactionHash: result }))) + .expect((res) => expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ type: "fee" }))) + .expect((res) => + expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ from: Wallets.richWalletAddress })) + ) + .expect((res) => expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ to: Token.ETHER_Address }))) + .expect((res) => expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ transactionHash: result }))) + .expect((res) => + expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ amount: "200000000000000000" })) + ) + .expect((res) => expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ type: "transfer" }))) + .expect((res) => + expect(res.body.items[1]).toStrictEqual( + expect.objectContaining({ + token: { + l2Address: customTokenL2, + l1Address: customTokenL1, + symbol: "L1", + name: "L1 ERC20 token", + decimals: 18, + }, + }) + ) + ) + .expect((res) => + expect(res.body.items[2]).toStrictEqual(expect.objectContaining({ from: Wallets.richWalletAddress })) + ) + .expect((res) => + expect(res.body.items[2]).toStrictEqual(expect.objectContaining({ to: Wallets.mainWalletAddress })) + ) + .expect((res) => expect(res.body.items[2]).toStrictEqual(expect.objectContaining({ transactionHash: result }))) + .expect((res) => + expect(res.body.items[2]).toStrictEqual(expect.objectContaining({ amount: "200000000000000000" })) + ) + .expect((res) => expect(res.body.items[2]).toStrictEqual(expect.objectContaining({ type: "withdrawal" }))) + .expect((res) => + expect(res.body.items[1]).toStrictEqual( + expect.objectContaining({ + token: { + l2Address: customTokenL2, + l1Address: customTokenL1, + symbol: "L1", + name: "L1 ERC20 token", + decimals: 18, + }, + }) + ) + ) + .expect((res) => + expect(res.body.items[3]).toStrictEqual(expect.objectContaining({ from: Token.ETHER_PULL_Address })) + ) + .expect((res) => + expect(res.body.items[3]).toStrictEqual(expect.objectContaining({ to: Wallets.richWalletAddress })) + ) + .expect((res) => expect(res.body.items[3]).toStrictEqual(expect.objectContaining({ transactionHash: result }))) + .expect((res) => expect(res.body.items[3]).toStrictEqual(expect.objectContaining({ type: "refund" }))); + }); + }); +}); diff --git a/packages/integration-tests/tests/api/transactions/multiCall.test.ts b/packages/integration-tests/tests/api/transactions/multiCall.test.ts new file mode 100644 index 0000000000..310a5fea9b --- /dev/null +++ b/packages/integration-tests/tests/api/transactions/multiCall.test.ts @@ -0,0 +1,333 @@ +import * as request from "supertest"; +import { setTimeout } from "timers/promises"; + +import { environment, localConfig } from "../../../src/config"; +import { Buffer, Logger, Token, TransactionsType, Wallets } from "../../../src/entities"; +import { Helper } from "../../../src/helper"; +import { Playbook } from "../../../src/playbook/playbook"; + +describe("Multicall transactions", () => { + jest.setTimeout(localConfig.extendedTimeout); + const playbook = new Playbook(); + const helper = new Helper(); + const bufferRoute = "src/playbook/"; + let txHash: string; + let txMulticall: string; + let contract: string; + + //@id689 + it("Deploy the Multicall contracts", async () => { + const contract: string[] = await playbook.deployMultiCallContracts(); + expect(contract[0]).toContain(Logger.txHashStartsWith); + expect(contract[1]).toContain(Logger.txHashStartsWith); + expect(contract[2]).toContain(Logger.txHashStartsWith); + }); + + //@id1464 + it("Verify the deployed Root contract via /address/{address}", async () => { + await setTimeout(localConfig.standardPause); //works unstable without timeout + contract = await helper.getStringFromFile(bufferRoute + Buffer.addressMultiCallRoot); + txHash = await helper.getStringFromFile(bufferRoute + Buffer.txMultiCallRoot); + + const apiRoute = `/address/${contract}`; + + return request(environment.blockExplorerAPI) + .get(apiRoute) + .expect(200) + .expect((res) => expect(res.body).toStrictEqual(expect.objectContaining({ type: "contract" }))) + .expect((res) => expect(res.body).toStrictEqual(expect.objectContaining({ address: contract }))) + .expect((res) => + expect(res.body).toStrictEqual(expect.objectContaining({ creatorAddress: Wallets.richWalletAddress })) + ) + .expect((res) => expect(res.body).toStrictEqual(expect.objectContaining({ creatorTxHash: txHash }))) + .expect((res) => expect(res.body).toStrictEqual(expect.objectContaining({ balances: {} }))); + }); + + //@id1465 + it("Verify the deployed Middle contract via /address/{address}", async () => { + await setTimeout(localConfig.standardPause); //works unstable without timeout + contract = await helper.getStringFromFile(bufferRoute + Buffer.addressMultiCallMiddle); + txHash = await helper.getStringFromFile(bufferRoute + Buffer.txMultiCallMiddle); + + const apiRoute = `/address/${contract}`; + + return request(environment.blockExplorerAPI) + .get(apiRoute) + .expect(200) + .expect((res) => expect(res.body).toStrictEqual(expect.objectContaining({ type: "contract" }))) + .expect((res) => expect(res.body).toStrictEqual(expect.objectContaining({ address: contract }))) + .expect((res) => + expect(res.body).toStrictEqual(expect.objectContaining({ creatorAddress: Wallets.richWalletAddress })) + ) + .expect((res) => expect(res.body).toStrictEqual(expect.objectContaining({ creatorTxHash: txHash }))) + .expect((res) => expect(res.body).toStrictEqual(expect.objectContaining({ balances: {} }))); + }); + + //@id1466 + it("Verify the deployed Caller contract via /address/{address}", async () => { + await setTimeout(localConfig.standardPause); //works unstable without timeout + contract = await helper.getStringFromFile(bufferRoute + Buffer.addressMultiCallCaller); + txHash = await helper.getStringFromFile(bufferRoute + Buffer.txMultiCallCaller); + + const apiRoute = `/address/${contract}`; + + return request(environment.blockExplorerAPI) + .get(apiRoute) + .expect(200) + .expect((res) => expect(res.body).toStrictEqual(expect.objectContaining({ type: "contract" }))) + .expect((res) => expect(res.body).toStrictEqual(expect.objectContaining({ address: contract }))) + .expect((res) => + expect(res.body).toStrictEqual(expect.objectContaining({ creatorAddress: Wallets.richWalletAddress })) + ) + .expect((res) => expect(res.body).toStrictEqual(expect.objectContaining({ creatorTxHash: txHash }))) + .expect((res) => expect(res.body).toStrictEqual(expect.objectContaining({ balances: {} }))); + }); + + //@id690:I --> @id1467 + it("Use the multicall contracts", async () => { + txMulticall = await playbook.useMultiCallContracts(); + expect(txMulticall).toContain(Logger.txHashStartsWith); + }); + + describe("Verify the multicall transactions via /transactions/${txHash}", () => { + //@id1464:I --> @id1468 + it("Verify transaction for the Root contract via /transactions/${txHash}", async () => { + await setTimeout(localConfig.standardPause); //works unstable without timeout + + txHash = await helper.getStringFromFile(bufferRoute + Buffer.txMultiCallRoot); + const apiRoute = `/transactions/${txHash}`; + + return request(environment.blockExplorerAPI) + .get(apiRoute) + .expect(200) + .expect((res) => expect(res.body).toStrictEqual(expect.objectContaining({ hash: txHash }))) + .expect((res) => expect(res.body).toStrictEqual(expect.objectContaining({ from: Wallets.richWalletAddress }))) + .expect((res) => expect(res.body).toStrictEqual(expect.objectContaining({ value: "0" }))) + .expect((res) => expect(res.body).toStrictEqual(expect.objectContaining({ isL1Originated: false }))) + .expect((res) => expect(res.body).toStrictEqual(expect.objectContaining({ transactionIndex: 0 }))); + }); + + //@id1465:I --> @id1469 + it("Verify transaction for the Middle contract via /transactions/${txHash}", async () => { + await setTimeout(localConfig.standardPause); //works unstable without timeout + + txHash = await helper.getStringFromFile(bufferRoute + Buffer.txMultiCallMiddle); + const apiRoute = `/transactions/${txHash}`; + + return request(environment.blockExplorerAPI) + .get(apiRoute) + .expect(200) + .expect((res) => expect(res.body).toStrictEqual(expect.objectContaining({ hash: txHash }))) + .expect((res) => expect(res.body).toStrictEqual(expect.objectContaining({ from: Wallets.richWalletAddress }))) + .expect((res) => expect(res.body).toStrictEqual(expect.objectContaining({ value: "0" }))) + .expect((res) => expect(res.body).toStrictEqual(expect.objectContaining({ isL1Originated: false }))) + .expect((res) => expect(res.body).toStrictEqual(expect.objectContaining({ transactionIndex: 0 }))); + }); + + //@id1466:I --> @id1470 + it("Verify transaction for the Caller contract via /transactions/${txHash}", async () => { + await setTimeout(localConfig.standardPause); //works unstable without timeout + + txHash = await helper.getStringFromFile(bufferRoute + Buffer.txMultiCallCaller); + const apiRoute = `/transactions/${txHash}`; + + return request(environment.blockExplorerAPI) + .get(apiRoute) + .expect(200) + .expect((res) => expect(res.body).toStrictEqual(expect.objectContaining({ hash: txHash }))) + .expect((res) => expect(res.body).toStrictEqual(expect.objectContaining({ from: Wallets.richWalletAddress }))) + .expect((res) => expect(res.body).toStrictEqual(expect.objectContaining({ value: "0" }))) + .expect((res) => expect(res.body).toStrictEqual(expect.objectContaining({ isL1Originated: false }))) + .expect((res) => expect(res.body).toStrictEqual(expect.objectContaining({ transactionIndex: 0 }))); + }); + + //@id1471 + it("Verify transaction for the use multicall contract via /transactions/${txHash}", async () => { + await setTimeout(localConfig.standardPause); //works unstable without timeout + + txHash = await helper.getStringFromFile(bufferRoute + Buffer.txUseMultiCallContracts); + const apiRoute = `/transactions/${txHash}`; + + return request(environment.blockExplorerAPI) + .get(apiRoute) + .expect(200) + .expect((res) => expect(res.body).toStrictEqual(expect.objectContaining({ hash: txHash }))) + .expect((res) => expect(res.body).toStrictEqual(expect.objectContaining({ from: Wallets.richWalletAddress }))) + .expect((res) => expect(res.body).toStrictEqual(expect.objectContaining({ value: "0" }))) + .expect((res) => expect(res.body).toStrictEqual(expect.objectContaining({ isL1Originated: false }))) + .expect((res) => expect(res.body).toStrictEqual(expect.objectContaining({ transactionIndex: 0 }))); + }); + }); + + describe("Verify the multicall transactions via /transactions/${txHash}/transfers", () => { + //@id1472 + it("Verify transaction for the Root contract via /transactions/${txHash}/transfers", async () => { + await setTimeout(localConfig.standardPause); //works unstable without timeout + + txHash = await helper.getStringFromFile(bufferRoute + Buffer.txMultiCallRoot); + const apiRoute = `/transactions/${txHash}/transfers?page=1&limit=10`; + + return request(environment.blockExplorerAPI) + .get(apiRoute) + .expect(200) + .expect((res) => + expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ from: Wallets.richWalletAddress })) + ) + .expect((res) => + expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ to: Token.ETHER_PULL_Address })) + ) + .expect((res) => expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ transactionHash: txHash }))) + .expect((res) => + expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ tokenAddress: Token.ETHER_ERC20_Address })) + ) + .expect((res) => + expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ type: TransactionsType.fee })) + ) + .expect((res) => expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ fields: null }))) + .expect((res) => expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ token: null }))) + .expect((res) => + expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ from: Token.ETHER_PULL_Address })) + ) + .expect((res) => + expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ to: Wallets.richWalletAddress })) + ) + .expect((res) => expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ transactionHash: txHash }))) + .expect((res) => + expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ tokenAddress: Token.ETHER_ERC20_Address })) + ) + .expect((res) => + expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ type: TransactionsType.refund })) + ) + .expect((res) => expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ fields: null }))) + .expect((res) => expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ token: null }))); + }); + + //@id1473 + it("Verify transaction for the Middle contract via /transactions/${txHash}/transfers", async () => { + await setTimeout(localConfig.standardPause); //works unstable without timeout + + txHash = await helper.getStringFromFile(bufferRoute + Buffer.txMultiCallMiddle); + const apiRoute = `/transactions/${txHash}/transfers?page=1&limit=10`; + + return request(environment.blockExplorerAPI) + .get(apiRoute) + .expect(200) + .expect((res) => + expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ from: Wallets.richWalletAddress })) + ) + .expect((res) => + expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ to: Token.ETHER_PULL_Address })) + ) + .expect((res) => expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ transactionHash: txHash }))) + .expect((res) => + expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ tokenAddress: Token.ETHER_ERC20_Address })) + ) + .expect((res) => + expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ type: TransactionsType.fee })) + ) + .expect((res) => expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ fields: null }))) + .expect((res) => expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ token: null }))) + .expect((res) => + expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ from: Token.ETHER_PULL_Address })) + ) + .expect((res) => + expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ to: Wallets.richWalletAddress })) + ) + .expect((res) => expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ transactionHash: txHash }))) + .expect((res) => + expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ tokenAddress: Token.ETHER_ERC20_Address })) + ) + .expect((res) => + expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ type: TransactionsType.refund })) + ) + .expect((res) => expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ fields: null }))) + .expect((res) => expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ token: null }))); + }); + + //@id1474 + it("Verify transaction for the Caller contract via /transactions/${txHash}/transfers", async () => { + await setTimeout(localConfig.standardPause); //works unstable without timeout + + txHash = await helper.getStringFromFile(bufferRoute + Buffer.txMultiCallCaller); + const apiRoute = `/transactions/${txHash}/transfers?page=1&limit=10`; + + return request(environment.blockExplorerAPI) + .get(apiRoute) + .expect(200) + .expect((res) => + expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ from: Wallets.richWalletAddress })) + ) + .expect((res) => + expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ to: Token.ETHER_PULL_Address })) + ) + .expect((res) => expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ transactionHash: txHash }))) + .expect((res) => + expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ tokenAddress: Token.ETHER_ERC20_Address })) + ) + .expect((res) => + expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ type: TransactionsType.fee })) + ) + .expect((res) => expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ fields: null }))) + .expect((res) => expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ token: null }))) + .expect((res) => + expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ from: Token.ETHER_PULL_Address })) + ) + .expect((res) => + expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ to: Wallets.richWalletAddress })) + ) + .expect((res) => expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ transactionHash: txHash }))) + .expect((res) => + expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ tokenAddress: Token.ETHER_ERC20_Address })) + ) + .expect((res) => + expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ type: TransactionsType.refund })) + ) + .expect((res) => expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ fields: null }))) + .expect((res) => expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ token: null }))); + }); + + //@id1475 + it("Verify transaction for the use multicall contract via /transactions/${txHash}/transfers", async () => { + await setTimeout(localConfig.standardPause); //works unstable without timeout + + txHash = await helper.getStringFromFile(bufferRoute + Buffer.txUseMultiCallContracts); + + const apiRoute = `/transactions/${txHash}/transfers?page=1&limit=10`; + await setTimeout(localConfig.standardPause); //works unstable without timeout + + return request(environment.blockExplorerAPI) + .get(apiRoute) + .expect(200) + .expect((res) => + expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ from: Wallets.richWalletAddress })) + ) + .expect((res) => + expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ to: Token.ETHER_PULL_Address })) + ) + .expect((res) => expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ transactionHash: txHash }))) + .expect((res) => + expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ tokenAddress: Token.ETHER_ERC20_Address })) + ) + .expect((res) => + expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ type: TransactionsType.fee })) + ) + .expect((res) => expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ fields: null }))) + .expect((res) => expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ token: null }))) + .expect((res) => + expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ from: Token.ETHER_PULL_Address })) + ) + .expect((res) => + expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ to: Wallets.richWalletAddress })) + ) + .expect((res) => expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ transactionHash: txHash }))) + .expect((res) => + expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ tokenAddress: Token.ETHER_ERC20_Address })) + ) + .expect((res) => + expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ type: TransactionsType.refund })) + ) + .expect((res) => expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ fields: null }))) + .expect((res) => expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ token: null }))); + }); + }); +}); diff --git a/packages/integration-tests/tests/api/transactions/multiTransfer.test.ts b/packages/integration-tests/tests/api/transactions/multiTransfer.test.ts new file mode 100644 index 0000000000..7bdde1c14f --- /dev/null +++ b/packages/integration-tests/tests/api/transactions/multiTransfer.test.ts @@ -0,0 +1,306 @@ +import * as request from "supertest"; +import { setTimeout } from "timers/promises"; + +import { environment, localConfig } from "../../../src/config"; +import { Buffer, Logger, Token, TransactionsType, Wallets } from "../../../src/entities"; +import { Helper } from "../../../src/helper"; +import { Playbook } from "../../../src/playbook/playbook"; + +describe("Mulitransfer ETH", () => { + jest.setTimeout(localConfig.extendedTimeout); + const playbook = new Playbook(); + const helper = new Helper(); + const bufferRoute = "src/playbook/"; + let txHash: string; + let txMultiTransfer: string[]; + let token: string; + let contract: string; + + beforeEach(async () => { + contract = await helper.getStringFromFile(bufferRoute + Buffer.addressMultiTransferETH); + }); + + //@id690 + it("Deploy the multitransfer ETH contract to the L2", async () => { + contract = await playbook.deployMultiTransferETH(); + expect(contract).toContain(Logger.txHashStartsWith); + }); + + //@id1476 + it("Verify the deployed multitransfer contract via /address/{address}", async () => { + await setTimeout(localConfig.standardPause); //works unstable without timeout + + const apiRoute = `/address/${contract}`; + + return request(environment.blockExplorerAPI) + .get(apiRoute) + .expect(200) + .expect((res) => expect(res.body).toStrictEqual(expect.objectContaining({ address: contract }))) + .expect((res) => + expect(res.body).toStrictEqual(expect.objectContaining({ creatorAddress: Wallets.richWalletAddress })) + ); + }); + + //@id690 --> //@id1477 + it("Call the multitransfer contract to the L2", async () => { + txMultiTransfer = await playbook.useMultiTransferETH(); + expect(txMultiTransfer[0]).toContain(Logger.txHashStartsWith); + expect(txMultiTransfer[1]).toContain(Logger.txHashStartsWith); + expect(txMultiTransfer[2]).toContain(Logger.txHashStartsWith); + }); + + describe("Verify the multitransfer transactions via /transactions/${txHash}", () => { + //@id1478 + it("Verify transaction for the ETH via /transactions/${txHash}", async () => { + await setTimeout(localConfig.standardPause); //works unstable without timeout + + txHash = await helper.getStringFromFile(bufferRoute + Buffer.txMultiTransferETH); + const apiRoute = `/transactions/${txHash}`; + + return request(environment.blockExplorerAPI) + .get(apiRoute) + .expect(200) + .expect((res) => expect(res.body).toStrictEqual(expect.objectContaining({ hash: txHash }))) + .expect((res) => expect(res.body).toStrictEqual(expect.objectContaining({ to: contract }))) + .expect((res) => expect(res.body).toStrictEqual(expect.objectContaining({ from: Wallets.richWalletAddress }))) + .expect((res) => expect(res.body).toStrictEqual(expect.objectContaining({ isL1Originated: false }))); + }); + + //@id1479 + it("Verify transaction for the Custom Token I via /transactions/${txHash}", async () => { + await setTimeout(localConfig.standardPause); //works unstable without timeout + + txHash = await helper.getStringFromFile(bufferRoute + Buffer.txMultiTransferCustomTokenI); + contract = await helper.getStringFromFile(bufferRoute + Buffer.L2); + const apiRoute = `/transactions/${txHash}`; + + return request(environment.blockExplorerAPI) + .get(apiRoute) + .expect(200) + .expect((res) => expect(res.body).toStrictEqual(expect.objectContaining({ hash: txHash }))) + .expect((res) => expect(res.body).toStrictEqual(expect.objectContaining({ to: contract }))) + .expect((res) => expect(res.body).toStrictEqual(expect.objectContaining({ from: Wallets.richWalletAddress }))) + .expect((res) => expect(res.body).toStrictEqual(expect.objectContaining({ isL1Originated: false }))); + }); + + //@id1480 + it("Verify transaction for the Custom Token II via /transactions/${txHash}", async () => { + await setTimeout(localConfig.standardPause); //works unstable without timeout + + txHash = await helper.getStringFromFile(bufferRoute + Buffer.txMultiTransferCustomTokenII); + contract = await helper.getStringFromFile(bufferRoute + Buffer.L2deposited); + const apiRoute = `/transactions/${txHash}`; + + return request(environment.blockExplorerAPI) + .get(apiRoute) + .expect(200) + .expect((res) => expect(res.body).toStrictEqual(expect.objectContaining({ hash: txHash }))) + .expect((res) => expect(res.body).toStrictEqual(expect.objectContaining({ to: contract }))) + .expect((res) => expect(res.body).toStrictEqual(expect.objectContaining({ from: Wallets.richWalletAddress }))) + .expect((res) => expect(res.body).toStrictEqual(expect.objectContaining({ isL1Originated: false }))); + }); + }); + + describe("Verify the multitransfer transactions via /transactions/${txHash}/transfer", () => { + beforeAll(async () => { + token = await helper.getStringFromFile(bufferRoute + Buffer.L2); + }); + + //@id1481 + it("Verify transaction for the ETH via /transactions/${txHash}/transfers", async () => { + await setTimeout(localConfig.standardPause); //works unstable without timeout + + txHash = await helper.getStringFromFile(bufferRoute + Buffer.txMultiTransferETH); + const apiRoute = `/transactions/${txHash}/transfers?page=1&limit=10`; + + return request(environment.blockExplorerAPI) + .get(apiRoute) + .expect(200) + .expect((res) => + expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ from: Wallets.richWalletAddress })) + ) + .expect((res) => + expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ to: Token.ETHER_PULL_Address })) + ) + .expect((res) => expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ transactionHash: txHash }))) + .expect((res) => + expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ tokenAddress: Token.ETHER_ERC20_Address })) + ) + .expect((res) => + expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ type: TransactionsType.fee })) + ) + .expect((res) => expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ fields: null }))) + .expect((res) => expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ token: null }))) + .expect((res) => + expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ from: Wallets.richWalletAddress })) + ) + .expect((res) => expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ to: contract }))) + .expect((res) => expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ transactionHash: txHash }))) + .expect((res) => + expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ tokenAddress: Token.ETHER_ERC20_Address })) + ) + .expect((res) => + expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ type: TransactionsType.transfer })) + ) + .expect((res) => expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ fields: null }))) + .expect((res) => expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ token: null }))) + .expect((res) => + expect(res.body.items[2]).toStrictEqual(expect.objectContaining({ from: Token.ETHER_PULL_Address })) + ) + .expect((res) => + expect(res.body.items[2]).toStrictEqual(expect.objectContaining({ to: Wallets.richWalletAddress })) + ) + .expect((res) => expect(res.body.items[2]).toStrictEqual(expect.objectContaining({ transactionHash: txHash }))) + .expect((res) => + expect(res.body.items[2]).toStrictEqual(expect.objectContaining({ tokenAddress: Token.ETHER_ERC20_Address })) + ) + .expect((res) => + expect(res.body.items[2]).toStrictEqual(expect.objectContaining({ type: TransactionsType.refund })) + ) + .expect((res) => expect(res.body.items[2]).toStrictEqual(expect.objectContaining({ fields: null }))) + .expect((res) => expect(res.body.items[2]).toStrictEqual(expect.objectContaining({ token: null }))); + }); + + //@id1482 + it("Verify transaction for the Custom tokenI via /transactions/${txHash}/transfers", async () => { + await setTimeout(localConfig.standardPause); //works unstable without timeout + contract = await helper.getStringFromFile(bufferRoute + Buffer.addressMultiTransferETH); + txHash = await helper.getStringFromFile(bufferRoute + Buffer.txMultiTransferCustomTokenI); + const apiRoute = `/transactions/${txHash}/transfers?page=1&limit=10`; + + return request(environment.blockExplorerAPI) + .get(apiRoute) + .expect(200) + .expect((res) => + expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ from: Wallets.richWalletAddress })) + ) + .expect((res) => + expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ to: Token.ETHER_PULL_Address })) + ) + .expect((res) => expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ transactionHash: txHash }))) + .expect((res) => + expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ tokenAddress: Token.ETHER_ERC20_Address })) + ) + .expect((res) => + expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ type: TransactionsType.fee })) + ) + .expect((res) => expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ fields: null }))) + .expect((res) => + expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ from: Wallets.richWalletAddress })) + ) + .expect((res) => expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ to: contract }))) + .expect((res) => expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ transactionHash: txHash }))) + .expect((res) => expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ tokenAddress: token }))) + .expect((res) => + expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ type: TransactionsType.transfer })) + ) + .expect((res) => expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ fields: null }))) + .expect((res) => + expect(res.body.items[1]).toStrictEqual( + expect.objectContaining({ + token: { + l2Address: token, + l1Address: null, + symbol: "L2", + name: "L2 ERC20 token", + decimals: 18, + }, + }) + ) + ) + .expect((res) => + expect(res.body.items[2]).toStrictEqual(expect.objectContaining({ from: Token.ETHER_PULL_Address })) + ) + .expect((res) => + expect(res.body.items[2]).toStrictEqual(expect.objectContaining({ to: Wallets.richWalletAddress })) + ) + .expect((res) => expect(res.body.items[2]).toStrictEqual(expect.objectContaining({ transactionHash: txHash }))) + .expect((res) => + expect(res.body.items[2]).toStrictEqual(expect.objectContaining({ tokenAddress: Token.ETHER_ERC20_Address })) + ) + .expect((res) => + expect(res.body.items[2]).toStrictEqual(expect.objectContaining({ type: TransactionsType.refund })) + ) + .expect((res) => expect(res.body.items[2]).toStrictEqual(expect.objectContaining({ fields: null }))) + .expect((res) => expect(res.body.items[2]).toStrictEqual(expect.objectContaining({ token: null }))); + }); + + //@id1483 + it("Verify transaction for the Custom tokenII via /transactions/${txHash}/transfers", async () => { + await setTimeout(localConfig.standardPause); //works unstable without timeout + + const tokenL1 = await helper.getStringFromFile(bufferRoute + Buffer.L1); + token = await helper.getStringFromFile(bufferRoute + Buffer.L2deposited); + txHash = await helper.getStringFromFile(bufferRoute + Buffer.txMultiTransferCustomTokenII); + const apiRoute = `/transactions/${txHash}/transfers?page=1&limit=10`; + + return ( + request(environment.blockExplorerAPI) + .get(apiRoute) + .expect(200) + .expect((res) => + expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ from: Wallets.richWalletAddress })) + ) + .expect((res) => + expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ to: Token.ETHER_PULL_Address })) + ) + .expect((res) => + expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ transactionHash: txHash })) + ) + .expect((res) => + expect(res.body.items[0]).toStrictEqual( + expect.objectContaining({ tokenAddress: Token.ETHER_ERC20_Address }) + ) + ) + .expect((res) => + expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ type: TransactionsType.fee })) + ) + .expect((res) => expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ fields: null }))) + .expect((res) => + expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ from: Wallets.richWalletAddress })) + ) + .expect((res) => expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ to: contract }))) + .expect((res) => + expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ transactionHash: txHash })) + ) + // .expect((res) => expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ tokenAddress: Token.ETHER_ERC20_Address }))) + .expect((res) => + expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ type: TransactionsType.transfer })) + ) + .expect((res) => expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ fields: null }))) + .expect((res) => + expect(res.body.items[1]).toStrictEqual( + expect.objectContaining({ + token: { + l2Address: token, + l1Address: tokenL1, + symbol: "L1", + name: "L1 ERC20 token", + decimals: 18, + }, + }) + ) + ) + .expect((res) => + expect(res.body.items[2]).toStrictEqual(expect.objectContaining({ from: Token.ETHER_PULL_Address })) + ) + .expect((res) => + expect(res.body.items[2]).toStrictEqual(expect.objectContaining({ to: Wallets.richWalletAddress })) + ) + .expect((res) => + expect(res.body.items[2]).toStrictEqual(expect.objectContaining({ transactionHash: txHash })) + ) + .expect((res) => + expect(res.body.items[2]).toStrictEqual( + expect.objectContaining({ tokenAddress: Token.ETHER_ERC20_Address }) + ) + ) + .expect((res) => + expect(res.body.items[2]).toStrictEqual(expect.objectContaining({ type: TransactionsType.refund })) + ) + .expect((res) => expect(res.body.items[2]).toStrictEqual(expect.objectContaining({ fields: null }))) + .expect((res) => expect(res.body.items[2]).toStrictEqual(expect.objectContaining({ token: null }))) + ); + }); + }); +}); diff --git a/packages/integration-tests/tests/api/transactions/transaction.test.ts b/packages/integration-tests/tests/api/transactions/transaction.test.ts new file mode 100644 index 0000000000..c8431a49b7 --- /dev/null +++ b/packages/integration-tests/tests/api/transactions/transaction.test.ts @@ -0,0 +1,422 @@ +import * as request from "supertest"; +import { setTimeout } from "timers/promises"; + +import { environment, localConfig } from "../../../src/config"; +import { Buffer, Logger, Token, TransactionsStatus, TransactionsType, Wallets } from "../../../src/entities"; +import { Helper } from "../../../src/helper"; +import { Playbook } from "../../../src/playbook/playbook"; + +describe("Transactions", () => { + jest.setTimeout(localConfig.standardTimeout); + const playbook = new Playbook(); + const helper = new Helper(); + const bufferRoute = "src/playbook/"; + let txHash: string; + let token: string; + let contract: string; + let emptyWallet: string; + + describe("Paymaster", () => { + jest.setTimeout(localConfig.extendedTimeout); + + beforeEach(async () => { + token = await helper.getStringFromFile(bufferRoute + Buffer.customToken); + txHash = await helper.getStringFromFile(bufferRoute + Buffer.paymasterTx); + emptyWallet = await helper.getStringFromFile(bufferRoute + Buffer.emptyWalletAddress); + }); + + //@id1450 + it("Deploy contract via Paymaster", async () => { + const result = await playbook.deployViaPaymaster(); + expect(result[0]).toContain(Logger.txHashStartsWith); + }); + + //@id644 + it("Transaction via Paymaster usage", async () => { + const result = await playbook.usePaymaster(); + expect(result).toContain(Logger.txHashStartsWith); + }); + + //@id1451 + it("Verify the custom token includes paymaster transaction", async () => { + const paymaster = await helper.getStringFromFile(bufferRoute + Buffer.paymaster); + const apiRoute = `/tokens/${token}/transfers?page=1&limit=10`; + + await setTimeout(localConfig.standardPause); //works unstable without timeout + + return request(environment.blockExplorerAPI) + .get(apiRoute) + .expect(200) + .expect((res) => expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ from: emptyWallet }))) + .expect((res) => expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ to: paymaster }))) + .expect((res) => expect(res.body.items[0].token).toStrictEqual(expect.objectContaining({ l2Address: token }))) + .expect((res) => expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ transactionHash: txHash }))) + .expect((res) => + expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ type: TransactionsType.transfer })) + ); + }); + + //@id1452 + it("Verify transaction through Paymaster", async () => { + const apiRoute = `/transactions/${txHash}/transfers?page=1&limit=10`; + const paymasterAddress = await helper.getStringFromFile(bufferRoute + Buffer.paymaster); + + await setTimeout(localConfig.standardPause); //works unstable without timeout + + return request(environment.blockExplorerAPI) + .get(apiRoute) + .expect(200) + .expect((res) => expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ from: emptyWallet }))) + .expect((res) => expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ to: paymasterAddress }))) + .expect((res) => expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ transactionHash: txHash }))) + .expect((res) => expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ tokenAddress: token }))) + .expect((res) => + expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ type: TransactionsType.transfer })) + ) + .expect((res) => expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ fields: null }))) + .expect((res) => + expect(res.body.items[0]).toStrictEqual( + expect.objectContaining({ + token: { + l2Address: token, + l1Address: null, + symbol: "MyToken", + name: "MyToken", + decimals: 18, + }, + }) + ) + ) + .expect((res) => expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ from: paymasterAddress }))) + .expect((res) => + expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ to: Token.ETHER_PULL_Address })) + ) + .expect((res) => expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ transactionHash: txHash }))) + .expect((res) => + expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ tokenAddress: Token.ETHER_ERC20_Address })) + ) + .expect((res) => + expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ type: TransactionsType.fee })) + ) + .expect((res) => expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ fields: null }))) + .expect((res) => expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ token: null }))) + .expect((res) => + expect(res.body.items[2]).toStrictEqual(expect.objectContaining({ from: Token.ETHER_PULL_Address })) + ) + .expect((res) => expect(res.body.items[2]).toStrictEqual(expect.objectContaining({ to: paymasterAddress }))) + .expect((res) => expect(res.body.items[2]).toStrictEqual(expect.objectContaining({ transactionHash: txHash }))) + .expect((res) => + expect(res.body.items[2]).toStrictEqual(expect.objectContaining({ tokenAddress: Token.ETHER_ERC20_Address })) + ) + .expect((res) => + expect(res.body.items[2]).toStrictEqual(expect.objectContaining({ type: TransactionsType.refund })) + ) + .expect((res) => expect(res.body.items[2]).toStrictEqual(expect.objectContaining({ fields: null }))) + .expect((res) => expect(res.body.items[2]).toStrictEqual(expect.objectContaining({ token: null }))); + }); + }); + + describe("Transaction with failed state", () => { + beforeAll(async () => { + const bufferFile = bufferRoute + Buffer.L2; + token = await helper.getStringFromFile(bufferFile); + txHash = await playbook.transferFailedState(token); + return [txHash, token]; + }); + + //@id645 + it("Verify the transactions with failed state", async () => { + const apiRoute = `/transactions/${txHash}?page=1&limit=10`; + + await setTimeout(localConfig.standardPause); //works unstable without timeout + + return request(environment.blockExplorerAPI) + .get(apiRoute) + .expect(200) + .expect((res) => expect(res.body.from).toStrictEqual(Wallets.richWalletAddress)) + .expect((res) => expect(res.body.to).toStrictEqual(token)) + .expect((res) => expect(res.body.hash).toStrictEqual(txHash)) + .expect((res) => expect(res.body.status).toStrictEqual(TransactionsStatus.failed)); + }); + }); + + describe("Greeter", () => { + jest.setTimeout(localConfig.extendedTimeout); + + beforeEach(async () => { + contract = await helper.getStringFromFile(bufferRoute + Buffer.greeterL2); + txHash = await helper.getStringFromFile(bufferRoute + Buffer.executeGreeterTx); + }); + + //@id597 + it("Deploy the Greeter contract to the L2", async () => { + contract = await playbook.deployGreeterToL2(); + expect(contract).toContain(Logger.txHashStartsWith); + }); + + //@id1449 + it("Verify the deployed Greeter contract via /address/{address}", async () => { + const apiRoute = `/address/${contract}`; + + await setTimeout(localConfig.standardPause); //works unstable without timeout + + return request(environment.blockExplorerAPI) + .get(apiRoute) + .expect(200) + .expect((res) => expect(res.body).toStrictEqual(expect.objectContaining({ address: contract }))) + .expect((res) => expect(res.body).toStrictEqual(expect.objectContaining({ balances: {} }))); + }); + + //@id604 + it("Use the Greeter contract - execute SetGreeting", async () => { + const executedContract = await playbook.useGreeter(); + expect(executedContract).toContain(Logger.txHashStartsWith); + }); + + //@id1454 + it("Verify the transaction after SetGreeting execution via transactions/{transactionHash}", async () => { + const apiRoute = `/transactions/${txHash}?page=1&limit=10`; + + await setTimeout(localConfig.standardPause); //works unstable without timeout + + return request(environment.blockExplorerAPI) + .get(apiRoute) + .expect(200) + .expect((res) => expect(res.body).toStrictEqual(expect.objectContaining({ hash: txHash }))) + .expect((res) => expect(res.body).toStrictEqual(expect.objectContaining({ to: contract }))) + .expect((res) => expect(res.body).toStrictEqual(expect.objectContaining({ value: "0" }))) + .expect((res) => expect(res.body).toStrictEqual(expect.objectContaining({ isL1Originated: false }))); + }); + + //@id1455 + it("Verify the transaction after SetGreeting execution via transactions/{transactionHash}/transfers", async () => { + const apiRoute = `/transactions/${txHash}/transfers?page=1&limit=10`; + await setTimeout(localConfig.standardPause); //works unstable without timeout + + return request(environment.blockExplorerAPI) + .get(apiRoute) + .expect(200) + .expect((res) => + expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ from: Wallets.richWalletAddress })) + ) + .expect((res) => + expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ to: Token.ETHER_PULL_Address })) + ) + .expect((res) => expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ transactionHash: txHash }))) + .expect((res) => + expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ tokenAddress: Token.ETHER_ERC20_Address })) + ) + .expect((res) => + expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ type: TransactionsType.fee })) + ) + .expect((res) => expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ fields: null }))) + .expect((res) => expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ token: null }))) + .expect((res) => + expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ from: Token.ETHER_PULL_Address })) + ) + .expect((res) => + expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ to: Wallets.richWalletAddress })) + ) + .expect((res) => expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ transactionHash: txHash }))) + .expect((res) => + expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ tokenAddress: Token.ETHER_ERC20_Address })) + ) + .expect((res) => + expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ type: TransactionsType.refund })) + ) + .expect((res) => expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ fields: null }))) + .expect((res) => expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ token: null }))); + }); + }); + + describe("Transactions for the /address/{address} endpoints", () => { + jest.setTimeout(localConfig.extendedTimeout); + + //@id1510 + it("Verify the transaction via /address/{address}/logs", async () => { + contract = await helper.getStringFromFile(bufferRoute + Buffer.greeterL2); + txHash = await helper.getStringFromFile(bufferRoute + Buffer.executeGreeterTx); + + const apiRoute = `/address/${contract}/logs`; + const decapitalizedAddress = apiRoute.slice(1).toLowerCase(); + + await setTimeout(localConfig.standardPause); //works unstable without timeout + + return request(environment.blockExplorerAPI) + .get(apiRoute) + .expect(200) + .expect((res) => expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ address: contract }))) + .expect((res) => expect(Array.isArray(res.body.items[0].topics)).toStrictEqual(true)) + .expect((res) => expect(typeof res.body.items[0].data).toStrictEqual("string")) + .expect((res) => expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ transactionHash: txHash }))) + .expect((res) => expect(typeof res.body.items[0].transactionIndex).toStrictEqual("number")) + .expect((res) => expect(typeof res.body.items[0].logIndex).toStrictEqual("number")) + .expect((res) => expect(typeof res.body.items[0].timestamp).toStrictEqual("string")) + .expect((res) => expect(res.body.meta).toStrictEqual(expect.objectContaining({ totalItems: 1 }))) + .expect((res) => expect(res.body.meta).toStrictEqual(expect.objectContaining({ itemCount: 1 }))) + .expect((res) => expect(res.body.meta).toStrictEqual(expect.objectContaining({ itemsPerPage: 10 }))) + .expect((res) => expect(res.body.meta).toStrictEqual(expect.objectContaining({ totalPages: 1 }))) + .expect((res) => expect(res.body.meta).toStrictEqual(expect.objectContaining({ currentPage: 1 }))) + .expect((res) => + expect(res.body.links).toStrictEqual(expect.objectContaining({ first: `${decapitalizedAddress}?limit=10` })) + ) + .expect((res) => expect(res.body.links).toStrictEqual(expect.objectContaining({ previous: "" }))) + .expect((res) => expect(res.body.links).toStrictEqual(expect.objectContaining({ next: "" }))) + .expect((res) => + expect(res.body.links).toStrictEqual( + expect.objectContaining({ last: `${decapitalizedAddress}?page=1&limit=10` }) + ) + ); + }); + + //@id1509 + it("Verify the transaction via /address/{address}/transfers", async () => { + contract = await helper.getStringFromFile(bufferRoute + Buffer.paymaster); + emptyWallet = await helper.getStringFromFile(bufferRoute + Buffer.emptyWalletAddress); + txHash = await helper.getStringFromFile(bufferRoute + Buffer.paymasterTx); + + const customTokenAddress = await helper.getStringFromFile(bufferRoute + Buffer.customToken); + const apiRoute = `/address/${contract}/transfers`; + const decapitalizedAddress = apiRoute.slice(1).toLowerCase(); + + await setTimeout(localConfig.standardPause); //works unstable without timeout + + return request(environment.blockExplorerAPI) + .get(apiRoute) + .expect(200) + .expect((res) => expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ from: emptyWallet }))) + .expect((res) => expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ to: contract }))) + .expect((res) => expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ transactionHash: txHash }))) + .expect((res) => expect(typeof res.body.items[0].timestamp).toStrictEqual("string")) + .expect((res) => expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ amount: "1" }))) + .expect((res) => + expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ tokenAddress: customTokenAddress })) + ) + .expect((res) => expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ type: "transfer" }))) + .expect((res) => expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ fields: null }))) + .expect((res) => expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ fields: null }))) + .expect((res) => + expect(res.body.items[0].token).toStrictEqual(expect.objectContaining({ l2Address: customTokenAddress })) + ) + .expect((res) => expect(res.body.items[0].token).toStrictEqual(expect.objectContaining({ l1Address: null }))) + .expect((res) => expect(res.body.items[0].token).toStrictEqual(expect.objectContaining({ symbol: "MyToken" }))) + .expect((res) => expect(res.body.items[0].token).toStrictEqual(expect.objectContaining({ name: "MyToken" }))) + .expect((res) => expect(res.body.items[0].token).toStrictEqual(expect.objectContaining({ decimals: 18 }))) + .expect((res) => + expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ from: Wallets.richWalletAddress })) + ) + .expect((res) => expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ to: contract }))) + .expect((res) => expect(typeof res.body.items[1].timestamp).toStrictEqual("string")) + .expect((res) => + expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ amount: "30000000000000000" })) + ) + .expect((res) => + expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ tokenAddress: Token.ETHER_ERC20_Address })) + ) + .expect((res) => expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ type: "transfer" }))) + .expect((res) => expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ fields: null }))) + .expect((res) => expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ fields: null }))) + .expect((res) => expect(res.body.meta).toStrictEqual(expect.objectContaining({ totalItems: 2 }))) + .expect((res) => expect(res.body.meta).toStrictEqual(expect.objectContaining({ itemCount: 2 }))) + .expect((res) => expect(res.body.meta).toStrictEqual(expect.objectContaining({ itemsPerPage: 10 }))) + .expect((res) => expect(res.body.meta).toStrictEqual(expect.objectContaining({ totalPages: 1 }))) + .expect((res) => expect(res.body.meta).toStrictEqual(expect.objectContaining({ currentPage: 1 }))) + .expect((res) => + expect(res.body.links).toStrictEqual(expect.objectContaining({ first: `${decapitalizedAddress}?limit=10` })) + ) + .expect((res) => expect(res.body.links).toStrictEqual(expect.objectContaining({ previous: "" }))) + .expect((res) => expect(res.body.links).toStrictEqual(expect.objectContaining({ next: "" }))) + .expect((res) => + expect(res.body.links).toStrictEqual( + expect.objectContaining({ last: `${decapitalizedAddress}?page=1&limit=10` }) + ) + ); + }); + }); + describe("Transactions for the /transactions endpoint", () => { + jest.setTimeout(localConfig.extendedTimeout); + + //@id1506 + it("Verify the transaction via /transactions", async () => { + contract = await helper.getStringFromFile(bufferRoute + Buffer.greeterL2); + txHash = await helper.getStringFromFile(bufferRoute + Buffer.executeGreeterTx); + + const apiRoute = `/transactions`; + + await setTimeout(localConfig.standardPause); //works unstable without timeout + + return request(environment.blockExplorerAPI) + .get(apiRoute) + .expect(200) + .expect((res) => expect(Array.isArray(res.body.items)).toStrictEqual(true)) + .expect((res) => expect(res.body.items.length).toBe(10)) + .expect((res) => expect(typeof res.body.meta.totalItems).toStrictEqual("number")) + .expect((res) => expect(typeof res.body.meta.itemCount).toStrictEqual("number")) + .expect((res) => expect(typeof res.body.meta.itemsPerPage).toStrictEqual("number")) + .expect((res) => expect(typeof res.body.meta.totalPages).toStrictEqual("number")) + .expect((res) => expect(typeof res.body.meta.currentPage).toStrictEqual("number")) + .expect((res) => expect(typeof res.body.links.first).toStrictEqual("string")) + .expect((res) => expect(typeof res.body.links.previous).toStrictEqual("string")) + .expect((res) => expect(typeof res.body.links.next).toStrictEqual("string")) + .expect((res) => expect(typeof res.body.links.last).toStrictEqual("string")); + }); + + //@id1507 + it("Verify the transaction via /transactions/{transactionHash}/logs", async () => { + contract = await helper.getStringFromFile(bufferRoute + Buffer.greeterL2); + txHash = await helper.getStringFromFile(bufferRoute + Buffer.executeGreeterTx); + + const apiRoute = `/transactions/${txHash}/logs`; + const decapitalizedAddress = apiRoute.slice(1).toLowerCase(); + + await setTimeout(localConfig.standardPause); //works unstable without timeout + + return request(environment.blockExplorerAPI) + .get(apiRoute) + .expect(200) + .expect((res) => + expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ address: Token.ETHER_ERC20_Address })) + ) + .expect((res) => expect(Array.isArray(res.body.items[0].topics)).toStrictEqual(true)) + .expect((res) => expect(typeof res.body.items[0].data).toStrictEqual("string")) + .expect((res) => expect(typeof res.body.items[0].blockNumber).toStrictEqual("number")) + .expect((res) => expect(res.body.items[0]).toStrictEqual(expect.objectContaining({ transactionHash: txHash }))) + .expect((res) => expect(typeof res.body.items[0].transactionIndex).toStrictEqual("number")) + .expect((res) => expect(typeof res.body.items[0].logIndex).toStrictEqual("number")) + .expect((res) => expect(typeof res.body.items[0].timestamp).toStrictEqual("string")) + .expect((res) => expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ address: contract }))) + .expect((res) => expect(Array.isArray(res.body.items[1].topics)).toStrictEqual(true)) + .expect((res) => expect(typeof res.body.items[1].data).toStrictEqual("string")) + .expect((res) => expect(typeof res.body.items[1].blockNumber).toStrictEqual("number")) + .expect((res) => expect(res.body.items[1]).toStrictEqual(expect.objectContaining({ transactionHash: txHash }))) + .expect((res) => expect(typeof res.body.items[1].transactionIndex).toStrictEqual("number")) + .expect((res) => expect(typeof res.body.items[1].logIndex).toStrictEqual("number")) + .expect((res) => expect(typeof res.body.items[1].timestamp).toStrictEqual("string")) + .expect((res) => + expect(res.body.items[2]).toStrictEqual(expect.objectContaining({ address: Token.ETHER_ERC20_Address })) + ) + .expect((res) => expect(Array.isArray(res.body.items[2].topics)).toStrictEqual(true)) + .expect((res) => expect(typeof res.body.items[2].data).toStrictEqual("string")) + .expect((res) => expect(typeof res.body.items[2].blockNumber).toStrictEqual("number")) + .expect((res) => expect(res.body.items[2]).toStrictEqual(expect.objectContaining({ transactionHash: txHash }))) + .expect((res) => expect(typeof res.body.items[2].transactionIndex).toStrictEqual("number")) + .expect((res) => expect(typeof res.body.items[2].logIndex).toStrictEqual("number")) + .expect((res) => expect(typeof res.body.items[2].timestamp).toStrictEqual("string")) + .expect((res) => expect(res.body.meta).toStrictEqual(expect.objectContaining({ totalItems: 3 }))) + .expect((res) => expect(res.body.meta).toStrictEqual(expect.objectContaining({ itemCount: 3 }))) + .expect((res) => expect(res.body.meta).toStrictEqual(expect.objectContaining({ itemsPerPage: 10 }))) + .expect((res) => expect(res.body.meta).toStrictEqual(expect.objectContaining({ totalPages: 1 }))) + .expect((res) => expect(res.body.meta).toStrictEqual(expect.objectContaining({ currentPage: 1 }))) + .expect((res) => + expect(res.body.links).toStrictEqual(expect.objectContaining({ first: `${decapitalizedAddress}?limit=10` })) + ) + .expect((res) => expect(res.body.links).toStrictEqual(expect.objectContaining({ previous: "" }))) + .expect((res) => expect(res.body.links).toStrictEqual(expect.objectContaining({ next: "" }))) + .expect((res) => + expect(res.body.links).toStrictEqual( + expect.objectContaining({ last: `${decapitalizedAddress}?page=1&limit=10` }) + ) + ); + }); + }); +});