diff --git a/.gitignore b/.gitignore index 3589ad7..51819d8 100644 --- a/.gitignore +++ b/.gitignore @@ -9,3 +9,6 @@ dist/ *.tsbuildinfo bin .codegpt + +# jest coverage +coverage/ \ No newline at end of file diff --git a/packages/ccip-svm/.prettierignore b/packages/ccip-svm/.prettierignore new file mode 100644 index 0000000..04c01ba --- /dev/null +++ b/packages/ccip-svm/.prettierignore @@ -0,0 +1,2 @@ +node_modules/ +dist/ \ No newline at end of file diff --git a/packages/ccip-svm/.prettierrc b/packages/ccip-svm/.prettierrc new file mode 100644 index 0000000..87d4114 --- /dev/null +++ b/packages/ccip-svm/.prettierrc @@ -0,0 +1,7 @@ +{ + "singleQuote": true, + "trailingComma": "all", + "tabWidth": 2, + "semi": false, + "printWidth": 120 +} \ No newline at end of file diff --git a/packages/ccip-svm/eslint.config.js b/packages/ccip-svm/eslint.config.js new file mode 100644 index 0000000..a614fa1 --- /dev/null +++ b/packages/ccip-svm/eslint.config.js @@ -0,0 +1,69 @@ +import js from '@eslint/js' +import tseslint from '@typescript-eslint/eslint-plugin' +import tsparser from '@typescript-eslint/parser' +import prettier from 'eslint-plugin-prettier' +import prettierConfig from 'eslint-config-prettier' + +export default [ + js.configs.recommended, + { + files: ['**/*.{js,ts}'], + languageOptions: { + parser: tsparser, + parserOptions: { + ecmaVersion: 'latest', + sourceType: 'module', + }, + globals: { + console: 'readonly', + process: 'readonly', + Buffer: 'readonly', + __dirname: 'readonly', + __filename: 'readonly', + global: 'readonly', + module: 'readonly', + require: 'readonly', + exports: 'readonly', + }, + }, + plugins: { + '@typescript-eslint': tseslint, + prettier: prettier, + }, + rules: { + ...tseslint.configs.recommended.rules, + ...prettierConfig.rules, + 'prettier/prettier': 'error', + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/ban-ts-comment': 'off', + '@typescript-eslint/no-non-null-assertion': 'off', + '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }], + '@typescript-eslint/explicit-module-boundary-types': 'off', + }, + }, + { + files: ['**/*.test.{js,ts}', '**/__tests__/**/*.{js,ts}'], + languageOptions: { + globals: { + describe: 'readonly', + it: 'readonly', + test: 'readonly', + expect: 'readonly', + beforeEach: 'readonly', + afterEach: 'readonly', + beforeAll: 'readonly', + afterAll: 'readonly', + jest: 'readonly', + }, + }, + }, + { + ignores: [ + 'node_modules/**', + 'dist/**', + 'coverage/**', + '*.config.js', + '*.config.json', + ], + }, +] \ No newline at end of file diff --git a/packages/ccip-svm/jest.config.json b/packages/ccip-svm/jest.config.json new file mode 100644 index 0000000..e8fdebe --- /dev/null +++ b/packages/ccip-svm/jest.config.json @@ -0,0 +1,22 @@ +{ + "preset": "ts-jest", + "testEnvironment": "node", + "testMatch": [ + "**/__tests__/**/*.test.ts" + ], + "collectCoverageFrom": [ + "src/**/*.ts", + "!src/**/*.d.ts", + "!src/__tests__/**/*" + ], + "moduleFileExtensions": [ + "ts", + "js", + "json" + ], + "transform": { + "^.+\\.ts$": "ts-jest" + }, + "workerThreads": true, + "testTimeout": 180000 +} \ No newline at end of file diff --git a/packages/ccip-svm/package-lock.json b/packages/ccip-svm/package-lock.json deleted file mode 100644 index c6bed98..0000000 --- a/packages/ccip-svm/package-lock.json +++ /dev/null @@ -1,953 +0,0 @@ -{ - "name": "@chainlink/ccip-svm", - "version": "0.0.1", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "@chainlink/ccip-svm", - "version": "0.0.1", - "license": "MIT", - "dependencies": { - "@solana/kit": "^3.0.3", - "viem": "^2.37.6" - } - }, - "node_modules/@adraffy/ens-normalize": { - "version": "1.11.0", - "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.11.0.tgz", - "integrity": "sha512-/3DDPKHqqIqxUULp8yP4zODUY1i+2xvVWsv8A79xGWdCAG+8sb0hRh0Rk2QyOJUnnbyPUAZYcpBuRe3nS2OIUg==", - "license": "MIT" - }, - "node_modules/@noble/ciphers": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-1.3.0.tgz", - "integrity": "sha512-2I0gnIVPtfnMw9ee9h1dJG7tp81+8Ob3OJb3Mv37rx5L40/b0i7djjCVvGOVqc9AEIQyvyu1i6ypKdFw8R8gQw==", - "license": "MIT", - "engines": { - "node": "^14.21.3 || >=16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@noble/curves": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.1.tgz", - "integrity": "sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA==", - "license": "MIT", - "dependencies": { - "@noble/hashes": "1.8.0" - }, - "engines": { - "node": "^14.21.3 || >=16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@noble/hashes": { - "version": "1.8.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz", - "integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==", - "license": "MIT", - "engines": { - "node": "^14.21.3 || >=16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@scure/base": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.2.6.tgz", - "integrity": "sha512-g/nm5FgUa//MCj1gV09zTJTaM6KBAHqLN907YVQqf7zC49+DcO4B1so4ZX07Ef10Twr6nuqYEH9GEggFXA4Fmg==", - "license": "MIT", - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@scure/bip32": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.7.0.tgz", - "integrity": "sha512-E4FFX/N3f4B80AKWp5dP6ow+flD1LQZo/w8UnLGYZO674jS6YnYeepycOOksv+vLPSpgN35wgKgy+ybfTb2SMw==", - "license": "MIT", - "dependencies": { - "@noble/curves": "~1.9.0", - "@noble/hashes": "~1.8.0", - "@scure/base": "~1.2.5" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@scure/bip39": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.6.0.tgz", - "integrity": "sha512-+lF0BbLiJNwVlev4eKelw1WWLaiKXw7sSl8T6FvBlWkdX+94aGJ4o8XjUdlyhTCjd8c+B3KT3JfS8P0bLRNU6A==", - "license": "MIT", - "dependencies": { - "@noble/hashes": "~1.8.0", - "@scure/base": "~1.2.5" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@solana/accounts": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@solana/accounts/-/accounts-3.0.3.tgz", - "integrity": "sha512-KqlePrlZaHXfu8YQTCxN204ZuVm9o68CCcUr6l27MG2cuRUtEM1Ta0iR8JFkRUAEfZJC4Cu0ZDjK/v49loXjZQ==", - "license": "MIT", - "dependencies": { - "@solana/addresses": "3.0.3", - "@solana/codecs-core": "3.0.3", - "@solana/codecs-strings": "3.0.3", - "@solana/errors": "3.0.3", - "@solana/rpc-spec": "3.0.3", - "@solana/rpc-types": "3.0.3" - }, - "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": ">=5.3.3" - } - }, - "node_modules/@solana/addresses": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@solana/addresses/-/addresses-3.0.3.tgz", - "integrity": "sha512-AuMwKhJI89ANqiuJ/fawcwxNKkSeHH9CApZd2xelQQLS7X8uxAOovpcmEgiObQuiVP944s9ScGUT62Bdul9qYg==", - "license": "MIT", - "dependencies": { - "@solana/assertions": "3.0.3", - "@solana/codecs-core": "3.0.3", - "@solana/codecs-strings": "3.0.3", - "@solana/errors": "3.0.3", - "@solana/nominal-types": "3.0.3" - }, - "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": ">=5.3.3" - } - }, - "node_modules/@solana/assertions": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@solana/assertions/-/assertions-3.0.3.tgz", - "integrity": "sha512-2qspxdbWp2y62dfCIlqeWQr4g+hE8FYSSwcaP6itwMwGRb8393yDGCJfI/znuzJh6m/XVWhMHIgFgsBwnevCmg==", - "license": "MIT", - "dependencies": { - "@solana/errors": "3.0.3" - }, - "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": ">=5.3.3" - } - }, - "node_modules/@solana/codecs": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@solana/codecs/-/codecs-3.0.3.tgz", - "integrity": "sha512-GOHwTlIQsCoJx9Ryr6cEf0FHKAQ7pY4aO4xgncAftrv0lveTQ1rPP2inQ1QT0gJllsIa8nwbfXAADs9nNJxQDA==", - "license": "MIT", - "dependencies": { - "@solana/codecs-core": "3.0.3", - "@solana/codecs-data-structures": "3.0.3", - "@solana/codecs-numbers": "3.0.3", - "@solana/codecs-strings": "3.0.3", - "@solana/options": "3.0.3" - }, - "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": ">=5.3.3" - } - }, - "node_modules/@solana/codecs-core": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@solana/codecs-core/-/codecs-core-3.0.3.tgz", - "integrity": "sha512-emKykJ3h1DmnDOY29Uv9eJXP8E/FHzvlUBJ6te+5EbKdFjj7vdlKYPfDxOI6iGdXTY+YC/ELtbNBh6QwF2uEDQ==", - "license": "MIT", - "dependencies": { - "@solana/errors": "3.0.3" - }, - "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": ">=5.3.3" - } - }, - "node_modules/@solana/codecs-data-structures": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@solana/codecs-data-structures/-/codecs-data-structures-3.0.3.tgz", - "integrity": "sha512-R15cLp8riJvToXziW8lP6AMSwsztGhEnwgyGmll32Mo0Yjq+hduW2/fJrA/TJs6tA/OgTzMQjlxgk009EqZHCw==", - "license": "MIT", - "dependencies": { - "@solana/codecs-core": "3.0.3", - "@solana/codecs-numbers": "3.0.3", - "@solana/errors": "3.0.3" - }, - "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": ">=5.3.3" - } - }, - "node_modules/@solana/codecs-numbers": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@solana/codecs-numbers/-/codecs-numbers-3.0.3.tgz", - "integrity": "sha512-pfXkH9J0glrM8qj6389GAn30+cJOxzXLR2FsPOHCUMXrqLhGjMMZAWhsQkpOQ37SGc/7EiQsT/gmyGC7gxHqJQ==", - "license": "MIT", - "dependencies": { - "@solana/codecs-core": "3.0.3", - "@solana/errors": "3.0.3" - }, - "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": ">=5.3.3" - } - }, - "node_modules/@solana/codecs-strings": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@solana/codecs-strings/-/codecs-strings-3.0.3.tgz", - "integrity": "sha512-VHBXnnTVtcQ1j+7Vrz+qSYo38no+jiHRdGnhFspRXEHNJbllzwKqgBE7YN3qoIXH+MKxgJUcwO5KHmdzf8Wn2A==", - "license": "MIT", - "dependencies": { - "@solana/codecs-core": "3.0.3", - "@solana/codecs-numbers": "3.0.3", - "@solana/errors": "3.0.3" - }, - "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "fastestsmallesttextencoderdecoder": "^1.0.22", - "typescript": ">=5.3.3" - } - }, - "node_modules/@solana/errors": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@solana/errors/-/errors-3.0.3.tgz", - "integrity": "sha512-1l84xJlHNva6io62PcYfUamwWlc0eM95nHgCrKX0g0cLoC6D6QHYPCEbEVkR+C5UtP9JDgyQM8MFiv+Ei5tO9Q==", - "license": "MIT", - "dependencies": { - "chalk": "5.6.2", - "commander": "14.0.0" - }, - "bin": { - "errors": "bin/cli.mjs" - }, - "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": ">=5.3.3" - } - }, - "node_modules/@solana/fast-stable-stringify": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@solana/fast-stable-stringify/-/fast-stable-stringify-3.0.3.tgz", - "integrity": "sha512-ED0pxB6lSEYvg+vOd5hcuQrgzEDnOrURFgp1ZOY+lQhJkQU6xo+P829NcJZQVP1rdU2/YQPAKJKEseyfe9VMIw==", - "license": "MIT", - "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": ">=5.3.3" - } - }, - "node_modules/@solana/functional": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@solana/functional/-/functional-3.0.3.tgz", - "integrity": "sha512-2qX1kKANn8995vOOh5S9AmF4ItGZcfbny0w28Eqy8AFh+GMnSDN4gqpmV2LvxBI9HibXZptGH3RVOMk82h1Mpw==", - "license": "MIT", - "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": ">=5.3.3" - } - }, - "node_modules/@solana/instruction-plans": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@solana/instruction-plans/-/instruction-plans-3.0.3.tgz", - "integrity": "sha512-eqoaPtWtmLTTpdvbt4BZF5H6FIlJtXi9H7qLOM1dLYonkOX2Ncezx5NDCZ9tMb2qxVMF4IocYsQnNSnMfjQF1w==", - "license": "MIT", - "dependencies": { - "@solana/errors": "3.0.3", - "@solana/instructions": "3.0.3", - "@solana/promises": "3.0.3", - "@solana/transaction-messages": "3.0.3", - "@solana/transactions": "3.0.3" - }, - "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": ">=5.3.3" - } - }, - "node_modules/@solana/instructions": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@solana/instructions/-/instructions-3.0.3.tgz", - "integrity": "sha512-4csIi8YUDb5j/J+gDzmYtOvq7ZWLbCxj4t0xKn+fPrBk/FD2pK29KVT3Fu7j4Lh1/ojunQUP9X4NHwUexY3PnA==", - "license": "MIT", - "dependencies": { - "@solana/codecs-core": "3.0.3", - "@solana/errors": "3.0.3" - }, - "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": ">=5.3.3" - } - }, - "node_modules/@solana/keys": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@solana/keys/-/keys-3.0.3.tgz", - "integrity": "sha512-tp8oK9tMadtSIc4vF4aXXWkPd4oU5XPW8nf28NgrGDWGt25fUHIydKjkf2hPtMt9i1WfRyQZ33B5P3dnsNqcPQ==", - "license": "MIT", - "dependencies": { - "@solana/assertions": "3.0.3", - "@solana/codecs-core": "3.0.3", - "@solana/codecs-strings": "3.0.3", - "@solana/errors": "3.0.3", - "@solana/nominal-types": "3.0.3" - }, - "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": ">=5.3.3" - } - }, - "node_modules/@solana/kit": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@solana/kit/-/kit-3.0.3.tgz", - "integrity": "sha512-CEEhCDmkvztd1zbgADsEQhmj9GyWOOGeW1hZD+gtwbBSF5YN1uofS/pex5MIh/VIqKRj+A2UnYWI1V+9+q/lyQ==", - "license": "MIT", - "dependencies": { - "@solana/accounts": "3.0.3", - "@solana/addresses": "3.0.3", - "@solana/codecs": "3.0.3", - "@solana/errors": "3.0.3", - "@solana/functional": "3.0.3", - "@solana/instruction-plans": "3.0.3", - "@solana/instructions": "3.0.3", - "@solana/keys": "3.0.3", - "@solana/programs": "3.0.3", - "@solana/rpc": "3.0.3", - "@solana/rpc-parsed-types": "3.0.3", - "@solana/rpc-spec-types": "3.0.3", - "@solana/rpc-subscriptions": "3.0.3", - "@solana/rpc-types": "3.0.3", - "@solana/signers": "3.0.3", - "@solana/sysvars": "3.0.3", - "@solana/transaction-confirmation": "3.0.3", - "@solana/transaction-messages": "3.0.3", - "@solana/transactions": "3.0.3" - }, - "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": ">=5.3.3" - } - }, - "node_modules/@solana/nominal-types": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@solana/nominal-types/-/nominal-types-3.0.3.tgz", - "integrity": "sha512-aZavCiexeUAoMHRQg4s1AHkH3wscbOb70diyfjhwZVgFz1uUsFez7csPp9tNFkNolnadVb2gky7yBk3IImQJ6A==", - "license": "MIT", - "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": ">=5.3.3" - } - }, - "node_modules/@solana/options": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@solana/options/-/options-3.0.3.tgz", - "integrity": "sha512-jarsmnQ63RN0JPC5j9sgUat07NrL9PC71XU7pUItd6LOHtu4+wJMio3l5mT0DHVfkfbFLL6iI6+QmXSVhTNF3g==", - "license": "MIT", - "dependencies": { - "@solana/codecs-core": "3.0.3", - "@solana/codecs-data-structures": "3.0.3", - "@solana/codecs-numbers": "3.0.3", - "@solana/codecs-strings": "3.0.3", - "@solana/errors": "3.0.3" - }, - "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": ">=5.3.3" - } - }, - "node_modules/@solana/programs": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@solana/programs/-/programs-3.0.3.tgz", - "integrity": "sha512-JZlVE3/AeSNDuH3aEzCZoDu8GTXkMpGXxf93zXLzbxfxhiQ/kHrReN4XE/JWZ/uGWbaFZGR5B3UtdN2QsoZL7w==", - "license": "MIT", - "dependencies": { - "@solana/addresses": "3.0.3", - "@solana/errors": "3.0.3" - }, - "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": ">=5.3.3" - } - }, - "node_modules/@solana/promises": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@solana/promises/-/promises-3.0.3.tgz", - "integrity": "sha512-K+UflGBVxj30XQMHTylHHZJdKH5QG3oj5k2s42GrZ/Wbu72oapVJySMBgpK45+p90t8/LEqV6rRPyTXlet9J+Q==", - "license": "MIT", - "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": ">=5.3.3" - } - }, - "node_modules/@solana/rpc": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@solana/rpc/-/rpc-3.0.3.tgz", - "integrity": "sha512-3oukAaLK78GegkKcm6iNmRnO4mFeNz+BMvA8T56oizoBNKiRVEq/6DFzVX/LkmZ+wvD601pAB3uCdrTPcC0YKQ==", - "license": "MIT", - "dependencies": { - "@solana/errors": "3.0.3", - "@solana/fast-stable-stringify": "3.0.3", - "@solana/functional": "3.0.3", - "@solana/rpc-api": "3.0.3", - "@solana/rpc-spec": "3.0.3", - "@solana/rpc-spec-types": "3.0.3", - "@solana/rpc-transformers": "3.0.3", - "@solana/rpc-transport-http": "3.0.3", - "@solana/rpc-types": "3.0.3" - }, - "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": ">=5.3.3" - } - }, - "node_modules/@solana/rpc-api": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@solana/rpc-api/-/rpc-api-3.0.3.tgz", - "integrity": "sha512-Yym9/Ama62OY69rAZgbOCAy1QlqaWAyb0VlqFuwSaZV1pkFCCFSwWEJEsiN1n8pb2ZP+RtwNvmYixvWizx9yvA==", - "license": "MIT", - "dependencies": { - "@solana/addresses": "3.0.3", - "@solana/codecs-core": "3.0.3", - "@solana/codecs-strings": "3.0.3", - "@solana/errors": "3.0.3", - "@solana/keys": "3.0.3", - "@solana/rpc-parsed-types": "3.0.3", - "@solana/rpc-spec": "3.0.3", - "@solana/rpc-transformers": "3.0.3", - "@solana/rpc-types": "3.0.3", - "@solana/transaction-messages": "3.0.3", - "@solana/transactions": "3.0.3" - }, - "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": ">=5.3.3" - } - }, - "node_modules/@solana/rpc-parsed-types": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@solana/rpc-parsed-types/-/rpc-parsed-types-3.0.3.tgz", - "integrity": "sha512-/koM05IM2fU91kYDQxXil3VBNlOfcP+gXE0js1sdGz8KonGuLsF61CiKB5xt6u1KEXhRyDdXYLjf63JarL4Ozg==", - "license": "MIT", - "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": ">=5.3.3" - } - }, - "node_modules/@solana/rpc-spec": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@solana/rpc-spec/-/rpc-spec-3.0.3.tgz", - "integrity": "sha512-MZn5/8BebB6MQ4Gstw6zyfWsFAZYAyLzMK+AUf/rSfT8tPmWiJ/mcxnxqOXvFup/l6D67U8pyGpIoFqwCeZqqA==", - "license": "MIT", - "dependencies": { - "@solana/errors": "3.0.3", - "@solana/rpc-spec-types": "3.0.3" - }, - "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": ">=5.3.3" - } - }, - "node_modules/@solana/rpc-spec-types": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@solana/rpc-spec-types/-/rpc-spec-types-3.0.3.tgz", - "integrity": "sha512-A6Jt8SRRetnN3CeGAvGJxigA9zYRslGgWcSjueAZGvPX+MesFxEUjSWZCfl+FogVFvwkqfkgQZQbPAGZQFJQ6Q==", - "license": "MIT", - "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": ">=5.3.3" - } - }, - "node_modules/@solana/rpc-subscriptions": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@solana/rpc-subscriptions/-/rpc-subscriptions-3.0.3.tgz", - "integrity": "sha512-LRvz6NaqvtsYFd32KwZ+rwYQ9XCs+DWjV8BvBLsJpt9/NWSuHf/7Sy/vvP6qtKxut692H/TMvHnC4iulg0WmiQ==", - "license": "MIT", - "dependencies": { - "@solana/errors": "3.0.3", - "@solana/fast-stable-stringify": "3.0.3", - "@solana/functional": "3.0.3", - "@solana/promises": "3.0.3", - "@solana/rpc-spec-types": "3.0.3", - "@solana/rpc-subscriptions-api": "3.0.3", - "@solana/rpc-subscriptions-channel-websocket": "3.0.3", - "@solana/rpc-subscriptions-spec": "3.0.3", - "@solana/rpc-transformers": "3.0.3", - "@solana/rpc-types": "3.0.3", - "@solana/subscribable": "3.0.3" - }, - "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": ">=5.3.3" - } - }, - "node_modules/@solana/rpc-subscriptions-api": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@solana/rpc-subscriptions-api/-/rpc-subscriptions-api-3.0.3.tgz", - "integrity": "sha512-MGgVK3PUS15qsjuhimpzGZrKD/CTTvS0mAlQ0Jw84zsr1RJVdQJK/F0igu07BVd172eTZL8d90NoAQ3dahW5pA==", - "license": "MIT", - "dependencies": { - "@solana/addresses": "3.0.3", - "@solana/keys": "3.0.3", - "@solana/rpc-subscriptions-spec": "3.0.3", - "@solana/rpc-transformers": "3.0.3", - "@solana/rpc-types": "3.0.3", - "@solana/transaction-messages": "3.0.3", - "@solana/transactions": "3.0.3" - }, - "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": ">=5.3.3" - } - }, - "node_modules/@solana/rpc-subscriptions-channel-websocket": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@solana/rpc-subscriptions-channel-websocket/-/rpc-subscriptions-channel-websocket-3.0.3.tgz", - "integrity": "sha512-zUzUlb8Cwnw+SHlsLrSqyBRtOJKGc+FvSNJo/vWAkLShoV0wUDMPv7VvhTngJx3B/3ANfrOZ4i08i9QfYPAvpQ==", - "license": "MIT", - "dependencies": { - "@solana/errors": "3.0.3", - "@solana/functional": "3.0.3", - "@solana/rpc-subscriptions-spec": "3.0.3", - "@solana/subscribable": "3.0.3" - }, - "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": ">=5.3.3", - "ws": "^8.18.0" - } - }, - "node_modules/@solana/rpc-subscriptions-spec": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@solana/rpc-subscriptions-spec/-/rpc-subscriptions-spec-3.0.3.tgz", - "integrity": "sha512-9KpQ32OBJWS85mn6q3gkM0AjQe1LKYlMU7gpJRrla/lvXxNLhI95tz5K6StctpUreVmRWTVkNamHE69uUQyY8A==", - "license": "MIT", - "dependencies": { - "@solana/errors": "3.0.3", - "@solana/promises": "3.0.3", - "@solana/rpc-spec-types": "3.0.3", - "@solana/subscribable": "3.0.3" - }, - "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": ">=5.3.3" - } - }, - "node_modules/@solana/rpc-transformers": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@solana/rpc-transformers/-/rpc-transformers-3.0.3.tgz", - "integrity": "sha512-lzdaZM/dG3s19Tsk4mkJA5JBoS1eX9DnD7z62gkDwrwJDkDBzkAJT9aLcsYFfTmwTfIp6uU2UPgGYc97i1wezw==", - "license": "MIT", - "dependencies": { - "@solana/errors": "3.0.3", - "@solana/functional": "3.0.3", - "@solana/nominal-types": "3.0.3", - "@solana/rpc-spec-types": "3.0.3", - "@solana/rpc-types": "3.0.3" - }, - "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": ">=5.3.3" - } - }, - "node_modules/@solana/rpc-transport-http": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@solana/rpc-transport-http/-/rpc-transport-http-3.0.3.tgz", - "integrity": "sha512-bIXFwr2LR5A97Z46dI661MJPbHnPfcShBjFzOS/8Rnr8P4ho3j/9EUtjDrsqoxGJT3SLWj5OlyXAlaDAvVTOUQ==", - "license": "MIT", - "dependencies": { - "@solana/errors": "3.0.3", - "@solana/rpc-spec": "3.0.3", - "@solana/rpc-spec-types": "3.0.3", - "undici-types": "^7.15.0" - }, - "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": ">=5.3.3" - } - }, - "node_modules/@solana/rpc-types": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@solana/rpc-types/-/rpc-types-3.0.3.tgz", - "integrity": "sha512-petWQ5xSny9UfmC3Qp2owyhNU0w9SyBww4+v7tSVyXMcCC9v6j/XsqTeimH1S0qQUllnv0/FY83ohFaxofmZ6Q==", - "license": "MIT", - "dependencies": { - "@solana/addresses": "3.0.3", - "@solana/codecs-core": "3.0.3", - "@solana/codecs-numbers": "3.0.3", - "@solana/codecs-strings": "3.0.3", - "@solana/errors": "3.0.3", - "@solana/nominal-types": "3.0.3" - }, - "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": ">=5.3.3" - } - }, - "node_modules/@solana/signers": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@solana/signers/-/signers-3.0.3.tgz", - "integrity": "sha512-UwCd/uPYTZiwd283JKVyOWLLN5sIgMBqGDyUmNU3vo9hcmXKv5ZGm/9TvwMY2z35sXWuIOcj7etxJ8OoWc/ObQ==", - "license": "MIT", - "dependencies": { - "@solana/addresses": "3.0.3", - "@solana/codecs-core": "3.0.3", - "@solana/errors": "3.0.3", - "@solana/instructions": "3.0.3", - "@solana/keys": "3.0.3", - "@solana/nominal-types": "3.0.3", - "@solana/transaction-messages": "3.0.3", - "@solana/transactions": "3.0.3" - }, - "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": ">=5.3.3" - } - }, - "node_modules/@solana/subscribable": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@solana/subscribable/-/subscribable-3.0.3.tgz", - "integrity": "sha512-FJ27LKGHLQ5GGttPvTOLQDLrrOZEgvaJhB7yYaHAhPk25+p+erBaQpjePhfkMyUbL1FQbxn1SUJmS6jUuaPjlQ==", - "license": "MIT", - "dependencies": { - "@solana/errors": "3.0.3" - }, - "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": ">=5.3.3" - } - }, - "node_modules/@solana/sysvars": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@solana/sysvars/-/sysvars-3.0.3.tgz", - "integrity": "sha512-GnHew+QeKCs2f9ow+20swEJMH4mDfJA/QhtPgOPTYQx/z69J4IieYJ7fZenSHnA//lJ45fVdNdmy1trypvPLBQ==", - "license": "MIT", - "dependencies": { - "@solana/accounts": "3.0.3", - "@solana/codecs": "3.0.3", - "@solana/errors": "3.0.3", - "@solana/rpc-types": "3.0.3" - }, - "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": ">=5.3.3" - } - }, - "node_modules/@solana/transaction-confirmation": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@solana/transaction-confirmation/-/transaction-confirmation-3.0.3.tgz", - "integrity": "sha512-dXx0OLtR95LMuARgi2dDQlL1QYmk56DOou5q9wKymmeV3JTvfDExeWXnOgjRBBq/dEfj4ugN1aZuTaS18UirFw==", - "license": "MIT", - "dependencies": { - "@solana/addresses": "3.0.3", - "@solana/codecs-strings": "3.0.3", - "@solana/errors": "3.0.3", - "@solana/keys": "3.0.3", - "@solana/promises": "3.0.3", - "@solana/rpc": "3.0.3", - "@solana/rpc-subscriptions": "3.0.3", - "@solana/rpc-types": "3.0.3", - "@solana/transaction-messages": "3.0.3", - "@solana/transactions": "3.0.3" - }, - "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": ">=5.3.3" - } - }, - "node_modules/@solana/transaction-messages": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@solana/transaction-messages/-/transaction-messages-3.0.3.tgz", - "integrity": "sha512-s+6NWRnBhnnjFWV4x2tzBzoWa6e5LiIxIvJlWwVQBFkc8fMGY04w7jkFh0PM08t/QFKeXBEWkyBDa/TFYdkWug==", - "license": "MIT", - "dependencies": { - "@solana/addresses": "3.0.3", - "@solana/codecs-core": "3.0.3", - "@solana/codecs-data-structures": "3.0.3", - "@solana/codecs-numbers": "3.0.3", - "@solana/errors": "3.0.3", - "@solana/functional": "3.0.3", - "@solana/instructions": "3.0.3", - "@solana/nominal-types": "3.0.3", - "@solana/rpc-types": "3.0.3" - }, - "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": ">=5.3.3" - } - }, - "node_modules/@solana/transactions": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@solana/transactions/-/transactions-3.0.3.tgz", - "integrity": "sha512-iMX+n9j4ON7H1nKlWEbMqMOpKYC6yVGxKKmWHT1KdLRG7v+03I4DnDeFoI+Zmw56FA+7Bbne8jwwX60Q1vk/MQ==", - "license": "MIT", - "dependencies": { - "@solana/addresses": "3.0.3", - "@solana/codecs-core": "3.0.3", - "@solana/codecs-data-structures": "3.0.3", - "@solana/codecs-numbers": "3.0.3", - "@solana/codecs-strings": "3.0.3", - "@solana/errors": "3.0.3", - "@solana/functional": "3.0.3", - "@solana/instructions": "3.0.3", - "@solana/keys": "3.0.3", - "@solana/nominal-types": "3.0.3", - "@solana/rpc-types": "3.0.3", - "@solana/transaction-messages": "3.0.3" - }, - "engines": { - "node": ">=20.18.0" - }, - "peerDependencies": { - "typescript": ">=5.3.3" - } - }, - "node_modules/abitype": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.1.0.tgz", - "integrity": "sha512-6Vh4HcRxNMLA0puzPjM5GBgT4aAcFGKZzSgAXvuZ27shJP6NEpielTuqbBmZILR5/xd0PizkBGy5hReKz9jl5A==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/wevm" - }, - "peerDependencies": { - "typescript": ">=5.0.4", - "zod": "^3.22.0 || ^4.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - }, - "zod": { - "optional": true - } - } - }, - "node_modules/chalk": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", - "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", - "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/commander": { - "version": "14.0.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.0.tgz", - "integrity": "sha512-2uM9rYjPvyq39NwLRqaiLtWHyDC1FvryJDa2ATTVims5YAS4PupsEQsDvP14FqhFr0P49CYDugi59xaxJlTXRA==", - "license": "MIT", - "engines": { - "node": ">=20" - } - }, - "node_modules/eventemitter3": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", - "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", - "license": "MIT" - }, - "node_modules/fastestsmallesttextencoderdecoder": { - "version": "1.0.22", - "resolved": "https://registry.npmjs.org/fastestsmallesttextencoderdecoder/-/fastestsmallesttextencoderdecoder-1.0.22.tgz", - "integrity": "sha512-Pb8d48e+oIuY4MaM64Cd7OW1gt4nxCHs7/ddPPZ/Ic3sg8yVGM7O9wDvZ7us6ScaUupzM+pfBolwtYhN1IxBIw==", - "license": "CC0-1.0", - "peer": true - }, - "node_modules/isows": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/isows/-/isows-1.0.7.tgz", - "integrity": "sha512-I1fSfDCZL5P0v33sVqeTDSpcstAg/N+wF5HS033mogOVIp4B+oHC7oOCsA3axAbBSGTJ8QubbNmnIRN/h8U7hg==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/wevm" - } - ], - "license": "MIT", - "peerDependencies": { - "ws": "*" - } - }, - "node_modules/ox": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/ox/-/ox-0.9.3.tgz", - "integrity": "sha512-KzyJP+fPV4uhuuqrTZyok4DC7vFzi7HLUFiUNEmpbyh59htKWkOC98IONC1zgXJPbHAhQgqs6B0Z6StCGhmQvg==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/wevm" - } - ], - "license": "MIT", - "dependencies": { - "@adraffy/ens-normalize": "^1.11.0", - "@noble/ciphers": "^1.3.0", - "@noble/curves": "1.9.1", - "@noble/hashes": "^1.8.0", - "@scure/bip32": "^1.7.0", - "@scure/bip39": "^1.6.0", - "abitype": "^1.0.9", - "eventemitter3": "5.0.1" - }, - "peerDependencies": { - "typescript": ">=5.4.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/typescript": { - "version": "5.9.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz", - "integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==", - "license": "Apache-2.0", - "peer": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/undici-types": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", - "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", - "license": "MIT" - }, - "node_modules/viem": { - "version": "2.37.6", - "resolved": "https://registry.npmjs.org/viem/-/viem-2.37.6.tgz", - "integrity": "sha512-b+1IozQ8TciVQNdQUkOH5xtFR0z7ZxR8pyloENi/a+RA408lv4LoX12ofwoiT3ip0VRhO5ni1em//X0jn/eW0g==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/wevm" - } - ], - "license": "MIT", - "dependencies": { - "@noble/curves": "1.9.1", - "@noble/hashes": "1.8.0", - "@scure/bip32": "1.7.0", - "@scure/bip39": "1.6.0", - "abitype": "1.1.0", - "isows": "1.0.7", - "ox": "0.9.3", - "ws": "8.18.3" - }, - "peerDependencies": { - "typescript": ">=5.0.4" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/ws": { - "version": "8.18.3", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", - "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", - "license": "MIT", - "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 - } - } - } - } -} diff --git a/packages/ccip-svm/package.json b/packages/ccip-svm/package.json index 638b531..9d890c4 100644 --- a/packages/ccip-svm/package.json +++ b/packages/ccip-svm/package.json @@ -9,9 +9,11 @@ "dist" ], "scripts": { - "build": "tsc ", + "build": "tsc", "dev": "tsc -w", - "test": "echo \"Error: no test specified\" && exit 1" + "test": "jest", + "lint": "eslint 'src/**/*.{ts,js}'", + "format": "prettier --write 'src/**/*.{ts,js,json,md}'" }, "repository": { "type": "git", @@ -32,6 +34,16 @@ "viem": "^2.37.6" }, "devDependencies": { + "@eslint/js": "^9.15.0", + "@types/jest": "^29.5.14", + "@typescript-eslint/eslint-plugin": "^8.0.0", + "@typescript-eslint/parser": "^8.0.0", + "eslint": "^9.15.0", + "eslint-config-prettier": "^9.0.0", + "eslint-plugin-prettier": "^5.0.0", + "jest": "^29.7.0", + "prettier": "^3.0.0", + "ts-jest": "^29.2.5", "typescript": "^5.6.3" } } \ No newline at end of file diff --git a/packages/ccip-svm/src/__tests__/evmExtraArgsV2.test.ts b/packages/ccip-svm/src/__tests__/evmExtraArgsV2.test.ts new file mode 100644 index 0000000..d2f3227 --- /dev/null +++ b/packages/ccip-svm/src/__tests__/evmExtraArgsV2.test.ts @@ -0,0 +1,114 @@ +import { + encodeEVMExtraArgsV2, + decodeEVMExtraArgsV2, + EVM_EXTRA_ARGS_V2_TAG, + EVM_EXTRA_ARGS_V2_MIN_LENGTH, +} from '../encoders/evmExtraArgsV2' +import { keccak256, toBytes } from 'viem' +import { fromHexBuffer } from '../utils/hex' + +describe('EVM Extra Args V2', () => { + let consoleSpy: jest.SpyInstance + + beforeEach(() => { + consoleSpy = jest.spyOn(console, 'warn').mockImplementation(() => {}) + }) + + afterEach(() => { + consoleSpy.mockRestore() + }) + + const testCases = [ + { + name: 'should encode with default allowOutOfOrderExecution=true', + input: { gasLimit: 100000n }, + expected: + '0x181dcf1000000000000000000000000000000000000000000000000000000000000186a00000000000000000000000000000000000000000000000000000000000000001', + shouldWarn: false, + }, + { + name: 'should encode with explicit allowOutOfOrderExecution=true', + input: { gasLimit: 100000n, allowOutOfOrderExecution: true }, + expected: + '0x181dcf1000000000000000000000000000000000000000000000000000000000000186a00000000000000000000000000000000000000000000000000000000000000001', + shouldWarn: false, + }, + { + name: 'should encode with allowOutOfOrderExecution=false and show warning', + input: { gasLimit: 100000n, allowOutOfOrderExecution: false }, + expected: + '0x181dcf1000000000000000000000000000000000000000000000000000000000000186a00000000000000000000000000000000000000000000000000000000000000000', + shouldWarn: true, + }, + { + name: 'should handle token-only transfers (gasLimit = 0)', + input: { gasLimit: 0n, allowOutOfOrderExecution: true }, + expected: + '0x181dcf1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001', + shouldWarn: false, + }, + ] + + describe('encodeEVMExtraArgsV2', () => { + test.each(testCases)('$name', ({ input, expected, shouldWarn }) => { + const encoded = encodeEVMExtraArgsV2(input) + + if (shouldWarn) { + expect(consoleSpy).toHaveBeenCalledWith( + `Warning: Setting allowOutOfOrderExecution to false is not recommended for EVM destinations. More details: https://docs.chain.link/ccip/concepts/best-practices/evm#best-practices`, + ) + } else { + expect(consoleSpy).not.toHaveBeenCalled() + } + + expect(encoded).toBeInstanceOf(Uint8Array) + expect(encoded.length).toBe(EVM_EXTRA_ARGS_V2_MIN_LENGTH) + const tag = new DataView(encoded.buffer, encoded.byteOffset, 4).getUint32(0, false) + expect(tag).toBe(EVM_EXTRA_ARGS_V2_TAG) + expect(encoded).toEqual(fromHexBuffer(expected)) + }) + }) + + describe('decodeEVMExtraArgsV2', () => { + test.each(testCases)('should decode EVM extra args correctly with $name', ({ input }) => { + const encoded = encodeEVMExtraArgsV2(input) + const decoded = decodeEVMExtraArgsV2(encoded) + + expect(decoded.gasLimit).toBe(input.gasLimit) + expect(decoded.allowOutOfOrderExecution).toBe(input.allowOutOfOrderExecution ?? true) + }) + + const errorTestCases = [ + { + name: 'data too short', + data: new Uint8Array(10), + expectedError: `Invalid EVM Extra Args V2: data too short, expected at least ${EVM_EXTRA_ARGS_V2_MIN_LENGTH} bytes (4 bytes tag + 32 bytes gasLimit + 32 bytes bool). Example (100_000 gasLimit and true): 0x181dcf1000000000000000000000000000000000000000000000000000000000000186a00000000000000000000000000000000000000000000000000000000000000001`, + }, + { + name: 'invalid tag', + data: (() => { + const invalidData = new Uint8Array(EVM_EXTRA_ARGS_V2_MIN_LENGTH) + invalidData[0] = 0x12 + invalidData[1] = 0x34 + invalidData[2] = 0x56 + invalidData[3] = 0x78 + return invalidData + })(), + expectedError: 'Invalid EVM Extra Args V2 tag: expected 0x181dcf10, got 0x12345678', + }, + ] + + test.each(errorTestCases)('should throw error for $name', ({ data, expectedError }) => { + expect(() => decodeEVMExtraArgsV2(data)).toThrow(expectedError) + }) + }) + + describe('EVM_EXTRA_ARGS_V2_TAG constant validation', () => { + it('should have correct EVM_EXTRA_ARGS_V2_TAG value matching bytes4(keccak256("CCIP EVMExtraArgsV2"))', () => { + const hash = keccak256(toBytes('CCIP EVMExtraArgsV2')) + const tagSelector = parseInt(hash.slice(0, 10), 16) // Take first 4 bytes (8 hex chars + 0x prefix) + + expect(EVM_EXTRA_ARGS_V2_TAG).toBe(tagSelector) + }) + }) +}) diff --git a/packages/ccip-svm/src/__tests__/svmExtraArgsV1.test.ts b/packages/ccip-svm/src/__tests__/svmExtraArgsV1.test.ts new file mode 100644 index 0000000..a5a4bab --- /dev/null +++ b/packages/ccip-svm/src/__tests__/svmExtraArgsV1.test.ts @@ -0,0 +1,175 @@ +import { address } from '@solana/kit' +import { + encodeSVMExtraArgsV1, + decodeSVMExtraArgsV1, + SVM_EXTRA_ARGS_V1_TAG, + SVM_EXTRA_ARGS_V1_MIN_LENGTH, +} from '../encoders/svmExtraArgsV1' +import { keccak256, toBytes } from 'viem' +import { fromHexBuffer } from '../utils/hex' + +const MOCK_TOKEN_RECEIVER = address('11111111111111111111111111111112') // System Program ID (Devnet) +const MOCK_ACCOUNT_1 = address('TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA') // Token Program ID (Devnet) +const MOCK_ACCOUNT_2 = address('ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL') // Associated Token Program ID (Devnet) +const MOCK_ACCOUNT_3 = address('So11111111111111111111111111111111111111112') // Wrapped SOL Token Mint (Devnet) +const MOCK_ACCOUNT_4 = address('4zMMC9srt5Ri5X14GAgXhaHii3GnPAEERYPJgZJDncDU') // USDC Token Mint (Devnet) +const MOCK_ACCOUNT_5 = address('DzcwGnG1kM1i6zE9vR4YmzjL48mF8Eik1gC9CkJTQ7K1') // USDT Token Mint (Devnet) + +describe('SVM Extra Args V1', () => { + const testCases = [ + { + name: 'should encode with default values', + input: {}, + expectedLength: SVM_EXTRA_ARGS_V1_MIN_LENGTH, + expectedHex: + '0x1f3b3aba00000000000000000000000001000000000000000000000000000000000000000000000000000000000000000000000000', + }, + { + name: 'should encode minimal SVM extra args', + input: { + computeUnits: 0, + accountIsWritableBitmap: 0n, + allowOutOfOrderExecution: false, + accounts: [], + }, + expectedLength: SVM_EXTRA_ARGS_V1_MIN_LENGTH, + expectedHex: + '0x1f3b3aba00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000', + }, + { + name: 'should handle token-only transfers (computeUnits = 0)', + input: { computeUnits: 0, allowOutOfOrderExecution: true }, + expectedLength: SVM_EXTRA_ARGS_V1_MIN_LENGTH, + }, + { + name: 'should encode SVM extra args with all parameters', + input: { + computeUnits: 400000, + accountIsWritableBitmap: 0b1010n, + allowOutOfOrderExecution: true, + tokenReceiver: MOCK_TOKEN_RECEIVER, + accounts: [MOCK_ACCOUNT_1, MOCK_ACCOUNT_2], + }, + expectedLength: SVM_EXTRA_ARGS_V1_MIN_LENGTH + 2 * 32, // 53 + 64 bytes for 2 accounts + }, + { + name: 'should encode with many accounts', + input: { + accounts: [MOCK_ACCOUNT_1, MOCK_ACCOUNT_2, MOCK_ACCOUNT_3, MOCK_ACCOUNT_4, MOCK_ACCOUNT_5], + }, + expectedLength: SVM_EXTRA_ARGS_V1_MIN_LENGTH + 5 * 32, // 53 + 160 bytes for 5 accounts + }, + ] + + describe('encodeSVMExtraArgsV1', () => { + test.each(testCases)('$name', ({ input, expectedLength, expectedHex }) => { + const encoded = encodeSVMExtraArgsV1(input) + + expect(encoded).toBeInstanceOf(Uint8Array) + expect(encoded.length).toBe(expectedLength) + + const tag = new DataView(encoded.buffer, encoded.byteOffset, 4).getUint32(0, false) + expect(tag).toBe(SVM_EXTRA_ARGS_V1_TAG) + + if (expectedHex) { + expect(encoded).toEqual(fromHexBuffer(expectedHex)) + } + }) + }) + + describe('decodeSVMExtraArgsV1', () => { + test.each(testCases)('should decode SVM extra args correctly with $name', ({ input }) => { + const encoded = encodeSVMExtraArgsV1(input) + const decoded = decodeSVMExtraArgsV1(encoded) + + expect(decoded.computeUnits).toBe(input.computeUnits ?? 0) + expect(decoded.accountIsWritableBitmap).toBe(input.accountIsWritableBitmap ?? 0n) + expect(decoded.allowOutOfOrderExecution).toBe(input.allowOutOfOrderExecution ?? true) + expect(decoded.accounts?.length).toBe(input.accounts?.length ?? 0) + expect(typeof decoded.tokenReceiver).toBe('string') + + if (input.tokenReceiver) { + expect(decoded.tokenReceiver?.toString()).toBe(input.tokenReceiver.toString()) + } + if (input.accounts) { + input.accounts.forEach((account, index) => { + expect(decoded.accounts?.[index].toString()).toBe(account.toString()) + }) + } + }) + + const errorTestCases = [ + { + name: 'data too short', + data: new Uint8Array(10), + expectedError: `Invalid SVM Extra Args V1: data too short, expected at least ${SVM_EXTRA_ARGS_V1_MIN_LENGTH} bytes (4 bytes tag + 4 bytes computeUnits + 8 bytes bitmap + 1 byte bool + 32 bytes tokenReceiver + 4 bytes accounts length)`, + }, + { + name: 'invalid tag', + data: (() => { + const invalidData = new Uint8Array(SVM_EXTRA_ARGS_V1_MIN_LENGTH) + invalidData[0] = 0x12 + invalidData[1] = 0x34 + invalidData[2] = 0x56 + invalidData[3] = 0x78 + return invalidData + })(), + expectedError: 'Invalid SVM Extra Args V1 tag: expected 0x1f3b3aba, got 0x12345678', + }, + ] + + test.each(errorTestCases)('should throw error for $name', ({ data, expectedError }) => { + expect(() => decodeSVMExtraArgsV1(data)).toThrow(expectedError) + }) + }) + + describe('serialization format validation', () => { + it('should serialize fields in correct Borsh-like format', () => { + const input = { + computeUnits: 0x12345678, + accountIsWritableBitmap: 0x123456789abcdef0n, + allowOutOfOrderExecution: false, + tokenReceiver: MOCK_TOKEN_RECEIVER, + accounts: [MOCK_ACCOUNT_1], + } + + const encoded = encodeSVMExtraArgsV1(input) + + // Verify tag (big-endian) + expect(encoded[0]).toBe(0x1f) + expect(encoded[1]).toBe(0x3b) + expect(encoded[2]).toBe(0x3a) + expect(encoded[3]).toBe(0xba) + + // Verify computeUnits (little-endian u32) + expect(encoded[4]).toBe(0x78) + expect(encoded[5]).toBe(0x56) + expect(encoded[6]).toBe(0x34) + expect(encoded[7]).toBe(0x12) + + // Verify accountIsWritableBitmap (little-endian u64) + expect(encoded[8]).toBe(0xf0) + expect(encoded[9]).toBe(0xde) + expect(encoded[10]).toBe(0xbc) + expect(encoded[11]).toBe(0x9a) + + // Verify allowOutOfOrderExecution (bool) + expect(encoded[16]).toBe(0x00) // false + + // Verify accounts length (little-endian u32) + expect(encoded[49]).toBe(0x01) // 1 account + expect(encoded[50]).toBe(0x00) + expect(encoded[51]).toBe(0x00) + expect(encoded[52]).toBe(0x00) + }) + }) + + describe('SVM_EXTRA_ARGS_V1_TAG constant validation', () => { + it('should have correct SVM_EXTRA_ARGS_V1_TAG value matching bytes4(keccak256("CCIP SVMExtraArgsV1"))', () => { + const hash = keccak256(toBytes('CCIP SVMExtraArgsV1')) + const tagSelector = parseInt(hash.slice(0, 10), 16) // Take first 4 bytes (8 hex chars + 0x prefix) + + expect(SVM_EXTRA_ARGS_V1_TAG).toBe(tagSelector) + }) + }) +}) diff --git a/packages/ccip-svm/src/encoders/evmExtraArgsV2.ts b/packages/ccip-svm/src/encoders/evmExtraArgsV2.ts new file mode 100644 index 0000000..9c81adf --- /dev/null +++ b/packages/ccip-svm/src/encoders/evmExtraArgsV2.ts @@ -0,0 +1,82 @@ +import { encodeAbiParameters, parseAbiParameters, decodeAbiParameters } from 'viem' +import { toHex, fromHexBuffer } from '../utils/hex' + +/** + * EVM Extra Args V2 tag: bytes4(keccak256("CCIP EVMExtraArgsV2")) + */ +export const EVM_EXTRA_ARGS_V2_TAG = 0x181dcf10 + +/** + * Minimum byte length for EVM Extra Args V2: 4 bytes tag + 32 bytes gasLimit + 32 bytes bool + */ +export const EVM_EXTRA_ARGS_V2_MIN_LENGTH = 68 + +export interface EVMExtraArgsV2 { + gasLimit: bigint + allowOutOfOrderExecution?: boolean +} + +/** + * Creates properly encoded extraArgs buffer for EVM destinations + * More details: https://docs.chain.link/ccip/api-reference/svm/v0.1.1/messages#evmextraargsv2 + * @param gasLimit - Gas limit for execution on destination chain (use 0 for token-only transfers) + * @param allowOutOfOrderExecution - Whether messages can be executed out of order (default: true) + * @returns Properly encoded extraArgs as Uint8Array + */ +export function encodeEVMExtraArgsV2({ gasLimit, allowOutOfOrderExecution = true }: EVMExtraArgsV2): Uint8Array { + if (allowOutOfOrderExecution === false) { + console.warn( + `Warning: Setting allowOutOfOrderExecution to false is not recommended for EVM destinations. More details: https://docs.chain.link/ccip/concepts/best-practices/evm#best-practices`, + ) + } + + // bytes4(keccak256("CCIP EVMExtraArgsV2")) = 0x181dcf10 + const tag = new Uint8Array([0x18, 0x1d, 0xcf, 0x10]) + + const encodedExtraArgs = encodeAbiParameters(parseAbiParameters('uint128 gasLimit, bool allowOutOfOrderExecution'), [ + gasLimit, + allowOutOfOrderExecution, + ]) + + const encodedExtraArgsBytes = fromHexBuffer(encodedExtraArgs) + + // abi.encodeWithSelector(EVM_EXTRA_ARGS_V2_TAG, extraArgs) + const result = new Uint8Array(tag.length + encodedExtraArgsBytes.length) + result.set(tag, 0) + result.set(encodedExtraArgsBytes, tag.length) + + return result +} + +/** + * Decodes EVM Extra Args V2 from bytes + * @param data - Encoded extra args bytes + * @returns Decoded EVMExtraArgsV2 object + */ +export function decodeEVMExtraArgsV2(data: Uint8Array): EVMExtraArgsV2 { + if (data.length < EVM_EXTRA_ARGS_V2_MIN_LENGTH) { + throw new Error( + `Invalid EVM Extra Args V2: data too short, expected at least ${EVM_EXTRA_ARGS_V2_MIN_LENGTH} bytes (4 bytes tag + 32 bytes gasLimit + 32 bytes bool). Example (100_000 gasLimit and true): 0x181dcf1000000000000000000000000000000000000000000000000000000000000186a00000000000000000000000000000000000000000000000000000000000000001`, + ) + } + + const tag = new DataView(data.buffer, data.byteOffset, 4).getUint32(0, false) // big endian + if (tag !== EVM_EXTRA_ARGS_V2_TAG) { + throw new Error( + `Invalid EVM Extra Args V2 tag: expected 0x${EVM_EXTRA_ARGS_V2_TAG.toString(16)}, got 0x${tag.toString(16)}`, + ) + } + + const extraArgsData = data.slice(4) + const extraArgsHex = toHex(extraArgsData) + + const [gasLimit, allowOutOfOrderExecution] = decodeAbiParameters( + parseAbiParameters('uint128 gasLimit, bool allowOutOfOrderExecution'), + extraArgsHex, + ) + + return { + gasLimit, + allowOutOfOrderExecution, + } +} diff --git a/packages/ccip-svm/src/encoders/svmExtraArgsV1.ts b/packages/ccip-svm/src/encoders/svmExtraArgsV1.ts new file mode 100644 index 0000000..8283e0c --- /dev/null +++ b/packages/ccip-svm/src/encoders/svmExtraArgsV1.ts @@ -0,0 +1,138 @@ +import { address, getAddressEncoder, getAddressDecoder } from '@solana/kit' + +/** + * SVM Extra Args V1 tag: bytes4(keccak256("CCIP SVMExtraArgsV1")) + */ +export const SVM_EXTRA_ARGS_V1_TAG = 0x1f3b3aba + +/** + * Minimum byte length for SVM Extra Args V1: 4 bytes tag + 4 bytes computeUnits + 8 bytes bitmap + 1 byte bool + 32 bytes tokenReceiver + 4 bytes accounts length + */ +export const SVM_EXTRA_ARGS_V1_MIN_LENGTH = 53 + +export type Address = ReturnType + +export interface SVMExtraArgsV1 { + computeUnits?: number + accountIsWritableBitmap?: bigint + allowOutOfOrderExecution?: boolean + tokenReceiver?: Address + accounts?: Address[] +} + +/** + * Creates properly encoded extraArgs buffer for SVM destinations + * More details: https://docs.chain.link/ccip/api-reference/svm/v0.1.1/messages#svmextraargsv1 + * @param options - SVM extra args configuration + * @returns Properly encoded extraArgs as Uint8Array + */ +export function encodeSVMExtraArgsV1({ + computeUnits = 0, + accountIsWritableBitmap = 0n, + allowOutOfOrderExecution = true, + tokenReceiver, + accounts = [], +}: SVMExtraArgsV1): Uint8Array { + // bytes4(keccak256("CCIP SVMExtraArgsV1")) = 0x1f3b3aba + const tag = new Uint8Array([0x1f, 0x3b, 0x3a, 0xba]) + + // Prepare data for Borsh-like serialization + const buffer: number[] = [] + + // Serialize compute_units (u32, little-endian) + const computeUnitsBytes = new Uint8Array(4) + new DataView(computeUnitsBytes.buffer).setUint32(0, computeUnits, true) + buffer.push(...computeUnitsBytes) + + // Serialize account_is_writable_bitmap (u64, little-endian) + const bitmapBytes = new Uint8Array(8) + new DataView(bitmapBytes.buffer).setBigUint64(0, accountIsWritableBitmap, true) + buffer.push(...bitmapBytes) + + // Serialize allow_out_of_order_execution (bool, 1 byte) + buffer.push(allowOutOfOrderExecution ? 1 : 0) + + // Serialize token_receiver ([u8; 32]) + const encoder = getAddressEncoder() + const tokenReceiverBytes = tokenReceiver ? encoder.encode(tokenReceiver) : new Uint8Array(32) // Default/zero address + buffer.push(...tokenReceiverBytes) + + // Serialize accounts (Vec<[u8; 32]>) + // First, serialize the length of the vector as u32 little-endian + const accountsLengthBytes = new Uint8Array(4) + new DataView(accountsLengthBytes.buffer).setUint32(0, accounts.length, true) + buffer.push(...accountsLengthBytes) + + // Then serialize each account (32 bytes each) + for (const account of accounts) { + buffer.push(...encoder.encode(account)) + } + + // Combine tag + serialized data + const serializedData = new Uint8Array(buffer) + const result = new Uint8Array(tag.length + serializedData.length) + result.set(tag, 0) + result.set(serializedData, tag.length) + + return result +} + +/** + * Decodes SVM Extra Args V1 from bytes + * @param data - Encoded extra args bytes + * @returns Decoded SVMExtraArgsV1 object + */ +export function decodeSVMExtraArgsV1(data: Uint8Array): SVMExtraArgsV1 { + if (data.length < SVM_EXTRA_ARGS_V1_MIN_LENGTH) { + throw new Error( + `Invalid SVM Extra Args V1: data too short, expected at least ${SVM_EXTRA_ARGS_V1_MIN_LENGTH} bytes (4 bytes tag + 4 bytes computeUnits + 8 bytes bitmap + 1 byte bool + 32 bytes tokenReceiver + 4 bytes accounts length)`, + ) + } + + // Verify tag + const tag = new DataView(data.buffer, data.byteOffset, 4).getUint32(0, false) // big endian + if (tag !== SVM_EXTRA_ARGS_V1_TAG) { + throw new Error( + `Invalid SVM Extra Args V1 tag: expected 0x${SVM_EXTRA_ARGS_V1_TAG.toString(16)}, got 0x${tag.toString(16)}`, + ) + } + + let offset = 4 // Skip tag + + // Deserialize compute_units (u32, little-endian) + const computeUnits = new DataView(data.buffer, data.byteOffset + offset, 4).getUint32(0, true) + offset += 4 + + // Deserialize account_is_writable_bitmap (u64, little-endian) + const accountIsWritableBitmap = new DataView(data.buffer, data.byteOffset + offset, 8).getBigUint64(0, true) + offset += 8 + + // Deserialize allow_out_of_order_execution (bool) + const allowOutOfOrderExecution = data[offset] === 1 + offset += 1 + + // Deserialize token_receiver ([u8; 32]) + const tokenReceiverBytes = data.slice(offset, offset + 32) + const decoder = getAddressDecoder() + const tokenReceiver = decoder.decode(tokenReceiverBytes) + offset += 32 + + // Deserialize accounts (Vec<[u8; 32]>) + const accountsLength = new DataView(data.buffer, data.byteOffset + offset, 4).getUint32(0, true) + offset += 4 + + const accounts: Address[] = [] + for (let i = 0; i < accountsLength; i++) { + const accountBytes = data.slice(offset, offset + 32) + accounts.push(decoder.decode(accountBytes)) + offset += 32 + } + + return { + computeUnits, + accountIsWritableBitmap, + allowOutOfOrderExecution, + tokenReceiver, + accounts, + } +} diff --git a/packages/ccip-svm/src/errors/custom.ts b/packages/ccip-svm/src/errors/custom.ts index a0fb6f2..575b4b4 100644 --- a/packages/ccip-svm/src/errors/custom.ts +++ b/packages/ccip-svm/src/errors/custom.ts @@ -1,296 +1,392 @@ export type CustomError = - | Unauthorized - | InvalidRMNRemoteAddress - | InvalidInputsMint - | InvalidVersion - | FeeTokenMismatch - | RedundantOwnerProposal - | ReachedMaxSequenceNumber - | InvalidInputsTokenIndices - | InvalidInputsPoolAccounts - | InvalidInputsTokenAccounts - | InvalidInputsTokenAdminRegistryAccounts - | InvalidInputsLookupTableAccounts - | InvalidInputsLookupTableAccountWritable - | InvalidInputsTokenAmount - | InvalidInputsTransferAllAmount - | InvalidInputsAtaAddress - | InvalidInputsAtaWritable - | InvalidInputsChainSelector - | InsufficientLamports - | InsufficientFunds - | SourceTokenDataTooLarge - | InvalidTokenAdminRegistryInputsZeroAddress - | InvalidTokenAdminRegistryProposedAdmin - | SenderNotAllowed - | InvalidCodeVersion - | InvalidCcipVersionRollback - | InvalidAccountListForPdaDerivation - | InvalidDerivationStage - | InvalidNonceVersion - | InvalidTokenPoolAccountDerivationResponse - | AccountDerivationResponseTooLarge - | DefaultOwnerProposal; + | Unauthorized + | InvalidRMNRemoteAddress + | InvalidInputsMint + | InvalidVersion + | FeeTokenMismatch + | RedundantOwnerProposal + | ReachedMaxSequenceNumber + | InvalidInputsTokenIndices + | InvalidInputsPoolAccounts + | InvalidInputsTokenAccounts + | InvalidInputsTokenAdminRegistryAccounts + | InvalidInputsLookupTableAccounts + | InvalidInputsLookupTableAccountWritable + | InvalidInputsTokenAmount + | InvalidInputsTransferAllAmount + | InvalidInputsAtaAddress + | InvalidInputsAtaWritable + | InvalidInputsChainSelector + | InsufficientLamports + | InsufficientFunds + | SourceTokenDataTooLarge + | InvalidTokenAdminRegistryInputsZeroAddress + | InvalidTokenAdminRegistryProposedAdmin + | SenderNotAllowed + | InvalidCodeVersion + | InvalidCcipVersionRollback + | InvalidAccountListForPdaDerivation + | InvalidDerivationStage + | InvalidNonceVersion + | InvalidTokenPoolAccountDerivationResponse + | AccountDerivationResponseTooLarge + | DefaultOwnerProposal export class Unauthorized extends Error { - static readonly code = 7000; - readonly code = 7000; - readonly name = 'Unauthorized'; - readonly msg = 'The signer is unauthorized'; - constructor(readonly logs?: string[]) { super('7000: The signer is unauthorized'); } + static readonly code = 7000 + readonly code = 7000 + readonly name = 'Unauthorized' + readonly msg = 'The signer is unauthorized' + constructor(readonly logs?: string[]) { + super('7000: The signer is unauthorized') + } } export class InvalidRMNRemoteAddress extends Error { - static readonly code = 7001; - readonly code = 7001; - readonly name = 'InvalidRMNRemoteAddress'; - readonly msg = 'Invalid RMN Remote Address'; - constructor(readonly logs?: string[]) { super('7001: Invalid RMN Remote Address'); } + static readonly code = 7001 + readonly code = 7001 + readonly name = 'InvalidRMNRemoteAddress' + readonly msg = 'Invalid RMN Remote Address' + constructor(readonly logs?: string[]) { + super('7001: Invalid RMN Remote Address') + } } export class InvalidInputsMint extends Error { - static readonly code = 7002; - readonly code = 7002; - readonly name = 'InvalidInputsMint'; - readonly msg = 'Mint account input is invalid'; - constructor(readonly logs?: string[]) { super('7002: Mint account input is invalid'); } + static readonly code = 7002 + readonly code = 7002 + readonly name = 'InvalidInputsMint' + readonly msg = 'Mint account input is invalid' + constructor(readonly logs?: string[]) { + super('7002: Mint account input is invalid') + } } export class InvalidVersion extends Error { - static readonly code = 7003; - readonly code = 7003; - readonly name = 'InvalidVersion'; - readonly msg = 'Invalid version of the onchain state'; - constructor(readonly logs?: string[]) { super('7003: Invalid version of the onchain state'); } + static readonly code = 7003 + readonly code = 7003 + readonly name = 'InvalidVersion' + readonly msg = 'Invalid version of the onchain state' + constructor(readonly logs?: string[]) { + super('7003: Invalid version of the onchain state') + } } export class FeeTokenMismatch extends Error { - static readonly code = 7004; - readonly code = 7004; - readonly name = 'FeeTokenMismatch'; - readonly msg = "Fee token doesn't match transfer token"; - constructor(readonly logs?: string[]) { super("7004: Fee token doesn't match transfer token"); } + static readonly code = 7004 + readonly code = 7004 + readonly name = 'FeeTokenMismatch' + readonly msg = "Fee token doesn't match transfer token" + constructor(readonly logs?: string[]) { + super("7004: Fee token doesn't match transfer token") + } } export class RedundantOwnerProposal extends Error { - static readonly code = 7005; - readonly code = 7005; - readonly name = 'RedundantOwnerProposal'; - readonly msg = 'Proposed owner is the current owner'; - constructor(readonly logs?: string[]) { super('7005: Proposed owner is the current owner'); } + static readonly code = 7005 + readonly code = 7005 + readonly name = 'RedundantOwnerProposal' + readonly msg = 'Proposed owner is the current owner' + constructor(readonly logs?: string[]) { + super('7005: Proposed owner is the current owner') + } } export class ReachedMaxSequenceNumber extends Error { - static readonly code = 7006; - readonly code = 7006; - readonly name = 'ReachedMaxSequenceNumber'; - readonly msg = 'Reached max sequence number'; - constructor(readonly logs?: string[]) { super('7006: Reached max sequence number'); } + static readonly code = 7006 + readonly code = 7006 + readonly name = 'ReachedMaxSequenceNumber' + readonly msg = 'Reached max sequence number' + constructor(readonly logs?: string[]) { + super('7006: Reached max sequence number') + } } export class InvalidInputsTokenIndices extends Error { - static readonly code = 7007; - readonly code = 7007; - readonly name = 'InvalidInputsTokenIndices'; - readonly msg = 'Invalid pool account indices'; - constructor(readonly logs?: string[]) { super('7007: Invalid pool account indices'); } + static readonly code = 7007 + readonly code = 7007 + readonly name = 'InvalidInputsTokenIndices' + readonly msg = 'Invalid pool account indices' + constructor(readonly logs?: string[]) { + super('7007: Invalid pool account indices') + } } export class InvalidInputsPoolAccounts extends Error { - static readonly code = 7008; - readonly code = 7008; - readonly name = 'InvalidInputsPoolAccounts'; - readonly msg = 'Invalid pool accounts'; - constructor(readonly logs?: string[]) { super('7008: Invalid pool accounts'); } + static readonly code = 7008 + readonly code = 7008 + readonly name = 'InvalidInputsPoolAccounts' + readonly msg = 'Invalid pool accounts' + constructor(readonly logs?: string[]) { + super('7008: Invalid pool accounts') + } } export class InvalidInputsTokenAccounts extends Error { - static readonly code = 7009; - readonly code = 7009; - readonly name = 'InvalidInputsTokenAccounts'; - readonly msg = 'Invalid token accounts'; - constructor(readonly logs?: string[]) { super('7009: Invalid token accounts'); } + static readonly code = 7009 + readonly code = 7009 + readonly name = 'InvalidInputsTokenAccounts' + readonly msg = 'Invalid token accounts' + constructor(readonly logs?: string[]) { + super('7009: Invalid token accounts') + } } export class InvalidInputsTokenAdminRegistryAccounts extends Error { - static readonly code = 7010; - readonly code = 7010; - readonly name = 'InvalidInputsTokenAdminRegistryAccounts'; - readonly msg = 'Invalid Token Admin Registry account'; - constructor(readonly logs?: string[]) { super('7010: Invalid Token Admin Registry account'); } + static readonly code = 7010 + readonly code = 7010 + readonly name = 'InvalidInputsTokenAdminRegistryAccounts' + readonly msg = 'Invalid Token Admin Registry account' + constructor(readonly logs?: string[]) { + super('7010: Invalid Token Admin Registry account') + } } export class InvalidInputsLookupTableAccounts extends Error { - static readonly code = 7011; - readonly code = 7011; - readonly name = 'InvalidInputsLookupTableAccounts'; - readonly msg = 'Invalid LookupTable account'; - constructor(readonly logs?: string[]) { super('7011: Invalid LookupTable account'); } + static readonly code = 7011 + readonly code = 7011 + readonly name = 'InvalidInputsLookupTableAccounts' + readonly msg = 'Invalid LookupTable account' + constructor(readonly logs?: string[]) { + super('7011: Invalid LookupTable account') + } } export class InvalidInputsLookupTableAccountWritable extends Error { - static readonly code = 7012; - readonly code = 7012; - readonly name = 'InvalidInputsLookupTableAccountWritable'; - readonly msg = 'Invalid LookupTable account writable access'; - constructor(readonly logs?: string[]) { super('7012: Invalid LookupTable account writable access'); } + static readonly code = 7012 + readonly code = 7012 + readonly name = 'InvalidInputsLookupTableAccountWritable' + readonly msg = 'Invalid LookupTable account writable access' + constructor(readonly logs?: string[]) { + super('7012: Invalid LookupTable account writable access') + } } export class InvalidInputsTokenAmount extends Error { - static readonly code = 7013; - readonly code = 7013; - readonly name = 'InvalidInputsTokenAmount'; - readonly msg = 'Cannot send zero tokens'; - constructor(readonly logs?: string[]) { super('7013: Cannot send zero tokens'); } + static readonly code = 7013 + readonly code = 7013 + readonly name = 'InvalidInputsTokenAmount' + readonly msg = 'Cannot send zero tokens' + constructor(readonly logs?: string[]) { + super('7013: Cannot send zero tokens') + } } export class InvalidInputsTransferAllAmount extends Error { - static readonly code = 7014; - readonly code = 7014; - readonly name = 'InvalidInputsTransferAllAmount'; - readonly msg = 'Must specify zero amount to send alongside transfer_all'; - constructor(readonly logs?: string[]) { super('7014: Must specify zero amount to send alongside transfer_all'); } + static readonly code = 7014 + readonly code = 7014 + readonly name = 'InvalidInputsTransferAllAmount' + readonly msg = 'Must specify zero amount to send alongside transfer_all' + constructor(readonly logs?: string[]) { + super('7014: Must specify zero amount to send alongside transfer_all') + } } export class InvalidInputsAtaAddress extends Error { - static readonly code = 7015; - readonly code = 7015; - readonly name = 'InvalidInputsAtaAddress'; - readonly msg = 'Invalid Associated Token Account address'; - constructor(readonly logs?: string[]) { super('7015: Invalid Associated Token Account address'); } + static readonly code = 7015 + readonly code = 7015 + readonly name = 'InvalidInputsAtaAddress' + readonly msg = 'Invalid Associated Token Account address' + constructor(readonly logs?: string[]) { + super('7015: Invalid Associated Token Account address') + } } export class InvalidInputsAtaWritable extends Error { - static readonly code = 7016; - readonly code = 7016; - readonly name = 'InvalidInputsAtaWritable'; - readonly msg = 'Invalid Associated Token Account writable flag'; - constructor(readonly logs?: string[]) { super('7016: Invalid Associated Token Account writable flag'); } + static readonly code = 7016 + readonly code = 7016 + readonly name = 'InvalidInputsAtaWritable' + readonly msg = 'Invalid Associated Token Account writable flag' + constructor(readonly logs?: string[]) { + super('7016: Invalid Associated Token Account writable flag') + } } export class InvalidInputsChainSelector extends Error { - static readonly code = 7017; - readonly code = 7017; - readonly name = 'InvalidInputsChainSelector'; - readonly msg = 'Chain selector is invalid'; - constructor(readonly logs?: string[]) { super('7017: Chain selector is invalid'); } + static readonly code = 7017 + readonly code = 7017 + readonly name = 'InvalidInputsChainSelector' + readonly msg = 'Chain selector is invalid' + constructor(readonly logs?: string[]) { + super('7017: Chain selector is invalid') + } } export class InsufficientLamports extends Error { - static readonly code = 7018; - readonly code = 7018; - readonly name = 'InsufficientLamports'; - readonly msg = 'Insufficient lamports'; - constructor(readonly logs?: string[]) { super('7018: Insufficient lamports'); } + static readonly code = 7018 + readonly code = 7018 + readonly name = 'InsufficientLamports' + readonly msg = 'Insufficient lamports' + constructor(readonly logs?: string[]) { + super('7018: Insufficient lamports') + } } export class InsufficientFunds extends Error { - static readonly code = 7019; - readonly code = 7019; - readonly name = 'InsufficientFunds'; - readonly msg = 'Insufficient funds'; - constructor(readonly logs?: string[]) { super('7019: Insufficient funds'); } + static readonly code = 7019 + readonly code = 7019 + readonly name = 'InsufficientFunds' + readonly msg = 'Insufficient funds' + constructor(readonly logs?: string[]) { + super('7019: Insufficient funds') + } } export class SourceTokenDataTooLarge extends Error { - static readonly code = 7020; - readonly code = 7020; - readonly name = 'SourceTokenDataTooLarge'; - readonly msg = 'Source token data is too large'; - constructor(readonly logs?: string[]) { super('7020: Source token data is too large'); } + static readonly code = 7020 + readonly code = 7020 + readonly name = 'SourceTokenDataTooLarge' + readonly msg = 'Source token data is too large' + constructor(readonly logs?: string[]) { + super('7020: Source token data is too large') + } } export class InvalidTokenAdminRegistryInputsZeroAddress extends Error { - static readonly code = 7021; - readonly code = 7021; - readonly name = 'InvalidTokenAdminRegistryInputsZeroAddress'; - readonly msg = 'New Admin can not be zero address'; - constructor(readonly logs?: string[]) { super('7021: New Admin can not be zero address'); } + static readonly code = 7021 + readonly code = 7021 + readonly name = 'InvalidTokenAdminRegistryInputsZeroAddress' + readonly msg = 'New Admin can not be zero address' + constructor(readonly logs?: string[]) { + super('7021: New Admin can not be zero address') + } } export class InvalidTokenAdminRegistryProposedAdmin extends Error { - static readonly code = 7022; - readonly code = 7022; - readonly name = 'InvalidTokenAdminRegistryProposedAdmin'; - readonly msg = 'An already owned registry can not be proposed'; - constructor(readonly logs?: string[]) { super('7022: An already owned registry can not be proposed'); } + static readonly code = 7022 + readonly code = 7022 + readonly name = 'InvalidTokenAdminRegistryProposedAdmin' + readonly msg = 'An already owned registry can not be proposed' + constructor(readonly logs?: string[]) { + super('7022: An already owned registry can not be proposed') + } } export class SenderNotAllowed extends Error { - static readonly code = 7023; - readonly code = 7023; - readonly name = 'SenderNotAllowed'; - readonly msg = 'Sender not allowed for that destination chain'; - constructor(readonly logs?: string[]) { super('7023: Sender not allowed for that destination chain'); } + static readonly code = 7023 + readonly code = 7023 + readonly name = 'SenderNotAllowed' + readonly msg = 'Sender not allowed for that destination chain' + constructor(readonly logs?: string[]) { + super('7023: Sender not allowed for that destination chain') + } } export class InvalidCodeVersion extends Error { - static readonly code = 7024; - readonly code = 7024; - readonly name = 'InvalidCodeVersion'; - readonly msg = 'Invalid code version'; - constructor(readonly logs?: string[]) { super('7024: Invalid code version'); } + static readonly code = 7024 + readonly code = 7024 + readonly name = 'InvalidCodeVersion' + readonly msg = 'Invalid code version' + constructor(readonly logs?: string[]) { + super('7024: Invalid code version') + } } export class InvalidCcipVersionRollback extends Error { - static readonly code = 7025; - readonly code = 7025; - readonly name = 'InvalidCcipVersionRollback'; - readonly msg = 'Invalid rollback attempt on the CCIP version of the onramp to the destination chain'; - constructor(readonly logs?: string[]) { super('7025: Invalid rollback attempt on the CCIP version of the onramp to the destination chain'); } + static readonly code = 7025 + readonly code = 7025 + readonly name = 'InvalidCcipVersionRollback' + readonly msg = 'Invalid rollback attempt on the CCIP version of the onramp to the destination chain' + constructor(readonly logs?: string[]) { + super('7025: Invalid rollback attempt on the CCIP version of the onramp to the destination chain') + } } export class InvalidAccountListForPdaDerivation extends Error { - static readonly code = 7026; - readonly code = 7026; - readonly name = 'InvalidAccountListForPdaDerivation'; - readonly msg = 'Invalid account list for PDA derivation'; - constructor(readonly logs?: string[]) { super('7026: Invalid account list for PDA derivation'); } + static readonly code = 7026 + readonly code = 7026 + readonly name = 'InvalidAccountListForPdaDerivation' + readonly msg = 'Invalid account list for PDA derivation' + constructor(readonly logs?: string[]) { + super('7026: Invalid account list for PDA derivation') + } } export class InvalidDerivationStage extends Error { - static readonly code = 7027; - readonly code = 7027; - readonly name = 'InvalidDerivationStage'; - readonly msg = 'Unexpected account derivation stage'; - constructor(readonly logs?: string[]) { super('7027: Unexpected account derivation stage'); } + static readonly code = 7027 + readonly code = 7027 + readonly name = 'InvalidDerivationStage' + readonly msg = 'Unexpected account derivation stage' + constructor(readonly logs?: string[]) { + super('7027: Unexpected account derivation stage') + } } export class InvalidNonceVersion extends Error { - static readonly code = 7028; - readonly code = 7028; - readonly name = 'InvalidNonceVersion'; - readonly msg = 'Invalid version of the Nonce account'; - constructor(readonly logs?: string[]) { super('7028: Invalid version of the Nonce account'); } + static readonly code = 7028 + readonly code = 7028 + readonly name = 'InvalidNonceVersion' + readonly msg = 'Invalid version of the Nonce account' + constructor(readonly logs?: string[]) { + super('7028: Invalid version of the Nonce account') + } } export class InvalidTokenPoolAccountDerivationResponse extends Error { - static readonly code = 7029; - readonly code = 7029; - readonly name = 'InvalidTokenPoolAccountDerivationResponse'; - readonly msg = 'Token pool returned an unexpected derivation response'; - constructor(readonly logs?: string[]) { super('7029: Token pool returned an unexpected derivation response'); } + static readonly code = 7029 + readonly code = 7029 + readonly name = 'InvalidTokenPoolAccountDerivationResponse' + readonly msg = 'Token pool returned an unexpected derivation response' + constructor(readonly logs?: string[]) { + super('7029: Token pool returned an unexpected derivation response') + } } export class AccountDerivationResponseTooLarge extends Error { - static readonly code = 7030; - readonly code = 7030; - readonly name = 'AccountDerivationResponseTooLarge'; - readonly msg = "Can't fit account derivation response"; - constructor(readonly logs?: string[]) { super("7030: Can't fit account derivation response"); } + static readonly code = 7030 + readonly code = 7030 + readonly name = 'AccountDerivationResponseTooLarge' + readonly msg = "Can't fit account derivation response" + constructor(readonly logs?: string[]) { + super("7030: Can't fit account derivation response") + } } export class DefaultOwnerProposal extends Error { - static readonly code = 7031; - readonly code = 7031; - readonly name = 'DefaultOwnerProposal'; - readonly msg = 'Proposed owner is the default pubkey'; - constructor(readonly logs?: string[]) { super('7031: Proposed owner is the default pubkey'); } + static readonly code = 7031 + readonly code = 7031 + readonly name = 'DefaultOwnerProposal' + readonly msg = 'Proposed owner is the default pubkey' + constructor(readonly logs?: string[]) { + super('7031: Proposed owner is the default pubkey') + } } export function fromCode(code: number, logs?: string[]): CustomError | null { - switch (code) { - case 7000: return new Unauthorized(logs); - case 7001: return new InvalidRMNRemoteAddress(logs); - case 7002: return new InvalidInputsMint(logs); - case 7003: return new InvalidVersion(logs); - case 7004: return new FeeTokenMismatch(logs); - case 7005: return new RedundantOwnerProposal(logs); - case 7006: return new ReachedMaxSequenceNumber(logs); - case 7007: return new InvalidInputsTokenIndices(logs); - case 7008: return new InvalidInputsPoolAccounts(logs); - case 7009: return new InvalidInputsTokenAccounts(logs); - case 7010: return new InvalidInputsTokenAdminRegistryAccounts(logs); - case 7011: return new InvalidInputsLookupTableAccounts(logs); - case 7012: return new InvalidInputsLookupTableAccountWritable(logs); - case 7013: return new InvalidInputsTokenAmount(logs); - case 7014: return new InvalidInputsTransferAllAmount(logs); - case 7015: return new InvalidInputsAtaAddress(logs); - case 7016: return new InvalidInputsAtaWritable(logs); - case 7017: return new InvalidInputsChainSelector(logs); - case 7018: return new InsufficientLamports(logs); - case 7019: return new InsufficientFunds(logs); - case 7020: return new SourceTokenDataTooLarge(logs); - case 7021: return new InvalidTokenAdminRegistryInputsZeroAddress(logs); - case 7022: return new InvalidTokenAdminRegistryProposedAdmin(logs); - case 7023: return new SenderNotAllowed(logs); - case 7024: return new InvalidCodeVersion(logs); - case 7025: return new InvalidCcipVersionRollback(logs); - case 7026: return new InvalidAccountListForPdaDerivation(logs); - case 7027: return new InvalidDerivationStage(logs); - case 7028: return new InvalidNonceVersion(logs); - case 7029: return new InvalidTokenPoolAccountDerivationResponse(logs); - case 7030: return new AccountDerivationResponseTooLarge(logs); - case 7031: return new DefaultOwnerProposal(logs); - } - return null; + switch (code) { + case 7000: + return new Unauthorized(logs) + case 7001: + return new InvalidRMNRemoteAddress(logs) + case 7002: + return new InvalidInputsMint(logs) + case 7003: + return new InvalidVersion(logs) + case 7004: + return new FeeTokenMismatch(logs) + case 7005: + return new RedundantOwnerProposal(logs) + case 7006: + return new ReachedMaxSequenceNumber(logs) + case 7007: + return new InvalidInputsTokenIndices(logs) + case 7008: + return new InvalidInputsPoolAccounts(logs) + case 7009: + return new InvalidInputsTokenAccounts(logs) + case 7010: + return new InvalidInputsTokenAdminRegistryAccounts(logs) + case 7011: + return new InvalidInputsLookupTableAccounts(logs) + case 7012: + return new InvalidInputsLookupTableAccountWritable(logs) + case 7013: + return new InvalidInputsTokenAmount(logs) + case 7014: + return new InvalidInputsTransferAllAmount(logs) + case 7015: + return new InvalidInputsAtaAddress(logs) + case 7016: + return new InvalidInputsAtaWritable(logs) + case 7017: + return new InvalidInputsChainSelector(logs) + case 7018: + return new InsufficientLamports(logs) + case 7019: + return new InsufficientFunds(logs) + case 7020: + return new SourceTokenDataTooLarge(logs) + case 7021: + return new InvalidTokenAdminRegistryInputsZeroAddress(logs) + case 7022: + return new InvalidTokenAdminRegistryProposedAdmin(logs) + case 7023: + return new SenderNotAllowed(logs) + case 7024: + return new InvalidCodeVersion(logs) + case 7025: + return new InvalidCcipVersionRollback(logs) + case 7026: + return new InvalidAccountListForPdaDerivation(logs) + case 7027: + return new InvalidDerivationStage(logs) + case 7028: + return new InvalidNonceVersion(logs) + case 7029: + return new InvalidTokenPoolAccountDerivationResponse(logs) + case 7030: + return new AccountDerivationResponseTooLarge(logs) + case 7031: + return new DefaultOwnerProposal(logs) + } + return null } diff --git a/packages/ccip-svm/src/index.ts b/packages/ccip-svm/src/index.ts index 8d52968..9401a38 100644 --- a/packages/ccip-svm/src/index.ts +++ b/packages/ccip-svm/src/index.ts @@ -1 +1,4 @@ -export * from './errors/custom'; +export * from './encoders/evmExtraArgsV2' +export * from './encoders/svmExtraArgsV1' +export * from './errors/custom' +export * from './utils/hex' diff --git a/packages/ccip-svm/src/utils/hex.ts b/packages/ccip-svm/src/utils/hex.ts new file mode 100644 index 0000000..504f4ac --- /dev/null +++ b/packages/ccip-svm/src/utils/hex.ts @@ -0,0 +1,38 @@ +/** + * Converts a Uint8Array to a hex string with 0x prefix + * @param bytes - The bytes to convert + * @returns Hex string with 0x prefix + */ +export function toHex(bytes: Uint8Array): `0x${string}` { + return `0x${Array.from(bytes) + .map((b) => b.toString(16).padStart(2, '0')) + .join('')}` as `0x${string}` +} + +/** + * Converts a hex string (with or without 0x prefix) to Uint8Array + * @param hex - The hex string to convert + * @returns Uint8Array containing the bytes + */ +export function fromHex(hex: string): Uint8Array { + const cleanHex = hex.startsWith('0x') ? hex.slice(2) : hex + if (cleanHex.length % 2 !== 0) { + throw new Error('Invalid hex string: length must be even') + } + + const bytes = new Uint8Array(cleanHex.length / 2) + for (let i = 0; i < cleanHex.length; i += 2) { + bytes[i / 2] = parseInt(cleanHex.slice(i, i + 2), 16) + } + return bytes +} + +/** + * Converts a hex string to Uint8Array using Buffer (for compatibility) + * @param hex - The hex string to convert (with or without 0x prefix) + * @returns Uint8Array containing the bytes + */ +export function fromHexBuffer(hex: string): Uint8Array { + const cleanHex = hex.startsWith('0x') ? hex.slice(2) : hex + return new Uint8Array(Buffer.from(cleanHex, 'hex')) +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 45c0b91..184e5bf 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -23,10 +23,10 @@ importers: dependencies: '@chainlink/ccip-js': specifier: ^0.2.1 - version: 0.2.4(a3c99c0fb0fe13a5c24ee996cead66b3) + version: 0.2.4(9f66f6640aaefa29aa7e5aa056ab9158) '@chainlink/ccip-react-components': specifier: ^0.3.0 - version: 0.3.0(1ed1302eb82042231a950ad4c671505f) + version: 0.3.0(db7643b72c37e7ac37a76874ef595e85) '@tanstack/react-query': specifier: ^5.37.1 version: 5.80.7(react@18.3.1) @@ -81,7 +81,7 @@ importers: version: 3.0.9(ethers@6.13.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.24.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.12.1)(@types/node@22.15.32)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) '@nomicfoundation/hardhat-toolbox': specifier: ^5.0.0 - version: 5.0.0(775720b1c6d0d796629832f440f70ca5) + version: 5.0.0(4a8c7a36d0534b6db66906aadca1ca67) '@nomicfoundation/hardhat-viem': specifier: ^2.0.5 version: 2.0.6(hardhat@2.24.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.12.1)(@types/node@22.15.32)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10))(typescript@5.8.3)(viem@2.21.25(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.67))(zod@3.25.67) @@ -310,6 +310,36 @@ importers: specifier: ^2.37.6 version: 2.37.6(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.67) devDependencies: + '@eslint/js': + specifier: ^9.15.0 + version: 9.29.0 + '@types/jest': + specifier: ^29.5.14 + version: 29.5.14 + '@typescript-eslint/eslint-plugin': + specifier: ^8.0.0 + version: 8.34.1(@typescript-eslint/parser@8.34.1(eslint@9.29.0(jiti@1.21.7))(typescript@5.8.3))(eslint@9.29.0(jiti@1.21.7))(typescript@5.8.3) + '@typescript-eslint/parser': + specifier: ^8.0.0 + version: 8.34.1(eslint@9.29.0(jiti@1.21.7))(typescript@5.8.3) + eslint: + specifier: ^9.15.0 + version: 9.29.0(jiti@1.21.7) + eslint-config-prettier: + specifier: ^9.0.0 + version: 9.1.0(eslint@9.29.0(jiti@1.21.7)) + eslint-plugin-prettier: + specifier: ^5.0.0 + version: 5.5.0(eslint-config-prettier@9.1.0(eslint@9.29.0(jiti@1.21.7)))(eslint@9.29.0(jiti@1.21.7))(prettier@3.5.3) + jest: + specifier: ^29.7.0 + version: 29.7.0 + prettier: + specifier: ^3.0.0 + version: 3.5.3 + ts-jest: + specifier: ^29.2.5 + version: 29.4.0(@babel/core@7.27.4)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.27.4))(jest-util@29.7.0)(jest@29.7.0)(typescript@5.8.3) typescript: specifier: ^5.6.3 version: 5.8.3 @@ -339,10 +369,6 @@ packages: '@asamuzakjp/css-color@3.1.1': resolution: {integrity: sha512-hpRD68SV2OMcZCsrbdkccTw5FXjNDLo5OuqSHyHZfwweGsDWZwDJ2+gONyNAbazZclobMirACLw0lk8WVxIqxA==} - '@babel/code-frame@7.26.2': - resolution: {integrity: sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==} - engines: {node: '>=6.9.0'} - '@babel/code-frame@7.27.1': resolution: {integrity: sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==} engines: {node: '>=6.9.0'} @@ -417,10 +443,6 @@ packages: resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==} engines: {node: '>=6.9.0'} - '@babel/helper-validator-identifier@7.25.9': - resolution: {integrity: sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==} - engines: {node: '>=6.9.0'} - '@babel/helper-validator-identifier@7.27.1': resolution: {integrity: sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==} engines: {node: '>=6.9.0'} @@ -3207,6 +3229,9 @@ packages: '@types/chai@5.2.0': resolution: {integrity: sha512-FWnQYdrG9FAC8KgPVhDFfrPL1FBsL3NtIt2WsxKvwu/61K6HiuDF3xAb7c7w/k9ML2QOUHcwTgU7dKLFPK6sBg==} + '@types/chai@5.2.2': + resolution: {integrity: sha512-8kB30R7Hwqf40JPiKhVzodJs2Qc1ZJ5zuT3uzw5Hq/dhNCl3G3l83jfpdI1e20BP348+fV7VIL/+FxaXkqBmWg==} + '@types/concat-stream@1.6.1': resolution: {integrity: sha512-eHE4cQPoj6ngxBZMvVf6Hw7Mh4jMW4U9lpGmS5GBPB9RYxlFg+CHaVN7ErNY4W9XfLIEn20b4VDYaIrbq0q4uA==} @@ -3240,6 +3265,9 @@ packages: '@types/istanbul-reports@3.0.4': resolution: {integrity: sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==} + '@types/jest@29.5.14': + resolution: {integrity: sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==} + '@types/json-schema@7.0.15': resolution: {integrity: sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==} @@ -8584,12 +8612,6 @@ snapshots: '@csstools/css-tokenizer': 3.0.3 lru-cache: 10.4.3 - '@babel/code-frame@7.26.2': - dependencies: - '@babel/helper-validator-identifier': 7.25.9 - js-tokens: 4.0.0 - picocolors: 1.1.1 - '@babel/code-frame@7.27.1': dependencies: '@babel/helper-validator-identifier': 7.27.1 @@ -8708,8 +8730,6 @@ snapshots: '@babel/helper-string-parser@7.27.1': {} - '@babel/helper-validator-identifier@7.25.9': {} - '@babel/helper-validator-identifier@7.27.1': {} '@babel/helper-validator-option@7.27.1': {} @@ -8884,7 +8904,7 @@ snapshots: '@babel/types@7.26.10': dependencies: '@babel/helper-string-parser': 7.25.9 - '@babel/helper-validator-identifier': 7.25.9 + '@babel/helper-validator-identifier': 7.27.1 '@babel/types@7.27.6': dependencies: @@ -8895,19 +8915,19 @@ snapshots: '@bcoe/v8-coverage@1.0.2': {} - '@chainlink/ccip-js@0.2.4(5e3e05d9b50680c4de2bc0a3c2cf5c97)': + '@chainlink/ccip-js@0.2.4(9f66f6640aaefa29aa7e5aa056ab9158)': dependencies: '@nomicfoundation/hardhat-chai-matchers': 2.0.8(@nomicfoundation/hardhat-ethers@3.0.8(ethers@6.13.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.24.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.12.1)(@types/node@20.19.1)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)))(chai@5.2.0)(ethers@6.13.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.24.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.12.1)(@types/node@20.19.1)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) '@nomicfoundation/hardhat-ethers': 3.0.8(ethers@6.13.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.24.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.12.1)(@types/node@20.19.1)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) - '@nomicfoundation/hardhat-toolbox': 5.0.0(13680ddddf672fc71131616f3a7f7389) - '@nomicfoundation/hardhat-viem': 2.0.6(hardhat@2.24.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.12.1)(@types/node@20.19.1)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10))(typescript@5.8.3)(viem@2.21.25(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.67))(zod@3.24.2) + '@nomicfoundation/hardhat-toolbox': 5.0.0(d50884c5ccf68f1f6d25fc3e5da82825) + '@nomicfoundation/hardhat-viem': 2.0.6(hardhat@2.24.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.12.1)(@types/node@20.19.1)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10))(typescript@5.8.3)(viem@2.21.25(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.67))(zod@3.25.67) '@openzeppelin/contracts': 5.2.0 chai: 5.2.0 ethers: 6.13.4(bufferutil@4.0.9)(utf-8-validate@5.0.10) mocha: 11.7.0 ts-jest: 29.2.6(@babel/core@7.27.4)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.27.4))(jest@29.7.0(@types/node@20.19.1)(ts-node@10.9.2(@swc/core@1.12.1)(@types/node@20.19.1)(typescript@5.8.3)))(typescript@5.8.3) typescript: 5.8.3 - viem: 2.21.25(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.24.2) + viem: 2.21.25(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.67) transitivePeerDependencies: - '@babel/core' - '@jest/transform' @@ -8933,19 +8953,19 @@ snapshots: - utf-8-validate - zod - '@chainlink/ccip-js@0.2.4(a3c99c0fb0fe13a5c24ee996cead66b3)': + '@chainlink/ccip-js@0.2.4(e75b9ef2f0597dd774bc03c1382dca08)': dependencies: '@nomicfoundation/hardhat-chai-matchers': 2.0.8(@nomicfoundation/hardhat-ethers@3.0.8(ethers@6.13.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.24.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.12.1)(@types/node@20.19.1)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)))(chai@5.2.0)(ethers@6.13.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.24.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.12.1)(@types/node@20.19.1)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) '@nomicfoundation/hardhat-ethers': 3.0.8(ethers@6.13.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.24.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.12.1)(@types/node@20.19.1)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) - '@nomicfoundation/hardhat-toolbox': 5.0.0(13680ddddf672fc71131616f3a7f7389) - '@nomicfoundation/hardhat-viem': 2.0.6(hardhat@2.24.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.12.1)(@types/node@20.19.1)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10))(typescript@5.8.3)(viem@2.21.25(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.67))(zod@3.25.67) + '@nomicfoundation/hardhat-toolbox': 5.0.0(d50884c5ccf68f1f6d25fc3e5da82825) + '@nomicfoundation/hardhat-viem': 2.0.6(hardhat@2.24.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.12.1)(@types/node@20.19.1)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10))(typescript@5.8.3)(viem@2.21.25(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.67))(zod@3.24.2) '@openzeppelin/contracts': 5.2.0 chai: 5.2.0 ethers: 6.13.4(bufferutil@4.0.9)(utf-8-validate@5.0.10) mocha: 11.7.0 ts-jest: 29.2.6(@babel/core@7.27.4)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.27.4))(jest@29.7.0(@types/node@20.19.1)(ts-node@10.9.2(@swc/core@1.12.1)(@types/node@20.19.1)(typescript@5.8.3)))(typescript@5.8.3) typescript: 5.8.3 - viem: 2.21.25(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.25.67) + viem: 2.21.25(bufferutil@4.0.9)(typescript@5.8.3)(utf-8-validate@5.0.10)(zod@3.24.2) transitivePeerDependencies: - '@babel/core' - '@jest/transform' @@ -8971,9 +8991,9 @@ snapshots: - utf-8-validate - zod - '@chainlink/ccip-react-components@0.3.0(1ed1302eb82042231a950ad4c671505f)': + '@chainlink/ccip-react-components@0.3.0(db7643b72c37e7ac37a76874ef595e85)': dependencies: - '@chainlink/ccip-js': 0.2.4(5e3e05d9b50680c4de2bc0a3c2cf5c97) + '@chainlink/ccip-js': 0.2.4(e75b9ef2f0597dd774bc03c1382dca08) '@hookform/resolvers': 3.10.0(react-hook-form@7.54.2(react@18.3.1)) '@radix-ui/react-dialog': 1.1.6(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@radix-ui/react-label': 2.1.2(@types/react-dom@18.3.7(@types/react@18.3.23))(@types/react@18.3.23)(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -9968,6 +9988,41 @@ snapshots: jest-util: 29.7.0 slash: 3.0.0 + '@jest/core@29.7.0': + 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': 22.15.32 + ansi-escapes: 4.3.2 + chalk: 4.1.2 + ci-info: 3.9.0 + exit: 0.1.2 + graceful-fs: 4.2.11 + jest-changed-files: 29.7.0 + jest-config: 29.7.0(@types/node@22.15.32)(ts-node@10.9.2(@swc/core@1.12.1)(@types/node@22.15.32)(typescript@5.8.3)) + 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.8 + pretty-format: 29.7.0 + slash: 3.0.0 + strip-ansi: 6.0.1 + transitivePeerDependencies: + - babel-plugin-macros + - supports-color + - ts-node + '@jest/core@29.7.0(ts-node@10.9.2(@swc/core@1.12.1)(@types/node@20.19.1)(typescript@5.8.3))': dependencies: '@jest/console': 29.7.0 @@ -10675,28 +10730,7 @@ snapshots: ethereumjs-util: 7.1.5 hardhat: 2.24.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.12.1)(@types/node@22.15.32)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10) - '@nomicfoundation/hardhat-toolbox@5.0.0(13680ddddf672fc71131616f3a7f7389)': - dependencies: - '@nomicfoundation/hardhat-chai-matchers': 2.0.8(@nomicfoundation/hardhat-ethers@3.0.8(ethers@6.13.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.24.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.12.1)(@types/node@20.19.1)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)))(chai@5.2.0)(ethers@6.13.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.24.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.12.1)(@types/node@20.19.1)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) - '@nomicfoundation/hardhat-ethers': 3.0.8(ethers@6.13.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.24.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.12.1)(@types/node@20.19.1)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) - '@nomicfoundation/hardhat-ignition-ethers': 0.15.10(@nomicfoundation/hardhat-ethers@3.0.8(ethers@6.13.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.24.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.12.1)(@types/node@20.19.1)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)))(@nomicfoundation/hardhat-ignition@0.15.10(@nomicfoundation/hardhat-verify@2.0.13(hardhat@2.24.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.12.1)(@types/node@20.19.1)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)))(bufferutil@4.0.9)(hardhat@2.24.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.12.1)(@types/node@20.19.1)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10))(@nomicfoundation/ignition-core@0.15.10(bufferutil@4.0.9)(utf-8-validate@5.0.10))(ethers@6.13.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.24.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.12.1)(@types/node@20.19.1)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) - '@nomicfoundation/hardhat-network-helpers': 1.0.12(hardhat@2.24.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.12.1)(@types/node@20.19.1)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) - '@nomicfoundation/hardhat-verify': 2.0.13(hardhat@2.24.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.12.1)(@types/node@20.19.1)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) - '@typechain/ethers-v6': 0.5.1(ethers@6.13.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typechain@8.3.2(typescript@5.8.3))(typescript@5.8.3) - '@typechain/hardhat': 9.1.0(@typechain/ethers-v6@0.5.1(ethers@6.13.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typechain@8.3.2(typescript@5.8.3))(typescript@5.8.3))(ethers@6.13.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.24.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.12.1)(@types/node@20.19.1)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10))(typechain@8.3.2(typescript@5.8.3)) - '@types/chai': 5.2.0 - '@types/mocha': 10.0.10 - '@types/node': 20.19.1 - chai: 5.2.0 - ethers: 6.13.4(bufferutil@4.0.9)(utf-8-validate@5.0.10) - hardhat: 2.24.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.12.1)(@types/node@20.19.1)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10) - hardhat-gas-reporter: 1.0.10(bufferutil@4.0.9)(hardhat@2.24.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.12.1)(@types/node@20.19.1)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10) - solidity-coverage: 0.8.14(hardhat@2.24.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.12.1)(@types/node@20.19.1)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) - ts-node: 10.9.2(@swc/core@1.12.1)(@types/node@20.19.1)(typescript@5.8.3) - typechain: 8.3.2(typescript@5.8.3) - typescript: 5.8.3 - - '@nomicfoundation/hardhat-toolbox@5.0.0(775720b1c6d0d796629832f440f70ca5)': + '@nomicfoundation/hardhat-toolbox@5.0.0(4a8c7a36d0534b6db66906aadca1ca67)': dependencies: '@nomicfoundation/hardhat-chai-matchers': 2.0.9(@nomicfoundation/hardhat-ethers@3.0.9(ethers@6.13.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.24.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.12.1)(@types/node@22.15.32)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)))(chai@5.2.0)(ethers@6.13.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.24.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.12.1)(@types/node@22.15.32)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) '@nomicfoundation/hardhat-ethers': 3.0.9(ethers@6.13.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.24.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.12.1)(@types/node@22.15.32)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) @@ -10705,7 +10739,7 @@ snapshots: '@nomicfoundation/hardhat-verify': 2.0.13(hardhat@2.24.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.12.1)(@types/node@22.15.32)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) '@typechain/ethers-v6': 0.5.1(ethers@6.13.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typechain@8.3.2(typescript@5.8.3))(typescript@5.8.3) '@typechain/hardhat': 9.1.0(@typechain/ethers-v6@0.5.1(ethers@6.13.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typechain@8.3.2(typescript@5.8.3))(typescript@5.8.3))(ethers@6.13.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.24.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.12.1)(@types/node@22.15.32)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10))(typechain@8.3.2(typescript@5.8.3)) - '@types/chai': 5.2.0 + '@types/chai': 5.2.2 '@types/mocha': 10.0.10 '@types/node': 22.15.32 chai: 5.2.0 @@ -10717,6 +10751,27 @@ snapshots: typechain: 8.3.2(typescript@5.8.3) typescript: 5.8.3 + '@nomicfoundation/hardhat-toolbox@5.0.0(d50884c5ccf68f1f6d25fc3e5da82825)': + dependencies: + '@nomicfoundation/hardhat-chai-matchers': 2.0.8(@nomicfoundation/hardhat-ethers@3.0.8(ethers@6.13.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.24.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.12.1)(@types/node@20.19.1)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)))(chai@5.2.0)(ethers@6.13.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.24.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.12.1)(@types/node@20.19.1)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) + '@nomicfoundation/hardhat-ethers': 3.0.8(ethers@6.13.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.24.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.12.1)(@types/node@20.19.1)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) + '@nomicfoundation/hardhat-ignition-ethers': 0.15.10(@nomicfoundation/hardhat-ethers@3.0.8(ethers@6.13.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.24.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.12.1)(@types/node@20.19.1)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)))(@nomicfoundation/hardhat-ignition@0.15.10(@nomicfoundation/hardhat-verify@2.0.13(hardhat@2.24.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.12.1)(@types/node@20.19.1)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)))(bufferutil@4.0.9)(hardhat@2.24.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.12.1)(@types/node@20.19.1)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10))(@nomicfoundation/ignition-core@0.15.10(bufferutil@4.0.9)(utf-8-validate@5.0.10))(ethers@6.13.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.24.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.12.1)(@types/node@20.19.1)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) + '@nomicfoundation/hardhat-network-helpers': 1.0.12(hardhat@2.24.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.12.1)(@types/node@20.19.1)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) + '@nomicfoundation/hardhat-verify': 2.0.13(hardhat@2.24.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.12.1)(@types/node@20.19.1)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) + '@typechain/ethers-v6': 0.5.1(ethers@6.13.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typechain@8.3.2(typescript@5.8.3))(typescript@5.8.3) + '@typechain/hardhat': 9.1.0(@typechain/ethers-v6@0.5.1(ethers@6.13.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(typechain@8.3.2(typescript@5.8.3))(typescript@5.8.3))(ethers@6.13.4(bufferutil@4.0.9)(utf-8-validate@5.0.10))(hardhat@2.24.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.12.1)(@types/node@20.19.1)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10))(typechain@8.3.2(typescript@5.8.3)) + '@types/chai': 5.2.2 + '@types/mocha': 10.0.10 + '@types/node': 20.19.1 + chai: 5.2.0 + ethers: 6.13.4(bufferutil@4.0.9)(utf-8-validate@5.0.10) + hardhat: 2.24.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.12.1)(@types/node@20.19.1)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10) + hardhat-gas-reporter: 1.0.10(bufferutil@4.0.9)(hardhat@2.24.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.12.1)(@types/node@20.19.1)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10))(utf-8-validate@5.0.10) + solidity-coverage: 0.8.14(hardhat@2.24.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.12.1)(@types/node@20.19.1)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10)) + ts-node: 10.9.2(@swc/core@1.12.1)(@types/node@20.19.1)(typescript@5.8.3) + typechain: 8.3.2(typescript@5.8.3) + typescript: 5.8.3 + '@nomicfoundation/hardhat-verify@2.0.13(hardhat@2.24.3(bufferutil@4.0.9)(ts-node@10.9.2(@swc/core@1.12.1)(@types/node@20.19.1)(typescript@5.8.3))(typescript@5.8.3)(utf-8-validate@5.0.10))': dependencies: '@ethersproject/abi': 5.8.0 @@ -12428,6 +12483,10 @@ snapshots: dependencies: '@types/deep-eql': 4.0.2 + '@types/chai@5.2.2': + dependencies: + '@types/deep-eql': 4.0.2 + '@types/concat-stream@1.6.1': dependencies: '@types/node': 20.19.1 @@ -12465,6 +12524,11 @@ snapshots: dependencies: '@types/istanbul-lib-report': 3.0.3 + '@types/jest@29.5.14': + dependencies: + expect: 29.7.0 + pretty-format: 29.7.0 + '@types/json-schema@7.0.15': {} '@types/json5@0.0.29': {} @@ -14122,6 +14186,21 @@ snapshots: safe-buffer: 5.2.1 sha.js: 2.4.11 + create-jest@29.7.0: + dependencies: + '@jest/types': 29.6.3 + chalk: 4.1.2 + exit: 0.1.2 + graceful-fs: 4.2.11 + jest-config: 29.7.0(@types/node@22.15.32)(ts-node@10.9.2(@swc/core@1.12.1)(@types/node@22.15.32)(typescript@5.8.3)) + jest-util: 29.7.0 + prompts: 2.4.2 + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + create-jest@29.7.0(@types/node@20.19.1)(ts-node@10.9.2(@swc/core@1.12.1)(@types/node@20.19.1)(typescript@5.8.3)): dependencies: '@jest/types': 29.6.3 @@ -16048,6 +16127,25 @@ snapshots: - babel-plugin-macros - supports-color + jest-cli@29.7.0: + dependencies: + '@jest/core': 29.7.0 + '@jest/test-result': 29.7.0 + '@jest/types': 29.6.3 + chalk: 4.1.2 + create-jest: 29.7.0 + exit: 0.1.2 + import-local: 3.2.0 + jest-config: 29.7.0(@types/node@22.15.32)(ts-node@10.9.2(@swc/core@1.12.1)(@types/node@22.15.32)(typescript@5.8.3)) + jest-util: 29.7.0 + jest-validate: 29.7.0 + yargs: 17.7.2 + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + jest-cli@29.7.0(@types/node@20.19.1)(ts-node@10.9.2(@swc/core@1.12.1)(@types/node@20.19.1)(typescript@5.8.3)): dependencies: '@jest/core': 29.7.0(ts-node@10.9.2(@swc/core@1.12.1)(@types/node@20.19.1)(typescript@5.8.3)) @@ -16239,7 +16337,7 @@ snapshots: jest-message-util@29.7.0: dependencies: - '@babel/code-frame': 7.26.2 + '@babel/code-frame': 7.27.1 '@jest/types': 29.6.3 '@types/stack-utils': 2.0.3 chalk: 4.1.2 @@ -16394,6 +16492,18 @@ snapshots: merge-stream: 2.0.0 supports-color: 8.1.1 + jest@29.7.0: + dependencies: + '@jest/core': 29.7.0 + '@jest/types': 29.6.3 + import-local: 3.2.0 + jest-cli: 29.7.0 + transitivePeerDependencies: + - '@types/node' + - babel-plugin-macros + - supports-color + - ts-node + jest@29.7.0(@types/node@20.19.1)(ts-node@10.9.2(@swc/core@1.12.1)(@types/node@20.19.1)(typescript@5.8.3)): dependencies: '@jest/core': 29.7.0(ts-node@10.9.2(@swc/core@1.12.1)(@types/node@20.19.1)(typescript@5.8.3)) @@ -18615,6 +18725,26 @@ snapshots: babel-jest: 29.7.0(@babel/core@7.27.4) jest-util: 29.7.0 + ts-jest@29.4.0(@babel/core@7.27.4)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.27.4))(jest-util@29.7.0)(jest@29.7.0)(typescript@5.8.3): + dependencies: + bs-logger: 0.2.6 + ejs: 3.1.10 + fast-json-stable-stringify: 2.1.0 + jest: 29.7.0 + json5: 2.2.3 + lodash.memoize: 4.1.2 + make-error: 1.3.6 + semver: 7.7.2 + type-fest: 4.41.0 + typescript: 5.8.3 + yargs-parser: 21.1.1 + optionalDependencies: + '@babel/core': 7.27.4 + '@jest/transform': 29.7.0 + '@jest/types': 29.6.3 + babel-jest: 29.7.0(@babel/core@7.27.4) + jest-util: 29.7.0 + ts-node@10.9.2(@swc/core@1.12.1)(@types/node@20.19.1)(typescript@5.8.3): dependencies: '@cspotcode/source-map-support': 0.8.1