From e6638dc47d9cd583a1ae5ab235b2fe988959b73a Mon Sep 17 00:00:00 2001 From: kvhnuke <10602065+kvhnuke@users.noreply.github.com> Date: Tue, 8 Oct 2024 16:25:32 -0700 Subject: [PATCH] devop: working example of eip7702 --- .editorconfig | 10 + .nvmrc | 1 + .prettierignore | 3 + .prettierrc | 12 + .vscode/launch.json | 19 + .vscode/settings.json | 35 ++ README.md | 5 + TestContract.sol | 11 + build/authorization-signer.js | 23 + build/authorization-signer.js.map | 1 + build/configs.js | 9 + build/configs.js.map | 1 + build/main.js | 39 ++ build/main.js.map | 1 + build/types.js | 2 + build/types.js.map | 1 + package.json | 29 + pnpm-lock.yaml | 875 ++++++++++++++++++++++++++++++ src/authorization-signer.ts | 29 + src/configs.ts | 10 + src/main.ts | 53 ++ src/types.ts | 0 tsconfig.json | 27 + 23 files changed, 1196 insertions(+) create mode 100644 .editorconfig create mode 100644 .nvmrc create mode 100644 .prettierignore create mode 100644 .prettierrc create mode 100644 .vscode/launch.json create mode 100644 .vscode/settings.json create mode 100644 TestContract.sol create mode 100644 build/authorization-signer.js create mode 100644 build/authorization-signer.js.map create mode 100644 build/configs.js create mode 100644 build/configs.js.map create mode 100644 build/main.js create mode 100644 build/main.js.map create mode 100644 build/types.js create mode 100644 build/types.js.map create mode 100644 package.json create mode 100644 pnpm-lock.yaml create mode 100644 src/authorization-signer.ts create mode 100644 src/configs.ts create mode 100644 src/main.ts create mode 100644 src/types.ts create mode 100644 tsconfig.json diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..47bb561 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,10 @@ +root = true + +[*.{yml,yaml,js,mjs,cjs,ts,mts,cts,json,json5,sql,md,html,hbs,ejs,njk}] +charset = utf-8 +end_of_line = lf +indent_size = 2 +tab_width = 2 +indent_style = tab +insert_final_newline = true +trim_trailing_whitespace = true diff --git a/.nvmrc b/.nvmrc new file mode 100644 index 0000000..620c5e1 --- /dev/null +++ b/.nvmrc @@ -0,0 +1 @@ +v22.9.0 diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..d344ca8 --- /dev/null +++ b/.prettierignore @@ -0,0 +1,3 @@ +./build +./src/**/generated +./src/**/*.generated.* diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..02ca1bc --- /dev/null +++ b/.prettierrc @@ -0,0 +1,12 @@ +{ + "arrowParens": "avoid", + "bracketSameLine": true, + "bracketSpacing": false, + "endOfLine": "lf", + "printWidth": 120, + "semi": false, + "singleQuote": true, + "tabWidth": 2, + "useTabs": true, + "trailingComma": "all" +} diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..3215c0b --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,19 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "Attach by Process ID", + "processId": "${command:PickProcess}", + "request": "attach", + "continueOnAttach": true, + "restart": true, + "skipFiles": [ + "/**" + ], + "type": "node", + } + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..25d2d7f --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,35 @@ +{ + "[typescript]": { + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": true, + }, + "[javascript]": { + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": true, + }, + "[typescriptreact]": { + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": true, + }, + "[javascriptreact]": { + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": true, + }, + "[json]": { + "editor.quickSuggestions": { + "strings": true + }, + "editor.suggest.insertMode": "replace" + }, + "[json5]": { + "editor.quickSuggestions": { + "strings": true + }, + "editor.suggest.insertMode": "replace" + }, + "files.associations": { + "*.ejs": "html", + "*.njk": "html", + "*.hbs": "handlebars", + } +} diff --git a/README.md b/README.md index 6108d7d..5bc7217 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,7 @@ # EIP-7702 + Examples for EIP-7702 Transactions + +Since some of the libraries are no publicly released you have to clone +https://github.com/ethereumjs/ethereumjs-monorepo/tree/master +locally and build it, then refrence it in the package.json diff --git a/TestContract.sol b/TestContract.sol new file mode 100644 index 0000000..ef70a1b --- /dev/null +++ b/TestContract.sol @@ -0,0 +1,11 @@ +// SPDX-License-Identifier: GPL-3.0 + +pragma solidity >=0.7.0 <0.9.0; + +contract SimpleTest { + event Deposit(address indexed _from, bytes32 indexed _id, uint _value); + + function doAnEvent() public { + emit Deposit(address(this), blockhash(block.number), block.number); + } +} diff --git a/build/authorization-signer.js b/build/authorization-signer.js new file mode 100644 index 0000000..b6b7370 --- /dev/null +++ b/build/authorization-signer.js @@ -0,0 +1,23 @@ +import { encodeRlp, keccak256 } from 'ethers'; +import { EIP7702 } from './configs.js'; +import { bigIntToBytes, bigIntToHex, bytesToHex, ecsign, hexToBytes } from '@ethereumjs/util'; +const populateAndSignAuthAddress = async (address, wallet, provider) => { + const walletAddress = await wallet.getAddress(); + const nonce = BigInt(await provider.getTransactionCount(walletAddress, 'pending')); + const { chainId } = await provider.getNetwork(); + const magicBuffer = Buffer.from([EIP7702.MAGIC]); + const rlpData = encodeRlp([bigIntToBytes(chainId), hexToBytes(address), bigIntToBytes(nonce)]); + const signBytes = Buffer.concat([magicBuffer, hexToBytes(rlpData)]); + const hash = keccak256(signBytes); + const signature = ecsign(hexToBytes(hash), hexToBytes(wallet.privateKey)); + return { + address: address, + chainId: bigIntToHex(chainId), + nonce: bigIntToHex(nonce) === '0x0' ? '0x' : bigIntToHex(nonce), + r: bytesToHex(signature.r), + s: bytesToHex(signature.s), + yParity: bigIntToHex(signature.v - BigInt(27)) === '0x0' ? '0x' : '0x1', + }; +}; +export { populateAndSignAuthAddress }; +//# sourceMappingURL=authorization-signer.js.map \ No newline at end of file diff --git a/build/authorization-signer.js.map b/build/authorization-signer.js.map new file mode 100644 index 0000000..c611e0f --- /dev/null +++ b/build/authorization-signer.js.map @@ -0,0 +1 @@ +{"version":3,"file":"authorization-signer.js","sourceRoot":"","sources":["../src/authorization-signer.ts"],"names":[],"mappings":"AAAA,OAAO,EAA6B,SAAS,EAAa,SAAS,EAAC,MAAM,QAAQ,CAAA;AAElF,OAAO,EAAC,OAAO,EAAC,MAAM,cAAc,CAAA;AACpC,OAAO,EAAC,aAAa,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,EAAC,MAAM,kBAAkB,CAAA;AAE3F,MAAM,0BAA0B,GAAG,KAAK,EACvC,OAAe,EACf,MAAc,EACd,QAAkB,EACe,EAAE;IACnC,MAAM,aAAa,GAAG,MAAM,MAAM,CAAC,UAAU,EAAE,CAAA;IAC/C,MAAM,KAAK,GAAG,MAAM,CAAC,MAAM,QAAQ,CAAC,mBAAmB,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC,CAAA;IAClF,MAAM,EAAC,OAAO,EAAC,GAAG,MAAM,QAAQ,CAAC,UAAU,EAAE,CAAA;IAC7C,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAA;IAChD,MAAM,OAAO,GAAG,SAAS,CAAC,CAAC,aAAa,CAAC,OAAO,CAAC,EAAE,UAAU,CAAC,OAAO,CAAC,EAAE,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;IAC9F,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA;IACnE,MAAM,IAAI,GAAG,SAAS,CAAC,SAAS,CAAC,CAAA;IACjC,MAAM,SAAS,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,UAAU,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAA;IACzE,OAAO;QACN,OAAO,EAAE,OAAwB;QACjC,OAAO,EAAE,WAAW,CAAC,OAAO,CAAC;QAC7B,KAAK,EAAE,WAAW,CAAC,KAAK,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC;QAC/D,CAAC,EAAE,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC;QAC1B,CAAC,EAAE,UAAU,CAAC,SAAS,CAAC,CAAC,CAAC;QAC1B,OAAO,EAAE,WAAW,CAAC,SAAS,CAAC,CAAC,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK;KACvE,CAAA;AACF,CAAC,CAAA;AAED,OAAO,EAAC,0BAA0B,EAAC,CAAA"} \ No newline at end of file diff --git a/build/configs.js b/build/configs.js new file mode 100644 index 0000000..064ebe3 --- /dev/null +++ b/build/configs.js @@ -0,0 +1,9 @@ +import { privateToAddress } from '@ethereumjs/util'; +const PAY_FROM_PRIVATE = Buffer.from(process.env.PAY_FROM_PRIV_KEY.replace('0x', ''), 'hex'); +const PAY_FROM_ADDRESS = privateToAddress(PAY_FROM_PRIVATE); +const EIP7702 = { + MAGIC: 0x05, + TX_TYPE: 0x04, +}; +export { PAY_FROM_ADDRESS, PAY_FROM_PRIVATE, EIP7702 }; +//# sourceMappingURL=configs.js.map \ No newline at end of file diff --git a/build/configs.js.map b/build/configs.js.map new file mode 100644 index 0000000..2e7b0e3 --- /dev/null +++ b/build/configs.js.map @@ -0,0 +1 @@ +{"version":3,"file":"configs.js","sourceRoot":"","sources":["../src/configs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,gBAAgB,EAAC,MAAM,kBAAkB,CAAA;AAEjD,MAAM,gBAAgB,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAkB,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,KAAK,CAAC,CAAA;AAC7F,MAAM,gBAAgB,GAAG,gBAAgB,CAAC,gBAAgB,CAAC,CAAA;AAC3D,MAAM,OAAO,GAAG;IACf,KAAK,EAAE,IAAI;IACX,OAAO,EAAE,IAAI;CACb,CAAA;AAED,OAAO,EAAC,gBAAgB,EAAE,gBAAgB,EAAE,OAAO,EAAC,CAAA"} \ No newline at end of file diff --git a/build/main.js b/build/main.js new file mode 100644 index 0000000..df217b3 --- /dev/null +++ b/build/main.js @@ -0,0 +1,39 @@ +import { Hardfork, Mainnet, createCustomCommon } from '@ethereumjs/common'; +import { createEOACode7702Tx } from '@ethereumjs/tx'; +import { bytesToHex, hexToBytes } from '@ethereumjs/util'; +import { PAY_FROM_ADDRESS, PAY_FROM_PRIVATE } from './configs.js'; +import { Wallet } from 'ethers'; +import { JsonRpcProvider, Interface } from 'ethers'; +import { populateAndSignAuthAddress } from './authorization-signer.js'; +const provider = new JsonRpcProvider('https://rpc.pectra-devnet-3.ethpandaops.io'); +const wallet = new Wallet(PAY_FROM_PRIVATE.toString('hex'), provider); +const CONTRACT_ADDRESS = '0x85F852931f4fb97d2DfeC1827273fd3c713b58C2'; +const abi = ['function doAnEvent()']; +let iface = new Interface(abi); +const data = iface.encodeFunctionData('doAnEvent'); +wallet + .populateTransaction({ + to: '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee', + value: '0x0', +}) + .then(async (tempTx) => { + const auth = await populateAndSignAuthAddress(CONTRACT_ADDRESS, wallet, provider); + const transactionCount = await provider.getTransactionCount(wallet.address); + const commonWithCustomChainId = createCustomCommon({ chainId: auth.chainId }, Mainnet, { + eips: [7702], + hardfork: Hardfork.Cancun, + }); + const tx = createEOACode7702Tx({ + authorizationList: [auth], + to: bytesToHex(PAY_FROM_ADDRESS), + gasLimit: BigInt(150000), + nonce: BigInt(transactionCount), + maxFeePerGas: tempTx.maxFeePerGas, + maxPriorityFeePerGas: tempTx.maxPriorityFeePerGas, + data: hexToBytes(data), + }, { common: commonWithCustomChainId }); + const signedTx = tx.sign(PAY_FROM_PRIVATE); + console.log(signedTx.toJSON()); + console.log(`https://explorer.pectra-devnet-3.ethpandaops.io/tx/${bytesToHex(signedTx.hash())}`); +}); +//# sourceMappingURL=main.js.map \ No newline at end of file diff --git a/build/main.js.map b/build/main.js.map new file mode 100644 index 0000000..05683a8 --- /dev/null +++ b/build/main.js.map @@ -0,0 +1 @@ +{"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,EAAE,OAAO,EAAE,kBAAkB,EAAC,MAAM,oBAAoB,CAAA;AACxE,OAAO,EAAC,mBAAmB,EAAC,MAAM,gBAAgB,CAAA;AAClD,OAAO,EAAC,UAAU,EAAE,UAAU,EAAyB,MAAM,kBAAkB,CAAA;AAC/E,OAAO,EAAC,gBAAgB,EAAE,gBAAgB,EAAC,MAAM,cAAc,CAAA;AAC/D,OAAO,EAAC,MAAM,EAAC,MAAM,QAAQ,CAAA;AAC7B,OAAO,EAAC,eAAe,EAAE,SAAS,EAAC,MAAM,QAAQ,CAAA;AACjD,OAAO,EAAC,0BAA0B,EAAC,MAAM,2BAA2B,CAAA;AAEpE,MAAM,QAAQ,GAAG,IAAI,eAAe,CAAC,4CAA4C,CAAC,CAAA;AAClF,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,gBAAgB,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,QAAQ,CAAC,CAAA;AAErE,MAAM,gBAAgB,GAAG,4CAA4C,CAAA;AAErE,MAAM,GAAG,GAAG,CAAC,sBAAsB,CAAC,CAAA;AACpC,IAAI,KAAK,GAAG,IAAI,SAAS,CAAC,GAAG,CAAC,CAAA;AAC9B,MAAM,IAAI,GAAG,KAAK,CAAC,kBAAkB,CAAC,WAAW,CAAC,CAAA;AAElD,MAAM;KACJ,mBAAmB,CAAC;IACpB,EAAE,EAAE,4CAA4C;IAChD,KAAK,EAAE,KAAK;CACZ,CAAC;KACD,IAAI,CAAC,KAAK,EAAC,MAAM,EAAC,EAAE;IAEpB,MAAM,IAAI,GAAG,MAAM,0BAA0B,CAAC,gBAAgB,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAA;IACjF,MAAM,gBAAgB,GAAG,MAAM,QAAQ,CAAC,mBAAmB,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;IAC3E,MAAM,uBAAuB,GAAG,kBAAkB,CAAC,EAAC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAC,EAAE,OAAO,EAAE;QACpF,IAAI,EAAE,CAAC,IAAI,CAAC;QACZ,QAAQ,EAAE,QAAQ,CAAC,MAAM;KACzB,CAAC,CAAA;IACF,MAAM,EAAE,GAAG,mBAAmB,CAC7B;QACC,iBAAiB,EAAE,CAAC,IAAI,CAAC;QACzB,EAAE,EAAE,UAAU,CAAC,gBAAgB,CAAC;QAChC,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC;QACxB,KAAK,EAAE,MAAM,CAAC,gBAAgB,CAAC;QAC/B,YAAY,EAAE,MAAM,CAAC,YAAsB;QAC3C,oBAAoB,EAAE,MAAM,CAAC,oBAA8B;QAC3D,IAAI,EAAE,UAAU,CAAC,IAAI,CAAC;KACtB,EACD,EAAC,MAAM,EAAE,uBAAuB,EAAC,CACjC,CAAA;IACD,MAAM,QAAQ,GAAG,EAAE,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAA;IAC1C,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAA;IAC9B,OAAO,CAAC,GAAG,CAAC,sDAAsD,UAAU,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,EAAE,CAAC,CAAA;AAQjG,CAAC,CAAC,CAAA"} \ No newline at end of file diff --git a/build/types.js b/build/types.js new file mode 100644 index 0000000..718fd38 --- /dev/null +++ b/build/types.js @@ -0,0 +1,2 @@ +export {}; +//# sourceMappingURL=types.js.map \ No newline at end of file diff --git a/build/types.js.map b/build/types.js.map new file mode 100644 index 0000000..c768b79 --- /dev/null +++ b/build/types.js.map @@ -0,0 +1 @@ +{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""} \ No newline at end of file diff --git a/package.json b/package.json new file mode 100644 index 0000000..1cea125 --- /dev/null +++ b/package.json @@ -0,0 +1,29 @@ +{ + "private": true, + "type": "module", + "scripts": { + "dev": "pnpm clean && pnpm build && concurrently -n \"build,run\" \"pnpm build:watch\" \"pnpm start:watch\"", + "start": "node --env-file ./.env --enable-source-maps --disable-proto=throw --disallow-code-generation-from-strings ./build/main.js", + "start:watch": "nodemon --delay 0.1 -w ./build -w ./views ./queries -w ./.env -w ./package.json -e .js,.mjs,.cts,.json,.sql,.html,.hbs,.ejs,.njk -x \"pnpm start\"", + "build": "tsc -p ./tsconfig.json", + "build:watch": "pnpm build --watch --preserveWatchOutput", + "clean": "rimraf ./build" + }, + "devDependencies": { + "@types/node": "^22.7.4", + "concurrently": "^9.0.1", + "nodemon": "^3.1.7", + "prettier": "^3.3.3", + "rimraf": "^6.0.1", + "typescript": "^5.6.2" + }, + "dependencies": { + "@ethereumjs/common": "link:../ethereumjs-monorepo/packages/common", + "@ethereumjs/tx": "link:../ethereumjs-monorepo/packages/tx", + "@ethereumjs/util": "link:../ethereumjs-monorepo/packages/util", + "ethers": "^6.13.3", + "pino": "^9.4.0", + "pino-pretty": "^11.2.2", + "tslib": "^2.7.0" + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..89bc99f --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,875 @@ +lockfileVersion: '6.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +dependencies: + ethers: + specifier: ^6.13.3 + version: 6.13.3 + pino: + specifier: ^9.4.0 + version: 9.4.0 + pino-pretty: + specifier: ^11.2.2 + version: 11.2.2 + tslib: + specifier: ^2.7.0 + version: 2.7.0 + +devDependencies: + '@types/node': + specifier: ^22.7.4 + version: 22.7.5 + concurrently: + specifier: ^9.0.1 + version: 9.0.1 + nodemon: + specifier: ^3.1.7 + version: 3.1.7 + prettier: + specifier: ^3.3.3 + version: 3.3.3 + rimraf: + specifier: ^6.0.1 + version: 6.0.1 + typescript: + specifier: ^5.6.2 + version: 5.6.2 + +packages: + + /@adraffy/ens-normalize@1.10.1: + resolution: {integrity: sha512-96Z2IP3mYmF1Xg2cDm8f1gWGf/HUVedQ3FMifV4kG/PQ4yEP51xDtRAEfhVNt5f/uzpNkZHwWQuUcu6D6K+Ekw==} + dev: false + + /@isaacs/cliui@8.0.2: + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + dependencies: + string-width: 5.1.2 + string-width-cjs: /string-width@4.2.3 + strip-ansi: 7.1.0 + strip-ansi-cjs: /strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: /wrap-ansi@7.0.0 + dev: true + + /@noble/curves@1.2.0: + resolution: {integrity: sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw==} + dependencies: + '@noble/hashes': 1.3.2 + dev: false + + /@noble/hashes@1.3.2: + resolution: {integrity: sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==} + engines: {node: '>= 16'} + dev: false + + /@types/node@18.15.13: + resolution: {integrity: sha512-N+0kuo9KgrUQ1Sn/ifDXsvg0TTleP7rIy4zOBGECxAljqvqfqpTfzx0Q1NUedOixRMBfe2Whhb056a42cWs26Q==} + dev: false + + /@types/node@22.7.5: + resolution: {integrity: sha512-jML7s2NAzMWc//QSJ1a3prpk78cOPchGvXJsC3C6R6PSMoooztvRVQEz89gmBTBY1SPMaqo5teB4uNHPdetShQ==} + dependencies: + undici-types: 6.19.8 + dev: true + + /abort-controller@3.0.0: + resolution: {integrity: sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==} + engines: {node: '>=6.5'} + dependencies: + event-target-shim: 5.0.1 + dev: false + + /aes-js@4.0.0-beta.5: + resolution: {integrity: sha512-G965FqalsNyrPqgEGON7nIx1e/OVENSgiEIzyC63haUMuvNnwIgIjMs52hlTCKhkBny7A2ORNlfY9Zu+jmGk1Q==} + dev: false + + /ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + dev: true + + /ansi-regex@6.1.0: + resolution: {integrity: sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==} + engines: {node: '>=12'} + dev: true + + /ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + dependencies: + color-convert: 2.0.1 + dev: true + + /ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + dev: true + + /anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + dev: true + + /atomic-sleep@1.0.0: + resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==} + engines: {node: '>=8.0.0'} + dev: false + + /balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + dev: true + + /base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + dev: false + + /binary-extensions@2.3.0: + resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} + engines: {node: '>=8'} + dev: true + + /brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + dev: true + + /brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + dependencies: + balanced-match: 1.0.2 + dev: true + + /braces@3.0.3: + resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==} + engines: {node: '>=8'} + dependencies: + fill-range: 7.1.1 + dev: true + + /buffer@6.0.3: + resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + dev: false + + /chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + dev: true + + /chokidar@3.6.0: + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} + engines: {node: '>= 8.10.0'} + dependencies: + anymatch: 3.1.3 + braces: 3.0.3 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + dev: true + + /cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + dev: true + + /color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + dependencies: + color-name: 1.1.4 + dev: true + + /color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + dev: true + + /colorette@2.0.20: + resolution: {integrity: sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==} + dev: false + + /concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + dev: true + + /concurrently@9.0.1: + resolution: {integrity: sha512-wYKvCd/f54sTXJMSfV6Ln/B8UrfLBKOYa+lzc6CHay3Qek+LorVSBdMVfyewFhRbH0Rbabsk4D+3PL/VjQ5gzg==} + engines: {node: '>=18'} + hasBin: true + dependencies: + chalk: 4.1.2 + lodash: 4.17.21 + rxjs: 7.8.1 + shell-quote: 1.8.1 + supports-color: 8.1.1 + tree-kill: 1.2.2 + yargs: 17.7.2 + dev: true + + /cross-spawn@7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + dev: true + + /dateformat@4.6.3: + resolution: {integrity: sha512-2P0p0pFGzHS5EMnhdxQi7aJN+iMheud0UhG4dlE1DLAlvL8JHjJJTX/CSm4JXwV0Ka5nGk3zC5mcb5bUQUxxMA==} + dev: false + + /debug@4.3.7(supports-color@5.5.0): + resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.3 + supports-color: 5.5.0 + dev: true + + /eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + dev: true + + /emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + dev: true + + /emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + dev: true + + /end-of-stream@1.4.4: + resolution: {integrity: sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==} + dependencies: + once: 1.4.0 + dev: false + + /escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} + engines: {node: '>=6'} + dev: true + + /ethers@6.13.3: + resolution: {integrity: sha512-/DzbZOLVtoO4fKvvQwpEucHAQgIwBGWuRvBdwE/lMXgXvvHHTSkn7XqAQ2b+gjJzZDJjWA9OD05bVceVOsBHbg==} + engines: {node: '>=14.0.0'} + dependencies: + '@adraffy/ens-normalize': 1.10.1 + '@noble/curves': 1.2.0 + '@noble/hashes': 1.3.2 + '@types/node': 18.15.13 + aes-js: 4.0.0-beta.5 + tslib: 2.4.0 + ws: 8.17.1 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + dev: false + + /event-target-shim@5.0.1: + resolution: {integrity: sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==} + engines: {node: '>=6'} + dev: false + + /events@3.3.0: + resolution: {integrity: sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==} + engines: {node: '>=0.8.x'} + dev: false + + /fast-copy@3.0.2: + resolution: {integrity: sha512-dl0O9Vhju8IrcLndv2eU4ldt1ftXMqqfgN4H1cpmGV7P6jeB9FwpN9a2c8DPGE1Ys88rNUJVYDHq73CGAGOPfQ==} + dev: false + + /fast-redact@3.5.0: + resolution: {integrity: sha512-dwsoQlS7h9hMeYUq1W++23NDcBLV4KqONnITDV9DjfS3q1SgDGVrBdvvTLUotWtPSD7asWDV9/CmsZPy8Hf70A==} + engines: {node: '>=6'} + dev: false + + /fast-safe-stringify@2.1.1: + resolution: {integrity: sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==} + dev: false + + /fill-range@7.1.1: + resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==} + engines: {node: '>=8'} + dependencies: + to-regex-range: 5.0.1 + dev: true + + /foreground-child@3.3.0: + resolution: {integrity: sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==} + engines: {node: '>=14'} + dependencies: + cross-spawn: 7.0.3 + signal-exit: 4.1.0 + dev: true + + /fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + dev: true + + /glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + dependencies: + is-glob: 4.0.3 + dev: true + + /glob@11.0.0: + resolution: {integrity: sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==} + engines: {node: 20 || >=22} + hasBin: true + dependencies: + foreground-child: 3.3.0 + jackspeak: 4.0.2 + minimatch: 10.0.1 + minipass: 7.1.2 + package-json-from-dist: 1.0.1 + path-scurry: 2.0.0 + dev: true + + /has-flag@3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + dev: true + + /has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + dev: true + + /help-me@5.0.0: + resolution: {integrity: sha512-7xgomUX6ADmcYzFik0HzAxh/73YlKR9bmFzf51CZwR+b6YtzU2m0u49hQCqV6SvlqIqsaxovfwdvbnsw3b/zpg==} + dev: false + + /ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + dev: false + + /ignore-by-default@1.0.1: + resolution: {integrity: sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==} + dev: true + + /is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + dependencies: + binary-extensions: 2.3.0 + dev: true + + /is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + dev: true + + /is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + dev: true + + /is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + dependencies: + is-extglob: 2.1.1 + dev: true + + /is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + dev: true + + /isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + dev: true + + /jackspeak@4.0.2: + resolution: {integrity: sha512-bZsjR/iRjl1Nk1UkjGpAzLNfQtzuijhn2g+pbZb98HQ1Gk8vM9hfbxeMBP+M2/UUdwj0RqGG3mlvk2MsAqwvEw==} + engines: {node: 20 || >=22} + dependencies: + '@isaacs/cliui': 8.0.2 + dev: true + + /joycon@3.1.1: + resolution: {integrity: sha512-34wB/Y7MW7bzjKRjUKTa46I2Z7eV62Rkhva+KkopW7Qvv/OSWBqvkSY7vusOPrNuZcUG3tApvdVgNB8POj3SPw==} + engines: {node: '>=10'} + dev: false + + /lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + dev: true + + /lru-cache@11.0.1: + resolution: {integrity: sha512-CgeuL5uom6j/ZVrg7G/+1IXqRY8JXX4Hghfy5YE0EhoYQWvndP1kufu58cmZLNIDKnRhZrXfdS9urVWx98AipQ==} + engines: {node: 20 || >=22} + dev: true + + /minimatch@10.0.1: + resolution: {integrity: sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==} + engines: {node: 20 || >=22} + dependencies: + brace-expansion: 2.0.1 + dev: true + + /minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + dependencies: + brace-expansion: 1.1.11 + dev: true + + /minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + dev: false + + /minipass@7.1.2: + resolution: {integrity: sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==} + engines: {node: '>=16 || 14 >=14.17'} + dev: true + + /ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + dev: true + + /nodemon@3.1.7: + resolution: {integrity: sha512-hLj7fuMow6f0lbB0cD14Lz2xNjwsyruH251Pk4t/yIitCFJbmY1myuLlHm/q06aST4jg6EgAh74PIBBrRqpVAQ==} + engines: {node: '>=10'} + hasBin: true + dependencies: + chokidar: 3.6.0 + debug: 4.3.7(supports-color@5.5.0) + ignore-by-default: 1.0.1 + minimatch: 3.1.2 + pstree.remy: 1.1.8 + semver: 7.6.3 + simple-update-notifier: 2.0.0 + supports-color: 5.5.0 + touch: 3.1.1 + undefsafe: 2.0.5 + dev: true + + /normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + dev: true + + /on-exit-leak-free@2.1.2: + resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==} + engines: {node: '>=14.0.0'} + dev: false + + /once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + dependencies: + wrappy: 1.0.2 + dev: false + + /package-json-from-dist@1.0.1: + resolution: {integrity: sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==} + dev: true + + /path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + dev: true + + /path-scurry@2.0.0: + resolution: {integrity: sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==} + engines: {node: 20 || >=22} + dependencies: + lru-cache: 11.0.1 + minipass: 7.1.2 + dev: true + + /picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + dev: true + + /pino-abstract-transport@1.2.0: + resolution: {integrity: sha512-Guhh8EZfPCfH+PMXAb6rKOjGQEoy0xlAIn+irODG5kgfYV+BQ0rGYYWTIel3P5mmyXqkYkPmdIkywsn6QKUR1Q==} + dependencies: + readable-stream: 4.5.2 + split2: 4.2.0 + dev: false + + /pino-pretty@11.2.2: + resolution: {integrity: sha512-2FnyGir8nAJAqD3srROdrF1J5BIcMT4nwj7hHSc60El6Uxlym00UbCCd8pYIterstVBFlMyF1yFV8XdGIPbj4A==} + hasBin: true + dependencies: + colorette: 2.0.20 + dateformat: 4.6.3 + fast-copy: 3.0.2 + fast-safe-stringify: 2.1.1 + help-me: 5.0.0 + joycon: 3.1.1 + minimist: 1.2.8 + on-exit-leak-free: 2.1.2 + pino-abstract-transport: 1.2.0 + pump: 3.0.2 + readable-stream: 4.5.2 + secure-json-parse: 2.7.0 + sonic-boom: 4.1.0 + strip-json-comments: 3.1.1 + dev: false + + /pino-std-serializers@7.0.0: + resolution: {integrity: sha512-e906FRY0+tV27iq4juKzSYPbUj2do2X2JX4EzSca1631EB2QJQUqGbDuERal7LCtOpxl6x3+nvo9NPZcmjkiFA==} + dev: false + + /pino@9.4.0: + resolution: {integrity: sha512-nbkQb5+9YPhQRz/BeQmrWpEknAaqjpAqRK8NwJpmrX/JHu7JuZC5G1CeAwJDJfGes4h+YihC6in3Q2nGb+Y09w==} + hasBin: true + dependencies: + atomic-sleep: 1.0.0 + fast-redact: 3.5.0 + on-exit-leak-free: 2.1.2 + pino-abstract-transport: 1.2.0 + pino-std-serializers: 7.0.0 + process-warning: 4.0.0 + quick-format-unescaped: 4.0.4 + real-require: 0.2.0 + safe-stable-stringify: 2.5.0 + sonic-boom: 4.1.0 + thread-stream: 3.1.0 + dev: false + + /prettier@3.3.3: + resolution: {integrity: sha512-i2tDNA0O5IrMO757lfrdQZCc2jPNDVntV0m/+4whiDfWaTKfMNgR7Qz0NAeGz/nRqF4m5/6CLzbP4/liHt12Ew==} + engines: {node: '>=14'} + hasBin: true + dev: true + + /process-warning@4.0.0: + resolution: {integrity: sha512-/MyYDxttz7DfGMMHiysAsFE4qF+pQYAA8ziO/3NcRVrQ5fSk+Mns4QZA/oRPFzvcqNoVJXQNWNAsdwBXLUkQKw==} + dev: false + + /process@0.11.10: + resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} + engines: {node: '>= 0.6.0'} + dev: false + + /pstree.remy@1.1.8: + resolution: {integrity: sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==} + dev: true + + /pump@3.0.2: + resolution: {integrity: sha512-tUPXtzlGM8FE3P0ZL6DVs/3P58k9nk8/jZeQCurTJylQA8qFYzHFfhBJkuqyE0FifOsQ0uKWekiZ5g8wtr28cw==} + dependencies: + end-of-stream: 1.4.4 + once: 1.4.0 + dev: false + + /quick-format-unescaped@4.0.4: + resolution: {integrity: sha512-tYC1Q1hgyRuHgloV/YXs2w15unPVh8qfu/qCTfhTYamaw7fyhumKa2yGpdSo87vY32rIclj+4fWYQXUMs9EHvg==} + dev: false + + /readable-stream@4.5.2: + resolution: {integrity: sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==} + engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} + dependencies: + abort-controller: 3.0.0 + buffer: 6.0.3 + events: 3.3.0 + process: 0.11.10 + string_decoder: 1.3.0 + dev: false + + /readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + dependencies: + picomatch: 2.3.1 + dev: true + + /real-require@0.2.0: + resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==} + engines: {node: '>= 12.13.0'} + dev: false + + /require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + dev: true + + /rimraf@6.0.1: + resolution: {integrity: sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A==} + engines: {node: 20 || >=22} + hasBin: true + dependencies: + glob: 11.0.0 + package-json-from-dist: 1.0.1 + dev: true + + /rxjs@7.8.1: + resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==} + dependencies: + tslib: 2.7.0 + dev: true + + /safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + dev: false + + /safe-stable-stringify@2.5.0: + resolution: {integrity: sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==} + engines: {node: '>=10'} + dev: false + + /secure-json-parse@2.7.0: + resolution: {integrity: sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==} + dev: false + + /semver@7.6.3: + resolution: {integrity: sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==} + engines: {node: '>=10'} + hasBin: true + dev: true + + /shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + dependencies: + shebang-regex: 3.0.0 + dev: true + + /shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + dev: true + + /shell-quote@1.8.1: + resolution: {integrity: sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==} + dev: true + + /signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + dev: true + + /simple-update-notifier@2.0.0: + resolution: {integrity: sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==} + engines: {node: '>=10'} + dependencies: + semver: 7.6.3 + dev: true + + /sonic-boom@4.1.0: + resolution: {integrity: sha512-NGipjjRicyJJ03rPiZCJYjwlsuP2d1/5QUviozRXC7S3WdVWNK5e3Ojieb9CCyfhq2UC+3+SRd9nG3I2lPRvUw==} + dependencies: + atomic-sleep: 1.0.0 + dev: false + + /split2@4.2.0: + resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} + engines: {node: '>= 10.x'} + dev: false + + /string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + dev: true + + /string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.1.0 + dev: true + + /string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + dependencies: + safe-buffer: 5.2.1 + dev: false + + /strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + dependencies: + ansi-regex: 5.0.1 + dev: true + + /strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} + dependencies: + ansi-regex: 6.1.0 + dev: true + + /strip-json-comments@3.1.1: + resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} + engines: {node: '>=8'} + dev: false + + /supports-color@5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + dependencies: + has-flag: 3.0.0 + dev: true + + /supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + dependencies: + has-flag: 4.0.0 + dev: true + + /supports-color@8.1.1: + resolution: {integrity: sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==} + engines: {node: '>=10'} + dependencies: + has-flag: 4.0.0 + dev: true + + /thread-stream@3.1.0: + resolution: {integrity: sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==} + dependencies: + real-require: 0.2.0 + dev: false + + /to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + dependencies: + is-number: 7.0.0 + dev: true + + /touch@3.1.1: + resolution: {integrity: sha512-r0eojU4bI8MnHr8c5bNo7lJDdI2qXlWWJk6a9EAFG7vbhTjElYhBVS3/miuE0uOuoLdb8Mc/rVfsmm6eo5o9GA==} + hasBin: true + dev: true + + /tree-kill@1.2.2: + resolution: {integrity: sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==} + hasBin: true + dev: true + + /tslib@2.4.0: + resolution: {integrity: sha512-d6xOpEDfsi2CZVlPQzGeux8XMwLT9hssAsaPYExaQMuYskwb+x1x7J371tWlbBdWHroy99KnVB6qIkUbs5X3UQ==} + dev: false + + /tslib@2.7.0: + resolution: {integrity: sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA==} + + /typescript@5.6.2: + resolution: {integrity: sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==} + engines: {node: '>=14.17'} + hasBin: true + dev: true + + /undefsafe@2.0.5: + resolution: {integrity: sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==} + dev: true + + /undici-types@6.19.8: + resolution: {integrity: sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==} + dev: true + + /which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + dependencies: + isexe: 2.0.0 + dev: true + + /wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + dev: true + + /wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + dependencies: + ansi-styles: 6.2.1 + string-width: 5.1.2 + strip-ansi: 7.1.0 + dev: true + + /wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + dev: false + + /ws@8.17.1: + resolution: {integrity: sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + dev: false + + /y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + dev: true + + /yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + dev: true + + /yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + dependencies: + cliui: 8.0.1 + escalade: 3.2.0 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + dev: true diff --git a/src/authorization-signer.ts b/src/authorization-signer.ts new file mode 100644 index 0000000..386d1cf --- /dev/null +++ b/src/authorization-signer.ts @@ -0,0 +1,29 @@ +import {type Wallet, type Provider, encodeRlp, decodeRlp, keccak256} from 'ethers' +import {AuthorizationListItem} from '@ethereumjs/tx' +import {EIP7702} from './configs.js' +import {bigIntToBytes, bigIntToHex, bytesToHex, ecsign, hexToBytes} from '@ethereumjs/util' + +const populateAndSignAuthAddress = async ( + address: string, + wallet: Wallet, + provider: Provider, +): Promise => { + const walletAddress = await wallet.getAddress() + const nonce = BigInt(await provider.getTransactionCount(walletAddress, 'pending')) + const {chainId} = await provider.getNetwork() + const magicBuffer = Buffer.from([EIP7702.MAGIC]) + const rlpData = encodeRlp([bigIntToBytes(chainId), hexToBytes(address), bigIntToBytes(nonce)]) + const signBytes = Buffer.concat([magicBuffer, hexToBytes(rlpData)]) + const hash = keccak256(signBytes) + const signature = ecsign(hexToBytes(hash), hexToBytes(wallet.privateKey)) + return { + address: address as `0x${string}`, + chainId: bigIntToHex(chainId), + nonce: bigIntToHex(nonce) === '0x0' ? '0x' : bigIntToHex(nonce), + r: bytesToHex(signature.r), + s: bytesToHex(signature.s), + yParity: bigIntToHex(signature.v - BigInt(27)) === '0x0' ? '0x' : '0x1', + } +} + +export {populateAndSignAuthAddress} diff --git a/src/configs.ts b/src/configs.ts new file mode 100644 index 0000000..7c605d9 --- /dev/null +++ b/src/configs.ts @@ -0,0 +1,10 @@ +import {privateToAddress} from '@ethereumjs/util' + +const PAY_FROM_PRIVATE = Buffer.from(process.env.PAY_FROM_PRIV_KEY!.replace('0x', ''), 'hex') +const PAY_FROM_ADDRESS = privateToAddress(PAY_FROM_PRIVATE) +const EIP7702 = { + MAGIC: 0x05, + TX_TYPE: 0x04, +} + +export {PAY_FROM_ADDRESS, PAY_FROM_PRIVATE, EIP7702} diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..ebaa6da --- /dev/null +++ b/src/main.ts @@ -0,0 +1,53 @@ +import {Hardfork, Mainnet, createCustomCommon} from '@ethereumjs/common' +import {createEOACode7702Tx} from '@ethereumjs/tx' +import {bytesToHex, hexToBytes, type PrefixedHexString} from '@ethereumjs/util' +import {PAY_FROM_ADDRESS, PAY_FROM_PRIVATE} from './configs.js' +import {Wallet} from 'ethers' +import {JsonRpcProvider, Interface} from 'ethers' +import {populateAndSignAuthAddress} from './authorization-signer.js' + +const provider = new JsonRpcProvider('https://rpc.pectra-devnet-3.ethpandaops.io') +const wallet = new Wallet(PAY_FROM_PRIVATE.toString('hex'), provider) + +const CONTRACT_ADDRESS = '0x85F852931f4fb97d2DfeC1827273fd3c713b58C2' // code is at TestContract.sol + +const abi = ['function doAnEvent()'] +let iface = new Interface(abi) +const data = iface.encodeFunctionData('doAnEvent') + +wallet + .populateTransaction({ + to: '0xeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee', + value: '0x0', + }) + .then(async tempTx => { + //Im doing this tempTx just to get maxFeePerGas and maxPriorityFeePerGas + const auth = await populateAndSignAuthAddress(CONTRACT_ADDRESS, wallet, provider) + const transactionCount = await provider.getTransactionCount(wallet.address) + const commonWithCustomChainId = createCustomCommon({chainId: auth.chainId}, Mainnet, { + eips: [7702], + hardfork: Hardfork.Cancun, + }) + const tx = createEOACode7702Tx( + { + authorizationList: [auth], + to: bytesToHex(PAY_FROM_ADDRESS), + gasLimit: BigInt(150000), + nonce: BigInt(transactionCount), + maxFeePerGas: tempTx.maxFeePerGas as bigint, + maxPriorityFeePerGas: tempTx.maxPriorityFeePerGas as bigint, + data: hexToBytes(data), + }, + {common: commonWithCustomChainId}, + ) + const signedTx = tx.sign(PAY_FROM_PRIVATE) + console.log(signedTx.toJSON()) + console.log(`https://explorer.pectra-devnet-3.ethpandaops.io/tx/${bytesToHex(signedTx.hash())}`) + // provider + // .broadcastTransaction(bytesToHex(signedTx.serialize())) + // .then(console.log) + // .catch(e => { + // console.log(e) + // console.log('Tx sent') + // }) + }) diff --git a/src/types.ts b/src/types.ts new file mode 100644 index 0000000..e69de29 diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 0000000..b9f2b27 --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,27 @@ +{ + "include": ["./src"], + "exclude": ["./build"], + "compilerOptions": { + "incremental": true, + "tsBuildInfoFile": "./build/.tsbuildinfo", + "target": "ES2022", + "module": "Node16", + "rootDir": "./src", + "moduleResolution": "Node16", + "sourceMap": true, + "outDir": "./build", + "removeComments": true, + "noEmitOnError": true, + "importHelpers": true, + "importsNotUsedAsValues": "remove", + "preserveValueImports": false, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "strict": true, + "useUnknownInCatchVariables": true, + "alwaysStrict": true, + "noFallthroughCasesInSwitch": true, + "noImplicitOverride": true, + "skipLibCheck": true, + } +}