From 51e873c216fe9536764d3187eb55245c32bb7a88 Mon Sep 17 00:00:00 2001 From: Yash Date: Fri, 31 Jul 2026 22:19:36 +0530 Subject: [PATCH] refactor(ens-controller): migrate from @ethersproject/providers to viem for ENS resolution This update replaces the usage of `@ethersproject/providers` with `viem` for ENS resolution in the `EnsController`. The `DEFAULT_ENS_NETWORK_MAP` has been updated to point to the ENS Universal Resolver contract address, reflecting changes in the default `ensEntries` state. Additionally, the test suite has been adjusted to accommodate these changes, ensuring compatibility with the new resolution method. Changelog entries have been updated to document these breaking changes and the transition to the new library. --- eslint-suppressions.json | 2 +- packages/ens-controller/CHANGELOG.md | 8 + packages/ens-controller/package.json | 4 +- .../ens-controller/src/EnsController.test.ts | 205 +++++------------- packages/ens-controller/src/EnsController.ts | 61 +++--- yarn.lock | 85 +++++--- 6 files changed, 160 insertions(+), 205 deletions(-) diff --git a/eslint-suppressions.json b/eslint-suppressions.json index 079300369b2..9a38edf9c1b 100644 --- a/eslint-suppressions.json +++ b/eslint-suppressions.json @@ -963,7 +963,7 @@ }, "packages/ens-controller/src/EnsController.test.ts": { "@typescript-eslint/explicit-function-return-type": { - "count": 11 + "count": 10 }, "@typescript-eslint/prefer-nullish-coalescing": { "count": 1 diff --git a/packages/ens-controller/CHANGELOG.md b/packages/ens-controller/CHANGELOG.md index b24ae8e8469..a5a1844e0e2 100644 --- a/packages/ens-controller/CHANGELOG.md +++ b/packages/ens-controller/CHANGELOG.md @@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Changed + +- **BREAKING:** `DEFAULT_ENS_NETWORK_MAP` now maps Mainnet and Sepolia to the ENS Universal Resolver contract address (`0xeEeEEEeE14D718C2B47D9923Deab1335E144EeEe`) + - Previously it mapped Mainnet, Ropsten, Rinkeby, Goerli, Holesky, and Sepolia to the ENS registry contract address; the default `ensEntries` state seeded from this map (under the `.` key) changes accordingly + - Reverse resolution is no longer available on Holesky by default; Ropsten, Rinkeby, and Goerli have been shut down and could not resolve anyway +- Replace `@ethersproject/providers` with `viem` for ENS resolution + - Reverse resolution now goes through the ENS Universal Resolver (ENSIP-23), which makes the controller compatible with ENSv2 when it launches + ## [19.1.6] ### Changed diff --git a/packages/ens-controller/package.json b/packages/ens-controller/package.json index 66656af2678..886f9f911f9 100644 --- a/packages/ens-controller/package.json +++ b/packages/ens-controller/package.json @@ -55,13 +55,13 @@ "test:watch": "NODE_OPTIONS=--experimental-vm-modules jest --watch" }, "dependencies": { - "@ethersproject/providers": "^5.7.0", "@metamask/base-controller": "^9.1.0", "@metamask/controller-utils": "^12.3.0", "@metamask/messenger": "^2.0.0", "@metamask/network-controller": "^35.0.0", "@metamask/utils": "^11.11.0", - "punycode": "^2.1.1" + "punycode": "^2.1.1", + "viem": "2.55.8" }, "devDependencies": { "@metamask/auto-changelog": "^6.1.0", diff --git a/packages/ens-controller/src/EnsController.test.ts b/packages/ens-controller/src/EnsController.test.ts index 7a93e4cf314..bdddeea507c 100644 --- a/packages/ens-controller/src/EnsController.test.ts +++ b/packages/ens-controller/src/EnsController.test.ts @@ -1,4 +1,3 @@ -import * as providersModule from '@ethersproject/providers'; import { deriveStateFromMetadata } from '@metamask/base-controller'; import { toChecksumHexAddress, @@ -16,6 +15,7 @@ import type { NetworkController, NetworkState, } from '@metamask/network-controller'; +import { getEnsAddress, getEnsName } from 'viem/actions'; import { buildMockGetNetworkClientById, @@ -44,14 +44,14 @@ for (const [cid, address] of Object.entries(DEFAULT_ENS_NETWORK_MAP)) { } Object.freeze(defaultState); -jest.mock('@ethersproject/providers', () => { - const originalModule = jest.requireActual('@ethersproject/providers'); +jest.mock('viem/actions', () => ({ + __esModule: true, + getEnsAddress: jest.fn(), + getEnsName: jest.fn(), +})); - return { - __esModule: true, - ...originalModule, - }; -}); +const getEnsNameMock = jest.mocked(getEnsName); +const getEnsAddressMock = jest.mocked(getEnsAddress); type AllEnsControllerActions = MessengerActions; @@ -135,15 +135,6 @@ function getEnsControllerMessenger( return ensControllerMessenger; } -/** - * Creates a mock provider. - * - * @returns mock provider - */ -function getProvider() { - return () => Promise.resolve(null); -} - describe('EnsController', () => { it('should set default state', () => { const rootMessenger = getRootMessenger(); @@ -154,7 +145,7 @@ describe('EnsController', () => { expect(controller.state).toStrictEqual(defaultState); }); - it('should return registry address for `.`', () => { + it('should return universal resolver address for `.`', () => { const rootMessenger = getRootMessenger(); const ensControllerMessenger = getEnsControllerMessenger(rootMessenger); const controller = new EnsController({ @@ -162,7 +153,7 @@ describe('EnsController', () => { }); expect(controller.get('0x1', '.')).toStrictEqual({ ensName: '.', - address: '0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e', + address: '0xeEeEEEeE14D718C2B47D9923Deab1335E144EeEe', chainId: '0x1', }); }); @@ -579,12 +570,8 @@ describe('EnsController', () => { it('should only resolve an ENS name once', async () => { const rootMessenger = getRootMessenger(); const ensControllerMessenger = getEnsControllerMessenger(rootMessenger); - const ethProvider = new providersModule.Web3Provider(getProvider()); - jest.spyOn(ethProvider, 'resolveName').mockResolvedValue(address1); - jest - .spyOn(ethProvider, 'lookupAddress') - .mockResolvedValue('peaksignal.eth'); - jest.spyOn(providersModule, 'Web3Provider').mockReturnValue(ethProvider); + getEnsAddressMock.mockResolvedValue(address1); + getEnsNameMock.mockResolvedValue('peaksignal.eth'); const ens = new EnsController({ messenger: ensControllerMessenger, @@ -598,14 +585,13 @@ describe('EnsController', () => { expect(await ens.reverseResolveAddress(address1)).toBe('peaksignal.eth'); expect(await ens.reverseResolveAddress(address1)).toBe('peaksignal.eth'); + expect(getEnsNameMock).toHaveBeenCalledTimes(1); }); it('should fail if lookupAddress through an error', async () => { const rootMessenger = getRootMessenger(); const ensControllerMessenger = getEnsControllerMessenger(rootMessenger); - const ethProvider = new providersModule.Web3Provider(getProvider()); - jest.spyOn(ethProvider, 'lookupAddress').mockRejectedValue('error'); - jest.spyOn(providersModule, 'Web3Provider').mockReturnValue(ethProvider); + getEnsNameMock.mockRejectedValue(new Error('error')); const ens = new EnsController({ messenger: ensControllerMessenger, onNetworkDidChange: (listener) => { @@ -622,9 +608,7 @@ describe('EnsController', () => { it('should fail if lookupAddress returns a null value', async () => { const rootMessenger = getRootMessenger(); const ensControllerMessenger = getEnsControllerMessenger(rootMessenger); - const ethProvider = new providersModule.Web3Provider(getProvider()); - jest.spyOn(ethProvider, 'lookupAddress').mockResolvedValue(null); - jest.spyOn(providersModule, 'Web3Provider').mockReturnValue(ethProvider); + getEnsNameMock.mockResolvedValue(null); const ens = new EnsController({ messenger: ensControllerMessenger, onNetworkDidChange: (listener) => { @@ -641,12 +625,8 @@ describe('EnsController', () => { it('should fail if resolveName through an error', async () => { const rootMessenger = getRootMessenger(); const ensControllerMessenger = getEnsControllerMessenger(rootMessenger); - const ethProvider = new providersModule.Web3Provider(getProvider()); - jest - .spyOn(ethProvider, 'lookupAddress') - .mockResolvedValue('peaksignal.eth'); - jest.spyOn(ethProvider, 'resolveName').mockRejectedValue('error'); - jest.spyOn(providersModule, 'Web3Provider').mockReturnValue(ethProvider); + getEnsNameMock.mockResolvedValue('peaksignal.eth'); + getEnsAddressMock.mockRejectedValue(new Error('error')); const ens = new EnsController({ messenger: ensControllerMessenger, onNetworkDidChange: (listener) => { @@ -663,12 +643,8 @@ describe('EnsController', () => { it('should fail if resolveName returns a null value', async () => { const rootMessenger = getRootMessenger(); const ensControllerMessenger = getEnsControllerMessenger(rootMessenger); - const ethProvider = new providersModule.Web3Provider(getProvider()); - jest.spyOn(ethProvider, 'resolveName').mockResolvedValue(null); - jest - .spyOn(ethProvider, 'lookupAddress') - .mockResolvedValue('peaksignal.eth'); - jest.spyOn(providersModule, 'Web3Provider').mockReturnValue(ethProvider); + getEnsNameMock.mockResolvedValue('peaksignal.eth'); + getEnsAddressMock.mockResolvedValue(null); const ens = new EnsController({ messenger: ensControllerMessenger, onNetworkDidChange: (listener) => { @@ -685,14 +661,8 @@ describe('EnsController', () => { it('should fail if registred address is zero x error address', async () => { const rootMessenger = getRootMessenger(); const ensControllerMessenger = getEnsControllerMessenger(rootMessenger); - const ethProvider = new providersModule.Web3Provider(getProvider()); - jest - .spyOn(ethProvider, 'resolveName') - .mockResolvedValue(ZERO_X_ERROR_ADDRESS); - jest - .spyOn(ethProvider, 'lookupAddress') - .mockResolvedValue('peaksignal.eth'); - jest.spyOn(providersModule, 'Web3Provider').mockReturnValue(ethProvider); + getEnsNameMock.mockResolvedValue('peaksignal.eth'); + getEnsAddressMock.mockResolvedValue(ZERO_X_ERROR_ADDRESS); const ens = new EnsController({ messenger: ensControllerMessenger, onNetworkDidChange: (listener) => { @@ -709,13 +679,8 @@ describe('EnsController', () => { it('should fail if the name is registered to a different address than the reverse resolved', async () => { const rootMessenger = getRootMessenger(); const ensControllerMessenger = getEnsControllerMessenger(rootMessenger); - - const ethProvider = new providersModule.Web3Provider(getProvider()); - jest.spyOn(ethProvider, 'resolveName').mockResolvedValue(address2); - jest - .spyOn(ethProvider, 'lookupAddress') - .mockResolvedValue('peaksignal.eth'); - jest.spyOn(providersModule, 'Web3Provider').mockReturnValue(ethProvider); + getEnsNameMock.mockResolvedValue('peaksignal.eth'); + getEnsAddressMock.mockResolvedValue(address2); const ens = new EnsController({ messenger: ensControllerMessenger, onNetworkDidChange: (listener) => { @@ -728,6 +693,34 @@ describe('EnsController', () => { expect(await ens.reverseResolveAddress(address1)).toBeUndefined(); }); + + it('should return undefined on a chain without a known universal resolver', async () => { + const rootMessenger = getRootMessenger(); + const getNetworkClientById = buildMockGetNetworkClientById({ + 'AAAA-AAAA-AAAA-AAAA': buildCustomNetworkClientConfiguration({ + chainId: '0x2105', + }), + }); + const ensControllerMessenger = getEnsControllerMessenger( + rootMessenger, + getNetworkClientById, + ); + const ens = new EnsController({ + messenger: ensControllerMessenger, + registriesByChainId: { + 8453: '0x74E20Bd2A1fE0cdbe45b9A1d89cb7e0a45b36376', + }, + onNetworkDidChange: (listener): void => { + listener({ + ...getDefaultNetworkControllerState(), + selectedNetworkClientId: 'AAAA-AAAA-AAAA-AAAA', + }); + }, + }); + + expect(await ens.reverseResolveAddress(address1)).toBeUndefined(); + expect(getEnsNameMock).not.toHaveBeenCalled(); + }); }); describe('metadata', () => { @@ -765,42 +758,14 @@ describe('EnsController', () => { "ensEntries": { "0x1": { ".": { - "address": "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e", + "address": "0xeEeEEEeE14D718C2B47D9923Deab1335E144EeEe", "chainId": "0x1", "ensName": ".", }, }, - "0x3": { - ".": { - "address": "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e", - "chainId": "0x3", - "ensName": ".", - }, - }, - "0x4": { - ".": { - "address": "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e", - "chainId": "0x4", - "ensName": ".", - }, - }, - "0x4268": { - ".": { - "address": "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e", - "chainId": "0x4268", - "ensName": ".", - }, - }, - "0x5": { - ".": { - "address": "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e", - "chainId": "0x5", - "ensName": ".", - }, - }, "0xaa36a7": { ".": { - "address": "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e", + "address": "0xeEeEEEeE14D718C2B47D9923Deab1335E144EeEe", "chainId": "0xaa36a7", "ensName": ".", }, @@ -829,42 +794,14 @@ describe('EnsController', () => { "ensEntries": { "0x1": { ".": { - "address": "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e", + "address": "0xeEeEEEeE14D718C2B47D9923Deab1335E144EeEe", "chainId": "0x1", "ensName": ".", }, }, - "0x3": { - ".": { - "address": "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e", - "chainId": "0x3", - "ensName": ".", - }, - }, - "0x4": { - ".": { - "address": "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e", - "chainId": "0x4", - "ensName": ".", - }, - }, - "0x4268": { - ".": { - "address": "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e", - "chainId": "0x4268", - "ensName": ".", - }, - }, - "0x5": { - ".": { - "address": "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e", - "chainId": "0x5", - "ensName": ".", - }, - }, "0xaa36a7": { ".": { - "address": "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e", + "address": "0xeEeEEEeE14D718C2B47D9923Deab1335E144EeEe", "chainId": "0xaa36a7", "ensName": ".", }, @@ -893,42 +830,14 @@ describe('EnsController', () => { "ensEntries": { "0x1": { ".": { - "address": "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e", + "address": "0xeEeEEEeE14D718C2B47D9923Deab1335E144EeEe", "chainId": "0x1", "ensName": ".", }, }, - "0x3": { - ".": { - "address": "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e", - "chainId": "0x3", - "ensName": ".", - }, - }, - "0x4": { - ".": { - "address": "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e", - "chainId": "0x4", - "ensName": ".", - }, - }, - "0x4268": { - ".": { - "address": "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e", - "chainId": "0x4268", - "ensName": ".", - }, - }, - "0x5": { - ".": { - "address": "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e", - "chainId": "0x5", - "ensName": ".", - }, - }, "0xaa36a7": { ".": { - "address": "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e", + "address": "0xeEeEEEeE14D718C2B47D9923Deab1335E144EeEe", "chainId": "0xaa36a7", "ensName": ".", }, diff --git a/packages/ens-controller/src/EnsController.ts b/packages/ens-controller/src/EnsController.ts index 456178f4dad..48cc43ec6c1 100644 --- a/packages/ens-controller/src/EnsController.ts +++ b/packages/ens-controller/src/EnsController.ts @@ -1,17 +1,14 @@ -import { Web3Provider } from '@ethersproject/providers'; import { BaseController } from '@metamask/base-controller'; import type { StateMetadata, ControllerGetStateAction, ControllerStateChangeEvent, } from '@metamask/base-controller'; -import type { ChainId } from '@metamask/controller-utils'; import { normalizeEnsName, isValidHexAddress, isSafeDynamicKey, toChecksumHexAddress, - CHAIN_ID_TO_ETHERS_NETWORK_NAME_MAP, convertHexToDecimal, toHex, } from '@metamask/controller-utils'; @@ -24,6 +21,11 @@ import type { import type { Hex } from '@metamask/utils'; import { createProjectLogger } from '@metamask/utils'; import { toASCII } from 'punycode/punycode.js'; +import type { Address, Chain, Client } from 'viem'; +import { createClient, custom } from 'viem'; +import { getEnsAddress, getEnsName } from 'viem/actions'; +import { mainnet, sepolia } from 'viem/chains'; +import { normalize } from 'viem/ens'; import type { EnsControllerMethodActions } from './EnsController-method-action-types.js'; @@ -40,20 +42,20 @@ const MESSENGER_EXPOSED_METHODS = [ 'set', ] as const; -// Map of chainIDs and ENS registry contract addresses +// Map of chainIDs and ENS universal resolver contract addresses (ENSIP-23 +// proxy, upgraded in place by the ENS DAO to support ENSv2 on launch). export const DEFAULT_ENS_NETWORK_MAP: Record = { // Mainnet - 1: '0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e', - // Ropsten - 3: '0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e', - // Rinkeby - 4: '0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e', - // Goerli - 5: '0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e', - // Holesky - 17000: '0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e', + 1: '0xeEeEEEeE14D718C2B47D9923Deab1335E144EeEe', // Sepolia - 11155111: '0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e', + 11155111: '0xeEeEEEeE14D718C2B47D9923Deab1335E144EeEe', +}; + +// Chains with a viem definition that includes an `ensUniversalResolver` +// contract, used as the default source of universal resolver addresses. +const VIEM_CHAINS_BY_ID: Record = { + [mainnet.id]: mainnet, + [sepolia.id]: sepolia, }; /** @@ -143,7 +145,7 @@ export class EnsController extends BaseController< EnsControllerState, EnsControllerMessenger > { - #ethProvider: Web3Provider | null = null; + #ethClient: Client | null = null; /** * Creates an EnsController instance. @@ -335,17 +337,22 @@ export class EnsController extends BaseController< selectedNetworkClientId, ); + const chainIdDecimal = convertHexToDecimal(currentChainId); + const chain = VIEM_CHAINS_BY_ID[chainIdDecimal]; + if ( - registriesByChainId?.[parseInt(currentChainId, 16)] && - this.#getChainEnsSupport(currentChainId) + registriesByChainId?.[chainIdDecimal] && + this.#getChainEnsSupport(currentChainId) && + chain ) { - this.#ethProvider = new Web3Provider(provider, { - chainId: convertHexToDecimal(currentChainId), - name: CHAIN_ID_TO_ETHERS_NETWORK_NAME_MAP[currentChainId as ChainId], - ensAddress: registriesByChainId[parseInt(currentChainId, 16)], + // viem resolves ENS names through the `ensUniversalResolver` contract + // defined on the chain. + this.#ethClient = createClient({ + chain, + transport: custom(provider), }); } else { - this.#ethProvider = null; + this.#ethClient = null; } } @@ -366,7 +373,7 @@ export class EnsController extends BaseController< * @returns ens resolution */ async reverseResolveAddress(nonChecksummedAddress: string) { - if (!this.#ethProvider) { + if (!this.#ethClient) { return undefined; } @@ -377,7 +384,9 @@ export class EnsController extends BaseController< let domain: string | null; try { - domain = await this.#ethProvider.lookupAddress(address); + domain = await getEnsName(this.#ethClient, { + address: address as Address, + }); } catch (error) { log(error); return undefined; @@ -389,7 +398,9 @@ export class EnsController extends BaseController< let registeredAddress: string | null; try { - registeredAddress = await this.#ethProvider.resolveName(domain); + registeredAddress = await getEnsAddress(this.#ethClient, { + name: normalize(domain), + }); } catch (error) { log(error); return undefined; diff --git a/yarn.lock b/yarn.lock index 2166edbfa67..38b75ad1f9c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6898,7 +6898,6 @@ __metadata: version: 0.0.0-use.local resolution: "@metamask/ens-controller@workspace:packages/ens-controller" dependencies: - "@ethersproject/providers": "npm:^5.7.0" "@metamask/auto-changelog": "npm:^6.1.0" "@metamask/base-controller": "npm:^9.1.0" "@metamask/controller-utils": "npm:^12.3.0" @@ -6915,6 +6914,7 @@ __metadata: typedoc: "npm:^0.25.13" typedoc-plugin-missing-exports: "npm:^2.0.0" typescript: "npm:~5.3.3" + viem: "npm:2.55.8" languageName: unknown linkType: soft @@ -22510,9 +22510,9 @@ __metadata: languageName: node linkType: hard -"ox@npm:0.14.20": - version: 0.14.20 - resolution: "ox@npm:0.14.20" +"ox@npm:0.14.32": + version: 0.14.32 + resolution: "ox@npm:0.14.32" dependencies: "@adraffy/ens-normalize": "npm:^1.11.0" "@noble/ciphers": "npm:^1.3.0" @@ -22527,7 +22527,28 @@ __metadata: peerDependenciesMeta: typescript: optional: true - checksum: 10/96526073193f3a6dd2ccd21bcc255e82c7226d6de63fa17a2021c75232fdc9bc969e75e2cbc0c8d5163d88c575e08dc4c75dec7333b1727f080585f07fc6c1ed + checksum: 10/d631768f48d7b1208b586df92661273019b9d95a135eeb691ce6721857acfebe6c61b3ab7f950ba8ca1b43d531a0971b4e3e39be703fbceab27e4bd0ead8a5b2 + languageName: node + linkType: hard + +"ox@npm:0.14.33": + version: 0.14.33 + resolution: "ox@npm:0.14.33" + dependencies: + "@adraffy/ens-normalize": "npm:^1.11.0" + "@noble/ciphers": "npm:^1.3.0" + "@noble/curves": "npm:1.9.1" + "@noble/hashes": "npm:^1.8.0" + "@scure/bip32": "npm:^1.7.0" + "@scure/bip39": "npm:^1.6.0" + abitype: "npm:^1.2.3" + eventemitter3: "npm:5.0.1" + peerDependencies: + typescript: ">=5.4.0" + peerDependenciesMeta: + typescript: + optional: true + checksum: 10/8a1390fa4799fc8629ea64c00b49fe4c5c93417c92033bad7599a1861842af202303ea1cdc85023f19145192563ebe9085609d84b0a3d0145ed1b61e579a2052 languageName: node linkType: hard @@ -27474,9 +27495,30 @@ __metadata: languageName: node linkType: hard +"viem@npm:2.55.8": + version: 2.55.8 + resolution: "viem@npm:2.55.8" + dependencies: + "@noble/curves": "npm:1.9.1" + "@noble/hashes": "npm:1.8.0" + "@scure/bip32": "npm:1.7.0" + "@scure/bip39": "npm:1.6.0" + abitype: "npm:1.2.3" + isows: "npm:1.0.7" + ox: "npm:0.14.32" + ws: "npm:8.21.0" + peerDependencies: + typescript: ">=5.0.4" + peerDependenciesMeta: + typescript: + optional: true + checksum: 10/77a5c474e185654e78f5a561d618ce2152263f126ff91aedcb24f5b1f79454494f825e1863603f12d7f4eb85f84ff1cee6b32f93dc70f32853506dde4a94c54e + languageName: node + linkType: hard + "viem@npm:^2.36.0": - version: 2.48.4 - resolution: "viem@npm:2.48.4" + version: 2.55.10 + resolution: "viem@npm:2.55.10" dependencies: "@noble/curves": "npm:1.9.1" "@noble/hashes": "npm:1.8.0" @@ -27484,14 +27526,14 @@ __metadata: "@scure/bip39": "npm:1.6.0" abitype: "npm:1.2.3" isows: "npm:1.0.7" - ox: "npm:0.14.20" - ws: "npm:8.18.3" + ox: "npm:0.14.33" + ws: "npm:8.21.0" peerDependencies: typescript: ">=5.0.4" peerDependenciesMeta: typescript: optional: true - checksum: 10/79ab1c8941013e1b4d12ef0bd7fcca6108cfc078b669cc02ae5a08c94d4e3b6de182071cfb40fb4e33ddc40b3aa997f3ebb50d269c85512cefcefdce49b193a0 + checksum: 10/4da52637c5ef51a05748cb4566fc9842b39148fcd847746df239eb19a013fc9cbedeaf70331258b808ddef7c6ca984b1b5b5995a3e47869091723a9d73c245c2 languageName: node linkType: hard @@ -28011,9 +28053,9 @@ __metadata: languageName: node linkType: hard -"ws@npm:8.18.3": - version: 8.18.3 - resolution: "ws@npm:8.18.3" +"ws@npm:8.21.0, ws@npm:^8.18.0, ws@npm:^8.18.3": + version: 8.21.0 + resolution: "ws@npm:8.21.0" peerDependencies: bufferutil: ^4.0.1 utf-8-validate: ">=5.0.2" @@ -28022,7 +28064,7 @@ __metadata: optional: true utf-8-validate: optional: true - checksum: 10/725964438d752f0ab0de582cd48d6eeada58d1511c3f613485b5598a83680bedac6187c765b0fe082e2d8cc4341fc57707c813ae780feee82d0c5efe6a4c61b6 + checksum: 10/088411956432c8f876158409d5a285cb9ad1382f593391f51d3a599bd0a5b277f876609ebd00fc3596321c4a4c9064d6fffe1ebad960e8ea7fd9ae25324f35c2 languageName: node linkType: hard @@ -28041,21 +28083,6 @@ __metadata: languageName: node linkType: hard -"ws@npm:^8.18.0, ws@npm:^8.18.3": - version: 8.21.0 - resolution: "ws@npm:8.21.0" - peerDependencies: - bufferutil: ^4.0.1 - utf-8-validate: ">=5.0.2" - peerDependenciesMeta: - bufferutil: - optional: true - utf-8-validate: - optional: true - checksum: 10/088411956432c8f876158409d5a285cb9ad1382f593391f51d3a599bd0a5b277f876609ebd00fc3596321c4a4c9064d6fffe1ebad960e8ea7fd9ae25324f35c2 - languageName: node - linkType: hard - "wsl-utils@npm:^0.1.0": version: 0.1.0 resolution: "wsl-utils@npm:0.1.0"