From 984855f47abb4a43034a857825165ca10981710d Mon Sep 17 00:00:00 2001 From: tate Date: Tue, 12 Sep 2023 11:59:03 +1000 Subject: [PATCH] unit tests cont. --- jest.config.ts | 4 +- package.json | 2 +- pnpm-lock.yaml | 319 +++++++++++++----- src/assets/address/DynamicAddressIcon.tsx | 2 +- src/constants/chains.ts | 73 ++++ src/constants/resolverAddressData.test.ts | 23 ++ src/constants/resolverAddressData.ts | 3 +- src/hooks/useAdvancedEditor.ts | 16 +- src/hooks/usePublicClient.ts | 6 +- src/test-utils.tsx | 6 +- .../AdvancedEditor/AdvancedEditor-flow.tsx | 4 +- .../AdvancedEditor/AdvancedEditor.test.tsx | 227 ++++++------- .../transaction/registerName.test.ts | 38 +-- .../transaction/unwrapName.test.ts | 52 ++- .../SyncDroppedTransaction.test.tsx | 296 ++++++++-------- .../SyncProvider/SyncDroppedTransaction.tsx | 2 +- src/utils/constants.test.ts | 11 - src/utils/editor.ts | 10 +- src/utils/profile.test.ts | 48 +-- src/utils/query.ts | 78 +---- src/utils/records.test.ts | 304 ++++++----------- src/utils/records.ts | 15 +- src/utils/safe.test.ts | 38 ++- tsconfig.json | 12 +- 24 files changed, 807 insertions(+), 782 deletions(-) create mode 100644 src/constants/chains.ts create mode 100644 src/constants/resolverAddressData.test.ts delete mode 100644 src/utils/constants.test.ts diff --git a/jest.config.ts b/jest.config.ts index b2231483d..4e4b50ec9 100644 --- a/jest.config.ts +++ b/jest.config.ts @@ -22,7 +22,7 @@ const customJestConfig: Config = { moduleNameMapper: { // Handle image imports // https://jestjs.io/docs/webpack#handling-static-assets - '\\.svg$': '/__mocks__/svgMock.tsx', + '^.+\\.(svg)$': '/__mocks__/svgMock.tsx', '^__tests__/(.*)$': '/__tests__/$1', '^@app/(.*)$': '/src/$1', '^@rainbow-me/rainbowkit$': '/__mocks__/rainbowkitMock.js', @@ -33,6 +33,8 @@ const customJestConfig: Config = { '^@wagmi/core(.*)$': '@wagmi/core-cjs$1', '^multiformats$': '/node_modules/multiformats/dist/index.min.js', '^multiformats/(.*)$': '/node_modules/multiformats/src/$1', + '^uint8arrays$': + '/node_modules/.pnpm/uint8arrays@3.1.1/node_modules/uint8arrays/cjs/src/index.js', }, setupFilesAfterEnv: ['/jest/jest.setup.ts'], setupFiles: ['/jest/setEnvVars.js', 'jest-canvas-mock'], diff --git a/package.json b/package.json index 1fafd6833..e1e6ab6d5 100644 --- a/package.json +++ b/package.json @@ -115,7 +115,7 @@ "@openzeppelin/test-helpers": "^0.5.16", "@playwright/test": "^1.36.2", "@testing-library/jest-dom": "^5.16.5", - "@testing-library/react": "^12.1.5", + "@testing-library/react": "^14.0.0", "@testing-library/react-hooks": "^8.0.1", "@testing-library/user-event": "^14.4.3", "@trivago/prettier-plugin-sort-imports": "^3.3.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 2cc18aff9..fd415bcd1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -52,7 +52,7 @@ importers: '@tanstack/react-query': 4.29.1 '@tanstack/react-query-persist-client': 4.29.1 '@testing-library/jest-dom': ^5.16.5 - '@testing-library/react': ^12.1.5 + '@testing-library/react': ^14.0.0 '@testing-library/react-hooks': ^8.0.1 '@testing-library/user-event': ^14.4.3 '@trivago/prettier-plugin-sort-imports': ^3.3.0 @@ -220,7 +220,7 @@ importers: '@openzeppelin/test-helpers': 0.5.16 '@playwright/test': 1.36.2 '@testing-library/jest-dom': 5.16.5 - '@testing-library/react': 12.1.5_biqbaboplfbrettd7655fr4n2y + '@testing-library/react': 14.0.0_biqbaboplfbrettd7655fr4n2y '@testing-library/react-hooks': 8.0.1_vnxzf5c44dqo4vncfl2mrh2gwm '@testing-library/user-event': 14.4.3 '@trivago/prettier-plugin-sort-imports': 3.3.0_prettier@2.8.8 @@ -316,12 +316,6 @@ packages: '@jridgewell/gen-mapping': 0.1.1 '@jridgewell/trace-mapping': 0.3.19 - /@babel/code-frame/7.18.6: - resolution: {integrity: sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/highlight': 7.18.6 - /@babel/code-frame/7.22.13: resolution: {integrity: sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==} engines: {node: '>=6.9.0'} @@ -338,7 +332,7 @@ packages: engines: {node: '>=6.9.0'} dependencies: '@ampproject/remapping': 2.2.0 - '@babel/code-frame': 7.18.6 + '@babel/code-frame': 7.22.13 '@babel/generator': 7.21.3 '@babel/helper-compilation-targets': 7.19.3_@babel+core@7.17.8 '@babel/helper-module-transforms': 7.19.0 @@ -361,7 +355,7 @@ packages: engines: {node: '>=6.9.0'} dependencies: '@ampproject/remapping': 2.2.0 - '@babel/code-frame': 7.18.6 + '@babel/code-frame': 7.22.13 '@babel/generator': 7.21.3 '@babel/helper-compilation-targets': 7.20.7_@babel+core@7.21.3 '@babel/helper-module-transforms': 7.21.2 @@ -589,7 +583,7 @@ packages: '@babel/helper-module-imports': 7.18.6 '@babel/helper-simple-access': 7.20.2 '@babel/helper-split-export-declaration': 7.18.6 - '@babel/helper-validator-identifier': 7.19.1 + '@babel/helper-validator-identifier': 7.22.15 '@babel/template': 7.20.7 '@babel/traverse': 7.21.3 '@babel/types': 7.22.15 @@ -684,10 +678,6 @@ packages: resolution: {integrity: sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==} engines: {node: '>=6.9.0'} - /@babel/helper-validator-identifier/7.19.1: - resolution: {integrity: sha512-awrNfaMtnHUr653GgGEs++LlAvW6w+DcPrOliSMXWCKo597CwL5Acf/wWdNkf/tfEQE3mjkeD1YOVZOUV/od1w==} - engines: {node: '>=6.9.0'} - /@babel/helper-validator-identifier/7.22.15: resolution: {integrity: sha512-4E/F9IIEi8WR94324mbDUMo074YTheJmd7eZF5vITTeYchqAi6sYXRLHUVsmkdmY4QjfKTcB2jB7dVP3NaBElQ==} engines: {node: '>=6.9.0'} @@ -731,14 +721,6 @@ packages: transitivePeerDependencies: - supports-color - /@babel/highlight/7.18.6: - resolution: {integrity: sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-validator-identifier': 7.22.15 - chalk: 2.4.2 - js-tokens: 4.0.0 - /@babel/highlight/7.22.13: resolution: {integrity: sha512-C/BaXcnnvBCmHTpz/VGZ8jgtE2aYlW4hxDhseJAWZb7gqGM/qtCK6iZUb0TyKFf7BOUsBH7Q7fkRsDRhg1XklQ==} engines: {node: '>=6.9.0'} @@ -1854,7 +1836,7 @@ packages: resolution: {integrity: sha512-8SegXApWe6VoNw0r9JHpSteLKTpTiLZ4rMlGIm9JQ18KiCtyQiAMEazujAHrUS5flrcqYZa75ukev3P6QmUwUw==} engines: {node: '>=6.9.0'} dependencies: - '@babel/code-frame': 7.18.6 + '@babel/code-frame': 7.22.13 '@babel/parser': 7.21.3 '@babel/types': 7.22.15 @@ -1870,7 +1852,7 @@ packages: resolution: {integrity: sha512-5irClVky7TxRWIRtxlh2WPUUOLhcPN06AGgaQSB8AEwuyEBgJVuJ5imdHm5zxk8w0QS5T+tDfnDxAlhWjpb7cw==} engines: {node: '>=6.9.0'} dependencies: - '@babel/code-frame': 7.18.6 + '@babel/code-frame': 7.22.13 '@babel/generator': 7.21.3 '@babel/helper-environment-visitor': 7.18.9 '@babel/helper-function-name': 7.21.0 @@ -1888,7 +1870,7 @@ packages: resolution: {integrity: sha512-qh5yf6149zhq2sgIXmwjnsvmnNQC2iw70UFjp4olxucKrWd/dvlUsBI88VSLUsnMNF7/vnOiA+nk1+yLoCqROQ==} engines: {node: '>=6.9.0'} dependencies: - '@babel/code-frame': 7.18.6 + '@babel/code-frame': 7.22.13 '@babel/generator': 7.21.3 '@babel/helper-environment-visitor': 7.18.9 '@babel/helper-function-name': 7.21.0 @@ -1906,7 +1888,7 @@ packages: resolution: {integrity: sha512-XLyopNeaTancVitYZe2MlUEvgKb6YVVPXzofHgqHijCImG33b/uTurMS488ht/Hbsb2XK3U2BnSTxKVNGV3nGQ==} engines: {node: '>=6.9.0'} dependencies: - '@babel/code-frame': 7.18.6 + '@babel/code-frame': 7.22.13 '@babel/generator': 7.21.3 '@babel/helper-environment-visitor': 7.18.9 '@babel/helper-function-name': 7.21.0 @@ -1923,7 +1905,7 @@ packages: resolution: {integrity: sha512-XLyopNeaTancVitYZe2MlUEvgKb6YVVPXzofHgqHijCImG33b/uTurMS488ht/Hbsb2XK3U2BnSTxKVNGV3nGQ==} engines: {node: '>=6.9.0'} dependencies: - '@babel/code-frame': 7.18.6 + '@babel/code-frame': 7.22.13 '@babel/generator': 7.21.3 '@babel/helper-environment-visitor': 7.18.9 '@babel/helper-function-name': 7.21.0 @@ -1941,7 +1923,7 @@ packages: resolution: {integrity: sha512-TmKSNO4D5rzhL5bjWFcVHHLETzfQ/AmbKpKPOSjlP0WoHZ6L911fgoOKY4Alp/emzG4cHJdyN49zpgkbXFEHHw==} engines: {node: '>=6.9.0'} dependencies: - '@babel/helper-validator-identifier': 7.19.1 + '@babel/helper-validator-identifier': 7.22.15 to-fast-properties: 2.0.0 dev: true @@ -1950,7 +1932,7 @@ packages: engines: {node: '>=6.9.0'} dependencies: '@babel/helper-string-parser': 7.19.4 - '@babel/helper-validator-identifier': 7.19.1 + '@babel/helper-validator-identifier': 7.22.15 to-fast-properties: 2.0.0 /@babel/types/7.22.15: @@ -4902,17 +4884,17 @@ packages: react-dom: 18.2.0_react@18.2.0 use-sync-external-store: 1.2.0_react@18.2.0 - /@testing-library/dom/8.18.1: - resolution: {integrity: sha512-oEvsm2B/WtcHKE+IcEeeCqNU/ltFGaVyGbpcm4g/2ytuT49jrlH9x5qRKL/H3A6yfM4YAbSbC0ceT5+9CEXnLg==} - engines: {node: '>=12'} + /@testing-library/dom/9.3.1: + resolution: {integrity: sha512-0DGPd9AR3+iDTjGoMpxIkAsUihHZ3Ai6CneU6bRRrffXMgzCdlNk43jTrD2/5LT6CBb3MWTP8v510JzYtahD2w==} + engines: {node: '>=14'} dependencies: - '@babel/code-frame': 7.18.6 + '@babel/code-frame': 7.22.13 '@babel/runtime': 7.19.0 - '@types/aria-query': 4.2.2 - aria-query: 5.0.2 + '@types/aria-query': 5.0.1 + aria-query: 5.1.3 chalk: 4.1.2 dom-accessibility-api: 0.5.14 - lz-string: 1.4.4 + lz-string: 1.5.0 pretty-format: 27.5.1 dev: true @@ -4954,16 +4936,16 @@ packages: react-error-boundary: 3.1.4_react@18.2.0 dev: true - /@testing-library/react/12.1.5_biqbaboplfbrettd7655fr4n2y: - resolution: {integrity: sha512-OfTXCJUFgjd/digLUuPxa0+/3ZxsQmE7ub9kcbW/wi96Bh3o/p5vrETcBGfP17NWPGqeYYl5LTRpwyGoMC4ysg==} - engines: {node: '>=12'} + /@testing-library/react/14.0.0_biqbaboplfbrettd7655fr4n2y: + resolution: {integrity: sha512-S04gSNJbYE30TlIMLTzv6QCTzt9AqIF5y6s6SzVFILNcNvbV/jU96GeiTPillGQo+Ny64M/5PV7klNYYgv5Dfg==} + engines: {node: '>=14'} peerDependencies: - react: <18.0.0 - react-dom: <18.0.0 + react: ^18.0.0 + react-dom: ^18.0.0 dependencies: '@babel/runtime': 7.19.0 - '@testing-library/dom': 8.18.1 - '@types/react-dom': 17.0.17 + '@testing-library/dom': 9.3.1 + '@types/react-dom': 18.2.7 react: 18.2.0 react-dom: 18.2.0_react@18.2.0 dev: true @@ -5135,8 +5117,8 @@ packages: resolution: {integrity: sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ==} dev: true - /@types/aria-query/4.2.2: - resolution: {integrity: sha512-HnYpAE1Y6kRyKM/XkEuiRQhTHvkzMBurTHnpFLYLBGPIylZNPs9jJcuOOYWxPLJCSEtmZT0Y8rHDokKN7rRTig==} + /@types/aria-query/5.0.1: + resolution: {integrity: sha512-XTIieEY+gvJ39ChLcB4If5zHtPxt3Syj5rgZR+e1ctpmK8NjPf0zFqsz4JpLJT0xla9GFDKjy8Cpu331nrmE1Q==} dev: true /@types/async-eventemitter/0.2.1: @@ -5391,12 +5373,6 @@ packages: resolution: {integrity: sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==} dev: true - /@types/react-dom/17.0.17: - resolution: {integrity: sha512-VjnqEmqGnasQKV0CWLevqMTXBYG9GbwuE6x3VetERLh0cq2LTptFE73MrQi2S7GkKXCf2GgwItB/melLnxfnsg==} - dependencies: - '@types/react': 17.0.30 - dev: true - /@types/react-dom/18.2.7: resolution: {integrity: sha512-GRaAEriuT4zp9N4p1i8BDBYmEyfo+xQ3yHjJU4eiK5NDa1RmUZG+unZABUTK4/Ox/M+GaHwb6Ow8rUITrtjszA==} dependencies: @@ -5409,14 +5385,6 @@ packages: '@types/react': 18.2.21 dev: true - /@types/react/17.0.30: - resolution: {integrity: sha512-3Dt/A8gd3TCXi2aRe84y7cK1K8G+N9CZRDG8kDGguOKa0kf/ZkSwTmVIDPsm/KbQOVMaDJXwhBtuOXxqwdpWVg==} - dependencies: - '@types/prop-types': 15.7.5 - '@types/scheduler': 0.16.2 - csstype: 3.1.1 - dev: true - /@types/react/18.2.21: resolution: {integrity: sha512-neFKG/sBAwGxHgXiIxnbm3/AAVQ/cMRS93hvBpg8xYRbeQSPVABp9U2bRnPf0iI4+Ucdv3plSxKK+3CW2ENJxA==} dependencies: @@ -6706,6 +6674,19 @@ packages: engines: {node: '>=6.0'} dev: true + /aria-query/5.1.3: + resolution: {integrity: sha512-R5iJ5lkuHybztUfuOAznmboyjWq8O6sqNqtK7CLOqdydi54VNbORp49mb14KbWgG1QD3JFO9hJdZ+y4KutfdOQ==} + dependencies: + deep-equal: 2.2.2 + dev: true + + /array-buffer-byte-length/1.0.0: + resolution: {integrity: sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==} + dependencies: + call-bind: 1.0.2 + is-array-buffer: 3.0.2 + dev: true + /array-flatten/1.1.1: resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} dev: true @@ -7433,7 +7414,7 @@ packages: resolution: {integrity: sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==} dependencies: function-bind: 1.1.1 - get-intrinsic: 1.1.3 + get-intrinsic: 1.2.1 /callsites/3.1.0: resolution: {integrity: sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==} @@ -8356,6 +8337,29 @@ packages: type-detect: 4.0.8 dev: true + /deep-equal/2.2.2: + resolution: {integrity: sha512-xjVyBf0w5vH0I42jdAZzOKVldmPgSulmiyPRywoyq7HXC9qdgo17kxJE+rdnif5Tz6+pIrpJI8dCpMNLIGkUiA==} + dependencies: + array-buffer-byte-length: 1.0.0 + call-bind: 1.0.2 + es-get-iterator: 1.1.3 + get-intrinsic: 1.2.1 + is-arguments: 1.1.1 + is-array-buffer: 3.0.2 + is-date-object: 1.0.5 + is-regex: 1.1.4 + is-shared-array-buffer: 1.0.2 + isarray: 2.0.5 + object-is: 1.1.5 + object-keys: 1.1.1 + object.assign: 4.1.4 + regexp.prototype.flags: 1.5.0 + side-channel: 1.0.4 + which-boxed-primitive: 1.0.2 + which-collection: 1.0.1 + which-typed-array: 1.1.11 + dev: true + /deep-is/0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} dev: true @@ -8389,6 +8393,15 @@ packages: dependencies: has-property-descriptors: 1.0.0 object-keys: 1.1.1 + dev: true + + /define-properties/1.2.0: + resolution: {integrity: sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==} + engines: {node: '>= 0.4'} + dependencies: + has-property-descriptors: 1.0.0 + object-keys: 1.1.1 + dev: true /delay/5.0.0: resolution: {integrity: sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw==} @@ -8716,12 +8729,12 @@ packages: es-to-primitive: 1.2.1 function-bind: 1.1.1 function.prototype.name: 1.1.5 - get-intrinsic: 1.1.3 + get-intrinsic: 1.2.1 get-symbol-description: 1.0.0 has: 1.0.3 has-property-descriptors: 1.0.0 has-symbols: 1.0.3 - internal-slot: 1.0.3 + internal-slot: 1.0.5 is-callable: 1.2.7 is-negative-zero: 2.0.2 is-regex: 1.1.4 @@ -8731,11 +8744,26 @@ packages: object-inspect: 1.12.2 object-keys: 1.1.1 object.assign: 4.1.4 - regexp.prototype.flags: 1.4.3 + regexp.prototype.flags: 1.5.0 safe-regex-test: 1.0.0 string.prototype.trimend: 1.0.5 string.prototype.trimstart: 1.0.5 unbox-primitive: 1.0.2 + dev: true + + /es-get-iterator/1.1.3: + resolution: {integrity: sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.2.1 + has-symbols: 1.0.3 + is-arguments: 1.1.1 + is-map: 2.0.2 + is-set: 2.0.2 + is-string: 1.0.7 + isarray: 2.0.5 + stop-iteration-iterator: 1.0.0 + dev: true /es-shim-unscopables/1.0.0: resolution: {integrity: sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==} @@ -8750,6 +8778,7 @@ packages: is-callable: 1.2.7 is-date-object: 1.0.5 is-symbol: 1.0.4 + dev: true /es5-ext/0.10.62: resolution: {integrity: sha512-BHLqn0klhEpnOKSrzn/Xsz2UIW8j+cGmo9JLzr8BiUapV8hPL9+FliFqjwr9ngW7jWdnxv6eO+/LqyhJVqgrjA==} @@ -10087,9 +10116,10 @@ packages: engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.2 - define-properties: 1.1.4 + define-properties: 1.2.0 es-abstract: 1.20.4 functions-have-names: 1.2.3 + dev: true /functional-red-black-tree/1.0.1: resolution: {integrity: sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==} @@ -10097,6 +10127,7 @@ packages: /functions-have-names/1.2.3: resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + dev: true /ganache/7.4.3: resolution: {integrity: sha512-RpEDUiCkqbouyE7+NMXG26ynZ+7sGiODU84Kz+FVoXUnQ4qQM4M8wif3Y4qUCt+D/eM1RVeGq0my62FPD6Y1KA==} @@ -10161,6 +10192,15 @@ packages: function-bind: 1.1.1 has: 1.0.3 has-symbols: 1.0.3 + dev: true + + /get-intrinsic/1.2.1: + resolution: {integrity: sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==} + dependencies: + function-bind: 1.1.1 + has: 1.0.3 + has-proto: 1.0.1 + has-symbols: 1.0.3 /get-nonce/1.0.1: resolution: {integrity: sha512-FJhYRoDaiatfEkUK8HKlicmu/3SGFD51q3itKDGoSTysQJBnfOcxU5GxnhE1E6soB76MbT0MBtnKJuXyAx+96Q==} @@ -10196,7 +10236,8 @@ packages: engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.2 - get-intrinsic: 1.1.3 + get-intrinsic: 1.2.1 + dev: true /get-tsconfig/4.7.0: resolution: {integrity: sha512-pmjiZ7xtB8URYm74PlGJozDNyhvsVLUcpBa8DZBG3bWHwaHa9bPiRpiSfovw+fjhwONSCWKRyk+JQHEGZmMrzw==} @@ -10321,6 +10362,11 @@ packages: resolution: {integrity: sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==} dev: true + /gopd/1.0.1: + resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + dependencies: + get-intrinsic: 1.2.1 + /got/11.8.5: resolution: {integrity: sha512-o0Je4NvQObAuZPHLFoRSkdG2lTgtcynqymzg2Vupdx6PorhaT5MCbIyXG6d4D94kk8ZG57QeosgdiqfJWhEhlQ==} engines: {node: '>=10.19.0'} @@ -10575,6 +10621,7 @@ packages: /has-bigints/1.0.2: resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} + dev: true /has-flag/3.0.0: resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} @@ -10587,7 +10634,12 @@ packages: /has-property-descriptors/1.0.0: resolution: {integrity: sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==} dependencies: - get-intrinsic: 1.1.3 + get-intrinsic: 1.2.1 + dev: true + + /has-proto/1.0.1: + resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==} + engines: {node: '>= 0.4'} /has-symbols/1.0.3: resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} @@ -10975,9 +11027,19 @@ packages: resolution: {integrity: sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==} engines: {node: '>= 0.4'} dependencies: - get-intrinsic: 1.1.3 + get-intrinsic: 1.2.1 has: 1.0.3 side-channel: 1.0.4 + dev: true + + /internal-slot/1.0.5: + resolution: {integrity: sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.1 + has: 1.0.3 + side-channel: 1.0.4 + dev: true /intl-segmenter-polyfill/0.4.4: resolution: {integrity: sha512-dIOcmvH+Q1WYGkjMqxPfaCgHEwOegH5UPcd/LLeaeY8aguHadC46MzGb40q8C1LrsuyJxJGKeKqoVtIh9ADRXQ==} @@ -11014,6 +11076,14 @@ packages: call-bind: 1.0.2 has-tostringtag: 1.0.0 + /is-array-buffer/3.0.2: + resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.2.1 + is-typed-array: 1.1.12 + dev: true + /is-arrayish/0.2.1: resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} @@ -11021,6 +11091,7 @@ packages: resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} dependencies: has-bigints: 1.0.2 + dev: true /is-binary-path/2.1.0: resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} @@ -11035,6 +11106,7 @@ packages: dependencies: call-bind: 1.0.2 has-tostringtag: 1.0.0 + dev: true /is-buffer/2.0.5: resolution: {integrity: sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==} @@ -11061,6 +11133,7 @@ packages: engines: {node: '>= 0.4'} dependencies: has-tostringtag: 1.0.0 + dev: true /is-extglob/2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} @@ -11116,9 +11189,14 @@ packages: lower-case: 1.1.4 dev: true + /is-map/2.0.2: + resolution: {integrity: sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==} + dev: true + /is-negative-zero/2.0.2: resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==} engines: {node: '>= 0.4'} + dev: true /is-node-process/1.2.0: resolution: {integrity: sha512-Vg4o6/fqPxIjtxgUH5QLJhwZ7gW5diGCVlXpuUfELC62CuxM1iHcRe51f2W1FDy04Ai4KJkagKjx3XaqyfRKXw==} @@ -11129,6 +11207,7 @@ packages: engines: {node: '>= 0.4'} dependencies: has-tostringtag: 1.0.0 + dev: true /is-number/7.0.0: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} @@ -11171,11 +11250,17 @@ packages: dependencies: call-bind: 1.0.2 has-tostringtag: 1.0.0 + dev: true + + /is-set/2.0.2: + resolution: {integrity: sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==} + dev: true /is-shared-array-buffer/1.0.2: resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==} dependencies: call-bind: 1.0.2 + dev: true /is-stream/2.0.1: resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} @@ -11191,22 +11276,20 @@ packages: engines: {node: '>= 0.4'} dependencies: has-tostringtag: 1.0.0 + dev: true /is-symbol/1.0.4: resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} engines: {node: '>= 0.4'} dependencies: has-symbols: 1.0.3 + dev: true - /is-typed-array/1.1.9: - resolution: {integrity: sha512-kfrlnTTn8pZkfpJMUgYD7YZ3qzeJgWUn8XfVYBARc4wnmNOmLbmuuaAs3q5fvB0UJOn6yHAKaGTPM7d6ezoD/A==} + /is-typed-array/1.1.12: + resolution: {integrity: sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==} engines: {node: '>= 0.4'} dependencies: - available-typed-arrays: 1.0.5 - call-bind: 1.0.2 - es-abstract: 1.20.4 - for-each: 0.3.3 - has-tostringtag: 1.0.0 + which-typed-array: 1.1.11 /is-typedarray/1.0.0: resolution: {integrity: sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==} @@ -11226,14 +11309,30 @@ packages: resolution: {integrity: sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q==} dev: true + /is-weakmap/2.0.1: + resolution: {integrity: sha512-NSBR4kH5oVj1Uwvv970ruUkCV7O1mzgVFO4/rev2cLRda9Tm9HrL70ZPut4rOHgY0FNrUu9BCbXA2sdQ+x0chA==} + dev: true + /is-weakref/1.0.2: resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} dependencies: call-bind: 1.0.2 + dev: true + + /is-weakset/2.0.2: + resolution: {integrity: sha512-t2yVvttHkQktwnNNmBQ98AhENLdPUTDTE21uPqAQ0ARwQfGeQKRVS0NNurH7bTf7RrvcVn1OOge45CnBeHCSmg==} + dependencies: + call-bind: 1.0.2 + get-intrinsic: 1.2.1 + dev: true /isarray/1.0.0: resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + /isarray/2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + dev: true + /isexe/2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} @@ -11652,7 +11751,7 @@ packages: resolution: {integrity: sha512-PFdn9Iewbt575zKPf1286Ht9EPoJmYT7P0kY+RibeYZ2XtOr53pDLEFoTWXbd1h4JiGiWpTBC84fc8xMXQMb7g==} engines: {node: ^12.13.0 || ^14.15.0 || ^16.10.0 || >=17.0.0} dependencies: - '@babel/code-frame': 7.18.6 + '@babel/code-frame': 7.22.13 '@jest/types': 28.1.3 '@types/stack-utils': 2.0.1 chalk: 4.1.2 @@ -11667,7 +11766,7 @@ packages: resolution: {integrity: sha512-vnIGYEjoPSuRqV8W9t+Wow95SDp6KPX2Uf7EoeG9G99J2OVh7OSwpS4B6J0NfpEIpfkBNHlBZpA2rblEuEFhZQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@babel/code-frame': 7.18.6 + '@babel/code-frame': 7.22.13 '@jest/types': 29.6.1 '@types/stack-utils': 2.0.1 chalk: 4.1.2 @@ -12473,8 +12572,8 @@ packages: /lru_map/0.3.3: resolution: {integrity: sha512-Pn9cox5CsMYngeDbmChANltQl+5pi6XmTrraMSzhPmMBbmgcxmqWry0U3PGapCU1yB4/LqCcom7qhHZiF/jGfQ==} - /lz-string/1.4.4: - resolution: {integrity: sha512-0ckx7ZHRPqb0oUm8zNr+90mtf9DQB60H1wMCjBtfi62Kl3a7JbHob6gA2bC+xRvZoOL+1hzUK8jeuEIQE8svEQ==} + /lz-string/1.5.0: + resolution: {integrity: sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==} hasBin: true dev: true @@ -13363,9 +13462,18 @@ packages: /object-inspect/1.12.2: resolution: {integrity: sha512-z+cPxW0QGUp0mcqcsgQyLVRDoXFQbXOwBaqyF7VIgI4TWNQsDHrBpUQslRmIfAoYWdYzs6UlKJtB2XJpTaNSpQ==} + /object-is/1.1.5: + resolution: {integrity: sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.1.4 + dev: true + /object-keys/1.1.1: resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} engines: {node: '>= 0.4'} + dev: true /object.assign/4.1.4: resolution: {integrity: sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==} @@ -13375,6 +13483,7 @@ packages: define-properties: 1.1.4 has-symbols: 1.0.3 object-keys: 1.1.1 + dev: true /object.entries/1.1.5: resolution: {integrity: sha512-TyxmjUoZggd4OrrU1W66FMDG6CuqJxsFvymeyXI51+vQLN67zYfZseptRge703kKQdo4uccgAKebXFcRCzk4+g==} @@ -14483,8 +14592,18 @@ packages: engines: {node: '>= 0.4'} dependencies: call-bind: 1.0.2 - define-properties: 1.1.4 + define-properties: 1.2.0 + functions-have-names: 1.2.3 + dev: true + + /regexp.prototype.flags/1.5.0: + resolution: {integrity: sha512-0SutC3pNudRKgquxGoRGIz946MZVHqbNfPjBdxeOhBrdgDKlRoXmYLQN9xRbrR09ZXWeGAdPuif7egofn6v5LA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.2 + define-properties: 1.2.0 functions-have-names: 1.2.3 + dev: true /regexpu-core/5.2.1: resolution: {integrity: sha512-HrnlNtpvqP1Xkb28tMhBUO2EbyUHdQlsnlAhzWcwHy8WJR53UWr7/MAvqrsQKMbV4qdpv03oTMG8iIhfsPFktQ==} @@ -14789,8 +14908,9 @@ packages: resolution: {integrity: sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==} dependencies: call-bind: 1.0.2 - get-intrinsic: 1.1.3 + get-intrinsic: 1.2.1 is-regex: 1.1.4 + dev: true /safe-stable-stringify/2.4.2: resolution: {integrity: sha512-gMxvPJYhP0O9n2pvcfYfIuYgbledAOJFcqRThtPRmjscaipiwcwPPKLytpVzMkG2HAN87Qmo2d4PtGiri1dSLA==} @@ -15014,7 +15134,7 @@ packages: resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} dependencies: call-bind: 1.0.2 - get-intrinsic: 1.1.3 + get-intrinsic: 1.2.1 object-inspect: 1.12.2 /signal-exit/3.0.7: @@ -15297,6 +15417,13 @@ packages: engines: {node: '>= 0.8'} dev: true + /stop-iteration-iterator/1.0.0: + resolution: {integrity: sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==} + engines: {node: '>= 0.4'} + dependencies: + internal-slot: 1.0.5 + dev: true + /stream-browserify/3.0.0: resolution: {integrity: sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==} dependencies: @@ -15371,15 +15498,17 @@ packages: resolution: {integrity: sha512-I7RGvmjV4pJ7O3kdf+LXFpVfdNOxtCW/2C8f6jNiW4+PQchwxkCDzlk1/7p+Wl4bqFIZeF47qAHXLuHHWKAxog==} dependencies: call-bind: 1.0.2 - define-properties: 1.1.4 + define-properties: 1.2.0 es-abstract: 1.20.4 + dev: true /string.prototype.trimstart/1.0.5: resolution: {integrity: sha512-THx16TJCGlsN0o6dl2o6ncWUsdgnLRSA23rRE5pyGBw/mLr3Ej/R2LaqCtgP8VNMGZsvMWnf9ooZPyY2bHvUFg==} dependencies: call-bind: 1.0.2 - define-properties: 1.1.4 + define-properties: 1.2.0 es-abstract: 1.20.4 + dev: true /string_decoder/1.0.3: resolution: {integrity: sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==} @@ -16166,6 +16295,7 @@ packages: has-bigints: 1.0.2 has-symbols: 1.0.3 which-boxed-primitive: 1.0.2 + dev: true /underscore/1.13.6: resolution: {integrity: sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==} @@ -16368,9 +16498,9 @@ packages: inherits: 2.0.4 is-arguments: 1.1.1 is-generator-function: 1.0.10 - is-typed-array: 1.1.9 + is-typed-array: 1.1.12 safe-buffer: 5.2.1 - which-typed-array: 1.1.8 + which-typed-array: 1.1.11 /utils-merge/1.0.1: resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} @@ -17294,6 +17424,16 @@ packages: is-number-object: 1.0.7 is-string: 1.0.7 is-symbol: 1.0.4 + dev: true + + /which-collection/1.0.1: + resolution: {integrity: sha512-W8xeTUwaln8i3K/cY1nGXzdnVZlidBcagyNFtBdD5kxnb4TvGKR7FfSIS3mYpwWS1QUCutfKz8IY8RjftB0+1A==} + dependencies: + is-map: 2.0.2 + is-set: 2.0.2 + is-weakmap: 2.0.1 + is-weakset: 2.0.2 + dev: true /which-module/1.0.0: resolution: {integrity: sha512-F6+WgncZi/mJDrammbTuHe1q0R5hOXv/mBaiNA2TCNT/LTHusX0V+CJnj9XT8ki5ln2UZyyddDgHfCzyrOH7MQ==} @@ -17302,16 +17442,15 @@ packages: /which-module/2.0.0: resolution: {integrity: sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==} - /which-typed-array/1.1.8: - resolution: {integrity: sha512-Jn4e5PItbcAHyLoRDwvPj1ypu27DJbtdYXUa5zsinrUx77Uvfb0cXwwnGMTn7cjUfhhqgVQnVJCwF+7cgU7tpw==} + /which-typed-array/1.1.11: + resolution: {integrity: sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==} engines: {node: '>= 0.4'} dependencies: available-typed-arrays: 1.0.5 call-bind: 1.0.2 - es-abstract: 1.20.4 for-each: 0.3.3 + gopd: 1.0.1 has-tostringtag: 1.0.0 - is-typed-array: 1.1.9 /which/1.3.1: resolution: {integrity: sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==} diff --git a/src/assets/address/DynamicAddressIcon.tsx b/src/assets/address/DynamicAddressIcon.tsx index da3ca2b63..feaba70aa 100644 --- a/src/assets/address/DynamicAddressIcon.tsx +++ b/src/assets/address/DynamicAddressIcon.tsx @@ -12,7 +12,7 @@ export const DynamicAddressIcon = ({ }) => { if (name.toLowerCase() in dynamicAddressIcons) { const key = name.toLowerCase() as DynamicAddressIconName - const Icon = dynamicAddressIcons[key] as any + const Icon = dynamicAddressIcons[key] return } if (showDefault) { diff --git a/src/constants/chains.ts b/src/constants/chains.ts new file mode 100644 index 000000000..96ba7b1b1 --- /dev/null +++ b/src/constants/chains.ts @@ -0,0 +1,73 @@ +import type { Address } from 'viem' +import { goerli, localhost, mainnet, sepolia } from 'wagmi/chains' + +import { addEnsContracts } from '@ensdomains/ensjs' + +type ContractName = + | 'BaseRegistrarImplementation' + | 'ETHRegistrarController' + | 'Multicall' + | 'NameWrapper' + | 'DNSRegistrar' + | 'PublicResolver' + | 'ENSRegistry' + | 'ReverseRegistrar' + | 'UniversalResolver' + | 'StaticBulkRenewal' + | 'DNSSECImpl' + | 'LegacyDNSRegistrar' + | 'LegacyDNSSECImpl' + | 'LegacyPublicResolver' + +export const deploymentAddresses = JSON.parse(process.env.DEPLOYMENT_ADDRESSES! || '{}') as Record< + ContractName | 'ENSRegistry', + Address +> + +export const localhostWithEns = { + ...localhost, + contracts: { + ensRegistry: { + address: deploymentAddresses.ENSRegistry, + }, + ensUniversalResolver: { + address: deploymentAddresses.UniversalResolver, + }, + multicall3: { + address: deploymentAddresses.Multicall, + }, + ensBaseRegistrarImplementation: { + address: deploymentAddresses.BaseRegistrarImplementation, + }, + ensDnsRegistrar: { + address: deploymentAddresses.LegacyDNSRegistrar, + }, + ensEthRegistrarController: { + address: deploymentAddresses.ETHRegistrarController, + }, + ensNameWrapper: { + address: deploymentAddresses.NameWrapper, + }, + ensPublicResolver: { + address: deploymentAddresses.PublicResolver, + }, + ensReverseRegistrar: { + address: deploymentAddresses.ReverseRegistrar, + }, + ensBulkRenewal: { + address: deploymentAddresses.StaticBulkRenewal, + }, + ensDnssecImpl: { + address: deploymentAddresses.LegacyDNSSECImpl, + }, + }, + subgraphs: { + ens: { + url: 'http://localhost:8000/subgraphs/name/graphprotocol/ens', + }, + }, +} as const + +export const mainnetWithEns = addEnsContracts(mainnet) +export const goerliWithEns = addEnsContracts(goerli) +export const sepoliaWithEns = addEnsContracts(sepolia) diff --git a/src/constants/resolverAddressData.test.ts b/src/constants/resolverAddressData.test.ts new file mode 100644 index 000000000..b9934cb60 --- /dev/null +++ b/src/constants/resolverAddressData.test.ts @@ -0,0 +1,23 @@ +import { getChainContractAddress } from 'viem/utils' + +import { goerliWithEns, localhostWithEns, mainnetWithEns, sepoliaWithEns } from './chains' + +;(process.env as any).NODE_ENV = 'development' + +it('should have the most recent resolver as the first address', async () => { + // dynamic import for NODE_ENV to be set + const { KNOWN_RESOLVER_DATA } = await import('./resolverAddressData') + + expect(KNOWN_RESOLVER_DATA['1']![0].address).toEqual( + getChainContractAddress({ chain: mainnetWithEns, contract: 'ensPublicResolver' }), + ) + expect(KNOWN_RESOLVER_DATA['1337']![0].address).toEqual( + getChainContractAddress({ chain: localhostWithEns, contract: 'ensPublicResolver' }), + ) + expect(KNOWN_RESOLVER_DATA['5']![0].address).toEqual( + getChainContractAddress({ chain: goerliWithEns, contract: 'ensPublicResolver' }), + ) + expect(KNOWN_RESOLVER_DATA['11155111']![0].address).toEqual( + getChainContractAddress({ chain: sepoliaWithEns, contract: 'ensPublicResolver' }), + ) +}) diff --git a/src/constants/resolverAddressData.ts b/src/constants/resolverAddressData.ts index f443067fd..1c1aa56a5 100644 --- a/src/constants/resolverAddressData.ts +++ b/src/constants/resolverAddressData.ts @@ -1,7 +1,6 @@ import { Address } from 'viem' -import { deploymentAddresses } from '@app/utils/query' - +import { deploymentAddresses } from './chains' import { RESOLVER_INTERFACE_IDS, ResolverInterfaceId } from './resolverInterfaceIds' type KnownResolverItem = { diff --git a/src/hooks/useAdvancedEditor.ts b/src/hooks/useAdvancedEditor.ts index c11b6bc33..be027328b 100644 --- a/src/hooks/useAdvancedEditor.ts +++ b/src/hooks/useAdvancedEditor.ts @@ -184,6 +184,7 @@ const useAdvancedEditor = ({ profile, isLoading, overwrites, callback }: Props) abi: formObject.abi, }, } + reset(newDefaultValues) const newExistingRecords: ExpandableRecordsState = { address: Object.keys(newDefaultValues.address) || [], @@ -204,6 +205,7 @@ const useAdvancedEditor = ({ profile, isLoading, overwrites, callback }: Props) const formKey = formSafeKey(String(coin)) setValue(`address.${formKey}`, value!, { shouldDirty: true }) if (!newExistingRecords.address.includes(formKey)) { + newExistingRecords.address.push(formKey) } }) @@ -224,14 +226,14 @@ const useAdvancedEditor = ({ profile, isLoading, overwrites, callback }: Props) value, })) as { key: string; value: string }[] - const coinTypes = Object.entries(getFieldsByType('addr', dirtyFields)).map(([key, value]) => ({ - key, + const coins = Object.entries(getFieldsByType('addr', dirtyFields)).map(([coin, value]) => ({ + coin, value, - })) as { key: string; value: string }[] + })) as { coin: string; value: string }[] - const coinTypesWithZeroAddressses = coinTypes.map((coinType) => { + const coinTypesWithZeroAddressses = coins.map((coinType) => { if (coinType.value) return coinType - return { key: coinType.key, value: emptyAddress } + return { coin: coinType.coin, value: emptyAddress } }) const contentHash = dirtyFields.other?.contentHash @@ -244,9 +246,9 @@ const useAdvancedEditor = ({ profile, isLoading, overwrites, callback }: Props) ) .otherwise(() => undefined) - const records = { + const records: RecordOptions = { texts, - coinTypes: coinTypesWithZeroAddressses, + coins: coinTypesWithZeroAddressses, contentHash, abi, } diff --git a/src/hooks/usePublicClient.ts b/src/hooks/usePublicClient.ts index e54b64bea..b82297d3e 100644 --- a/src/hooks/usePublicClient.ts +++ b/src/hooks/usePublicClient.ts @@ -3,6 +3,6 @@ import { usePublicClient as usePublicClient_ } from 'wagmi' import { PublicClientWithChain } from '@app/types' -export const usePublicClient = usePublicClient_ as ({ - chainId, -}?: Partial) => TPublicClient +export const usePublicClient = usePublicClient_ as ( + args?: Partial, +) => TPublicClient diff --git a/src/test-utils.tsx b/src/test-utils.tsx index 0b5f7c827..55b6db8c2 100644 --- a/src/test-utils.tsx +++ b/src/test-utils.tsx @@ -18,7 +18,7 @@ import { DeepPartial } from './types' window.scroll = jest.fn() jest.mock('@app/hooks/useRegistrationReducer', () => jest.fn(() => ({ item: { stepIndex: 0 } }))) -jest.mock('@app/hooks/useChainId', () => ({ useChainId: () => 1 })) +jest.mock('@app/hooks/chain/useChainId', () => ({ useChainId: () => 1 })) export const mockUseAccountReturnValue = { address: '0x123' } @@ -43,10 +43,8 @@ jest.mock('wagmi', () => { useBalance: jest.fn(() => ({ data: { value: { lt: () => false } } })), useNetwork: jest.fn(() => ({ chainId: 1 })), useFeeData: jest.fn(), - useProvider: jest.fn(() => ({ - providerConfigs: [{ provider: { send: jest.fn(() => ({ gasUsed: 0, accessList: [] })) } }], - })), useSigner: jest.fn(), + usePublicClient: jest.fn(), useSignTypedData: jest.fn(), useBlockNumber: jest.fn(), useSendTransaction: jest.fn(), diff --git a/src/transaction-flow/input/AdvancedEditor/AdvancedEditor-flow.tsx b/src/transaction-flow/input/AdvancedEditor/AdvancedEditor-flow.tsx index 113b727b9..d83e7ed42 100644 --- a/src/transaction-flow/input/AdvancedEditor/AdvancedEditor-flow.tsx +++ b/src/transaction-flow/input/AdvancedEditor/AdvancedEditor-flow.tsx @@ -9,7 +9,7 @@ import AddRecord from '@app/components/@molecules/AdvancedEditor/AddRecord' import AdvancedEditorContent from '@app/components/@molecules/AdvancedEditor/AdvancedEditorTabContent' import AdvancedEditorTabs from '@app/components/@molecules/AdvancedEditor/AdvancedEditorTabs' import useAdvancedEditor from '@app/hooks/useAdvancedEditor' -import { useNameDetails } from '@app/hooks/useNameDetails' +import { useProfile } from '@app/hooks/useProfile' import { TransactionItem, makeTransactionItem } from '@app/transaction-flow/transaction' import type { TransactionDialogPassthrough } from '@app/transaction-flow/types' @@ -87,7 +87,7 @@ const AdvancedEditor = ({ data, transactions = [], dispatch, onDismiss }: Props) (item: TransactionItem) => item.name === 'updateProfile', ) as TransactionItem<'updateProfile'> - const { profile, isLoading: isProfileLoading } = useNameDetails({ name }) + const { data: profile, isLoading: isProfileLoading } = useProfile({ name }) const handleCreateTransaction = useCallback( (records: RecordOptions) => { diff --git a/src/transaction-flow/input/AdvancedEditor/AdvancedEditor.test.tsx b/src/transaction-flow/input/AdvancedEditor/AdvancedEditor.test.tsx index ebbf8df1c..03fb9a4e7 100644 --- a/src/transaction-flow/input/AdvancedEditor/AdvancedEditor.test.tsx +++ b/src/transaction-flow/input/AdvancedEditor/AdvancedEditor.test.tsx @@ -10,124 +10,109 @@ import { within, } from '@app/test-utils' -import { useNameDetails } from '@app/hooks/useNameDetails' +import { useProfile } from '@app/hooks/useProfile' import { useResolverHasInterfaces } from '@app/hooks/useResolverHasInterfaces' -import { Profile } from '@app/types' import { convertFormSafeKey, formSafeKey } from '@app/utils/editor' import AdvancedEditor from './AdvancedEditor-flow' const mockProfileData = { - profile: { - address: '0x70643CB203137b9b9eE19deA56080CD2BA01dBFd', - records: { - contentHash: {}, - texts: [ - { - key: 'email', - type: 'text', - value: 'test@ens.domains', - }, - { - key: 'url', - type: 'text', - value: 'https://ens.domains', - }, - { - key: 'avatar', - type: 'text', - value: 'https://example.xyz/avatar/test.jpg', - }, - { - key: 'com.discord', - type: 'text', - value: 'test', - }, - { - key: 'com.reddit', - type: 'text', - value: 'https://www.reddit.com/user/test/', - }, - { - key: 'com.twitter', - type: 'text', - value: 'https://twitter.com/test', - }, - { - key: 'org.telegram', - type: 'text', - value: '@test', - }, - { - key: 'com.linkedin.com', - type: 'text', - value: 'https://www.linkedin.com/in/test/', - }, - { - key: 'xyz.lensfrens', - type: 'text', - value: 'https://www.lensfrens.xyz/test.lens', - }, - ], - coinTypes: [ - { - key: '60', - type: 'addr', - coin: 'ETH', - addr: '0xb794f5ea0ba39494ce839613fffba74279579268', - }, - { - key: '0', - type: 'addr', - coin: 'BTC', - addr: '1JnJvEBykLcGHYxCZVWgDGDm7pkK3EBHwB', - }, - { - key: '3030', - type: 'addr', - coin: 'HBAR', - addr: '0.0.123123', - }, + data: { + address: '0x70643CB203137b9b9eE19deA56080CD2BA01dBFd' as const, + contentHash: null, + texts: [ + { + key: 'email', + value: 'test@ens.domains', + }, + { + key: 'url', + value: 'https://ens.domains', + }, + { + key: 'avatar', + value: 'https://example.xyz/avatar/test.jpg', + }, + { + key: 'com.discord', + value: 'test', + }, + { + key: 'com.reddit', + value: 'https://www.reddit.com/user/test/', + }, + { + key: 'com.twitter', + value: 'https://twitter.com/test', + }, + { + key: 'org.telegram', + value: '@test', + }, + { + key: 'com.linkedin.com', + value: 'https://www.linkedin.com/in/test/', + }, + { + key: 'xyz.lensfrens', + value: 'https://www.lensfrens.xyz/test.lens', + }, + ], + coins: [ + { + id: 60, + name: 'ETH', + value: '0xb794f5ea0ba39494ce839613fffba74279579268', + }, + { + id: 0, + name: 'BTC', + value: '1JnJvEBykLcGHYxCZVWgDGDm7pkK3EBHwB', + }, + { + id: 3030, + name: 'HBAR', + value: '0.0.123123', + }, + { + id: 501, + name: 'SOL', + value: 'HN7cABqLq46Es1jh92dQQisAq662SmxELLLsHHe4YWrH', + }, + ], + abi: { + abi: JSON.stringify([ { - key: '501', - type: 'addr', - coin: 'SOL', - addr: 'HN7cABqLq46Es1jh92dQQisAq662SmxELLLsHHe4YWrH', + inputs: [ + { + internalType: 'string', + type: 'string', + name: 'name', + }, + ], + stateMutability: 'nonpayable', + outputs: [], + name: 'setName', + type: 'function', }, - ], - abi: { - data: JSON.stringify([ - { - inputs: [ - { - internalType: 'string', - type: 'string', - name: 'name', - }, - ], - stateMutability: 'nonpayable', - outputs: [], - name: 'setName', - type: 'function', - }, - ]), - contentType: 1, - }, + ]), + contentType: 1, }, - resolverAddress: '0x0', + resolverAddress: '0x0' as const, isMigrated: true, - createdAt: '1630553876', + createdAt: { + date: new Date(1630553876), + value: 1630553876, + }, }, isLoading: false, - isWrapped: false, } -jest.mock('@app/utils/EnsProvider') -jest.mock('@app/hooks/useNameDetails') +jest.mock('@app/hooks/useProfile') jest.mock('@app/transaction-flow/TransactionFlowProvider') jest.mock('@app/hooks/useResolverHasInterfaces') -const mockUseProfile = mockFunction(useNameDetails) +const mockUseProfile = mockFunction(useProfile) const mockUseResolverHasInterfaces = mockFunction(useResolverHasInterfaces) const mockIntersectionObserver = jest.fn() @@ -136,12 +121,10 @@ const mockDispatch = jest.fn() describe('AdvancedEditor', () => { beforeEach(() => { - mockUseProfile.mockReturnValue( - mockProfileData as unknown as { profile: Profile; loading: boolean }, - ) + mockUseProfile.mockReturnValue(mockProfileData) mockUseResolverHasInterfaces.mockReturnValue({ - hasInterface: true, + data: [true], isLoading: false, status: 'success', }) @@ -182,8 +165,7 @@ describe('AdvancedEditor', () => { await waitFor(() => { expect(submitBtn).not.toHaveAttribute('disabled') }) - fireEvent.click(submitBtn) - fireEvent.submit(screen.getByTestId('advanced-editor')) + userEvent.click(submitBtn) await waitFor(() => { expect(mockDispatch).toHaveBeenCalled() @@ -212,8 +194,7 @@ describe('AdvancedEditor', () => { await waitFor(() => { expect(submitBtn).not.toHaveAttribute('disabled') }) - fireEvent.click(submitBtn) - fireEvent.submit(screen.getByTestId('advanced-editor')) + userEvent.click(submitBtn) await waitFor(() => { expect(mockDispatch).toHaveBeenCalled() @@ -242,8 +223,7 @@ describe('AdvancedEditor', () => { await waitFor(() => { expect(submitBtn).not.toHaveAttribute('disabled') }) - fireEvent.click(submitBtn) - fireEvent.submit(screen.getByTestId('advanced-editor')) + userEvent.click(submitBtn) await waitFor(() => { expect(mockDispatch).toHaveBeenCalled() @@ -270,17 +250,16 @@ describe('AdvancedEditor', () => { await waitFor(() => { expect(submitBtn).not.toHaveAttribute('disabled') }) - fireEvent.click(submitBtn) - fireEvent.submit(screen.getByTestId('advanced-editor')) + userEvent.click(submitBtn) await waitFor(() => { expect(mockDispatch).toHaveBeenCalled() }) - expect(mockDispatch.mock.calls[0][0].payload[0].data.records.coinTypes[0]).toEqual({ - key: 'ETH', + expect(mockDispatch.mock.calls[0][0].payload[0].data.records.coins[0]).toEqual({ + coin: 'ETH', value: '0x0000000000000000000000000000000000000000', }) - expect(mockDispatch.mock.calls[0][0].payload[0].data.records.coinTypes.length).toBe(1) + expect(mockDispatch.mock.calls[0][0].payload[0].data.records.coins.length).toBe(1) }) it('should submit key/value when new address is added', async () => { @@ -307,16 +286,15 @@ describe('AdvancedEditor', () => { expect(submitBtn).not.toHaveAttribute('disabled') }) await userEvent.click(submitBtn) - fireEvent.submit(screen.getByTestId('advanced-editor')) await waitFor(() => { expect(mockDispatch).toHaveBeenCalled() }) - expect(mockDispatch.mock.calls[0][0].payload[0].data.records.coinTypes[0]).toEqual({ - key: 'DOT', + expect(mockDispatch.mock.calls[0][0].payload[0].data.records.coins[0]).toEqual({ + coin: 'DOT', value: '5F3sa2TJAWMqDhXG6jhV4N8ko9SxwGy8TpaNS1repo5EYjQX', }) - expect(mockDispatch.mock.calls[0][0].payload[0].data.records.coinTypes.length).toBe(1) + expect(mockDispatch.mock.calls[0][0].payload[0].data.records.coins.length).toBe(1) }) it('should overwrite existing records and add new records for records passed in transactions', async () => { @@ -346,13 +324,13 @@ describe('AdvancedEditor', () => { value: 'test@ens.domains', }, ], - coinTypes: [ + coins: [ { - key: 'BNB', + coin: 'BNB', value: 'bnb1g5p04snezgpky203fq6da9qyjsy2k9kzr5yuhl', }, { - key: 'ETH', + coin: 'ETH', value: '0x71C7656EC7ab88b098defB751B7401B5f6d8976F', }, ], @@ -444,7 +422,8 @@ describe('AdvancedEditor', () => { expect(mockDispatch).toHaveBeenCalled() }) expect(mockDispatch.mock.calls[0][0].payload[0].data.records.abi).toEqual({ - data: '', + contentType: 0, + encodedData: null, }) }) }) diff --git a/src/transaction-flow/transaction/registerName.test.ts b/src/transaction-flow/transaction/registerName.test.ts index f472c0e35..2b34d3ce9 100644 --- a/src/transaction-flow/transaction/registerName.test.ts +++ b/src/transaction-flow/transaction/registerName.test.ts @@ -1,25 +1,25 @@ -import { BigNumber } from '@ethersproject/bignumber' +import { mockFunction } from '@app/test-utils' -import registerName from './registerName' +import { getPrice } from '@ensdomains/ensjs/public' +import { registerName } from '@ensdomains/ensjs/wallet' -const mockEns = { - getPrice: async () => ({ - base: BigNumber.from(100), - premium: BigNumber.from(0), - }), - registerName: { - populateTransaction: (...args: any[]) => args, - }, -} +import registerNameFlowTransaction from './registerName' + +jest.mock('@ensdomains/ensjs/public') +jest.mock('@ensdomains/ensjs/wallet') + +const mockGetPrice = mockFunction(getPrice) +const mockRegisterName = mockFunction(registerName.makeFunctionData) + +mockGetPrice.mockImplementation(async () => ({ base: 100n, premium: 0n })) +mockRegisterName.mockImplementation((...args: any[]) => args as any) it('adds a 2% value buffer to the transaction from the real price', async () => { - const result = (await registerName.transaction( - {} as any, - mockEns as any, - { - name: 'test.eth', - } as any, - )) as [string, { value: BigNumber }] + const result = (await registerNameFlowTransaction.transaction({ + publicClient: {} as any, + walletClient: { walletClient: true } as any, + data: { name: 'test.eth' } as any, + })) as unknown as [{ walletClient: true }, { name: string; value: bigint }] const data = result[1] - expect(data.value).toEqual(BigNumber.from(102)) + expect(data.value).toEqual(102n) }) diff --git a/src/transaction-flow/transaction/unwrapName.test.ts b/src/transaction-flow/transaction/unwrapName.test.ts index 1ec4dd581..a19af8b6c 100644 --- a/src/transaction-flow/transaction/unwrapName.test.ts +++ b/src/transaction-flow/transaction/unwrapName.test.ts @@ -1,4 +1,14 @@ -import unwrapName from './unwrapName' +import { mockFunction } from '@app/test-utils' + +import { unwrapName } from '@ensdomains/ensjs/wallet' + +import { PublicClientWithChain, WalletClientWithAccount } from '@app/types' + +import unwrapNameFlowTransaction from './unwrapName' + +jest.mock('@ensdomains/ensjs/wallet') + +const mockUnwrapName = mockFunction(unwrapName.makeFunctionData) describe('unwrapName', () => { const name = 'myname.eth' @@ -7,7 +17,7 @@ describe('unwrapName', () => { describe('displayItems', () => { it('returns the correct display items', () => { const t = (key: string) => key - const items = unwrapName.displayItems(data, t) + const items = unwrapNameFlowTransaction.displayItems(data, t) expect(items).toEqual([ { label: 'action', @@ -24,36 +34,42 @@ describe('unwrapName', () => { describe('transaction', () => { const address = '0x123' - const signer: any = { getAddress: () => Promise.resolve(address) } - const mockPopulateTransaction = jest.fn() - const ens = { unwrapName: { populateTransaction: mockPopulateTransaction } } as any + const walletClient = { account: { address } } as unknown as WalletClientWithAccount + const publicClient = {} as PublicClientWithChain afterEach(() => { jest.clearAllMocks() }) it('should provide controller and registrant when name is an eth 2ld', async () => { - await unwrapName.transaction(signer, ens, data) - expect(mockPopulateTransaction).toHaveBeenCalledWith( - name, + await unwrapNameFlowTransaction.transaction({ + walletClient, + publicClient, + data: { name: 'test.eth' }, + }) + expect(mockUnwrapName).toHaveBeenCalledWith( + walletClient, expect.objectContaining({ - newController: address, - newRegistrant: address, - signer, + name: 'test.eth', + newOwnerAddress: address, + newRegistrantAddress: address, }), ) }) it('should not provide registrant when name is not an eth 2ld', async () => { - const subname = 'sub.myname.eth' + const subname = 'sub.test.eth' const dataWithSubname = { name: subname } - await unwrapName.transaction(signer, ens, dataWithSubname) - expect(mockPopulateTransaction).toHaveBeenCalledWith( - subname, + await unwrapNameFlowTransaction.transaction({ + walletClient, + publicClient, + data: dataWithSubname, + }) + expect(mockUnwrapName).toHaveBeenCalledWith( + walletClient, expect.objectContaining({ - newController: address, - newRegistrant: undefined, - signer, + name: 'sub.test.eth', + newOwnerAddress: address, }), ) }) diff --git a/src/utils/SyncProvider/SyncDroppedTransaction.test.tsx b/src/utils/SyncProvider/SyncDroppedTransaction.test.tsx index d7cffca29..8d33f3103 100644 --- a/src/utils/SyncProvider/SyncDroppedTransaction.test.tsx +++ b/src/utils/SyncProvider/SyncDroppedTransaction.test.tsx @@ -1,12 +1,13 @@ -import { render } from '@app/test-utils' +import { mockFunction, render } from '@app/test-utils' import { rest } from 'msw' import { setupServer } from 'msw/node' -import { useProvider } from 'wagmi' import { useAccountSafely } from '@app/hooks/account/useAccountSafely' import { useTransactionStore } from '@app/hooks/transactions/TransactionStoreContext' import { useRecentTransactions } from '@app/hooks/transactions/useRecentTransactions' +import { usePublicClient } from '@app/hooks/usePublicClient' +import { PublicClientWithChain } from '@app/types' import { SyncDroppedTransaction, @@ -34,23 +35,29 @@ export const handlers = [ export const server = setupServer(...handlers) -jest.mock('wagmi') -jest.mock('@app/hooks/useAccountSafely') +jest.mock('@app/hooks/account/useAccountSafely') jest.mock('@app/hooks/transactions/useRecentTransactions') jest.mock('@app/hooks/transactions/TransactionStoreContext') +jest.mock('@app/hooks/usePublicClient') + +const mockUsePublicClient = mockFunction(usePublicClient) +const mockUseAccountSafely = mockFunction(useAccountSafely) +const mockUseRecentTransactions = mockFunction(useRecentTransactions) +const mockUseTransactionStore = mockFunction(useTransactionStore) + +console.log('mockUsePublicClient', mockUseAccountSafely) describe('SyncDroppedTransaction', () => { - const mockProvider = { test: 'provider' } + const mockPublicClient = { chain: { id: 1 } } const mockAddress = '0x1234567890abcdef' - const mockTransactions = [{ hash: '0xabc123' }, { hash: '0xdef456' }] + const mockTransactions = [{ hash: '0xabc123' as const }, { hash: '0xdef456' as const }] const mockStore = { test: 'store' } - const mockChainId = 1 beforeEach(() => { - useProvider.mockReturnValue(mockProvider) - useAccountSafely.mockReturnValue({ address: mockAddress }) - useRecentTransactions.mockReturnValue(mockTransactions) - useTransactionStore.mockReturnValue(mockStore) + mockUsePublicClient.mockReturnValue(mockPublicClient) + mockUseAccountSafely.mockReturnValue({ address: mockAddress }) + mockUseRecentTransactions.mockReturnValue(mockTransactions) + mockUseTransactionStore.mockReturnValue(mockStore as any) }) afterEach(() => { @@ -59,7 +66,7 @@ describe('SyncDroppedTransaction', () => { it('should call setInterval with the correct arguments', () => { const mockDelay = 10000 - jest.spyOn(global, 'setInterval').mockImplementation((fn) => fn()) + jest.spyOn(global, 'setInterval').mockImplementation((fn: any) => fn()) render(Test) @@ -109,19 +116,16 @@ describe('findDroppedTransactions', () => { describe('searchingTransactions', () => { it('should exit early if there is no connected account', async () => { - const mockTransactions = [] + const mockPublicClient = { chain: { id: 1 } } as PublicClientWithChain + const mockTransactions: any[] = [] const mockAddress = undefined const mockStore = undefined - const mockChainId = undefined - const mockProvider = undefined - - const result = await findDroppedTransactions( - mockTransactions, - mockAddress, - mockStore, - mockChainId, - mockProvider, - ) + + const result = await findDroppedTransactions(mockPublicClient, { + address: mockAddress, + store: mockStore, + transactions: mockTransactions, + }) expect(result).toBeUndefined() }) @@ -134,20 +138,17 @@ describe('findDroppedTransactions', () => { { status: 'confirmed', }, - ] + ] as any const mockAddress = '0x1234567890abcdef' - const mockStore = {} - const mockChainId = 1 - const mockProvider = {} - - const result = await findDroppedTransactions( - mockTransactions, - mockAddress, - mockStore, - mockChainId, - mockProvider, - ) + const mockStore = {} as any + const mockPublicClient = { chain: { id: 1 } } as PublicClientWithChain + + const result = await findDroppedTransactions(mockPublicClient, { + address: mockAddress, + store: mockStore, + transactions: mockTransactions, + }) expect(result).toBeUndefined() }) @@ -158,18 +159,16 @@ describe('findDroppedTransactions', () => { searchStatus: 'searching', hash: '0xabc123', }, - ] + ] as any const mockAddress = '0x1234567890abcdef' - const mockStore = { foundMinedTransaction: jest.fn() } - const mockChainId = 1 - const mockProvider = { test: 'provider' } - await findDroppedTransactions( - mockTransactions, - mockAddress, - mockStore, - mockChainId, - mockProvider, - ) + const mockStore = { foundMinedTransaction: jest.fn() } as any + const mockPublicClient = { chain: { id: 1 } } as PublicClientWithChain + + await findDroppedTransactions(mockPublicClient, { + address: mockAddress, + store: mockStore, + transactions: mockTransactions, + }) expect(mockStore.foundMinedTransaction).toHaveBeenCalled() }) it('should error if there is more than one transaction that could be a replacement', async () => { @@ -198,18 +197,16 @@ describe('findDroppedTransactions', () => { input: 'input', timestamp: 0, }, - ] + ] as any const mockAddress = '0x1234567890abcdef' - const mockStore = { setReplacedTransaction: jest.fn() } - const mockChainId = 1 - const mockProvider = { test: 'provider' } - await findDroppedTransactions( - mockTransactions, - mockAddress, - mockStore, - mockChainId, - mockProvider, - ) + const mockStore = { setReplacedTransaction: jest.fn() } as any + const mockPublicClient = { chain: { id: 1 } } as PublicClientWithChain + + await findDroppedTransactions(mockPublicClient, { + address: mockAddress, + store: mockStore, + transactions: mockTransactions, + }) expect(mockStore.setReplacedTransaction).not.toHaveBeenCalled() }) it('should set replaced transaction if there is a unique candidate', async () => { @@ -219,18 +216,16 @@ describe('findDroppedTransactions', () => { input: 'input', timestamp: 0, }, - ] + ] as any const mockAddress = '0x1234567890abcdef' - const mockStore = { setReplacedTransaction: jest.fn() } - const mockChainId = 1 - const mockProvider = { test: 'provider' } - await findDroppedTransactions( - mockTransactions, - mockAddress, - mockStore, - mockChainId, - mockProvider, - ) + const mockStore = { setReplacedTransaction: jest.fn() } as any + const mockPublicClient = { chain: { id: 1 } } as PublicClientWithChain + + await findDroppedTransactions(mockPublicClient, { + address: mockAddress, + store: mockStore, + transactions: mockTransactions, + }) expect(mockStore.setReplacedTransaction).toHaveBeenCalled() }) it('should try to find the searching transaction again as a failsafe if it was not found, was not a replacement etc', async () => { @@ -240,18 +235,19 @@ describe('findDroppedTransactions', () => { input: 'notReplacement', timestamp: 0, }, - ] + ] as any const mockAddress = '0x1234567890abcdef' - const mockStore = { foundTransaction: jest.fn() } - const mockChainId = 1 - const mockProvider = { getTransaction: () => ({}) } - await findDroppedTransactions( - mockTransactions, - mockAddress, - mockStore, - mockChainId, - mockProvider, - ) + const mockStore = { foundTransaction: jest.fn() } as any + const mockPublicClient = { + chain: { id: 1 }, + getTransaction: () => Promise.resolve({}), + } as unknown as PublicClientWithChain + + await findDroppedTransactions(mockPublicClient, { + address: mockAddress, + store: mockStore, + transactions: mockTransactions, + }) expect(mockStore.foundTransaction).toHaveBeenCalled() }) it('should handle cancelled transactions', async () => { @@ -261,18 +257,19 @@ describe('findDroppedTransactions', () => { input: 'notReplacement', timestamp: 0, }, - ] + ] as any const mockAddress = '0x1234567890abcdef' - const mockStore = { setFailedTransaction: jest.fn() } - const mockChainId = 1 - const mockProvider = { getTransaction: () => null } - await findDroppedTransactions( - mockTransactions, - mockAddress, - mockStore, - mockChainId, - mockProvider, - ) + const mockStore = { setFailedTransaction: jest.fn() } as any + const mockPublicClient = { + chain: { id: 1 }, + getTransaction: () => Promise.resolve(null), + } as unknown as PublicClientWithChain + + await findDroppedTransactions(mockPublicClient, { + address: mockAddress, + store: mockStore, + transactions: mockTransactions, + }) expect(mockStore.setFailedTransaction).toHaveBeenCalled() }) it('should update the retries count if all else fails', async () => { @@ -282,18 +279,19 @@ describe('findDroppedTransactions', () => { input: 'notReplacement', timestamp: 2, }, - ] + ] as any const mockAddress = '0x1234567890abcdef' - const mockStore = { updateRetries: jest.fn() } - const mockChainId = 1 - const mockProvider = { getTransaction: () => null } - await findDroppedTransactions( - mockTransactions, - mockAddress, - mockStore, - mockChainId, - mockProvider, - ) + const mockStore = { updateRetries: jest.fn() } as any + const mockPublicClient = { + chain: { id: 1 }, + getTransaction: () => Promise.resolve(null), + } as unknown as PublicClientWithChain + + await findDroppedTransactions(mockPublicClient, { + address: mockAddress, + store: mockStore, + transactions: mockTransactions, + }) expect(mockStore.updateRetries).toHaveBeenCalled() }) }) @@ -308,18 +306,20 @@ describe('findDroppedTransactions', () => { timestamp: 0, nonce: 0, }, - ] + ] as any const mockAddress = '0x1234567890abcdef' - const mockStore = { setReplacedTransactionByNonce: jest.fn() } - const mockChainId = 1 - const mockProvider = { getTransaction: () => null, getTransactionCount: () => 1 } - await findDroppedTransactions( - mockTransactions, - mockAddress, - mockStore, - mockChainId, - mockProvider, - ) + const mockStore = { setReplacedTransactionByNonce: jest.fn() } as any + const mockPublicClient = { + chain: { id: 1 }, + getTransaction: () => Promise.resolve(null), + getTransactionCount: () => Promise.resolve(1), + } as unknown as PublicClientWithChain + + await findDroppedTransactions(mockPublicClient, { + address: mockAddress, + store: mockStore, + transactions: mockTransactions, + }) expect(mockStore.setReplacedTransactionByNonce).toHaveBeenCalled() }) @@ -332,21 +332,23 @@ describe('findDroppedTransactions', () => { timestamp: 0, nonce: 0, }, - ] + ] as any const mockAddress = '0x1234567890abcdef' const mockStore = { setReplacedTransactionByNonce: jest.fn(), setFailedTransaction: jest.fn(), - } - const mockChainId = 1 - const mockProvider = { getTransaction: () => null, getTransactionCount: () => 3 } - await findDroppedTransactions( - mockTransactions, - mockAddress, - mockStore, - mockChainId, - mockProvider, - ) + } as any + const mockPublicClient = { + chain: { id: 1 }, + getTransaction: () => Promise.resolve(null), + getTransactionCount: () => Promise.resolve(3), + } as unknown as PublicClientWithChain + + await findDroppedTransactions(mockPublicClient, { + address: mockAddress, + store: mockStore, + transactions: mockTransactions, + }) expect(mockStore.setReplacedTransactionByNonce).not.toHaveBeenCalled() expect(mockStore.setFailedTransaction).not.toHaveBeenCalled() }) @@ -360,18 +362,20 @@ describe('findDroppedTransactions', () => { timestamp: 0, nonce: 0, }, - ] + ] as any const mockAddress = '0x1234567890abcdef' - const mockStore = { setFailedTransaction: jest.fn() } - const mockChainId = 1 - const mockProvider = { getTransaction: () => null, getTransactionCount: () => 1 } - await findDroppedTransactions( - mockTransactions, - mockAddress, - mockStore, - mockChainId, - mockProvider, - ) + const mockStore = { setFailedTransaction: jest.fn() } as any + const mockPublicClient = { + chain: { id: 1 }, + getTransaction: () => Promise.resolve(null), + getTransactionCount: () => Promise.resolve(1), + } as unknown as PublicClientWithChain + + await findDroppedTransactions(mockPublicClient, { + address: mockAddress, + store: mockStore, + transactions: mockTransactions, + }) expect(mockStore.setFailedTransaction).toHaveBeenCalled() }) }) @@ -385,18 +389,20 @@ describe('findDroppedTransactions', () => { timestamp: 0, nonce: 1, }, - ] + ] as any const mockAddress = '0x1234567890abcdef' - const mockStore = { setFailedTransaction: jest.fn() } - const mockChainId = 1 - const mockProvider = { getTransaction: () => null, getTransactionCount: () => 1 } - await findDroppedTransactions( - mockTransactions, - mockAddress, - mockStore, - mockChainId, - mockProvider, - ) + const mockStore = { setFailedTransaction: jest.fn() } as any + const mockPublicClient = { + chain: { id: 1 }, + getTransaction: () => Promise.resolve(null), + getTransactionCount: () => Promise.resolve(1), + } as unknown as PublicClientWithChain + + await findDroppedTransactions(mockPublicClient, { + address: mockAddress, + store: mockStore, + transactions: mockTransactions, + }) expect(mockStore.setFailedTransaction).toHaveBeenCalled() }) }) diff --git a/src/utils/SyncProvider/SyncDroppedTransaction.tsx b/src/utils/SyncProvider/SyncDroppedTransaction.tsx index cc2ed7187..28bf06365 100644 --- a/src/utils/SyncProvider/SyncDroppedTransaction.tsx +++ b/src/utils/SyncProvider/SyncDroppedTransaction.tsx @@ -59,7 +59,7 @@ export const findDroppedTransactions = async ( }: { transactions: Transaction[] address: Address | undefined - store: TransactionStore + store: TransactionStore | undefined }, ) => { const chainId = publicClient.chain.id diff --git a/src/utils/constants.test.ts b/src/utils/constants.test.ts deleted file mode 100644 index 2c4be3226..000000000 --- a/src/utils/constants.test.ts +++ /dev/null @@ -1,11 +0,0 @@ -import { getContractAddress } from '@ensdomains/ensjs/contracts/getContractAddress' - -import { RESOLVER_ADDRESSES } from './constants' - -describe('RESOLVER_ADDRESSES', () => { - it('should have the most recent resolver as the first address', () => { - expect(RESOLVER_ADDRESSES['1'][0]).toEqual(getContractAddress('1')('PublicResolver')) - expect(RESOLVER_ADDRESSES['1337'][0]).toEqual('0x0E801D84Fa97b50751Dbf25036d067dCf18858bF') - expect(RESOLVER_ADDRESSES['5'][0]).toEqual(getContractAddress('5')('PublicResolver')) - }) -}) diff --git a/src/utils/editor.ts b/src/utils/editor.ts index 44c1e22b1..d97c08a0b 100644 --- a/src/utils/editor.ts +++ b/src/utils/editor.ts @@ -36,13 +36,13 @@ export type ProfileFormObject = { export const convertProfileToProfileFormObject = (profile: Profile): ProfileFormObject => { const address = profile.coins?.reduce((map, record) => { - const { id, name, value } = record + const { name, value } = record if (name && supportedAddresses.includes(name.toLowerCase())) { - const newMap = { [id]: value, ...map } + const newMap = { [name]: value, ...map } return newMap } - if (id) { - const newMap = { ...map, [id]: value } + if (name) { + const newMap = { ...map, [name]: value } return newMap } return map @@ -106,7 +106,7 @@ export const convertProfileToProfileFormObject = (profile: Profile): ProfileForm website, abi: profile.abi ? { data: profile.abi.abi as any, contentType: profile.abi.contentType } - : undefined, + : { data: '', contentType: 0 }, } } diff --git a/src/utils/profile.test.ts b/src/utils/profile.test.ts index d22e8678a..4f8b602b0 100644 --- a/src/utils/profile.test.ts +++ b/src/utils/profile.test.ts @@ -1,73 +1,47 @@ -import { Profile } from '@app/types' - import { profileHasRecords } from './profile' describe('profileHasRecords', () => { it('should return true if a text record exists', () => { expect( profileHasRecords({ - records: { texts: [{ key: 'test', value: 'test', type: 'text' }] }, - } as Profile), + texts: [{ key: 'test', value: 'test' }], + }), ).toBe(true) }) it('should return true if a coin record exists', () => { expect( profileHasRecords({ - records: { coinTypes: [{ coin: 'test', key: '', value: 'test', type: 'addr' }] }, - } as Profile), - ).toBe(true) - }) - - it('should return true if a content hash record string exists', () => { - expect( - profileHasRecords({ - records: { contentHash: 'ipfs://contentId' }, - } as Profile), + coins: [{ id: 0, name: 'test', value: 'test' }], + }), ).toBe(true) }) it('should return true if a content hash object string exists', () => { expect( profileHasRecords({ - records: { contentHash: { protocolType: 'ipfs', decoded: 'contentId' } }, - } as Profile), + contentHash: { protocolType: 'ipfs', decoded: 'contentId' }, + }), ).toBe(true) }) it('should return true if an abi record string exists', () => { expect( profileHasRecords({ - records: { abi: { contentType: 1, data: '[{}]' } }, - } as any), + abi: { contentType: 1, abi: '[{}]', decoded: true }, + }), ).toBe(true) }) it('should return false if profile is empty', () => { - expect(profileHasRecords({} as any)).toBe(false) - }) - - it('should return false if records is empty', () => { - expect( - profileHasRecords({ - records: {}, - } as Profile), - ).toBe(false) + expect(profileHasRecords({})).toBe(false) }) it('should return false if contentHash is empty', () => { expect( profileHasRecords({ - records: { contentHash: {} }, - } as Profile), - ).toBe(false) - }) - - it('should return false if contentHash is empty string', () => { - expect( - profileHasRecords({ - records: { contentHash: '' }, - } as Profile), + contentHash: {} as any, + }), ).toBe(false) }) }) diff --git a/src/utils/query.ts b/src/utils/query.ts index 346ceafc5..398e261f8 100644 --- a/src/utils/query.ts +++ b/src/utils/query.ts @@ -1,13 +1,16 @@ import '@rainbow-me/rainbowkit/styles.css' import { DefaultOptions, QueryClient } from '@tanstack/react-query' -import type { Address } from 'viem' import { ChainProviderFn, configureChains, createConfig } from 'wagmi' import { goerli, localhost, mainnet, sepolia } from 'wagmi/chains' import { infuraProvider } from 'wagmi/providers/infura' import { jsonRpcProvider } from 'wagmi/providers/jsonRpc' -import { addEnsContracts } from '@ensdomains/ensjs' - +import { + goerliWithEns, + localhostWithEns, + mainnetWithEns, + sepoliaWithEns, +} from '@app/constants/chains' import { makePersistent } from '@app/utils/persist' import { WC_PROJECT_ID } from './constants' @@ -44,75 +47,6 @@ if (process.env.NEXT_PUBLIC_PROVIDER) { ) } -type ContractName = - | 'BaseRegistrarImplementation' - | 'ETHRegistrarController' - | 'Multicall' - | 'NameWrapper' - | 'DNSRegistrar' - | 'PublicResolver' - | 'ENSRegistry' - | 'ReverseRegistrar' - | 'UniversalResolver' - | 'StaticBulkRenewal' - | 'DNSSECImpl' - | 'LegacyDNSRegistrar' - | 'LegacyDNSSECImpl' - | 'LegacyPublicResolver' - -export const deploymentAddresses = JSON.parse(process.env.DEPLOYMENT_ADDRESSES! || '{}') as Record< - ContractName | 'ENSRegistry', - Address -> - -const localhostWithEns = { - ...localhost, - contracts: { - ensRegistry: { - address: deploymentAddresses.ENSRegistry, - }, - ensUniversalResolver: { - address: deploymentAddresses.UniversalResolver, - }, - multicall3: { - address: deploymentAddresses.Multicall, - }, - ensBaseRegistrarImplementation: { - address: deploymentAddresses.BaseRegistrarImplementation, - }, - ensDnsRegistrar: { - address: deploymentAddresses.LegacyDNSRegistrar, - }, - ensEthRegistrarController: { - address: deploymentAddresses.ETHRegistrarController, - }, - ensNameWrapper: { - address: deploymentAddresses.NameWrapper, - }, - ensPublicResolver: { - address: deploymentAddresses.PublicResolver, - }, - ensReverseRegistrar: { - address: deploymentAddresses.ReverseRegistrar, - }, - ensBulkRenewal: { - address: deploymentAddresses.StaticBulkRenewal, - }, - ensDnssecImpl: { - address: deploymentAddresses.LegacyDNSSECImpl, - }, - }, - subgraphs: { - ens: { - url: 'http://localhost:8000/subgraphs/name/graphprotocol/ens', - }, - }, -} as const - -const mainnetWithEns = addEnsContracts(mainnet) -const goerliWithEns = addEnsContracts(goerli) -const sepoliaWithEns = addEnsContracts(sepolia) - const { publicClient, chains } = configureChains( [mainnetWithEns, goerliWithEns, localhostWithEns, sepoliaWithEns], providerArray, diff --git a/src/utils/records.test.ts b/src/utils/records.test.ts index 140e30993..dbd65cbf1 100644 --- a/src/utils/records.test.ts +++ b/src/utils/records.test.ts @@ -1,60 +1,11 @@ -import { RecordItem } from '@app/types' - import { checkContentHashEqual, checkProfileRecordsContains, checkProfileRecordsEqual, - checkRecordsEqual, makeProfileRecordsWithEthRecordItem, - mergeProfileRecords, - mergeRecords, profileRecordsToKeyValue, } from './records' -describe('mergeRecords', () => { - it('should merge records as with the second record taking precedence', () => { - expect( - mergeRecords( - [{ key: 'key', value: 'value', type: 'text' }], - [{ key: 'key', value: 'value2', type: 'text' }], - ), - ).toEqual([{ key: 'key', value: 'value2', type: 'text' }]) - }) - - it('should work if either records is undefined', () => { - expect(mergeRecords(undefined, [{ key: 'key', value: 'value2', type: 'text' }])).toEqual([ - { key: 'key', value: 'value2', type: 'text' }, - ]) - expect(mergeRecords([{ key: 'key', value: 'value', type: 'text' }], undefined)).toEqual([ - { key: 'key', value: 'value', type: 'text' }, - ]) - }) -}) - -describe('checkRecordsEqual', () => { - it('should return true if text records are equal', () => { - const records: RecordItem[] = [{ key: 'key', value: 'value', type: 'text' }] - expect(checkRecordsEqual('texts')(records, records)).toBe(true) - }) - - it('should return true if coinType records are equal', () => { - const records: any[] = [{ key: 'key', value: 'value', type: 'addr', addr: '0x123' }] - expect(checkRecordsEqual('coinTypes')(records, records)).toBe(true) - }) - - it('should return false if text records are not equal', () => { - const records: RecordItem[] = [{ key: 'key', value: 'value', type: 'text' }] - const records2: RecordItem[] = [{ key: 'key', value: 'value2', type: 'text' }] - expect(checkRecordsEqual('texts')(records, records2)).toBe(false) - }) - - it('should return false if coinType records are not equal', () => { - const records: any[] = [{ key: 'key', value: 'value', type: 'addr', addr: '0x123' }] - const records2: any[] = [{ key: 'key', value: 'value', type: 'addr', addr: '0x1234' }] - expect(checkRecordsEqual('coinTypes')(records, records2)).toBe(false) - }) -}) - describe('checkContentHashEqual', () => { it('should return true if contentHashes are equal strings', () => { expect(checkContentHashEqual('0x123', '0x123')).toBe(true) @@ -86,229 +37,184 @@ describe('checkContentHashEqual', () => { }) it('should return true if one contentHash is undefined and the other is empty object', () => { - expect(checkContentHashEqual(undefined, {})).toBe(true) + expect(checkContentHashEqual(undefined, {} as any)).toBe(true) }) }) describe('checkProfileRecordsEqual', () => { it('should return true if records are equal', () => { - const records: any = { - texts: [{ key: 'key', value: 'value', type: 'text' }], - coinTypes: [{ key: 'key', value: 'value', type: 'addr', addr: '0x123' }], - contentHash: '0x123', + const records = { + texts: [{ key: 'key', value: 'value' }], + coins: [{ id: 60, name: 'ETH', value: '0x123' }], + contentHash: { protocolType: 'ipfs', decoded: '0x1234' } as const, } expect(checkProfileRecordsEqual(records, records)).toBe(true) }) it('should return false if text record not equal', () => { - const records: any = { - texts: [{ key: 'key', value: 'value2', type: 'text' }], - coinTypes: [{ key: 'key', value: 'value', type: 'addr', addr: '0x123' }], - contentHash: '0x123', + const records = { + texts: [{ key: 'key', value: 'value' }], + coins: [{ id: 60, name: 'ETH', value: '0x123' }], + contentHash: { protocolType: 'ipfs', decoded: '0x1234' } as const, } - const records2: any = { - texts: [{ key: 'key', value: 'value', type: 'text' }], - coinTypes: [{ key: 'key', value: 'value', type: 'addr', addr: '0x123' }], - contentHash: '0x123', + const records2 = { + texts: [{ key: 'key', value: 'value2' }], + coins: [{ id: 60, name: 'ETH', value: '0x123' }], + contentHash: { protocolType: 'ipfs', decoded: '0x1234' } as const, } expect(checkProfileRecordsEqual(records, records2)).toBe(false) }) it('should return false if coinTypes record not equal', () => { - const records: any = { - texts: [{ key: 'key', value: 'value', type: 'text' }], - coinTypes: [{ key: 'key', value: 'value', type: 'addr', addr: '0x123' }], - contentHash: '0x123', + const records = { + texts: [{ key: 'key', value: 'value' }], + coins: [{ id: 60, name: 'ETH', value: '0x123' }], + contentHash: { protocolType: 'ipfs', decoded: '0x1234' } as const, } - const records2: any = { - texts: [{ key: 'key', value: 'value', type: 'text' }], - coinTypes: [{ key: 'key', value: 'value', type: 'addr', addr: '0x1234' }], - contentHash: '0x123', + const records2 = { + texts: [{ key: 'key', value: 'value' }], + coins: [{ id: 60, name: 'ETH', value: '0x1234' }], + contentHash: { protocolType: 'ipfs', decoded: '0x1234' } as const, } expect(checkProfileRecordsEqual(records, records2)).toBe(false) }) - it('should return false if text record not equal', () => { - const records: any = { - texts: [{ key: 'key', value: 'value', type: 'text' }], - coinTypes: [{ key: 'key', value: 'value', type: 'addr', addr: '0x123' }], - contentHash: '0x123', + it('should return false if content record not equal', () => { + const records = { + texts: [{ key: 'key', value: 'value' }], + coins: [{ id: 60, name: 'ETH', value: '0x123' }], + contentHash: { protocolType: 'ipfs', decoded: '0x123' } as const, } - const records2: any = { - texts: [{ key: 'key', value: 'value', type: 'text' }], - coinTypes: [{ key: 'key', value: 'value', type: 'addr', addr: '0x123' }], - contentHash: '0x1234', + const records2 = { + texts: [{ key: 'key', value: 'value' }], + coins: [{ id: 60, name: 'ETH', value: '0x123' }], + contentHash: { protocolType: 'ipfs', decoded: '0x1234' } as const, } expect(checkProfileRecordsEqual(records, records2)).toBe(false) }) }) -describe('mergeProfileRecords', () => { - it('should merge records', () => { - const profileRecords: any = { - texts: [{ key: 'key', value: 'value', type: 'text' }], - coinTypes: [{ key: 'key', coin: 'ETH', type: 'addr', addr: '0x123' }], - contentHash: '0x123', - } - expect(mergeProfileRecords(profileRecords, profileRecords)).toEqual(profileRecords) - }) - - it('should merge records with right value overriding left', () => { - const profileRecords: any = { - texts: [{ key: 'key', value: 'value', type: 'text' }], - coinTypes: [{ key: 'key', coin: 'ETH', type: 'addr', addr: '0x123' }], - contentHash: '0x123', - } - const profileRecords2: any = { - texts: [{ key: 'key', value: 'value2', type: 'text' }], - coinTypes: [{ key: 'key', coin: 'ETH', type: 'addr', addr: '0x1234' }], - contentHash: '0x1234', - } - expect(mergeProfileRecords(profileRecords, profileRecords2)).toEqual(profileRecords2) - }) - - it('should append records that do not have a match', () => { - const profileRecords: any = { - texts: [{ key: 'key', value: 'value', type: 'text' }], - coinTypes: [{ key: 'key', coin: 'ETH', type: 'addr', addr: '0x123' }], - contentHash: '0x123', - } - const profileRecords2: any = { - texts: [{ key: 'key1', value: 'value2', type: 'text' }], - coinTypes: [{ key: 'key2', coin: 'ETH', type: 'addr', addr: '0x1234' }], - contentHash: '0x1234', - } - expect(mergeProfileRecords(profileRecords, profileRecords2)).toEqual({ - texts: [ - { key: 'key', value: 'value', type: 'text' }, - { key: 'key1', value: 'value2', type: 'text' }, - ], - coinTypes: [ - { key: 'key', coin: 'ETH', type: 'addr', addr: '0x123' }, - { key: 'key2', coin: 'ETH', type: 'addr', addr: '0x1234' }, - ], - contentHash: '0x1234', - }) - }) - - it('should not merge contenthash if it is falsy', () => { - const profileRecords: any = { - texts: [{ key: 'key', value: 'value', type: 'text' }], - coinTypes: [{ key: 'key', coin: 'ETH', type: 'addr', addr: '0x123' }], - contentHash: '0x123', - } - const profileRecords2: any = { - contentHash: '', - } - expect(mergeProfileRecords(profileRecords, profileRecords2)).toEqual(profileRecords) - }) -}) - describe('makeProfileRecordsWithEthRecordItem', () => { it('should append eth record item to profile records', () => { - const profileRecords: any = { - texts: [{ key: 'key', value: 'value', type: 'text' }], - coinTypes: [{ key: 'key', coin: 'BTC', type: 'addr', addr: '0x123' }], - contentHash: '0x123', + const profileRecords = { + texts: [{ key: 'key', value: 'value' }], + coins: [{ id: 0, name: 'BTC', value: '0x123' }], + contentHash: { protocolType: 'ipfs', decoded: '0x123' } as const, } expect(makeProfileRecordsWithEthRecordItem(profileRecords, '0x1234')).toEqual({ - texts: [{ key: 'key', value: 'value', type: 'text' }], - coinTypes: [ - { key: 'key', coin: 'BTC', type: 'addr', addr: '0x123' }, - { key: '60', coin: 'ETH', type: 'addr', addr: '0x1234' }, + texts: [{ key: 'key', value: 'value' }], + coins: [ + { id: 0, name: 'BTC', value: '0x123' }, + { id: 60, name: 'ETH', value: '0x1234' }, ], - contentHash: '0x123', + contentHash: { protocolType: 'ipfs', decoded: '0x123' }, }) }) it('should replace existing eth record item in profile records', () => { - const profileRecords: any = { - texts: [{ key: 'key', value: 'value', type: 'text' }], - coinTypes: [{ key: '60', coin: 'ETH', type: 'addr', addr: '0x123' }], - contentHash: '0x123', + const profileRecords = { + texts: [{ key: 'key', value: 'value' }], + coins: [{ id: 60, name: 'ETH', value: '0x123' }], + contentHash: { protocolType: 'ipfs', decoded: '0x123' } as const, } expect(makeProfileRecordsWithEthRecordItem(profileRecords, '0x1234')).toEqual({ - texts: [{ key: 'key', value: 'value', type: 'text' }], - coinTypes: [{ key: '60', coin: 'ETH', type: 'addr', addr: '0x1234' }], - contentHash: '0x123', + texts: [{ key: 'key', value: 'value' }], + coins: [{ id: 60, name: 'ETH', value: '0x1234' }], + contentHash: { protocolType: 'ipfs', decoded: '0x123' }, }) }) it('should do nothing if ethAddress is undefined', () => { - const profileRecords: any = { - texts: [{ key: 'key', value: 'value', type: 'text' }], - coinTypes: [{ key: 'key', coin: 'BTC', type: 'addr', addr: '0x123' }], - contentHash: '0x123', + const profileRecords = { + texts: [{ key: 'key', value: 'value' }], + coins: [{ id: 0, name: 'BTC', value: '0x123' }], + contentHash: { protocolType: 'ipfs', decoded: '0x123' } as const, } expect(makeProfileRecordsWithEthRecordItem(profileRecords, undefined)).toEqual(profileRecords) }) }) describe('profileRecordsToKeyValue', () => { - it('should convert profile records to key value', () => { - const profileRecords: any = { - texts: [{ key: 'key', value: 'value', type: 'text' }], - coinTypes: [{ key: '60', coin: 'ETH', type: 'addr', addr: '0x123' }], - contentHash: '0x123', + it('should convert profile records to key value', async () => { + const profileRecords = { + texts: [{ key: 'key', value: 'value' }], + coins: [{ id: 60, name: 'ETH', value: '0x123' }], + contentHash: { protocolType: 'ipfs', decoded: '0x123' } as const, } - expect(profileRecordsToKeyValue(profileRecords)).toEqual({ + expect(await profileRecordsToKeyValue(profileRecords)).toEqual({ texts: [{ key: 'key', value: 'value' }], - coinTypes: [{ key: '60', value: '0x123' }], - contentHash: '0x123', + coins: [{ coin: 60, value: '0x123' }], + contentHash: 'ipfs://0x123', }) }) - it('should not include contentHash if it is empty string', () => { - const profileRecords: any = { - texts: [{ key: 'key', value: 'value', type: 'text' }], - coinTypes: [{ key: '60', coin: 'ETH', type: 'addr', addr: '0x123' }], - contentHash: '', + it('should not include contentHash if it is null', async () => { + const profileRecords = { + texts: [{ key: 'key', value: 'value' }], + coins: [{ id: 60, name: 'ETH', value: '0x123' }], + contentHash: null, } - expect(profileRecordsToKeyValue(profileRecords)).toEqual({ + expect(await profileRecordsToKeyValue(profileRecords)).toEqual({ texts: [{ key: 'key', value: 'value' }], - coinTypes: [{ key: '60', value: '0x123' }], + coins: [{ coin: 60, value: '0x123' }], }) }) }) describe('checkProfileRecordsContains', () => { it('should return true if match is found in texts', () => { - const records: any = { - texts: [{ key: 'key', value: 'value', type: 'text' }], - coinTypes: [{ key: '60', coin: 'ETH', type: 'addr', addr: '0x123' }], + const records = { + texts: [{ key: 'key', value: 'value' }], + coins: [{ id: 60, name: 'ETH', value: '0x123' }], } - expect(checkProfileRecordsContains(records, { key: 'key', value: 'value', type: 'text' })).toBe( - true, - ) + expect( + checkProfileRecordsContains({ + profile: records, + type: 'text', + match: { key: 'key', value: 'value' }, + }), + ).toBe(true) }) it('should return true if match is found in coinTypes', () => { - const records: any = { - texts: [{ key: 'key', value: 'value', type: 'text' }], - coinTypes: [{ key: '60', coin: 'ETH', type: 'addr', addr: '0x123' }], + const records = { + texts: [{ key: 'key', value: 'value' }], + coins: [{ id: 60, name: 'ETH', value: '0x123' }], } - expect(checkProfileRecordsContains(records, { key: '60', addr: '0x123', type: 'addr' })).toBe( - true, - ) + expect( + checkProfileRecordsContains({ + profile: records, + match: { id: 60, value: '0x123' }, + type: 'address', + }), + ).toBe(true) }) it('should return false if match is not found in texts', () => { - const records: any = { - texts: [{ key: 'key', value: 'value2', type: 'text' }], - coinTypes: [{ key: '60', coin: 'ETH', type: 'addr', addr: '0x123' }], + const records = { + texts: [{ key: 'key', value: 'value2' }], + coins: [{ id: 60, name: 'ETH', value: '0x123' }], } - expect(checkProfileRecordsContains(records, { key: 'key', value: 'value', type: 'text' })).toBe( - false, - ) + expect( + checkProfileRecordsContains({ + profile: records, + type: 'text', + match: { key: 'key', value: 'value' }, + }), + ).toBe(false) }) it('should return false if match is not found in coinTypes', () => { - const records: any = { - texts: [{ key: 'key', value: 'value', type: 'text' }], - coinTypes: [{ key: '60', coin: 'ETH', type: 'addr', addr: '0x1234' }], + const records = { + texts: [{ key: 'key', value: 'value' }], + coins: [{ id: 60, name: 'ETH', value: '0x1234' }], } - expect(checkProfileRecordsContains(records, { key: '60', addr: '0x123', type: 'addr' })).toBe( - false, - ) + expect( + checkProfileRecordsContains({ + profile: records, + match: { id: 60, value: '0x123' }, + type: 'address', + }), + ).toBe(false) }) }) diff --git a/src/utils/records.ts b/src/utils/records.ts index f0956a27b..ec118d86b 100644 --- a/src/utils/records.ts +++ b/src/utils/records.ts @@ -71,8 +71,8 @@ const checkAddressRecordsEqual = checkRecordsEqual( const checkTextRecordsEqual = checkRecordsEqual((item) => `${item.key}-${item.value}`) export const checkContentHashEqual = ( - a?: DecodedContentHash | null, - b?: DecodedContentHash | null, + a?: DecodedContentHash | string | null, + b?: DecodedContentHash | string | null, ): boolean => { return contentHashToString(a) === contentHashToString(b) } @@ -84,17 +84,6 @@ export const checkProfileRecordsEqual = (a: Profile, b: Profile): boolean => { return true } -export const mergeProfileRecords = (a?: Profile, b?: Profile) => { - const texts = mergeTextRecords(a?.texts, b?.texts) - const coinTypes = mergeAddressRecords(a?.coins, b?.coins) - const contentHash = contentHashToString(b?.contentHash) || contentHashToString(a?.contentHash) - return { - texts, - coinTypes, - contentHash, - } -} - export const makeEthRecordItem = (address: Address): AddressRecord => { return { id: 60, diff --git a/src/utils/safe.test.ts b/src/utils/safe.test.ts index 6e8873ba5..7bc7e89d8 100644 --- a/src/utils/safe.test.ts +++ b/src/utils/safe.test.ts @@ -1,7 +1,7 @@ import { SafeConnector } from 'wagmi/connectors/safe' import { WalletConnectConnector } from 'wagmi/connectors/walletConnect' -import { checkIsSafeApp, SafeAppType } from './safe' +import { checkIsSafeApp } from './safe' describe('checkIsSafeApp', () => { it('should return false if connector is undefined', async () => { @@ -10,7 +10,7 @@ describe('checkIsSafeApp', () => { }) it('should return "iframe" if connector is a SafeConnector', async () => { - const connector = new SafeConnector('https://safe-client.safe.global') + const connector = new SafeConnector({}) const result = await checkIsSafeApp(connector) expect(result).toBe('iframe') }) @@ -18,29 +18,33 @@ describe('checkIsSafeApp', () => { it('should return "walletconnect" if connector is a WalletConnectConnector and connected to Safe app', async () => { const connector = Object.create(WalletConnectConnector.prototype) - connector.getProvider = () => ({ session: { + connector.getProvider = () => ({ + session: { peer: { - metadata: { - name: 'Safe', - url: 'https://app.safe.global/', - }, - } - } }) + metadata: { + name: 'Safe', + url: 'https://app.safe.global/', + }, + }, + }, + }) const result = await checkIsSafeApp(connector) expect(result).toBe('walletconnect') }) it('should return false if connector is a WalletConnectConnector but not connected to Safe app', async () => { const connector = Object.create(WalletConnectConnector.prototype) - connector.getProvider = () => ({ session: { + connector.getProvider = () => ({ + session: { peer: { - metadata: { - name: 'WalletConnect', - url: 'https://bridge.walletconnect.org/', - }, - } - } }) + metadata: { + name: 'WalletConnect', + url: 'https://bridge.walletconnect.org/', + }, + }, + }, + }) const result = await checkIsSafeApp(connector) expect(result).toBe(false) }) -}) \ No newline at end of file +}) diff --git a/tsconfig.json b/tsconfig.json index e185c164f..98f7b3f86 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -33,7 +33,7 @@ "jsx": "preserve", "rootDir": ".", "baseUrl": ".", - "types": ["jest", "@cloudflare/workers-types"], + "types": ["jest", "@cloudflare/workers-types", "@testing-library/jest-dom"], "incremental": true, "paths": { "@app/*": ["./src/*"], @@ -58,13 +58,5 @@ /* TODO (tate): revert to initial val after refactor */ "src/**/*.tsx", "next.config.js" ], - "exclude": [ - "custom-test-env.js", - "**/*.ignore.ts", - "**/*.ignore.tsx", - // TODO (tate): remove this after initial refactor - "**/*.test.ts", - // TODO (tate): remove this after initial refactor - "**/*.test.tsx" - ] + "exclude": ["custom-test-env.js", "**/*.ignore.ts", "**/*.ignore.tsx"] }