diff --git a/.github/workflows/ci-common-testnets.yml b/.github/workflows/ci-common-testnets.yml new file mode 100644 index 000000000..f94728892 --- /dev/null +++ b/.github/workflows/ci-common-testnets.yml @@ -0,0 +1,43 @@ +name: CI (common-testnets) + +on: + pull_request: + # @todo: uncomment when testnet factories are stable + # paths: + # - "packages/common-testnets/**" + # - "pnpm-lock.yaml" + push: + branches: + - main + +jobs: + test-e2e: + strategy: + matrix: + node: [ "20" ] + os: [ ubuntu-latest ] + runs-on: ${{ matrix.os }} + + steps: + - uses: actions/checkout@v4 + - uses: pnpm/action-setup@v4 + with: + version: 9.14.2 + - uses: actions/setup-node@v4 + with: + node-version: ${{ matrix.node }} + cache: "pnpm" + - run: pnpm install + + - name: Install Foundry + uses: foundry-rs/foundry-toolchain@v1.2.0 + with: + version: nightly-58bf161bc9dd6e74de8cb61e3ae23f701feb5512 + + - run: pnpm test-e2e + working-directory: ./packages/common-testnets + env: + TENDERLY_API_KEY: "${{ secrets.TENDERLY_API_KEY }}" + TENDERLY_ACCOUNT: phoenixlabs + TENDERLY_PROJECT: spark-app-e2e-tests + TEST_E2E_ALCHEMY_API_KEY: "${{ secrets.ALCHEMY_API_KEY }}" diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 10d087faf..ea73ae002 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -65,7 +65,7 @@ jobs: - run: pnpm install - run: pnpm check - - run: pnpm verify # does linting, type checking, and tests in parallel + - run: pnpm verify # runs linting, type checking, and unit tests in parallel storybook-visual-regression: strategy: @@ -132,9 +132,7 @@ jobs: env: TENDERLY_API_KEY: "${{ secrets.TENDERLY_API_KEY }}" TENDERLY_ACCOUNT: phoenixlabs - TENDERLY_PROJECT: sparklend - TENDERLY_BASE_DEVNET_CONTAINER_ID: "${{ secrets.TENDERLY_BASE_DEVNET_CONTAINER_ID }}" - VITE_DEV_BASE_DEVNET_RPC_URL: "${{ secrets.VITE_DEV_BASE_DEVNET_RPC_URL }}" + TENDERLY_PROJECT: spark-app-e2e-tests PLAYWRIGHT_TRACE: 1 - name: Upload report to GitHub Actions Artifacts if: failure() diff --git a/package.json b/package.json index 2d4c1466a..207859f68 100644 --- a/package.json +++ b/package.json @@ -18,7 +18,8 @@ "clean": "pnpm run --parallel --aggregate-output --reporter append-only --filter './packages/**' clean" }, "dependencies": { - "bignumber.js": "^9.1.2" + "bignumber.js": "^9.1.2", + "zod": "3.22.4" }, "devDependencies": { "@biomejs/biome": "^1.8.1", diff --git a/packages/app/package.json b/packages/app/package.json index ef288e826..60f4e0d15 100644 --- a/packages/app/package.json +++ b/packages/app/package.json @@ -78,7 +78,6 @@ "tailwindcss-animate": "^1.0.6", "viem": "^2.9.21", "wagmi": "^2.5.20", - "zod": "^3.22.4", "zustand": "^4.4.1" }, "devDependencies": { diff --git a/packages/common-testnets/.mocharc.json b/packages/common-testnets/.mocharc.json new file mode 100644 index 000000000..e6ab882fe --- /dev/null +++ b/packages/common-testnets/.mocharc.json @@ -0,0 +1,7 @@ +{ + "$schema": "https://json.schemastore.org/mocharc", + "extension": ["ts"], + "require": "dotenv/config", + "node-option": ["import=tsx", "conditions=@marsfoundation/local-spark-monorepo"], + "timeout": 60000 +} diff --git a/packages/common-testnets/package.json b/packages/common-testnets/package.json new file mode 100644 index 000000000..cef3dccdd --- /dev/null +++ b/packages/common-testnets/package.json @@ -0,0 +1,59 @@ +{ + "name": "@marsfoundation/common-testnets", + "version": "0.0.1", + "engines": { + "node": ">=18.0.0" + }, + "type": "module", + "main": "./dist/cjs/index.js", + "module": "./dist/esm/index.js", + "types": "./dist/types/index.d.ts", + "repository": { + "type": "git", + "url": "https://github.com/marsfoundation/spark-app.git", + "directory": "packages/common-testnets" + }, + "exports": { + ".": { + "import": { + "@marsfoundation/local-spark-monorepo": "./src/index.ts", + "types": "./dist/types/index.d.ts", + "default": "./dist/esm/index.js" + }, + "require": { + "@marsfoundation/local-spark-monorepo": "./src/index.ts", + "types": "./dist/types/index.d.ts", + "default": "./dist/cjs/index.js" + } + } + }, + "files": ["dist"], + "scripts": { + "lint": "eslint src", + "verify": "concurrently --names \"LINT,TEST,TYPECHECK,LINT-CUSTOM\" -c \"bgMagenta.bold,bgGreen.bold,bgBlue.bold,bgCyan.bold\" \"pnpm run lint\" \"pnpm run test --silent\" \"pnpm run typecheck\"", + "fix": "cd ../../ && pnpm run check:fix && cd - && pnpm run verify", + "test": "true", + "test-e2e": "mocha src/**/*.test.ts", + "typecheck": "tsc --noEmit", + "build:cjs": "tsc -p tsconfig.cjs.json", + "build:esm": "tsc -p tsconfig.esm.json", + "build": "pnpm run build:cjs && pnpm run build:esm", + "clean": "rm -rf dist", + "prepublishOnly": "pnpm run clean && pnpm run build" + }, + "dependencies": { + "@marsfoundation/common-nodejs": "workspace:^", + "@marsfoundation/common-universal": "workspace:^", + "@viem/anvil": "^0.0.10", + "get-port": "^7.1.0", + "viem": "2.21.18", + "viem-deal": "^2.0.0" + }, + "devDependencies": { + "@types/mocha": "^10.0.10", + "@types/uuid": "^10.0.0", + "earl": "^1.3.0", + "mocha": "^10.8.2", + "uuid": "^11.0.2" + } +} diff --git a/packages/common-testnets/src/TestnetClient.ts b/packages/common-testnets/src/TestnetClient.ts new file mode 100644 index 000000000..30bb565fb --- /dev/null +++ b/packages/common-testnets/src/TestnetClient.ts @@ -0,0 +1,15 @@ +import { raise } from '@marsfoundation/common-universal' +import { Address, PublicActions, WalletClient } from 'viem' + +export interface TestnetClient extends WalletClient, PublicActions { + setErc20Balance(tkn: Address, usr: Address, amount: bigint): Promise + setBalance(usr: Address, amount: bigint): Promise + snapshot(): Promise + revert(snapshotId: string): Promise // @note: returns new snapshot id (may be the same as the input) + mineBlocks(blocks: bigint): Promise + setNextBlockTimestamp(timestamp: bigint): Promise +} + +export function getUrlFromClient(client: TestnetClient): string { + return client.transport.type === 'http' ? client.transport.url : raise('Only http transport is supported') +} diff --git a/packages/common-testnets/src/TestnetFactory.test.ts b/packages/common-testnets/src/TestnetFactory.test.ts new file mode 100644 index 000000000..020c1b14f --- /dev/null +++ b/packages/common-testnets/src/TestnetFactory.test.ts @@ -0,0 +1,106 @@ +import { getEnv } from '@marsfoundation/common-nodejs/env' +import { expect } from 'earl' +import { after, before, describe, it } from 'mocha' +import { TestnetClient } from './TestnetClient' +import { TestnetFactory } from './TestnetFactory' +import { AnvilTestnetFactory } from './anvil' +import { TenderlyTestnetFactory } from './tenderly' + +const env = getEnv() + +describe('TestnetFactory', () => { + const factories: TestnetFactory[] = [ + new TenderlyTestnetFactory({ + apiKey: env.string('TENDERLY_API_KEY'), + account: env.string('TENDERLY_ACCOUNT'), + project: env.string('TENDERLY_PROJECT'), + }), + new AnvilTestnetFactory({ alchemyApiKey: env.string('TEST_E2E_ALCHEMY_API_KEY') }), + ] + + for (const factory of factories) { + describe(factory.constructor.name, () => { + const expectedChainId = 2137 + + describe('With block specified', () => { + let testnetClient: TestnetClient + let cleanup: () => Promise + const blockNumber = 21378357n + const expectedTimestamp = 1733909123n + 2n + + before(async () => { + ;({ client: testnetClient, cleanup } = await factory.create({ + id: 'test', + originChainId: 1, + forkChainId: expectedChainId, + blockNumber, + })) + }) + + after(async () => { + await cleanup() + }) + + it('creates a testnet with desired block', async () => { + const currentBlockNumber = await testnetClient.getBlockNumber() + + expect(currentBlockNumber).toEqual(blockNumber + 2n) + }) + + it('creates a testnet with desired timestamp', async () => { + const currentBlockNumber = await testnetClient.getBlockNumber() + const currentBlock = await testnetClient.getBlock({ blockNumber: currentBlockNumber }) + + expect(currentBlock.timestamp).toEqual(expectedTimestamp) + }) + + it('creates a testnet with desired chainId', async () => { + const chainId = await testnetClient.getChainId() + + expect(chainId).toEqual(expectedChainId) + }) + + it('contains tx from a top of the forked blockchain', async () => { + const receipt = await testnetClient.getTransactionReceipt({ + hash: '0x3c66f14cafc6b806538d97953be5bf4775be4f851448e937a612007c9e207c37', + }) + + expect(receipt).toEqual( + expect.subset({ + status: 'success', + }), + ) + }) + + it('does not contain tx from future block', async () => { + await expect( + testnetClient.getTransactionReceipt({ + hash: '0x7057abf025862e54cb1c33b4f4d4e6f8793383098abb84e58a85d1f10d14b765', + }), + ).toBeRejectedWith('The Transaction may not be processed on a block yet.') + }) + }) + + describe('Without block specified', () => { + let testnetClient: TestnetClient + let cleanup: () => Promise + + before(async () => { + ;({ client: testnetClient, cleanup } = await factory.create({ + id: 'test', + originChainId: 1, + forkChainId: expectedChainId, + })) + }) + after(async () => { + await cleanup() + }) + + it('can fetch block number', async () => { + const currentBlockNumber = await testnetClient.getBlockNumber() + expect(currentBlockNumber).toBeGreaterThan(21385842n) + }) + }) + }) + } +}) diff --git a/packages/common-testnets/src/TestnetFactory.ts b/packages/common-testnets/src/TestnetFactory.ts new file mode 100644 index 000000000..2f70ab919 --- /dev/null +++ b/packages/common-testnets/src/TestnetFactory.ts @@ -0,0 +1,23 @@ +import { TestnetClient } from './TestnetClient' + +export interface TestnetCreateResult { + client: TestnetClient + cleanup: () => Promise +} +/** + * The created testnet will have a small, though known beforehand, difference in both the final block number + * and its timestamp compared to the requested block. This is due to necessary normalization + * steps that ensure compatibility with different client implementations. + */ +export interface TestnetFactory { + create(network: CreateNetworkArgs): Promise + createClientFromUrl(rpcUrl: string): TestnetClient +} + +export interface CreateNetworkArgs { + id: string + displayName?: string + originChainId: number + forkChainId: number + blockNumber?: bigint +} diff --git a/packages/common-testnets/src/anvil/AnvilClient.ts b/packages/common-testnets/src/anvil/AnvilClient.ts new file mode 100644 index 000000000..f86aec63a --- /dev/null +++ b/packages/common-testnets/src/anvil/AnvilClient.ts @@ -0,0 +1,61 @@ +import { assert } from '@marsfoundation/common-universal' +import { http, Address, createTestClient, numberToHex, publicActions, walletActions } from 'viem' +import { dealActions } from 'viem-deal' +import { mainnet } from 'viem/chains' +import { TestnetClient } from '../TestnetClient' + +export function getAnvilClient(rpc: string): TestnetClient { + return createTestClient({ + chain: mainnet, + mode: 'anvil', + transport: http(rpc), + cacheTime: 0, // do not cache block numbers + }) + .extend(publicActions) + .extend(dealActions) + .extend((c) => ({ + async setErc20Balance(tkn: Address, usr: Address, amt: bigint): Promise { + return await c.deal({ + erc20: tkn.toLowerCase() as any, + account: usr.toLowerCase() as any, + amount: amt, + }) + }, + async setBalance(usr: Address, amt: bigint): Promise { + return c.request({ + method: 'anvil_setBalance', + params: [usr.toString(), `0x${amt.toString(16)}`], + } as any) + }, + async snapshot(): Promise { + return c.request({ + method: 'evm_snapshot', + params: [], + } as any) + }, + async revert(snapshotId: string) { + const result = await c.request({ + method: 'evm_revert', + params: [snapshotId], + } as any) + + assert(result === true, 'revert failed') + + // anvil snapshots are "burned" after revert so we need to create a new one + return await c.snapshot() + }, + async mineBlocks(blocks: bigint) { + await c.request({ + method: 'anvil_mine', + params: [numberToHex(blocks), '0x1'], + }) + }, + async setNextBlockTimestamp(timestamp: bigint) { + await c.request({ + method: 'evm_setNextBlockTimestamp', + params: [numberToHex(timestamp)], + }) + }, + })) + .extend(walletActions) +} diff --git a/packages/common-testnets/src/anvil/AnvilTestnetFactory.ts b/packages/common-testnets/src/anvil/AnvilTestnetFactory.ts new file mode 100644 index 000000000..c08954059 --- /dev/null +++ b/packages/common-testnets/src/anvil/AnvilTestnetFactory.ts @@ -0,0 +1,72 @@ +import { assert } from '@marsfoundation/common-universal' +import { TestnetClient } from '../TestnetClient' +import { CreateNetworkArgs, TestnetCreateResult, TestnetFactory } from '../TestnetFactory' + +import { createAnvil } from '@viem/anvil' +import getPort from 'get-port' +import { http, createPublicClient } from 'viem' +import { getAnvilClient } from './AnvilClient' + +export class AnvilTestnetFactory implements TestnetFactory { + constructor(private readonly opts: { alchemyApiKey: string }) {} + + async create(args: CreateNetworkArgs): Promise { + const { originChainId, forkChainId, blockNumber } = args + + const forkUrl = originChainIdToForkUrl(originChainId, this.opts.alchemyApiKey) + // if forkChainId is specified, anvil requires blockNumber to be specified as well + const forkBlockNumber = await (async () => { + if (blockNumber) { + return blockNumber + } + + const publicClient = createPublicClient({ transport: http(forkUrl) }) + return publicClient.getBlockNumber() + })() + const port = await getPort({ port: 8545 }) + + const anvil = createAnvil({ + forkUrl, + autoImpersonate: true, + forkBlockNumber, + forkChainId, + port, + gasPrice: 0, + blockBaseFeePerGas: 0, + }) + + await anvil.start() + + const url = `http://${anvil.host}:${anvil.port}` + + assert(anvil.status === 'listening', `Anvil failed to start: ${anvil.status}`) + + const client = getAnvilClient(url) + + const lastBlockTimestamp = (await client.getBlock()).timestamp + await client.setNextBlockTimestamp(lastBlockTimestamp + 1n) // mineBlocks does not respect interval for the first block + await client.mineBlocks(2n) + + return { + client, + cleanup: async () => { + await anvil.stop() + }, + } + } + + createClientFromUrl(rpcUrl: string): TestnetClient { + return getAnvilClient(rpcUrl) + } +} + +function originChainIdToForkUrl(originChainId: number, alchemyApiKey: string): string { + switch (originChainId) { + case 1: + return `https://eth-mainnet.g.alchemy.com/v2/${alchemyApiKey}` + case 8453: + return `https://base-mainnet.g.alchemy.com/v2/${alchemyApiKey}` + default: + throw new Error(`Unsupported origin chain id: ${originChainId}`) + } +} diff --git a/packages/common-testnets/src/anvil/index.ts b/packages/common-testnets/src/anvil/index.ts new file mode 100644 index 000000000..0147555c3 --- /dev/null +++ b/packages/common-testnets/src/anvil/index.ts @@ -0,0 +1,2 @@ +export * from './AnvilClient' +export * from './AnvilTestnetFactory' diff --git a/packages/common-testnets/src/index.ts b/packages/common-testnets/src/index.ts new file mode 100644 index 000000000..d20d81b08 --- /dev/null +++ b/packages/common-testnets/src/index.ts @@ -0,0 +1,4 @@ +export * from './TestnetClient' +export * from './TestnetFactory' +export * from './tenderly' +export * from './anvil' diff --git a/packages/common-testnets/src/tenderly/TenderlyClient.ts b/packages/common-testnets/src/tenderly/TenderlyClient.ts new file mode 100644 index 000000000..c6a9b501b --- /dev/null +++ b/packages/common-testnets/src/tenderly/TenderlyClient.ts @@ -0,0 +1,54 @@ +import { http, Address, createTestClient, numberToHex, publicActions, walletActions } from 'viem' +import { mainnet } from 'viem/chains' +import { TestnetClient } from '../TestnetClient' + +export function getTenderlyClient(rpc: string): TestnetClient { + return createTestClient({ + chain: mainnet, + mode: 'anvil', + transport: http(rpc), + cacheTime: 0, // do not cache block numbers + }) + .extend((c) => ({ + async setErc20Balance(tkn: Address, usr: Address, amt: bigint): Promise { + return c.request({ + method: 'tenderly_setErc20Balance', + params: [tkn.toString(), usr.toString(), numberToHex(amt)], + } as any) + }, + async setBalance(usr: Address, amt: bigint): Promise { + return c.request({ + method: 'tenderly_setBalance', + params: [usr.toString(), numberToHex(amt)], + } as any) + }, + async snapshot(): Promise { + return c.request({ + method: 'evm_snapshot', + params: [], + } as any) + }, + async revert(snapshotId: string) { + await c.request({ + method: 'evm_revert', + params: [snapshotId], + } as any) + // tenderly doesn't burn the snapshots id so we can reuse it + return snapshotId + }, + async mineBlocks(blocks: bigint) { + await c.request({ + method: 'evm_increaseBlocks', + params: [numberToHex(blocks)], + } as any) + }, + async setNextBlockTimestamp(timestamp: bigint) { + await c.request({ + method: 'tenderly_setNextBlockTimestamp', + params: [numberToHex(timestamp)], + } as any) + }, + })) + .extend(walletActions) + .extend(publicActions) +} diff --git a/packages/common-testnets/src/tenderly/TenderlyTestnetFactory.ts b/packages/common-testnets/src/tenderly/TenderlyTestnetFactory.ts new file mode 100644 index 000000000..f7a8bc60c --- /dev/null +++ b/packages/common-testnets/src/tenderly/TenderlyTestnetFactory.ts @@ -0,0 +1,87 @@ +import { assert, solidFetch } from '@marsfoundation/common-universal' +import { v4 as uuidv4 } from 'uuid' +import { numberToHex } from 'viem' +import { z } from 'zod' +import { TestnetClient } from '../TestnetClient' +import { CreateNetworkArgs, TestnetCreateResult, TestnetFactory } from '../TestnetFactory' +import { getTenderlyClient } from './TenderlyClient' + +export class TenderlyTestnetFactory implements TestnetFactory { + constructor(private readonly opts: { apiKey: string; account: string; project: string }) {} + + async create(args: CreateNetworkArgs): Promise { + const { id, displayName, originChainId, forkChainId, blockNumber } = args + const uniqueId = uuidv4() + + const response = await solidFetch( + `https://api.tenderly.co/api/v1/account/${this.opts.account}/project/${this.opts.project}/vnets`, + { + method: 'post', + headers: { + 'Content-Type': 'application/json', + 'X-Access-Key': this.opts.apiKey, + }, + body: JSON.stringify({ + slug: `${id}-${uniqueId}`, + display_name: displayName, + fork_config: { + network_id: originChainId, + block_number: Number(blockNumber) + 1, + }, + virtual_network_config: { + chain_config: { + chain_id: forkChainId, + }, + }, + sync_state_config: { + enabled: false, + commitment_level: 'latest', + }, + explorer_page_config: { + enabled: false, + verification_visibility: 'bytecode', + }, + }), + }, + ) + + const data = createVnetSchema.parse(await response.json()) + + const adminRpc = data.rpcs.find((rpc: any) => rpc.name === 'Admin RPC') + const publicRpc = data.rpcs.find((rpc: any) => rpc.name === 'Public RPC') + assert(adminRpc && publicRpc, 'Missing admin or public RPC') + + const client = getTenderlyClient(adminRpc.url) + const legacyClient = client.extend((c) => ({ + async legacySetNextBlockTimestamp(timestamp: bigint) { + await c.request({ + method: 'evm_setNextBlockTimestamp', + params: [numberToHex(timestamp)], + } as any) + }, + })) + + const block = await client.getBlock({ blockNumber }) + const nextBlockTimestamp = block.timestamp + 2n // to normalize with anvil we need to lowest common timestamp + + await legacyClient.legacySetNextBlockTimestamp(nextBlockTimestamp) + + return { + client, + cleanup: () => Promise.resolve(), + } + } + + createClientFromUrl(rpcUrl: string): TestnetClient { + return getTenderlyClient(rpcUrl) + } +} + +const createVnetSchema = z.object({ + rpcs: z.array( + z.object({ + name: z.string(), + url: z.string(), + }), + ), +}) diff --git a/packages/common-testnets/src/tenderly/index.ts b/packages/common-testnets/src/tenderly/index.ts new file mode 100644 index 000000000..ae249985a --- /dev/null +++ b/packages/common-testnets/src/tenderly/index.ts @@ -0,0 +1 @@ +export * from './TenderlyTestnetFactory' diff --git a/packages/common-testnets/tsconfig.cjs.json b/packages/common-testnets/tsconfig.cjs.json new file mode 100644 index 000000000..e093f0a9c --- /dev/null +++ b/packages/common-testnets/tsconfig.cjs.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "module": "commonjs", + "customConditions": null, + "moduleResolution": "node", + "outDir": "./dist/cjs", + "declaration": true, + "declarationDir": "./dist/types" + } +} diff --git a/packages/common-testnets/tsconfig.esm.json b/packages/common-testnets/tsconfig.esm.json new file mode 100644 index 000000000..0ebcdc1ac --- /dev/null +++ b/packages/common-testnets/tsconfig.esm.json @@ -0,0 +1,7 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "module": "esnext", + "outDir": "./dist/esm" + } +} diff --git a/packages/common-testnets/tsconfig.json b/packages/common-testnets/tsconfig.json new file mode 100644 index 000000000..51527e361 --- /dev/null +++ b/packages/common-testnets/tsconfig.json @@ -0,0 +1,6 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "rootDir": "./src" + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 28bd5e2df..cc5e79f56 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -16,6 +16,9 @@ importers: bignumber.js: specifier: ^9.1.2 version: 9.1.2 + zod: + specifier: 3.22.4 + version: 3.22.4 devDependencies: '@biomejs/biome': specifier: ^1.8.1 @@ -202,13 +205,10 @@ importers: version: 1.0.6(tailwindcss@3.4.3) viem: specifier: ^2.9.21 - version: 2.9.21(bufferutil@4.0.8)(typescript@5.6.3)(utf-8-validate@6.0.3)(zod@3.22.4) + version: 2.9.21(bufferutil@4.0.8)(typescript@5.6.3)(zod@3.22.4) wagmi: specifier: ^2.5.20 version: 2.5.20(@react-native-async-storage/async-storage@1.22.0(react-native@0.76.1(@babel/core@7.22.9)(@babel/preset-env@7.24.6(@babel/core@7.22.9))(@types/react@18.2.14)(bufferutil@4.0.8)(react@18.2.0)))(@tanstack/query-core@5.28.8)(@tanstack/react-query@5.28.8(react@18.2.0))(@types/react@18.2.14)(bufferutil@4.0.8)(react-dom@18.2.0(react@18.2.0))(react-native@0.76.1(@babel/core@7.22.9)(@babel/preset-env@7.24.6(@babel/core@7.22.9))(@types/react@18.2.14)(bufferutil@4.0.8)(react@18.2.0))(react@18.2.0)(rollup@4.27.4)(typescript@5.6.3)(viem@2.9.21(bufferutil@4.0.8)(typescript@5.6.3)(zod@3.22.4))(zod@3.22.4) - zod: - specifier: ^3.22.4 - version: 3.22.4 zustand: specifier: ^4.4.1 version: 4.4.1(@types/react@18.2.14)(react@18.2.0) @@ -398,6 +398,43 @@ importers: specifier: ^10.8.2 version: 10.8.2 + packages/common-testnets: + dependencies: + '@marsfoundation/common-nodejs': + specifier: workspace:^ + version: link:../common-nodejs + '@marsfoundation/common-universal': + specifier: workspace:^ + version: link:../common-universal + '@viem/anvil': + specifier: ^0.0.10 + version: 0.0.10(bufferutil@4.0.8)(utf-8-validate@6.0.3) + get-port: + specifier: ^7.1.0 + version: 7.1.0 + viem: + specifier: 2.21.18 + version: 2.21.18(bufferutil@4.0.8)(typescript@5.6.3)(utf-8-validate@6.0.3)(zod@3.24.1) + viem-deal: + specifier: ^2.0.0 + version: 2.0.4(viem@2.21.18(bufferutil@4.0.8)(typescript@5.6.3)(utf-8-validate@6.0.3)(zod@3.24.1)) + devDependencies: + '@types/mocha': + specifier: ^10.0.10 + version: 10.0.10 + '@types/uuid': + specifier: ^10.0.0 + version: 10.0.0 + earl: + specifier: ^1.3.0 + version: 1.3.0 + mocha: + specifier: ^10.8.2 + version: 10.8.2 + uuid: + specifier: ^11.0.2 + version: 11.0.3 + packages/common-universal: dependencies: bignumber.js: @@ -411,7 +448,7 @@ importers: version: 6.1.0 viem: specifier: ^2.9.21 - version: 2.9.21(bufferutil@4.0.8)(typescript@5.6.3)(utf-8-validate@6.0.3)(zod@3.22.4) + version: 2.9.21(bufferutil@4.0.8)(typescript@5.6.3)(utf-8-validate@6.0.3)(zod@3.24.1) devDependencies: '@sinonjs/fake-timers': specifier: ^13.0.5 @@ -2558,6 +2595,9 @@ packages: '@noble/curves@1.3.0': resolution: {integrity: sha512-t01iSXPuN+Eqzb4eBX0S5oubSqXbK/xXa1Ne18Hj8f9pStxztHCE2gfboSp/dZRLSqfuLpRK2nDXDK+W9puocA==} + '@noble/curves@1.4.0': + resolution: {integrity: sha512-p+4cb332SFCrReJkCYe8Xzm0OWi4Jji5jVdIZRL/PmacmDkFNw6MrrV+gGpiPxLHbV+zKFRywUWbaseT+tZRXg==} + '@noble/hashes@1.3.2': resolution: {integrity: sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ==} engines: {node: '>= 16'} @@ -2566,6 +2606,14 @@ packages: resolution: {integrity: sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA==} engines: {node: '>= 16'} + '@noble/hashes@1.4.0': + resolution: {integrity: sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==} + engines: {node: '>= 16'} + + '@noble/hashes@1.5.0': + resolution: {integrity: sha512-1j6kQFb7QRru7eKN3ZDvRcP13rugwdxZqCjbiAVZfIJwgj2A65UmT4TgARXGlXgnRkORLTDTrO19ZErt7+QXgA==} + engines: {node: ^14.21.3 || >=16} + '@nodelib/fs.scandir@2.1.5': resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} engines: {node: '>= 8'} @@ -3325,18 +3373,27 @@ packages: '@scure/base@1.1.6': resolution: {integrity: sha512-ok9AWwhcgYuGG3Zfhyqg+zwl+Wn5uE+dwC0NV/2qQkx4dABbb/bx96vWu8NSj+BNjjSjno+JRYRjle1jV08k3g==} + '@scure/base@1.1.9': + resolution: {integrity: sha512-8YKhl8GHiNI/pU2VMaofa2Tor7PJRAjwQLBBuilkJ9L5+13yVbC7JO/wS7piioAvPSwR3JKM1IJ/u4xQzbcXKg==} + '@scure/bip32@1.3.2': resolution: {integrity: sha512-N1ZhksgwD3OBlwTv3R6KFEcPojl/W4ElJOeCZdi+vuI5QmTFwLq3OFf2zd2ROpKvxFdgZ6hUpb0dx9bVNEwYCA==} '@scure/bip32@1.3.3': resolution: {integrity: sha512-LJaN3HwRbfQK0X1xFSi0Q9amqOgzQnnDngIt+ZlsBC3Bm7/nE7K0kwshZHyaru79yIVRv/e1mQAjZyuZG6jOFQ==} + '@scure/bip32@1.4.0': + resolution: {integrity: sha512-sVUpc0Vq3tXCkDGYVWGIZTRfnvu8LoTDaev7vbwh0omSvVORONr960MQWdKqJDCReIEmTj3PAr73O3aoxz7OPg==} + '@scure/bip39@1.2.1': resolution: {integrity: sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg==} '@scure/bip39@1.2.2': resolution: {integrity: sha512-HYf9TUXG80beW+hGAt3TRM8wU6pQoYur9iNypTROm42dorCGmLnFe3eWjz3gOq6G62H2WRh0FCzAR1PI+29zIA==} + '@scure/bip39@1.4.0': + resolution: {integrity: sha512-BEEm6p8IueV/ZTfQLp/0vhw4NPnT9oWf5+28nvmeUICjP99f4vr2d+qc7AVGDDtwRep6ifR43Yed9ERVmiITzw==} + '@sentry-internal/feedback@7.114.0': resolution: {integrity: sha512-kUiLRUDZuh10QE9JbSVVLgqxFoD9eDPOzT0MmzlPuas8JlTmJuV4FtSANNcqctd5mBuLt2ebNXH0MhRMwyae4A==} engines: {node: '>=12'} @@ -4338,6 +4395,9 @@ packages: peerDependencies: '@vanilla-extract/css': ^1.0.0 + '@viem/anvil@0.0.10': + resolution: {integrity: sha512-9PzYXBRikfSUhhm8Bd0avv07agwcbMJ5FaSu2D2vbE0cxkvXGtolL3fW5nz2yefMqOqVQL4XzfM5nwY81x3ytw==} + '@viem/anvil@0.0.6': resolution: {integrity: sha512-OjKR/+FVwzuygXYFqP8MBal1SXG8bT2gbZwqqB0XuLw81LNBBvmE/Repm6+5kkBh4IUj0PhYdrqOsnayS14Gtg==} @@ -4594,6 +4654,17 @@ packages: zod: optional: true + abitype@1.0.5: + resolution: {integrity: sha512-YzDhti7cjlfaBhHutMaboYB21Ha3rXR9QTkNJFzYC4kC8YclaiwPBBBJY8ejFdu2wnJeZCVZSMlQJ7fi8S6hsw==} + peerDependencies: + typescript: '>=5.0.4' + zod: ^3 >=3.22.0 + peerDependenciesMeta: + typescript: + optional: true + zod: + optional: true + abitype@1.0.6: resolution: {integrity: sha512-MMSqYh4+C/aVqI2RQaWqbvI4Kxo5cQV40WQ4QFtDnNzCkqChm8MuENhElmynZlO0qUy/ObkEUaXtKqYnx1Kp3A==} peerDependencies: @@ -6250,6 +6321,10 @@ packages: resolution: {integrity: sha512-BrGGraKm2uPqurfGVj/z97/zv8dPleC6x9JBNRTrDNtCkkRF4rPwrQXFgL7+I+q8QSdU4ntLQX2D7KIxSy8nGw==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} + get-port@7.1.0: + resolution: {integrity: sha512-QB9NKEeDg3xxVwCCwJQ9+xycaz6pBB6iQ76wiWMl1927n0Kir6alPiP+yuiICLLU4jpMe08dXfpebuQppFA2zw==} + engines: {node: '>=16'} + get-stream@6.0.1: resolution: {integrity: sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==} engines: {node: '>=10'} @@ -6818,6 +6893,11 @@ packages: peerDependencies: ws: '*' + isows@1.0.4: + resolution: {integrity: sha512-hEzjY+x9u9hPmBom9IIAqdJCwNLax+xrPb51vEPpERoFlIxgmZcHzsT5jKG06nvInKOBGvReAVz80Umed5CczQ==} + peerDependencies: + ws: '*' + istanbul-lib-coverage@3.2.2: resolution: {integrity: sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==} engines: {node: '>=8'} @@ -7515,10 +7595,6 @@ packages: resolution: {integrity: sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==} engines: {node: '>=8'} - npm-run-path@5.1.0: - resolution: {integrity: sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q==} - engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} - npm-run-path@5.3.0: resolution: {integrity: sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==} engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} @@ -9331,6 +9407,11 @@ packages: resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} engines: {node: '>= 0.8'} + viem-deal@2.0.4: + resolution: {integrity: sha512-gd1+pnLissjxYbaJ8u2UtdOOpv0o4W8RsVlSwy5w+SEasi/f5VJvrCVmE8cBrcHpvWYqoaxwj4VfJG45oLPnyQ==} + peerDependencies: + viem: ^2.21.18 + viem@1.21.4: resolution: {integrity: sha512-BNVYdSaUjeS2zKQgPs+49e5JKocfo60Ib2yiXOWBT6LuVxY1I/6fFX3waEtpXvL1Xn4qu+BVitVtMh9lyThyhQ==} peerDependencies: @@ -9339,6 +9420,14 @@ packages: typescript: optional: true + viem@2.21.18: + resolution: {integrity: sha512-CuZpymwBsuK2/YNDJE06EXxpfYs71X4v5ZwiGV5RczLKOwfHa/XuM3+GKbAoKCVeQ/tFt5n8XeHsMnbvEAauTg==} + peerDependencies: + typescript: '>=5.0.4' + peerDependenciesMeta: + typescript: + optional: true + viem@2.9.21: resolution: {integrity: sha512-8GtxPjPGpiN5cmr19zSX9mb1LX/eON3MPxxAd3QmyUFn69Rp566zlREOqE7zM35y5yX59fXwnz6O3X7e9+C9zg==} peerDependencies: @@ -9453,6 +9542,9 @@ packages: wcwidth@1.0.1: resolution: {integrity: sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==} + webauthn-p256@0.0.5: + resolution: {integrity: sha512-drMGNWKdaixZNobeORVIqq7k5DsRC9FnG201K2QjeOoQLmtSDaSsVZdkg6n5jUALJKcAG++zBPJXmv6hy0nWFg==} + webextension-polyfill-ts@0.25.0: resolution: {integrity: sha512-ikQhwwHYkpBu00pFaUzIKY26I6L87DeRI+Q6jBT1daZUNuu8dSrg5U9l/ZbqdaQ1M/TTSPKeAa3kolP5liuedw==} deprecated: This project has moved to @types/webextension-polyfill @@ -9625,6 +9717,18 @@ packages: utf-8-validate: optional: true + ws@8.17.1: + resolution: {integrity: sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==} + engines: {node: '>=10.0.0'} + peerDependencies: + bufferutil: ^4.0.1 + utf-8-validate: '>=5.0.2' + peerDependenciesMeta: + bufferutil: + optional: true + utf-8-validate: + optional: true + xml-name-validator@4.0.0: resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==} engines: {node: '>=12'} @@ -9705,6 +9809,9 @@ packages: zod@3.22.4: resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==} + zod@3.24.1: + resolution: {integrity: sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A==} + zustand@4.4.1: resolution: {integrity: sha512-QCPfstAS4EBiTQzlaGP1gmorkh/UL1Leaj2tdj+zZCZ/9bm0WS7sI2wnfD5lpOszFqWJ1DcPnGoY8RDL61uokw==} engines: {node: '>=12.7.0'} @@ -12233,10 +12340,18 @@ snapshots: dependencies: '@noble/hashes': 1.3.3 + '@noble/curves@1.4.0': + dependencies: + '@noble/hashes': 1.4.0 + '@noble/hashes@1.3.2': {} '@noble/hashes@1.3.3': {} + '@noble/hashes@1.4.0': {} + + '@noble/hashes@1.5.0': {} + '@nodelib/fs.scandir@2.1.5': dependencies: '@nodelib/fs.stat': 2.0.5 @@ -12851,7 +12966,7 @@ snapshots: react-dom: 18.2.0(react@18.2.0) react-remove-scroll: 2.5.7(@types/react@18.2.14)(react@18.2.0) ua-parser-js: 1.0.37 - viem: 2.9.21(bufferutil@4.0.8)(typescript@5.6.3)(utf-8-validate@6.0.3)(zod@3.22.4) + viem: 2.9.21(bufferutil@4.0.8)(typescript@5.6.3)(zod@3.22.4) wagmi: 2.5.20(@react-native-async-storage/async-storage@1.22.0(react-native@0.76.1(@babel/core@7.22.9)(@babel/preset-env@7.24.6(@babel/core@7.22.9))(@types/react@18.2.14)(bufferutil@4.0.8)(react@18.2.0)))(@tanstack/query-core@5.28.8)(@tanstack/react-query@5.28.8(react@18.2.0))(@types/react@18.2.14)(bufferutil@4.0.8)(react-dom@18.2.0(react@18.2.0))(react-native@0.76.1(@babel/core@7.22.9)(@babel/preset-env@7.24.6(@babel/core@7.22.9))(@types/react@18.2.14)(bufferutil@4.0.8)(react@18.2.0))(react@18.2.0)(rollup@4.27.4)(typescript@5.6.3)(viem@2.9.21(bufferutil@4.0.8)(typescript@5.6.3)(zod@3.22.4))(zod@3.22.4) transitivePeerDependencies: - '@types/react' @@ -13092,6 +13207,8 @@ snapshots: '@scure/base@1.1.6': {} + '@scure/base@1.1.9': {} + '@scure/bip32@1.3.2': dependencies: '@noble/curves': 1.2.0 @@ -13104,6 +13221,12 @@ snapshots: '@noble/hashes': 1.3.3 '@scure/base': 1.1.6 + '@scure/bip32@1.4.0': + dependencies: + '@noble/curves': 1.4.0 + '@noble/hashes': 1.4.0 + '@scure/base': 1.1.6 + '@scure/bip39@1.2.1': dependencies: '@noble/hashes': 1.3.3 @@ -13114,6 +13237,11 @@ snapshots: '@noble/hashes': 1.3.3 '@scure/base': 1.1.6 + '@scure/bip39@1.4.0': + dependencies: + '@noble/hashes': 1.5.0 + '@scure/base': 1.1.9 + '@sentry-internal/feedback@7.114.0': dependencies: '@sentry/core': 7.114.0 @@ -13757,7 +13885,7 @@ snapshots: util: 0.12.5 util-deprecate: 1.0.2 watchpack: 2.4.1 - ws: 8.14.2(bufferutil@4.0.8) + ws: 8.14.2(bufferutil@4.0.8)(utf-8-validate@6.0.3) transitivePeerDependencies: - bufferutil - encoding @@ -14612,6 +14740,17 @@ snapshots: dependencies: '@vanilla-extract/css': 1.14.0 + '@viem/anvil@0.0.10(bufferutil@4.0.8)(utf-8-validate@6.0.3)': + dependencies: + execa: 7.2.0 + get-port: 6.1.2 + http-proxy: 1.18.1 + ws: 8.14.2(bufferutil@4.0.8)(utf-8-validate@6.0.3) + transitivePeerDependencies: + - bufferutil + - debug + - utf-8-validate + '@viem/anvil@0.0.6(bufferutil@4.0.8)': dependencies: execa: 7.2.0 @@ -14836,7 +14975,7 @@ snapshots: picocolors: 1.0.0 picomatch: 3.0.1 prettier: 3.2.5 - viem: 2.9.21(bufferutil@4.0.8)(typescript@5.6.3)(utf-8-validate@6.0.3)(zod@3.22.4) + viem: 2.9.21(bufferutil@4.0.8)(typescript@5.6.3)(zod@3.22.4) zod: 3.22.4 optionalDependencies: typescript: 5.6.3 @@ -14853,7 +14992,7 @@ snapshots: '@wagmi/core': 2.6.17(@tanstack/query-core@5.28.8)(@types/react@18.2.14)(bufferutil@4.0.8)(react@18.2.0)(typescript@5.6.3)(viem@2.9.21(bufferutil@4.0.8)(typescript@5.6.3)(zod@3.22.4))(zod@3.22.4) '@walletconnect/ethereum-provider': 2.11.2(@react-native-async-storage/async-storage@1.22.0(react-native@0.76.1(@babel/core@7.22.9)(@babel/preset-env@7.24.6(@babel/core@7.22.9))(@types/react@18.2.14)(bufferutil@4.0.8)(react@18.2.0)))(@types/react@18.2.14)(bufferutil@4.0.8)(react@18.2.0) '@walletconnect/modal': 2.6.2(@types/react@18.2.14)(react@18.2.0) - viem: 2.9.21(bufferutil@4.0.8)(typescript@5.6.3)(utf-8-validate@6.0.3)(zod@3.22.4) + viem: 2.9.21(bufferutil@4.0.8)(typescript@5.6.3)(zod@3.22.4) optionalDependencies: typescript: 5.6.3 transitivePeerDependencies: @@ -14884,7 +15023,7 @@ snapshots: dependencies: eventemitter3: 5.0.1 mipd: 0.0.5(bufferutil@4.0.8)(typescript@5.6.3)(zod@3.22.4) - viem: 2.9.21(bufferutil@4.0.8)(typescript@5.6.3)(utf-8-validate@6.0.3)(zod@3.22.4) + viem: 2.9.21(bufferutil@4.0.8)(typescript@5.6.3)(zod@3.22.4) zustand: 4.4.1(@types/react@18.2.14)(react@18.2.0) optionalDependencies: '@tanstack/query-core': 5.28.8 @@ -15242,6 +15381,16 @@ snapshots: typescript: 5.6.3 zod: 3.22.4 + abitype@1.0.0(typescript@5.6.3)(zod@3.24.1): + optionalDependencies: + typescript: 5.6.3 + zod: 3.24.1 + + abitype@1.0.5(typescript@5.6.3)(zod@3.24.1): + optionalDependencies: + typescript: 5.6.3 + zod: 3.24.1 + abitype@1.0.6(typescript@5.6.3)(zod@3.22.4): optionalDependencies: typescript: 5.6.3 @@ -16881,7 +17030,7 @@ snapshots: human-signals: 4.3.1 is-stream: 3.0.0 merge-stream: 2.0.0 - npm-run-path: 5.1.0 + npm-run-path: 5.3.0 onetime: 6.0.0 signal-exit: 3.0.7 strip-final-newline: 3.0.0 @@ -17185,6 +17334,8 @@ snapshots: get-port@6.1.2: {} + get-port@7.1.0: {} + get-stream@6.0.1: {} get-stream@8.0.1: {} @@ -17774,6 +17925,10 @@ snapshots: dependencies: ws: 8.13.0(bufferutil@4.0.8)(utf-8-validate@6.0.3) + isows@1.0.4(ws@8.17.1(bufferutil@4.0.8)(utf-8-validate@6.0.3)): + dependencies: + ws: 8.17.1(bufferutil@4.0.8)(utf-8-validate@6.0.3) + istanbul-lib-coverage@3.2.2: {} istanbul-lib-instrument@5.2.1: @@ -18674,10 +18829,6 @@ snapshots: dependencies: path-key: 3.1.1 - npm-run-path@5.1.0: - dependencies: - path-key: 4.0.0 - npm-run-path@5.3.0: dependencies: path-key: 4.0.0 @@ -20644,6 +20795,10 @@ snapshots: vary@1.1.2: {} + viem-deal@2.0.4(viem@2.21.18(bufferutil@4.0.8)(typescript@5.6.3)(utf-8-validate@6.0.3)(zod@3.24.1)): + dependencies: + viem: 2.21.18(bufferutil@4.0.8)(typescript@5.6.3)(utf-8-validate@6.0.3)(zod@3.24.1) + viem@1.21.4(bufferutil@4.0.8)(typescript@5.6.3)(zod@3.22.4): dependencies: '@adraffy/ens-normalize': 1.10.0 @@ -20661,7 +20816,42 @@ snapshots: - utf-8-validate - zod - viem@2.9.21(bufferutil@4.0.8)(typescript@5.6.3)(utf-8-validate@6.0.3)(zod@3.22.4): + viem@2.21.18(bufferutil@4.0.8)(typescript@5.6.3)(utf-8-validate@6.0.3)(zod@3.24.1): + dependencies: + '@adraffy/ens-normalize': 1.10.0 + '@noble/curves': 1.4.0 + '@noble/hashes': 1.4.0 + '@scure/bip32': 1.4.0 + '@scure/bip39': 1.4.0 + abitype: 1.0.5(typescript@5.6.3)(zod@3.24.1) + isows: 1.0.4(ws@8.17.1(bufferutil@4.0.8)(utf-8-validate@6.0.3)) + webauthn-p256: 0.0.5 + ws: 8.17.1(bufferutil@4.0.8)(utf-8-validate@6.0.3) + optionalDependencies: + typescript: 5.6.3 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + - zod + + viem@2.9.21(bufferutil@4.0.8)(typescript@5.6.3)(utf-8-validate@6.0.3)(zod@3.24.1): + dependencies: + '@adraffy/ens-normalize': 1.10.0 + '@noble/curves': 1.2.0 + '@noble/hashes': 1.3.2 + '@scure/bip32': 1.3.2 + '@scure/bip39': 1.2.1 + abitype: 1.0.0(typescript@5.6.3)(zod@3.24.1) + isows: 1.0.3(ws@8.13.0(bufferutil@4.0.8)(utf-8-validate@6.0.3)) + ws: 8.13.0(bufferutil@4.0.8)(utf-8-validate@6.0.3) + optionalDependencies: + typescript: 5.6.3 + transitivePeerDependencies: + - bufferutil + - utf-8-validate + - zod + + viem@2.9.21(bufferutil@4.0.8)(typescript@5.6.3)(zod@3.22.4): dependencies: '@adraffy/ens-normalize': 1.10.0 '@noble/curves': 1.2.0 @@ -20777,7 +20967,7 @@ snapshots: '@wagmi/core': 2.6.17(@tanstack/query-core@5.28.8)(@types/react@18.2.14)(bufferutil@4.0.8)(react@18.2.0)(typescript@5.6.3)(viem@2.9.21(bufferutil@4.0.8)(typescript@5.6.3)(zod@3.22.4))(zod@3.22.4) react: 18.2.0 use-sync-external-store: 1.2.0(react@18.2.0) - viem: 2.9.21(bufferutil@4.0.8)(typescript@5.6.3)(utf-8-validate@6.0.3)(zod@3.22.4) + viem: 2.9.21(bufferutil@4.0.8)(typescript@5.6.3)(zod@3.22.4) optionalDependencies: typescript: 5.6.3 transitivePeerDependencies: @@ -20818,6 +21008,11 @@ snapshots: dependencies: defaults: 1.0.4 + webauthn-p256@0.0.5: + dependencies: + '@noble/curves': 1.4.0 + '@noble/hashes': 1.4.0 + webextension-polyfill-ts@0.25.0: dependencies: webextension-polyfill: 0.7.0 @@ -20979,9 +21174,15 @@ snapshots: bufferutil: 4.0.8 utf-8-validate: 6.0.3 - ws@8.14.2(bufferutil@4.0.8): + ws@8.14.2(bufferutil@4.0.8)(utf-8-validate@6.0.3): + optionalDependencies: + bufferutil: 4.0.8 + utf-8-validate: 6.0.3 + + ws@8.17.1(bufferutil@4.0.8)(utf-8-validate@6.0.3): optionalDependencies: bufferutil: 4.0.8 + utf-8-validate: 6.0.3 xml-name-validator@4.0.0: {} @@ -21061,6 +21262,9 @@ snapshots: zod@3.22.4: {} + zod@3.24.1: + optional: true + zustand@4.4.1(@types/react@18.2.14)(react@18.2.0): dependencies: use-sync-external-store: 1.2.0(react@18.2.0)