diff --git a/.cspell.json b/.cspell.json index e6c6f1fa0a..c53d7fe1e4 100644 --- a/.cspell.json +++ b/.cspell.json @@ -132,7 +132,9 @@ "upgrader", "vacp", "varint", + "viem", "vkey", + "wagmi", "waku", "wakuconnect", "wakunode", diff --git a/package-lock.json b/package-lock.json index 0f5db83b83..673ed6a631 100644 --- a/package-lock.json +++ b/package-lock.json @@ -56,7 +56,6 @@ "version": "1.11.1", "resolved": "https://registry.npmjs.org/@adraffy/ens-normalize/-/ens-normalize-1.11.1.tgz", "integrity": "sha512-nhCBV3quEgesuf7c7KYfperqSS14T8bYuvJ8PcLJp6znkZpFc0AuW4qBtr8eKVyPPe/8RSr7sglCWPU5eaxwKQ==", - "dev": true, "license": "MIT" }, "node_modules/@ampproject/remapping": { @@ -2661,164 +2660,6 @@ "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "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==", - "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/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" - } - }, - "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==", - "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/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" - } - }, - "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==", - "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/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" - } - }, - "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==", - "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/bignumber": "^5.8.0", - "@ethersproject/bytes": "^5.8.0", - "@ethersproject/keccak256": "^5.8.0", - "@ethersproject/logger": "^5.8.0", - "@ethersproject/rlp": "^5.8.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==", - "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.8.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==", - "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.8.0", - "@ethersproject/properties": "^5.8.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==", - "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.8.0", - "@ethersproject/logger": "^5.8.0", - "bn.js": "^5.2.1" - } - }, "node_modules/@ethersproject/bytes": { "version": "5.8.0", "resolved": "https://registry.npmjs.org/@ethersproject/bytes/-/bytes-5.8.0.tgz", @@ -2838,161 +2679,6 @@ "@ethersproject/logger": "^5.8.0" } }, - "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==", - "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/bignumber": "^5.8.0" - } - }, - "node_modules/@ethersproject/contracts": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/@ethersproject/contracts/-/contracts-5.8.0.tgz", - "integrity": "sha512-0eFjGz9GtuAi6MZwhb4uvUM216F38xiuR0yYCjKJpNfSEy4HUM8hvqqBj9Jmm0IUz8l0xKEhWwLIhPgxNY0yvQ==", - "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/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" - } - }, - "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==", - "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/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" - } - }, - "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==", - "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/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" - } - }, - "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==", - "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/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", - "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==", - "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.8.0", - "js-sha3": "0.8.0" - } - }, "node_modules/@ethersproject/logger": { "version": "5.8.0", "resolved": "https://registry.npmjs.org/@ethersproject/logger/-/logger-5.8.0.tgz", @@ -3009,143 +2695,6 @@ ], "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==", - "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.8.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==", - "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.8.0", - "@ethersproject/sha2": "^5.8.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==", - "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.8.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==", - "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/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", - "bech32": "1.1.4", - "ws": "8.18.0" - } - }, - "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==", - "license": "MIT", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { - "optional": true - } - } - }, - "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==", - "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.8.0", - "@ethersproject/logger": "^5.8.0" - } - }, "node_modules/@ethersproject/rlp": { "version": "5.8.0", "resolved": "https://registry.npmjs.org/@ethersproject/rlp/-/rlp-5.8.0.tgz", @@ -3166,223 +2715,6 @@ "@ethersproject/logger": "^5.8.0" } }, - "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==", - "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.8.0", - "@ethersproject/logger": "^5.8.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==", - "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.8.0", - "@ethersproject/logger": "^5.8.0", - "@ethersproject/properties": "^5.8.0", - "bn.js": "^5.2.1", - "elliptic": "6.6.1", - "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==", - "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/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" - } - }, - "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==", - "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.8.0", - "@ethersproject/constants": "^5.8.0", - "@ethersproject/logger": "^5.8.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==", - "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/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" - } - }, - "node_modules/@ethersproject/units": { - "version": "5.8.0", - "resolved": "https://registry.npmjs.org/@ethersproject/units/-/units-5.8.0.tgz", - "integrity": "sha512-lxq0CAnc5kMGIiWW4Mr041VT8IhNM+Pn5T3haO74XZWFulk7wH1Gv64HqE96hT4a7iiNMdOCFEBgaxWuk8ETKQ==", - "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/bignumber": "^5.8.0", - "@ethersproject/constants": "^5.8.0", - "@ethersproject/logger": "^5.8.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==", - "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/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" - } - }, - "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==", - "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/base64": "^5.8.0", - "@ethersproject/bytes": "^5.8.0", - "@ethersproject/logger": "^5.8.0", - "@ethersproject/properties": "^5.8.0", - "@ethersproject/strings": "^5.8.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==", - "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.8.0", - "@ethersproject/hash": "^5.8.0", - "@ethersproject/logger": "^5.8.0", - "@ethersproject/properties": "^5.8.0", - "@ethersproject/strings": "^5.8.0" - } - }, "node_modules/@fastify/busboy": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", @@ -6817,7 +6149,7 @@ "version": "15.7.15", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/@types/qs": { @@ -6838,7 +6170,7 @@ "version": "18.3.24", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.24.tgz", "integrity": "sha512-0dLEBsA1kI3OezMBF8nSsb7Nk19ZnsyE1LLhB8r27KbgU5H4pvuqZLdtE+aUkJVoXgTVuA+iLIwmZ0TuK4tx6A==", - "dev": true, + "devOptional": true, "license": "MIT", "dependencies": { "@types/prop-types": "*", @@ -7651,6 +6983,39 @@ "url": "https://github.com/sponsors/colinhacks" } }, + "node_modules/@wagmi/core": { + "version": "2.22.1", + "resolved": "https://registry.npmjs.org/@wagmi/core/-/core-2.22.1.tgz", + "integrity": "sha512-cG/xwQWsBEcKgRTkQVhH29cbpbs/TdcUJVFXCyri3ZknxhMyGv0YEjTcrNpRgt2SaswL1KrvslSNYKKo+5YEAg==", + "license": "MIT", + "dependencies": { + "eventemitter3": "5.0.1", + "mipd": "0.0.7", + "zustand": "5.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/wevm" + }, + "peerDependencies": { + "@tanstack/query-core": ">=5.0.0", + "typescript": ">=5.0.4", + "viem": "2.x" + }, + "peerDependenciesMeta": { + "@tanstack/query-core": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/@wagmi/core/node_modules/eventemitter3": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "license": "MIT" + }, "node_modules/@waku/browser-tests": { "resolved": "packages/browser-tests", "link": true @@ -7963,7 +7328,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.1.1.tgz", "integrity": "sha512-Loe5/6tAgsBukY95eGaPSDmQHIjRZYQq8PB1MpsNccDIK8WiV+Uw6WzaIXipvaxTEL2yEB0OpEaQv3gs8pkS9Q==", - "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/wevm" @@ -9608,12 +8972,6 @@ "integrity": "sha512-Xz4Nm9c+LiBHhDR5bDLnNzmj6+5F+cyEAWPMkbs2awq/dYazR/efelZzUAjB/y3kNHL+uzkHvxVVpaOfGCPV7A==", "license": "Apache-2.0" }, - "node_modules/aes-js": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/aes-js/-/aes-js-3.0.0.tgz", - "integrity": "sha512-H7wUZRn8WpTq9jocdxQ2c8x2sKo9ZVmzfRE13GiNJXfp7NcKYEdvl3vspKjXox6RIG2VtaRe4JFvxG4rqp2Zuw==", - "license": "MIT" - }, "node_modules/agent-base": { "version": "7.1.3", "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", @@ -10584,12 +9942,6 @@ "tweetnacl": "^0.14.3" } }, - "node_modules/bech32": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz", - "integrity": "sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==", - "license": "MIT" - }, "node_modules/before-after-hook": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-4.0.0.tgz", @@ -10627,12 +9979,6 @@ "dev": true, "license": "MIT" }, - "node_modules/bn.js": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.2.tgz", - "integrity": "sha512-v2YAxEmKaBLahNwE1mjp4WON6huMNeuDvagFZW+ASCuA/ku0bXR9hSMw0XpiqMoA3+rmnyck/tPRSFQkoC9Cuw==", - "license": "MIT" - }, "node_modules/body-parser": { "version": "1.20.3", "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", @@ -10707,12 +10053,6 @@ "node": ">=8" } }, - "node_modules/brorand": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz", - "integrity": "sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==", - "license": "MIT" - }, "node_modules/browser-stdout": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", @@ -12484,7 +11824,7 @@ "version": "3.1.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "dev": true, + "devOptional": true, "license": "MIT" }, "node_modules/custom-event": { @@ -13655,27 +12995,6 @@ "node": ">=0.10.0" } }, - "node_modules/elliptic": { - "version": "6.6.1", - "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.1.tgz", - "integrity": "sha512-RaddvvMatK2LJHqFJ+YA4WysVN5Ita9E35botqIYspQ4TkRAlCicdzKOjlyv/1Za5RyTNn7di//eEV0uTAfe3g==", - "license": "MIT", - "dependencies": { - "bn.js": "^4.11.9", - "brorand": "^1.1.0", - "hash.js": "^1.0.0", - "hmac-drbg": "^1.0.1", - "inherits": "^2.0.4", - "minimalistic-assert": "^1.0.1", - "minimalistic-crypto-utils": "^1.0.1" - } - }, - "node_modules/elliptic/node_modules/bn.js": { - "version": "4.12.2", - "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.2.tgz", - "integrity": "sha512-n4DSx829VRTRByMRGdjQ9iqsN0Bh4OolPsFnaZBLcbi8iXcB+kJ9s7EnRt4wILZNV3kPLHkRVfOc/HvhC3ovDw==", - "license": "MIT" - }, "node_modules/email-addresses": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/email-addresses/-/email-addresses-5.0.0.tgz", @@ -15206,54 +14525,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", @@ -16754,16 +16025,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/hash.js": { - "version": "1.1.7", - "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz", - "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==", - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "minimalistic-assert": "^1.0.1" - } - }, "node_modules/hasha": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz", @@ -16843,17 +16104,6 @@ "node": "*" } }, - "node_modules/hmac-drbg": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz", - "integrity": "sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==", - "license": "MIT", - "dependencies": { - "hash.js": "^1.0.3", - "minimalistic-assert": "^1.0.0", - "minimalistic-crypto-utils": "^1.0.1" - } - }, "node_modules/homedir-polyfill": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", @@ -18099,7 +17349,6 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/isows/-/isows-1.0.7.tgz", "integrity": "sha512-I1fSfDCZL5P0v33sVqeTDSpcstAg/N+wF5HS033mogOVIp4B+oHC7oOCsA3axAbBSGTJ8QubbNmnIRN/h8U7hg==", - "dev": true, "funding": [ { "type": "github", @@ -21386,18 +20635,6 @@ "node": ">=4" } }, - "node_modules/minimalistic-assert": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", - "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==", - "license": "ISC" - }, - "node_modules/minimalistic-crypto-utils": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz", - "integrity": "sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==", - "license": "MIT" - }, "node_modules/minimatch": { "version": "9.0.3", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", @@ -21464,6 +20701,26 @@ "node": ">=16 || 14 >=14.17" } }, + "node_modules/mipd": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mipd/-/mipd-0.0.7.tgz", + "integrity": "sha512-aAPZPNDQ3uMTdKbuO2YmAw2TxLHO0moa4YKAyETM/DTj5FloZo+a+8tU+iv4GmW+sOxKLSRwcSFuczk+Cpt6fg==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/wagmi-dev" + } + ], + "license": "MIT", + "peerDependencies": { + "typescript": ">=5.0.4" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/mitt": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", @@ -25806,7 +25063,6 @@ "version": "0.9.6", "resolved": "https://registry.npmjs.org/ox/-/ox-0.9.6.tgz", "integrity": "sha512-8SuCbHPvv2eZLYXrNmC0EC12rdzXQLdhnOMlHDW2wiCPLxBrOOJwX5L5E61by+UjTPOryqQiRSnjIKCI+GykKg==", - "dev": true, "funding": [ { "type": "github", @@ -25837,7 +25093,6 @@ "version": "1.9.1", "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.1.tgz", "integrity": "sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA==", - "dev": true, "license": "MIT", "dependencies": { "@noble/hashes": "1.8.0" @@ -25853,7 +25108,6 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", - "dev": true, "license": "MIT" }, "node_modules/p-cancelable": { @@ -29392,12 +28646,6 @@ "dev": true, "license": "MIT" }, - "node_modules/scrypt-js": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/scrypt-js/-/scrypt-js-3.0.1.tgz", - "integrity": "sha512-cdwTTnqPu0Hyvf5in5asVdZocVDTNRmR7XEcJuIzMjJeSHybHl7vpB66AzwTaIg6CLSbtjcxc8fqcySfnTkccA==", - "license": "MIT" - }, "node_modules/semantic-release": { "version": "24.2.5", "resolved": "https://registry.npmjs.org/semantic-release/-/semantic-release-24.2.5.tgz", @@ -33256,10 +32504,9 @@ } }, "node_modules/viem": { - "version": "2.38.3", - "resolved": "https://registry.npmjs.org/viem/-/viem-2.38.3.tgz", - "integrity": "sha512-By2TutLv07iNHHtWqHHzjGipevYsfGqT7KQbGEmqLco1qTJxKnvBbSviqiu6/v/9REV6Q/FpmIxf2Z7/l5AbcQ==", - "dev": true, + "version": "2.38.4", + "resolved": "https://registry.npmjs.org/viem/-/viem-2.38.4.tgz", + "integrity": "sha512-qnyPNg6Lz1EEC86si/1dq7GlOyZVFHSgAW+p8Q31R5idnAYCOdTM2q5KLE4/ykMeMXzY0bnp5MWTtR/wjCtWmQ==", "funding": [ { "type": "github", @@ -33290,7 +32537,6 @@ "version": "1.9.1", "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.9.1.tgz", "integrity": "sha512-k11yZxZg+t+gWvBbIswW0yoJlu8cHOC7dhunwOzoWH/mXGBiYyR4YY6hAEK/3EUs4UpB8la1RfdRpeGsFHkWsA==", - "dev": true, "license": "MIT", "dependencies": { "@noble/hashes": "1.8.0" @@ -33306,7 +32552,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/abitype/-/abitype-1.1.0.tgz", "integrity": "sha512-6Vh4HcRxNMLA0puzPjM5GBgT4aAcFGKZzSgAXvuZ27shJP6NEpielTuqbBmZILR5/xd0PizkBGy5hReKz9jl5A==", - "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/wevm" @@ -33328,7 +32573,6 @@ "version": "8.18.3", "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz", "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==", - "dev": true, "license": "MIT", "engines": { "node": ">=10.0.0" @@ -34136,12 +33380,41 @@ "version": "3.25.76", "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", - "dev": true, + "devOptional": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/colinhacks" } }, + "node_modules/zustand": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/zustand/-/zustand-5.0.0.tgz", + "integrity": "sha512-LE+VcmbartOPM+auOjCCLQOsQ05zUTp8RkgwRzefUk+2jISdMMFnxvyTjA4YNWr5ZGXYbVsEMZosttuxUBkojQ==", + "license": "MIT", + "engines": { + "node": ">=12.20.0" + }, + "peerDependencies": { + "@types/react": ">=18.0.0", + "immer": ">=9.0.6", + "react": ">=18.0.0", + "use-sync-external-store": ">=1.2.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "immer": { + "optional": true + }, + "react": { + "optional": true + }, + "use-sync-external-store": { + "optional": true + } + } + }, "node_modules/zwitch": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", @@ -34758,12 +34031,6 @@ "@esbuild/win32-x64": "0.21.5" } }, - "packages/browser-tests/node_modules/js-sha3": { - "version": "0.9.3", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.9.3.tgz", - "integrity": "sha512-BcJPCQeLg6WjEx3FE591wVAevlli8lxsxm9/FzV4HXkV49TmBH38Yvrpce6fjbADGMKFrBMGTqrVz3qPIZ88Gg==", - "license": "MIT" - }, "packages/browser-tests/node_modules/undici-types": { "version": "6.19.8", "dev": true, @@ -34934,10 +34201,6 @@ } } }, - "packages/enr/node_modules/js-sha3": { - "version": "0.9.3", - "license": "MIT" - }, "packages/headless-tests": { "name": "@waku/headless-tests", "version": "0.1.0", @@ -35006,10 +34269,6 @@ "node": ">=22" } }, - "packages/message-encryption/node_modules/js-sha3": { - "version": "0.9.3", - "license": "MIT" - }, "packages/proto": { "name": "@waku/proto", "version": "0.0.15", @@ -35473,6 +34732,7 @@ "dependencies": { "@chainsafe/bls-keystore": "3.0.0", "@noble/hashes": "^1.2.0", + "@wagmi/core": "^2.22.1", "@waku/core": "^0.0.40", "@waku/utils": "^0.0.27", "@waku/zerokit-rln-wasm": "^0.2.1", @@ -35481,10 +34741,10 @@ "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" + "uuid": "^11.0.5", + "viem": "^2.38.4" }, "devDependencies": { "@rollup/plugin-commonjs": "^25.0.7", @@ -35522,6 +34782,89 @@ "@types/deep-eql": "*" } }, + "packages/rln/node_modules/@waku/message-encryption": { + "version": "0.0.37", + "resolved": "https://registry.npmjs.org/@waku/message-encryption/-/message-encryption-0.0.37.tgz", + "integrity": "sha512-8WmDxVnitqzxWrKRHdmHmOKk81LBh0OE9uLFzBNxirmH9G4uDx0va3+S4lazgCQ4kT0zKrsN8VldX0BfePTVDQ==", + "dev": true, + "license": "MIT OR Apache-2.0", + "dependencies": { + "@noble/secp256k1": "^1.7.1", + "@waku/core": "0.0.39", + "@waku/interfaces": "0.0.34", + "@waku/proto": "0.0.14", + "@waku/utils": "0.0.27", + "debug": "^4.3.4", + "js-sha3": "^0.9.2", + "uint8arrays": "^5.0.1" + }, + "engines": { + "node": ">=22" + } + }, + "packages/rln/node_modules/@waku/message-encryption/node_modules/@waku/core": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@waku/core/-/core-0.0.39.tgz", + "integrity": "sha512-Vgb52md4GOzM5z9xfULzjN2tvVHKszFmj5zc2mVDoIgySH4cFBgDTHtVtGEwrFRFWadWYKBtpKBdmG3X+W7SNA==", + "dev": true, + "license": "MIT OR Apache-2.0", + "dependencies": { + "@libp2p/ping": "2.0.35", + "@noble/hashes": "^1.3.2", + "@waku/enr": "^0.0.33", + "@waku/interfaces": "0.0.34", + "@waku/proto": "0.0.14", + "@waku/utils": "0.0.27", + "debug": "^4.3.4", + "it-all": "^3.0.4", + "it-length-prefixed": "^9.0.4", + "it-pipe": "^3.0.1", + "uint8arraylist": "^2.4.3", + "uuid": "^9.0.0" + }, + "engines": { + "node": ">=22" + }, + "peerDependencies": { + "@multiformats/multiaddr": "^12.0.0", + "libp2p": "2.8.11" + }, + "peerDependenciesMeta": { + "@multiformats/multiaddr": { + "optional": true + }, + "libp2p": { + "optional": true + } + } + }, + "packages/rln/node_modules/@waku/message-encryption/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "dev": true, + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "packages/rln/node_modules/@waku/proto": { + "version": "0.0.14", + "resolved": "https://registry.npmjs.org/@waku/proto/-/proto-0.0.14.tgz", + "integrity": "sha512-8zKVHrKzzKQfZBVnpSmJ6G8H1Zd4Gqms1tj3L6K2WCE/NQDR8wJtFwziab3dJ/5rKUTjfPAWFJ57RN97ltzxGA==", + "dev": true, + "license": "MIT OR Apache-2.0", + "dependencies": { + "protons-runtime": "^5.4.0" + }, + "engines": { + "node": ">=22" + } + }, "packages/rln/node_modules/assertion-error": { "version": "2.0.1", "license": "MIT", diff --git a/packages/rln/generate_contract_abi.sh b/packages/rln/generate_contract_abi.sh new file mode 100755 index 0000000000..385b56f2b0 --- /dev/null +++ b/packages/rln/generate_contract_abi.sh @@ -0,0 +1,43 @@ +#!/bin/bash + +set -e + +# Script to generate contract ABIs from waku-rlnv2-contract +# Usage: ./generate_contract_abi.sh + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +CONTRACT_DIR="$SCRIPT_DIR/waku-rlnv2-contract" +REPO_URL="git@github.com:waku-org/waku-rlnv2-contract.git" + +echo "📦 Setting up waku-rlnv2-contract..." + +# Remove existing directory if it exists +if [ -d "$CONTRACT_DIR" ]; then + echo "🗑️ Removing existing waku-rlnv2-contract directory..." + rm -rf "$CONTRACT_DIR" +fi + +# Clone the repository +echo "📥 Cloning waku-rlnv2-contract..." +git clone "$REPO_URL" "$CONTRACT_DIR" + +# Navigate to contract directory +cd "$CONTRACT_DIR" + +# Install dependencies +echo "📦 Installing dependencies..." +npm install + +# Build contracts with Foundry +echo "🔨 Building contracts with Foundry..." +forge build + +# Navigate back to rln package +cd "$SCRIPT_DIR" + +# Generate ABIs with wagmi +echo "⚙️ Generating ABIs with wagmi..." +npx wagmi generate + +echo "✅ Contract ABIs generated successfully!" +echo "📄 Output: src/contract/wagmi/generated.ts" diff --git a/packages/rln/package.json b/packages/rln/package.json index 1c3e524ad4..71fbc8f957 100644 --- a/packages/rln/package.json +++ b/packages/rln/package.json @@ -56,13 +56,13 @@ "@rollup/plugin-node-resolve": "^15.2.3", "@types/chai": "^5.0.1", "@types/chai-spies": "^1.0.6", - "@waku/interfaces": "0.0.34", "@types/deep-equal-in-any-order": "^1.0.4", "@types/lodash": "^4.17.15", "@types/sinon": "^17.0.3", - "@waku/build-utils": "^1.0.0", - "@waku/message-encryption": "^0.0.37", "@wagmi/cli": "^2.7.0", + "@waku/build-utils": "^1.0.0", + "@waku/interfaces": "0.0.34", + "@waku/message-encryption": "^0.0.37", "deep-equal-in-any-order": "^2.0.6", "fast-check": "^3.23.2", "rollup-plugin-copy": "^3.5.0" @@ -79,18 +79,19 @@ ], "dependencies": { "@chainsafe/bls-keystore": "3.0.0", + "@noble/hashes": "^1.2.0", + "@wagmi/core": "^2.22.1", "@waku/core": "^0.0.40", "@waku/utils": "^0.0.27", - "@noble/hashes": "^1.2.0", "@waku/zerokit-rln-wasm": "^0.2.1", - "ethereum-cryptography": "^3.1.0", - "ethers": "^5.7.2", - "lodash": "^4.17.21", - "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" + "ethereum-cryptography": "^3.1.0", + "lodash": "^4.17.21", + "sinon": "^19.0.2", + "uuid": "^11.0.5", + "viem": "^2.38.4" } } diff --git a/packages/rln/setup-contract-abi.sh b/packages/rln/setup-contract-abi.sh deleted file mode 100755 index 73061023cc..0000000000 --- a/packages/rln/setup-contract-abi.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/bash -set -e - -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -SUBMODULE_DIR="$SCRIPT_DIR/waku-rlnv2-contract" - -echo "Setting up waku-rlnv2-contract submodule..." - -# Initialize submodule if needed -if [ ! -d "$SUBMODULE_DIR/.git" ]; then - echo "Initializing submodule..." - cd "$SCRIPT_DIR/../.." - git submodule update --init --recursive packages/rln/waku-rlnv2-contract -fi - -# Install dependencies -echo "Installing submodule dependencies..." -cd "$SUBMODULE_DIR" -npm install - -# Build contracts with Foundry -echo "Building contracts with Foundry..." -forge build - -# Generate ABIs -echo "Generating contract ABIs..." -cd "$SCRIPT_DIR" -npx wagmi generate - -echo "✅ Contract ABI setup complete!" diff --git a/packages/rln/src/contract/price_calculator.spec.ts b/packages/rln/src/contract/price_calculator.spec.ts index 2b36585509..4f6b414664 100644 --- a/packages/rln/src/contract/price_calculator.spec.ts +++ b/packages/rln/src/contract/price_calculator.spec.ts @@ -1,28 +1,40 @@ import { expect, use } from "chai"; import chaiAsPromised from "chai-as-promised"; -import { ethers } from "ethers"; import sinon from "sinon"; +import { PublicClient } from "viem"; import { RLNBaseContract } from "./rln_base_contract.js"; use(chaiAsPromised); -function createMockRLNBaseContract(provider: any): RLNBaseContract { +function createMockRLNBaseContract( + mockContract: any, + mockPublicClient: PublicClient +): RLNBaseContract { const dummy = Object.create(RLNBaseContract.prototype); - dummy.contract = { provider }; + dummy.contract = mockContract; + dummy.publicClient = mockPublicClient; return dummy as RLNBaseContract; } describe("RLNBaseContract.getPriceForRateLimit (unit)", function () { - let provider: any; - let calculateStub: sinon.SinonStub; - let mockContractFactory: any; + let mockContract: any; + let mockPublicClient: any; + let priceCalculatorReadStub: sinon.SinonStub; + let readContractStub: sinon.SinonStub; beforeEach(() => { - provider = {}; - calculateStub = sinon.stub(); - mockContractFactory = function () { - return { calculate: calculateStub }; + priceCalculatorReadStub = sinon.stub(); + readContractStub = sinon.stub(); + + mockContract = { + read: { + priceCalculator: priceCalculatorReadStub + } + }; + + mockPublicClient = { + readContract: readContractStub }; }); @@ -32,35 +44,53 @@ describe("RLNBaseContract.getPriceForRateLimit (unit)", function () { it("returns token and price for valid calculate", async () => { const fakeToken = "0x1234567890abcdef1234567890abcdef12345678"; - const fakePrice = ethers.BigNumber.from(42); - calculateStub.resolves([fakeToken, fakePrice]); + const fakePrice = 42n; + const priceCalculatorAddress = "0xabcdef1234567890abcdef1234567890abcdef12"; + + priceCalculatorReadStub.resolves(priceCalculatorAddress); + readContractStub.resolves([fakeToken, fakePrice]); + + const rlnBase = createMockRLNBaseContract(mockContract, mockPublicClient); + const result = await rlnBase.getPriceForRateLimit(20); - const rlnBase = createMockRLNBaseContract(provider); - const result = await rlnBase.getPriceForRateLimit(20, mockContractFactory); expect(result.token).to.equal(fakeToken); - expect(result.price).to.not.be.null; - if (result.price) { - expect(result.price.eq(fakePrice)).to.be.true; - } - expect(calculateStub.calledOnceWith(20)).to.be.true; + expect(result.price).to.equal(fakePrice); + expect(priceCalculatorReadStub.calledOnce).to.be.true; + expect(readContractStub.calledOnce).to.be.true; + + const readContractCall = readContractStub.getCall(0); + expect(readContractCall.args[0]).to.deep.include({ + address: priceCalculatorAddress, + functionName: "calculate", + args: [20] + }); }); it("throws if calculate throws", async () => { - calculateStub.rejects(new Error("fail")); + const priceCalculatorAddress = "0xabcdef1234567890abcdef1234567890abcdef12"; - const rlnBase = createMockRLNBaseContract(provider); - await expect( - rlnBase.getPriceForRateLimit(20, mockContractFactory) - ).to.be.rejectedWith("fail"); - expect(calculateStub.calledOnceWith(20)).to.be.true; + priceCalculatorReadStub.resolves(priceCalculatorAddress); + readContractStub.rejects(new Error("fail")); + + const rlnBase = createMockRLNBaseContract(mockContract, mockPublicClient); + await expect(rlnBase.getPriceForRateLimit(20)).to.be.rejectedWith("fail"); + + expect(priceCalculatorReadStub.calledOnce).to.be.true; + expect(readContractStub.calledOnce).to.be.true; }); - it("throws if calculate returns malformed data", async () => { - calculateStub.resolves([null, null]); + it("returns null values if calculate returns malformed data", async () => { + const priceCalculatorAddress = "0xabcdef1234567890abcdef1234567890abcdef12"; + + priceCalculatorReadStub.resolves(priceCalculatorAddress); + readContractStub.resolves([null, null]); + + const rlnBase = createMockRLNBaseContract(mockContract, mockPublicClient); + const result = await rlnBase.getPriceForRateLimit(20); - const rlnBase = createMockRLNBaseContract(provider); - const result = await rlnBase.getPriceForRateLimit(20, mockContractFactory); expect(result.token).to.be.null; expect(result.price).to.be.null; + expect(priceCalculatorReadStub.calledOnce).to.be.true; + expect(readContractStub.calledOnce).to.be.true; }); }); diff --git a/packages/rln/src/contract/rln_base_contract.ts b/packages/rln/src/contract/rln_base_contract.ts index db6481ec76..211f2fba80 100644 --- a/packages/rln/src/contract/rln_base_contract.ts +++ b/packages/rln/src/contract/rln_base_contract.ts @@ -1,70 +1,74 @@ import { Logger } from "@waku/utils"; -import { ethers } from "ethers"; +import { + type Address, + decodeEventLog, + getContract, + GetContractEventsReturnType, + GetContractReturnType, + type Hash, + PublicClient, + WalletClient +} from "viem"; import { IdentityCredential } from "../identity.js"; import { DecryptedCredentials } from "../keystore/types.js"; import { DEFAULT_RATE_LIMIT, - PRICE_CALCULATOR_CONTRACT, RATE_LIMIT_PARAMS, RLN_CONTRACT } from "./constants.js"; import { - CustomQueryOptions, FetchMembersOptions, Member, MembershipInfo, - MembershipRegisteredEvent, MembershipState, - RLNContractInitOptions + RLNContractOptions } from "./types.js"; +import { iPriceCalculatorAbi, wakuRlnV2Abi } from "./wagmi/generated.js"; const log = new Logger("rln:contract:base"); +type MembershipEvents = GetContractEventsReturnType< + typeof wakuRlnV2Abi, + "MembershipRegistered" | "MembershipErased" | "MembershipExpired" +>; export class RLNBaseContract { - public contract: ethers.Contract; + public contract: GetContractReturnType< + typeof wakuRlnV2Abi, + PublicClient | WalletClient + >; + public publicClient: PublicClient; + public walletClient: WalletClient; private deployBlock: undefined | number; private rateLimit: number; private minRateLimit?: number; private maxRateLimit?: number; protected _members: Map = new Map(); - private _membersFilter: ethers.EventFilter; - private _membershipErasedFilter: ethers.EventFilter; - private _membersExpiredFilter: ethers.EventFilter; /** * Private constructor for RLNBaseContract. Use static create() instead. */ - protected constructor(options: RLNContractInitOptions) { + protected constructor(options: RLNContractOptions) { const { address, - signer, - rateLimit = DEFAULT_RATE_LIMIT, - contract + publicClient, + walletClient, + rateLimit = DEFAULT_RATE_LIMIT } = options; log.info("Initializing RLNBaseContract", { address, rateLimit }); - this.contract = - contract || new ethers.Contract(address, RLN_CONTRACT.abi, signer); + this.publicClient = publicClient; + this.walletClient = walletClient; + this.contract = getContract({ + address, + abi: wakuRlnV2Abi, + client: { wallet: walletClient, public: publicClient } + }); this.rateLimit = rateLimit; - try { - log.info("Setting up event filters"); - // Initialize event filters - this._membersFilter = this.contract.filters.MembershipRegistered(); - this._membershipErasedFilter = this.contract.filters.MembershipErased(); - this._membersExpiredFilter = this.contract.filters.MembershipExpired(); - log.info("Event filters initialized successfully"); - } catch (error) { - log.error("Failed to initialize event filters", { error }); - throw new Error( - "Failed to initialize event filters: " + (error as Error).message - ); - } - // Initialize members and subscriptions this.fetchMembers() .then(() => { @@ -79,15 +83,19 @@ export class RLNBaseContract { * Static async factory to create and initialize RLNBaseContract */ public static async create( - options: RLNContractInitOptions + options: RLNContractOptions ): Promise { const instance = new RLNBaseContract(options); + + instance.deployBlock = await instance.contract.read.deployedBlockNumber(); + const [min, max] = await Promise.all([ - instance.contract.minMembershipRateLimit(), - instance.contract.maxMembershipRateLimit() + instance.contract.read.minMembershipRateLimit(), + instance.contract.read.maxMembershipRateLimit() ]); - instance.minRateLimit = ethers.BigNumber.from(min).toNumber(); - instance.maxRateLimit = ethers.BigNumber.from(max).toNumber(); + + instance.minRateLimit = min; + instance.maxRateLimit = max; instance.validateRateLimit(instance.rateLimit); return instance; @@ -107,13 +115,6 @@ export class RLNBaseContract { return this.contract.address; } - /** - * Gets the contract provider - */ - public get provider(): ethers.providers.Provider { - return this.contract.provider; - } - /** * Gets the minimum allowed rate limit (cached) */ @@ -137,8 +138,7 @@ export class RLNBaseContract { * @returns Promise The maximum total rate limit in messages per epoch */ public async getMaxTotalRateLimit(): Promise { - const maxTotalRate = await this.contract.maxTotalRateLimit(); - return maxTotalRate.toNumber(); + return await this.contract.read.maxTotalRateLimit(); } /** @@ -146,8 +146,7 @@ export class RLNBaseContract { * @returns Promise The current total rate limit usage in messages per epoch */ public async getCurrentTotalRateLimit(): Promise { - const currentTotal = await this.contract.currentTotalRateLimit(); - return currentTotal.toNumber(); + return Number(await this.contract.read.currentTotalRateLimit()); } /** @@ -155,11 +154,10 @@ export class RLNBaseContract { * @returns Promise The remaining rate limit that can be allocated */ public async getRemainingTotalRateLimit(): Promise { - const [maxTotal, currentTotal] = await Promise.all([ - this.contract.maxTotalRateLimit(), - this.contract.currentTotalRateLimit() - ]); - return Number(maxTotal) - Number(currentTotal); + return ( + (await this.contract.read.maxTotalRateLimit()) - + Number(await this.contract.read.currentTotalRateLimit()) + ); } /** @@ -171,36 +169,49 @@ export class RLNBaseContract { this.rateLimit = newRateLimit; } + /** + * Gets the Merkle tree root for RLN proof verification + * @returns Promise The Merkle tree root + * + */ + public async getMerkleRoot(): Promise { + return this.contract.read.root(); + } + + /** + * Gets the Merkle proof for a member at a given index + * @param index The index of the member in the membership set + * @returns Promise Array of 20 Merkle proof elements + * + */ + public async getMerkleProof(index: number): Promise { + return await this.contract.read.getMerkleProof([index]); + } + public get members(): Member[] { const sortedMembers = Array.from(this._members.values()).sort( - (left, right) => left.index.toNumber() - right.index.toNumber() + (left, right) => Number(left.index) - Number(right.index) ); return sortedMembers; } public async fetchMembers(options: FetchMembersOptions = {}): Promise { - const registeredMemberEvents = await RLNBaseContract.queryFilter( - this.contract, + const fromBlock = options.fromBlock + ? BigInt(options.fromBlock!) + : BigInt(this.deployBlock!); + const registeredMemberEvents = + await this.contract.getEvents.MembershipRegistered({ + fromBlock, + toBlock: fromBlock + BigInt(options.fetchRange!) + }); + const removedMemberEvents = await this.contract.getEvents.MembershipErased({ + fromBlock, + toBlock: fromBlock + BigInt(options.fetchRange!) + }); + const expiredMemberEvents = await this.contract.getEvents.MembershipExpired( { - fromBlock: this.deployBlock, - ...options, - membersFilter: this.membersFilter - } - ); - const removedMemberEvents = await RLNBaseContract.queryFilter( - this.contract, - { - fromBlock: this.deployBlock, - ...options, - membersFilter: this.membershipErasedFilter - } - ); - const expiredMemberEvents = await RLNBaseContract.queryFilter( - this.contract, - { - fromBlock: this.deployBlock, - ...options, - membersFilter: this.membersExpiredFilter + fromBlock, + toBlock: fromBlock + BigInt(options.fetchRange!) } ); @@ -212,96 +223,40 @@ export class RLNBaseContract { this.processEvents(events); } - public static async queryFilter( - contract: ethers.Contract, - options: CustomQueryOptions - ): Promise { - const FETCH_CHUNK = 5; - const BLOCK_RANGE = 3000; - - const { - fromBlock, - membersFilter, - fetchRange = BLOCK_RANGE, - fetchChunks = FETCH_CHUNK - } = options; - - if (fromBlock === undefined) { - return contract.queryFilter(membersFilter); - } - - if (!contract.provider) { - throw Error("No provider found on the contract."); - } - - const toBlock = await contract.provider.getBlockNumber(); - - if (toBlock - fromBlock < fetchRange) { - return contract.queryFilter(membersFilter, fromBlock, toBlock); - } - - const events: ethers.Event[][] = []; - const chunks = RLNBaseContract.splitToChunks( - fromBlock, - toBlock, - fetchRange - ); - - for (const portion of RLNBaseContract.takeN<[number, number]>( - chunks, - fetchChunks - )) { - const promises = portion.map(([left, right]) => - RLNBaseContract.ignoreErrors( - contract.queryFilter(membersFilter, left, right), - [] - ) - ); - const fetchedEvents = await Promise.all(promises); - events.push(fetchedEvents.flatMap((v) => v)); - } - - return events.flatMap((v) => v); - } - - public processEvents(events: ethers.Event[]): void { + public processEvents(events: MembershipEvents): void { const toRemoveTable = new Map(); - const toInsertTable = new Map(); + const toInsertTable = new Map(); events.forEach((evt) => { if (!evt.args) { return; } - + const blockNumber = Number(evt.blockNumber); if ( - evt.event === "MembershipErased" || - evt.event === "MembershipExpired" + evt.eventName === "MembershipErased" || + evt.eventName === "MembershipExpired" ) { - let index = evt.args.index; + const index = evt.args.index; if (!index) { return; } - if (typeof index === "number" || typeof index === "string") { - index = ethers.BigNumber.from(index); - } - - const toRemoveVal = toRemoveTable.get(evt.blockNumber); + const toRemoveVal = toRemoveTable.get(blockNumber); if (toRemoveVal != undefined) { - toRemoveVal.push(index.toNumber()); - toRemoveTable.set(evt.blockNumber, toRemoveVal); + toRemoveVal.push(index); + toRemoveTable.set(blockNumber, toRemoveVal); } else { - toRemoveTable.set(evt.blockNumber, [index.toNumber()]); + toRemoveTable.set(blockNumber, [index]); } - } else if (evt.event === "MembershipRegistered") { - let eventsPerBlock = toInsertTable.get(evt.blockNumber); + } else if (evt.eventName === "MembershipRegistered") { + let eventsPerBlock = toInsertTable.get(blockNumber); if (eventsPerBlock == undefined) { eventsPerBlock = []; } eventsPerBlock.push(evt); - toInsertTable.set(evt.blockNumber, eventsPerBlock); + toInsertTable.set(blockNumber, eventsPerBlock); } }); } @@ -354,50 +309,33 @@ export class RLNBaseContract { } public subscribeToMembers(): void { - this.contract.on( - this.membersFilter, - ( - _idCommitment: bigint, - _membershipRateLimit: ethers.BigNumber, - _index: ethers.BigNumber, - event: ethers.Event - ) => { - this.processEvents([event]); + this.contract.watchEvent.MembershipRegistered({ + onLogs: (logs) => { + this.processEvents(logs); } - ); - - this.contract.on( - this.membershipErasedFilter, - ( - _idCommitment: bigint, - _membershipRateLimit: ethers.BigNumber, - _index: ethers.BigNumber, - event: ethers.Event - ) => { - this.processEvents([event]); + }); + this.contract.watchEvent.MembershipExpired({ + onLogs: (logs) => { + this.processEvents(logs); } - ); - - this.contract.on( - this.membersExpiredFilter, - ( - _idCommitment: bigint, - _membershipRateLimit: ethers.BigNumber, - _index: ethers.BigNumber, - event: ethers.Event - ) => { - this.processEvents([event]); + }); + this.contract.watchEvent.MembershipErased({ + onLogs: (logs) => { + this.processEvents(logs); } - ); + }); } public async getMembershipInfo( idCommitmentBigInt: bigint ): Promise { try { - const membershipData = - await this.contract.memberships(idCommitmentBigInt); - const currentBlock = await this.contract.provider.getBlockNumber(); + const membershipData = await this.contract.read.memberships([ + idCommitmentBigInt + ]); + + const currentBlock = await this.publicClient.getBlockNumber(); + const [ depositAmount, activeDuration, @@ -409,12 +347,13 @@ export class RLNBaseContract { token ] = membershipData; - const gracePeriodEnd = gracePeriodStartTimestamp.add(gracePeriodDuration); + const gracePeriodEnd = + Number(gracePeriodStartTimestamp) + Number(gracePeriodDuration); let state: MembershipState; - if (currentBlock < gracePeriodStartTimestamp.toNumber()) { + if (currentBlock < Number(gracePeriodStartTimestamp)) { state = MembershipState.Active; - } else if (currentBlock < gracePeriodEnd.toNumber()) { + } else if (currentBlock < gracePeriodEnd) { state = MembershipState.GracePeriod; } else { state = MembershipState.Expired; @@ -423,9 +362,9 @@ export class RLNBaseContract { return { index, idCommitment: idCommitmentBigInt.toString(), - rateLimit: Number(rateLimit), - startBlock: gracePeriodStartTimestamp.toNumber(), - endBlock: gracePeriodEnd.toNumber(), + rateLimit: rateLimit, + startBlock: Number(gracePeriodStartTimestamp), + endBlock: gracePeriodEnd, state, depositAmount, activeDuration, @@ -439,43 +378,75 @@ export class RLNBaseContract { } } - public async extendMembership( - idCommitmentBigInt: bigint - ): Promise { - const tx = await this.contract.extendMemberships([idCommitmentBigInt]); - await tx.wait(); - return tx; + public async extendMembership(idCommitmentBigInt: bigint): Promise { + if (!this.walletClient.account) { + throw new Error( + "Failed to extendMembership: no account set in wallet client" + ); + } + try { + await this.contract.simulate.extendMemberships([[idCommitmentBigInt]], { + chain: this.walletClient.chain, + account: this.walletClient.account!.address + }); + } catch (err) { + throw new Error("Simulating extending membership failed: " + err); + } + const hash = await this.contract.write.extendMemberships( + [[idCommitmentBigInt]], + { + account: this.walletClient.account!, + chain: this.walletClient.chain + } + ); + + await this.publicClient.waitForTransactionReceipt({ hash }); + return hash; } public async eraseMembership( idCommitmentBigInt: bigint, eraseFromMembershipSet: boolean = true - ): Promise { + ): Promise { if ( !(await this.isExpired(idCommitmentBigInt)) || !(await this.isInGracePeriod(idCommitmentBigInt)) ) { throw new Error("Membership is not expired or in grace period"); } + if (!this.walletClient.account) { + throw new Error( + "Failed to eraseMembership: no account set in wallet client" + ); + } - const estimatedGas = await this.contract.estimateGas[ - "eraseMemberships(uint256[],bool)" - ]([idCommitmentBigInt], eraseFromMembershipSet); - const gasLimit = estimatedGas.add(10000); + try { + await this.contract.simulate.eraseMemberships( + [[idCommitmentBigInt], eraseFromMembershipSet], + { + chain: this.walletClient.chain, + account: this.walletClient.account!.address + } + ); + } catch (err) { + throw new Error("Error simulating eraseMemberships: " + err); + } - const tx = await this.contract["eraseMemberships(uint256[],bool)"]( - [idCommitmentBigInt], - eraseFromMembershipSet, - { gasLimit } + const hash = await this.contract.write.eraseMemberships( + [[idCommitmentBigInt], eraseFromMembershipSet], + { + chain: this.walletClient.chain, + account: this.walletClient.account! + } ); - await tx.wait(); - return tx; + await this.publicClient.waitForTransactionReceipt({ hash }); + return hash; } public async registerMembership( idCommitmentBigInt: bigint, rateLimit: number = DEFAULT_RATE_LIMIT - ): Promise { + ): Promise { if ( rateLimit < RATE_LIMIT_PARAMS.MIN_RATE || rateLimit > RATE_LIMIT_PARAMS.MAX_RATE @@ -484,16 +455,60 @@ export class RLNBaseContract { `Rate limit must be between ${RATE_LIMIT_PARAMS.MIN_RATE} and ${RATE_LIMIT_PARAMS.MAX_RATE}` ); } - return this.contract.register(idCommitmentBigInt, rateLimit, []); + if (!this.walletClient.account) { + throw new Error( + "Failed to registerMembership: no account set in wallet client" + ); + } + try { + await this.contract.simulate.register( + [idCommitmentBigInt, rateLimit, []], + { + chain: this.walletClient.chain, + account: this.walletClient.account!.address + } + ); + } catch (err) { + throw new Error("Failed to simulate register membership: " + err); + } + + const hash = await this.contract.write.register( + [idCommitmentBigInt, rateLimit, []], + { + chain: this.walletClient.chain, + account: this.walletClient.account! + } + ); + await this.publicClient.waitForTransactionReceipt({ hash }); + return hash; } - public async withdraw(token: string, walletAddress: string): Promise { - try { - const tx = await this.contract.withdraw(token, walletAddress); - await tx.wait(); - } catch (error) { - log.error(`Error in withdraw: ${(error as Error).message}`); + /** + * Withdraw deposited tokens after membership is erased + * @param token - Token address to withdraw + * NOTE: Funds are sent to msg.sender (the walletClient's address) + */ + public async withdraw(token: string): Promise { + if (!this.walletClient.account) { + throw new Error("Failed to withdraw: no account set in wallet client"); } + + try { + await this.contract.simulate.withdraw([token as Address], { + chain: this.walletClient.chain, + account: this.walletClient.account!.address + }); + } catch (err) { + throw new Error("Error simulating withdraw: " + err); + } + + const hash = await this.contract.write.withdraw([token as Address], { + chain: this.walletClient.chain, + account: this.walletClient.account! + }); + + await this.publicClient.waitForTransactionReceipt({ hash }); + return hash; } public async registerWithIdentity( identity: IdentityCredential @@ -521,62 +536,77 @@ export class RLNBaseContract { ); } - const estimatedGas = await this.contract.estimateGas.register( - identity.IDCommitmentBigInt, - this.rateLimit, - [] + await this.contract.simulate.register( + [identity.IDCommitmentBigInt, this.rateLimit, []], + { + chain: this.walletClient.chain, + account: this.walletClient.account!.address + } ); - const gasLimit = estimatedGas.add(10000); - const txRegisterResponse: ethers.ContractTransaction = - await this.contract.register( - identity.IDCommitmentBigInt, - this.rateLimit, - [], - { - gasLimit - } - ); + const hash: Hash = await this.contract.write.register( + [identity.IDCommitmentBigInt, this.rateLimit, []], + { + chain: this.walletClient.chain, + account: this.walletClient.account! + } + ); - const txRegisterReceipt = await txRegisterResponse.wait(); + const txRegisterReceipt = + await this.publicClient.waitForTransactionReceipt({ + hash + }); - if (txRegisterReceipt.status === 0) { + if (txRegisterReceipt.status === "reverted") { throw new Error("Transaction failed on-chain"); } - const memberRegistered = txRegisterReceipt.events?.find( - (event: ethers.Event) => event.event === "MembershipRegistered" - ); + // Parse MembershipRegistered event from logs + const memberRegisteredLog = txRegisterReceipt.logs.find((log) => { + try { + const decoded = decodeEventLog({ + abi: wakuRlnV2Abi, + data: log.data, + topics: log.topics + }); + return decoded.eventName === "MembershipRegistered"; + } catch { + return false; + } + }); - if (!memberRegistered || !memberRegistered.args) { + if (!memberRegisteredLog) { log.error( "Failed to register membership: No MembershipRegistered event found" ); return undefined; } - const decodedData: MembershipRegisteredEvent = { - idCommitment: memberRegistered.args.idCommitment, - membershipRateLimit: memberRegistered.args.membershipRateLimit, - index: memberRegistered.args.index + // Decode the event + const decoded = decodeEventLog({ + abi: wakuRlnV2Abi, + data: memberRegisteredLog.data, + topics: memberRegisteredLog.topics + }); + + const decodedArgs = decoded.args as { + idCommitment: bigint; + membershipRateLimit: number; + index: number; }; log.info( - `Successfully registered membership with index ${decodedData.index} ` + - `and rate limit ${decodedData.membershipRateLimit}` + `Successfully registered membership with index ${decodedArgs.index} ` + + `and rate limit ${decodedArgs.membershipRateLimit}` ); - const network = await this.contract.provider.getNetwork(); - const address = this.contract.address; - const membershipId = Number(decodedData.index); - return { identity, membership: { - address, - treeIndex: membershipId, - chainId: network.chainId.toString(), - rateLimit: decodedData.membershipRateLimit.toNumber() + address: this.contract.address, + treeIndex: decodedArgs.index, + chainId: String(RLN_CONTRACT.chainId), + rateLimit: decodedArgs.membershipRateLimit } }; } catch (error) { @@ -609,78 +639,6 @@ export class RLNBaseContract { } } - public async registerWithPermitAndErase( - identity: IdentityCredential, - permit: { - owner: string; - deadline: number; - v: number; - r: string; - s: string; - }, - idCommitmentsToErase: string[] - ): Promise { - try { - log.info( - `Registering identity with permit and rate limit: ${this.rateLimit} messages/epoch` - ); - - const txRegisterResponse: ethers.ContractTransaction = - await this.contract.registerWithPermit( - permit.owner, - permit.deadline, - permit.v, - permit.r, - permit.s, - identity.IDCommitmentBigInt, - this.rateLimit, - idCommitmentsToErase.map((id) => ethers.BigNumber.from(id)) - ); - const txRegisterReceipt = await txRegisterResponse.wait(); - - const memberRegistered = txRegisterReceipt.events?.find( - (event: ethers.Event) => event.event === "MembershipRegistered" - ); - - if (!memberRegistered || !memberRegistered.args) { - log.error( - "Failed to register membership with permit: No MembershipRegistered event found" - ); - return undefined; - } - - const decodedData: MembershipRegisteredEvent = { - idCommitment: memberRegistered.args.idCommitment, - membershipRateLimit: memberRegistered.args.membershipRateLimit, - index: memberRegistered.args.index - }; - - log.info( - `Successfully registered membership with permit. Index: ${decodedData.index}, ` + - `Rate limit: ${decodedData.membershipRateLimit}, Erased ${idCommitmentsToErase.length} commitments` - ); - - const network = await this.contract.provider.getNetwork(); - const address = this.contract.address; - const membershipId = Number(decodedData.index); - - return { - identity, - membership: { - address, - treeIndex: membershipId, - chainId: network.chainId.toString(), - rateLimit: decodedData.membershipRateLimit.toNumber() - } - }; - } catch (error) { - log.error( - `Error in registerWithPermitAndErase: ${(error as Error).message}` - ); - return undefined; - } - } - /** * Validates that the rate limit is within the allowed range (sync) * @throws Error if the rate limit is outside the allowed range @@ -696,50 +654,16 @@ export class RLNBaseContract { } } - private get membersFilter(): ethers.EventFilter { - if (!this._membersFilter) { - throw Error("Members filter was not initialized."); - } - return this._membersFilter; - } - - private get membershipErasedFilter(): ethers.EventFilter { - if (!this._membershipErasedFilter) { - throw Error("MembershipErased filter was not initialized."); - } - return this._membershipErasedFilter; - } - - private get membersExpiredFilter(): ethers.EventFilter { - if (!this._membersExpiredFilter) { - throw Error("MembersExpired filter was not initialized."); - } - return this._membersExpiredFilter; - } - - private async getMemberIndex( - idCommitmentBigInt: bigint - ): Promise { - try { - const events = await this.contract.queryFilter( - this.contract.filters.MembershipRegistered(idCommitmentBigInt) - ); - if (events.length === 0) return undefined; - - // Get the most recent registration event - const event = events[events.length - 1]; - return event.args?.index; - } catch (error) { - return undefined; - } + private async getMemberIndex(idCommitmentBigInt: bigint): Promise { + return (await this.contract.read.memberships([idCommitmentBigInt]))[5]; } public async getMembershipStatus( idCommitment: bigint ): Promise<"expired" | "grace" | "active"> { const [isExpired, isInGrace] = await Promise.all([ - this.contract.isExpired(idCommitment), - this.contract.isInGracePeriod(idCommitment) + this.contract.read.isExpired([idCommitment]), + this.contract.read.isInGracePeriod([idCommitment]) ]); if (isExpired) return "expired"; @@ -754,7 +678,7 @@ export class RLNBaseContract { */ public async isExpired(idCommitmentBigInt: bigint): Promise { try { - return await this.contract.isExpired(idCommitmentBigInt); + return await this.contract.read.isExpired([idCommitmentBigInt]); } catch (error) { log.error("Error in isExpired:", error); return false; @@ -768,7 +692,7 @@ export class RLNBaseContract { */ public async isInGracePeriod(idCommitmentBigInt: bigint): Promise { try { - return await this.contract.isInGracePeriod(idCommitmentBigInt); + return await this.contract.read.isInGracePeriod([idCommitmentBigInt]); } catch (error) { log.error("Error in isInGracePeriod:", error); return false; @@ -780,21 +704,18 @@ export class RLNBaseContract { * @param rateLimit The rate limit to calculate the price for * @param contractFactory Optional factory for creating the contract (for testing) */ - public async getPriceForRateLimit( - rateLimit: number, - contractFactory?: typeof import("ethers").Contract - ): Promise<{ + public async getPriceForRateLimit(rateLimit: number): Promise<{ token: string | null; - price: import("ethers").BigNumber | null; + price: bigint | null; }> { - const provider = this.contract.provider; - const ContractCtor = contractFactory || ethers.Contract; - const priceCalculator = new ContractCtor( - PRICE_CALCULATOR_CONTRACT.address, - PRICE_CALCULATOR_CONTRACT.abi, - provider - ); - const [token, price] = await priceCalculator.calculate(rateLimit); + const address = await this.contract.read.priceCalculator(); + const [token, price] = await this.publicClient.readContract({ + address, + abi: iPriceCalculatorAbi, + functionName: "calculate", + args: [rateLimit] + }); + // Defensive: if token or price is null/undefined, return nulls if (!token || !price) { return { token: null, price: null }; diff --git a/packages/rln/src/contract/types.ts b/packages/rln/src/contract/types.ts index bd0247bb6a..5553f6ddbe 100644 --- a/packages/rln/src/contract/types.ts +++ b/packages/rln/src/contract/types.ts @@ -1,28 +1,21 @@ -import { ethers } from "ethers"; - -export interface CustomQueryOptions extends FetchMembersOptions { - membersFilter: ethers.EventFilter; -} +import { Address, PublicClient, WalletClient } from "viem"; export type Member = { idCommitment: string; - index: ethers.BigNumber; + index: bigint; }; export interface RLNContractOptions { - signer: ethers.Signer; - address: string; + publicClient: PublicClient; + walletClient: WalletClient; + address: Address; rateLimit?: number; } -export interface RLNContractInitOptions extends RLNContractOptions { - contract?: ethers.Contract; -} - export interface MembershipRegisteredEvent { idCommitment: string; - membershipRateLimit: ethers.BigNumber; - index: ethers.BigNumber; + membershipRateLimit: bigint; + index: bigint; } export type FetchMembersOptions = { @@ -32,13 +25,13 @@ export type FetchMembersOptions = { }; export interface MembershipInfo { - index: ethers.BigNumber; + index: number; idCommitment: string; rateLimit: number; startBlock: number; endBlock: number; state: MembershipState; - depositAmount: ethers.BigNumber; + depositAmount: bigint; activeDuration: number; gracePeriodDuration: number; holder: string; diff --git a/packages/rln/src/credentials_manager.ts b/packages/rln/src/credentials_manager.ts index b82d9421f1..d79202f4ad 100644 --- a/packages/rln/src/credentials_manager.ts +++ b/packages/rln/src/credentials_manager.ts @@ -1,5 +1,5 @@ import { Logger } from "@waku/utils"; -import { ethers } from "ethers"; +import { PublicClient, WalletClient } from "viem"; import { RLN_CONTRACT } from "./contract/constants.js"; import { RLNBaseContract } from "./contract/rln_base_contract.js"; @@ -10,7 +10,7 @@ import type { } from "./keystore/index.js"; import { KeystoreEntity, Password } from "./keystore/types.js"; import { RegisterMembershipOptions, StartRLNOptions } from "./types.js"; -import { extractMetaMaskSigner } from "./utils/index.js"; +import { createViemClientsFromWindow } from "./utils/index.js"; import { Zerokit } from "./zerokit.js"; const log = new Logger("rln:credentials"); @@ -24,7 +24,8 @@ export class RLNCredentialsManager { protected starting = false; public contract: undefined | RLNBaseContract; - public signer: undefined | ethers.Signer; + public walletClient: undefined | WalletClient; + public publicClient: undefined | PublicClient; protected keystore = Keystore.create(); public credentials: undefined | DecryptedCredentials; @@ -36,10 +37,6 @@ export class RLNCredentialsManager { this.zerokit = zerokit; } - public get provider(): undefined | ethers.providers.Provider { - return this.contract?.provider; - } - public async start(options: StartRLNOptions = {}): Promise { if (this.started || this.starting) { log.info("RLNCredentialsManager already started or starting"); @@ -59,10 +56,8 @@ export class RLNCredentialsManager { log.info("Credentials successfully decrypted"); } - const { signer, address, rateLimit } = await this.determineStartOptions( - options, - credentials - ); + const { walletClient, publicClient, address, rateLimit } = + await this.determineStartOptions(options, credentials); log.info(`Using contract address: ${address}`); @@ -72,10 +67,12 @@ export class RLNCredentialsManager { } this.credentials = credentials; - this.signer = signer!; + this.walletClient = walletClient!; + this.publicClient = publicClient!; this.contract = await RLNBaseContract.create({ - address: address!, - signer: signer!, + address: address! as `0x${string}`, + publicClient: publicClient!, + walletClient: walletClient!, rateLimit: rateLimit ?? this.zerokit.rateLimit }); @@ -134,7 +131,9 @@ export class RLNCredentialsManager { protected async determineStartOptions( options: StartRLNOptions, credentials: KeystoreEntity | undefined - ): Promise { + ): Promise< + StartRLNOptions & { walletClient: WalletClient; publicClient: PublicClient } + > { let chainId = credentials?.membership.chainId; const address = credentials?.membership.address || @@ -146,8 +145,18 @@ export class RLNCredentialsManager { log.info(`Using Linea contract with chainId: ${chainId}`); } - const signer = options.signer || (await extractMetaMaskSigner()); - const currentChainId = await signer.getChainId(); + const walletClient = options.walletClient; + const publicClient = options.publicClient; + + let clients: { walletClient: WalletClient; publicClient: PublicClient }; + + if (!walletClient || !publicClient) { + clients = await createViemClientsFromWindow(); + } else { + clients = { walletClient, publicClient }; + } + + const currentChainId = await clients.publicClient.getChainId(); log.info(`Current chain ID: ${currentChainId}`); if (chainId && chainId !== currentChainId.toString()) { @@ -160,7 +169,8 @@ export class RLNCredentialsManager { } return { - signer, + walletClient: clients.walletClient, + publicClient: clients.publicClient, address }; } @@ -206,9 +216,9 @@ export class RLNCredentialsManager { protected async verifyCredentialsAgainstContract( credentials: KeystoreEntity ): Promise { - if (!this.contract) { + if (!this.contract || !this.publicClient) { throw Error( - "Failed to verify chain coordinates: no contract initialized." + "Failed to verify chain coordinates: no contract or publicClient initialized." ); } @@ -221,8 +231,7 @@ export class RLNCredentialsManager { } const chainId = credentials.membership.chainId; - const network = await this.contract.provider.getNetwork(); - const currentChainId = network.chainId; + const currentChainId = await this.publicClient.getChainId(); if (chainId !== currentChainId.toString()) { throw Error( `Failed to verify chain coordinates: credentials chainID=${chainId} is not equal to registryContract chainID=${currentChainId}` diff --git a/packages/rln/src/index.ts b/packages/rln/src/index.ts index 855720b7d5..9f1bee0338 100644 --- a/packages/rln/src/index.ts +++ b/packages/rln/src/index.ts @@ -4,7 +4,7 @@ import { createRLN } from "./create.js"; import { IdentityCredential } from "./identity.js"; import { Keystore } from "./keystore/index.js"; import { RLNInstance } from "./rln.js"; -import { extractMetaMaskSigner } from "./utils/index.js"; +import { createViemClientsFromWindow } from "./utils/index.js"; export { RLNBaseContract, @@ -13,7 +13,7 @@ export { RLNInstance, IdentityCredential, RLN_CONTRACT, - extractMetaMaskSigner + createViemClientsFromWindow as extractMetaMaskSigner }; // Export wagmi-generated ABIs diff --git a/packages/rln/src/types.ts b/packages/rln/src/types.ts index 7980c8aea9..a95dace147 100644 --- a/packages/rln/src/types.ts +++ b/packages/rln/src/types.ts @@ -1,4 +1,4 @@ -import { ethers } from "ethers"; +import { PublicClient, WalletClient } from "viem"; import { IdentityCredential } from "./identity.js"; import { @@ -8,9 +8,10 @@ import { export type StartRLNOptions = { /** - * If not set - will extract MetaMask account and get signer from it. + * If not set - will attempt to create from injected provider. */ - signer?: ethers.Signer; + walletClient?: WalletClient; + publicClient?: PublicClient; /** * If not set - will use default SEPOLIA_CONTRACT address. */ diff --git a/packages/rln/src/utils/index.ts b/packages/rln/src/utils/index.ts index dddc0b8285..cac46beaf2 100644 --- a/packages/rln/src/utils/index.ts +++ b/packages/rln/src/utils/index.ts @@ -1,4 +1,4 @@ -export { extractMetaMaskSigner } from "./metamask.js"; +export { createViemClientsFromWindow } from "./walletClient.js"; export { BytesUtils } from "./bytes.js"; export { sha256, poseidonHash } from "./hash.js"; export { dateToEpoch, epochIntToBytes, epochBytesToInt } from "./epoch.js"; diff --git a/packages/rln/src/utils/metamask.ts b/packages/rln/src/utils/metamask.ts deleted file mode 100644 index 83c7066106..0000000000 --- a/packages/rln/src/utils/metamask.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { ethers } from "ethers"; - -export const extractMetaMaskSigner = async (): Promise => { - // eslint-disable-next-line @typescript-eslint/no-explicit-any - const ethereum = (window as any).ethereum; - - if (!ethereum) { - throw Error( - "Missing or invalid Ethereum provider. Please install a Web3 wallet such as MetaMask." - ); - } - - await ethereum.request({ method: "eth_requestAccounts" }); - const provider = new ethers.providers.Web3Provider(ethereum, "any"); - - return provider.getSigner(); -}; diff --git a/packages/rln/src/utils/walletClient.ts b/packages/rln/src/utils/walletClient.ts new file mode 100644 index 0000000000..b9b3d174f5 --- /dev/null +++ b/packages/rln/src/utils/walletClient.ts @@ -0,0 +1,36 @@ +import { + createPublicClient, + createWalletClient, + custom, + PublicClient, + WalletClient +} from "viem"; +import { type Chain, lineaSepolia } from "viem/chains"; + +export const createViemClientsFromWindow = async ( + chain: Chain = lineaSepolia +): Promise<{ walletClient: WalletClient; publicClient: PublicClient }> => { + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const ethereum = (window as any).ethereum; + + if (!ethereum) { + throw Error( + "Missing or invalid Ethereum provider. Please install a Web3 wallet such as MetaMask." + ); + } + + const [account] = await ethereum.request({ method: "eth_requestAccounts" }); + + const walletClient = createWalletClient({ + account, + chain, + transport: custom(ethereum) + }); + + const publicClient = createPublicClient({ + chain, + transport: custom(ethereum) + }); + + return { walletClient, publicClient }; +}; diff --git a/packages/rln/tsconfig.dev.json b/packages/rln/tsconfig.dev.json index 96c99dc461..d53a621c4f 100644 --- a/packages/rln/tsconfig.dev.json +++ b/packages/rln/tsconfig.dev.json @@ -1,3 +1,4 @@ { - "extends": "../../tsconfig.dev" -} \ No newline at end of file + "extends": "../../tsconfig.dev", + "exclude": ["wagmi.config.ts"] +} diff --git a/packages/rln/tsconfig.json b/packages/rln/tsconfig.json index 6f8756934b..170dfc02c2 100644 --- a/packages/rln/tsconfig.json +++ b/packages/rln/tsconfig.json @@ -6,5 +6,5 @@ "tsBuildInfoFile": "dist/.tsbuildinfo" }, "include": ["src"], - "exclude": ["src/**/*.spec.ts", "src/test_utils"] -} \ No newline at end of file + "exclude": ["wagmi.config.ts"] +}