diff --git a/.cspell.json b/.cspell.json index 1bc9243e54..731b362bbb 100644 --- a/.cspell.json +++ b/.cspell.json @@ -8,8 +8,8 @@ "ahadns", "Alives", "alphabeta", - "Arraylike", "arrayify", + "Arraylike", "asym", "autoshard", "autosharding", @@ -70,6 +70,7 @@ "libauth", "libp", "lightpush", + "LINEA", "livechat", "Merkle", "mkdir", diff --git a/.gitignore b/.gitignore index e9b7959725..55148342e1 100644 --- a/.gitignore +++ b/.gitignore @@ -12,4 +12,7 @@ docs test-results playwright-report example -packages/discovery/mock_local_storage \ No newline at end of file +packages/discovery/mock_local_storage +.cursorrules +.giga +.cursor \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 28a8e597fd..c6559abab1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -160,13 +160,13 @@ } }, "node_modules/@babel/generator": { - "version": "7.26.10", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.10.tgz", - "integrity": "sha512-rRHT8siFIXQrAYOYqZQVsAr8vJ+cBNqcVAY6m5V8/4QqzaPl+zDBe6cLEPRDuNOUf3ww8RfJVlOyQMoSI+5Ang==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.27.0.tgz", + "integrity": "sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw==", "license": "MIT", "dependencies": { - "@babel/parser": "^7.26.10", - "@babel/types": "^7.26.10", + "@babel/parser": "^7.27.0", + "@babel/types": "^7.27.0", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" @@ -198,12 +198,12 @@ } }, "node_modules/@babel/helper-compilation-targets": { - "version": "7.26.5", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.26.5.tgz", - "integrity": "sha512-IXuyn5EkouFJscIDuFF5EsiSolseme1s0CZB+QxVugqJLYmKdxI1VfIBOst0SUu4rnk2Z7kqTwmoO1lp3HIfnA==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.0.tgz", + "integrity": "sha512-LVk7fbXml0H2xH34dFzKQ7TDZ2G4/rVTOrq9V+icbbadjbVxxeFeDsNHv2SrZeWoA+6ZiTyWYWtScEIW07EAcA==", "license": "MIT", "dependencies": { - "@babel/compat-data": "^7.26.5", + "@babel/compat-data": "^7.26.8", "@babel/helper-validator-option": "^7.25.9", "browserslist": "^4.24.0", "lru-cache": "^5.1.1", @@ -238,9 +238,9 @@ "license": "ISC" }, "node_modules/@babel/helper-create-class-features-plugin": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.26.9.tgz", - "integrity": "sha512-ubbUqCofvxPRurw5L8WTsCLSkQiVpov4Qx0WMA+jUN+nXBK8ADPlJO1grkFw5CWKC5+sZSOfuGMdX1aI1iT9Sg==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.27.0.tgz", + "integrity": "sha512-vSGCvMecvFCd/BdpGlhpXYNhhC4ccxyvQWpbGL4CWbvfEoLFWUZuSuf7s9Aw70flgQF+6vptvgK2IfOnKlRmBg==", "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.25.9", @@ -248,7 +248,7 @@ "@babel/helper-optimise-call-expression": "^7.25.9", "@babel/helper-replace-supers": "^7.26.5", "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", - "@babel/traverse": "^7.26.9", + "@babel/traverse": "^7.27.0", "semver": "^6.3.1" }, "engines": { @@ -268,9 +268,9 @@ } }, "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.26.3.tgz", - "integrity": "sha512-G7ZRb40uUgdKOQqPLjfD12ZmGA54PzqDFUv2BKImnC9QIfGhIHKvVML0oN8IUiDq4iRqpq74ABpvOaerfWdong==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.27.0.tgz", + "integrity": "sha512-fO8l08T76v48BhpNRW/nQ0MxfnSdoSKUJBMjubOAYffsVuGG5qOfMq7N6Es7UJvi7Y8goXXo07EfcHZXDPuELQ==", "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.25.9", @@ -474,13 +474,13 @@ } }, "node_modules/@babel/helpers": { - "version": "7.26.10", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.10.tgz", - "integrity": "sha512-UPYc3SauzZ3JGgj87GgZ89JVdC5dj0AoetR5Bw6wj4niittNyFh6+eOGonYvJ1ao6B8lEa3Q3klS7ADZ53bc5g==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.27.0.tgz", + "integrity": "sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg==", "license": "MIT", "dependencies": { - "@babel/template": "^7.26.9", - "@babel/types": "^7.26.10" + "@babel/template": "^7.27.0", + "@babel/types": "^7.27.0" }, "engines": { "node": ">=6.9.0" @@ -581,12 +581,12 @@ } }, "node_modules/@babel/parser": { - "version": "7.26.10", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.10.tgz", - "integrity": "sha512-6aQR2zGE/QFi8JpDLjUZEPYOs7+mhKXm86VaKFiLP35JQwQb6bwUE+XbvkH0EptsYhbNBSUGaUBLKqxH1xSgsA==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.0.tgz", + "integrity": "sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg==", "license": "MIT", "dependencies": { - "@babel/types": "^7.26.10" + "@babel/types": "^7.27.0" }, "bin": { "parser": "bin/babel-parser.js" @@ -1157,12 +1157,12 @@ } }, "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.9.tgz", - "integrity": "sha512-1F05O7AYjymAtqbsFETboN1NvBdcnzMerO+zlMyJBEz6WkMdejvGWw9p05iTSjC85RLlBseHHQpYaM4gzJkBGg==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.27.0.tgz", + "integrity": "sha512-u1jGphZ8uDI2Pj/HJj6YQ6XQLZCNjOlprjxB5SVz6rq2T6SwAR+CdrWK0CP7F+9rDVMXdB0+r6Am5G5aobOjAQ==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-plugin-utils": "^7.26.5" }, "engines": { "node": ">=6.9.0" @@ -1850,12 +1850,12 @@ } }, "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.25.9.tgz", - "integrity": "sha512-vwDcDNsgMPDGP0nMqzahDWE5/MLcX8sv96+wfX7as7LoF/kr97Bo/7fI00lXY4wUXYfVmwIIyG80fGZ1uvt2qg==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.27.0.tgz", + "integrity": "sha512-LX/vCajUJQDqE7Aum/ELUMZAY19+cDpghxrnyt5I1tV6X5PyC86AOoWXWFYFeIvauyeSA6/ktn4tQVn/3ZifsA==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-plugin-utils": "^7.26.5", "regenerator-transform": "^0.15.2" }, "engines": { @@ -1989,9 +1989,9 @@ } }, "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.26.7", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.26.7.tgz", - "integrity": "sha512-jfoTXXZTgGg36BmhqT3cAYK5qkmqvJpvNrPhaK/52Vgjhw4Rq29s9UqpWWV0D6yuRmgiFH/BUVlkl96zJWqnaw==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.27.0.tgz", + "integrity": "sha512-+LLkxA9rKJpNoGsbLnAgOCdESl73vwYn+V6b+5wHbrE7OGKVDPHIQvbFSzqE6rwqaCw2RE+zdJrlLkcf8YOA0w==", "license": "MIT", "peer": true, "dependencies": { @@ -2005,13 +2005,13 @@ } }, "node_modules/@babel/plugin-transform-typescript": { - "version": "7.26.8", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.26.8.tgz", - "integrity": "sha512-bME5J9AC8ChwA7aEPJ6zym3w7aObZULHhbNLU0bKUhKsAkylkzUdq+0kdymh9rzi8nlNFl2bmldFBCKNJBUpuw==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.27.0.tgz", + "integrity": "sha512-fRGGjO2UEGPjvEcyAZXRXAS8AfdaQoq7HnxAbJoAoW10B9xOKesmmndJv+Sym2a+9FHWZ9KbyyLCe9s0Sn5jtg==", "license": "MIT", "dependencies": { "@babel/helper-annotate-as-pure": "^7.25.9", - "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-create-class-features-plugin": "^7.27.0", "@babel/helper-plugin-utils": "^7.26.5", "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", "@babel/plugin-syntax-typescript": "^7.25.9" @@ -2237,16 +2237,16 @@ } }, "node_modules/@babel/preset-typescript": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.26.0.tgz", - "integrity": "sha512-NMk1IGZ5I/oHhoXEElcm+xUnL/szL6xflkFZmoEU9xj1qSJXpiS7rsspYo92B4DRCDvZn2erT5LdsCeXAKNCkg==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.27.0.tgz", + "integrity": "sha512-vxaPFfJtHhgeOVXRKuHpHPAOgymmy8V8I65T1q53R7GCZlefKeCaTyDs3zOPHTTbmquvNlQYC5klEvWsBAtrBQ==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-plugin-utils": "^7.26.5", "@babel/helper-validator-option": "^7.25.9", "@babel/plugin-syntax-jsx": "^7.25.9", - "@babel/plugin-transform-modules-commonjs": "^7.25.9", - "@babel/plugin-transform-typescript": "^7.25.9" + "@babel/plugin-transform-modules-commonjs": "^7.26.3", + "@babel/plugin-transform-typescript": "^7.27.0" }, "engines": { "node": ">=6.9.0" @@ -2393,9 +2393,9 @@ } }, "node_modules/@babel/runtime": { - "version": "7.26.10", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.10.tgz", - "integrity": "sha512-2WJMeRQPHKSPemqk/awGrAiuFfzBmOIPXKizAsVhWH9YJqLZ0H+HS4c8loHGgW6utJ3E/ejXQUsiGaQy2NZ9Fw==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.0.tgz", + "integrity": "sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw==", "license": "MIT", "dependencies": { "regenerator-runtime": "^0.14.0" @@ -2405,30 +2405,30 @@ } }, "node_modules/@babel/template": { - "version": "7.26.9", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.26.9.tgz", - "integrity": "sha512-qyRplbeIpNZhmzOysF/wFMuP9sctmh2cFzRAZOn1YapxBsE1i9bJIY586R/WBLfLcmcBlM8ROBiQURnnNy+zfA==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.0.tgz", + "integrity": "sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA==", "license": "MIT", "dependencies": { "@babel/code-frame": "^7.26.2", - "@babel/parser": "^7.26.9", - "@babel/types": "^7.26.9" + "@babel/parser": "^7.27.0", + "@babel/types": "^7.27.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { - "version": "7.26.10", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.10.tgz", - "integrity": "sha512-k8NuDrxr0WrPH5Aupqb2LCVURP/S0vBEn5mK6iH+GIYob66U5EtoZvcdudR2jQ4cmTwhEwW1DLB+Yyas9zjF6A==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.27.0.tgz", + "integrity": "sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA==", "license": "MIT", "dependencies": { "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.26.10", - "@babel/parser": "^7.26.10", - "@babel/template": "^7.26.9", - "@babel/types": "^7.26.10", + "@babel/generator": "^7.27.0", + "@babel/parser": "^7.27.0", + "@babel/template": "^7.27.0", + "@babel/types": "^7.27.0", "debug": "^4.3.1", "globals": "^11.1.0" }, @@ -2446,9 +2446,9 @@ } }, "node_modules/@babel/types": { - "version": "7.26.10", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.10.tgz", - "integrity": "sha512-emqcG3vHrpxUKTrxcblR36dcrcoRDvKmnL/dCL6ZsHaShW80qxCAcNhzQZrpeM765VzEos+xOi4s+r4IXzTwdQ==", + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.0.tgz", + "integrity": "sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg==", "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.25.9", @@ -2485,91 +2485,6 @@ "integrity": "sha512-HJ8GZBRjLeWtRsAXf3EbNsNzmTGpzTFjfpSf4yHkLYC+E52DhT6hwz+7qpj6I/EmFzSUm5tYYvT9K8GZokLQCQ==", "license": "Apache-2.0" }, - "node_modules/@chainsafe/bls-keystore": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@chainsafe/bls-keystore/-/bls-keystore-3.0.0.tgz", - "integrity": "sha512-vlRIIXnn555wq2emhqnSR7btno17M0sCcfdQ+Dhgr7IH6n0CMoTGw9qcrpnNYwM+9OPm3matSYeZc9mNlXf7fQ==", - "license": "MIT", - "dependencies": { - "ethereum-cryptography": "^1.0.0", - "uuid": "8.3.2" - } - }, - "node_modules/@chainsafe/bls-keystore/node_modules/@noble/hashes": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.2.0.tgz", - "integrity": "sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "license": "MIT" - }, - "node_modules/@chainsafe/bls-keystore/node_modules/@scure/base": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.9.tgz", - "integrity": "sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==", - "license": "MIT", - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@chainsafe/bls-keystore/node_modules/@scure/bip32": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.1.5.tgz", - "integrity": "sha512-XyNh1rB0SkEqd3tXcXMi+Xe1fvg+kUIcoRIEujP1Jgv7DqW2r9lg3Ah0NkFaCs9sTkQAQA8kw7xiRXzENi9Rtw==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "license": "MIT", - "dependencies": { - "@noble/hashes": "~1.2.0", - "@noble/secp256k1": "~1.7.0", - "@scure/base": "~1.1.0" - } - }, - "node_modules/@chainsafe/bls-keystore/node_modules/@scure/bip39": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.1.1.tgz", - "integrity": "sha512-t+wDck2rVkh65Hmv280fYdVdY25J9YeEUIgn2LG1WM6gxFkGzcksoDiUkWVpVp3Oex9xGC68JU2dSbUfwZ2jPg==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "license": "MIT", - "dependencies": { - "@noble/hashes": "~1.2.0", - "@scure/base": "~1.1.0" - } - }, - "node_modules/@chainsafe/bls-keystore/node_modules/ethereum-cryptography": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/ethereum-cryptography/-/ethereum-cryptography-1.2.0.tgz", - "integrity": "sha512-6yFQC9b5ug6/17CQpCyE3k9eKBMdhyVjzUy1WkiuY/E4vj/SXDBbCw8QEIaXqf0Mf2SnY6RmpDcwlUmBSS0EJw==", - "license": "MIT", - "dependencies": { - "@noble/hashes": "1.2.0", - "@noble/secp256k1": "1.7.1", - "@scure/bip32": "1.1.5", - "@scure/bip39": "1.1.1" - } - }, - "node_modules/@chainsafe/bls-keystore/node_modules/uuid": { - "version": "8.3.2", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", - "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", - "license": "MIT", - "bin": { - "uuid": "dist/bin/uuid" - } - }, "node_modules/@chainsafe/is-ip": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/@chainsafe/is-ip/-/is-ip-2.1.0.tgz", @@ -3743,9 +3658,9 @@ } }, "node_modules/@ethersproject/abi": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.8.0.tgz", - "integrity": "sha512-b9YS/43ObplgyV6SlyQsG53/vkSal0MNA1fskSC4mbnCMi8R+NkcH8K9FPYNESf6jUefBUniE4SOKms0E/KK1Q==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.7.0.tgz", + "integrity": "sha512-351ktp42TiRcYB3H1OP8yajPeAQstMW/yCFokj/AthP9bLHzQFPlOrxOcwYEDkUAICmOHljvN4K39OMTMUa9RA==", "funding": [ { "type": "individual", @@ -3758,21 +3673,21 @@ ], "license": "MIT", "dependencies": { - "@ethersproject/address": "^5.8.0", - "@ethersproject/bignumber": "^5.8.0", - "@ethersproject/bytes": "^5.8.0", - "@ethersproject/constants": "^5.8.0", - "@ethersproject/hash": "^5.8.0", - "@ethersproject/keccak256": "^5.8.0", - "@ethersproject/logger": "^5.8.0", - "@ethersproject/properties": "^5.8.0", - "@ethersproject/strings": "^5.8.0" + "@ethersproject/address": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/hash": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/strings": "^5.7.0" } }, "node_modules/@ethersproject/abstract-provider": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.8.0.tgz", - "integrity": "sha512-wC9SFcmh4UK0oKuLJQItoQdzS/qZ51EJegK6EmAWlh+OptpQ/npECOR3QqECd8iGHC0RJb4WKbVdSfif4ammrg==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-provider/-/abstract-provider-5.7.0.tgz", + "integrity": "sha512-R41c9UkchKCpAqStMYUpdunjo3pkEvZC3FAwZn5S5MGbXoMQOHIdHItezTETxAO5bevtMApSyEhn9+CHcDsWBw==", "funding": [ { "type": "individual", @@ -3785,19 +3700,19 @@ ], "license": "MIT", "dependencies": { - "@ethersproject/bignumber": "^5.8.0", - "@ethersproject/bytes": "^5.8.0", - "@ethersproject/logger": "^5.8.0", - "@ethersproject/networks": "^5.8.0", - "@ethersproject/properties": "^5.8.0", - "@ethersproject/transactions": "^5.8.0", - "@ethersproject/web": "^5.8.0" + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/networks": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/transactions": "^5.7.0", + "@ethersproject/web": "^5.7.0" } }, "node_modules/@ethersproject/abstract-signer": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.8.0.tgz", - "integrity": "sha512-N0XhZTswXcmIZQdYtUnd79VJzvEwXQw6PK0dTl9VoYrEBxxCPXqS0Eod7q5TNKRxe1/5WUMuR0u0nqTF/avdCA==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/abstract-signer/-/abstract-signer-5.7.0.tgz", + "integrity": "sha512-a16V8bq1/Cz+TGCkE2OPMTOUDLS3grCpdjoJCYNnVBbdYEMSgKrU0+B90s8b6H+ByYTBZN7a3g76jdIJi7UfKQ==", "funding": [ { "type": "individual", @@ -3810,17 +3725,17 @@ ], "license": "MIT", "dependencies": { - "@ethersproject/abstract-provider": "^5.8.0", - "@ethersproject/bignumber": "^5.8.0", - "@ethersproject/bytes": "^5.8.0", - "@ethersproject/logger": "^5.8.0", - "@ethersproject/properties": "^5.8.0" + "@ethersproject/abstract-provider": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0" } }, "node_modules/@ethersproject/address": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.8.0.tgz", - "integrity": "sha512-GhH/abcC46LJwshoN+uBNoKVFPxUuZm6dA257z0vZkKmU1+t8xTn8oK7B9qrj8W2rFRMch4gbJl6PmVxjxBEBA==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/address/-/address-5.7.0.tgz", + "integrity": "sha512-9wYhYt7aghVGo758POM5nqcOMaE168Q6aRLJZwUmiqSrAungkG74gSSeKEIR7ukixesdRZGPgVqme6vmxs1fkA==", "funding": [ { "type": "individual", @@ -3833,17 +3748,17 @@ ], "license": "MIT", "dependencies": { - "@ethersproject/bignumber": "^5.8.0", - "@ethersproject/bytes": "^5.8.0", - "@ethersproject/keccak256": "^5.8.0", - "@ethersproject/logger": "^5.8.0", - "@ethersproject/rlp": "^5.8.0" + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/rlp": "^5.7.0" } }, "node_modules/@ethersproject/base64": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.8.0.tgz", - "integrity": "sha512-lN0oIwfkYj9LbPx4xEkie6rAMJtySbpOAFXSDVQaBnAzYfB4X2Qr+FXJGxMoc3Bxp2Sm8OwvzMrywxyw0gLjIQ==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/base64/-/base64-5.7.0.tgz", + "integrity": "sha512-Dr8tcHt2mEbsZr/mwTPIQAf3Ai0Bks/7gTw9dSqk1mQvhW3XvRlmDJr/4n+wg1JmCl16NZue17CDh8xb/vZ0sQ==", "funding": [ { "type": "individual", @@ -3856,13 +3771,13 @@ ], "license": "MIT", "dependencies": { - "@ethersproject/bytes": "^5.8.0" + "@ethersproject/bytes": "^5.7.0" } }, "node_modules/@ethersproject/basex": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.8.0.tgz", - "integrity": "sha512-PIgTszMlDRmNwW9nhS6iqtVfdTAKosA7llYXNmGPw4YAI1PUyMv28988wAb41/gHF/WqGdoLv0erHaRcHRKW2Q==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/basex/-/basex-5.7.0.tgz", + "integrity": "sha512-ywlh43GwZLv2Voc2gQVTKBoVQ1mti3d8HK5aMxsfu/nRDnMmNqaSJ3r3n85HBByT8OpoY96SXM1FogC533T4zw==", "funding": [ { "type": "individual", @@ -3875,14 +3790,14 @@ ], "license": "MIT", "dependencies": { - "@ethersproject/bytes": "^5.8.0", - "@ethersproject/properties": "^5.8.0" + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/properties": "^5.7.0" } }, "node_modules/@ethersproject/bignumber": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.8.0.tgz", - "integrity": "sha512-ZyaT24bHaSeJon2tGPKIiHszWjD/54Sz8t57Toch475lCLljC6MgPmxk7Gtzz+ddNN5LuHea9qhAe0x3D+uYPA==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/bignumber/-/bignumber-5.7.0.tgz", + "integrity": "sha512-n1CAdIHRWjSucQO3MC1zPSVgV/6dy/fjL9pMrPP9peL+QxEg9wOsVqwD4+818B6LUEtaXzVHQiuivzRoxPxUGw==", "funding": [ { "type": "individual", @@ -3895,8 +3810,8 @@ ], "license": "MIT", "dependencies": { - "@ethersproject/bytes": "^5.8.0", - "@ethersproject/logger": "^5.8.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", "bn.js": "^5.2.1" } }, @@ -3920,9 +3835,9 @@ } }, "node_modules/@ethersproject/constants": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.8.0.tgz", - "integrity": "sha512-wigX4lrf5Vu+axVTIvNsuL6YrV4O5AXl5ubcURKMEME5TnWBouUh0CDTWxZ2GpnRn1kcCgE7l8O5+VbV9QTTcg==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/constants/-/constants-5.7.0.tgz", + "integrity": "sha512-DHI+y5dBNvkpYUMiRQyxRBYBefZkJfo70VUkUAsRjcPs47muV9evftfZ0PJVCXYbAiCgght0DtcF9srFQmIgWA==", "funding": [ { "type": "individual", @@ -3935,13 +3850,13 @@ ], "license": "MIT", "dependencies": { - "@ethersproject/bignumber": "^5.8.0" + "@ethersproject/bignumber": "^5.7.0" } }, "node_modules/@ethersproject/contracts": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.8.0.tgz", - "integrity": "sha512-0eFjGz9GtuAi6MZwhb4uvUM216F38xiuR0yYCjKJpNfSEy4HUM8hvqqBj9Jmm0IUz8l0xKEhWwLIhPgxNY0yvQ==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.7.0.tgz", + "integrity": "sha512-5GJbzEU3X+d33CdfPhcyS+z8MzsTrBGk/sc+G+59+tPa9yFkl6HQ9D6L0QMgNTA9q8dT0XKxxkyp883XsQvbbg==", "funding": [ { "type": "individual", @@ -3954,22 +3869,22 @@ ], "license": "MIT", "dependencies": { - "@ethersproject/abi": "^5.8.0", - "@ethersproject/abstract-provider": "^5.8.0", - "@ethersproject/abstract-signer": "^5.8.0", - "@ethersproject/address": "^5.8.0", - "@ethersproject/bignumber": "^5.8.0", - "@ethersproject/bytes": "^5.8.0", - "@ethersproject/constants": "^5.8.0", - "@ethersproject/logger": "^5.8.0", - "@ethersproject/properties": "^5.8.0", - "@ethersproject/transactions": "^5.8.0" + "@ethersproject/abi": "^5.7.0", + "@ethersproject/abstract-provider": "^5.7.0", + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/address": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/transactions": "^5.7.0" } }, "node_modules/@ethersproject/hash": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.8.0.tgz", - "integrity": "sha512-ac/lBcTbEWW/VGJij0CNSw/wPcw9bSRgCB0AIBz8CvED/jfvDoV9hsIIiWfvWmFEi8RcXtlNwp2jv6ozWOsooA==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/hash/-/hash-5.7.0.tgz", + "integrity": "sha512-qX5WrQfnah1EFnO5zJv1v46a8HW0+E5xuBBDTwMFZLuVTx0tbU2kkx15NqdjxecrLGatQN9FGQKpb1FKdHCt+g==", "funding": [ { "type": "individual", @@ -3982,21 +3897,21 @@ ], "license": "MIT", "dependencies": { - "@ethersproject/abstract-signer": "^5.8.0", - "@ethersproject/address": "^5.8.0", - "@ethersproject/base64": "^5.8.0", - "@ethersproject/bignumber": "^5.8.0", - "@ethersproject/bytes": "^5.8.0", - "@ethersproject/keccak256": "^5.8.0", - "@ethersproject/logger": "^5.8.0", - "@ethersproject/properties": "^5.8.0", - "@ethersproject/strings": "^5.8.0" + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/address": "^5.7.0", + "@ethersproject/base64": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/strings": "^5.7.0" } }, "node_modules/@ethersproject/hdnode": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.8.0.tgz", - "integrity": "sha512-4bK1VF6E83/3/Im0ERnnUeWOY3P1BZml4ZD3wcH8Ys0/d1h1xaFt6Zc+Dh9zXf9TapGro0T4wvO71UTCp3/uoA==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/hdnode/-/hdnode-5.7.0.tgz", + "integrity": "sha512-OmyYo9EENBPPf4ERhR7oj6uAtUAhYGqOnIS+jE5pTXvdKBS99ikzq1E7Iv0ZQZ5V36Lqx1qZLeak0Ra16qpeOg==", "funding": [ { "type": "individual", @@ -4009,24 +3924,24 @@ ], "license": "MIT", "dependencies": { - "@ethersproject/abstract-signer": "^5.8.0", - "@ethersproject/basex": "^5.8.0", - "@ethersproject/bignumber": "^5.8.0", - "@ethersproject/bytes": "^5.8.0", - "@ethersproject/logger": "^5.8.0", - "@ethersproject/pbkdf2": "^5.8.0", - "@ethersproject/properties": "^5.8.0", - "@ethersproject/sha2": "^5.8.0", - "@ethersproject/signing-key": "^5.8.0", - "@ethersproject/strings": "^5.8.0", - "@ethersproject/transactions": "^5.8.0", - "@ethersproject/wordlists": "^5.8.0" + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/basex": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/pbkdf2": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/sha2": "^5.7.0", + "@ethersproject/signing-key": "^5.7.0", + "@ethersproject/strings": "^5.7.0", + "@ethersproject/transactions": "^5.7.0", + "@ethersproject/wordlists": "^5.7.0" } }, "node_modules/@ethersproject/json-wallets": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.8.0.tgz", - "integrity": "sha512-HxblNck8FVUtNxS3VTEYJAcwiKYsBIF77W15HufqlBF9gGfhmYOJtYZp8fSDZtn9y5EaXTE87zDwzxRoTFk11w==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/json-wallets/-/json-wallets-5.7.0.tgz", + "integrity": "sha512-8oee5Xgu6+RKgJTkvEMl2wDgSPSAQ9MB/3JYjFV9jlKvcYHUXZC+cQp0njgmxdHkYWn8s6/IqIZYm0YWCjO/0g==", "funding": [ { "type": "individual", @@ -4039,25 +3954,25 @@ ], "license": "MIT", "dependencies": { - "@ethersproject/abstract-signer": "^5.8.0", - "@ethersproject/address": "^5.8.0", - "@ethersproject/bytes": "^5.8.0", - "@ethersproject/hdnode": "^5.8.0", - "@ethersproject/keccak256": "^5.8.0", - "@ethersproject/logger": "^5.8.0", - "@ethersproject/pbkdf2": "^5.8.0", - "@ethersproject/properties": "^5.8.0", - "@ethersproject/random": "^5.8.0", - "@ethersproject/strings": "^5.8.0", - "@ethersproject/transactions": "^5.8.0", + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/address": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/hdnode": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/pbkdf2": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/random": "^5.7.0", + "@ethersproject/strings": "^5.7.0", + "@ethersproject/transactions": "^5.7.0", "aes-js": "3.0.0", "scrypt-js": "3.0.1" } }, "node_modules/@ethersproject/keccak256": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.8.0.tgz", - "integrity": "sha512-A1pkKLZSz8pDaQ1ftutZoaN46I6+jvuqugx5KYNeQOPqq+JZ0Txm7dlWesCHB5cndJSu5vP2VKptKf7cksERng==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/keccak256/-/keccak256-5.7.0.tgz", + "integrity": "sha512-2UcPboeL/iW+pSg6vZ6ydF8tCnv3Iu/8tUmLLzWWGzxWKFFqOBQFLo6uLUv6BDrLgCDfN28RJ/wtByx+jZ4KBg==", "funding": [ { "type": "individual", @@ -4070,10 +3985,16 @@ ], "license": "MIT", "dependencies": { - "@ethersproject/bytes": "^5.8.0", + "@ethersproject/bytes": "^5.7.0", "js-sha3": "0.8.0" } }, + "node_modules/@ethersproject/keccak256/node_modules/js-sha3": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", + "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==", + "license": "MIT" + }, "node_modules/@ethersproject/logger": { "version": "5.8.0", "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.8.0.tgz", @@ -4091,9 +4012,9 @@ "license": "MIT" }, "node_modules/@ethersproject/networks": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.8.0.tgz", - "integrity": "sha512-egPJh3aPVAzbHwq8DD7Po53J4OUSsA1MjQp8Vf/OZPav5rlmWUaFLiq8cvQiGK0Z5K6LYzm29+VA/p4RL1FzNg==", + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/@ethersproject/networks/-/networks-5.7.1.tgz", + "integrity": "sha512-n/MufjFYv3yFcUyfhnXotyDlNdFb7onmkSy8aQERi2PjNcnWQ66xXxa3XlS8nCcA8aJKJjIIMNJTC7tu80GwpQ==", "funding": [ { "type": "individual", @@ -4106,13 +4027,13 @@ ], "license": "MIT", "dependencies": { - "@ethersproject/logger": "^5.8.0" + "@ethersproject/logger": "^5.7.0" } }, "node_modules/@ethersproject/pbkdf2": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.8.0.tgz", - "integrity": "sha512-wuHiv97BrzCmfEaPbUFpMjlVg/IDkZThp9Ri88BpjRleg4iePJaj2SW8AIyE8cXn5V1tuAaMj6lzvsGJkGWskg==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/pbkdf2/-/pbkdf2-5.7.0.tgz", + "integrity": "sha512-oR/dBRZR6GTyaofd86DehG72hY6NpAjhabkhxgr3X2FpJtJuodEl2auADWBZfhDHgVCbu3/H/Ocq2uC6dpNjjw==", "funding": [ { "type": "individual", @@ -4125,14 +4046,14 @@ ], "license": "MIT", "dependencies": { - "@ethersproject/bytes": "^5.8.0", - "@ethersproject/sha2": "^5.8.0" + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/sha2": "^5.7.0" } }, "node_modules/@ethersproject/properties": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.8.0.tgz", - "integrity": "sha512-PYuiEoQ+FMaZZNGrStmN7+lWjlsoufGIHdww7454FIaGdbe/p5rnaCXTr5MtBYl3NkeoVhHZuyzChPeGeKIpQw==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/properties/-/properties-5.7.0.tgz", + "integrity": "sha512-J87jy8suntrAkIZtecpxEPxY//szqr1mlBaYlQ0r4RCaiD2hjheqF9s1LVE8vVuJCXisjIP+JgtK/Do54ej4Sw==", "funding": [ { "type": "individual", @@ -4145,13 +4066,13 @@ ], "license": "MIT", "dependencies": { - "@ethersproject/logger": "^5.8.0" + "@ethersproject/logger": "^5.7.0" } }, "node_modules/@ethersproject/providers": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.8.0.tgz", - "integrity": "sha512-3Il3oTzEx3o6kzcg9ZzbE+oCZYyY+3Zh83sKkn4s1DZfTUjIegHnN2Cm0kbn9YFy45FDVcuCLLONhU7ny0SsCw==", + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/@ethersproject/providers/-/providers-5.7.2.tgz", + "integrity": "sha512-g34EWZ1WWAVgr4aptGlVBF8mhl3VWjv+8hoAnzStu8Ah22VHBsuGzP17eb6xDVRzw895G4W7vvx60lFFur/1Rg==", "funding": [ { "type": "individual", @@ -4164,39 +4085,39 @@ ], "license": "MIT", "dependencies": { - "@ethersproject/abstract-provider": "^5.8.0", - "@ethersproject/abstract-signer": "^5.8.0", - "@ethersproject/address": "^5.8.0", - "@ethersproject/base64": "^5.8.0", - "@ethersproject/basex": "^5.8.0", - "@ethersproject/bignumber": "^5.8.0", - "@ethersproject/bytes": "^5.8.0", - "@ethersproject/constants": "^5.8.0", - "@ethersproject/hash": "^5.8.0", - "@ethersproject/logger": "^5.8.0", - "@ethersproject/networks": "^5.8.0", - "@ethersproject/properties": "^5.8.0", - "@ethersproject/random": "^5.8.0", - "@ethersproject/rlp": "^5.8.0", - "@ethersproject/sha2": "^5.8.0", - "@ethersproject/strings": "^5.8.0", - "@ethersproject/transactions": "^5.8.0", - "@ethersproject/web": "^5.8.0", + "@ethersproject/abstract-provider": "^5.7.0", + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/address": "^5.7.0", + "@ethersproject/base64": "^5.7.0", + "@ethersproject/basex": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/hash": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/networks": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/random": "^5.7.0", + "@ethersproject/rlp": "^5.7.0", + "@ethersproject/sha2": "^5.7.0", + "@ethersproject/strings": "^5.7.0", + "@ethersproject/transactions": "^5.7.0", + "@ethersproject/web": "^5.7.0", "bech32": "1.1.4", - "ws": "8.18.0" + "ws": "7.4.6" } }, "node_modules/@ethersproject/providers/node_modules/ws": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz", - "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==", + "version": "7.4.6", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.4.6.tgz", + "integrity": "sha512-YmhHDO4MzaDLB+M9ym/mDA5z0naX8j7SIlT8f8z+I0VtzsRbekxEutHSme7NPS2qE8StCYQNUnfWdXta/Yu85A==", "license": "MIT", "engines": { - "node": ">=10.0.0" + "node": ">=8.3.0" }, "peerDependencies": { "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" + "utf-8-validate": "^5.0.2" }, "peerDependenciesMeta": { "bufferutil": { @@ -4208,9 +4129,9 @@ } }, "node_modules/@ethersproject/random": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/@ethersproject/random/-/random-5.8.0.tgz", - "integrity": "sha512-E4I5TDl7SVqyg4/kkA/qTfuLWAQGXmSOgYyO01So8hLfwgKvYK5snIlzxJMk72IFdG/7oh8yuSqY2KX7MMwg+A==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/random/-/random-5.7.0.tgz", + "integrity": "sha512-19WjScqRA8IIeWclFme75VMXSBvi4e6InrUNuaR4s5pTF2qNhcGdCUwdxUVGtDDqC00sDLCO93jPQoDUH4HVmQ==", "funding": [ { "type": "individual", @@ -4223,8 +4144,8 @@ ], "license": "MIT", "dependencies": { - "@ethersproject/bytes": "^5.8.0", - "@ethersproject/logger": "^5.8.0" + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0" } }, "node_modules/@ethersproject/rlp": { @@ -4248,9 +4169,9 @@ } }, "node_modules/@ethersproject/sha2": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.8.0.tgz", - "integrity": "sha512-dDOUrXr9wF/YFltgTBYS0tKslPEKr6AekjqDW2dbn1L1xmjGR+9GiKu4ajxovnrDbwxAKdHjW8jNcwfz8PAz4A==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/sha2/-/sha2-5.7.0.tgz", + "integrity": "sha512-gKlH42riwb3KYp0reLsFTokByAKoJdgFCwI+CCiX/k+Jm2mbNs6oOaCjYQSlI1+XBVejwH2KrmCbMAT/GnRDQw==", "funding": [ { "type": "individual", @@ -4263,15 +4184,15 @@ ], "license": "MIT", "dependencies": { - "@ethersproject/bytes": "^5.8.0", - "@ethersproject/logger": "^5.8.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", "hash.js": "1.1.7" } }, "node_modules/@ethersproject/signing-key": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.8.0.tgz", - "integrity": "sha512-LrPW2ZxoigFi6U6aVkFN/fa9Yx/+4AtIUe4/HACTvKJdhm0eeb107EVCIQcrLZkxaSIgc/eCrX8Q1GtbH+9n3w==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/signing-key/-/signing-key-5.7.0.tgz", + "integrity": "sha512-MZdy2nL3wO0u7gkB4nA/pEf8lu1TlFswPNmy8AiYkfKTdO6eXBJyUdmHO/ehm/htHw9K/qF8ujnTyUAD+Ry54Q==", "funding": [ { "type": "individual", @@ -4284,18 +4205,18 @@ ], "license": "MIT", "dependencies": { - "@ethersproject/bytes": "^5.8.0", - "@ethersproject/logger": "^5.8.0", - "@ethersproject/properties": "^5.8.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", "bn.js": "^5.2.1", - "elliptic": "6.6.1", + "elliptic": "6.5.4", "hash.js": "1.1.7" } }, "node_modules/@ethersproject/solidity": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.8.0.tgz", - "integrity": "sha512-4CxFeCgmIWamOHwYN9d+QWGxye9qQLilpgTU0XhYs1OahkclF+ewO+3V1U0mvpiuQxm5EHHmv8f7ClVII8EHsA==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/solidity/-/solidity-5.7.0.tgz", + "integrity": "sha512-HmabMd2Dt/raavyaGukF4XxizWKhKQ24DoLtdNbBmNKUOPqwjsKQSdV9GQtj9CBEea9DlzETlVER1gYeXXBGaA==", "funding": [ { "type": "individual", @@ -4308,18 +4229,18 @@ ], "license": "MIT", "dependencies": { - "@ethersproject/bignumber": "^5.8.0", - "@ethersproject/bytes": "^5.8.0", - "@ethersproject/keccak256": "^5.8.0", - "@ethersproject/logger": "^5.8.0", - "@ethersproject/sha2": "^5.8.0", - "@ethersproject/strings": "^5.8.0" + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/sha2": "^5.7.0", + "@ethersproject/strings": "^5.7.0" } }, "node_modules/@ethersproject/strings": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.8.0.tgz", - "integrity": "sha512-qWEAk0MAvl0LszjdfnZ2uC8xbR2wdv4cDabyHiBh3Cldq/T8dPH3V4BbBsAYJUeonwD+8afVXld274Ls+Y1xXg==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/strings/-/strings-5.7.0.tgz", + "integrity": "sha512-/9nu+lj0YswRNSH0NXYqrh8775XNyEdUQAuf3f+SmOrnVewcJ5SBNAjF7lpgehKi4abvNNXyf+HX86czCdJ8Mg==", "funding": [ { "type": "individual", @@ -4332,15 +4253,15 @@ ], "license": "MIT", "dependencies": { - "@ethersproject/bytes": "^5.8.0", - "@ethersproject/constants": "^5.8.0", - "@ethersproject/logger": "^5.8.0" + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/logger": "^5.7.0" } }, "node_modules/@ethersproject/transactions": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.8.0.tgz", - "integrity": "sha512-UglxSDjByHG0TuU17bDfCemZ3AnKO2vYrL5/2n2oXvKzvb7Cz+W9gOWXKARjp2URVwcWlQlPOEQyAviKwT4AHg==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/transactions/-/transactions-5.7.0.tgz", + "integrity": "sha512-kmcNicCp1lp8qanMTC3RIikGgoJ80ztTyvtsFvCYpSCfkjhD0jZ2LOrnbcuxuToLIUYYf+4XwD1rP+B/erDIhQ==", "funding": [ { "type": "individual", @@ -4353,21 +4274,21 @@ ], "license": "MIT", "dependencies": { - "@ethersproject/address": "^5.8.0", - "@ethersproject/bignumber": "^5.8.0", - "@ethersproject/bytes": "^5.8.0", - "@ethersproject/constants": "^5.8.0", - "@ethersproject/keccak256": "^5.8.0", - "@ethersproject/logger": "^5.8.0", - "@ethersproject/properties": "^5.8.0", - "@ethersproject/rlp": "^5.8.0", - "@ethersproject/signing-key": "^5.8.0" + "@ethersproject/address": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/rlp": "^5.7.0", + "@ethersproject/signing-key": "^5.7.0" } }, "node_modules/@ethersproject/units": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.8.0.tgz", - "integrity": "sha512-lxq0CAnc5kMGIiWW4Mr041VT8IhNM+Pn5T3haO74XZWFulk7wH1Gv64HqE96hT4a7iiNMdOCFEBgaxWuk8ETKQ==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.7.0.tgz", + "integrity": "sha512-pD3xLMy3SJu9kG5xDGI7+xhTEmGXlEqXU4OfNapmfnxLVY4EMSSRp7j1k7eezutBPH7RBN/7QPnwR7hzNlEFeg==", "funding": [ { "type": "individual", @@ -4380,15 +4301,15 @@ ], "license": "MIT", "dependencies": { - "@ethersproject/bignumber": "^5.8.0", - "@ethersproject/constants": "^5.8.0", - "@ethersproject/logger": "^5.8.0" + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/constants": "^5.7.0", + "@ethersproject/logger": "^5.7.0" } }, "node_modules/@ethersproject/wallet": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.8.0.tgz", - "integrity": "sha512-G+jnzmgg6UxurVKRKvw27h0kvG75YKXZKdlLYmAHeF32TGUzHkOFd7Zn6QHOTYRFWnfjtSSFjBowKo7vfrXzPA==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/wallet/-/wallet-5.7.0.tgz", + "integrity": "sha512-MhmXlJXEJFBFVKrDLB4ZdDzxcBxQ3rLyCkhNqVu3CDYvR97E+8r01UgrI+TI99Le+aYm/in/0vp86guJuM7FCA==", "funding": [ { "type": "individual", @@ -4401,27 +4322,27 @@ ], "license": "MIT", "dependencies": { - "@ethersproject/abstract-provider": "^5.8.0", - "@ethersproject/abstract-signer": "^5.8.0", - "@ethersproject/address": "^5.8.0", - "@ethersproject/bignumber": "^5.8.0", - "@ethersproject/bytes": "^5.8.0", - "@ethersproject/hash": "^5.8.0", - "@ethersproject/hdnode": "^5.8.0", - "@ethersproject/json-wallets": "^5.8.0", - "@ethersproject/keccak256": "^5.8.0", - "@ethersproject/logger": "^5.8.0", - "@ethersproject/properties": "^5.8.0", - "@ethersproject/random": "^5.8.0", - "@ethersproject/signing-key": "^5.8.0", - "@ethersproject/transactions": "^5.8.0", - "@ethersproject/wordlists": "^5.8.0" + "@ethersproject/abstract-provider": "^5.7.0", + "@ethersproject/abstract-signer": "^5.7.0", + "@ethersproject/address": "^5.7.0", + "@ethersproject/bignumber": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/hash": "^5.7.0", + "@ethersproject/hdnode": "^5.7.0", + "@ethersproject/json-wallets": "^5.7.0", + "@ethersproject/keccak256": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/random": "^5.7.0", + "@ethersproject/signing-key": "^5.7.0", + "@ethersproject/transactions": "^5.7.0", + "@ethersproject/wordlists": "^5.7.0" } }, "node_modules/@ethersproject/web": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.8.0.tgz", - "integrity": "sha512-j7+Ksi/9KfGviws6Qtf9Q7KCqRhpwrYKQPs+JBA/rKVFF/yaWLHJEH3zfVP2plVu+eys0d2DlFmhoQJayFewcw==", + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/@ethersproject/web/-/web-5.7.1.tgz", + "integrity": "sha512-Gueu8lSvyjBWL4cYsWsjh6MtMwM0+H4HvqFPZfB6dV8ctbP9zFAO73VG1cMWae0FLPCtz0peKPpZY8/ugJJX2w==", "funding": [ { "type": "individual", @@ -4434,17 +4355,17 @@ ], "license": "MIT", "dependencies": { - "@ethersproject/base64": "^5.8.0", - "@ethersproject/bytes": "^5.8.0", - "@ethersproject/logger": "^5.8.0", - "@ethersproject/properties": "^5.8.0", - "@ethersproject/strings": "^5.8.0" + "@ethersproject/base64": "^5.7.0", + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/strings": "^5.7.0" } }, "node_modules/@ethersproject/wordlists": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.8.0.tgz", - "integrity": "sha512-2df9bbXicZws2Sb5S6ET493uJ0Z84Fjr3pC4tu/qlnZERibZCeUVuqdtt+7Tv9xxhUxHoIekIA7avrKUWHrezg==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/wordlists/-/wordlists-5.7.0.tgz", + "integrity": "sha512-S2TFNJNfHWVHNE6cNDjbVlZ6MgE17MIxMbMg2zv3wn+3XSJGosL1m9ZVv3GXCf/2ymSsQ+hRI5IzoMJTG6aoVA==", "funding": [ { "type": "individual", @@ -4457,11 +4378,11 @@ ], "license": "MIT", "dependencies": { - "@ethersproject/bytes": "^5.8.0", - "@ethersproject/hash": "^5.8.0", - "@ethersproject/logger": "^5.8.0", - "@ethersproject/properties": "^5.8.0", - "@ethersproject/strings": "^5.8.0" + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/hash": "^5.7.0", + "@ethersproject/logger": "^5.7.0", + "@ethersproject/properties": "^5.7.0", + "@ethersproject/strings": "^5.7.0" } }, "node_modules/@expo/bunyan": { @@ -6502,9 +6423,9 @@ } }, "node_modules/@libp2p/interface-compliance-tests/node_modules/sinon": { - "version": "19.0.4", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-19.0.4.tgz", - "integrity": "sha512-myidFob7fjmYHJb+CHNLtAYScxn3sngGq4t75L2rCGGpE/k4OQVkN3KE5FsN+XkO2+fcDZ65PGvq3KHrlLAm7g==", + "version": "19.0.5", + "resolved": "https://registry.npmjs.org/sinon/-/sinon-19.0.5.tgz", + "integrity": "sha512-r15s9/s+ub/d4bxNXqIUmwp6imVSdTorIRaxoecYjqTVLZ8RuoXr/4EDGwIBo6Waxn7f2gnURX9zuhAfCwaF6Q==", "license": "BSD-3-Clause", "dependencies": { "@sinonjs/commons": "^3.0.1", @@ -12403,9 +12324,9 @@ } }, "node_modules/aegir/node_modules/lru-cache": { - "version": "11.0.2", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.2.tgz", - "integrity": "sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.1.0.tgz", + "integrity": "sha512-QIXZUBJUx+2zHUdQujWejBkcD9+cs94tLn0+YL8UrCh+D5sCXZ4c7LaEH48pNwRY3MLDgqUFyhlCyjJPf1WP0A==", "license": "ISC", "engines": { "node": "20 || >=22" @@ -14606,7 +14527,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/chai-spies/-/chai-spies-1.1.0.tgz", "integrity": "sha512-ikaUhQvQWchRYj2K54itFp3nrcxaFRpSDQxDlRzSn9aWgu9Pi7lD8yFxTso4WnQ39+WZ69oB/qOvqp+isJIIWA==", - "dev": true, "license": "MIT", "engines": { "node": ">= 4.0.0" @@ -17074,9 +16994,9 @@ } }, "node_modules/dns-over-http-resolver": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/dns-over-http-resolver/-/dns-over-http-resolver-3.0.9.tgz", - "integrity": "sha512-HxgY2zqPZ23QKYWokgmRGGtvZZlinvP/bfo4sOHWqLgkRojIJU73YdUVagDVjCtcDq8Kd55jVhVQWsbIA1+ZLA==", + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/dns-over-http-resolver/-/dns-over-http-resolver-3.0.10.tgz", + "integrity": "sha512-l2kMOLxK6f9ll+5sf2Ndl8WS/2eXhOf9ZSXZMPnTVyHsv1ktN1WX3FwcyYklMq3ORv2N1nhf0TsGKWBjhgn0ug==", "license": "Apache-2.0 OR MIT", "dependencies": { "quick-lru": "^7.0.0", @@ -17484,9 +17404,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.123", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.123.tgz", - "integrity": "sha512-refir3NlutEZqlKaBLK0tzlVLe5P2wDKS7UQt/3SpibizgsRAPOsqQC3ffw1nlv3ze5gjRQZYHoPymgVZkplFA==", + "version": "1.5.124", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.124.tgz", + "integrity": "sha512-riELkpDUqBi00gqreV3RIGoowxGrfueEKBd6zPdOk/I8lvuFpBGNkYoHof3zUHbiTBsIU8oxdIIL/WNrAG1/7A==", "license": "ISC" }, "node_modules/electron-window": { @@ -17508,9 +17428,9 @@ } }, "node_modules/elliptic": { - "version": "6.6.1", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.1.tgz", - "integrity": "sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==", + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", + "integrity": "sha512-iLhC6ULemrljPZb+QutR5TQGB+pdW6KGD5RSegS+8sorOZT+rdQFbsQFJgvN3eRqNALqJer4oQ16YvJHlU8hzQ==", "license": "MIT", "dependencies": { "bn.js": "^4.11.9", @@ -18984,9 +18904,9 @@ } }, "node_modules/eslint-plugin-prettier": { - "version": "5.2.4", - "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.4.tgz", - "integrity": "sha512-SFtuYmnhwYCtuCDTKPoK+CEzCnEgKTU2qTLwoCxvrC0MFBTIXo1i6hDYOI4cwHaE5GZtlWmTN3YfucYi7KJwPw==", + "version": "5.2.5", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.2.5.tgz", + "integrity": "sha512-IKKP8R87pJyMl7WWamLgPkloB16dagPIdd2FjBDbyRYPKo93wS/NbCOPh6gH+ieNLC+XZrhJt/kWj0PS/DFdmg==", "dev": true, "license": "MIT", "dependencies": { @@ -19002,7 +18922,7 @@ "peerDependencies": { "@types/eslint": ">=8.0.0", "eslint": ">=8.0.0", - "eslint-config-prettier": "*", + "eslint-config-prettier": ">= 7.0.0 <10.0.0 || >=10.1.0", "prettier": ">=3.0.0" }, "peerDependenciesMeta": { @@ -19258,54 +19178,6 @@ "url": "https://paulmillr.com/funding/" } }, - "node_modules/ethers": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/ethers/-/ethers-5.8.0.tgz", - "integrity": "sha512-DUq+7fHrCg1aPDFCHx6UIPb3nmt2XMpM7Y/g2gLhsl3lIBqeAfOJIl1qEvRf2uq3BiKxmh6Fh5pfp2ieyek7Kg==", - "funding": [ - { - "type": "individual", - "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" - }, - { - "type": "individual", - "url": "https://www.buymeacoffee.com/ricmoo" - } - ], - "license": "MIT", - "dependencies": { - "@ethersproject/abi": "5.8.0", - "@ethersproject/abstract-provider": "5.8.0", - "@ethersproject/abstract-signer": "5.8.0", - "@ethersproject/address": "5.8.0", - "@ethersproject/base64": "5.8.0", - "@ethersproject/basex": "5.8.0", - "@ethersproject/bignumber": "5.8.0", - "@ethersproject/bytes": "5.8.0", - "@ethersproject/constants": "5.8.0", - "@ethersproject/contracts": "5.8.0", - "@ethersproject/hash": "5.8.0", - "@ethersproject/hdnode": "5.8.0", - "@ethersproject/json-wallets": "5.8.0", - "@ethersproject/keccak256": "5.8.0", - "@ethersproject/logger": "5.8.0", - "@ethersproject/networks": "5.8.0", - "@ethersproject/pbkdf2": "5.8.0", - "@ethersproject/properties": "5.8.0", - "@ethersproject/providers": "5.8.0", - "@ethersproject/random": "5.8.0", - "@ethersproject/rlp": "5.8.0", - "@ethersproject/sha2": "5.8.0", - "@ethersproject/signing-key": "5.8.0", - "@ethersproject/solidity": "5.8.0", - "@ethersproject/strings": "5.8.0", - "@ethersproject/transactions": "5.8.0", - "@ethersproject/units": "5.8.0", - "@ethersproject/wallet": "5.8.0", - "@ethersproject/web": "5.8.0", - "@ethersproject/wordlists": "5.8.0" - } - }, "node_modules/event-iterator": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/event-iterator/-/event-iterator-2.0.0.tgz", @@ -23400,9 +23272,9 @@ "license": "MIT" }, "node_modules/js-sha3": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", - "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==", + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.9.3.tgz", + "integrity": "sha512-BcJPCQeLg6WjEx3FE591wVAevlli8lxsxm9/FzV4HXkV49TmBH38Yvrpce6fjbADGMKFrBMGTqrVz3qPIZ88Gg==", "license": "MIT" }, "node_modules/js-tokens": { @@ -42254,10 +42126,6 @@ } } }, - "packages/enr/node_modules/js-sha3": { - "version": "0.9.3", - "license": "MIT" - }, "packages/interfaces": { "name": "@waku/interfaces", "version": "0.0.29", @@ -42309,10 +42177,6 @@ "node": ">=20" } }, - "packages/message-encryption/node_modules/js-sha3": { - "version": "0.9.3", - "license": "MIT" - }, "packages/message-hash": { "name": "@waku/message-hash", "version": "0.1.18", @@ -42431,9 +42295,14 @@ "@waku/core": "^0.0.34", "@waku/utils": "^0.0.22", "@waku/zerokit-rln-wasm": "^0.0.13", + "chai": "^5.1.2", + "chai-as-promised": "^8.0.1", + "chai-spies": "^1.1.0", + "chai-subset": "^1.6.0", "ethereum-cryptography": "^3.1.0", "ethers": "^5.7.2", "lodash": "^4.17.21", + "sinon": "^19.0.2", "uuid": "^11.0.5" }, "devDependencies": { @@ -42447,29 +42316,149 @@ "@types/sinon": "^17.0.3", "@waku/build-utils": "^1.0.0", "@waku/message-encryption": "^0.0.32", - "chai": "^5.1.2", - "chai-as-promised": "^8.0.1", - "chai-spies": "^1.1.0", - "chai-subset": "^1.6.0", "deep-equal-in-any-order": "^2.0.6", "fast-check": "^3.23.2", - "rollup-plugin-copy": "^3.5.0", - "sinon": "^19.0.2" + "rollup-plugin-copy": "^3.5.0" }, "engines": { "node": ">=20" } }, + "packages/rln/node_modules/@chainsafe/bls-keystore": { + "version": "3.0.0", + "license": "MIT", + "dependencies": { + "ethereum-cryptography": "^1.0.0", + "uuid": "8.3.2" + } + }, + "packages/rln/node_modules/@chainsafe/bls-keystore/node_modules/ethereum-cryptography": { + "version": "1.2.0", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.2.0", + "@noble/secp256k1": "1.7.1", + "@scure/bip32": "1.1.5", + "@scure/bip39": "1.1.1" + } + }, + "packages/rln/node_modules/@chainsafe/bls-keystore/node_modules/uuid": { + "version": "8.3.2", + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "packages/rln/node_modules/@ethersproject/bytes": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.7.0.tgz", + "integrity": "sha512-nsbxwgFXWh9NyYWo+U8atvmMsSdKJprTcICAkvbBffT75qDocbuggBU0SJiVK2MuTrp0q+xvLkTnGMPK1+uA9A==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/logger": "^5.7.0" + } + }, + "packages/rln/node_modules/@ethersproject/logger": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.7.0.tgz", + "integrity": "sha512-0odtFdXu/XHtjQXJYA3u9G0G8btm0ND5Cu8M7i5vhEcE8/HmF4Lbdqanwyv4uQTr2tx6b7fQRmgLrsnpQlmnig==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT" + }, + "packages/rln/node_modules/@ethersproject/rlp": { + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.7.0.tgz", + "integrity": "sha512-rBxzX2vK8mVF7b0Tol44t5Tb8gomOHkj5guL+HhzQ1yBh/ydjGnpw6at+X6Iw0Kp3OzzzkcKp8N9r0W4kYSs9w==", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/bytes": "^5.7.0", + "@ethersproject/logger": "^5.7.0" + } + }, + "packages/rln/node_modules/@noble/hashes": { + "version": "1.2.0", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "license": "MIT" + }, + "packages/rln/node_modules/@scure/base": { + "version": "1.1.9", + "license": "MIT", + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "packages/rln/node_modules/@scure/bip32": { + "version": "1.1.5", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "license": "MIT", + "dependencies": { + "@noble/hashes": "~1.2.0", + "@noble/secp256k1": "~1.7.0", + "@scure/base": "~1.1.0" + } + }, + "packages/rln/node_modules/@scure/bip39": { + "version": "1.1.1", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "license": "MIT", + "dependencies": { + "@noble/hashes": "~1.2.0", + "@scure/base": "~1.1.0" + } + }, "packages/rln/node_modules/@sinonjs/fake-timers": { "version": "13.0.5", - "dev": true, "license": "BSD-3-Clause", "dependencies": { "@sinonjs/commons": "^3.0.1" } }, "packages/rln/node_modules/@types/chai": { - "version": "5.2.0", + "version": "5.0.1", "dev": true, "license": "MIT", "dependencies": { @@ -42478,15 +42467,13 @@ }, "packages/rln/node_modules/assertion-error": { "version": "2.0.1", - "dev": true, "license": "MIT", "engines": { "node": ">=12" } }, "packages/rln/node_modules/chai": { - "version": "5.2.0", - "dev": true, + "version": "5.1.2", "license": "MIT", "dependencies": { "assertion-error": "^2.0.1", @@ -42501,7 +42488,6 @@ }, "packages/rln/node_modules/chai-as-promised": { "version": "8.0.1", - "dev": true, "license": "MIT", "dependencies": { "check-error": "^2.0.0" @@ -42512,7 +42498,6 @@ }, "packages/rln/node_modules/check-error": { "version": "2.1.1", - "dev": true, "license": "MIT", "engines": { "node": ">= 16" @@ -42520,7 +42505,6 @@ }, "packages/rln/node_modules/deep-eql": { "version": "5.0.2", - "dev": true, "license": "MIT", "engines": { "node": ">=6" @@ -42528,32 +42512,74 @@ }, "packages/rln/node_modules/diff": { "version": "7.0.0", - "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.3.1" } }, + "packages/rln/node_modules/ethers": { + "version": "5.7.2", + "funding": [ + { + "type": "individual", + "url": "https://gitcoin.co/grants/13/ethersjs-complete-simple-and-tiny-2" + }, + { + "type": "individual", + "url": "https://www.buymeacoffee.com/ricmoo" + } + ], + "license": "MIT", + "dependencies": { + "@ethersproject/abi": "5.7.0", + "@ethersproject/abstract-provider": "5.7.0", + "@ethersproject/abstract-signer": "5.7.0", + "@ethersproject/address": "5.7.0", + "@ethersproject/base64": "5.7.0", + "@ethersproject/basex": "5.7.0", + "@ethersproject/bignumber": "5.7.0", + "@ethersproject/bytes": "5.7.0", + "@ethersproject/constants": "5.7.0", + "@ethersproject/contracts": "5.7.0", + "@ethersproject/hash": "5.7.0", + "@ethersproject/hdnode": "5.7.0", + "@ethersproject/json-wallets": "5.7.0", + "@ethersproject/keccak256": "5.7.0", + "@ethersproject/logger": "5.7.0", + "@ethersproject/networks": "5.7.1", + "@ethersproject/pbkdf2": "5.7.0", + "@ethersproject/properties": "5.7.0", + "@ethersproject/providers": "5.7.2", + "@ethersproject/random": "5.7.0", + "@ethersproject/rlp": "5.7.0", + "@ethersproject/sha2": "5.7.0", + "@ethersproject/signing-key": "5.7.0", + "@ethersproject/solidity": "5.7.0", + "@ethersproject/strings": "5.7.0", + "@ethersproject/transactions": "5.7.0", + "@ethersproject/units": "5.7.0", + "@ethersproject/wallet": "5.7.0", + "@ethersproject/web": "5.7.1", + "@ethersproject/wordlists": "5.7.0" + } + }, "packages/rln/node_modules/loupe": { "version": "3.1.3", - "dev": true, "license": "MIT" }, "packages/rln/node_modules/pathval": { "version": "2.0.0", - "dev": true, "license": "MIT", "engines": { "node": ">= 14.16" } }, "packages/rln/node_modules/sinon": { - "version": "19.0.4", - "dev": true, + "version": "19.0.2", "license": "BSD-3-Clause", "dependencies": { "@sinonjs/commons": "^3.0.1", - "@sinonjs/fake-timers": "^13.0.5", + "@sinonjs/fake-timers": "^13.0.2", "@sinonjs/samsam": "^8.0.1", "diff": "^7.0.0", "nise": "^6.1.1", @@ -42565,7 +42591,7 @@ } }, "packages/rln/node_modules/uuid": { - "version": "11.1.0", + "version": "11.0.5", "funding": [ "https://github.com/sponsors/broofa", "https://github.com/sponsors/ctavan" @@ -42633,7 +42659,7 @@ } }, "packages/sdk/node_modules/chai": { - "version": "5.2.0", + "version": "5.1.2", "dev": true, "license": "MIT", "dependencies": { @@ -42685,12 +42711,12 @@ } }, "packages/sdk/node_modules/sinon": { - "version": "19.0.4", + "version": "19.0.2", "dev": true, "license": "BSD-3-Clause", "dependencies": { "@sinonjs/commons": "^3.0.1", - "@sinonjs/fake-timers": "^13.0.5", + "@sinonjs/fake-timers": "^13.0.2", "@sinonjs/samsam": "^8.0.1", "diff": "^7.0.0", "nise": "^6.1.1", @@ -42737,7 +42763,7 @@ } }, "packages/sds/node_modules/chai": { - "version": "5.2.0", + "version": "5.1.2", "license": "MIT", "dependencies": { "assertion-error": "^2.0.1", diff --git a/packages/rln/README.md b/packages/rln/README.md index 9148245514..3de34d55a1 100644 --- a/packages/rln/README.md +++ b/packages/rln/README.md @@ -20,6 +20,11 @@ import { RLN } from '@waku/rln'; // Usage examples coming soon ``` +## Constants + +- Implementation contract: 0xde2260ca49300357d5af4153cda0d18f7b3ea9b3 +- Proxy contract: 0xb9cd878c90e49f797b4431fbf4fb333108cb90e6 + ## License MIT OR Apache-2.0 \ No newline at end of file diff --git a/packages/rln/package.json b/packages/rln/package.json index f95a5e8787..a0035b2342 100644 --- a/packages/rln/package.json +++ b/packages/rln/package.json @@ -59,14 +59,9 @@ "@types/sinon": "^17.0.3", "@waku/build-utils": "^1.0.0", "@waku/message-encryption": "^0.0.32", - "chai": "^5.1.2", - "chai-as-promised": "^8.0.1", - "chai-spies": "^1.1.0", - "chai-subset": "^1.6.0", "deep-equal-in-any-order": "^2.0.6", "fast-check": "^3.23.2", - "rollup-plugin-copy": "^3.5.0", - "sinon": "^19.0.2" + "rollup-plugin-copy": "^3.5.0" }, "files": [ "dist", @@ -86,6 +81,11 @@ "ethereum-cryptography": "^3.1.0", "ethers": "^5.7.2", "lodash": "^4.17.21", - "uuid": "^11.0.5" + "uuid": "^11.0.5", + "chai": "^5.1.2", + "chai-as-promised": "^8.0.1", + "chai-spies": "^1.1.0", + "chai-subset": "^1.6.0", + "sinon": "^19.0.2" } } diff --git a/packages/rln/src/codec.spec.ts b/packages/rln/src/codec.spec.ts index df41f676c2..d3162762bc 100644 --- a/packages/rln/src/codec.spec.ts +++ b/packages/rln/src/codec.spec.ts @@ -3,7 +3,6 @@ import { createEncoder, DecodedMessage } from "@waku/core/lib/message/version_0"; -import type { IProtoMessage } from "@waku/interfaces"; import { generatePrivateKey, generateSymmetricKey, @@ -25,40 +24,30 @@ import { RLNDecoder, RLNEncoder } from "./codec.js"; -import { createRLN } from "./create.js"; +import { + createTestMetaSetter, + createTestRLNCodecSetup, + EMPTY_PROTO_MESSAGE, + TEST_CONSTANTS, + verifyRLNMessage +} from "./codec.test-utils.js"; import { RlnMessage } from "./message.js"; import { epochBytesToInt } from "./utils/index.js"; -const TestContentTopic = "/test/1/waku-message/utf8"; -const EMPTY_PUBSUB_TOPIC = ""; - -const EMPTY_PROTO_MESSAGE = { - timestamp: undefined, - contentTopic: "", - ephemeral: undefined, - meta: undefined, - rateLimitProof: undefined, - version: undefined -}; - describe("RLN codec with version 0", () => { it("toWire", async function () { - const rlnInstance = await createRLN(); - const credential = rlnInstance.zerokit.generateIdentityCredentials(); - const index = 0; - const payload = new Uint8Array([1, 2, 3, 4, 5]); - - rlnInstance.zerokit.insertMember(credential.IDCommitment); + const { rlnInstance, credential, index, payload } = + await createTestRLNCodecSetup(); const rlnEncoder = createRLNEncoder({ - encoder: createEncoder({ contentTopic: TestContentTopic }), + encoder: createEncoder({ contentTopic: TEST_CONSTANTS.contentTopic }), rlnInstance, index, credential }); const rlnDecoder = createRLNDecoder({ rlnInstance, - decoder: createDecoder(TestContentTopic) + decoder: createDecoder(TEST_CONSTANTS.contentTopic) }); const bytes = await rlnEncoder.toWire({ payload }); @@ -67,78 +56,49 @@ describe("RLN codec with version 0", () => { const protoResult = await rlnDecoder.fromWireToProtoObj(bytes!); expect(protoResult).to.not.be.undefined; const msg = (await rlnDecoder.fromProtoObj( - EMPTY_PUBSUB_TOPIC, + TEST_CONSTANTS.emptyPubsubTopic, protoResult! ))!; - expect(msg.rateLimitProof).to.not.be.undefined; - expect(msg.verify([rlnInstance.zerokit.getMerkleRoot()])).to.be.true; - expect(msg.verifyNoRoot()).to.be.true; - expect(msg.epoch).to.not.be.undefined; - expect(msg.epoch).to.be.gt(0); - - expect(msg.contentTopic).to.eq(TestContentTopic); - expect(msg.msg.version).to.eq(0); - expect(msg.payload).to.deep.eq(payload); - expect(msg.timestamp).to.not.be.undefined; + verifyRLNMessage(msg, payload, TEST_CONSTANTS.contentTopic, 0, rlnInstance); }); it("toProtoObj", async function () { - const rlnInstance = await createRLN(); - const credential = rlnInstance.zerokit.generateIdentityCredentials(); - const index = 0; - const payload = new Uint8Array([1, 2, 3, 4, 5]); - - rlnInstance.zerokit.insertMember(credential.IDCommitment); + const { rlnInstance, credential, index, payload } = + await createTestRLNCodecSetup(); const rlnEncoder = new RLNEncoder( - createEncoder({ contentTopic: TestContentTopic }), + createEncoder({ contentTopic: TEST_CONSTANTS.contentTopic }), rlnInstance, index, credential ); const rlnDecoder = new RLNDecoder( rlnInstance, - createDecoder(TestContentTopic) + createDecoder(TEST_CONSTANTS.contentTopic) ); const proto = await rlnEncoder.toProtoObj({ payload }); expect(proto).to.not.be.undefined; const msg = (await rlnDecoder.fromProtoObj( - EMPTY_PUBSUB_TOPIC, + TEST_CONSTANTS.emptyPubsubTopic, proto! )) as RlnMessage; - expect(msg).to.not.be.undefined; - expect(msg.rateLimitProof).to.not.be.undefined; - - expect(msg.verify([rlnInstance.zerokit.getMerkleRoot()])).to.be.true; - expect(msg.verifyNoRoot()).to.be.true; - expect(msg.epoch).to.not.be.undefined; - expect(msg.epoch).to.be.gt(0); - - expect(msg.contentTopic).to.eq(TestContentTopic); - expect(msg.msg.version).to.eq(0); - expect(msg.payload).to.deep.eq(payload); - expect(msg.timestamp).to.not.be.undefined; + verifyRLNMessage(msg, payload, TEST_CONSTANTS.contentTopic, 0, rlnInstance); }); }); describe("RLN codec with version 1", () => { it("Symmetric, toWire", async function () { - const rlnInstance = await createRLN(); - const credential = rlnInstance.zerokit.generateIdentityCredentials(); - const index = 0; - const payload = new Uint8Array([1, 2, 3, 4, 5]); - - rlnInstance.zerokit.insertMember(credential.IDCommitment); - + const { rlnInstance, credential, index, payload } = + await createTestRLNCodecSetup(); const symKey = generateSymmetricKey(); const rlnEncoder = new RLNEncoder( createSymEncoder({ - contentTopic: TestContentTopic, + contentTopic: TEST_CONSTANTS.contentTopic, symKey }), rlnInstance, @@ -147,45 +107,30 @@ describe("RLN codec with version 1", () => { ); const rlnDecoder = new RLNDecoder( rlnInstance, - createSymDecoder(TestContentTopic, symKey) + createSymDecoder(TEST_CONSTANTS.contentTopic, symKey) ); const bytes = await rlnEncoder.toWire({ payload }); expect(bytes).to.not.be.undefined; const protoResult = await rlnDecoder.fromWireToProtoObj(bytes!); - expect(protoResult).to.not.be.undefined; const msg = (await rlnDecoder.fromProtoObj( - EMPTY_PUBSUB_TOPIC, + TEST_CONSTANTS.emptyPubsubTopic, protoResult! ))!; - expect(msg.rateLimitProof).to.not.be.undefined; - expect(msg.verify([rlnInstance.zerokit.getMerkleRoot()])).to.be.true; - expect(msg.verifyNoRoot()).to.be.true; - expect(msg.epoch).to.not.be.undefined; - expect(msg.epoch).to.be.gt(0); - - expect(msg.contentTopic).to.eq(TestContentTopic); - expect(msg.msg.version).to.eq(1); - expect(msg.payload).to.deep.eq(payload); - expect(msg.timestamp).to.not.be.undefined; + verifyRLNMessage(msg, payload, TEST_CONSTANTS.contentTopic, 1, rlnInstance); }); it("Symmetric, toProtoObj", async function () { - const rlnInstance = await createRLN(); - const credential = rlnInstance.zerokit.generateIdentityCredentials(); - const index = 0; - const payload = new Uint8Array([1, 2, 3, 4, 5]); - - rlnInstance.zerokit.insertMember(credential.IDCommitment); - + const { rlnInstance, credential, index, payload } = + await createTestRLNCodecSetup(); const symKey = generateSymmetricKey(); const rlnEncoder = new RLNEncoder( createSymEncoder({ - contentTopic: TestContentTopic, + contentTopic: TEST_CONSTANTS.contentTopic, symKey }), rlnInstance, @@ -194,45 +139,29 @@ describe("RLN codec with version 1", () => { ); const rlnDecoder = new RLNDecoder( rlnInstance, - createSymDecoder(TestContentTopic, symKey) + createSymDecoder(TEST_CONSTANTS.contentTopic, symKey) ); const proto = await rlnEncoder.toProtoObj({ payload }); expect(proto).to.not.be.undefined; const msg = (await rlnDecoder.fromProtoObj( - EMPTY_PUBSUB_TOPIC, + TEST_CONSTANTS.emptyPubsubTopic, proto! )) as RlnMessage; - expect(msg).to.not.be.undefined; - expect(msg.rateLimitProof).to.not.be.undefined; - - expect(msg.verify([rlnInstance.zerokit.getMerkleRoot()])).to.be.true; - expect(msg.verifyNoRoot()).to.be.true; - expect(msg.epoch).to.not.be.undefined; - expect(msg.epoch).to.be.gt(0); - - expect(msg.contentTopic).to.eq(TestContentTopic); - expect(msg.msg.version).to.eq(1); - expect(msg.payload).to.deep.eq(payload); - expect(msg.timestamp).to.not.be.undefined; + verifyRLNMessage(msg, payload, TEST_CONSTANTS.contentTopic, 1, rlnInstance); }); it("Asymmetric, toWire", async function () { - const rlnInstance = await createRLN(); - const credential = rlnInstance.zerokit.generateIdentityCredentials(); - const index = 0; - const payload = new Uint8Array([1, 2, 3, 4, 5]); - - rlnInstance.zerokit.insertMember(credential.IDCommitment); - + const { rlnInstance, credential, index, payload } = + await createTestRLNCodecSetup(); const privateKey = generatePrivateKey(); const publicKey = getPublicKey(privateKey); const rlnEncoder = new RLNEncoder( createAsymEncoder({ - contentTopic: TestContentTopic, + contentTopic: TEST_CONSTANTS.contentTopic, publicKey }), rlnInstance, @@ -241,46 +170,31 @@ describe("RLN codec with version 1", () => { ); const rlnDecoder = new RLNDecoder( rlnInstance, - createAsymDecoder(TestContentTopic, privateKey) + createAsymDecoder(TEST_CONSTANTS.contentTopic, privateKey) ); const bytes = await rlnEncoder.toWire({ payload }); expect(bytes).to.not.be.undefined; const protoResult = await rlnDecoder.fromWireToProtoObj(bytes!); - expect(protoResult).to.not.be.undefined; const msg = (await rlnDecoder.fromProtoObj( - EMPTY_PUBSUB_TOPIC, + TEST_CONSTANTS.emptyPubsubTopic, protoResult! ))!; - expect(msg.rateLimitProof).to.not.be.undefined; - expect(msg.verify([rlnInstance.zerokit.getMerkleRoot()])).to.be.true; - expect(msg.verifyNoRoot()).to.be.true; - expect(msg.epoch).to.not.be.undefined; - expect(msg.epoch).to.be.gt(0); - - expect(msg.contentTopic).to.eq(TestContentTopic); - expect(msg.msg.version).to.eq(1); - expect(msg.payload).to.deep.eq(payload); - expect(msg.timestamp).to.not.be.undefined; + verifyRLNMessage(msg, payload, TEST_CONSTANTS.contentTopic, 1, rlnInstance); }); it("Asymmetric, toProtoObj", async function () { - const rlnInstance = await createRLN(); - const credential = rlnInstance.zerokit.generateIdentityCredentials(); - const index = 0; - const payload = new Uint8Array([1, 2, 3, 4, 5]); - - rlnInstance.zerokit.insertMember(credential.IDCommitment); - + const { rlnInstance, credential, index, payload } = + await createTestRLNCodecSetup(); const privateKey = generatePrivateKey(); const publicKey = getPublicKey(privateKey); const rlnEncoder = new RLNEncoder( createAsymEncoder({ - contentTopic: TestContentTopic, + contentTopic: TEST_CONSTANTS.contentTopic, publicKey }), rlnInstance, @@ -289,106 +203,73 @@ describe("RLN codec with version 1", () => { ); const rlnDecoder = new RLNDecoder( rlnInstance, - createAsymDecoder(TestContentTopic, privateKey) + createAsymDecoder(TEST_CONSTANTS.contentTopic, privateKey) ); const proto = await rlnEncoder.toProtoObj({ payload }); expect(proto).to.not.be.undefined; const msg = (await rlnDecoder.fromProtoObj( - EMPTY_PUBSUB_TOPIC, + TEST_CONSTANTS.emptyPubsubTopic, proto! )) as RlnMessage; - expect(msg).to.not.be.undefined; - expect(msg.rateLimitProof).to.not.be.undefined; - - expect(msg.verify([rlnInstance.zerokit.getMerkleRoot()])).to.be.true; - expect(msg.verifyNoRoot()).to.be.true; - expect(msg.epoch).to.not.be.undefined; - expect(msg.epoch).to.be.gt(0); - - expect(msg.contentTopic).to.eq(TestContentTopic); - expect(msg.msg.version).to.eq(1); - expect(msg.payload).to.deep.eq(payload); - expect(msg.timestamp).to.not.be.undefined; + verifyRLNMessage(msg, payload, TEST_CONSTANTS.contentTopic, 1, rlnInstance); }); }); describe("RLN Codec - epoch", () => { it("toProtoObj", async function () { - const rlnInstance = await createRLN(); - const credential = rlnInstance.zerokit.generateIdentityCredentials(); - const index = 0; - const payload = new Uint8Array([1, 2, 3, 4, 5]); - - rlnInstance.zerokit.insertMember(credential.IDCommitment); + const { rlnInstance, credential, index, payload } = + await createTestRLNCodecSetup(); const rlnEncoder = new RLNEncoder( - createEncoder({ contentTopic: TestContentTopic }), + createEncoder({ contentTopic: TEST_CONSTANTS.contentTopic }), rlnInstance, index, credential ); const rlnDecoder = new RLNDecoder( rlnInstance, - createDecoder(TestContentTopic) + createDecoder(TEST_CONSTANTS.contentTopic) ); const proto = await rlnEncoder.toProtoObj({ payload }); expect(proto).to.not.be.undefined; const msg = (await rlnDecoder.fromProtoObj( - EMPTY_PUBSUB_TOPIC, + TEST_CONSTANTS.emptyPubsubTopic, proto! )) as RlnMessage; const epochBytes = proto!.rateLimitProof!.epoch; const epoch = epochBytesToInt(epochBytes); - expect(msg).to.not.be.undefined; - expect(msg.rateLimitProof).to.not.be.undefined; - - expect(msg.verify([rlnInstance.zerokit.getMerkleRoot()])).to.be.true; - expect(msg.verifyNoRoot()).to.be.true; - expect(msg.epoch).to.not.be.undefined; expect(msg.epoch!.toString(10).length).to.eq(9); expect(msg.epoch).to.eq(epoch); - expect(msg.contentTopic).to.eq(TestContentTopic); - expect(msg.msg.version).to.eq(0); - expect(msg.payload).to.deep.eq(payload); - expect(msg.timestamp).to.not.be.undefined; + verifyRLNMessage(msg, payload, TEST_CONSTANTS.contentTopic, 0, rlnInstance); }); }); describe("RLN codec with version 0 and meta setter", () => { - // Encode the length of the payload - // Not a relevant real life example - const metaSetter = (msg: IProtoMessage & { meta: undefined }): Uint8Array => { - const buffer = new ArrayBuffer(4); - const view = new DataView(buffer); - view.setUint32(0, msg.payload.length, false); - return new Uint8Array(buffer); - }; - it("toWire", async function () { - const rlnInstance = await createRLN(); - const credential = rlnInstance.zerokit.generateIdentityCredentials(); - const index = 0; - const payload = new Uint8Array([1, 2, 3, 4, 5]); - - rlnInstance.zerokit.insertMember(credential.IDCommitment); + const { rlnInstance, credential, index, payload } = + await createTestRLNCodecSetup(); + const metaSetter = createTestMetaSetter(); const rlnEncoder = createRLNEncoder({ - encoder: createEncoder({ contentTopic: TestContentTopic, metaSetter }), + encoder: createEncoder({ + contentTopic: TEST_CONSTANTS.contentTopic, + metaSetter + }), rlnInstance, index, credential }); const rlnDecoder = createRLNDecoder({ rlnInstance, - decoder: createDecoder(TestContentTopic) + decoder: createDecoder(TEST_CONSTANTS.contentTopic) }); const bytes = await rlnEncoder.toWire({ payload }); @@ -397,7 +278,7 @@ describe("RLN codec with version 0 and meta setter", () => { const protoResult = await rlnDecoder.fromWireToProtoObj(bytes!); expect(protoResult).to.not.be.undefined; const msg = (await rlnDecoder.fromProtoObj( - EMPTY_PUBSUB_TOPIC, + TEST_CONSTANTS.emptyPubsubTopic, protoResult! ))!; @@ -407,43 +288,30 @@ describe("RLN codec with version 0 and meta setter", () => { }); expect(msg!.meta).to.deep.eq(expectedMeta); - - expect(msg.rateLimitProof).to.not.be.undefined; - expect(msg.verify([rlnInstance.zerokit.getMerkleRoot()])).to.be.true; - expect(msg.verifyNoRoot()).to.be.true; - expect(msg.epoch).to.not.be.undefined; - expect(msg.epoch).to.be.gt(0); - - expect(msg.contentTopic).to.eq(TestContentTopic); - expect(msg.msg.version).to.eq(0); - expect(msg.payload).to.deep.eq(payload); - expect(msg.timestamp).to.not.be.undefined; + verifyRLNMessage(msg, payload, TEST_CONSTANTS.contentTopic, 0, rlnInstance); }); it("toProtoObj", async function () { - const rlnInstance = await createRLN(); - const credential = rlnInstance.zerokit.generateIdentityCredentials(); - const index = 0; - const payload = new Uint8Array([1, 2, 3, 4, 5]); - - rlnInstance.zerokit.insertMember(credential.IDCommitment); + const { rlnInstance, credential, index, payload } = + await createTestRLNCodecSetup(); + const metaSetter = createTestMetaSetter(); const rlnEncoder = new RLNEncoder( - createEncoder({ contentTopic: TestContentTopic, metaSetter }), + createEncoder({ contentTopic: TEST_CONSTANTS.contentTopic, metaSetter }), rlnInstance, index, credential ); const rlnDecoder = new RLNDecoder( rlnInstance, - createDecoder(TestContentTopic) + createDecoder(TEST_CONSTANTS.contentTopic) ); const proto = await rlnEncoder.toProtoObj({ payload }); expect(proto).to.not.be.undefined; const msg = (await rlnDecoder.fromProtoObj( - EMPTY_PUBSUB_TOPIC, + TEST_CONSTANTS.emptyPubsubTopic, proto! )) as RlnMessage; @@ -453,18 +321,6 @@ describe("RLN codec with version 0 and meta setter", () => { }); expect(msg!.meta).to.deep.eq(expectedMeta); - - expect(msg).to.not.be.undefined; - expect(msg.rateLimitProof).to.not.be.undefined; - - expect(msg.verify([rlnInstance.zerokit.getMerkleRoot()])).to.be.true; - expect(msg.verifyNoRoot()).to.be.true; - expect(msg.epoch).to.not.be.undefined; - expect(msg.epoch).to.be.gt(0); - - expect(msg.contentTopic).to.eq(TestContentTopic); - expect(msg.msg.version).to.eq(0); - expect(msg.payload).to.deep.eq(payload); - expect(msg.timestamp).to.not.be.undefined; + verifyRLNMessage(msg, payload, TEST_CONSTANTS.contentTopic, 0, rlnInstance); }); }); diff --git a/packages/rln/src/codec.test-utils.ts b/packages/rln/src/codec.test-utils.ts new file mode 100644 index 0000000000..b3bfc29612 --- /dev/null +++ b/packages/rln/src/codec.test-utils.ts @@ -0,0 +1,80 @@ +import type { IProtoMessage } from "@waku/interfaces"; +import { expect } from "chai"; + +import { createRLN } from "./create.js"; +import type { IdentityCredential } from "./identity.js"; + +export interface TestRLNCodecSetup { + rlnInstance: any; + credential: IdentityCredential; + index: number; + payload: Uint8Array; +} + +export const TEST_CONSTANTS = { + contentTopic: "/test/1/waku-message/utf8", + emptyPubsubTopic: "", + defaultIndex: 0, + defaultPayload: new Uint8Array([1, 2, 3, 4, 5]) +} as const; + +export const EMPTY_PROTO_MESSAGE = { + timestamp: undefined, + contentTopic: "", + ephemeral: undefined, + meta: undefined, + rateLimitProof: undefined, + version: undefined +} as const; + +/** + * Creates a basic RLN setup for codec tests + */ +export async function createTestRLNCodecSetup(): Promise { + const rlnInstance = await createRLN(); + const credential = rlnInstance.zerokit.generateIdentityCredentials(); + rlnInstance.zerokit.insertMember(credential.IDCommitment); + + return { + rlnInstance, + credential, + index: TEST_CONSTANTS.defaultIndex, + payload: TEST_CONSTANTS.defaultPayload + }; +} + +/** + * Creates a meta setter function for testing + */ +export function createTestMetaSetter(): ( + msg: IProtoMessage & { meta: undefined } +) => Uint8Array { + return (msg: IProtoMessage & { meta: undefined }): Uint8Array => { + const buffer = new ArrayBuffer(4); + const view = new DataView(buffer); + view.setUint32(0, msg.payload.length, false); + return new Uint8Array(buffer); + }; +} + +/** + * Verifies common RLN message properties + */ +export function verifyRLNMessage( + msg: any, + payload: Uint8Array, + contentTopic: string, + version: number, + rlnInstance: any +): void { + expect(msg.rateLimitProof).to.not.be.undefined; + expect(msg.verify([rlnInstance.zerokit.getMerkleRoot()])).to.be.true; + expect(msg.verifyNoRoot()).to.be.true; + expect(msg.epoch).to.not.be.undefined; + expect(msg.epoch).to.be.gt(0); + + expect(msg.contentTopic).to.eq(contentTopic); + expect(msg.msg.version).to.eq(version); + expect(msg.payload).to.deep.eq(payload); + expect(msg.timestamp).to.not.be.undefined; +} diff --git a/packages/rln/src/contract/abi.ts b/packages/rln/src/contract/abi.ts index 748e23f04f..858ec25de5 100644 --- a/packages/rln/src/contract/abi.ts +++ b/packages/rln/src/contract/abi.ts @@ -1,392 +1,646 @@ export const RLN_ABI = [ + { inputs: [], stateMutability: "nonpayable", type: "constructor" }, { - type: "constructor", - inputs: [], - stateMutability: "nonpayable" + inputs: [ + { internalType: "uint256", name: "idCommitment", type: "uint256" } + ], + name: "CannotEraseActiveMembership", + type: "error" + }, + { inputs: [], name: "CannotExceedMaxTotalRateLimit", type: "error" }, + { + inputs: [ + { internalType: "uint256", name: "idCommitment", type: "uint256" } + ], + name: "CannotExtendNonGracePeriodMembership", + type: "error" }, { - type: "error", - name: "DuplicateIdCommitment", - inputs: [] - }, - { - type: "error", + inputs: [ + { internalType: "uint256", name: "idCommitment", type: "uint256" } + ], name: "InvalidIdCommitment", - inputs: [ - { - name: "idCommitment", - type: "uint256" - } - ] + type: "error" }, + { inputs: [], name: "InvalidMembershipRateLimit", type: "error" }, { - type: "error", + inputs: [ + { internalType: "uint256", name: "startIndex", type: "uint256" }, + { internalType: "uint256", name: "endIndex", type: "uint256" } + ], name: "InvalidPaginationQuery", + type: "error" + }, + { + inputs: [ + { internalType: "uint256", name: "idCommitment", type: "uint256" } + ], + name: "MembershipDoesNotExist", + type: "error" + }, + { + inputs: [ + { internalType: "uint256", name: "idCommitment", type: "uint256" } + ], + name: "NonHolderCannotEraseGracePeriodMembership", + type: "error" + }, + { + inputs: [ + { internalType: "uint256", name: "idCommitment", type: "uint256" } + ], + name: "NonHolderCannotExtend", + type: "error" + }, + { + anonymous: false, inputs: [ { - name: "startIndex", - type: "uint256" - }, - { - name: "endIndex", - type: "uint256" - } - ] - }, - { - type: "function", - name: "MAX_MEMBERSHIP_SET_SIZE", - inputs: [], - outputs: [ - { - name: "", - type: "uint32" - } - ], - stateMutability: "view" - }, - { - type: "function", - name: "MERKLE_TREE_DEPTH", - inputs: [], - outputs: [ - { - name: "", - type: "uint8" - } - ], - stateMutability: "view" - }, - { - type: "function", - name: "Q", - inputs: [], - outputs: [ - { - name: "", - type: "uint256" - } - ], - stateMutability: "view" - }, - { - type: "function", - name: "activeDurationForNewMemberships", - inputs: [], - outputs: [ - { - name: "", - type: "uint32" - } - ], - stateMutability: "view" - }, - { - type: "function", - name: "currentTotalRateLimit", - inputs: [], - outputs: [ - { - name: "", - type: "uint256" - } - ], - stateMutability: "view" - }, - { - type: "function", - name: "deployedBlockNumber", - inputs: [], - outputs: [ - { - name: "", - type: "uint32" - } - ], - stateMutability: "view" - }, - { - type: "function", - name: "depositsToWithdraw", - inputs: [ - { - name: "holder", + indexed: false, + internalType: "address", + name: "previousAdmin", type: "address" }, { - name: "token", + indexed: false, + internalType: "address", + name: "newAdmin", type: "address" } ], - outputs: [ - { - name: "balance", - type: "uint256" - } - ], - stateMutability: "view" + name: "AdminChanged", + type: "event" }, { - type: "function", - name: "eraseMemberships", + anonymous: false, inputs: [ { - name: "idCommitments", - type: "uint256[]" + indexed: true, + internalType: "address", + name: "beacon", + type: "address" } ], - outputs: [], - stateMutability: "nonpayable" + name: "BeaconUpgraded", + type: "event" }, { - type: "function", - name: "eraseMemberships", + anonymous: false, inputs: [ - { - name: "idCommitments", - type: "uint256[]" - }, - { - name: "eraseFromMembershipSet", - type: "bool" - } + { indexed: false, internalType: "uint8", name: "version", type: "uint8" } ], - outputs: [], - stateMutability: "nonpayable" + name: "Initialized", + type: "event" }, { - type: "function", - name: "extendMemberships", - inputs: [ - { - name: "idCommitments", - type: "uint256[]" - } - ], - outputs: [], - stateMutability: "nonpayable" - }, - { - type: "function", - name: "getMembershipInfo", + anonymous: false, inputs: [ { + indexed: false, + internalType: "uint256", name: "idCommitment", type: "uint256" - } + }, + { + indexed: false, + internalType: "uint32", + name: "membershipRateLimit", + type: "uint32" + }, + { indexed: false, internalType: "uint32", name: "index", type: "uint32" } ], - outputs: [ + name: "MembershipErased", + type: "event" + }, + { + anonymous: false, + inputs: [ { - name: "", - type: "uint32" + indexed: false, + internalType: "uint256", + name: "idCommitment", + type: "uint256" }, { - name: "", + indexed: false, + internalType: "uint32", + name: "membershipRateLimit", type: "uint32" }, + { indexed: false, internalType: "uint32", name: "index", type: "uint32" } + ], + name: "MembershipExpired", + type: "event" + }, + { + anonymous: false, + inputs: [ { - name: "", + indexed: false, + internalType: "uint256", + name: "idCommitment", + type: "uint256" + }, + { + indexed: false, + internalType: "uint32", + name: "membershipRateLimit", + type: "uint32" + }, + { indexed: false, internalType: "uint32", name: "index", type: "uint32" }, + { + indexed: false, + internalType: "uint256", + name: "newGracePeriodStartTimestamp", type: "uint256" } ], - stateMutability: "view" + name: "MembershipExtended", + type: "event" }, { - type: "function", - name: "getMerkleProof", + anonymous: false, inputs: [ { - name: "index", - type: "uint40" - } - ], - outputs: [ - { - name: "", - type: "uint256[20]" - } - ], - stateMutability: "view" - }, - { - type: "function", - name: "getRateCommitmentsInRangeBoundsInclusive", - inputs: [ - { - name: "startIndex", - type: "uint32" + indexed: false, + internalType: "uint256", + name: "idCommitment", + type: "uint256" }, { - name: "endIndex", - type: "uint32" - } + indexed: false, + internalType: "uint256", + name: "membershipRateLimit", + type: "uint256" + }, + { indexed: false, internalType: "uint32", name: "index", type: "uint32" } ], - outputs: [ - { - name: "", - type: "uint256[]" - } - ], - stateMutability: "view" + name: "MembershipRegistered", + type: "event" }, { - type: "function", - name: "gracePeriodDurationForNewMemberships", - inputs: [], - outputs: [ - { - name: "", - type: "uint32" - } - ], - stateMutability: "view" - }, - { - type: "function", - name: "initialize", + anonymous: false, inputs: [ { - name: "_priceCalculator", + indexed: true, + internalType: "address", + name: "previousOwner", type: "address" }, { - name: "_maxTotalRateLimit", - type: "uint32" - }, + indexed: true, + internalType: "address", + name: "newOwner", + type: "address" + } + ], + name: "OwnershipTransferred", + type: "event" + }, + { + anonymous: false, + inputs: [ { + indexed: true, + internalType: "address", + name: "implementation", + type: "address" + } + ], + name: "Upgraded", + type: "event" + }, + { + inputs: [], + name: "MAX_MEMBERSHIP_SET_SIZE", + outputs: [{ internalType: "uint32", name: "", type: "uint32" }], + stateMutability: "view", + type: "function" + }, + { + inputs: [], + name: "MERKLE_TREE_DEPTH", + outputs: [{ internalType: "uint8", name: "", type: "uint8" }], + stateMutability: "view", + type: "function" + }, + { + inputs: [], + name: "Q", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function" + }, + { + inputs: [], + name: "activeDurationForNewMemberships", + outputs: [{ internalType: "uint32", name: "", type: "uint32" }], + stateMutability: "view", + type: "function" + }, + { + inputs: [], + name: "currentTotalRateLimit", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function" + }, + { + inputs: [], + name: "deployedBlockNumber", + outputs: [{ internalType: "uint32", name: "", type: "uint32" }], + stateMutability: "view", + type: "function" + }, + { + inputs: [ + { internalType: "address", name: "holder", type: "address" }, + { internalType: "address", name: "token", type: "address" } + ], + name: "depositsToWithdraw", + outputs: [{ internalType: "uint256", name: "balance", type: "uint256" }], + stateMutability: "view", + type: "function" + }, + { + inputs: [ + { internalType: "uint256[]", name: "idCommitments", type: "uint256[]" } + ], + name: "eraseMemberships", + outputs: [], + stateMutability: "nonpayable", + type: "function" + }, + { + inputs: [ + { internalType: "uint256[]", name: "idCommitments", type: "uint256[]" }, + { internalType: "bool", name: "eraseFromMembershipSet", type: "bool" } + ], + name: "eraseMemberships", + outputs: [], + stateMutability: "nonpayable", + type: "function" + }, + { + inputs: [ + { internalType: "uint256[]", name: "idCommitments", type: "uint256[]" } + ], + name: "extendMemberships", + outputs: [], + stateMutability: "nonpayable", + type: "function" + }, + { + inputs: [ + { internalType: "uint256", name: "idCommitment", type: "uint256" } + ], + name: "getMembershipInfo", + outputs: [ + { internalType: "uint32", name: "", type: "uint32" }, + { internalType: "uint32", name: "", type: "uint32" }, + { internalType: "uint256", name: "", type: "uint256" } + ], + stateMutability: "view", + type: "function" + }, + { + inputs: [{ internalType: "uint40", name: "index", type: "uint40" }], + name: "getMerkleProof", + outputs: [{ internalType: "uint256[20]", name: "", type: "uint256[20]" }], + stateMutability: "view", + type: "function" + }, + { + inputs: [ + { internalType: "uint32", name: "startIndex", type: "uint32" }, + { internalType: "uint32", name: "endIndex", type: "uint32" } + ], + name: "getRateCommitmentsInRangeBoundsInclusive", + outputs: [{ internalType: "uint256[]", name: "", type: "uint256[]" }], + stateMutability: "view", + type: "function" + }, + { + inputs: [], + name: "gracePeriodDurationForNewMemberships", + outputs: [{ internalType: "uint32", name: "", type: "uint32" }], + stateMutability: "view", + type: "function" + }, + { + inputs: [{ internalType: "uint256", name: "", type: "uint256" }], + name: "indicesOfLazilyErasedMemberships", + outputs: [{ internalType: "uint32", name: "", type: "uint32" }], + stateMutability: "view", + type: "function" + }, + { + inputs: [ + { internalType: "address", name: "_priceCalculator", type: "address" }, + { internalType: "uint32", name: "_maxTotalRateLimit", type: "uint32" }, + { + internalType: "uint32", name: "_minMembershipRateLimit", type: "uint32" }, { + internalType: "uint32", name: "_maxMembershipRateLimit", type: "uint32" }, - { - name: "_activeDuration", - type: "uint32" - }, - { - name: "_gracePeriod", - type: "uint32" - } + { internalType: "uint32", name: "_activeDuration", type: "uint32" }, + { internalType: "uint32", name: "_gracePeriod", type: "uint32" } ], + name: "initialize", outputs: [], - stateMutability: "nonpayable" + stateMutability: "nonpayable", + type: "function" }, { - type: "function", + inputs: [ + { internalType: "uint256", name: "_idCommitment", type: "uint256" } + ], name: "isExpired", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function" + }, + { inputs: [ - { - name: "_idCommitment", - type: "uint256" - } + { internalType: "uint256", name: "_idCommitment", type: "uint256" } ], + name: "isInGracePeriod", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function" + }, + { + inputs: [ + { internalType: "uint256", name: "idCommitment", type: "uint256" } + ], + name: "isInMembershipSet", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function" + }, + { + inputs: [ + { internalType: "uint256", name: "idCommitment", type: "uint256" } + ], + name: "isValidIdCommitment", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "pure", + type: "function" + }, + { + inputs: [{ internalType: "uint32", name: "rateLimit", type: "uint32" }], + name: "isValidMembershipRateLimit", + outputs: [{ internalType: "bool", name: "", type: "bool" }], + stateMutability: "view", + type: "function" + }, + { + inputs: [], + name: "maxMembershipRateLimit", + outputs: [{ internalType: "uint32", name: "", type: "uint32" }], + stateMutability: "view", + type: "function" + }, + { + inputs: [], + name: "maxTotalRateLimit", + outputs: [{ internalType: "uint32", name: "", type: "uint32" }], + stateMutability: "view", + type: "function" + }, + { + inputs: [ + { internalType: "uint256", name: "_idCommitment", type: "uint256" } + ], + name: "membershipExpirationTimestamp", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function" + }, + { + inputs: [ + { internalType: "uint256", name: "idCommitment", type: "uint256" } + ], + name: "memberships", outputs: [ + { internalType: "uint256", name: "depositAmount", type: "uint256" }, + { internalType: "uint32", name: "activeDuration", type: "uint32" }, { - name: "", - type: "bool" - } + internalType: "uint256", + name: "gracePeriodStartTimestamp", + type: "uint256" + }, + { internalType: "uint32", name: "gracePeriodDuration", type: "uint32" }, + { internalType: "uint32", name: "rateLimit", type: "uint32" }, + { internalType: "uint32", name: "index", type: "uint32" }, + { internalType: "address", name: "holder", type: "address" }, + { internalType: "address", name: "token", type: "address" } ], - stateMutability: "view" + stateMutability: "view", + type: "function" }, { - type: "function", + inputs: [], + name: "merkleTree", + outputs: [ + { internalType: "uint40", name: "maxIndex", type: "uint40" }, + { internalType: "uint40", name: "numberOfLeaves", type: "uint40" } + ], + stateMutability: "view", + type: "function" + }, + { + inputs: [], + name: "minMembershipRateLimit", + outputs: [{ internalType: "uint32", name: "", type: "uint32" }], + stateMutability: "view", + type: "function" + }, + { + inputs: [], + name: "nextFreeIndex", + outputs: [{ internalType: "uint32", name: "", type: "uint32" }], + stateMutability: "view", + type: "function" + }, + { + inputs: [], + name: "owner", + outputs: [{ internalType: "address", name: "", type: "address" }], + stateMutability: "view", + type: "function" + }, + { + inputs: [], + name: "priceCalculator", + outputs: [ + { internalType: "contract IPriceCalculator", name: "", type: "address" } + ], + stateMutability: "view", + type: "function" + }, + { + inputs: [], + name: "proxiableUUID", + outputs: [{ internalType: "bytes32", name: "", type: "bytes32" }], + stateMutability: "view", + type: "function" + }, + { + inputs: [ + { internalType: "uint256", name: "idCommitment", type: "uint256" }, + { internalType: "uint32", name: "rateLimit", type: "uint32" }, + { + internalType: "uint256[]", + name: "idCommitmentsToErase", + type: "uint256[]" + } + ], name: "register", + outputs: [], + stateMutability: "nonpayable", + type: "function" + }, + { inputs: [ + { internalType: "address", name: "owner", type: "address" }, + { internalType: "uint256", name: "deadline", type: "uint256" }, + { internalType: "uint8", name: "v", type: "uint8" }, + { internalType: "bytes32", name: "r", type: "bytes32" }, + { internalType: "bytes32", name: "s", type: "bytes32" }, + { internalType: "uint256", name: "idCommitment", type: "uint256" }, + { internalType: "uint32", name: "rateLimit", type: "uint32" }, { - name: "idCommitment", - type: "uint256" - }, - { - name: "rateLimit", - type: "uint32" - }, - { + internalType: "uint256[]", name: "idCommitmentsToErase", type: "uint256[]" } ], - outputs: [], - stateMutability: "nonpayable" - }, - { - type: "function", name: "registerWithPermit", - inputs: [ - { - name: "owner", - type: "address" - }, - { - name: "deadline", - type: "uint256" - }, - { - name: "v", - type: "uint8" - }, - { - name: "r", - type: "bytes32" - }, - { - name: "s", - type: "bytes32" - }, - { - name: "idCommitment", - type: "uint256" - }, - { - name: "rateLimit", - type: "uint32" - }, - { - name: "idCommitmentsToErase", - type: "uint256[]" - } - ], outputs: [], - stateMutability: "nonpayable" + stateMutability: "nonpayable", + type: "function" }, { - type: "event", - name: "MembershipRegistered", - inputs: [ - { - name: "idCommitment", - type: "uint256", - indexed: false - }, - { - name: "rateLimit", - type: "uint32", - indexed: false - }, - { - name: "index", - type: "uint256", - indexed: false - } - ], - anonymous: false + inputs: [], + name: "renounceOwnership", + outputs: [], + stateMutability: "nonpayable", + type: "function" + }, + { + inputs: [], + name: "root", + outputs: [{ internalType: "uint256", name: "", type: "uint256" }], + stateMutability: "view", + type: "function" }, { - type: "event", - name: "MembershipRemoved", inputs: [ { - name: "idCommitment", - type: "uint256", - indexed: false - }, - { - name: "index", - type: "uint256", - indexed: false + internalType: "uint32", + name: "_activeDurationForNewMembership", + type: "uint32" } ], - anonymous: false + name: "setActiveDuration", + outputs: [], + stateMutability: "nonpayable", + type: "function" + }, + { + inputs: [ + { + internalType: "uint32", + name: "_gracePeriodDurationForNewMembership", + type: "uint32" + } + ], + name: "setGracePeriodDuration", + outputs: [], + stateMutability: "nonpayable", + type: "function" + }, + { + inputs: [ + { + internalType: "uint32", + name: "_maxMembershipRateLimit", + type: "uint32" + } + ], + name: "setMaxMembershipRateLimit", + outputs: [], + stateMutability: "nonpayable", + type: "function" + }, + { + inputs: [ + { internalType: "uint32", name: "_maxTotalRateLimit", type: "uint32" } + ], + name: "setMaxTotalRateLimit", + outputs: [], + stateMutability: "nonpayable", + type: "function" + }, + { + inputs: [ + { + internalType: "uint32", + name: "_minMembershipRateLimit", + type: "uint32" + } + ], + name: "setMinMembershipRateLimit", + outputs: [], + stateMutability: "nonpayable", + type: "function" + }, + { + inputs: [ + { internalType: "address", name: "_priceCalculator", type: "address" } + ], + name: "setPriceCalculator", + outputs: [], + stateMutability: "nonpayable", + type: "function" + }, + { + inputs: [{ internalType: "address", name: "newOwner", type: "address" }], + name: "transferOwnership", + outputs: [], + stateMutability: "nonpayable", + type: "function" + }, + { + inputs: [ + { internalType: "address", name: "newImplementation", type: "address" } + ], + name: "upgradeTo", + outputs: [], + stateMutability: "nonpayable", + type: "function" + }, + { + inputs: [ + { internalType: "address", name: "newImplementation", type: "address" }, + { internalType: "bytes", name: "data", type: "bytes" } + ], + name: "upgradeToAndCall", + outputs: [], + stateMutability: "payable", + type: "function" + }, + { + inputs: [{ internalType: "address", name: "token", type: "address" }], + name: "withdraw", + outputs: [], + stateMutability: "nonpayable", + type: "function" } ]; diff --git a/packages/rln/src/contract/constants.ts b/packages/rln/src/contract/constants.ts index 3d26b99639..636e4e16bc 100644 --- a/packages/rln/src/contract/constants.ts +++ b/packages/rln/src/contract/constants.ts @@ -1,8 +1,8 @@ import { RLN_ABI } from "./abi.js"; -export const SEPOLIA_CONTRACT = { - chainId: 11155111, - address: "0xCB33Aa5B38d79E3D9Fa8B10afF38AA201399a7e3", +export const LINEA_CONTRACT = { + chainId: 59141, + address: "0xb9cd878c90e49f797b4431fbf4fb333108cb90e6", abi: RLN_ABI }; diff --git a/packages/rln/src/contract/rln_contract.spec.ts b/packages/rln/src/contract/rln_contract.spec.ts index 817444d3ed..c05902e6e5 100644 --- a/packages/rln/src/contract/rln_contract.spec.ts +++ b/packages/rln/src/contract/rln_contract.spec.ts @@ -4,244 +4,87 @@ import chaiAsPromised from "chai-as-promised"; import * as ethers from "ethers"; import sinon, { SinonSandbox } from "sinon"; -import { createRLN } from "../create.js"; -import type { IdentityCredential } from "../identity.js"; - -import { DEFAULT_RATE_LIMIT, SEPOLIA_CONTRACT } from "./constants.js"; -import { RLNContract } from "./rln_contract.js"; +import { createTestRLNInstance, initializeRLNContract } from "./test-setup.js"; +import { + createMockRegistryContract, + createRegisterStub, + mockRLNRegisteredEvent, + verifyRegistration +} from "./test-utils.js"; use(chaiAsPromised); describe("RLN Contract abstraction - RLN", () => { let sandbox: SinonSandbox; - let rlnInstance: any; - let mockedRegistryContract: any; - - const mockRateLimits = { - minRate: 20, - maxRate: 600, - maxTotalRate: 1000, - currentTotalRate: 500 - }; beforeEach(async () => { sandbox = sinon.createSandbox(); - rlnInstance = await createRLN(); - rlnInstance.zerokit.insertMember = () => undefined; - - mockedRegistryContract = { - minMembershipRateLimit: () => - Promise.resolve(ethers.BigNumber.from(mockRateLimits.minRate)), - maxMembershipRateLimit: () => - Promise.resolve(ethers.BigNumber.from(mockRateLimits.maxRate)), - maxTotalRateLimit: () => - Promise.resolve(ethers.BigNumber.from(mockRateLimits.maxTotalRate)), - currentTotalRateLimit: () => - Promise.resolve(ethers.BigNumber.from(mockRateLimits.currentTotalRate)), - queryFilter: () => [mockRLNRegisteredEvent()], - provider: { - getLogs: () => [], - getBlockNumber: () => Promise.resolve(1000), - getNetwork: () => Promise.resolve({ chainId: 11155111 }) - }, - filters: { - MembershipRegistered: () => ({}), - MembershipRemoved: () => ({}) - }, - on: () => ({}) - }; - - const provider = new ethers.providers.JsonRpcProvider(); - const voidSigner = new ethers.VoidSigner( - SEPOLIA_CONTRACT.address, - provider - ); - await RLNContract.init(rlnInstance, { - address: SEPOLIA_CONTRACT.address, - signer: voidSigner, - rateLimit: DEFAULT_RATE_LIMIT, - contract: mockedRegistryContract as unknown as ethers.Contract - }); }); afterEach(() => { sandbox.restore(); }); - it("should fetch members from events and store them in the RLN instance", async () => { - const rlnInstance = await createRLN(); + describe("Member Registration", () => { + it("should fetch members from events and store them in the RLN instance", async () => { + const { rlnInstance, insertMemberSpy } = await createTestRLNInstance(); + const membershipRegisteredEvent = mockRLNRegisteredEvent(); + const queryFilterStub = sinon.stub().returns([membershipRegisteredEvent]); - const insertMemberSpy = sinon.stub(); - rlnInstance.zerokit.insertMember = insertMemberSpy; + const mockedRegistryContract = createMockRegistryContract({ + queryFilter: queryFilterStub + }); - const membershipRegisteredEvent = mockRLNRegisteredEvent(); + const rlnContract = await initializeRLNContract( + rlnInstance, + mockedRegistryContract + ); - const queryFilterStub = sinon.stub().returns([membershipRegisteredEvent]); - const mockedRegistryContract = { - queryFilter: queryFilterStub, - provider: { - getLogs: () => [], - getBlockNumber: () => Promise.resolve(1000) - }, - interface: { - getEvent: (eventName: string) => ({ - name: eventName, - format: () => {} - }) - }, - filters: { - MembershipRegistered: () => ({}), - MembershipRemoved: () => ({}) - }, - on: () => ({}), - removeAllListeners: () => ({}) - }; + await rlnContract.fetchMembers(rlnInstance, { + fromBlock: 0, + fetchRange: 1000, + fetchChunks: 2 + }); - const provider = new ethers.providers.JsonRpcProvider(); - const voidSigner = new ethers.VoidSigner( - SEPOLIA_CONTRACT.address, - provider - ); - const rlnContract = await RLNContract.init(rlnInstance, { - address: SEPOLIA_CONTRACT.address, - signer: voidSigner, - rateLimit: DEFAULT_RATE_LIMIT, - contract: mockedRegistryContract as unknown as ethers.Contract - }); - - await rlnContract.fetchMembers(rlnInstance, { - fromBlock: 0, - fetchRange: 1000, - fetchChunks: 2 - }); - - expect( - insertMemberSpy.calledWith( - ethers.utils.zeroPad( - hexToBytes(membershipRegisteredEvent.args!.idCommitment), - 32 + expect( + insertMemberSpy.calledWith( + ethers.utils.zeroPad( + hexToBytes(membershipRegisteredEvent.args!.idCommitment), + 32 + ) ) - ) - ).to.be.true; - - expect(queryFilterStub.called).to.be.true; - }); - - it("should register a member", async () => { - const mockSignature = - "0xdeb8a6b00a8e404deb1f52d3aa72ed7f60a2ff4484c737eedaef18a0aacb2dfb4d5d74ac39bb71fa358cf2eb390565a35b026cc6272f2010d4351e17670311c21c"; - - const rlnInstance = await createRLN(); - const identity: IdentityCredential = - rlnInstance.zerokit.generateSeededIdentityCredential(mockSignature); - - const insertMemberSpy = sinon.stub(); - rlnInstance.zerokit.insertMember = insertMemberSpy; - - const formatIdCommitment = (idCommitmentBigInt: bigint): string => - "0x" + idCommitmentBigInt.toString(16).padStart(64, "0"); - - const membershipRegisteredEvent = mockRLNRegisteredEvent( - formatIdCommitment(identity.IDCommitmentBigInt) - ); - - const registerStub = sinon.stub().returns({ - wait: () => - Promise.resolve({ - events: [ - { - event: "MembershipRegistered", - args: { - idCommitment: formatIdCommitment(identity.IDCommitmentBigInt), - rateLimit: DEFAULT_RATE_LIMIT, - index: ethers.BigNumber.from(1) - } - } - ] - }) + ).to.be.true; + expect(queryFilterStub.called).to.be.true; }); - const mockedRegistryContract = { - register: registerStub, - queryFilter: () => [membershipRegisteredEvent], - provider: { - getLogs: () => [], - getBlockNumber: () => Promise.resolve(1000), - getNetwork: () => Promise.resolve({ chainId: 11155111 }) - }, - address: SEPOLIA_CONTRACT.address, - interface: { - getEvent: (eventName: string) => ({ - name: eventName, - format: () => {} - }) - }, - filters: { - MembershipRegistered: () => ({}), - MembershipRemoved: () => ({}) - }, - on: () => ({}), - removeAllListeners: () => ({}) - }; + it("should register a member", async () => { + const { rlnInstance, identity, insertMemberSpy } = + await createTestRLNInstance(); - const provider = new ethers.providers.JsonRpcProvider(); - const voidSigner = new ethers.VoidSigner( - SEPOLIA_CONTRACT.address, - provider - ); - const rlnContract = await RLNContract.init(rlnInstance, { - signer: voidSigner, - address: SEPOLIA_CONTRACT.address, - rateLimit: DEFAULT_RATE_LIMIT, - contract: mockedRegistryContract as unknown as ethers.Contract + const registerStub = createRegisterStub(identity); + const mockedRegistryContract = createMockRegistryContract({ + register: registerStub, + queryFilter: () => [] + }); + + const rlnContract = await initializeRLNContract( + rlnInstance, + mockedRegistryContract + ); + + const decryptedCredentials = + await rlnContract.registerWithIdentity(identity); + + if (!decryptedCredentials) { + throw new Error("Failed to retrieve credentials"); + } + + verifyRegistration( + decryptedCredentials, + identity, + registerStub, + insertMemberSpy + ); }); - - const decryptedCredentials = - await rlnContract.registerWithIdentity(identity); - - expect(decryptedCredentials).to.not.be.undefined; - if (!decryptedCredentials) { - throw new Error("Decrypted credentials should not be undefined"); - } - - expect( - registerStub.calledWith( - identity.IDCommitmentBigInt, - DEFAULT_RATE_LIMIT, - [], - { - gasLimit: 300000 - } - ) - ).to.be.true; - - expect(decryptedCredentials).to.have.property("identity"); - expect(decryptedCredentials).to.have.property("membership"); - expect(decryptedCredentials.membership).to.include({ - address: SEPOLIA_CONTRACT.address, - treeIndex: 1 - }); - - const expectedIdCommitment = ethers.utils.zeroPad( - hexToBytes(formatIdCommitment(identity.IDCommitmentBigInt)), - 32 - ); - expect(insertMemberSpy.callCount).to.equal(2); - expect(insertMemberSpy.getCall(1).args[0]).to.deep.equal( - expectedIdCommitment - ); }); }); - -function mockRLNRegisteredEvent(idCommitment?: string): ethers.Event { - return { - args: { - idCommitment: - idCommitment || - "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef", - rateLimit: DEFAULT_RATE_LIMIT, - index: ethers.BigNumber.from(1) - }, - event: "MembershipRegistered" - } as unknown as ethers.Event; -} diff --git a/packages/rln/src/contract/rln_contract.ts b/packages/rln/src/contract/rln_contract.ts index c489d36dc5..863a9ee12c 100644 --- a/packages/rln/src/contract/rln_contract.ts +++ b/packages/rln/src/contract/rln_contract.ts @@ -30,7 +30,7 @@ interface RLNContractInitOptions extends RLNContractOptions { export interface MembershipRegisteredEvent { idCommitment: string; - rateLimit: number; + membershipRateLimit: ethers.BigNumber; index: ethers.BigNumber; } @@ -65,7 +65,8 @@ export class RLNContract { private _members: Map = new Map(); private _membersFilter: ethers.EventFilter; - private _membersRemovedFilter: ethers.EventFilter; + private _membershipErasedFilter: ethers.EventFilter; + private _membersExpiredFilter: ethers.EventFilter; /** * Asynchronous initializer for RLNContract. @@ -94,15 +95,7 @@ export class RLNContract { contract } = options; - if ( - rateLimit < RATE_LIMIT_PARAMS.MIN_RATE || - rateLimit > RATE_LIMIT_PARAMS.MAX_RATE - ) { - throw new Error( - `Rate limit must be between ${RATE_LIMIT_PARAMS.MIN_RATE} and ${RATE_LIMIT_PARAMS.MAX_RATE} messages per epoch` - ); - } - + this.validateRateLimit(rateLimit); this.rateLimit = rateLimit; const initialRoot = rlnInstance.zerokit.getMerkleRoot(); @@ -111,9 +104,25 @@ export class RLNContract { this.contract = contract || new ethers.Contract(address, RLN_ABI, signer); this.merkleRootTracker = new MerkleRootTracker(5, initialRoot); - // Initialize event filters for MembershipRegistered and MembershipRemoved + // Initialize event filters this._membersFilter = this.contract.filters.MembershipRegistered(); - this._membersRemovedFilter = this.contract.filters.MembershipRemoved(); + this._membershipErasedFilter = this.contract.filters.MembershipErased(); + this._membersExpiredFilter = this.contract.filters.MembershipExpired(); + } + + /** + * Validates that the rate limit is within the allowed range + * @throws Error if the rate limit is outside the allowed range + */ + private validateRateLimit(rateLimit: number): void { + if ( + rateLimit < RATE_LIMIT_PARAMS.MIN_RATE || + rateLimit > RATE_LIMIT_PARAMS.MAX_RATE + ) { + throw new Error( + `Rate limit must be between ${RATE_LIMIT_PARAMS.MIN_RATE} and ${RATE_LIMIT_PARAMS.MAX_RATE} messages per epoch` + ); + } } /** @@ -182,7 +191,7 @@ export class RLNContract { this.contract.maxTotalRateLimit(), this.contract.currentTotalRateLimit() ]); - return maxTotal.sub(currentTotal).toNumber(); + return Number(maxTotal) - Number(currentTotal); } /** @@ -190,6 +199,7 @@ export class RLNContract { * @param newRateLimit The new rate limit to use */ public async setRateLimit(newRateLimit: number): Promise { + this.validateRateLimit(newRateLimit); this.rateLimit = newRateLimit; } @@ -207,11 +217,18 @@ export class RLNContract { return this._membersFilter; } - private get membersRemovedFilter(): ethers.EventFilter { - if (!this._membersRemovedFilter) { - throw Error("MembersRemoved filter was not initialized."); + private get membershipErasedFilter(): ethers.EventFilter { + if (!this._membershipErasedFilter) { + throw Error("MembershipErased filter was not initialized."); } - return this._membersRemovedFilter; + return this._membershipErasedFilter; + } + + private get membersExpiredFilter(): ethers.EventFilter { + if (!this._membersExpiredFilter) { + throw Error("MembersExpired filter was not initialized."); + } + return this._membersExpiredFilter; } public async fetchMembers( @@ -226,10 +243,19 @@ export class RLNContract { const removedMemberEvents = await queryFilter(this.contract, { fromBlock: this.deployBlock, ...options, - membersFilter: this.membersRemovedFilter + membersFilter: this.membershipErasedFilter + }); + const expiredMemberEvents = await queryFilter(this.contract, { + fromBlock: this.deployBlock, + ...options, + membersFilter: this.membersExpiredFilter }); - const events = [...registeredMemberEvents, ...removedMemberEvents]; + const events = [ + ...registeredMemberEvents, + ...removedMemberEvents, + ...expiredMemberEvents + ]; this.processEvents(rlnInstance, events); } @@ -242,8 +268,26 @@ export class RLNContract { return; } - if (evt.event === "MembershipRemoved") { - const index = evt.args.index as ethers.BigNumber; + if ( + evt.event === "MembershipErased" || + evt.event === "MembershipExpired" + ) { + let index = evt.args.index; + + if (!index) { + return; + } + + if (typeof index === "number" || typeof index === "string") { + index = ethers.BigNumber.from(index); + } else { + log.error("Index is not a number or string", { + index, + event: evt + }); + return; + } + const toRemoveVal = toRemoveTable.get(evt.blockNumber); if (toRemoveVal != undefined) { toRemoveVal.push(index.toNumber()); @@ -275,15 +319,21 @@ export class RLNContract { if (!evt.args) return; const _idCommitment = evt.args.idCommitment as string; - const index = evt.args.index as ethers.BigNumber; + let index = evt.args.index; if (!_idCommitment || !index) { return; } + if (typeof index === "number" || typeof index === "string") { + index = ethers.BigNumber.from(index); + } + const idCommitment = zeroPadLE(hexToBytes(_idCommitment), 32); rlnInstance.zerokit.insertMember(idCommitment); - this._members.set(index.toNumber(), { + + const numericIndex = index.toNumber(); + this._members.set(numericIndex, { index, idCommitment: _idCommitment }); @@ -316,7 +366,7 @@ export class RLNContract { this.membersFilter, ( _idCommitment: string, - _rateLimit: number, + _membershipRateLimit: ethers.BigNumber, _index: ethers.BigNumber, event: ethers.Event ) => { @@ -325,9 +375,22 @@ export class RLNContract { ); this.contract.on( - this.membersRemovedFilter, + this.membershipErasedFilter, ( _idCommitment: string, + _membershipRateLimit: ethers.BigNumber, + _index: ethers.BigNumber, + event: ethers.Event + ) => { + this.processEvents(rlnInstance, [event]); + } + ); + + this.contract.on( + this.membersExpiredFilter, + ( + _idCommitment: string, + _membershipRateLimit: ethers.BigNumber, _index: ethers.BigNumber, event: ethers.Event ) => { @@ -344,15 +407,45 @@ export class RLNContract { `Registering identity with rate limit: ${this.rateLimit} messages/epoch` ); + // Check if the ID commitment is already registered + const existingIndex = await this.getMemberIndex( + identity.IDCommitmentBigInt.toString() + ); + if (existingIndex) { + throw new Error( + `ID commitment is already registered with index ${existingIndex}` + ); + } + + // Check if there's enough remaining rate limit + const remainingRateLimit = await this.getRemainingTotalRateLimit(); + if (remainingRateLimit < this.rateLimit) { + throw new Error( + `Not enough remaining rate limit. Requested: ${this.rateLimit}, Available: ${remainingRateLimit}` + ); + } + + const estimatedGas = await this.contract.estimateGas.register( + identity.IDCommitmentBigInt, + this.rateLimit, + [] + ); + const gasLimit = estimatedGas.add(10000); + const txRegisterResponse: ethers.ContractTransaction = await this.contract.register( identity.IDCommitmentBigInt, this.rateLimit, [], - { gasLimit: 300000 } + { gasLimit } ); + const txRegisterReceipt = await txRegisterResponse.wait(); + if (txRegisterReceipt.status === 0) { + throw new Error("Transaction failed on-chain"); + } + const memberRegistered = txRegisterReceipt.events?.find( (event) => event.event === "MembershipRegistered" ); @@ -366,30 +459,55 @@ export class RLNContract { const decodedData: MembershipRegisteredEvent = { idCommitment: memberRegistered.args.idCommitment, - rateLimit: memberRegistered.args.rateLimit, + membershipRateLimit: memberRegistered.args.membershipRateLimit, index: memberRegistered.args.index }; log.info( `Successfully registered membership with index ${decodedData.index} ` + - `and rate limit ${decodedData.rateLimit}` + `and rate limit ${decodedData.membershipRateLimit}` ); const network = await this.contract.provider.getNetwork(); const address = this.contract.address; - const membershipId = decodedData.index.toNumber(); + const membershipId = Number(decodedData.index); return { identity, membership: { address, treeIndex: membershipId, - chainId: network.chainId + chainId: network.chainId, + rateLimit: decodedData.membershipRateLimit.toNumber() } }; } catch (error) { - log.error(`Error in registerWithIdentity: ${(error as Error).message}`); - return undefined; + if (error instanceof Error) { + const errorMessage = error.message; + log.error("registerWithIdentity - error message:", errorMessage); + log.error("registerWithIdentity - error stack:", error.stack); + + // Try to extract more specific error information + if (errorMessage.includes("CannotExceedMaxTotalRateLimit")) { + throw new Error( + "Registration failed: Cannot exceed maximum total rate limit" + ); + } else if (errorMessage.includes("InvalidIdCommitment")) { + throw new Error("Registration failed: Invalid ID commitment"); + } else if (errorMessage.includes("InvalidMembershipRateLimit")) { + throw new Error("Registration failed: Invalid membership rate limit"); + } else if (errorMessage.includes("execution reverted")) { + throw new Error( + "Contract execution reverted. Check contract requirements." + ); + } else { + throw new Error(`Error in registerWithIdentity: ${errorMessage}`); + } + } else { + throw new Error("Unknown error in registerWithIdentity", { + cause: error + }); + } } } @@ -467,25 +585,26 @@ export class RLNContract { const decodedData: MembershipRegisteredEvent = { idCommitment: memberRegistered.args.idCommitment, - rateLimit: memberRegistered.args.rateLimit, + membershipRateLimit: memberRegistered.args.membershipRateLimit, index: memberRegistered.args.index }; log.info( `Successfully registered membership with permit. Index: ${decodedData.index}, ` + - `Rate limit: ${decodedData.rateLimit}, Erased ${idCommitmentsToErase.length} commitments` + `Rate limit: ${decodedData.membershipRateLimit}, Erased ${idCommitmentsToErase.length} commitments` ); const network = await this.contract.provider.getNetwork(); const address = this.contract.address; - const membershipId = decodedData.index.toNumber(); + const membershipId = ethers.BigNumber.from(decodedData.index).toNumber(); return { identity, membership: { address, treeIndex: membershipId, - chainId: network.chainId + chainId: network.chainId, + rateLimit: decodedData.membershipRateLimit.toNumber() } }; } catch (error) { @@ -560,16 +679,9 @@ export class RLNContract { public async registerMembership( idCommitment: string, - rateLimit: number = DEFAULT_RATE_LIMIT + rateLimit: number = this.rateLimit ): Promise { - if ( - rateLimit < RATE_LIMIT_PARAMS.MIN_RATE || - rateLimit > RATE_LIMIT_PARAMS.MAX_RATE - ) { - throw new Error( - `Rate limit must be between ${RATE_LIMIT_PARAMS.MIN_RATE} and ${RATE_LIMIT_PARAMS.MAX_RATE}` - ); - } + this.validateRateLimit(rateLimit); return this.contract.register(idCommitment, rateLimit, []); } diff --git a/packages/rln/src/contract/test-setup.ts b/packages/rln/src/contract/test-setup.ts new file mode 100644 index 0000000000..dae1d26954 --- /dev/null +++ b/packages/rln/src/contract/test-setup.ts @@ -0,0 +1,86 @@ +import { hexToBytes } from "@waku/utils/bytes"; +import { ethers } from "ethers"; +import sinon from "sinon"; + +import { createRLN } from "../create.js"; +import type { IdentityCredential } from "../identity.js"; + +import { DEFAULT_RATE_LIMIT, LINEA_CONTRACT } from "./constants.js"; +import { RLNContract } from "./rln_contract.js"; + +export interface TestRLNInstance { + rlnInstance: any; + identity: IdentityCredential; + insertMemberSpy: sinon.SinonStub; +} + +/** + * Creates a test RLN instance with basic setup + */ +export async function createTestRLNInstance(): Promise { + const rlnInstance = await createRLN(); + const insertMemberSpy = sinon.stub(); + rlnInstance.zerokit.insertMember = insertMemberSpy; + + const mockSignature = + "0xdeb8a6b00a8e404deb1f52d3aa72ed7f60a2ff4484c737eedaef18a0aacb2dfb4d5d74ac39bb71fa358cf2eb390565a35b026cc6272f2010d4351e17670311c21c"; + const identity = + rlnInstance.zerokit.generateSeededIdentityCredential(mockSignature); + + return { + rlnInstance, + identity, + insertMemberSpy + }; +} + +/** + * Initializes an RLN contract with the given registry contract + */ +export async function initializeRLNContract( + rlnInstance: any, + mockedRegistryContract: ethers.Contract +): Promise { + const provider = new ethers.providers.JsonRpcProvider(); + const voidSigner = new ethers.VoidSigner(LINEA_CONTRACT.address, provider); + + const originalRegister = mockedRegistryContract.register; + (mockedRegistryContract as any).register = function (...args: any[]) { + const result = originalRegister.apply(this, args); + + if (args[0] && rlnInstance.zerokit) { + const idCommitmentBigInt = args[0]; + const idCommitmentHex = + "0x" + idCommitmentBigInt.toString(16).padStart(64, "0"); + const idCommitment = ethers.utils.zeroPad( + hexToBytes(idCommitmentHex), + 32 + ); + rlnInstance.zerokit.insertMember(idCommitment); + } + + return result; + }; + + const contract = await RLNContract.init(rlnInstance, { + address: LINEA_CONTRACT.address, + signer: voidSigner, + rateLimit: DEFAULT_RATE_LIMIT, + contract: mockedRegistryContract + }); + + return contract; +} + +/** + * Common test message data + */ +export const TEST_DATA = { + contentTopic: "/test/1/waku-message/utf8", + emptyPubsubTopic: "", + testMessage: Uint8Array.from( + "Hello World".split("").map((x) => x.charCodeAt(0)) + ), + mockSignature: + "0xdeb8a6b00a8e404deb1f52d3aa72ed7f60a2ff4484c737eedaef18a0aacb2dfb4d5d74ac39bb71fa358cf2eb390565a35b026cc6272f2010d4351e17670311c21c" +} as const; diff --git a/packages/rln/src/contract/test-utils.ts b/packages/rln/src/contract/test-utils.ts new file mode 100644 index 0000000000..9b76999fbb --- /dev/null +++ b/packages/rln/src/contract/test-utils.ts @@ -0,0 +1,179 @@ +import { hexToBytes } from "@waku/utils/bytes"; +import { expect } from "chai"; +import * as ethers from "ethers"; +import sinon from "sinon"; + +import type { IdentityCredential } from "../identity.js"; + +import { DEFAULT_RATE_LIMIT, LINEA_CONTRACT } from "./constants.js"; + +export const mockRateLimits = { + minRate: 20, + maxRate: 600, + maxTotalRate: 1200, + currentTotalRate: 500 +}; + +type MockProvider = { + getLogs: () => never[]; + getBlockNumber: () => Promise; + getNetwork: () => Promise<{ chainId: number }>; +}; + +type MockFilters = { + MembershipRegistered: () => { address: string }; + MembershipErased: () => { address: string }; + MembershipExpired: () => { address: string }; +}; + +export function createMockProvider(): MockProvider { + return { + getLogs: () => [], + getBlockNumber: () => Promise.resolve(1000), + getNetwork: () => Promise.resolve({ chainId: 11155111 }) + }; +} + +export function createMockFilters(): MockFilters { + return { + MembershipRegistered: () => ({ address: LINEA_CONTRACT.address }), + MembershipErased: () => ({ address: LINEA_CONTRACT.address }), + MembershipExpired: () => ({ address: LINEA_CONTRACT.address }) + }; +} + +type ContractOverrides = Partial<{ + filters: Record; + [key: string]: unknown; +}>; + +export function createMockRegistryContract( + overrides: ContractOverrides = {} +): ethers.Contract { + const filters = { + MembershipRegistered: () => ({ address: LINEA_CONTRACT.address }), + MembershipErased: () => ({ address: LINEA_CONTRACT.address }), + MembershipExpired: () => ({ address: LINEA_CONTRACT.address }) + }; + + const baseContract = { + minMembershipRateLimit: () => + Promise.resolve(ethers.BigNumber.from(mockRateLimits.minRate)), + maxMembershipRateLimit: () => + Promise.resolve(ethers.BigNumber.from(mockRateLimits.maxRate)), + maxTotalRateLimit: () => + Promise.resolve(ethers.BigNumber.from(mockRateLimits.maxTotalRate)), + currentTotalRateLimit: () => + Promise.resolve(ethers.BigNumber.from(mockRateLimits.currentTotalRate)), + queryFilter: () => [], + provider: createMockProvider(), + filters, + on: () => ({}), + removeAllListeners: () => ({}), + register: () => ({ + wait: () => + Promise.resolve({ + events: [mockRLNRegisteredEvent()] + }) + }), + estimateGas: { + register: () => Promise.resolve(ethers.BigNumber.from(100000)) + }, + functions: { + register: () => Promise.resolve() + }, + getMemberIndex: () => Promise.resolve(null), + interface: { + getEvent: (eventName: string) => ({ + name: eventName, + format: () => {} + }) + }, + address: LINEA_CONTRACT.address + }; + + // Merge overrides while preserving filters + const merged = { + ...baseContract, + ...overrides, + filters: { ...filters, ...(overrides.filters || {}) } + }; + + return merged as unknown as ethers.Contract; +} + +export function mockRLNRegisteredEvent(idCommitment?: string): ethers.Event { + return { + args: { + idCommitment: + idCommitment || + "0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef", + membershipRateLimit: ethers.BigNumber.from(DEFAULT_RATE_LIMIT), + index: ethers.BigNumber.from(1) + }, + event: "MembershipRegistered" + } as unknown as ethers.Event; +} + +export function formatIdCommitment(idCommitmentBigInt: bigint): string { + return "0x" + idCommitmentBigInt.toString(16).padStart(64, "0"); +} + +export function createRegisterStub( + identity: IdentityCredential +): sinon.SinonStub { + return sinon.stub().callsFake(() => ({ + wait: () => + Promise.resolve({ + events: [ + { + event: "MembershipRegistered", + args: { + idCommitment: formatIdCommitment(identity.IDCommitmentBigInt), + membershipRateLimit: ethers.BigNumber.from(DEFAULT_RATE_LIMIT), + index: ethers.BigNumber.from(1) + } + } + ] + }) + })); +} + +export function verifyRegistration( + decryptedCredentials: any, + identity: IdentityCredential, + registerStub: sinon.SinonStub, + insertMemberSpy: sinon.SinonStub +): void { + if (!decryptedCredentials) { + throw new Error("Decrypted credentials should not be undefined"); + } + + // Verify registration call + expect( + registerStub.calledWith( + sinon.match.same(identity.IDCommitmentBigInt), + sinon.match.same(DEFAULT_RATE_LIMIT), + sinon.match.array, + sinon.match.object + ) + ).to.be.true; + + // Verify credential properties + expect(decryptedCredentials).to.have.property("identity"); + expect(decryptedCredentials).to.have.property("membership"); + expect(decryptedCredentials.membership).to.include({ + address: LINEA_CONTRACT.address, + treeIndex: 1 + }); + + // Verify member insertion + const expectedIdCommitment = ethers.utils.zeroPad( + hexToBytes(formatIdCommitment(identity.IDCommitmentBigInt)), + 32 + ); + expect(insertMemberSpy.callCount).to.equal(1); + expect(insertMemberSpy.getCall(0).args[0]).to.deep.equal( + expectedIdCommitment + ); +} diff --git a/packages/rln/src/index.ts b/packages/rln/src/index.ts index 6d45b3d280..da12a61ca3 100644 --- a/packages/rln/src/index.ts +++ b/packages/rln/src/index.ts @@ -1,6 +1,6 @@ import { RLNDecoder, RLNEncoder } from "./codec.js"; import { RLN_ABI } from "./contract/abi.js"; -import { RLNContract, SEPOLIA_CONTRACT } from "./contract/index.js"; +import { LINEA_CONTRACT, RLNContract } from "./contract/index.js"; import { createRLN } from "./create.js"; import { IdentityCredential } from "./identity.js"; import { Keystore } from "./keystore/index.js"; @@ -19,7 +19,18 @@ export { RLNDecoder, MerkleRootTracker, RLNContract, - SEPOLIA_CONTRACT, + LINEA_CONTRACT, extractMetaMaskSigner, RLN_ABI }; + +export type { + DecryptedCredentials, + EncryptedCredentials, + Keccak256Hash, + KeystoreEntity, + MembershipHash, + MembershipInfo, + Password, + Sha256Hash +} from "./keystore/types.js"; diff --git a/packages/rln/src/keystore/keystore.spec.ts b/packages/rln/src/keystore/keystore.spec.ts index 322c3db688..ddbb233cb7 100644 --- a/packages/rln/src/keystore/keystore.spec.ts +++ b/packages/rln/src/keystore/keystore.spec.ts @@ -231,7 +231,8 @@ describe("Keystore", () => { const membership = { chainId: "0xAA36A7", treeIndex: 8, - address: "0x8e1F3742B987d8BA376c0CBbD7357fE1F003ED71" + address: "0x8e1F3742B987d8BA376c0CBbD7357fE1F003ED71", + rateLimit: undefined } as unknown as MembershipInfo; const store = Keystore.create(); @@ -246,6 +247,11 @@ describe("Keystore", () => { expectedHash, DEFAULT_PASSWORD ); + + if (!actualCredentials) { + throw new Error("Failed to retrieve credentials"); + } + expect(actualCredentials).to.deep.equalInAnyOrder({ identity, membership @@ -276,7 +282,8 @@ describe("Keystore", () => { const membership = { chainId: "0xAA36A7", treeIndex: 8, - address: "0x8e1F3742B987d8BA376c0CBbD7357fE1F003ED71" + address: "0x8e1F3742B987d8BA376c0CBbD7357fE1F003ED71", + rateLimit: undefined } as unknown as MembershipInfo; const store = Keystore.fromObject(NWAKU_KEYSTORE as any); diff --git a/packages/rln/src/keystore/keystore.ts b/packages/rln/src/keystore/keystore.ts index 84836186bf..f39bfaf8a0 100644 --- a/packages/rln/src/keystore/keystore.ts +++ b/packages/rln/src/keystore/keystore.ts @@ -274,7 +274,8 @@ export class Keystore { membership: { treeIndex: _.get(obj, "treeIndex"), chainId: _.get(obj, "membershipContract.chainId"), - address: _.get(obj, "membershipContract.address") + address: _.get(obj, "membershipContract.address"), + rateLimit: _.get(obj, "membershipContract.rateLimit") } }; } catch (err) { diff --git a/packages/rln/src/keystore/types.ts b/packages/rln/src/keystore/types.ts index 9d8e86a891..a14867c1e1 100644 --- a/packages/rln/src/keystore/types.ts +++ b/packages/rln/src/keystore/types.ts @@ -11,6 +11,7 @@ export type MembershipInfo = { chainId: number; address: string; treeIndex: number; + rateLimit: number; }; export type KeystoreEntity = { diff --git a/packages/rln/src/rln.ts b/packages/rln/src/rln.ts index 103be43b4e..e908fa01fe 100644 --- a/packages/rln/src/rln.ts +++ b/packages/rln/src/rln.ts @@ -16,7 +16,7 @@ import { type RLNEncoder } from "./codec.js"; import { DEFAULT_RATE_LIMIT } from "./contract/constants.js"; -import { RLNContract, SEPOLIA_CONTRACT } from "./contract/index.js"; +import { LINEA_CONTRACT, RLNContract } from "./contract/index.js"; import { IdentityCredential } from "./identity.js"; import { Keystore } from "./keystore/index.js"; import type { @@ -108,7 +108,7 @@ type StartRLNOptions = { */ signer?: ethers.Signer; /** - * If not set - will use default SEPOLIA_CONTRACT address. + * If not set - will use default LINEA_CONTRACT address. */ address?: string; /** @@ -190,10 +190,10 @@ export class RLNInstance { const address = credentials?.membership.address || options.address || - SEPOLIA_CONTRACT.address; + LINEA_CONTRACT.address; - if (address === SEPOLIA_CONTRACT.address) { - chainId = SEPOLIA_CONTRACT.chainId; + if (address === LINEA_CONTRACT.address) { + chainId = LINEA_CONTRACT.chainId; } const signer = options.signer || (await extractMetaMaskSigner());