diff --git a/.changeset/config.json b/.changeset/config.json
index c47279e4c8..11187a0aca 100644
--- a/.changeset/config.json
+++ b/.changeset/config.json
@@ -1,9 +1,15 @@
{
- "$schema": "https://unpkg.com/@changesets/config@2.3.1/schema.json",
+ "$schema": "https://unpkg.com/@changesets/config@3.0.5/schema.json",
+ "changelog": [
+ "@svitejs/changesets-changelog-github-compact",
+ { "repo": "wevm/wagmi" }
+ ],
+ "commit": false,
"access": "public",
+ "fixed": [],
+ "linked": [],
"baseBranch": "main",
- "changelog": ["@changesets/changelog-github", { "repo": "wevm/wagmi" }],
- "commit": false,
+ "updateInternalDependencies": "minor",
"ignore": [
"*-register",
"@wagmi/test",
@@ -11,9 +17,5 @@
"next-app",
"nuxt-app",
"vite-*"
- ],
- "updateInternalDependencies": "patch",
- "___experimentalUnsafeOptions_WILL_CHANGE_IN_PATCH": {
- "onlyUpdatePeerDependentsWhenOutOfRange": true
- }
+ ]
}
diff --git a/.changeset/cool-masks-hang.md b/.changeset/cool-masks-hang.md
deleted file mode 100644
index 0c0ff73c79..0000000000
--- a/.changeset/cool-masks-hang.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"@wagmi/connectors": patch
----
-
-Added `rdns` property to Coinbase Wallet v3 connector
diff --git a/.changeset/young-houses-relate.md b/.changeset/young-houses-relate.md
deleted file mode 100644
index 288ab44256..0000000000
--- a/.changeset/young-houses-relate.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-"@wagmi/connectors": patch
----
-
-Bumped `@safe-global/safe-apps-provider` version to `0.18.6`.
diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS
index 12451d4bc9..9c8e90839e 100644
--- a/.github/CODEOWNERS
+++ b/.github/CODEOWNERS
@@ -1,5 +1,6 @@
@tmm @jxom
+/packages/connectors/src/gemini @mikelxc
/packages/connectors/src/metaMask @ecp4224 @omridan159 @abretonc7s @elefantel @BjornGunnarsson @EdouardBougon
/packages/connectors/src/safe @DaniSomoza @dasanra @mikhailxyz @yagopv
/packages/connectors/src/walletConnect @ganchoradkov @glitch-txs @ignaciosantise @tomiir
diff --git a/.github/README.md b/.github/README.md
index 6b5f336419..6a42bc8198 100644
--- a/.github/README.md
+++ b/.github/README.md
@@ -23,6 +23,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -239,6 +252,12 @@ If you find Wagmi useful or use it for work, please consider [sponsoring Wagmi](
+
+
+
+
+
+
[Sponsor Wagmi](https://github.com/sponsors/wevm?metadata_campaign=gh_readme_support_bottom)
diff --git a/.github/workflows/changesets.yml b/.github/workflows/changesets.yml
index 34e945ddf0..ad427406cf 100644
--- a/.github/workflows/changesets.yml
+++ b/.github/workflows/changesets.yml
@@ -2,6 +2,8 @@ name: Changesets
on:
push:
branches: [main]
+permissions:
+ contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
@@ -10,31 +12,37 @@ concurrency:
jobs:
verify:
name: Verify
+ permissions:
+ contents: write
uses: ./.github/workflows/verify.yml
secrets: inherit
changesets:
name: Publish
needs: verify
+ # prevents this action from running on forks
+ if: github.repository == 'wevm/wagmi'
permissions:
- contents: write
- id-token: write
- pull-requests: write
+ contents: write # to create release (changesets/action)
+ id-token: write # OpenID Connect token needed for provenance
+ pull-requests: write # to create pull request (changesets/action)
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Clone repository
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683
+ uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
with:
# This makes Actions fetch all Git history so that Changesets can generate changelogs with the correct commits
fetch-depth: 0
- name: Install dependencies
- uses: wevm/actions/.github/actions/pnpm@main
+ uses: wevm/actions/.github/actions/pnpm@f7ad7f00e16e73322562922c241f21f0c7ffbbec
+ with:
+ node-version: 24.5
- name: PR or publish
- uses: changesets/action@06245a4e0a36c064a573d4150030f5ec548e4fcc
+ uses: changesets/action@e0145edc7d9d8679003495b11f87bd8ef63c0cba # v1.5.3
with:
title: 'chore: version packages'
commit: 'chore: version packages'
@@ -43,18 +51,14 @@ jobs:
version: pnpm changeset:version
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
- - name: Publish prerelease
+ - name: Publish canary release
if: steps.changesets.outputs.published != 'true'
continue-on-error: true
env:
- NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
- npm config set "//registry.npmjs.org/:_authToken" "$NPM_TOKEN"
git reset --hard origin/main
- pnpm clean
pnpm changeset version --no-git-tag --snapshot canary
pnpm changeset:prepublish
pnpm changeset publish --no-git-tag --snapshot canary --tag canary
diff --git a/.github/workflows/issue-labeled.yml b/.github/workflows/issue-labeled.yml
index 39b98291d1..eaa28bfd01 100644
--- a/.github/workflows/issue-labeled.yml
+++ b/.github/workflows/issue-labeled.yml
@@ -1,4 +1,6 @@
name: Issue Labeled
+permissions:
+ issues: write
on:
issues:
@@ -7,7 +9,7 @@ on:
jobs:
issue-labeled:
if: ${{ github.repository_owner == 'wevm' }}
- uses: wevm/actions/.github/workflows/issue-labeled.yml@main
+ uses: wevm/actions/.github/workflows/issue-labeled.yml@f7ad7f00e16e73322562922c241f21f0c7ffbbec
with:
needs-reproduction-body: |
Hello @${{ github.event.issue.user.login }}.
diff --git a/.github/workflows/lock-issue.yml b/.github/workflows/lock-issue.yml
index 279452d223..afce18e9fb 100644
--- a/.github/workflows/lock-issue.yml
+++ b/.github/workflows/lock-issue.yml
@@ -1,4 +1,6 @@
name: Lock Issue
+permissions:
+ issues: write
on:
schedule:
@@ -7,7 +9,7 @@ on:
jobs:
lock-issue:
if: ${{ github.repository_owner == 'wevm' }}
- uses: wevm/actions/.github/workflows/lock-issue.yml@main
+ uses: wevm/actions/.github/workflows/lock-issue.yml@f7ad7f00e16e73322562922c241f21f0c7ffbbec
with:
issue-comment: |
This issue has been locked since it has been closed for more than 14 days.
diff --git a/.github/workflows/pull-request.yml b/.github/workflows/pull-request.yml
index 9ff4c5bb76..6634c53d07 100644
--- a/.github/workflows/pull-request.yml
+++ b/.github/workflows/pull-request.yml
@@ -2,6 +2,8 @@ name: Pull Request
on:
pull_request:
types: [opened, reopened, synchronize, ready_for_review]
+permissions:
+ contents: read
concurrency:
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
@@ -10,23 +12,55 @@ concurrency:
jobs:
verify:
name: Verify
+ permissions:
+ contents: write
uses: ./.github/workflows/verify.yml
secrets: inherit
+ publish:
+ name: Publish preview release
+ # prevents this action from running on forks
+ if: github.repository == 'wevm/wagmi'
+ permissions:
+ contents: read
+ runs-on: ubuntu-latest
+ timeout-minutes: 5
+
+ steps:
+ - name: Clone repository
+ uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
+
+ - name: Install dependencies
+ uses: wevm/actions/.github/actions/pnpm@f7ad7f00e16e73322562922c241f21f0c7ffbbec
+ with:
+ node-version: 24.5
+
+ - name: Publish to pkg.pr.new
+ run: |
+ pnpm changeset:prepublish
+ pnpx pkg-pr-new publish --pnpm --compact './packages/*'
+ env:
+ PKG_PR_NEW: true
+
size:
name: Size
+ permissions:
+ contents: read
+ pull-requests: write
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Clone repository
- uses: actions/checkout@v4
+ uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
- name: Install dependencies
- uses: wevm/actions/.github/actions/pnpm@main
+ uses: wevm/actions/.github/actions/pnpm@f7ad7f00e16e73322562922c241f21f0c7ffbbec
+ with:
+ node-version: 24.5
- name: Report build size
- uses: preactjs/compressed-size-action@v2
+ uses: preactjs/compressed-size-action@946a292cd35bd1088e0d7eb92b69d1a8d5b5d76a
with:
pattern: 'packages/**/dist/**'
repo-token: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/scorecard.yml b/.github/workflows/scorecard.yml
new file mode 100644
index 0000000000..ba176318ec
--- /dev/null
+++ b/.github/workflows/scorecard.yml
@@ -0,0 +1,51 @@
+name: Scorecard
+on:
+ # For Branch-Protection check. Only the default branch is supported. See
+ # https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection
+ branch_protection_rule:
+ # To guarantee Maintained check is occasionally updated. See
+ # https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained
+ schedule:
+ - cron: '22 13 * * 0'
+ push:
+ branches: [ "main" ]
+
+# Declare default permissions as read only.
+permissions: read-all
+
+jobs:
+ analysis:
+ name: Scorecard analysis
+ runs-on: ubuntu-latest
+ # `publish_results: true` only works when run from the default branch. conditional can be removed if disabled.
+ if: github.event.repository.default_branch == github.ref_name || github.event_name == 'pull_request'
+ permissions:
+ # Needed to upload the results to code-scanning dashboard.
+ security-events: write
+ # Needed to publish results and get a badge (see publish_results below).
+ id-token: write
+
+ steps:
+ - name: "Checkout code"
+ uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
+ with:
+ persist-credentials: false
+
+ - name: "Run analysis"
+ uses: ossf/scorecard-action@f49aabe0b5af0936a0987cfb85d86b75731b0186 # v2.4.1
+ with:
+ results_file: results.sarif
+ results_format: sarif
+ publish_results: true
+
+ - name: "Upload artifact"
+ uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1
+ with:
+ name: SARIF file
+ path: results.sarif
+ retention-days: 5
+
+ - name: "Upload to code-scanning"
+ uses: github/codeql-action/upload-sarif@80cb6b56b93de3e779c7d476d9100d06fb87c877 # codeql-bundle-v2.23.2
+ with:
+ sarif_file: results.sarif
diff --git a/.github/workflows/snapshot.yml b/.github/workflows/snapshot.yml
deleted file mode 100644
index 39683bb684..0000000000
--- a/.github/workflows/snapshot.yml
+++ /dev/null
@@ -1,32 +0,0 @@
-name: Snapshot
-on:
- workflow_dispatch:
-
-jobs:
- snapshot:
- name: Release snapshot version
- permissions:
- contents: write
- id-token: write
- runs-on: ubuntu-latest
- timeout-minutes: 5
-
- steps:
- - name: Clone repository
- uses: actions/checkout@v4
-
- - name: Install dependencies
- uses: wevm/actions/.github/actions/pnpm@main
-
- - name: Publish Snapshots
- continue-on-error: true
- env:
- NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
- GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- run: |
- snapshot=$(git branch --show-current | tr -cs '[:alnum:]-' '-' | tr '[:upper:]' '[:lower:]' | sed 's/-$//')
- npm config set "//registry.npmjs.org/:_authToken" "$NPM_TOKEN"
- pnpm clean
- pnpm changeset version --no-git-tag --snapshot $snapshot
- pnpm changeset:prepublish
- pnpm changeset publish --no-git-tag --snapshot $snapshot --tag $snapshot
diff --git a/.github/workflows/verify.yml b/.github/workflows/verify.yml
index 2ec609c42c..dc10db5e03 100644
--- a/.github/workflows/verify.yml
+++ b/.github/workflows/verify.yml
@@ -2,6 +2,8 @@ name: Verify
on:
workflow_call:
workflow_dispatch:
+permissions:
+ contents: read
jobs:
check:
@@ -13,12 +15,17 @@ jobs:
steps:
- name: Clone repository
- uses: actions/checkout@v4
+ uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
with:
token: ${{ secrets.GH_PTOKEN }}
- name: Install dependencies
- uses: wevm/actions/.github/actions/pnpm@main
+ uses: wevm/actions/.github/actions/pnpm@f7ad7f00e16e73322562922c241f21f0c7ffbbec
+ with:
+ node-version: 24.5
+
+ - name: Audit dependencies
+ run: pnpm audit
- name: Check repo
run: pnpm check:repo
@@ -29,7 +36,7 @@ jobs:
- name: Update package versions
run: pnpm version:update
- - uses: stefanzweifel/git-auto-commit-action@v5
+ - uses: stefanzweifel/git-auto-commit-action@778341af668090896ca464160c2def5d1d1a3eb0 # v6.0.1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
@@ -39,19 +46,23 @@ jobs:
build:
name: Build
+ permissions:
+ contents: read
needs: check
runs-on: ubuntu-latest
timeout-minutes: 5
steps:
- name: Clone repository
- uses: actions/checkout@v4
+ uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
- name: Install dependencies
- uses: wevm/actions/.github/actions/pnpm@main
+ uses: wevm/actions/.github/actions/pnpm@f7ad7f00e16e73322562922c241f21f0c7ffbbec
+ with:
+ node-version: 24.5
- name: Build
- run: pnpm build
+ run: pnpm clean && pnpm build
- name: Publint
run: pnpm test:build
@@ -61,20 +72,24 @@ jobs:
types:
name: Types
+ permissions:
+ contents: read
needs: check
runs-on: ubuntu-latest
timeout-minutes: 5
strategy:
matrix:
- typescript-version: ['5.2.2', '5.3.3', '5.4.5', '5.5.2']
- viem-version: ['2.23.12', 'latest']
+ typescript-version: ['5.7.3', '5.8.3', '5.9.3', 'latest']
+ viem-version: ['2.44.0', 'latest']
steps:
- name: Clone repository
- uses: actions/checkout@v4
+ uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
- name: Install dependencies
- uses: wevm/actions/.github/actions/pnpm@main
+ uses: wevm/actions/.github/actions/pnpm@f7ad7f00e16e73322562922c241f21f0c7ffbbec
+ with:
+ node-version: 24.5
- run: pnpm add -D -w typescript@${{ matrix.typescript-version }} viem@${{ matrix.viem-version }}
@@ -84,6 +99,9 @@ jobs:
- name: Check types
run: pnpm check:types
+ - name: Bench types
+ run: pnpm bench:types
+
# Redundant with `pnpm check:types`
# If Vitest adds special features in the future, e.g. type coverage, can add this back!
# - name: Test types
@@ -91,6 +109,8 @@ jobs:
test:
name: Test
+ permissions:
+ contents: read
runs-on: ubuntu-latest
timeout-minutes: 10
strategy:
@@ -101,18 +121,34 @@ jobs:
steps:
- name: Clone repository
- uses: actions/checkout@v4
+ uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8
- name: Install dependencies
- uses: wevm/actions/.github/actions/pnpm@main
+ uses: wevm/actions/.github/actions/pnpm@f7ad7f00e16e73322562922c241f21f0c7ffbbec
+ with:
+ node-version: 24.5
+
+ - name: Setup Docker
+ uses: docker/setup-docker-action@v4
- name: Set up foundry
- uses: foundry-rs/foundry-toolchain@v1
+ uses: foundry-rs/foundry-toolchain@50d5a8956f2e319df19e6b57539d7e2acb9f8c1e # v1.5.0
with:
version: nightly
+ - name: Cache Playwright
+ uses: actions/cache@9255dc7a253b0ccc959486e2bca901246202afeb
+ id: playwright-cache
+ with:
+ path: ~/.cache/ms-playwright
+ key: ${{ runner.os }}-playwright-${{ hashFiles('pnpm-lock.yaml') }}
+
+ - name: Install Playwright
+ if: steps.playwright-cache.outputs.cache-hit != 'true'
+ run: pnpm exec playwright install chromium --with-deps
+
- name: Run tests
- uses: nick-fields/retry@v3
+ uses: nick-fields/retry@ce71cc2ab81d554ebbe88c79ab5975992d79ba08
with:
command: CI=true pnpm test:cov --shard=${{ matrix.shard }}/${{ matrix.total-shards }} --retry=3 --bail=1
max_attempts: 3
@@ -122,6 +158,6 @@ jobs:
VITE_OPTIMISM_FORK_URL: ${{ secrets.VITE_OPTIMISM_FORK_URL }}
- name: Upload coverage reports to Codecov
- uses: codecov/codecov-action@v5
+ uses: codecov/codecov-action@5a1091511ad55cbe89839c7260b706298ca349f7
with:
token: ${{ secrets.CODECOV_TOKEN }}
diff --git a/.gitignore b/.gitignore
index 1834fe72ab..e89dcd50c3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,13 +1,17 @@
+*.vitest-temp.json
.DS_Store
+.attest
.next
.nuxt
.pnpm-debug.log*
+.tanstack
+.wrangler
+_
cache
coverage
dist
node_modules
tsconfig.tsbuildinfo
-*.vitest-temp.json
# local env files
.env
@@ -31,9 +35,11 @@ packages/react/chains
packages/react/codegen
packages/react/connectors
packages/react/experimental
+packages/react/internal
packages/react/query
packages/vue/actions
packages/vue/chains
packages/vue/connectors
+packages/vue/internal
packages/vue/nuxt
packages/vue/query
diff --git a/.npmrc b/.npmrc
deleted file mode 100644
index 47687565bf..0000000000
--- a/.npmrc
+++ /dev/null
@@ -1,5 +0,0 @@
-auto-install-peers=false
-enable-pre-post-scripts=true
-link-workspace-packages=deep
-provenance=true
-strict-peer-dependencies=false
diff --git a/.vscode/settings.json b/.vscode/settings.json
index c32e8fa4c3..6318c082c0 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -5,8 +5,7 @@
"typescript.preferences.importModuleSpecifier": "shortest",
"typescript.tsdk": "node_modules/typescript/lib",
"editor.codeActionsOnSave": {
- "quickfix.biome": "explicit",
- "source.organizeImports.biome": "explicit"
+ "source.fixAll.biome": "explicit"
},
"[javascript][javascriptreact][json][typescript][typescriptreact]": {
"editor.defaultFormatter": "biomejs.biome"
diff --git a/biome.json b/biome.json
index ce99662cb0..9fb7318f87 100644
--- a/biome.json
+++ b/biome.json
@@ -1,7 +1,14 @@
{
"$schema": "./node_modules/@biomejs/biome/configuration_schema.json",
"files": {
- "ignore": ["CHANGELOG.md", "pnpm-lock.yaml", "tsconfig.base.json"]
+ "includes": [
+ "**",
+ "!**/CHANGELOG.md",
+ "!**/pnpm-lock.yaml",
+ "!**/routeTree.gen.ts",
+ "!**/tsconfig.base.json",
+ "!**/worker-configuration.d.ts"
+ ]
},
"formatter": {
"enabled": true,
@@ -11,13 +18,16 @@
"lineWidth": 80
},
"linter": {
- "ignore": ["packages/create-wagmi/templates/*"],
+ "includes": ["**", "!**/packages/create-wagmi/templates/**/*"],
"enabled": true,
"rules": {
"recommended": true,
"a11y": {
"useButtonType": "off"
},
+ "complexity": {
+ "noImportantStyles": "off"
+ },
"correctness": {
"noUnusedVariables": "error",
"useExhaustiveDependencies": "error"
@@ -29,13 +39,34 @@
},
"style": {
"noNonNullAssertion": "off",
- "useShorthandArrayType": "error"
+ "noParameterAssign": "error",
+ "useAsConstAssertion": "error",
+ "useDefaultParameterLast": "error",
+ "useEnumInitializers": "error",
+ "useSelfClosingElements": "error",
+ "useSingleVarDeclarator": "error",
+ "noUnusedTemplateLiteral": "error",
+ "useNumberNamespace": "error",
+ "noInferrableTypes": "error",
+ "noUselessElse": "error",
+ "useConsistentArrayType": {
+ "level": "error",
+ "options": {
+ "syntax": "shorthand"
+ }
+ }
},
"suspicious": {
"noArrayIndexKey": "off",
"noConfusingVoidType": "off",
- "noConsoleLog": "error",
- "noExplicitAny": "off"
+ "noExplicitAny": "off",
+ "noConsole": {
+ "level": "error",
+ "options": {
+ "allow": ["log"]
+ }
+ },
+ "noTsIgnore": "off"
}
}
},
@@ -46,32 +77,52 @@
"semicolons": "asNeeded"
}
},
- "organizeImports": {
- "enabled": true
+ "assist": {
+ "actions": {
+ "source": {
+ "organizeImports": "on"
+ }
+ }
},
"overrides": [
{
- "include": ["*.vue"],
+ "includes": ["**/*.vue"],
"linter": {
"rules": {
"correctness": {
+ "noUnusedImports": "off",
"noUnusedVariables": "off"
}
}
}
},
{
- "include": ["./scripts/**/*.ts"],
+ "includes": ["site/snippets/**"],
+ "linter": {
+ "rules": {
+ "correctness": {
+ "noUnusedImports": "off"
+ }
+ }
+ }
+ },
+ {
+ "includes": ["scripts/**/*.ts"],
"linter": {
"rules": {
"suspicious": {
- "noConsoleLog": "off"
+ "noConsole": {
+ "level": "off",
+ "options": {
+ "allow": ["log"]
+ }
+ }
}
}
}
},
{
- "include": ["./playgrounds/**"],
+ "includes": ["playgrounds/**"],
"linter": {
"rules": {
"style": {
diff --git a/package.json b/package.json
index d7b3821bf0..7adf2c4848 100644
--- a/package.json
+++ b/package.json
@@ -1,9 +1,11 @@
{
+ "name": "workspace",
"private": true,
"type": "module",
"scripts": {
- "build": "pnpm run --r --filter \"./packages/**\" build",
- "changeset:prepublish": "pnpm version:update && pnpm build && bun scripts/formatPackageJson.ts && bun scripts/generateProxyPackages.ts",
+ "build": "pnpm run --filter @wagmi/core --filter @wagmi/cli build && pnpm run --filter @wagmi/connectors build && pnpm run --filter wagmi --filter @wagmi/vue build",
+ "bench:types": "TYPES=true vitest bench-d.ts",
+ "changeset:prepublish": "pnpm clean && pnpm version:update && pnpm build && node scripts/formatPackageJson.ts && node scripts/generateProxyPackages.ts",
"changeset:publish": "pnpm changeset:prepublish && changeset publish",
"changeset:version": "changeset version && pnpm version:update && pnpm format",
"check": "biome check --write",
@@ -12,6 +14,7 @@
"check:unused": "pnpm clean && knip",
"clean": "pnpm run --r --parallel clean && rm -rf packages/**/*.json.tmp",
"deps": "pnpx taze -r",
+ "deps:ci": "pnpx actions-up",
"dev": "pnpm dev:react",
"dev:cli": "pnpm --filter cli dev",
"dev:core": "pnpm --filter vite-core dev",
@@ -19,117 +22,143 @@
"dev:next": "pnpm --filter next-app dev",
"dev:nuxt": "pnpm --filter nuxt-app dev",
"dev:react": "pnpm --filter vite-react dev",
+ "dev:start": "pnpm --filter tanstack-start dev",
"dev:vue": "pnpm --filter vite-vue dev",
"docs:dev": "pnpm --filter site dev",
"format": "biome format --write",
"postinstall": "pnpm preconstruct",
- "preconstruct": "bun scripts/preconstruct.ts",
+ "preconstruct": "node scripts/preconstruct.ts",
"preinstall": "pnpx only-allow pnpm",
"prepare": "pnpm simple-git-hooks",
"test": "vitest",
- "test:build": "bun scripts/generateProxyPackages.ts && pnpm run --r --parallel test:build",
- "test:cli": "vitest --project @wagmi/cli",
- "test:connectors": "vitest --project @wagmi/connectors",
- "test:core": "vitest --project @wagmi/core",
- "test:create-wagmi": "vitest --project create-wagmi",
+ "test:build": "node scripts/generateProxyPackages.ts && pnpm run --r --parallel test:build",
"test:cov": "vitest run --coverage",
- "test:react": "vitest --project wagmi",
"test:typecheck": "vitest typecheck",
"test:update": "vitest --update",
- "test:vue": "vitest --project @wagmi/vue",
- "version:update": "bun scripts/updateVersion.ts",
- "version:update:viem": "bun scripts/updateViemVersion.ts"
+ "version:update": "node scripts/updateVersion.ts",
+ "version:update:viem": "node scripts/updateViemVersion.ts"
},
"devDependencies": {
"@arethetypeswrong/cli": "^0.16.4",
- "@biomejs/biome": "^1.9.4",
- "@changesets/changelog-github": "0.4.6",
- "@changesets/cli": "^2.27.8",
- "@types/bun": "^1.1.10",
- "@vitest/coverage-v8": "^2.1.1",
+ "@ark/attest": "^0.56.0",
+ "@biomejs/biome": "^2.2.4",
+ "@changesets/cli": "^3.0.0-next.0",
+ "@svitejs/changesets-changelog-github-compact": "^1.2.0",
+ "@types/node": "^24.5.1",
+ "@vitejs/plugin-react": "catalog:",
+ "@vitest/browser": "^4.0.16",
+ "@vitest/browser-playwright": "^4.0.16",
+ "@vitest/coverage-v8": "^4.0.16",
"@wagmi/test": "workspace:*",
- "bun": "^1.1.29",
- "happy-dom": "^15.7.4",
- "knip": "^5.30.6",
- "prool": "^0.0.23",
+ "happy-dom": "^20.0.0",
+ "knip": "^5.69.0",
+ "playwright": "1.56.1",
+ "prool": "^0.2.2",
"publint": "^0.2.11",
+ "react": "catalog:",
+ "react-dom": "catalog:",
"sherif": "^1.0.0",
"simple-git-hooks": "^2.11.1",
- "typescript": "5.5.4",
- "viem": "2.23.12",
- "vitest": "^2.1.1"
+ "testcontainers": "^11.11.0",
+ "typescript": "^5.9.3",
+ "viem": "2.44.0",
+ "vite-plugin-react-fallback-throttle": "^0.1.1",
+ "vitest": "^4.0.16",
+ "vitest-browser-react": "^2.0.2"
},
- "packageManager": "pnpm@9.11.0",
- "pnpm": {
- "peerDependencyRules": {
- "ignoreMissing": [
- "@algolia/client-search",
- "react",
- "react-native",
- "search-insights"
- ]
+ "packageManager": "pnpm@10.22.0",
+ "devEngines": {
+ "runtime": {
+ "name": "node",
+ "version": "^24.5.1",
+ "onFail": "download"
}
},
- "engines": {
- "node": "22.x"
- },
"simple-git-hooks": {
"pre-commit": "pnpm check"
},
"knip": {
- "ignore": ["**/templates/**", "**/hardhat.config.js"],
- "ignoreBinaries": ["only-allow"],
+ "ignore": [
+ "**/templates/**",
+ "**/hardhat.config.js",
+ "packages/**/*.bench-d.ts",
+ "scripts/**"
+ ],
"ignoreWorkspaces": [
"packages/register-tests/**",
"packages/test",
- "playgrounds/**"
+ "playgrounds/**",
+ "site/**"
],
"workspaces": {
- ".": {
- "project": "scripts/*.ts"
- },
"packages/cli": {
"entry": [
"src/cli.ts!",
"src/exports/{config,index,plugins}.ts!",
"types/*.d.ts!"
],
- "ignore": ["test/{constants,setup,utils}.ts"]
+ "ignore": [
+ "test/{constants,setup,utils}.ts"
+ ]
},
"packages/connectors": {
- "entry": "src/exports/index.ts!"
+ "entry": "src/exports/index.ts!",
+ "ignoreDependencies": [
+ "@base-org/account",
+ "@coinbase/wallet-sdk",
+ "@gemini-wallet/core",
+ "@metamask/sdk",
+ "@safe-global/safe-apps-provider",
+ "@safe-global/safe-apps-sdk",
+ "@wagmi/core",
+ "@walletconnect/ethereum-provider",
+ "porto"
+ ]
},
"packages/core": {
- "entry": "src/exports/{actions,chains,codegen,experimental,index,internal,query}.ts!",
- "ignore": ["test/setup.ts"],
- "ignoreDependencies": ["@tanstack/query-core"]
+ "entry": "src/exports/{actions,chains,codegen,experimental,index,internal,query,tempo}.ts!",
+ "ignore": [
+ "test/setup.ts"
+ ],
+ "ignoreDependencies": [
+ "@tanstack/query-core",
+ "ox"
+ ]
},
"packages/create-wagmi": {
"entry": "src/cli.ts!"
},
"packages/react": {
"entry": [
- "src/exports/{actions,chains,codegen,connectors,experimental,index,query}.ts!",
+ "src/exports/{actions,chains,codegen,connectors,experimental,index,internal,query,tempo}.ts!",
"src/exports/actions/experimental.ts!"
],
- "ignore": ["test/setup.ts"]
+ "ignore": [
+ "test/setup.ts"
+ ]
},
"packages/test": {
"entry": [
- "src/{globalSetup,setup}.ts!",
- "src/exports/{index,react}.ts!"
+ "src/setup.ts!",
+ "src/setup.global.ts!",
+ "src/setup.global.types.ts!",
+ "src/exports/{index,react,tempo}.ts!",
+ "src/tempo/setup.ts!",
+ "src/tempo/setup.global.ts!"
]
},
"packages/vue": {
"entry": [
- "src/exports/{actions,chains,connectors,index,nuxt,query}.ts!",
+ "src/exports/{actions,chains,connectors,index,internal,nuxt,query}.ts!",
"src/exports/actions/experimental.ts!"
],
- "ignore": ["src/nuxt/runtime/*", "test/setup.ts"],
- "ignoreDependencies": ["nuxt"]
- },
- "site": {
- "project": ["**/*.ts", "**/*.tsx"]
+ "ignore": [
+ "src/nuxt/runtime/*",
+ "test/setup.ts"
+ ],
+ "ignoreDependencies": [
+ "nuxt"
+ ]
}
}
}
diff --git a/packages/cli/CHANGELOG.md b/packages/cli/CHANGELOG.md
index 07c2aa5825..dc0bb61ddd 100644
--- a/packages/cli/CHANGELOG.md
+++ b/packages/cli/CHANGELOG.md
@@ -1,5 +1,65 @@
# @wagmi/cli
+## 2.8.0
+
+### Minor Changes
+
+- Added option to React plugin to disable generating hooks for each function/event in ABI. ([#4866](https://github.com/wevm/wagmi/pull/4866))
+
+## 2.7.1
+
+### Patch Changes
+
+- Bumped chains for block explorer plugins. ([`ed2d473`](https://github.com/wevm/wagmi/commit/ed2d473172e8d063f29400b8edcec33e5d21a659))
+
+## 2.7.0
+
+### Minor Changes
+
+- Updated block explorer plugins supported chains. ([#4830](https://github.com/wevm/wagmi/pull/4830))
+
+## 2.6.0
+
+### Minor Changes
+
+- Bumped internal deps. ([#4808](https://github.com/wevm/wagmi/pull/4808))
+
+## 2.5.1
+
+### Patch Changes
+
+- [#4773](https://github.com/wevm/wagmi/pull/4773) [`d4c367ca46c508598c997cf229a31593a1e2b8b8`](https://github.com/wevm/wagmi/commit/d4c367ca46c508598c997cf229a31593a1e2b8b8) Thanks [@tmm](https://github.com/tmm)! - Fixed issue with codegen actions/hooks, where `syncConnectedChain: false` did not work as intended.
+
+## 2.5.0
+
+### Minor Changes
+
+- [`1edb09f7b69da3d7819d0e070e875e2c6fe8015d`](https://github.com/wevm/wagmi/commit/1edb09f7b69da3d7819d0e070e875e2c6fe8015d) Thanks [@tmm](https://github.com/tmm)! - Added testnets to `routescan` plugin
+
+## 2.4.0
+
+### Minor Changes
+
+- [#4757](https://github.com/wevm/wagmi/pull/4757) [`aec8a61ef0dfe02421d514bd130505ec13f8d3a0`](https://github.com/wevm/wagmi/commit/aec8a61ef0dfe02421d514bd130505ec13f8d3a0) Thanks [@tmm](https://github.com/tmm)! - Added Routescan plugin.
+
+## 2.3.2
+
+### Patch Changes
+
+- [#4727](https://github.com/wevm/wagmi/pull/4727) [`910e6c6180bd632e65bad348bd0814de5a8cfa4b`](https://github.com/wevm/wagmi/commit/910e6c6180bd632e65bad348bd0814de5a8cfa4b) Thanks [@reallesee](https://github.com/reallesee)! - `fetch` plugin: cleared timeout on fetch error
+
+## 2.3.1
+
+### Patch Changes
+
+- [#4655](https://github.com/wevm/wagmi/pull/4655) [`43241c8417f3c342036bb46ec8e507d052ae2691`](https://github.com/wevm/wagmi/commit/43241c8417f3c342036bb46ec8e507d052ae2691) Thanks [@tmm](https://github.com/tmm)! - Bumped internal deps.
+
+## 2.3.0
+
+### Minor Changes
+
+- [#4629](https://github.com/wevm/wagmi/pull/4629) [`66dec7d75d580b3121ebc7e8162c1f9ae37cfd41`](https://github.com/wevm/wagmi/commit/66dec7d75d580b3121ebc7e8162c1f9ae37cfd41) Thanks [@allezxandre](https://github.com/allezxandre)! - Upgraded to Sourcify v2 API in `sourcify` plugin
+
## 2.2.1
### Patch Changes
diff --git a/packages/cli/package.json b/packages/cli/package.json
index 88fb1e82cc..35e8a2b378 100644
--- a/packages/cli/package.json
+++ b/packages/cli/package.json
@@ -1,7 +1,7 @@
{
"name": "@wagmi/cli",
"description": "Manage and generate code from Ethereum ABIs",
- "version": "2.2.1",
+ "version": "2.8.0",
"license": "MIT",
"repository": {
"type": "git",
@@ -9,7 +9,7 @@
"directory": "packages/cli"
},
"scripts": {
- "build": "pnpm run clean && pnpm run build:esm+types",
+ "build": "pnpm run build:esm+types",
"build:esm+types": "tsc --project tsconfig.build.json --outDir ./dist/esm --declaration --declarationMap --declarationDir ./dist/types",
"check:types": "tsc --noEmit",
"clean": "rm -rf dist tsconfig.tsbuildinfo config plugins",
@@ -50,12 +50,16 @@
},
"typesVersions": {
"*": {
- "config": ["./dist/types/exports/config.d.ts"],
- "plugins": ["./dist/types/exports/plugins.d.ts"]
+ "config": [
+ "./dist/types/exports/config.d.ts"
+ ],
+ "plugins": [
+ "./dist/types/exports/plugins.d.ts"
+ ]
}
},
"peerDependencies": {
- "typescript": ">=5.0.4"
+ "typescript": ">=5.7.3"
},
"peerDependenciesMeta": {
"typescript": {
@@ -63,15 +67,15 @@
}
},
"dependencies": {
- "abitype": "^1.0.4",
- "bundle-require": "^4.0.2",
+ "abitype": "^1.1.1",
+ "bundle-require": "^5.1.0",
"cac": "^6.7.14",
"change-case": "^5.4.4",
"chokidar": "4.0.1",
"dedent": "^0.7.0",
"dotenv": "^16.3.1",
"dotenv-expand": "^10.0.0",
- "esbuild": "^0.19.0",
+ "esbuild": "~0.25.4",
"escalade": "3.2.0",
"fdir": "^6.1.1",
"nanospinner": "1.2.2",
@@ -80,15 +84,26 @@
"picomatch": "^3.0.0",
"prettier": "^3.0.3",
"viem": "2.x",
- "zod": "^3.22.2"
+ "zod": "^4.1.11"
},
"devDependencies": {
"@types/dedent": "^0.7.2",
- "@types/node": "^20.12.10",
+ "@types/node": "^24.5.1",
"fixturez": "^1.1.0",
"msw": "^2.4.9"
},
- "contributors": ["awkweb.eth ", "jxom.eth "],
+ "contributors": [
+ "awkweb.eth ",
+ "jxom.eth "
+ ],
"funding": "https://github.com/sponsors/wevm",
- "keywords": ["wagmi", "eth", "ethereum", "dapps", "wallet", "web3", "cli"]
+ "keywords": [
+ "wagmi",
+ "eth",
+ "ethereum",
+ "dapps",
+ "wallet",
+ "web3",
+ "cli"
+ ]
}
diff --git a/packages/cli/src/commands/generate.test.ts b/packages/cli/src/commands/generate.test.ts
index 91e4265216..ccebce18d9 100644
--- a/packages/cli/src/commands/generate.test.ts
+++ b/packages/cli/src/commands/generate.test.ts
@@ -169,7 +169,7 @@ test('behavior: invalid cli options', async () => {
}),
).rejects.toThrowErrorMatchingInlineSnapshot(`
[Error: Invalid option
- - Expected string, received number at \`config\`]
+ - Invalid input: expected string, received number at \`config\`]
`)
})
@@ -334,7 +334,7 @@ test('behavior: throws when address is invalid', async () => {
await expect(generate()).rejects.toThrowErrorMatchingInlineSnapshot(`
[Error: Invalid address for contract "Foo"
- - Invalid address]
+ - Invalid input]
`)
})
diff --git a/packages/cli/src/commands/generate.ts b/packages/cli/src/commands/generate.ts
index 5e1f5a2a1a..992a2e2923 100644
--- a/packages/cli/src/commands/generate.ts
+++ b/packages/cli/src/commands/generate.ts
@@ -1,5 +1,4 @@
import { mkdir, writeFile } from 'node:fs/promises'
-import type { Abi } from 'abitype'
import { Abi as AbiSchema } from 'abitype/zod'
import { camelCase } from 'change-case'
import type { ChokidarOptions, FSWatcher } from 'chokidar'
@@ -7,7 +6,7 @@ import { watch } from 'chokidar'
import { default as dedent } from 'dedent'
import { basename, dirname, resolve } from 'pathe'
import pc from 'picocolors'
-import { type Address, getAddress } from 'viem'
+import { type Abi, type Address, getAddress } from 'viem'
import { z } from 'zod'
import type { Contract, ContractConfig, Plugin, Watch } from '../config.js'
diff --git a/packages/cli/src/config.ts b/packages/cli/src/config.ts
index 94c54d7c41..146a1e3424 100644
--- a/packages/cli/src/config.ts
+++ b/packages/cli/src/config.ts
@@ -1,5 +1,4 @@
-import type { Abi } from 'abitype'
-import type { Address } from 'viem'
+import type { Abi, Address } from 'viem'
import type { Compute, MaybeArray, MaybePromise } from './types.js'
diff --git a/packages/cli/src/errors.ts b/packages/cli/src/errors.ts
index 6ef37093fc..7f87212220 100644
--- a/packages/cli/src/errors.ts
+++ b/packages/cli/src/errors.ts
@@ -1,12 +1,12 @@
-import type { z } from 'zod'
+import type * as z from 'zod'
class ValidationError extends Error {
- details: Zod.ZodIssue[]
+ details: z.core.$ZodIssue[]
constructor(
message: string,
options: {
- details: Zod.ZodIssue[]
+ details: z.core.$ZodIssue[]
},
) {
super(message)
@@ -29,15 +29,15 @@ export function fromZodError(
prefix?: string
} = {},
): ValidationError {
- function joinPath(arr: Array): string {
+ function joinPath(arr: Array): string {
return arr.reduce((acc, value) => {
if (typeof value === 'number') return `${acc}[${value}]`
const separator = acc === '' ? '' : '.'
- return acc + separator + value
+ return acc + separator + value.toString()
}, '')
}
- const reason = zError.errors
+ const reason = zError.issues
// limit max number of issues printed in the reason section
.slice(0, maxIssuesInMessage)
// format error message
@@ -52,6 +52,6 @@ export function fromZodError(
const message = reason ? [prefix, reason].join(prefixSeparator) : prefix
return new ValidationError(message, {
- details: zError.errors,
+ details: zError.issues,
})
}
diff --git a/packages/cli/src/exports/config.test.ts b/packages/cli/src/exports/config.test.ts
index c833780ffc..f8154635b2 100644
--- a/packages/cli/src/exports/config.test.ts
+++ b/packages/cli/src/exports/config.test.ts
@@ -5,8 +5,8 @@ import * as Exports from './config.js'
test('exports', () => {
expect(Object.keys(Exports)).toMatchInlineSnapshot(`
[
- "defineConfig",
"defaultConfig",
+ "defineConfig",
]
`)
})
diff --git a/packages/cli/src/exports/config.ts b/packages/cli/src/exports/config.ts
index b3c4a83ba4..6dea251a10 100644
--- a/packages/cli/src/exports/config.ts
+++ b/packages/cli/src/exports/config.ts
@@ -1,10 +1,10 @@
// biome-ignore lint/performance/noBarrelFile: entrypoint module
export {
- type ContractConfig,
- type Contract,
- type Watch,
- type Plugin,
type Config,
- defineConfig,
+ type Contract,
+ type ContractConfig,
defaultConfig,
+ defineConfig,
+ type Plugin,
+ type Watch,
} from '../config.js'
diff --git a/packages/cli/src/exports/index.ts b/packages/cli/src/exports/index.ts
index 1c5e624df6..4ab9b10ab3 100644
--- a/packages/cli/src/exports/index.ts
+++ b/packages/cli/src/exports/index.ts
@@ -1,8 +1,8 @@
// biome-ignore lint/performance/noBarrelFile: entrypoint module
export {
- defineConfig,
type Config,
type ContractConfig,
+ defineConfig,
type Plugin,
} from '../config.js'
diff --git a/packages/cli/src/exports/plugins.test.ts b/packages/cli/src/exports/plugins.test.ts
index 4d7b5a97cd..e8d8e5a5fe 100644
--- a/packages/cli/src/exports/plugins.test.ts
+++ b/packages/cli/src/exports/plugins.test.ts
@@ -14,6 +14,7 @@ test('exports', () => {
"hardhat",
"hardhatDefaultExcludes",
"react",
+ "routescan",
"sourcify",
]
`)
diff --git a/packages/cli/src/exports/plugins.ts b/packages/cli/src/exports/plugins.ts
index a289b5c576..baeef622cb 100644
--- a/packages/cli/src/exports/plugins.ts
+++ b/packages/cli/src/exports/plugins.ts
@@ -1,27 +1,29 @@
// biome-ignore lint/performance/noBarrelFile: entrypoint module
-export { actions, type ActionsConfig } from '../plugins/actions.js'
+export { type ActionsConfig, actions } from '../plugins/actions.js'
export {
- blockExplorer,
type BlockExplorerConfig,
+ blockExplorer,
} from '../plugins/blockExplorer.js'
-export { etherscan, type EtherscanConfig } from '../plugins/etherscan.js'
+export { type EtherscanConfig, etherscan } from '../plugins/etherscan.js'
-export { fetch, type FetchConfig } from '../plugins/fetch.js'
+export { type FetchConfig, fetch } from '../plugins/fetch.js'
export {
+ type FoundryConfig,
foundry,
foundryDefaultExcludes,
- type FoundryConfig,
} from '../plugins/foundry.js'
export {
+ type HardhatConfig,
hardhat,
hardhatDefaultExcludes,
- type HardhatConfig,
} from '../plugins/hardhat.js'
-export { react, type ReactConfig } from '../plugins/react.js'
+export { type ReactConfig, react } from '../plugins/react.js'
+
+export { type RoutescanConfig, routescan } from '../plugins/routescan.js'
-export { sourcify, type SourcifyConfig } from '../plugins/sourcify.js'
+export { type SourcifyConfig, sourcify } from '../plugins/sourcify.js'
diff --git a/packages/cli/src/logger.ts b/packages/cli/src/logger.ts
index b56fb9728b..758eb16ed5 100644
--- a/packages/cli/src/logger.ts
+++ b/packages/cli/src/logger.ts
@@ -9,24 +9,25 @@ function format(args: any[]) {
}
export function success(...args: any[]) {
- // biome-ignore lint/suspicious/noConsoleLog: console.log is used for logging
console.log(pc.green(format(args)))
}
export function info(...args: any[]) {
+ // biome-ignore lint/suspicious/noConsole: logger
console.info(pc.blue(format(args)))
}
export function log(...args: any[]) {
- // biome-ignore lint/suspicious/noConsoleLog: console.log is used for logging
console.log(pc.white(format(args)))
}
export function warn(...args: any[]) {
+ // biome-ignore lint/suspicious/noConsole: logger
console.warn(pc.yellow(format(args)))
}
export function error(...args: any[]) {
+ // biome-ignore lint/suspicious/noConsole: logger
console.error(pc.red(format(args)))
}
diff --git a/packages/cli/src/plugins/__fixtures__/hardhat/hardhat.config.js b/packages/cli/src/plugins/__fixtures__/hardhat/hardhat.config.js
index c8126eedfa..2ff4f7cbae 100644
--- a/packages/cli/src/plugins/__fixtures__/hardhat/hardhat.config.js
+++ b/packages/cli/src/plugins/__fixtures__/hardhat/hardhat.config.js
@@ -1,3 +1,5 @@
-module.exports = {
+import { defineConfig } from 'hardhat/config'
+
+export default defineConfig({
solidity: '0.8.17',
-}
+})
diff --git a/packages/cli/src/plugins/__fixtures__/hardhat/package.json b/packages/cli/src/plugins/__fixtures__/hardhat/package.json
index 85c9ffb7bd..e3385bb9cc 100644
--- a/packages/cli/src/plugins/__fixtures__/hardhat/package.json
+++ b/packages/cli/src/plugins/__fixtures__/hardhat/package.json
@@ -1,7 +1,8 @@
{
"name": "hardhat-fixture",
"private": true,
+ "type": "module",
"devDependencies": {
- "hardhat": "^2.22.3"
+ "hardhat": "^3.0.0"
}
}
diff --git a/packages/cli/src/plugins/__snapshots__/routescan.test.ts.snap b/packages/cli/src/plugins/__snapshots__/routescan.test.ts.snap
new file mode 100644
index 0000000000..e03ee30f81
--- /dev/null
+++ b/packages/cli/src/plugins/__snapshots__/routescan.test.ts.snap
@@ -0,0 +1,1238 @@
+// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
+
+exports[`fetches ABI 1`] = `
+[
+ {
+ "abi": [
+ {
+ "inputs": [],
+ "stateMutability": "nonpayable",
+ "type": "constructor",
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "owner",
+ "type": "address",
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "approved",
+ "type": "address",
+ },
+ {
+ "indexed": true,
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256",
+ },
+ ],
+ "name": "Approval",
+ "type": "event",
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "owner",
+ "type": "address",
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "operator",
+ "type": "address",
+ },
+ {
+ "indexed": false,
+ "internalType": "bool",
+ "name": "approved",
+ "type": "bool",
+ },
+ ],
+ "name": "ApprovalForAll",
+ "type": "event",
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "from",
+ "type": "address",
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "to",
+ "type": "address",
+ },
+ {
+ "indexed": true,
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256",
+ },
+ ],
+ "name": "Transfer",
+ "type": "event",
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "to",
+ "type": "address",
+ },
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256",
+ },
+ ],
+ "name": "approve",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function",
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "owner",
+ "type": "address",
+ },
+ ],
+ "name": "balanceOf",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256",
+ },
+ ],
+ "stateMutability": "view",
+ "type": "function",
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256",
+ },
+ ],
+ "name": "getApproved",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address",
+ },
+ ],
+ "stateMutability": "view",
+ "type": "function",
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "owner",
+ "type": "address",
+ },
+ {
+ "internalType": "address",
+ "name": "operator",
+ "type": "address",
+ },
+ ],
+ "name": "isApprovedForAll",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool",
+ },
+ ],
+ "stateMutability": "view",
+ "type": "function",
+ },
+ {
+ "inputs": [],
+ "name": "mint",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function",
+ },
+ {
+ "inputs": [],
+ "name": "name",
+ "outputs": [
+ {
+ "internalType": "string",
+ "name": "",
+ "type": "string",
+ },
+ ],
+ "stateMutability": "view",
+ "type": "function",
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256",
+ },
+ ],
+ "name": "ownerOf",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address",
+ },
+ ],
+ "stateMutability": "view",
+ "type": "function",
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "from",
+ "type": "address",
+ },
+ {
+ "internalType": "address",
+ "name": "to",
+ "type": "address",
+ },
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256",
+ },
+ ],
+ "name": "safeTransferFrom",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function",
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "from",
+ "type": "address",
+ },
+ {
+ "internalType": "address",
+ "name": "to",
+ "type": "address",
+ },
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256",
+ },
+ {
+ "internalType": "bytes",
+ "name": "_data",
+ "type": "bytes",
+ },
+ ],
+ "name": "safeTransferFrom",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function",
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "operator",
+ "type": "address",
+ },
+ {
+ "internalType": "bool",
+ "name": "approved",
+ "type": "bool",
+ },
+ ],
+ "name": "setApprovalForAll",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function",
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes4",
+ "name": "interfaceId",
+ "type": "bytes4",
+ },
+ ],
+ "name": "supportsInterface",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool",
+ },
+ ],
+ "stateMutability": "view",
+ "type": "function",
+ },
+ {
+ "inputs": [],
+ "name": "symbol",
+ "outputs": [
+ {
+ "internalType": "string",
+ "name": "",
+ "type": "string",
+ },
+ ],
+ "stateMutability": "view",
+ "type": "function",
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256",
+ },
+ ],
+ "name": "tokenURI",
+ "outputs": [
+ {
+ "internalType": "string",
+ "name": "",
+ "type": "string",
+ },
+ ],
+ "stateMutability": "pure",
+ "type": "function",
+ },
+ {
+ "inputs": [],
+ "name": "totalSupply",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256",
+ },
+ ],
+ "stateMutability": "view",
+ "type": "function",
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "from",
+ "type": "address",
+ },
+ {
+ "internalType": "address",
+ "name": "to",
+ "type": "address",
+ },
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256",
+ },
+ ],
+ "name": "transferFrom",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function",
+ },
+ ],
+ "address": {
+ "1": "0xaf0326d92b97df1221759476b072abfd8084f9be",
+ },
+ "name": "WagmiMintExample",
+ },
+]
+`;
+
+exports[`fetches ABI with multichain deployment 1`] = `
+[
+ {
+ "abi": [
+ {
+ "inputs": [],
+ "stateMutability": "nonpayable",
+ "type": "constructor",
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "owner",
+ "type": "address",
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "approved",
+ "type": "address",
+ },
+ {
+ "indexed": true,
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256",
+ },
+ ],
+ "name": "Approval",
+ "type": "event",
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "owner",
+ "type": "address",
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "operator",
+ "type": "address",
+ },
+ {
+ "indexed": false,
+ "internalType": "bool",
+ "name": "approved",
+ "type": "bool",
+ },
+ ],
+ "name": "ApprovalForAll",
+ "type": "event",
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "from",
+ "type": "address",
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "to",
+ "type": "address",
+ },
+ {
+ "indexed": true,
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256",
+ },
+ ],
+ "name": "Transfer",
+ "type": "event",
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "to",
+ "type": "address",
+ },
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256",
+ },
+ ],
+ "name": "approve",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function",
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "owner",
+ "type": "address",
+ },
+ ],
+ "name": "balanceOf",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256",
+ },
+ ],
+ "stateMutability": "view",
+ "type": "function",
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256",
+ },
+ ],
+ "name": "getApproved",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address",
+ },
+ ],
+ "stateMutability": "view",
+ "type": "function",
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "owner",
+ "type": "address",
+ },
+ {
+ "internalType": "address",
+ "name": "operator",
+ "type": "address",
+ },
+ ],
+ "name": "isApprovedForAll",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool",
+ },
+ ],
+ "stateMutability": "view",
+ "type": "function",
+ },
+ {
+ "inputs": [],
+ "name": "mint",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function",
+ },
+ {
+ "inputs": [],
+ "name": "name",
+ "outputs": [
+ {
+ "internalType": "string",
+ "name": "",
+ "type": "string",
+ },
+ ],
+ "stateMutability": "view",
+ "type": "function",
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256",
+ },
+ ],
+ "name": "ownerOf",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address",
+ },
+ ],
+ "stateMutability": "view",
+ "type": "function",
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "from",
+ "type": "address",
+ },
+ {
+ "internalType": "address",
+ "name": "to",
+ "type": "address",
+ },
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256",
+ },
+ ],
+ "name": "safeTransferFrom",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function",
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "from",
+ "type": "address",
+ },
+ {
+ "internalType": "address",
+ "name": "to",
+ "type": "address",
+ },
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256",
+ },
+ {
+ "internalType": "bytes",
+ "name": "_data",
+ "type": "bytes",
+ },
+ ],
+ "name": "safeTransferFrom",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function",
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "operator",
+ "type": "address",
+ },
+ {
+ "internalType": "bool",
+ "name": "approved",
+ "type": "bool",
+ },
+ ],
+ "name": "setApprovalForAll",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function",
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes4",
+ "name": "interfaceId",
+ "type": "bytes4",
+ },
+ ],
+ "name": "supportsInterface",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool",
+ },
+ ],
+ "stateMutability": "view",
+ "type": "function",
+ },
+ {
+ "inputs": [],
+ "name": "symbol",
+ "outputs": [
+ {
+ "internalType": "string",
+ "name": "",
+ "type": "string",
+ },
+ ],
+ "stateMutability": "view",
+ "type": "function",
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256",
+ },
+ ],
+ "name": "tokenURI",
+ "outputs": [
+ {
+ "internalType": "string",
+ "name": "",
+ "type": "string",
+ },
+ ],
+ "stateMutability": "pure",
+ "type": "function",
+ },
+ {
+ "inputs": [],
+ "name": "totalSupply",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256",
+ },
+ ],
+ "stateMutability": "view",
+ "type": "function",
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "from",
+ "type": "address",
+ },
+ {
+ "internalType": "address",
+ "name": "to",
+ "type": "address",
+ },
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256",
+ },
+ ],
+ "name": "transferFrom",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function",
+ },
+ ],
+ "address": {
+ "1": "0xaf0326d92b97df1221759476b072abfd8084f9be",
+ "10": "0xaf0326d92b97df1221759476b072abfd8084f9be",
+ },
+ "name": "WagmiMintExample",
+ },
+]
+`;
+
+exports[`tryFetchProxyImplementation: fetches ABI 1`] = `
+[
+ {
+ "abi": [
+ {
+ "inputs": [],
+ "stateMutability": "nonpayable",
+ "type": "constructor",
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "owner",
+ "type": "address",
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "approved",
+ "type": "address",
+ },
+ {
+ "indexed": true,
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256",
+ },
+ ],
+ "name": "Approval",
+ "type": "event",
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "owner",
+ "type": "address",
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "operator",
+ "type": "address",
+ },
+ {
+ "indexed": false,
+ "internalType": "bool",
+ "name": "approved",
+ "type": "bool",
+ },
+ ],
+ "name": "ApprovalForAll",
+ "type": "event",
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "from",
+ "type": "address",
+ },
+ {
+ "indexed": true,
+ "internalType": "address",
+ "name": "to",
+ "type": "address",
+ },
+ {
+ "indexed": true,
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256",
+ },
+ ],
+ "name": "Transfer",
+ "type": "event",
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "to",
+ "type": "address",
+ },
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256",
+ },
+ ],
+ "name": "approve",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function",
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "owner",
+ "type": "address",
+ },
+ ],
+ "name": "balanceOf",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256",
+ },
+ ],
+ "stateMutability": "view",
+ "type": "function",
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256",
+ },
+ ],
+ "name": "getApproved",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address",
+ },
+ ],
+ "stateMutability": "view",
+ "type": "function",
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "owner",
+ "type": "address",
+ },
+ {
+ "internalType": "address",
+ "name": "operator",
+ "type": "address",
+ },
+ ],
+ "name": "isApprovedForAll",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool",
+ },
+ ],
+ "stateMutability": "view",
+ "type": "function",
+ },
+ {
+ "inputs": [],
+ "name": "mint",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function",
+ },
+ {
+ "inputs": [],
+ "name": "name",
+ "outputs": [
+ {
+ "internalType": "string",
+ "name": "",
+ "type": "string",
+ },
+ ],
+ "stateMutability": "view",
+ "type": "function",
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256",
+ },
+ ],
+ "name": "ownerOf",
+ "outputs": [
+ {
+ "internalType": "address",
+ "name": "",
+ "type": "address",
+ },
+ ],
+ "stateMutability": "view",
+ "type": "function",
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "from",
+ "type": "address",
+ },
+ {
+ "internalType": "address",
+ "name": "to",
+ "type": "address",
+ },
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256",
+ },
+ ],
+ "name": "safeTransferFrom",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function",
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "from",
+ "type": "address",
+ },
+ {
+ "internalType": "address",
+ "name": "to",
+ "type": "address",
+ },
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256",
+ },
+ {
+ "internalType": "bytes",
+ "name": "_data",
+ "type": "bytes",
+ },
+ ],
+ "name": "safeTransferFrom",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function",
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "operator",
+ "type": "address",
+ },
+ {
+ "internalType": "bool",
+ "name": "approved",
+ "type": "bool",
+ },
+ ],
+ "name": "setApprovalForAll",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function",
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "bytes4",
+ "name": "interfaceId",
+ "type": "bytes4",
+ },
+ ],
+ "name": "supportsInterface",
+ "outputs": [
+ {
+ "internalType": "bool",
+ "name": "",
+ "type": "bool",
+ },
+ ],
+ "stateMutability": "view",
+ "type": "function",
+ },
+ {
+ "inputs": [],
+ "name": "symbol",
+ "outputs": [
+ {
+ "internalType": "string",
+ "name": "",
+ "type": "string",
+ },
+ ],
+ "stateMutability": "view",
+ "type": "function",
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256",
+ },
+ ],
+ "name": "tokenURI",
+ "outputs": [
+ {
+ "internalType": "string",
+ "name": "",
+ "type": "string",
+ },
+ ],
+ "stateMutability": "pure",
+ "type": "function",
+ },
+ {
+ "inputs": [],
+ "name": "totalSupply",
+ "outputs": [
+ {
+ "internalType": "uint256",
+ "name": "",
+ "type": "uint256",
+ },
+ ],
+ "stateMutability": "view",
+ "type": "function",
+ },
+ {
+ "inputs": [
+ {
+ "internalType": "address",
+ "name": "from",
+ "type": "address",
+ },
+ {
+ "internalType": "address",
+ "name": "to",
+ "type": "address",
+ },
+ {
+ "internalType": "uint256",
+ "name": "tokenId",
+ "type": "uint256",
+ },
+ ],
+ "name": "transferFrom",
+ "outputs": [],
+ "stateMutability": "nonpayable",
+ "type": "function",
+ },
+ ],
+ "address": {
+ "1": "0xaf0326d92b97df1221759476b072abfd8084f9be",
+ },
+ "name": "WagmiMintExample",
+ },
+]
+`;
+
+exports[`tryFetchProxyImplementation: fetches implementation ABI 1`] = `
+[
+ {
+ "abi": [
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "newImplementation",
+ "type": "address",
+ },
+ ],
+ "name": "upgradeTo",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function",
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "newImplementation",
+ "type": "address",
+ },
+ {
+ "name": "data",
+ "type": "bytes",
+ },
+ ],
+ "name": "upgradeToAndCall",
+ "outputs": [],
+ "payable": true,
+ "stateMutability": "payable",
+ "type": "function",
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "implementation",
+ "outputs": [
+ {
+ "name": "",
+ "type": "address",
+ },
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function",
+ },
+ {
+ "constant": false,
+ "inputs": [
+ {
+ "name": "newAdmin",
+ "type": "address",
+ },
+ ],
+ "name": "changeAdmin",
+ "outputs": [],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "function",
+ },
+ {
+ "constant": true,
+ "inputs": [],
+ "name": "admin",
+ "outputs": [
+ {
+ "name": "",
+ "type": "address",
+ },
+ ],
+ "payable": false,
+ "stateMutability": "view",
+ "type": "function",
+ },
+ {
+ "inputs": [
+ {
+ "name": "_implementation",
+ "type": "address",
+ },
+ ],
+ "payable": false,
+ "stateMutability": "nonpayable",
+ "type": "constructor",
+ },
+ {
+ "payable": true,
+ "stateMutability": "payable",
+ "type": "fallback",
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "name": "previousAdmin",
+ "type": "address",
+ },
+ {
+ "indexed": false,
+ "name": "newAdmin",
+ "type": "address",
+ },
+ ],
+ "name": "AdminChanged",
+ "type": "event",
+ },
+ {
+ "anonymous": false,
+ "inputs": [
+ {
+ "indexed": false,
+ "name": "implementation",
+ "type": "address",
+ },
+ ],
+ "name": "Upgraded",
+ "type": "event",
+ },
+ ],
+ "address": {
+ "1": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
+ },
+ "name": "FiatToken",
+ },
+]
+`;
diff --git a/packages/cli/src/plugins/blockExplorer.test.ts b/packages/cli/src/plugins/blockExplorer.test.ts
index 13372f53ec..83e9ce98d5 100644
--- a/packages/cli/src/plugins/blockExplorer.test.ts
+++ b/packages/cli/src/plugins/blockExplorer.test.ts
@@ -4,13 +4,13 @@ import { afterAll, afterEach, beforeAll, expect, test } from 'vitest'
import {
address,
apiKey,
- baseUrl,
- handlers,
+ getHandlers,
unverifiedContractAddress,
} from '../../test/utils.js'
import { blockExplorer } from './blockExplorer.js'
-const server = setupServer(...handlers)
+const baseUrl = 'https://api.etherscan.io/v2/api'
+const server = setupServer(...getHandlers(baseUrl))
beforeAll(() => server.listen())
afterEach(() => server.resetHandlers())
diff --git a/packages/cli/src/plugins/blockExplorer.ts b/packages/cli/src/plugins/blockExplorer.ts
index 2518b6e936..907f072908 100644
--- a/packages/cli/src/plugins/blockExplorer.ts
+++ b/packages/cli/src/plugins/blockExplorer.ts
@@ -34,9 +34,7 @@ export type BlockExplorerConfig = {
* Function to get address from contract config.
*/
getAddress?:
- | ((config: {
- address: NonNullable
- }) => Address)
+ | ((config: { address: NonNullable }) => Address)
| undefined
/**
* Name of source.
diff --git a/packages/cli/src/plugins/etherscan.test.ts b/packages/cli/src/plugins/etherscan.test.ts
index dc496f4630..9dc31496bd 100644
--- a/packages/cli/src/plugins/etherscan.test.ts
+++ b/packages/cli/src/plugins/etherscan.test.ts
@@ -5,7 +5,7 @@ import { afterAll, afterEach, beforeAll, expect, test } from 'vitest'
import {
address,
apiKey,
- handlers,
+ getHandlers,
invalidApiKey,
proxyAddress,
timeoutAddress,
@@ -14,7 +14,7 @@ import {
import { etherscan } from './etherscan.js'
import { getCacheDir } from './fetch.js'
-const server = setupServer(...handlers)
+const server = setupServer(...getHandlers())
beforeAll(() => server.listen())
afterEach(() => server.resetHandlers())
diff --git a/packages/cli/src/plugins/etherscan.ts b/packages/cli/src/plugins/etherscan.ts
index fdd344c3b5..4a00b5aeb0 100644
--- a/packages/cli/src/plugins/etherscan.ts
+++ b/packages/cli/src/plugins/etherscan.ts
@@ -1,9 +1,8 @@
import { mkdir, writeFile } from 'node:fs/promises'
-import type { Abi } from 'abitype'
import { Address as AddressSchema } from 'abitype/zod'
import { camelCase } from 'change-case'
import { join } from 'pathe'
-import type { Address } from 'viem'
+import type { Abi, Address } from 'viem'
import { z } from 'zod'
import type { ContractConfig } from '../config.js'
@@ -199,12 +198,11 @@ type ChainId =
| 1 // Ethereum Mainnet
| 11155111 // Sepolia Testnet
| 17000 // Holesky Testnet
+ | 560048 // Hoodi Testnet
| 56 // BNB Smart Chain Mainnet
| 97 // BNB Smart Chain Testnet
| 137 // Polygon Mainnet
| 80002 // Polygon Amoy Testnet
- | 1101 // Polygon zkEVM Mainnet
- | 2442 // Polygon zkEVM Cardona Testnet
| 8453 // Base Mainnet
| 84532 // Base Sepolia Testnet
| 42161 // Arbitrum One Mainnet
@@ -212,8 +210,6 @@ type ChainId =
| 421614 // Arbitrum Sepolia Testnet
| 59144 // Linea Mainnet
| 59141 // Linea Sepolia Testnet
- | 250 // Fantom Opera Mainnet
- | 4002 // Fantom Testnet
| 81457 // Blast Mainnet
| 168587773 // Blast Sepolia Testnet
| 10 // OP Mainnet
@@ -221,17 +217,16 @@ type ChainId =
| 43114 // Avalanche C-Chain
| 43113 // Avalanche Fuji Testnet
| 199 // BitTorrent Chain Mainnet
- | 1028 // BitTorrent Chain Testnet
+ | 1029 // BitTorrent Chain Testnet
| 42220 // Celo Mainnet
- | 44787 // Celo Alfajores Testnet
+ | 11142220 // Celo Sepolia Testnet
| 25 // Cronos Mainnet
| 252 // Fraxtal Mainnet
| 2522 // Fraxtal Testnet
| 100 // Gnosis
- | 255 // Kroma Mainnet
- | 2358 // Kroma Sepolia Testnet
| 5000 // Mantle Mainnet
| 5003 // Mantle Sepolia Testnet
+ | 43521 // Memecore Testnet
| 1284 // Moonbeam Mainnet
| 1285 // Moonriver Mainnet
| 1287 // Moonbase Alpha Testnet
@@ -240,13 +235,9 @@ type ChainId =
| 534352 // Scroll Mainnet
| 534351 // Scroll Sepolia Testnet
| 167000 // Taiko Mainnet
- | 167009 // Taiko Hekla L2 Testnet
- | 1111 // WEMIX3.0 Mainnet
- | 1112 // WEMIX3.0 Testnet
+ | 167012 // Taiko Hoodi
| 324 // zkSync Mainnet
| 300 // zkSync Sepolia Testnet
- | 660279 // Xai Mainnet
- | 37714555429 // Xai Sepolia Testnet
| 50 // XDC Mainnet
| 51 // XDC Apothem Testnet
| 33139 // ApeChain Mainnet
@@ -256,9 +247,18 @@ type ChainId =
| 50104 // Sophon Mainnet
| 531050104 // Sophon Sepolia Testnet
| 146 // Sonic Mainnet
- | 57054 // Sonic Blaze Testnet
+ | 14601 // Sonic Testnet
| 130 // Unichain Mainnet
| 1301 // Unichain Sepolia Testnet
| 2741 // Abstract Mainnet
| 11124 // Abstract Sepolia Testnet
| 80094 // Berachain Mainnet
+ | 80069 // Berachain Bepolia Testnet
+ | 1923 // Swellchain Mainnet
+ | 1924 // Swellchain Testnet
+ | 10143 // Monad Testnet
+ | 999 // HyperEVM Mainnet
+ | 747474 // Katana Mainnet
+ | 737373 // Katana Bokuto
+ | 1329 // Sei Mainnet
+ | 1328 // Sei Testnet
diff --git a/packages/cli/src/plugins/fetch.test.ts b/packages/cli/src/plugins/fetch.test.ts
index 600cbfeda7..937a03f50a 100644
--- a/packages/cli/src/plugins/fetch.test.ts
+++ b/packages/cli/src/plugins/fetch.test.ts
@@ -6,14 +6,14 @@ import { afterAll, afterEach, beforeAll, expect, test } from 'vitest'
import {
address,
apiKey,
- baseUrl,
- handlers,
+ getHandlers,
timeoutAddress,
unverifiedContractAddress,
} from '../../test/utils.js'
import { fetch, getCacheDir } from './fetch.js'
-const server = setupServer(...handlers)
+const baseUrl = 'https://api.etherscan.io/v2/api'
+const server = setupServer(...getHandlers(baseUrl))
beforeAll(() => server.listen())
afterEach(() => server.resetHandlers())
diff --git a/packages/cli/src/plugins/fetch.ts b/packages/cli/src/plugins/fetch.ts
index 9e6b737e09..99502dd7b6 100644
--- a/packages/cli/src/plugins/fetch.ts
+++ b/packages/cli/src/plugins/fetch.ts
@@ -2,7 +2,7 @@ import { mkdir, readFile, writeFile } from 'node:fs/promises'
import { homedir } from 'node:os'
import { join } from 'pathe'
-import type { Abi } from 'abitype'
+import type { Abi } from 'viem'
import type { ContractConfig, Plugin } from '../config.js'
import type { Compute, RequiredBy } from '../types.js'
@@ -85,13 +85,9 @@ export function fetch(config: FetchConfig): FetchResult {
let abi: Abi | undefined
if (cachedFile?.timestamp > Date.now()) abi = cachedFile.abi
else {
+ const controller = new globalThis.AbortController()
+ const timeout = setTimeout(() => controller.abort(), timeoutDuration)
try {
- const controller = new globalThis.AbortController()
- const timeout = setTimeout(
- () => controller.abort(),
- timeoutDuration,
- )
-
const { url, init } = await request(contract)
const response = await globalThis.fetch(url, {
...init,
@@ -105,6 +101,7 @@ export function fetch(config: FetchConfig): FetchResult {
`${JSON.stringify({ abi, timestamp }, undefined, 2)}\n`,
)
} catch (error) {
+ clearTimeout(timeout)
try {
// Attempt to read from cache if fetch fails.
abi = JSON.parse(await readFile(cacheFilePath, 'utf8')).abi
diff --git a/packages/cli/src/plugins/foundry.test.ts b/packages/cli/src/plugins/foundry.test.ts
index 75e5ec73ee..9bc794a059 100644
--- a/packages/cli/src/plugins/foundry.test.ts
+++ b/packages/cli/src/plugins/foundry.test.ts
@@ -12,7 +12,7 @@ afterEach(() => {
test('forge not installed', async () => {
const dir = f.temp()
- expect(
+ await expect(
foundry({
project: dir,
forge: {
diff --git a/packages/cli/src/plugins/hardhat.test.ts b/packages/cli/src/plugins/hardhat.test.ts
index efb416c5e6..108b25abde 100644
--- a/packages/cli/src/plugins/hardhat.test.ts
+++ b/packages/cli/src/plugins/hardhat.test.ts
@@ -12,7 +12,7 @@ afterEach(() => {
test('validate', async () => {
const temp = f.temp()
- expect(
+ await expect(
hardhat({ project: temp }).validate?.(),
).rejects.toThrowErrorMatchingInlineSnapshot(
'[Error: hardhat must be installed to use Hardhat plugin.]',
@@ -34,7 +34,7 @@ test('project does not exist', async () => {
})
test('contracts', async () => {
- expect(
+ await expect(
hardhat({
project: resolve(__dirname, '__fixtures__/hardhat/'),
exclude: ['Foo.sol/**'],
diff --git a/packages/cli/src/plugins/react.test.ts b/packages/cli/src/plugins/react.test.ts
index 939a5299ae..e693e5fa20 100644
--- a/packages/cli/src/plugins/react.test.ts
+++ b/packages/cli/src/plugins/react.test.ts
@@ -335,3 +335,46 @@ test('legacy hook names', async () => {
export const useErc20TransferEvent = /*#__PURE__*/ createUseWatchContractEvent({ abi: erc20Abi, address: erc20Address, eventName: 'Transfer' })"
`)
})
+
+test('abi item hooks disabled', async () => {
+ const result = await react({ abiItemHooks: false }).run?.({
+ contracts: [
+ {
+ name: 'erc20',
+ abi: erc20Abi,
+ content: '',
+ meta: {
+ abiName: 'erc20Abi',
+ },
+ },
+ ],
+ isTypeScript: true,
+ outputs: [],
+ })
+
+ expect(result?.imports).toMatchInlineSnapshot(`
+ "import { createUseReadContract, createUseWriteContract, createUseSimulateContract, createUseWatchContractEvent } from 'wagmi/codegen'
+ "
+ `)
+ expect(result?.content).toMatchInlineSnapshot(`
+ "/**
+ * Wraps __{@link useReadContract}__ with \`abi\` set to __{@link erc20Abi}__
+ */
+ export const useReadErc20 = /*#__PURE__*/ createUseReadContract({ abi: erc20Abi })
+
+ /**
+ * Wraps __{@link useWriteContract}__ with \`abi\` set to __{@link erc20Abi}__
+ */
+ export const useWriteErc20 = /*#__PURE__*/ createUseWriteContract({ abi: erc20Abi })
+
+ /**
+ * Wraps __{@link useSimulateContract}__ with \`abi\` set to __{@link erc20Abi}__
+ */
+ export const useSimulateErc20 = /*#__PURE__*/ createUseSimulateContract({ abi: erc20Abi })
+
+ /**
+ * Wraps __{@link useWatchContractEvent}__ with \`abi\` set to __{@link erc20Abi}__
+ */
+ export const useWatchErc20Event = /*#__PURE__*/ createUseWatchContractEvent({ abi: erc20Abi })"
+ `)
+})
diff --git a/packages/cli/src/plugins/react.ts b/packages/cli/src/plugins/react.ts
index b76ea006a5..dfe41fffb3 100644
--- a/packages/cli/src/plugins/react.ts
+++ b/packages/cli/src/plugins/react.ts
@@ -4,15 +4,23 @@ import type { Contract, Plugin } from '../config.js'
import type { Compute, RequiredBy } from '../types.js'
import { getAddressDocString } from '../utils/getAddressDocString.js'
-export type ReactConfig = {
- getHookName?:
- | 'legacy' // TODO: Deprecate `'legacy'` option
- | ((options: {
- contractName: string
- itemName?: string | undefined
- type: 'read' | 'simulate' | 'watch' | 'write'
- }) => `use${string}`)
-}
+export type ReactConfig = Compute<
+ {
+ abiItemHooks?: boolean | undefined
+ } & (
+ | {
+ /** @deprecated */
+ getHookName: 'legacy'
+ }
+ | {
+ getHookName?: (options: {
+ contractName: string
+ itemName?: string | undefined
+ type: 'read' | 'simulate' | 'watch' | 'write'
+ }) => `use${string}`
+ }
+ )
+>
type ReactResult = Compute>
@@ -25,6 +33,8 @@ export function react(config: ReactConfig = {}): ReactResult {
const pure = '/*#__PURE__*/'
const hookNames = new Set()
+ const isAbiItemHooksEnabled = config.abiItemHooks ?? true
+
for (const contract of contracts) {
let hasReadFunction = false
let hasWriteFunction = false
@@ -65,34 +75,36 @@ export function react(config: ReactConfig = {}): ReactResult {
export const ${hookName} = ${pure} ${functionName}({ ${innerContent} })`,
)
- const names = new Set()
- for (const item of readItems) {
- if (item.type !== 'function') continue
- if (
- item.stateMutability !== 'pure' &&
- item.stateMutability !== 'view'
- )
- continue
+ if (isAbiItemHooksEnabled) {
+ const names = new Set()
+ for (const item of readItems) {
+ if (item.type !== 'function') continue
+ if (
+ item.stateMutability !== 'pure' &&
+ item.stateMutability !== 'view'
+ )
+ continue
- // Skip overrides since they are captured by same hook
- if (names.has(item.name)) continue
- names.add(item.name)
+ // Skip overrides since they are captured by same hook
+ if (names.has(item.name)) continue
+ names.add(item.name)
- const hookName = getHookName(
- config,
- hookNames,
- 'read',
- contract.name,
- item.name,
- )
- const docString = genDocString('useReadContract', contract, {
- name: 'functionName',
- value: item.name,
- })
- content.push(
- `${docString}
+ const hookName = getHookName(
+ config,
+ hookNames,
+ 'read',
+ contract.name,
+ item.name,
+ )
+ const docString = genDocString('useReadContract', contract, {
+ name: 'functionName',
+ value: item.name,
+ })
+ content.push(
+ `${docString}
export const ${hookName} = ${pure} ${functionName}({ ${innerContent}, functionName: '${item.name}' })`,
- )
+ )
+ }
}
}
@@ -112,34 +124,36 @@ export const ${hookName} = ${pure} ${functionName}({ ${innerContent}, functionNa
export const ${hookName} = ${pure} ${functionName}({ ${innerContent} })`,
)
- const names = new Set()
- for (const item of writeItems) {
- if (item.type !== 'function') continue
- if (
- item.stateMutability !== 'nonpayable' &&
- item.stateMutability !== 'payable'
- )
- continue
+ if (isAbiItemHooksEnabled) {
+ const names = new Set()
+ for (const item of writeItems) {
+ if (item.type !== 'function') continue
+ if (
+ item.stateMutability !== 'nonpayable' &&
+ item.stateMutability !== 'payable'
+ )
+ continue
- // Skip overrides since they are captured by same hook
- if (names.has(item.name)) continue
- names.add(item.name)
+ // Skip overrides since they are captured by same hook
+ if (names.has(item.name)) continue
+ names.add(item.name)
- const hookName = getHookName(
- config,
- hookNames,
- 'write',
- contract.name,
- item.name,
- )
- const docString = genDocString('useWriteContract', contract, {
- name: 'functionName',
- value: item.name,
- })
- content.push(
- `${docString}
+ const hookName = getHookName(
+ config,
+ hookNames,
+ 'write',
+ contract.name,
+ item.name,
+ )
+ const docString = genDocString('useWriteContract', contract, {
+ name: 'functionName',
+ value: item.name,
+ })
+ content.push(
+ `${docString}
export const ${hookName} = ${pure} ${functionName}({ ${innerContent}, functionName: '${item.name}' })`,
- )
+ )
+ }
}
}
@@ -158,34 +172,40 @@ export const ${hookName} = ${pure} ${functionName}({ ${innerContent}, functionNa
export const ${hookName} = ${pure} ${functionName}({ ${innerContent} })`,
)
- const names = new Set()
- for (const item of writeItems) {
- if (item.type !== 'function') continue
- if (
- item.stateMutability !== 'nonpayable' &&
- item.stateMutability !== 'payable'
- )
- continue
+ if (isAbiItemHooksEnabled) {
+ const names = new Set()
+ for (const item of writeItems) {
+ if (item.type !== 'function') continue
+ if (
+ item.stateMutability !== 'nonpayable' &&
+ item.stateMutability !== 'payable'
+ )
+ continue
- // Skip overrides since they are captured by same hook
- if (names.has(item.name)) continue
- names.add(item.name)
+ // Skip overrides since they are captured by same hook
+ if (names.has(item.name)) continue
+ names.add(item.name)
- const hookName = getHookName(
- config,
- hookNames,
- 'simulate',
- contract.name,
- item.name,
- )
- const docString = genDocString('useSimulateContract', contract, {
- name: 'functionName',
- value: item.name,
- })
- content.push(
- `${docString}
+ const hookName = getHookName(
+ config,
+ hookNames,
+ 'simulate',
+ contract.name,
+ item.name,
+ )
+ const docString = genDocString(
+ 'useSimulateContract',
+ contract,
+ {
+ name: 'functionName',
+ value: item.name,
+ },
+ )
+ content.push(
+ `${docString}
export const ${hookName} = ${pure} ${functionName}({ ${innerContent}, functionName: '${item.name}' })`,
- )
+ )
+ }
}
}
}
@@ -205,29 +225,35 @@ export const ${hookName} = ${pure} ${functionName}({ ${innerContent}, functionNa
export const ${hookName} = ${pure} ${functionName}({ ${innerContent} })`,
)
- const names = new Set()
- for (const item of eventItems) {
- if (item.type !== 'event') continue
+ if (isAbiItemHooksEnabled) {
+ const names = new Set()
+ for (const item of eventItems) {
+ if (item.type !== 'event') continue
- // Skip overrides since they are captured by same hook
- if (names.has(item.name)) continue
- names.add(item.name)
+ // Skip overrides since they are captured by same hook
+ if (names.has(item.name)) continue
+ names.add(item.name)
- const hookName = getHookName(
- config,
- hookNames,
- 'watch',
- contract.name,
- item.name,
- )
- const docString = genDocString('useWatchContractEvent', contract, {
- name: 'eventName',
- value: item.name,
- })
- content.push(
- `${docString}
+ const hookName = getHookName(
+ config,
+ hookNames,
+ 'watch',
+ contract.name,
+ item.name,
+ )
+ const docString = genDocString(
+ 'useWatchContractEvent',
+ contract,
+ {
+ name: 'eventName',
+ value: item.name,
+ },
+ )
+ content.push(
+ `${docString}
export const ${hookName} = ${pure} ${functionName}({ ${innerContent}, eventName: '${item.name}' })`,
- )
+ )
+ }
}
}
}
diff --git a/packages/cli/src/plugins/routescan.test.ts b/packages/cli/src/plugins/routescan.test.ts
new file mode 100644
index 0000000000..28cdc1323c
--- /dev/null
+++ b/packages/cli/src/plugins/routescan.test.ts
@@ -0,0 +1,116 @@
+import { mkdir, rm } from 'node:fs/promises'
+import { setupServer } from 'msw/node'
+import { afterAll, afterEach, beforeAll, expect, test } from 'vitest'
+
+import {
+ address,
+ apiKey,
+ getHandlers,
+ invalidApiKey,
+ proxyAddress,
+ timeoutAddress,
+ unverifiedContractAddress,
+} from '../../test/utils.js'
+import { getCacheDir } from './fetch.js'
+import { routescan } from './routescan.js'
+
+const server = setupServer(
+ ...getHandlers(
+ 'https://api.routescan.io/v2/network/mainnet/evm/1/etherscan/api',
+ ),
+)
+
+beforeAll(() => server.listen())
+afterEach(() => server.resetHandlers())
+afterAll(() => server.close())
+
+test('fetches ABI', async () => {
+ await expect(
+ routescan({
+ apiKey,
+ chainId: 1,
+ contracts: [{ name: 'WagmiMintExample', address }],
+ }).contracts?.(),
+ ).resolves.toMatchSnapshot()
+})
+
+test('fetches ABI with multichain deployment', async () => {
+ await expect(
+ routescan({
+ apiKey,
+ chainId: 1,
+ contracts: [
+ { name: 'WagmiMintExample', address: { 1: address, 10: address } },
+ ],
+ }).contracts?.(),
+ ).resolves.toMatchSnapshot()
+})
+
+test('fails to fetch for unverified contract', async () => {
+ await expect(
+ routescan({
+ apiKey,
+ chainId: 1,
+ contracts: [
+ { name: 'WagmiMintExample', address: unverifiedContractAddress },
+ ],
+ }).contracts?.(),
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
+ '[Error: Contract source code not verified]',
+ )
+})
+
+test('missing address for chainId', async () => {
+ await expect(
+ routescan({
+ apiKey,
+ chainId: 1,
+ // @ts-expect-error `chainId` and `keyof typeof contracts[number].address` mismatch
+ contracts: [{ name: 'WagmiMintExample', address: { 10: address } }],
+ }).contracts?.(),
+ ).rejects.toThrowErrorMatchingInlineSnapshot(
+ `[Error: No address found for chainId "1". Make sure chainId "1" is set as an address.]`,
+ )
+})
+
+test('invalid api key', async () => {
+ await expect(
+ routescan({
+ apiKey: invalidApiKey,
+ chainId: 1,
+ contracts: [{ name: 'WagmiMintExample', address: timeoutAddress }],
+ }).contracts?.(),
+ ).rejects.toThrowErrorMatchingInlineSnapshot('[Error: Invalid API Key]')
+})
+
+test('tryFetchProxyImplementation: fetches ABI', async () => {
+ const cacheDir = getCacheDir()
+ await mkdir(cacheDir, { recursive: true })
+
+ await expect(
+ routescan({
+ apiKey,
+ chainId: 1,
+ contracts: [{ name: 'WagmiMintExample', address }],
+ tryFetchProxyImplementation: true,
+ }).contracts?.(),
+ ).resolves.toMatchSnapshot()
+
+ await rm(cacheDir, { recursive: true })
+})
+
+test('tryFetchProxyImplementation: fetches implementation ABI', async () => {
+ const cacheDir = getCacheDir()
+ await mkdir(cacheDir, { recursive: true })
+
+ await expect(
+ routescan({
+ apiKey,
+ chainId: 1,
+ contracts: [{ name: 'FiatToken', address: proxyAddress }],
+ tryFetchProxyImplementation: true,
+ }).contracts?.(),
+ ).resolves.toMatchSnapshot()
+
+ await rm(cacheDir, { recursive: true })
+})
diff --git a/packages/cli/src/plugins/routescan.ts b/packages/cli/src/plugins/routescan.ts
new file mode 100644
index 0000000000..0d2419c61d
--- /dev/null
+++ b/packages/cli/src/plugins/routescan.ts
@@ -0,0 +1,354 @@
+import { mkdir, writeFile } from 'node:fs/promises'
+import { Address as AddressSchema } from 'abitype/zod'
+import { camelCase } from 'change-case'
+import { join } from 'pathe'
+import type { Abi, Address } from 'viem'
+import { z } from 'zod'
+
+import type { ContractConfig } from '../config.js'
+import { fromZodError } from '../errors.js'
+import type { Compute } from '../types.js'
+import { fetch, getCacheDir } from './fetch.js'
+
+export type RoutescanConfig = {
+ /**
+ * Routescan API key.
+ */
+ apiKey: string
+ /**
+ * Duration in milliseconds to cache ABIs.
+ *
+ * @default 1_800_000 // 30m in ms
+ */
+ cacheDuration?: number | undefined
+ /**
+ * Chain ID to use for fetching ABI.
+ *
+ * If `address` is an object, `chainId` is used to select the address.
+ */
+ chainId: (chainId extends ChainId ? chainId : never) | (ChainId & {})
+ /**
+ * Contracts to fetch ABIs for.
+ */
+ contracts: Compute, 'abi'>>[]
+ /**
+ * Whether to try fetching proxy implementation address of the contract
+ *
+ * @default false
+ */
+ tryFetchProxyImplementation?: boolean | undefined
+}
+
+/**
+ * Fetches contract ABIs from Routescan.
+ */
+export function routescan(
+ config: RoutescanConfig,
+) {
+ const {
+ apiKey,
+ cacheDuration = 1_800_000,
+ chainId,
+ tryFetchProxyImplementation = false,
+ } = config
+
+ const contracts = config.contracts.map((x) => ({
+ ...x,
+ address:
+ typeof x.address === 'string' ? { [chainId]: x.address } : x.address,
+ })) as Omit[]
+
+ const name = 'Routescan'
+
+ const getCacheKey: Parameters[0]['getCacheKey'] = ({
+ contract,
+ }) => {
+ if (typeof contract.address === 'string')
+ return `${camelCase(name)}:${contract.address}`
+ return `${camelCase(name)}:${JSON.stringify(contract.address)}`
+ }
+
+ return fetch({
+ cacheDuration,
+ contracts,
+ name,
+ getCacheKey,
+ async parse({ response }) {
+ const json = await response.json()
+ const parsed = await GetAbiResponse.safeParseAsync(json)
+ if (!parsed.success)
+ throw fromZodError(parsed.error, { prefix: 'Invalid response' })
+ if (parsed.data.status === '0') throw new Error(parsed.data.result)
+ return parsed.data.result
+ },
+ async request(contract) {
+ if (!contract.address) throw new Error('address is required')
+
+ const resolvedAddress = (() => {
+ if (!contract.address) throw new Error('address is required')
+ if (typeof contract.address === 'string') return contract.address
+ const contractAddress = contract.address[chainId]
+ if (!contractAddress)
+ throw new Error(
+ `No address found for chainId "${chainId}". Make sure chainId "${chainId}" is set as an address.`,
+ )
+ return contractAddress
+ })()
+
+ const options = {
+ address: resolvedAddress,
+ apiKey,
+ chainId,
+ }
+
+ let abi: Abi | undefined
+ const implementationAddress = await (async () => {
+ if (!tryFetchProxyImplementation) return
+ const json = await globalThis
+ .fetch(buildUrl({ ...options, action: 'getsourcecode' }))
+ .then((res) => res.json())
+ const parsed = await GetSourceCodeResponse.safeParseAsync(json)
+ if (!parsed.success)
+ throw fromZodError(parsed.error, { prefix: 'Invalid response' })
+ if (parsed.data.status === '0') throw new Error(parsed.data.result)
+ if (!parsed.data.result[0]) return
+ abi = parsed.data.result[0].ABI
+ return parsed.data.result[0].Implementation as Address
+ })()
+
+ if (abi) {
+ const cacheDir = getCacheDir()
+ await mkdir(cacheDir, { recursive: true })
+ const cacheKey = getCacheKey({ contract })
+ const cacheFilePath = join(cacheDir, `${cacheKey}.json`)
+ await writeFile(
+ cacheFilePath,
+ `${JSON.stringify({ abi, timestamp: Date.now() + cacheDuration }, undefined, 2)}\n`,
+ )
+ }
+
+ return {
+ url: buildUrl({
+ ...options,
+ action: 'getabi',
+ address: implementationAddress || resolvedAddress,
+ }),
+ }
+ },
+ })
+}
+
+function buildUrl(options: {
+ action: 'getabi' | 'getsourcecode'
+ address: Address
+ apiKey: string
+ chainId: ChainId | undefined
+}) {
+ const { action, address, apiKey, chainId } = options
+ const baseUrl = `https://api.routescan.io/v2/network/mainnet/evm/${chainId}/etherscan/api`
+ return `${baseUrl}?module=contract&action=${action}&address=${address}${apiKey ? `&apikey=${apiKey}` : ''}`
+}
+
+const GetAbiResponse = z.discriminatedUnion('status', [
+ z.object({
+ status: z.literal('1'),
+ message: z.literal('OK'),
+ result: z.string().transform((val) => JSON.parse(val) as Abi),
+ }),
+ z.object({
+ status: z.literal('0'),
+ message: z.literal('NOTOK'),
+ result: z.string(),
+ }),
+])
+
+const GetSourceCodeResponse = z.discriminatedUnion('status', [
+ z.object({
+ status: z.literal('1'),
+ message: z.literal('OK'),
+ result: z.array(
+ z.discriminatedUnion('Proxy', [
+ z.object({
+ ABI: z.string().transform((val) => JSON.parse(val) as Abi),
+ Implementation: AddressSchema,
+ Proxy: z.literal('1'),
+ }),
+ z.object({
+ ABI: z.string().transform((val) => JSON.parse(val) as Abi),
+ Implementation: z.string(),
+ Proxy: z.literal('0'),
+ }),
+ ]),
+ ),
+ }),
+ z.object({
+ status: z.literal('0'),
+ message: z.literal('NOTOK'),
+ result: z.string(),
+ }),
+])
+
+// Supported chains
+type ChainId =
+ | 1 // Ethereum
+ | 10 // OP Mainnet
+ | 14 // Flare Mainnet
+ | 16 // Coston
+ | 19 // Songbird Canary
+ | 56 // BNB Smart Chain
+ | 114 // Coston2
+ | 130 // Unichain
+ | 151 // Redbelly
+ | 166 // Nomina
+ | 185 // Mint
+ | 252 // Fraxtal
+ | 254 // Swan chain
+ | 288 // Boba Ethereum
+ | 291 // Orderly
+ | 324 // zkSync Era
+ | 335 // DFK
+ | 357 // Pulsar
+ | 369 // Pulse Chain
+ | 919 // Mode
+ | 1301 // Unichain
+ | 1687 // Mint Sepolia
+ | 1946 // Minato
+ | 2037 // Kiwi
+ | 2233 // Chainbase
+ | 2522 // Fraxtal
+ | 3012 // PLAYA3ULL Games
+ | 3636 // Botanix
+ | 3939 // DOS
+ | 4202 // Lisk
+ | 4460 // Orderly
+ | 10888 // GameSwift
+ | 17000 // Holesky
+ | 28882 // Boba Sepolia
+ | 48795 // Space
+ | 49321 // GUNZ
+ | 70800 // Barret
+ | 80008 // Polynomial Sepolia
+ | 80085 // Artio Testnet
+ | 84532 // Base Sepolia
+ | 88882 // Chiliz Spicy
+ | 167008 // Taiko Katla
+ | 167009 // Taiko Hekla
+ | 173750 // Echo
+ | 421614 // Arbitrum Sepolia
+ | 555666 // Eclipse
+ | 763373 // Ink
+ | 779672 // Dispatch
+ | 11155111 // Sepolia
+ | 11155420 // OP Sepolia
+ | 20241133 // Proxima
+ | 21000001 // Corn
+ | 168587773 // Blast Sepolia
+ | 999999999 // Zora Sepolia
+ | 164_4 // Nomina
+ | 153_2 // Redbelly
+ | 70805_2 // Cloud
+ | 378 // Koroshi
+ | 379 // KOROSHI
+ | 987 // Orange
+ | 999 // Hyperliquid EVM
+ | 1088 // Metis
+ | 1135 // Lisk
+ | 1216 // Intersect
+ | 1234 // StepNetwork
+ | 1344 // Blitz
+ | 1853 // HighOctane
+ | 1888 // Memoria
+ | 1923 // Swell
+ | 2038 // Shrapnel
+ | 2044 // Shrapnel
+ | 2786 // Apertum
+ | 2818 // Morph
+ | 3011 // PLAYA3ULL Games
+ | 3084 // XL Network
+ | 3278 // Soshi
+ | 3637 // Botanix
+ | 4227 // Hashfire
+ | 4313 // Artery
+ | 4337 // Beam
+ | 5000 // Mantle
+ | 5039 // Onigiri
+ | 5040 // Onigiri
+ | 5115 // Citrea
+ | 5330 // Superseed
+ | 5566 // StraitsX
+ | 6119 // UPTN
+ | 6533 // Kalichain
+ | 6900 // Nibiru
+ | 6911 // Nibiru Testnet-2
+ | 7894 // Mintus
+ | 7979 // DOS
+ | 8008 // Polynomial
+ | 8021 // Numine
+ | 8227 // Space
+ | 8453 // Base
+ | 8787 // Animalia
+ | 9745 // Plasma
+ | 10036 // Innovo
+ | 10507 // Numbers
+ | 10849 // Lamina1
+ | 10850 // Lamina1 Identity
+ | 11227 // Jiritsutes
+ | 12150 // QChain
+ | 13322 // Fifa Blockchain
+ | 13337 // Beam
+ | 13576 // Mythgames
+ | 14174 // Pecorino
+ | 16180 // Plyr
+ | 21024 // Tradex
+ | 21816 // Frqtal
+ | 24010 // Stealthnet
+ | 27827 // Zeroone
+ | 28530 // Blockticity
+ | 33311 // Feature
+ | 34443 // Mode
+ | 42161 // Arbitrum One
+ | 43113 // C-Chain Fuji
+ | 43114 // C-Chain
+ | 43419 // GUNZ
+ | 47208 // Armada
+ | 53188 // DSRV2
+ | 53302 // Superseed
+ | 53935 // DFK
+ | 54414 // Innovomark
+ | 55197 // Egmtester
+ | 56288 // Boba BNB
+ | 56400 // Zeroone
+ | 57073 // Ink
+ | 59409 // Lifeaiv1
+ | 59932 // Insomnia
+ | 61587 // Growth
+ | 62521 // Lucid
+ | 62831 // Plyr
+ | 68414 // Henesys
+ | 69696 // Ceden
+ | 76736 // Hiss
+ | 79554 // Lucid
+ | 79685 // Modex
+ | 80069 // Berachain bepolia
+ | 80094 // Berachain
+ | 81457 // Blast
+ | 84358 // Titan
+ | 88888 // Chiliz
+ | 96786 // Delaunch
+ | 97433 // Growth
+ | 124816 // Mitosis
+ | 132008 // BitcoinL1
+ | 167000 // Taiko
+ | 210815 // Stavax
+ | 432201 // Dexalot
+ | 432204 // Dexalot
+ | 560048 // Hoodi
+ | 710420 // Tiltyard
+ | 723107 // Tixchain
+ | 5278000 // JSC Kaigan
+ | 7777777 // Zora
+ | 21000000 // Corn
+ | 420120000 // Alpha 0
+ | 420120001 // Alpha 1
+ | 420420421 // Westend
+ | 9746_5 // Plasma
diff --git a/packages/cli/src/plugins/sourcify.test.ts b/packages/cli/src/plugins/sourcify.test.ts
index b5ebb104c1..6ca0ecb536 100644
--- a/packages/cli/src/plugins/sourcify.test.ts
+++ b/packages/cli/src/plugins/sourcify.test.ts
@@ -1,43 +1,32 @@
-import { http, HttpResponse } from 'msw'
+import { HttpResponse, http } from 'msw'
import { setupServer } from 'msw/node'
import { afterAll, afterEach, beforeAll, expect, test } from 'vitest'
import { depositAbi } from '../../test/constants.js'
import { sourcify } from './sourcify.js'
-const baseUrl = 'https://repo.sourcify.dev/contracts/full_match'
+const baseUrl = 'https://sourcify.dev/server/v2/contract'
const address = '0x00000000219ab540356cbb839cbe05303d7705fa'
const chainId = 1
const multichainAddress = '0xC4c622862a8F548997699bE24EA4bc504e5cA865'
const multichainIdGnosis = 100
const multichainIdPolygon = 137
const successJson = {
- compiler: { version: '0.6.11+commit.5ef660b1' },
- language: 'Solidity',
- output: {
- abi: depositAbi,
- devdoc: {},
- userdoc: {},
- },
- settings: {},
- sources: {},
- version: 1,
+ abi: depositAbi,
}
const handlers = [
- http.get(`${baseUrl}/${chainId}/${address}/metadata.json`, () =>
+ http.get(`${baseUrl}/${chainId}/${address}`, () =>
HttpResponse.json(successJson),
),
- http.get(`${baseUrl}/${multichainIdGnosis}/${address}/metadata.json`, () =>
+ http.get(`${baseUrl}/${multichainIdGnosis}/${address}`, () =>
HttpResponse.json({}, { status: 404 }),
),
- http.get(
- `${baseUrl}/${multichainIdGnosis}/${multichainAddress}/metadata.json`,
- () => HttpResponse.json(successJson),
+ http.get(`${baseUrl}/${multichainIdGnosis}/${multichainAddress}`, () =>
+ HttpResponse.json(successJson),
),
- http.get(
- `${baseUrl}/${multichainIdPolygon}/${multichainAddress}/metadata.json`,
- () => HttpResponse.json(successJson),
+ http.get(`${baseUrl}/${multichainIdPolygon}/${multichainAddress}`, () =>
+ HttpResponse.json(successJson),
),
]
@@ -47,8 +36,8 @@ beforeAll(() => server.listen())
afterEach(() => server.resetHandlers())
afterAll(() => server.close())
-test('fetches ABI', () => {
- expect(
+test('fetches ABI', async () => {
+ await expect(
sourcify({
chainId: chainId,
contracts: [{ name: 'DepositContract', address }],
@@ -56,8 +45,8 @@ test('fetches ABI', () => {
).resolves.toMatchSnapshot()
})
-test('fetches ABI with multichain deployment', () => {
- expect(
+test('fetches ABI with multichain deployment', async () => {
+ await expect(
sourcify({
chainId: 100,
contracts: [
@@ -70,8 +59,8 @@ test('fetches ABI with multichain deployment', () => {
).resolves.toMatchSnapshot()
})
-test('fails to fetch for unverified contract', () => {
- expect(
+test('fails to fetch for unverified contract', async () => {
+ await expect(
sourcify({
chainId: 100,
contracts: [{ name: 'DepositContract', address }],
@@ -81,8 +70,8 @@ test('fails to fetch for unverified contract', () => {
)
})
-test('missing address for chainId', () => {
- expect(
+test('missing address for chainId', async () => {
+ await expect(
sourcify({
chainId: 1,
// @ts-expect-error `chainId` and `keyof typeof contracts[number].address` mismatch
diff --git a/packages/cli/src/plugins/sourcify.ts b/packages/cli/src/plugins/sourcify.ts
index f53a020a3c..5c0637308a 100644
--- a/packages/cli/src/plugins/sourcify.ts
+++ b/packages/cli/src/plugins/sourcify.ts
@@ -29,18 +29,7 @@ export type SourcifyConfig = {
}
const SourcifyResponse = z.object({
- compiler: z.object({
- version: z.string(),
- }),
- language: z.string(),
- output: z.object({
- abi: AbiSchema,
- devdoc: z.any(),
- userdoc: z.any(),
- }),
- settings: z.any(),
- sources: z.any(),
- version: z.number(),
+ abi: AbiSchema,
})
/** Fetches contract ABIs from Sourcify. */
@@ -67,8 +56,7 @@ export function sourcify(
if (!parsed.success)
throw fromZodError(parsed.error, { prefix: 'Invalid response' })
- if (parsed.data.output.abi)
- return parsed.data.output.abi as ContractConfig['abi']
+ if (parsed.data.abi) return parsed.data.abi as ContractConfig['abi']
throw new Error('contract not found')
},
request({ address }) {
@@ -82,9 +70,8 @@ export function sourcify(
throw new Error(
`No address found for chainId "${chainId}". Make sure chainId "${chainId}" is set as an address.`,
)
-
return {
- url: `https://repo.sourcify.dev/contracts/full_match/${chainId}/${contractAddress}/metadata.json`,
+ url: `https://sourcify.dev/server/v2/contract/${chainId}/${contractAddress}?fields=abi`,
}
},
})
@@ -94,231 +81,247 @@ export function sourcify(
// https://docs.sourcify.dev/docs/chains
type ChainId =
| 1 // Ethereum Mainnet
+ | 560048 // Ethereum Testnet Hoodi
+ | 11155111 // Ethereum Testnet Sepolia
| 17000 // Ethereum Testnet Holesky
| 5 // Ethereum Testnet Goerli
- | 11155111 // Ethereum Testnet Sepolia
| 3 // Ethereum Testnet Ropsten
| 4 // Ethereum Testnet Rinkeby
- | 10 // OP Mainnet
- | 100 // Gnosis
- | 100009 // VeChain
- | 100010 // VeChain Testnet
- | 1001 // Kaia Kairos Testnet
- | 10200 // Gnosis Chiado Testnet
+ | 96969696 // Privix Chain Testnet
+ | 180 // AME Chain Mainnet
+ | 78430 // Amplify Subnet
+ | 1339 // Elysium Mainnet
+ | 421613 // Arbitrum Goerli
+ | 42170 // Arbitrum Nova
+ | 42161 // Arbitrum One
+ | 421614 // Arbitrum Sepolia
+ | 421611 // Arbitrum Rinkeby
| 10242 // Arthera Mainnet
| 10243 // Arthera Testnet
- | 1030 // Conflux eSpace
- | 103090 // Crystaleum
- | 105105 // Stratis Mainnet
- | 106 // Velas EVM Mainnet
- | 10849 // Lamina1
- | 10850 // Lamina1 Identity
- | 1088 // Metis Andromeda Mainnet
- | 1101 // Polygon zkEVM
- | 111000 // Siberium Test Network
- | 11111 // WAGMI
- | 1114 // Core Blockchain Testnet2
- | 1115 // Core Blockchain Testnet
- | 11155420 // OP Sepolia Testnet
- | 1116 // Core Blockchain Mainnet
- | 11235 // Haqq Network
- | 1127469 // Tiltyard Subnet
- | 11297108099 // Palm Testnet
- | 11297108109 // Palm
- | 1149 // Symplexia Smart Chain
- | 122 // Fuse Mainnet
- | 1284 // Moonbeam
- | 1285 // Moonriver
- | 1287 // Moonbase Alpha
- | 12898 // PlayFair Testnet Subnet
- | 1291 // Swisstronik Testnet
+ | 592 // Astar
+ | 6321 // Aura Euphoria Testnet
+ | 6322 // Aura Mainnet
| 1313161554 // Aurora Mainnet
| 1313161555 // Aurora Testnet
+ | 43114 // Avalanche C-Chain
+ | 43113 // Avalanche Fuji Testnet
+ | 223 // B2 Mainnet
+ | 56 // BNB Smart Chain Mainnet
+ | 97 // BNB Smart Chain Testnet
+ | 8453 // Base
+ | 84531 // Base Goerli Testnet
+ | 84532 // Base Sepolia Testnet
+ | 4337 // Beam
| 13337 // Beam Testnet
- | 13381 // Phoenix Mainnet
- | 1339 // Elysium Mainnet
- | 137 // Polygon Mainnet
- | 14 // Flare Mainnet
- | 1433 // Rikeza Network Mainnet
- | 1516 // Story Odyssey Testnet
- | 16180 // PLYR PHI
- | 16350 // Incentiv Devnet
- | 167005 // Taiko Grimsvotn L2
- | 167006 // Taiko Eldfell L3
- | 17069 // Garnet Holesky
- | 180 // AME Chain Mainnet
- | 1890 // Lightlink Phoenix Mainnet
- | 1891 // Lightlink Pegasus Testnet
- | 19 // Songbird Canary-Network
- | 19011 // HOME Verse Mainnet
- | 192837465 // Gather Mainnet Network
- | 2000 // Dogechain Mainnet
- | 200810 // Bitlayer Testnet
+ | 641230 // Bear Network Chain Mainnet
| 200901 // Bitlayer Mainnet
- | 2017 // Adiri
- | 2020 // Ronin Mainnet
+ | 200810 // Bitlayer Testnet
+ | 7171 // Bitrock Mainnet
+ | 7771 // Bitrock Testnet
+ | 81457 // Blast
+ | 288 // Boba Network
+ | 28 // Boba Network Rinkeby Testnet
+ | 78431 // Bulletin Subnet
+ | 534 // Candle
+ | 7700 // Canto
+ | 7701 // Canto Tesnet
+ | 44787 // Celo Alfajores Testnet
+ | 62320 // Celo Baklava Testnet
+ | 42220 // Celo Mainnet
+ | 11142220 // Celo Sepolia Testnet
+ | 5115 // Citrea Testnet
+ | 78432 // Conduit Subnet
+ | 1030 // Conflux eSpace
+ | 1116 // Core Blockchain Mainnet
+ | 1115 // Core Blockchain Testnet
+ | 1114 // Core Blockchain Testnet2
+ | 21000000 // Corn
+ | 44 // Crab Network
+ | 25 // Cronos Mainnet
+ | 4157 // CrossFi Testnet
+ | 3737 // Crossbell
+ | 103090 // Crystaleum
+ | 33111 // Curtis
+ | 53935 // DFK Chain
+ | 335 // DFK Chain Test
+ | 46 // Darwinia Network
+ | 43 // Darwinia Pangolin Testnet
+ | 666666666 // Degen Chain
+ | 432204 // Dexalot Subnet
+ | 432201 // Dexalot Subnet Testnet
+ | 2000 // Dogechain Mainnet
| 2021 // Edgeware EdgeEVM Mainnet
- | 202401 // YMTECH-BESU Testnet
- | 2037 // Kiwi Subnet
- | 2038 // Shrapnel Testnet
- | 2044 // Shrapnel Subnet
- | 2047 // Stratos Testnet
- | 2048 // Stratos
- | 205205 // Auroria Testnet
- | 212 // MAPO Makalu
- | 216 // Happychain Testnet
- | 222000222 // Kanazawa
- | 2221 // Kava Testnet
- | 2222 // Kava
- | 223 // B2 Mainnet
- | 22776 // MAP Protocol
- | 23294 // Oasis Sapphire
- | 23295 // Oasis Sapphire Testnet
- | 2358 // Kroma Sepolia
- | 2442 // Polygon zkEVM Cardona Testnet
+ | 648 // Endurance Smart Chain Mainnet
+ | 39797 // Energi Mainnet
+ | 49797 // Energi Testnet
| 246 // Energy Web Chain
- | 25 // Cronos Mainnet
+ | 73799 // Energy Web Volta Testnet
+ | 61 // Ethereum Classic
+ | 42793 // Etherlink Mainnet
+ | 128123 // Etherlink Testnet
+ | 9001 // Evmos
+ | 9000 // Evmos Testnet
| 250 // Fantom Opera
- | 252 // Fraxtal
- | 2522 // Fraxtal Testnet
- | 255 // Kroma
- | 25925 // KUB Testnet
| 26100 // Ferrum Quantum Portal Network
- | 28 // Boba Network Rinkeby Testnet
- | 28528 // Optimism Bedrock (Goerli Alpha Testnet)
- | 288 // Boba Network
- | 295 // Hedera Mainnet
- | 30 // Rootstock Mainnet
- | 300 // zkSync Sepolia Testnet
- | 311752642 // OneLedger Mainnet
- | 314 // Filecoin - Mainnet
| 314159 // Filecoin - Calibration testnet
- | 32769 // Zilliqa EVM
- | 32770 // Zilliqa 2 EVM proto-mainnet
- | 33101 // Zilliqa EVM Testnet
- | 33103 // Zilliqa 2 EVM proto-testnet
- | 33111 // Curtis
- | 333000333 // Meld
- | 335 // DFK Chain Test
- | 336 // Shiden
- | 34443 // Mode
- | 35441 // Q Mainnet
- | 35443 // Q Testnet
+ | 314 // Filecoin - Mainnet
+ | 14 // Flare Mainnet
+ | 252 // Fraxtal
+ | 2522 // Fraxtal Testnet
+ | 122 // Fuse Mainnet
+ | 17069 // Garnet Holesky
+ | 486217935 // Gather Devnet Network
+ | 192837465 // Gather Mainnet Network
| 356256156 // Gather Testnet Network
- | 369 // PulseChain
- | 3737 // Crossbell
- | 37714555429 // Xai Testnet v2
- | 383414847825 // Zeniq
- | 39797 // Energi Mainnet
- | 40 // Telos EVM Mainnet
- | 4000 // Ozone Chain Mainnet
- | 41 // Telos EVM Testnet
- | 4157 // CrossFi Testnet
- | 420 // Optimism Goerli Testnet
- | 4200 // Merlin Mainnet
+ | 100 // Gnosis
+ | 10200 // Gnosis Chiado Testnet
+ | 71402 // Godwoken Mainnet
+ | 71401 // Godwoken Testnet v1
+ | 19011 // HOME Verse Mainnet
+ | 216 // Happychain Testnet
+ | 54211 // Haqq Chain Testnet
+ | 11235 // Haqq Network
+ | 295 // Hedera Mainnet
+ | 16350 // Incentiv Devnet
+ | 96 // KUB Mainnet
+ | 25925 // KUB Testnet
+ | 1001 // Kaia Kairos Testnet
+ | 8217 // Kaia Mainnet
+ | 2222 // Kava
+ | 2221 // Kava Testnet
| 420420 // Kekchain
| 420666 // Kekchain (kektest)
- | 42161 // Arbitrum One
- | 421611 // Arbitrum Rinkeby
- | 421613 // Arbitrum Goerli
- | 4216137055 // OneLedger Testnet Frankenstein
- | 421614 // Arbitrum Sepolia
- | 42170 // Arbitrum Nova
- | 42220 // Celo Mainnet
- | 42261 // Oasis Emerald Testnet
- | 42262 // Oasis Emerald
- | 42766 // ZKFair Mainnet
- | 43 // Darwinia Pangolin Testnet
- | 43113 // Avalanche Fuji Testnet
- | 43114 // Avalanche C-Chain
- | 432201 // Dexalot Subnet Testnet
- | 432204 // Dexalot Subnet
- | 4337 // Beam
- | 44 // Crab Network
- | 44787 // Celo Alfajores Testnet
- | 46 // Darwinia Network
- | 486217935 // Gather Devnet Network
- | 48899 // Zircuit Testnet
- | 48900 // Zircuit Mainnet
- | 49797 // Energi Testnet
- | 50 // XDC Network
+ | 2037 // Kiwi Subnet
+ | 255 // Kroma
+ | 2358 // Kroma Sepolia
+ | 10849 // Lamina1
+ | 10850 // Lamina1 Identity
+ | 767368 // Lamina1 Identity Testnet
+ | 764984 // Lamina1 Testnet
+ | 1891 // Lightlink Pegasus Testnet
+ | 1890 // Lightlink Phoenix Mainnet
+ | 59144 // Linea
+ | 59141 // Linea Sepolia
+ | 1135 // Lisk
+ | 957 // Lyra Chain
+ | 22776 // MAP Protocol
+ | 212 // MAPO Makalu
| 5000 // Mantle
| 5003 // Mantle Sepolia Testnet
- | 51 // XDC Apothem Network
- | 5115 // Citrea Testnet
- | 534 // Candle
- | 534351 // Scroll Sepolia Testnet
- | 534352 // Scroll
- | 53935 // DFK Chain
- | 54211 // Haqq Chain Testnet
- | 56 // BNB Smart Chain Mainnet
- | 560048 // Hoodi testnet
- | 57 // Syscoin Mainnet
- | 570 // Rollux Mainnet
- | 5700 // Syscoin Tanenbaum Testnet
- | 57000 // Rollux Testnet
- | 5845 // Tangle
- | 59141 // Linea Sepolia
- | 59144 // Linea
- | 592 // Astar
+ | 7078815900 // Mekong
+ | 333000333 // Meld
+ | 222000222 // Kanazawa
+ | 4200 // Merlin Mainnet
+ | 82 // Meter Mainnet
+ | 83 // Meter Testnet
+ | 1088 // Metis Andromeda Mainnet
| 59902 // Metis Sepolia Testnet
- | 61 // Ethereum Classic
- | 6119 // UPTN
- | 62320 // Celo Baklava Testnet
+ | 31612 // Mezo
+ | 9996 // Mind Smart Chain Mainnet
+ | 9977 // Mind Smart Chain Testnet
+ | 34443 // Mode
+ | 919 // Mode Testnet
+ | 1287 // Moonbase Alpha
+ | 1284 // Moonbeam
+ | 1285 // Moonriver
| 62621 // MultiVAC Mainnet
- | 62831 // PLYR TAU Testnet
- | 6321 // Aura Euphoria Testnet
- | 6322 // Aura Mainnet
- | 641230 // Bear Network Chain Mainnet
- | 648 // Endurance Smart Chain Mainnet
- | 660279 // Xai Mainnet
- | 666666666 // Degen Chain
+ | 10 // OP Mainnet
+ | 11155420 // OP Sepolia Testnet
+ | 42262 // Oasis Emerald
+ | 42261 // Oasis Emerald Testnet
+ | 23294 // Oasis Sapphire
+ | 23295 // Oasis Sapphire Testnet
+ | 311752642 // OneLedger Mainnet
+ | 4216137055 // OneLedger Testnet Frankenstein
+ | 970 // Oort Mainnet
+ | 28528 // Optimism Bedrock (Goerli Alpha Testnet)
+ | 420 // Optimism Goerli Testnet
| 69 // Optimism Kovan
- | 690 // Redstone
- | 7000 // ZetaChain Mainnet
- | 7001 // ZetaChain Testnet
- | 7078815900 // Mekong
- | 710420 // Tiltyard Mainnet Subnet
- | 71401 // Godwoken Testnet v1
- | 71402 // Godwoken Mainnet
- | 7171 // Bitrock Mainnet
- | 7200 // exSat Mainnet
- | 723107 // TixChain Testnet
- | 73799 // Energy Web Volta Testnet
- | 764984 // Lamina1 Testnet
- | 7668 // The Root Network - Mainnet
- | 7672 // The Root Network - Porcini Testnet
- | 767368 // Lamina1 Identity Testnet
+ | 4000 // Ozone Chain Mainnet
+ | 16180 // PLYR PHI
+ | 62831 // PLYR TAU Testnet
+ | 99 // POA Network Core
| 77 // POA Network Sokol
- | 7700 // Canto
- | 7701 // Canto Tesnet
- | 7771 // Bitrock Testnet
- | 7777777 // Zora
- | 78430 // Amplify Subnet
- | 78431 // Bulletin Subnet
- | 78432 // Conduit Subnet
- | 8 // Ubiq
- | 80001 // Mumbai
+ | 11297108109 // Palm
+ | 11297108099 // Palm Testnet
+ | 13381 // Phoenix Mainnet
+ | 2206132 // PlatON Dev Testnet2
+ | 210425 // PlatON Mainnet
+ | 12898 // PlayFair Testnet Subnet
| 80002 // Amoy
- | 82 // Meter Mainnet
- | 8217 // Kaia Mainnet
- | 83 // Meter Testnet
- | 839999 // exSat Testnet
+ | 137 // Polygon Mainnet
+ | 80001 // Mumbai
+ | 1101 // Polygon zkEVM
+ | 2442 // Polygon zkEVM Cardona Testnet
+ | 16969696 // Privix Chain Mainnet
+ | 369 // PulseChain
+ | 35441 // Q Mainnet
+ | 35443 // Q Testnet
+ | 690 // Redstone
+ | 1433 // Rikeza Network Mainnet
+ | 570 // Rollux Mainnet
+ | 57000 // Rollux Testnet
+ | 2020 // Ronin Mainnet
+ | 30 // Rootstock Mainnet
+ | 534352 // Scroll
+ | 534351 // Scroll Sepolia Testnet
+ | 336 // Shiden
+ | 2044 // Shrapnel Subnet
+ | 2038 // Shrapnel Testnet
+ | 111000 // Siberium Test Network
+ | 19 // Songbird Canary-Network
+ | 1516 // Story Odyssey Testnet
+ | 105105 // Stratis Mainnet
+ | 205205 // Auroria Testnet
+ | 2048 // Stratos
+ | 2047 // Stratos Testnet
+ | 5330 // Superseed
+ | 1291 // Swisstronik Testnet
+ | 1149 // Symplexia Smart Chain
+ | 57 // Syscoin Mainnet
+ | 5700 // Syscoin Tanenbaum Testnet
+ | 167000 // Taiko Alethia
+ | 167006 // Taiko Eldfell L3
+ | 167005 // Taiko Grimsvotn L2
+ | 5845 // Tangle
| 841 // Taraxa Mainnet
| 842 // Taraxa Testnet
- | 8453 // Base
- | 84531 // Base Goerli Testnet
- | 84532 // Base Sepolia Testnet
+ | 2017 // Adiri
+ | 40 // Telos EVM Mainnet
+ | 41 // Telos EVM Testnet
+ | 7668 // The Root Network - Mainnet
+ | 7672 // The Root Network - Porcini Testnet
+ | 710420 // Tiltyard Mainnet Subnet
+ | 1127469 // Tiltyard Subnet
+ | 723107 // TixChain Testnet
+ | 6119 // UPTN
+ | 8 // Ubiq
+ | 130 // Unichain
+ | 100009 // VeChain
+ | 100010 // VeChain Testnet
+ | 106 // Velas EVM Mainnet
+ | 11111 // WAGMI
| 888 // Wanchain
- | 9000 // Evmos Testnet
- | 9001 // Evmos
- | 919 // Mode Testnet
- | 957 // Lyra Chain
- | 96 // KUB Mainnet
- | 97 // BNB Smart Chain Testnet
- | 970 // Oort Mainnet
- | 99 // POA Network Core
- | 9977 // Mind Smart Chain Testnet
| 999 // Wanchain Testnet
- | 9996 // Mind Smart Chain Mainnet
+ | 51 // XDC Apothem Network
+ | 50 // XDC Network
+ | 660279 // Xai Mainnet
+ | 37714555429 // Xai Testnet v2
+ | 202401 // YMTECH-BESU Testnet
+ | 42766 // ZKFair Mainnet
+ | 383414847825 // Zeniq
+ | 7000 // ZetaChain Mainnet
+ | 7001 // ZetaChain Testnet
+ | 32769 // Zilliqa 2
+ | 32770 // Zilliqa 2 EVM proto-mainnet
+ | 33103 // Zilliqa 2 EVM proto-testnet
+ | 33101 // Zilliqa 2 Testnet
+ | 48898 // Zircuit Garfield Testnet
+ | 48900 // Zircuit Mainnet
+ | 48899 // Zircuit Testnet
+ | 7777777 // Zora
| 999999999 // Zora Sepolia Testnet
+ | 7200 // exSat Mainnet
+ | 839999 // exSat Testnet
+ | 3338 // peaq
+ | 300 // zkSync Sepolia Testnet
diff --git a/packages/cli/src/utils/getAddressDocString.ts b/packages/cli/src/utils/getAddressDocString.ts
index d0e137928c..efe04f6b7c 100644
--- a/packages/cli/src/utils/getAddressDocString.ts
+++ b/packages/cli/src/utils/getAddressDocString.ts
@@ -19,23 +19,23 @@ export function getAddressDocString(parameters: {
if (Object.keys(address).length === 1)
return `* ${getLink({
- address: address[Number.parseInt(Object.keys(address)[0]!)]!,
- chainId: Number.parseInt(Object.keys(address)[0]!),
+ address: address[Number.parseInt(Object.keys(address)[0]!, 10)]!,
+ chainId: Number.parseInt(Object.keys(address)[0]!, 10),
})}`
const addresses = Object.entries(address).filter(
- (x) => chainMap[Number.parseInt(x[0])],
+ (x) => chainMap[Number.parseInt(x[0], 10)],
)
if (addresses.length === 0) return ''
if (addresses.length === 1 && addresses[0])
return `* ${getLink({
address: addresses[0][1],
- chainId: Number.parseInt(addresses[0][0])!,
+ chainId: Number.parseInt(addresses[0][0], 10)!,
})}`
return dedent`
${addresses.reduce((prev, curr) => {
- const chainId = Number.parseInt(curr[0])
+ const chainId = Number.parseInt(curr[0], 10)
const address = curr[1]
return `${prev}\n* - ${getLink({ address, chainId })}`
}, '')}
diff --git a/packages/cli/src/utils/loadEnv.ts b/packages/cli/src/utils/loadEnv.ts
index d7ffa99919..8a1f26c85f 100644
--- a/packages/cli/src/utils/loadEnv.ts
+++ b/packages/cli/src/utils/loadEnv.ts
@@ -1,15 +1,11 @@
-import { parse } from 'dotenv'
-import { expand } from 'dotenv-expand'
-
import { existsSync, readFileSync, statSync } from 'node:fs'
import { dirname, join } from 'node:path'
+import { parse } from 'dotenv'
+import { expand } from 'dotenv-expand'
// https://github.com/vitejs/vite/blob/main/packages/vite/src/node/env.ts#L7
export function loadEnv(
- config: {
- mode?: string
- envDir?: string
- } = {},
+ config: { mode?: string; envDir?: string } = {},
): Record {
const mode = config.mode
if (mode === 'local') {
diff --git a/packages/cli/src/version.ts b/packages/cli/src/version.ts
index 4f138388f5..1b52c57d4e 100644
--- a/packages/cli/src/version.ts
+++ b/packages/cli/src/version.ts
@@ -1 +1 @@
-export const version = '2.2.1'
+export const version = '2.8.0'
diff --git a/packages/cli/test/constants.ts b/packages/cli/test/constants.ts
index 6d3f243a92..9b84c5bb1b 100644
--- a/packages/cli/test/constants.ts
+++ b/packages/cli/test/constants.ts
@@ -1,4 +1,4 @@
-import { parseAbi } from 'abitype'
+import { parseAbi } from 'viem'
export const wagmiAbi = parseAbi([
'constructor()',
diff --git a/packages/cli/test/setup.ts b/packages/cli/test/setup.ts
index d2eed4a5e5..4f926cab74 100644
--- a/packages/cli/test/setup.ts
+++ b/packages/cli/test/setup.ts
@@ -21,17 +21,16 @@ vi.mock('nanospinner', async (importOriginal) => {
return {
...spinner,
start(text = initialText) {
- // biome-ignore lint/suspicious/noConsoleLog: console.log is used for logging
console.log(`- ${text}`)
spinner.start(text)
currentText = text
},
success(text = currentText) {
- // biome-ignore lint/suspicious/noConsoleLog: console.log is used for logging
console.log(`√ ${text}`)
spinner.success(text)
},
error(text = currentText) {
+ // biome-ignore lint/suspicious/noConsole: logging error
console.error(`× ${text}`)
spinner.error(text)
},
diff --git a/packages/cli/test/utils.ts b/packages/cli/test/utils.ts
index 4ea6c6051e..b3e76bf8e3 100644
--- a/packages/cli/test/utils.ts
+++ b/packages/cli/test/utils.ts
@@ -1,7 +1,7 @@
import { spawnSync } from 'node:child_process'
import { cp, mkdir, symlink, writeFile } from 'node:fs/promises'
import fixtures from 'fixturez'
-import { http, HttpResponse } from 'msw'
+import { HttpResponse, http } from 'msw'
import * as path from 'pathe'
import { vi } from 'vitest'
@@ -19,13 +19,7 @@ export async function createFixture<
TFiles extends { [filename: string]: string | Json } & {
tsconfig?: true
},
->(
- config: {
- copyNodeModules?: boolean
- dir?: string
- files?: TFiles
- } = {},
-) {
+>(config: { copyNodeModules?: boolean; dir?: string; files?: TFiles } = {}) {
const dir = config.dir ?? f.temp()
await mkdir(dir, { recursive: true })
@@ -130,6 +124,7 @@ export function watchConsole() {
}
}
return {
+ // biome-ignore lint/suspicious/noConsole: logging
debug: console.debug,
info: vi.spyOn(console, 'info').mockImplementation(handleOutput('info')),
log: vi.spyOn(console, 'log').mockImplementation(handleOutput('log')),
@@ -167,7 +162,6 @@ export async function typecheck(project: string) {
}
}
-export const baseUrl = 'https://api.etherscan.io/v2/api'
export const apiKey = 'abc'
export const invalidApiKey = 'xyz'
export const address = '0xaf0326d92b97df1221759476b072abfd8084f9be'
@@ -178,115 +172,117 @@ export const unverifiedContractAddress =
'0xA0Cf798816D4b9b9866b5330EEa46a18382f251e'
export const timeoutAddress = '0xecb504d39723b0be0e3a9aa33d646642d1051ee1'
-export const handlers = [
- http.get(baseUrl, async ({ request }) => {
- const url = new URL(request.url)
- const search = url.search.replace(/^\?chainId=\d&/, '?')
+export function getHandlers(baseUrl = 'https://api.etherscan.io/v2/api') {
+ return [
+ http.get(baseUrl, async ({ request }) => {
+ const url = new URL(request.url)
+ const search = url.search.replace(/^\?chainId=\d&/, '?')
- if (
- search ===
- `?module=contract&action=getabi&address=${unverifiedContractAddress}&apikey=${apiKey}`
- )
- return HttpResponse.json({
- status: '0',
- message: 'NOTOK',
- result: 'Contract source code not verified',
- })
+ if (
+ search ===
+ `?module=contract&action=getabi&address=${unverifiedContractAddress}&apikey=${apiKey}`
+ )
+ return HttpResponse.json({
+ status: '0',
+ message: 'NOTOK',
+ result: 'Contract source code not verified',
+ })
- if (
- search ===
- `?module=contract&action=getabi&address=${timeoutAddress}&apikey=${invalidApiKey}`
- )
- return HttpResponse.json({
- status: '0',
- message: 'NOTOK',
- result: 'Invalid API Key',
- })
+ if (
+ search ===
+ `?module=contract&action=getabi&address=${timeoutAddress}&apikey=${invalidApiKey}`
+ )
+ return HttpResponse.json({
+ status: '0',
+ message: 'NOTOK',
+ result: 'Invalid API Key',
+ })
- if (
- search ===
- `?module=contract&action=getabi&address=${address}&apikey=${apiKey}`
- )
- return HttpResponse.json({
- status: '1',
- message: 'OK',
- result:
- '[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"}]',
- })
+ if (
+ search ===
+ `?module=contract&action=getabi&address=${address}&apikey=${apiKey}`
+ )
+ return HttpResponse.json({
+ status: '1',
+ message: 'OK',
+ result:
+ '[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"}]',
+ })
- if (
- search ===
- `?module=contract&action=getabi&address=${timeoutAddress}&apikey=${apiKey}`
- ) {
- await new Promise((resolve) => setTimeout(resolve, 10_000))
- return HttpResponse.json({})
- }
+ if (
+ search ===
+ `?module=contract&action=getabi&address=${timeoutAddress}&apikey=${apiKey}`
+ ) {
+ await new Promise((resolve) => setTimeout(resolve, 10_000))
+ return HttpResponse.json({})
+ }
- if (
- search ===
- `?module=contract&action=getabi&address=${implementationAddress}&apikey=${apiKey}`
- )
- return HttpResponse.json({
- status: '1',
- message: 'OK',
- result:
- '[{"constant":false,"inputs":[{"name":"newImplementation","type":"address"}],"name":"upgradeTo","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"newImplementation","type":"address"},{"name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"implementation","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"newAdmin","type":"address"}],"name":"changeAdmin","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"admin","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_implementation","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":false,"name":"previousAdmin","type":"address"},{"indexed":false,"name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"implementation","type":"address"}],"name":"Upgraded","type":"event"}]',
- })
+ if (
+ search ===
+ `?module=contract&action=getabi&address=${implementationAddress}&apikey=${apiKey}`
+ )
+ return HttpResponse.json({
+ status: '1',
+ message: 'OK',
+ result:
+ '[{"constant":false,"inputs":[{"name":"newImplementation","type":"address"}],"name":"upgradeTo","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"newImplementation","type":"address"},{"name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"implementation","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"newAdmin","type":"address"}],"name":"changeAdmin","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"admin","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_implementation","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":false,"name":"previousAdmin","type":"address"},{"indexed":false,"name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"implementation","type":"address"}],"name":"Upgraded","type":"event"}]',
+ })
- if (
- search ===
- `?module=contract&action=getsourcecode&address=${proxyAddress}&apikey=${apiKey}`
- )
- return HttpResponse.json({
- status: '1',
- message: 'OK',
- result: [
- {
- SourceCode: '...',
- ABI: '[{"constant":false,"inputs":[{"name":"newImplementation","type":"address"}],"name":"upgradeTo","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"newImplementation","type":"address"},{"name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"implementation","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"newAdmin","type":"address"}],"name":"changeAdmin","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"admin","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_implementation","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":false,"name":"previousAdmin","type":"address"},{"indexed":false,"name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"implementation","type":"address"}],"name":"Upgraded","type":"event"}]',
- ContractName: 'FiatTokenProxy',
- CompilerVersion: 'v0.4.24+commit.e67f0147',
- OptimizationUsed: '0',
- Runs: '200',
- ConstructorArguments:
- '0000000000000000000000000882477e7895bdc5cea7cb1552ed914ab157fe56',
- EVMVersion: 'Default',
- Library: '',
- LicenseType: '',
- Proxy: '1',
- Implementation: '0x43506849d7c04f9138d1a2050bbf3a0c054402dd',
- SwarmSource:
- 'bzzr://a4a547cfc7202c5acaaae74d428e988bc62ad5024eb0165532d3a8f91db4ed24',
- },
- ],
- })
+ if (
+ search ===
+ `?module=contract&action=getsourcecode&address=${proxyAddress}&apikey=${apiKey}`
+ )
+ return HttpResponse.json({
+ status: '1',
+ message: 'OK',
+ result: [
+ {
+ SourceCode: '...',
+ ABI: '[{"constant":false,"inputs":[{"name":"newImplementation","type":"address"}],"name":"upgradeTo","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"newImplementation","type":"address"},{"name":"data","type":"bytes"}],"name":"upgradeToAndCall","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"implementation","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"newAdmin","type":"address"}],"name":"changeAdmin","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"admin","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_implementation","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"payable":true,"stateMutability":"payable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":false,"name":"previousAdmin","type":"address"},{"indexed":false,"name":"newAdmin","type":"address"}],"name":"AdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"implementation","type":"address"}],"name":"Upgraded","type":"event"}]',
+ ContractName: 'FiatTokenProxy',
+ CompilerVersion: 'v0.4.24+commit.e67f0147',
+ OptimizationUsed: '0',
+ Runs: '200',
+ ConstructorArguments:
+ '0000000000000000000000000882477e7895bdc5cea7cb1552ed914ab157fe56',
+ EVMVersion: 'Default',
+ Library: '',
+ LicenseType: '',
+ Proxy: '1',
+ Implementation: '0x43506849d7c04f9138d1a2050bbf3a0c054402dd',
+ SwarmSource:
+ 'bzzr://a4a547cfc7202c5acaaae74d428e988bc62ad5024eb0165532d3a8f91db4ed24',
+ },
+ ],
+ })
- if (
- search ===
- `?module=contract&action=getsourcecode&address=${address}&apikey=${apiKey}`
- )
- return HttpResponse.json({
- status: '1',
- message: 'OK',
- result: [
- {
- SourceCode: '...',
- ABI: '[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"}]',
- ContractName: 'WagmiMintExample',
- CompilerVersion: 'v0.8.11+commit.d7f03943',
- OptimizationUsed: '1',
- Runs: '10000',
- ConstructorArguments: '',
- EVMVersion: 'Default',
- Library: '',
- LicenseType: '',
- Proxy: '0',
- Implementation: '',
- SwarmSource: '',
- },
- ],
- })
+ if (
+ search ===
+ `?module=contract&action=getsourcecode&address=${address}&apikey=${apiKey}`
+ )
+ return HttpResponse.json({
+ status: '1',
+ message: 'OK',
+ result: [
+ {
+ SourceCode: '...',
+ ABI: '[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":true,"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"approve","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mint","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"_data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"transferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"}]',
+ ContractName: 'WagmiMintExample',
+ CompilerVersion: 'v0.8.11+commit.d7f03943',
+ OptimizationUsed: '1',
+ Runs: '10000',
+ ConstructorArguments: '',
+ EVMVersion: 'Default',
+ Library: '',
+ LicenseType: '',
+ Proxy: '0',
+ Implementation: '',
+ SwarmSource: '',
+ },
+ ],
+ })
- throw new Error(`Unhandled request: ${search}`)
- }),
-]
+ throw new Error(`Unhandled request: ${search}`)
+ }),
+ ]
+}
diff --git a/packages/connectors/CHANGELOG.md b/packages/connectors/CHANGELOG.md
index 6da26192bc..33e3572bb1 100644
--- a/packages/connectors/CHANGELOG.md
+++ b/packages/connectors/CHANGELOG.md
@@ -1,5 +1,364 @@
# @wagmi/connectors
+## 7.1.2
+
+### Patch Changes
+
+- Updated dependencies [[`4fefa57`](https://github.com/wevm/wagmi/commit/4fefa576014820b454344b579282ddecde5c7994)]:
+ - @wagmi/core@3.2.2
+
+## 7.1.1
+
+### Patch Changes
+
+- Updated dependencies [[`a373b50`](https://github.com/wevm/wagmi/commit/a373b504f2ba199ca63ec0da6138ad1aa12a3a8f)]:
+ - @wagmi/core@3.2.1
+
+## 7.1.0
+
+### Patch Changes
+
+- Updated dependencies [[`2ee3f55`](https://github.com/wevm/wagmi/commit/2ee3f559a2637c7aab3fca6c7d196cf238ecd63d)]:
+ - @wagmi/core@3.2.0
+
+## 7.0.7
+
+### Patch Changes
+
+- Updated dependencies [[`14989e4`](https://github.com/wevm/wagmi/commit/14989e425a36b765a6a24e5abf1782c2a26c70db)]:
+ - @wagmi/core@3.1.0
+
+## 7.0.6
+
+### Patch Changes
+
+- Updated dependencies [[`a5c4381`](https://github.com/wevm/wagmi/commit/a5c4381563374018dca0074017b21181ac027e9a)]:
+ - @wagmi/core@3.0.2
+
+## 7.0.5
+
+### Patch Changes
+
+- Fixed published exports. ([`ed86500`](https://github.com/wevm/wagmi/commit/ed86500fbd56e5f543cb04e990b2dadc08d8b3b5))
+
+## 7.0.4
+
+### Patch Changes
+
+- Fixed internal dynamic imports when using Webpack ([#4911](https://github.com/wevm/wagmi/pull/4911))
+
+## 7.0.3
+
+### Patch Changes
+
+- Updated dependencies [[`058c8c1`](https://github.com/wevm/wagmi/commit/058c8c18459a69a4aa2141e34640273a06a819f4)]:
+ - @wagmi/core@3.0.1
+
+## 7.0.2
+
+### Patch Changes
+
+- Fixed account ordering in `baseAccount` connection response ([#4882](https://github.com/wevm/wagmi/pull/4882))
+
+## 7.0.1
+
+### Patch Changes
+
+- Fixed `baseAccount` reconnect behavior ([#4884](https://github.com/wevm/wagmi/pull/4884))
+
+## 7.0.0
+
+### Major Changes
+
+- All connector dependencies are now optional peer dependencies. This means that if you want to use a specific connector, you need to install its required dependencies. ([#4857](https://github.com/wevm/wagmi/pull/4857))
+
+ #### baseAccount
+
+ [`baseAccount`](https://wagmi.sh/core/api/connectors/baseAccount) requires `@base-org/account`
+
+ ```
+ pnpm add @base-org/account@~2.4.0
+ ```
+
+ #### coinbaseWallet
+
+ [`coinbaseWallet`](https://wagmi.sh/core/api/connectors/coinbaseWallet) requires `@coinbase/wallet-sdk`
+
+ ```
+ pnpm add @coinbase/wallet-sdk@~4.3.6
+ ```
+
+ #### gemini
+
+ [`gemini`](https://wagmi.sh/core/api/connectors/gemini) requires `@gemini-wallet/core`
+
+ ```
+ pnpm add @gemini-wallet/core@~0.3.1
+ ```
+
+ #### metaMask
+
+ [`metaMask`](https://wagmi.sh/core/api/connectors/metaMask) requires `@metamask/sdk`
+
+ ```
+ pnpm add @metamask/sdk@~0.33.1
+ ```
+
+ #### porto
+
+ [`porto`](https://wagmi.sh/core/api/connectors/porto) requires `porto`
+
+ ```
+ pnpm add porto@~0.2.35
+ ```
+
+ #### safe
+
+ [`safe`](https://wagmi.sh/core/api/connectors/safe) requires `@safe-global/safe-apps-provider` and `@safe-global/safe-apps-sdk`
+
+ ```
+ pnpm add @safe-global/safe-apps-provider@~0.18.6 @safe-global/safe-apps-sdk@~9.1.0
+ ```
+
+ #### walletConnect
+
+ [`walletConnect`](https://wagmi.sh/core/api/connectors/walletConnect) requires `walletconnect/ethereum-provider`
+
+ ```
+ pnpm add @walletconnect/ethereum-provider@~2.21.1
+ ```
+
+### Patch Changes
+
+- Updated dependencies [[`73e7326`](https://github.com/wevm/wagmi/commit/73e7326ac21303d7790765c78a7076b319b2ad26)]:
+ - @wagmi/core@3.0.0
+
+## 6.2.0
+
+### Minor Changes
+
+- Added support for `'wallet_connect'` capabilities to `baseAccount` connector ([#4877](https://github.com/wevm/wagmi/pull/4877))
+
+## 6.1.4
+
+### Patch Changes
+
+- Bumped Gemini package version ([`2ddb506`](https://github.com/wevm/wagmi/commit/2ddb506b67fcb2abb464765d2af88df2eb58de60))
+
+## 6.1.3
+
+### Patch Changes
+
+- Added warning to `walletConnect` about vulnerability and relicensing. ([`65cf154`](https://github.com/wevm/wagmi/commit/65cf1544d65bfb1fb830c405a371e8cd3c3fb73e))
+
+## 6.1.2
+
+### Patch Changes
+
+- Bumped connector deps ([#4843](https://github.com/wevm/wagmi/pull/4843))
+
+## 6.1.1
+
+### Patch Changes
+
+- Bumped Porto version ([`990dd23`](https://github.com/wevm/wagmi/commit/990dd2339e96b302931056e0fb898bd2dd42a04d))
+
+## 6.1.0
+
+### Minor Changes
+
+- Added `getPortoInstance` method to `porto`. ([#4837](https://github.com/wevm/wagmi/pull/4837))
+
+## 6.0.1
+
+### Patch Changes
+
+- Updated dependencies [[`74100b0`](https://github.com/wevm/wagmi/commit/74100b0dea2dfe7b057fdbe1660596554c70642e)]:
+ - @wagmi/core@2.22.1
+
+## 6.0.0
+
+### Patch Changes
+
+- Updated dependencies [[`ebb2352`](https://github.com/wevm/wagmi/commit/ebb2352375e05e52d0bcf6ae1a60ac4e798bf29f)]:
+ - @wagmi/core@2.22.0
+
+## 5.11.2
+
+### Patch Changes
+
+- Added `chainId` parameter on `walletConnect#getProvider` ([#4806](https://github.com/wevm/wagmi/pull/4806))
+
+- Updated dependencies [[`866aeb0`](https://github.com/wevm/wagmi/commit/866aeb0e6361ef9114246e50149c1077bc05bf10)]:
+ - @wagmi/core@2.21.2
+
+## 5.11.1
+
+### Patch Changes
+
+- Updated `porto`. ([`41eb70e`](https://github.com/wevm/wagmi/commit/41eb70e072774b282053a5e98669a7d01c0e2438))
+
+- Pulled `porto` connector implementation. ([#4801](https://github.com/wevm/wagmi/pull/4801))
+
+## 5.11.0
+
+### Minor Changes
+
+- Added `porto` connector. ([#4794](https://github.com/wevm/wagmi/pull/4794))
+
+## 5.10.2
+
+### Patch Changes
+
+- Updated dependencies [[`72b703a`](https://github.com/wevm/wagmi/commit/72b703ab379c74ecf88f637cf47f31786c823a48)]:
+ - @wagmi/core@2.21.1
+
+## 5.10.1
+
+### Patch Changes
+
+- Bumped MetaMask SDK version in accordance with [security advisory](https://github.com/advisories/GHSA-qj3p-xc97-xw74). ([`5937456`](https://github.com/wevm/wagmi/commit/59374562f2c3a41245687eb1c29ee8023737c7cc))
+
+## 5.10.0
+
+### Minor Changes
+
+- [#4784](https://github.com/wevm/wagmi/pull/4784) [`8736133a13eb82099e20468b735525a266fdfd6c`](https://github.com/wevm/wagmi/commit/8736133a13eb82099e20468b735525a266fdfd6c) Thanks [@tmm](https://github.com/tmm)! - Added `withCapabilities` option to `connect` for exposing response capabilities.
+
+### Patch Changes
+
+- Updated dependencies [[`8736133a13eb82099e20468b735525a266fdfd6c`](https://github.com/wevm/wagmi/commit/8736133a13eb82099e20468b735525a266fdfd6c)]:
+ - @wagmi/core@2.21.0
+
+## 5.9.9
+
+### Patch Changes
+
+- Updated dependencies [[`ce06e137e7bfaf000464b1cecd6c86e19a66ebcf`](https://github.com/wevm/wagmi/commit/ce06e137e7bfaf000464b1cecd6c86e19a66ebcf)]:
+ - @wagmi/core@2.20.3
+
+## 5.9.8
+
+### Patch Changes
+
+- [#4691](https://github.com/wevm/wagmi/pull/4691) [`a03da817a388646c9b4885792101a67eef3616e7`](https://github.com/wevm/wagmi/commit/a03da817a388646c9b4885792101a67eef3616e7) Thanks [@frolic](https://github.com/frolic)! - Fixed `walletConnect#connect` by moving chain switch directly inside instead of relying on `getProvider`.
+
+## 5.9.7
+
+### Patch Changes
+
+- Updated dependencies [[`986b96427a4bb743d2673dfbc7e8cb5041316db3`](https://github.com/wevm/wagmi/commit/986b96427a4bb743d2673dfbc7e8cb5041316db3)]:
+ - @wagmi/core@2.20.2
+
+## 5.9.6
+
+### Patch Changes
+
+- Updated dependencies [[`d4c367ca46c508598c997cf229a31593a1e2b8b8`](https://github.com/wevm/wagmi/commit/d4c367ca46c508598c997cf229a31593a1e2b8b8)]:
+ - @wagmi/core@2.20.1
+
+## 5.9.5
+
+### Patch Changes
+
+- Updated dependencies [[`a13aa2b68890f180f6ac3f741cbb9817494cb66c`](https://github.com/wevm/wagmi/commit/a13aa2b68890f180f6ac3f741cbb9817494cb66c)]:
+ - @wagmi/core@2.20.0
+
+## 5.9.4
+
+### Patch Changes
+
+- [#4764](https://github.com/wevm/wagmi/pull/4764) [`f4039419b83b52b2984de149db85c11f503ffe39`](https://github.com/wevm/wagmi/commit/f4039419b83b52b2984de149db85c11f503ffe39) Thanks [@mikelxc](https://github.com/mikelxc)! - Updated gemini connector
+
+## 5.9.3
+
+### Patch Changes
+
+- [#4759](https://github.com/wevm/wagmi/pull/4759) [`909324d28c81e15c9df312b277dcff1983fbae4d`](https://github.com/wevm/wagmi/commit/909324d28c81e15c9df312b277dcff1983fbae4d) Thanks [@mikelxc](https://github.com/mikelxc)! - Added Gemini
+
+## 5.9.2
+
+### Patch Changes
+
+- Updated dependencies [[`b5f017dbc707729eb0b36d617352be224d1139d4`](https://github.com/wevm/wagmi/commit/b5f017dbc707729eb0b36d617352be224d1139d4)]:
+ - @wagmi/core@2.19.0
+
+## 5.9.1
+
+### Patch Changes
+
+- [`6fbafd425e488dbeee8404162dbeb3c737eeb8cf`](https://github.com/wevm/wagmi/commit/6fbafd425e488dbeee8404162dbeb3c737eeb8cf) Thanks [@jxom](https://github.com/jxom)! - Updated `@base-org/account`
+
+- Updated dependencies [[`6514ba29a5acb918773235fed0238d7d679d06d5`](https://github.com/wevm/wagmi/commit/6514ba29a5acb918773235fed0238d7d679d06d5)]:
+ - @wagmi/core@2.18.1
+
+## 5.9.0
+
+### Minor Changes
+
+- [#4734](https://github.com/wevm/wagmi/pull/4734) [`eac550ae5b49f96a7e3404a6d88adc62d3889013`](https://github.com/wevm/wagmi/commit/eac550ae5b49f96a7e3404a6d88adc62d3889013) Thanks [@jxom](https://github.com/jxom)! - Added `baseAccount` connector.
+
+### Patch Changes
+
+- Updated dependencies [[`eac550ae5b49f96a7e3404a6d88adc62d3889013`](https://github.com/wevm/wagmi/commit/eac550ae5b49f96a7e3404a6d88adc62d3889013)]:
+ - @wagmi/core@2.18.0
+
+## 5.8.6
+
+### Patch Changes
+
+- [#4731](https://github.com/wevm/wagmi/pull/4731) [`e75bd89406e9b6ff5b7d3a7148ab34140fe6352a`](https://github.com/wevm/wagmi/commit/e75bd89406e9b6ff5b7d3a7148ab34140fe6352a) Thanks [@tomiir](https://github.com/tomiir)! - Updated `@coinbase/wallet-sdk` to version 4.3.6
+
+## 5.8.5
+
+### Patch Changes
+
+- Updated dependencies [[`7ce242b549d8cc78e6c319d9ee419693da36704c`](https://github.com/wevm/wagmi/commit/7ce242b549d8cc78e6c319d9ee419693da36704c)]:
+ - @wagmi/core@2.17.3
+
+## 5.8.4
+
+### Patch Changes
+
+- [#4696](https://github.com/wevm/wagmi/pull/4696) [`3a90f358820444a85bb727742b0a16eb943fc361`](https://github.com/wevm/wagmi/commit/3a90f358820444a85bb727742b0a16eb943fc361) Thanks [@tomiir](https://github.com/tomiir)! - Updated @walletconnect/etereum-provider to version 2.21.1
+
+## 5.8.3
+
+### Patch Changes
+
+- [#4660](https://github.com/wevm/wagmi/pull/4660) [`42b1fed58e9ac09da0f8ebf3e9271f98a707aaac`](https://github.com/wevm/wagmi/commit/42b1fed58e9ac09da0f8ebf3e9271f98a707aaac) Thanks [@ganchoradkov](https://github.com/ganchoradkov)! - Updated `@walletconnect/ethereum-provider` version to `2.20.2`
+
+## 5.8.2
+
+### Patch Changes
+
+- Updated dependencies [[`29297a48af72b537173d948ccd2fe37d39914c66`](https://github.com/wevm/wagmi/commit/29297a48af72b537173d948ccd2fe37d39914c66), [`07370106d5fb6b8fe300992d93abf25b3d0eaf57`](https://github.com/wevm/wagmi/commit/07370106d5fb6b8fe300992d93abf25b3d0eaf57)]:
+ - @wagmi/core@2.17.2
+
+## 5.8.1
+
+### Patch Changes
+
+- Updated dependencies [[`01f64e64fa4f85cdd30023903f972f4f9023681f`](https://github.com/wevm/wagmi/commit/01f64e64fa4f85cdd30023903f972f4f9023681f)]:
+ - @wagmi/core@2.17.1
+
+## 5.8.0
+
+### Minor Changes
+
+- [#4644](https://github.com/wevm/wagmi/pull/4644) [`cc5517ff6880bb630f1b201930acc20dd1a0b451`](https://github.com/wevm/wagmi/commit/cc5517ff6880bb630f1b201930acc20dd1a0b451) Thanks [@lukaisailovic](https://github.com/lukaisailovic)! - Updated `@walletconnect/etherereum-provider` to `2.20.0`.
+
+## 5.7.13
+
+### Patch Changes
+
+- [#4622](https://github.com/wevm/wagmi/pull/4622) [`88427b2bcd13ec375ef519e9ad1ccffef9f02a7b`](https://github.com/wevm/wagmi/commit/88427b2bcd13ec375ef519e9ad1ccffef9f02a7b) Thanks [@dan1kov](https://github.com/dan1kov)! - Added `rdns` property to Coinbase Wallet v3 connector
+
+- [#4605](https://github.com/wevm/wagmi/pull/4605) [`3f8b2edc4f237cccff1009bcef03d51ca27a7324`](https://github.com/wevm/wagmi/commit/3f8b2edc4f237cccff1009bcef03d51ca27a7324) Thanks [@chybisov](https://github.com/chybisov)! - Bumped `@safe-global/safe-apps-provider` version to `0.18.6`.
+
+- Updated dependencies [[`799ee4d4b23c2ecd64e3f3668e67634e81939719`](https://github.com/wevm/wagmi/commit/799ee4d4b23c2ecd64e3f3668e67634e81939719)]:
+ - @wagmi/core@2.17.0
+
## 5.7.12
### Patch Changes
diff --git a/packages/connectors/package.json b/packages/connectors/package.json
index 0c085d330e..ce5df566d6 100644
--- a/packages/connectors/package.json
+++ b/packages/connectors/package.json
@@ -1,7 +1,7 @@
{
"name": "@wagmi/connectors",
"description": "Collection of connectors for Wagmi",
- "version": "5.7.12",
+ "version": "7.1.2",
"license": "MIT",
"repository": {
"type": "git",
@@ -9,7 +9,7 @@
"directory": "packages/connectors"
},
"scripts": {
- "build": "pnpm run clean && pnpm run build:esm+types",
+ "build": "pnpm run build:esm+types",
"build:esm+types": "tsc --project tsconfig.build.json --outDir ./dist/esm --declaration --declarationMap --declarationDir ./dist/types",
"check:types": "tsc --noEmit",
"clean": "rm -rf dist tsconfig.tsbuildinfo",
@@ -35,28 +35,63 @@
"./package.json": "./package.json"
},
"peerDependencies": {
+ "@base-org/account": "^2.5.1",
+ "@coinbase/wallet-sdk": "^4.3.6",
+ "@gemini-wallet/core": "~0.3.1",
+ "@metamask/sdk": "~0.33.1",
+ "@safe-global/safe-apps-provider": "~0.18.6",
+ "@safe-global/safe-apps-sdk": "^9.1.0",
"@wagmi/core": "workspace:*",
- "typescript": ">=5.0.4",
+ "@walletconnect/ethereum-provider": "^2.21.1",
+ "porto": "~0.2.35",
+ "typescript": ">=5.7.3",
"viem": "2.x"
},
"peerDependenciesMeta": {
+ "@base-org/account": {
+ "optional": true
+ },
+ "@coinbase/wallet-sdk": {
+ "optional": true
+ },
+ "@gemini-wallet/core": {
+ "optional": true
+ },
+ "@metamask/sdk": {
+ "optional": true
+ },
+ "@safe-global/safe-apps-provider": {
+ "optional": true
+ },
+ "@safe-global/safe-apps-sdk": {
+ "optional": true
+ },
+ "@walletconnect/ethereum-provider": {
+ "optional": true
+ },
+ "porto": {
+ "optional": true
+ },
"typescript": {
"optional": true
}
},
- "dependencies": {
- "@coinbase/wallet-sdk": "4.3.0",
- "@metamask/sdk": "0.32.0",
- "@safe-global/safe-apps-provider": "0.18.6",
- "@safe-global/safe-apps-sdk": "9.1.0",
- "@walletconnect/ethereum-provider": "2.19.2",
- "cbw-sdk": "npm:@coinbase/wallet-sdk@3.9.3"
- },
"devDependencies": {
+ "@base-org/account": "catalog:",
+ "@coinbase/wallet-sdk": "catalog:",
+ "@gemini-wallet/core": "catalog:",
+ "@metamask/sdk": "catalog:",
+ "@safe-global/safe-apps-provider": "catalog:",
+ "@safe-global/safe-apps-sdk": "catalog:",
"@wagmi/core": "workspace:*",
- "msw": "^2.4.9"
+ "@walletconnect/ethereum-provider": "catalog:",
+ "msw": "^2.4.9",
+ "porto": "catalog:"
},
- "contributors": ["awkweb.eth ", "jxom.eth "],
+ "contributors": [
+ "awkweb.eth ",
+ "jxom.eth "
+ ],
"funding": "https://github.com/sponsors/wevm",
"keywords": [
"react",
diff --git a/packages/connectors/src/baseAccount.test.ts b/packages/connectors/src/baseAccount.test.ts
new file mode 100644
index 0000000000..d5fe1a7aa6
--- /dev/null
+++ b/packages/connectors/src/baseAccount.test.ts
@@ -0,0 +1,10 @@
+import { config } from '@wagmi/test'
+import { expect, test } from 'vitest'
+
+import { baseAccount } from './baseAccount.js'
+
+test('setup', () => {
+ const connectorFn = baseAccount({ appName: 'wagmi' })
+ const connector = config._internal.connectors.setup(connectorFn)
+ expect(connector.name).toEqual('Base Account')
+})
diff --git a/packages/connectors/src/baseAccount.ts b/packages/connectors/src/baseAccount.ts
new file mode 100644
index 0000000000..9de7106efd
--- /dev/null
+++ b/packages/connectors/src/baseAccount.ts
@@ -0,0 +1,330 @@
+import type { createBaseAccountSDK, ProviderInterface } from '@base-org/account'
+import {
+ ChainNotConfiguredError,
+ type Connector,
+ createConnector,
+} from '@wagmi/core'
+import type { Mutable, Omit } from '@wagmi/core/internal'
+import {
+ type AddEthereumChainParameter,
+ type Address,
+ getAddress,
+ type Hex,
+ numberToHex,
+ type ProviderRpcError,
+ SwitchChainError,
+ UserRejectedRequestError,
+} from 'viem'
+
+export type BaseAccountParameters = Mutable<
+ Omit<
+ Parameters[0],
+ 'appChainIds' // set via wagmi config
+ >
+>
+
+export function baseAccount(parameters: BaseAccountParameters = {}) {
+ type Provider = ProviderInterface
+ type Properties = {
+ connect(parameters?: {
+ chainId?: number | undefined
+ capabilities?:
+ | {
+ signInWithEthereum?: {
+ chainId?: string | undefined
+ domain?: string | undefined
+ expirationTime?: string | undefined
+ issuedAt?: string | undefined
+ nonce: string
+ notBefore?: string | undefined
+ requestId?: string | undefined
+ resources?: string[] | undefined
+ scheme?: string | undefined
+ statement?: string | undefined
+ uri?: string | undefined
+ version?: string | undefined
+ }
+ [capability: string]: any
+ }
+ | undefined
+ isReconnecting?: boolean | undefined
+ withCapabilities?: withCapabilities | boolean | undefined
+ }): Promise<{
+ accounts: withCapabilities extends true
+ ? readonly {
+ address: Address
+ capabilities: WalletConnectResponseCapabilities
+ }[]
+ : readonly Address[]
+ chainId: number
+ }>
+ }
+ type WalletConnectResponseCapabilities = {
+ signInWithEthereum?: { message: string; signature: Hex } | undefined
+ [capability: string]: any
+ }
+
+ let walletProvider: Provider | undefined
+
+ let accountsChanged: Connector['onAccountsChanged'] | undefined
+ let chainChanged: Connector['onChainChanged'] | undefined
+ let disconnect: Connector['onDisconnect'] | undefined
+
+ return createConnector((config) => ({
+ id: 'baseAccount',
+ name: 'Base Account',
+ rdns: 'app.base.account',
+ type: 'baseAccount',
+ async connect({ chainId, withCapabilities, ...rest } = {}) {
+ try {
+ const provider = await this.getProvider()
+
+ const targetChainId = chainId ?? config.chains[0]?.id
+ if (!targetChainId) throw new ChainNotConfiguredError()
+
+ let { accounts, currentChainId } = await (async () => {
+ if (rest.isReconnecting)
+ return {
+ accounts: (
+ (await provider.request({
+ method: 'eth_accounts',
+ params: [],
+ })) as string[]
+ ).map((x) => ({ address: getAddress(x) })),
+ currentChainId: await this.getChainId(),
+ }
+ const response = (await provider.request({
+ method: 'wallet_connect',
+ params: [
+ {
+ capabilities:
+ 'capabilities' in rest && rest.capabilities
+ ? rest.capabilities
+ : {},
+ chainIds: [
+ numberToHex(targetChainId),
+ ...config.chains
+ .filter((x) => x.id !== targetChainId)
+ .map((x) => numberToHex(x.id)),
+ ],
+ },
+ ],
+ })) as {
+ accounts: {
+ address: Address
+ capabilities?: WalletConnectResponseCapabilities | undefined
+ }[]
+ chainIds: Hex[]
+ }
+ const orderedAccounts = (await provider.request({
+ method: 'eth_accounts',
+ })) as Address[]
+ const accounts = orderedAccounts.map(
+ (account1) =>
+ response.accounts.find(
+ (account2) => account2.address === account1,
+ ) ?? { address: account1 },
+ )
+ return {
+ accounts: accounts.map((account) => ({
+ address: getAddress(account.address),
+ capabilities: account.capabilities ?? {},
+ })),
+ currentChainId: Number(response.chainIds[0]),
+ }
+ })()
+
+ if (!accountsChanged) {
+ accountsChanged = this.onAccountsChanged.bind(this)
+ provider.on('accountsChanged', accountsChanged)
+ }
+ if (!chainChanged) {
+ chainChanged = this.onChainChanged.bind(this)
+ provider.on('chainChanged', chainChanged)
+ }
+ if (!disconnect) {
+ disconnect = this.onDisconnect.bind(this)
+ provider.on('disconnect', disconnect)
+ }
+
+ // Switch to chain if provided
+ if (chainId && currentChainId !== chainId) {
+ const chain = await this.switchChain!({ chainId }).catch((error) => {
+ if (error.code === UserRejectedRequestError.code) throw error
+ return { id: currentChainId }
+ })
+ currentChainId = chain?.id ?? currentChainId
+ }
+
+ return {
+ // TODO(v3): Make `withCapabilities: true` default behavior
+ accounts: (withCapabilities
+ ? accounts
+ : accounts.map((account) => account.address)) as never,
+ chainId: currentChainId,
+ }
+ } catch (error) {
+ if (
+ /(user closed modal|accounts received is empty|user denied account|request rejected)/i.test(
+ (error as Error).message,
+ )
+ )
+ throw new UserRejectedRequestError(error as Error)
+ throw error
+ }
+ },
+ async disconnect() {
+ const provider = await this.getProvider()
+
+ if (accountsChanged) {
+ provider.removeListener('accountsChanged', accountsChanged)
+ accountsChanged = undefined
+ }
+ if (chainChanged) {
+ provider.removeListener('chainChanged', chainChanged)
+ chainChanged = undefined
+ }
+ if (disconnect) {
+ provider.removeListener('disconnect', disconnect)
+ disconnect = undefined
+ }
+
+ provider.disconnect()
+ },
+ async getAccounts() {
+ const provider = await this.getProvider()
+ return (
+ (await provider.request({
+ method: 'eth_accounts',
+ })) as string[]
+ ).map((x) => getAddress(x))
+ },
+ async getChainId() {
+ const provider = await this.getProvider()
+ const chainId = (await provider.request({
+ method: 'eth_chainId',
+ })) as Hex
+ return Number(chainId)
+ },
+ async getProvider() {
+ if (!walletProvider) {
+ const preference = (() => {
+ if (typeof parameters.preference === 'string')
+ return { options: parameters.preference }
+ return {
+ ...parameters.preference,
+ options: parameters.preference?.options ?? 'all',
+ }
+ })()
+
+ const { createBaseAccountSDK } = await (() => {
+ // safe webpack optional peer dependency dynamic import
+ try {
+ return import('@base-org/account')
+ } catch {
+ throw new Error('dependency "@base-org/account" not found')
+ }
+ })()
+ const sdk = createBaseAccountSDK({
+ ...parameters,
+ appChainIds: config.chains.map((x) => x.id),
+ preference,
+ })
+
+ walletProvider = sdk.getProvider()
+ }
+
+ return walletProvider
+ },
+ async isAuthorized() {
+ try {
+ const accounts = await this.getAccounts()
+ return !!accounts.length
+ } catch {
+ return false
+ }
+ },
+ async switchChain({ addEthereumChainParameter, chainId }) {
+ const chain = config.chains.find((chain) => chain.id === chainId)
+ if (!chain) throw new SwitchChainError(new ChainNotConfiguredError())
+
+ const provider = await this.getProvider()
+
+ try {
+ await provider.request({
+ method: 'wallet_switchEthereumChain',
+ params: [{ chainId: numberToHex(chain.id) }],
+ })
+ return chain
+ } catch (error) {
+ // Indicates chain is not added to provider
+ if ((error as ProviderRpcError).code === 4902) {
+ try {
+ let blockExplorerUrls: string[] | undefined
+ if (addEthereumChainParameter?.blockExplorerUrls)
+ blockExplorerUrls = addEthereumChainParameter.blockExplorerUrls
+ else
+ blockExplorerUrls = chain.blockExplorers?.default.url
+ ? [chain.blockExplorers?.default.url]
+ : []
+
+ let rpcUrls: readonly string[]
+ if (addEthereumChainParameter?.rpcUrls?.length)
+ rpcUrls = addEthereumChainParameter.rpcUrls
+ else rpcUrls = [chain.rpcUrls.default?.http[0] ?? '']
+
+ const addEthereumChain = {
+ blockExplorerUrls,
+ chainId: numberToHex(chainId),
+ chainName: addEthereumChainParameter?.chainName ?? chain.name,
+ iconUrls: addEthereumChainParameter?.iconUrls,
+ nativeCurrency:
+ addEthereumChainParameter?.nativeCurrency ??
+ chain.nativeCurrency,
+ rpcUrls,
+ } satisfies AddEthereumChainParameter
+
+ await provider.request({
+ method: 'wallet_addEthereumChain',
+ params: [addEthereumChain],
+ })
+
+ return chain
+ } catch (error) {
+ throw new UserRejectedRequestError(error as Error)
+ }
+ }
+
+ throw new SwitchChainError(error as Error)
+ }
+ },
+ onAccountsChanged(accounts) {
+ if (accounts.length === 0) this.onDisconnect()
+ else
+ config.emitter.emit('change', {
+ accounts: accounts.map((x) => getAddress(x)),
+ })
+ },
+ onChainChanged(chain) {
+ const chainId = Number(chain)
+ config.emitter.emit('change', { chainId })
+ },
+ async onDisconnect(_error) {
+ config.emitter.emit('disconnect')
+
+ const provider = await this.getProvider()
+ if (accountsChanged) {
+ provider.removeListener('accountsChanged', accountsChanged)
+ accountsChanged = undefined
+ }
+ if (chainChanged) {
+ provider.removeListener('chainChanged', chainChanged)
+ chainChanged = undefined
+ }
+ if (disconnect) {
+ provider.removeListener('disconnect', disconnect)
+ disconnect = undefined
+ }
+ },
+ }))
+}
diff --git a/packages/connectors/src/coinbaseWallet.test.ts b/packages/connectors/src/coinbaseWallet.test.ts
index 99b141e49b..a551a16568 100644
--- a/packages/connectors/src/coinbaseWallet.test.ts
+++ b/packages/connectors/src/coinbaseWallet.test.ts
@@ -4,7 +4,7 @@ import { expect, expectTypeOf, test } from 'vitest'
import { coinbaseWallet } from './coinbaseWallet.js'
test('setup', () => {
- const connectorFn = coinbaseWallet({ appName: 'wagmi', version: '4' })
+ const connectorFn = coinbaseWallet({ appName: 'wagmi' })
const connector = config._internal.connectors.setup(connectorFn)
expect(connector.name).toEqual('Coinbase Wallet')
diff --git a/packages/connectors/src/coinbaseWallet.ts b/packages/connectors/src/coinbaseWallet.ts
index 630c91261e..25bb63c29c 100644
--- a/packages/connectors/src/coinbaseWallet.ts
+++ b/packages/connectors/src/coinbaseWallet.ts
@@ -1,93 +1,53 @@
import type {
- Preference,
- ProviderInterface,
createCoinbaseWalletSDK,
+ ProviderInterface,
} from '@coinbase/wallet-sdk'
import {
ChainNotConfiguredError,
type Connector,
createConnector,
} from '@wagmi/core'
-import type { Compute, Mutable, Omit } from '@wagmi/core/internal'
-import type {
- CoinbaseWalletProvider as CBW_Provider,
- CoinbaseWalletSDK as CBW_SDK,
-} from 'cbw-sdk'
+import type { Mutable, Omit } from '@wagmi/core/internal'
import {
type AddEthereumChainParameter,
type Address,
+ getAddress,
type Hex,
+ numberToHex,
type ProviderRpcError,
SwitchChainError,
UserRejectedRequestError,
- getAddress,
- numberToHex,
} from 'viem'
-type Version = '3' | '4'
-
-export type CoinbaseWalletParameters =
- version extends '4'
- ? Compute<
- {
- headlessMode?: false | undefined
- /** Coinbase Wallet SDK version */
- version?: version | '3' | undefined
- } & Version4Parameters
- >
- : Compute<
- {
- /**
- * @deprecated `headlessMode` will be removed in the next major version. Upgrade to `version: '4'`.
- */
- headlessMode?: true | undefined
- /**
- * Coinbase Wallet SDK version
- * @deprecated Version 3 will be removed in the next major version. Upgrade to `version: '4'`.
- * @default '4'
- */
- version?: version | '4' | undefined
- } & Version3Parameters
- >
-
-coinbaseWallet.type = 'coinbaseWallet' as const
-export function coinbaseWallet(
- parameters: CoinbaseWalletParameters = {} as any,
-): version extends '4'
- ? ReturnType
- : ReturnType {
- if (parameters.version === '3' || parameters.headlessMode)
- return version3(parameters as Version3Parameters) as any
- return version4(parameters as Version4Parameters) as any
-}
-
-type Version4Parameters = Mutable<
+export type CoinbaseWalletParameters<
+ /** @deprecated remove */
+ _ = unknown,
+> = Mutable<
Omit<
Parameters[0],
- | 'appChainIds' // set via wagmi config
- | 'preference'
- > & {
- // TODO(v3): Remove `Preference['options']`
- /**
- * Preference for the type of wallet to display.
- * @default 'all'
- */
- preference?: Preference['options'] | Compute | undefined
- }
+ 'appChainIds' // set via wagmi config
+ >
>
-function version4(parameters: Version4Parameters) {
+coinbaseWallet.type = 'coinbaseWallet' as const
+export function coinbaseWallet(
+ parameters: CoinbaseWalletParameters = {} as any,
+) {
type Provider = ProviderInterface & {
// for backwards compatibility
close?(): void
}
type Properties = {
- connect(parameters?: {
+ // TODO(v3): Make `withCapabilities: true` default behavior
+ connect(parameters?: {
chainId?: number | undefined
instantOnboarding?: boolean | undefined
isReconnecting?: boolean | undefined
+ withCapabilities?: withCapabilities | boolean | undefined
}): Promise<{
- accounts: readonly Address[]
+ accounts: withCapabilities extends true
+ ? readonly { address: Address }[]
+ : readonly Address[]
chainId: number
}>
}
@@ -103,7 +63,7 @@ function version4(parameters: Version4Parameters) {
name: 'Coinbase Wallet',
rdns: 'com.coinbase.wallet',
type: coinbaseWallet.type,
- async connect({ chainId, ...rest } = {}) {
+ async connect({ chainId, withCapabilities, ...rest } = {}) {
try {
const provider = await this.getProvider()
const accounts = (
@@ -139,7 +99,12 @@ function version4(parameters: Version4Parameters) {
currentChainId = chain?.id ?? currentChainId
}
- return { accounts, chainId: currentChainId }
+ return {
+ accounts: (withCapabilities
+ ? accounts.map((address) => ({ address, capabilities: {} }))
+ : accounts) as never,
+ chainId: currentChainId,
+ }
} catch (error) {
if (
/(user closed modal|accounts received is empty|user denied account|request rejected)/i.test(
@@ -186,20 +151,21 @@ function version4(parameters: Version4Parameters) {
},
async getProvider() {
if (!walletProvider) {
- const preference = (() => {
- if (typeof parameters.preference === 'string')
- return { options: parameters.preference }
- return {
- ...parameters.preference,
- options: parameters.preference?.options ?? 'all',
+ const { createCoinbaseWalletSDK } = await (() => {
+ // safe webpack optional peer dependency dynamic import
+ try {
+ return import('@coinbase/wallet-sdk')
+ } catch {
+ throw new Error('dependency "@coinbase/wallet-sdk" not found')
}
})()
-
- const { createCoinbaseWalletSDK } = await import('@coinbase/wallet-sdk')
const sdk = createCoinbaseWalletSDK({
...parameters,
appChainIds: config.chains.map((x) => x.id),
- preference,
+ preference: {
+ options: 'all',
+ ...(parameters.preference ?? {}),
+ },
})
walletProvider = sdk.getProvider()
@@ -299,248 +265,3 @@ function version4(parameters: Version4Parameters) {
},
}))
}
-
-type Version3Parameters = Mutable<
- Omit<
- ConstructorParameters[0],
- 'reloadOnDisconnect' // remove property since TSDoc says default is `true`
- >
-> & {
- /**
- * Fallback Ethereum JSON RPC URL
- * @default ""
- */
- jsonRpcUrl?: string | undefined
- /**
- * Fallback Ethereum Chain ID
- * @default 1
- */
- chainId?: number | undefined
- /**
- * Whether or not to reload dapp automatically after disconnect.
- * @default false
- */
- reloadOnDisconnect?: boolean | undefined
-}
-
-function version3(parameters: Version3Parameters) {
- const reloadOnDisconnect = false
-
- type Provider = CBW_Provider
-
- let sdk: CBW_SDK | undefined
- let walletProvider: Provider | undefined
-
- let accountsChanged: Connector['onAccountsChanged'] | undefined
- let chainChanged: Connector['onChainChanged'] | undefined
- let disconnect: Connector['onDisconnect'] | undefined
-
- return createConnector((config) => ({
- id: 'coinbaseWalletSDK',
- name: 'Coinbase Wallet',
- rdns: 'com.coinbase.wallet',
- type: coinbaseWallet.type,
- async connect({ chainId } = {}) {
- try {
- const provider = await this.getProvider()
- const accounts = (
- (await provider.request({
- method: 'eth_requestAccounts',
- })) as string[]
- ).map((x) => getAddress(x))
-
- if (!accountsChanged) {
- accountsChanged = this.onAccountsChanged.bind(this)
- provider.on('accountsChanged', accountsChanged)
- }
- if (!chainChanged) {
- chainChanged = this.onChainChanged.bind(this)
- provider.on('chainChanged', chainChanged)
- }
- if (!disconnect) {
- disconnect = this.onDisconnect.bind(this)
- provider.on('disconnect', disconnect)
- }
-
- // Switch to chain if provided
- let currentChainId = await this.getChainId()
- if (chainId && currentChainId !== chainId) {
- const chain = await this.switchChain!({ chainId }).catch((error) => {
- if (error.code === UserRejectedRequestError.code) throw error
- return { id: currentChainId }
- })
- currentChainId = chain?.id ?? currentChainId
- }
-
- return { accounts, chainId: currentChainId }
- } catch (error) {
- if (
- /(user closed modal|accounts received is empty|user denied account)/i.test(
- (error as Error).message,
- )
- )
- throw new UserRejectedRequestError(error as Error)
- throw error
- }
- },
- async disconnect() {
- const provider = await this.getProvider()
-
- if (accountsChanged) {
- provider.removeListener('accountsChanged', accountsChanged)
- accountsChanged = undefined
- }
- if (chainChanged) {
- provider.removeListener('chainChanged', chainChanged)
- chainChanged = undefined
- }
- if (disconnect) {
- provider.removeListener('disconnect', disconnect)
- disconnect = undefined
- }
-
- provider.disconnect()
- provider.close()
- },
- async getAccounts() {
- const provider = await this.getProvider()
- return (
- await provider.request({
- method: 'eth_accounts',
- })
- ).map((x) => getAddress(x))
- },
- async getChainId() {
- const provider = await this.getProvider()
- const chainId = await provider.request({
- method: 'eth_chainId',
- })
- return Number(chainId)
- },
- async getProvider() {
- if (!walletProvider) {
- // Unwrapping import for Vite compatibility.
- // See: https://github.com/vitejs/vite/issues/9703
- const CoinbaseWalletSDK = await (async () => {
- const { default: SDK } = await import('cbw-sdk')
- if (typeof SDK !== 'function' && typeof SDK.default === 'function')
- return SDK.default
- return SDK as unknown as typeof SDK.default
- })()
-
- sdk = new CoinbaseWalletSDK({ ...parameters, reloadOnDisconnect })
-
- // Force types to retrieve private `walletExtension` method from the Coinbase Wallet SDK.
- const walletExtensionChainId = (
- sdk as unknown as {
- get walletExtension(): { getChainId(): number } | undefined
- }
- ).walletExtension?.getChainId()
-
- const chain =
- config.chains.find((chain) =>
- parameters.chainId
- ? chain.id === parameters.chainId
- : chain.id === walletExtensionChainId,
- ) || config.chains[0]
- const chainId = parameters.chainId || chain?.id
- const jsonRpcUrl =
- parameters.jsonRpcUrl || chain?.rpcUrls.default.http[0]
-
- walletProvider = sdk.makeWeb3Provider(jsonRpcUrl, chainId)
- }
-
- return walletProvider
- },
- async isAuthorized() {
- try {
- const accounts = await this.getAccounts()
- return !!accounts.length
- } catch {
- return false
- }
- },
- async switchChain({ addEthereumChainParameter, chainId }) {
- const chain = config.chains.find((chain) => chain.id === chainId)
- if (!chain) throw new SwitchChainError(new ChainNotConfiguredError())
-
- const provider = await this.getProvider()
-
- try {
- await provider.request({
- method: 'wallet_switchEthereumChain',
- params: [{ chainId: numberToHex(chain.id) }],
- })
- return chain
- } catch (error) {
- // Indicates chain is not added to provider
- if ((error as ProviderRpcError).code === 4902) {
- try {
- let blockExplorerUrls: string[] | undefined
- if (addEthereumChainParameter?.blockExplorerUrls)
- blockExplorerUrls = addEthereumChainParameter.blockExplorerUrls
- else
- blockExplorerUrls = chain.blockExplorers?.default.url
- ? [chain.blockExplorers?.default.url]
- : []
-
- let rpcUrls: readonly string[]
- if (addEthereumChainParameter?.rpcUrls?.length)
- rpcUrls = addEthereumChainParameter.rpcUrls
- else rpcUrls = [chain.rpcUrls.default?.http[0] ?? '']
-
- const addEthereumChain = {
- blockExplorerUrls,
- chainId: numberToHex(chainId),
- chainName: addEthereumChainParameter?.chainName ?? chain.name,
- iconUrls: addEthereumChainParameter?.iconUrls,
- nativeCurrency:
- addEthereumChainParameter?.nativeCurrency ??
- chain.nativeCurrency,
- rpcUrls,
- } satisfies AddEthereumChainParameter
-
- await provider.request({
- method: 'wallet_addEthereumChain',
- params: [addEthereumChain],
- })
-
- return chain
- } catch (error) {
- throw new UserRejectedRequestError(error as Error)
- }
- }
-
- throw new SwitchChainError(error as Error)
- }
- },
- onAccountsChanged(accounts) {
- if (accounts.length === 0) this.onDisconnect()
- else
- config.emitter.emit('change', {
- accounts: accounts.map((x) => getAddress(x)),
- })
- },
- onChainChanged(chain) {
- const chainId = Number(chain)
- config.emitter.emit('change', { chainId })
- },
- async onDisconnect(_error) {
- config.emitter.emit('disconnect')
-
- const provider = await this.getProvider()
- if (accountsChanged) {
- provider.removeListener('accountsChanged', accountsChanged)
- accountsChanged = undefined
- }
- if (chainChanged) {
- provider.removeListener('chainChanged', chainChanged)
- chainChanged = undefined
- }
- if (disconnect) {
- provider.removeListener('disconnect', disconnect)
- disconnect = undefined
- }
- },
- }))
-}
diff --git a/packages/connectors/src/exports/index.test.ts b/packages/connectors/src/exports/index.test.ts
index bcf100cb61..66c405fa0b 100644
--- a/packages/connectors/src/exports/index.test.ts
+++ b/packages/connectors/src/exports/index.test.ts
@@ -7,11 +7,14 @@ test('exports', () => {
[
"injected",
"mock",
+ "baseAccount",
"coinbaseWallet",
+ "gemini",
"metaMask",
+ "porto",
"safe",
- "walletConnect",
"version",
+ "walletConnect",
]
`)
})
diff --git a/packages/connectors/src/exports/index.ts b/packages/connectors/src/exports/index.ts
index bac0975956..da6c805acc 100644
--- a/packages/connectors/src/exports/index.ts
+++ b/packages/connectors/src/exports/index.ts
@@ -5,19 +5,17 @@ export {
type MockParameters,
mock,
} from '@wagmi/core'
-
+export { type BaseAccountParameters, baseAccount } from '../baseAccount.js'
export {
type CoinbaseWalletParameters,
coinbaseWallet,
} from '../coinbaseWallet.js'
-
+export { type GeminiParameters, gemini } from '../gemini.js'
export { type MetaMaskParameters, metaMask } from '../metaMask.js'
-
+export { type PortoParameters, porto } from '../porto.js'
export { type SafeParameters, safe } from '../safe.js'
-
+export { version } from '../version.js'
export {
type WalletConnectParameters,
walletConnect,
} from '../walletConnect.js'
-
-export { version } from '../version.js'
diff --git a/packages/connectors/src/gemini.test.ts b/packages/connectors/src/gemini.test.ts
new file mode 100644
index 0000000000..3fd1cf3042
--- /dev/null
+++ b/packages/connectors/src/gemini.test.ts
@@ -0,0 +1,22 @@
+import { config } from '@wagmi/test'
+import { expect, test } from 'vitest'
+
+import { gemini } from './gemini.js'
+
+test('setup', () => {
+ const connectorFn = gemini()
+ const connector = config._internal.connectors.setup(connectorFn)
+ expect(connector.name).toEqual('Gemini Wallet')
+})
+
+test('setup with parameters', () => {
+ const connectorFn = gemini({
+ appMetadata: {
+ name: 'Test App',
+ url: 'https://example.com',
+ },
+ })
+ const connector = config._internal.connectors.setup(connectorFn)
+ expect(connector.name).toEqual('Gemini Wallet')
+ expect(connector.id).toEqual('gemini')
+})
diff --git a/packages/connectors/src/gemini.ts b/packages/connectors/src/gemini.ts
new file mode 100644
index 0000000000..69b9b6bd34
--- /dev/null
+++ b/packages/connectors/src/gemini.ts
@@ -0,0 +1,183 @@
+import type { AppMetadata, ProviderInterface } from '@gemini-wallet/core'
+import {
+ ChainNotConfiguredError,
+ type Connector,
+ createConnector,
+} from '@wagmi/core'
+import {
+ getAddress,
+ numberToHex,
+ SwitchChainError,
+ UserRejectedRequestError,
+} from 'viem'
+
+export type GeminiParameters = {
+ appMetadata?: AppMetadata
+}
+
+gemini.type = 'gemini' as const
+export function gemini(parameters: GeminiParameters = {}) {
+ type Provider = ProviderInterface
+
+ let walletProvider: Provider | undefined
+ let onAccountsChanged: Connector['onAccountsChanged'] | undefined
+ let onChainChanged: Connector['onChainChanged'] | undefined
+ let onDisconnect: Connector['onDisconnect'] | undefined
+
+ return createConnector((config) => ({
+ id: 'gemini',
+ name: 'Gemini Wallet',
+ type: gemini.type,
+ icon: 'https://keys.gemini.com/images/gemini-wallet-logo.svg',
+ async connect({ chainId, withCapabilities } = {}) {
+ try {
+ const provider = await this.getProvider()
+ const accounts = (await provider.request({
+ method: 'eth_requestAccounts',
+ })) as string[]
+
+ if (!onAccountsChanged) {
+ onAccountsChanged = this.onAccountsChanged.bind(this)
+ provider.on('accountsChanged', onAccountsChanged)
+ }
+ if (!onChainChanged) {
+ onChainChanged = this.onChainChanged.bind(this)
+ provider.on('chainChanged', onChainChanged)
+ }
+ if (!onDisconnect) {
+ onDisconnect = this.onDisconnect.bind(this)
+ provider.on('disconnect', onDisconnect)
+ }
+
+ let currentChainId = await this.getChainId()
+ if (chainId && currentChainId !== chainId) {
+ const chain = await this.switchChain!({ chainId }).catch((error) => {
+ if (error.code === UserRejectedRequestError.code) throw error
+ return { id: currentChainId }
+ })
+ currentChainId = chain?.id ?? currentChainId
+ }
+
+ return {
+ // TODO(v3): Make `withCapabilities: true` default behavior
+ accounts: (withCapabilities
+ ? accounts.map((address) => ({ address, capabilities: {} }))
+ : accounts) as never,
+ chainId: currentChainId,
+ }
+ } catch (error) {
+ if (
+ /(user closed modal|accounts received is empty|user denied account|request rejected)/i.test(
+ (error as Error).message,
+ )
+ )
+ throw new UserRejectedRequestError(error as Error)
+ throw error
+ }
+ },
+ async disconnect() {
+ const provider = await this.getProvider()
+
+ if (onAccountsChanged) {
+ provider.removeListener('accountsChanged', onAccountsChanged)
+ onAccountsChanged = undefined
+ }
+ if (onChainChanged) {
+ provider.removeListener('chainChanged', onChainChanged)
+ onChainChanged = undefined
+ }
+ if (onDisconnect) {
+ provider.removeListener('disconnect', onDisconnect)
+ onDisconnect = undefined
+ }
+
+ await provider.disconnect()
+ },
+ async getAccounts() {
+ const provider = await this.getProvider()
+ const accounts = (await provider.request({
+ method: 'eth_accounts',
+ })) as string[]
+ return accounts.map((x) => getAddress(x))
+ },
+ async getChainId() {
+ const provider = await this.getProvider()
+ const chainId = (await provider.request({
+ method: 'eth_chainId',
+ })) as string
+ return Number(chainId)
+ },
+ async getProvider() {
+ if (!walletProvider) {
+ const { GeminiWalletProvider } = await (() => {
+ // safe webpack optional peer dependency dynamic import
+ try {
+ return import('@gemini-wallet/core')
+ } catch {
+ throw new Error('dependency "@gemini-wallet/core" not found')
+ }
+ })()
+ walletProvider = new GeminiWalletProvider({
+ appMetadata: parameters.appMetadata ?? {},
+ chain: {
+ id: config.chains[0]?.id ?? 1,
+ rpcUrl: config.chains[0]?.rpcUrls?.default?.http[0],
+ },
+ })
+ }
+ return walletProvider
+ },
+ async isAuthorized() {
+ try {
+ const accounts = await this.getAccounts()
+ return Boolean(accounts.length)
+ } catch {
+ return false
+ }
+ },
+ async switchChain({ chainId }) {
+ const chain = config.chains.find((chain) => chain.id === chainId)
+ if (!chain) throw new SwitchChainError(new ChainNotConfiguredError())
+
+ const provider = await this.getProvider()
+
+ try {
+ await provider.request({
+ method: 'wallet_switchEthereumChain',
+ params: [{ chainId: numberToHex(chainId) }],
+ })
+ return chain
+ } catch (error) {
+ throw new SwitchChainError(error as Error)
+ }
+ },
+ onAccountsChanged(accounts) {
+ if (accounts.length === 0) this.onDisconnect()
+ else
+ config.emitter.emit('change', {
+ accounts: accounts.map((x: string) => getAddress(x)),
+ })
+ },
+ onChainChanged(chain) {
+ const chainId = Number(chain)
+ config.emitter.emit('change', { chainId })
+ },
+ async onDisconnect() {
+ config.emitter.emit('disconnect')
+
+ const provider = await this.getProvider()
+ if (onAccountsChanged) {
+ provider.removeListener('accountsChanged', onAccountsChanged)
+ onAccountsChanged = undefined
+ }
+ if (onChainChanged) {
+ provider.removeListener('chainChanged', onChainChanged)
+ onChainChanged = undefined
+ }
+ if (onDisconnect) {
+ provider.removeListener('disconnect', onDisconnect)
+ onDisconnect = undefined
+ }
+ },
+ }))
+}
diff --git a/packages/connectors/src/metaMask.ts b/packages/connectors/src/metaMask.ts
index 02ab4c3fb3..dd046c03e0 100644
--- a/packages/connectors/src/metaMask.ts
+++ b/packages/connectors/src/metaMask.ts
@@ -7,9 +7,9 @@ import type {
import {
ChainNotConfiguredError,
type Connector,
- ProviderNotFoundError,
createConnector,
extractRpcUrls,
+ ProviderNotFoundError,
} from '@wagmi/core'
import type {
Compute,
@@ -21,16 +21,16 @@ import type {
import {
type AddEthereumChainParameter,
type Address,
+ getAddress,
type Hex,
+ hexToNumber,
+ numberToHex,
type ProviderConnectInfo,
type ProviderRpcError,
ResourceUnavailableRpcError,
type RpcError,
SwitchChainError,
UserRejectedRequestError,
- getAddress,
- hexToNumber,
- numberToHex,
withRetry,
withTimeout,
} from 'viem'
@@ -61,16 +61,7 @@ type WagmiMetaMaskSDKOptions = Compute<
| 'useDeeplink'
| 'readonlyRPCMap'
>
- > & {
- /** @deprecated */
- forceDeleteProvider?: MetaMaskSDKOptions['forceDeleteProvider']
- /** @deprecated */
- forceInjectProvider?: MetaMaskSDKOptions['forceInjectProvider']
- /** @deprecated */
- injectProvider?: MetaMaskSDKOptions['injectProvider']
- /** @deprecated */
- useDeeplink?: MetaMaskSDKOptions['useDeeplink']
- }
+ >
>
metaMask.type = 'metaMask' as const
@@ -113,7 +104,7 @@ export function metaMask(parameters: MetaMaskParameters = {}) {
}
}
},
- async connect({ chainId, isReconnecting } = {}) {
+ async connect({ chainId, isReconnecting, withCapabilities } = {}) {
const provider = await this.getProvider()
if (!displayUri) {
displayUri = this.onDisplayUri
@@ -191,7 +182,13 @@ export function metaMask(parameters: MetaMaskParameters = {}) {
provider.on('disconnect', disconnect as Listener)
}
- return { accounts, chainId: currentChainId }
+ return {
+ // TODO(v3): Make `withCapabilities: true` default behavior
+ accounts: (withCapabilities
+ ? accounts.map((address) => ({ address, capabilities: {} }))
+ : accounts) as never,
+ chainId: currentChainId,
+ }
} catch (err) {
const error = err as RpcError
if (error.code === UserRejectedRequestError.code)
@@ -239,7 +236,14 @@ export function metaMask(parameters: MetaMaskParameters = {}) {
// Unwrapping import for Vite compatibility.
// See: https://github.com/vitejs/vite/issues/9703
const MetaMaskSDK = await (async () => {
- const { default: SDK } = await import('@metamask/sdk')
+ const { default: SDK } = await (() => {
+ // safe webpack optional peer dependency dynamic import
+ try {
+ return import('@metamask/sdk')
+ } catch {
+ throw new Error('dependency "@metamask/sdk" not found')
+ }
+ })()
if (typeof SDK !== 'function' && typeof SDK.default === 'function')
return SDK.default
return SDK as unknown as typeof SDK.default
@@ -253,12 +257,12 @@ export function metaMask(parameters: MetaMaskParameters = {}) {
})?.[0]
sdk = new MetaMaskSDK({
+ // Workaround cast since MetaMask SDK does not support `'exactOptionalPropertyTypes'`
+ ...(parameters as RemoveUndefined),
_source: 'wagmi',
forceDeleteProvider: false,
forceInjectProvider: false,
injectProvider: false,
- // Workaround cast since MetaMask SDK does not support `'exactOptionalPropertyTypes'`
- ...(parameters as RemoveUndefined),
readonlyRPCMap,
dappMetadata: {
...parameters.dappMetadata,
@@ -272,7 +276,7 @@ export function metaMask(parameters: MetaMaskParameters = {}) {
? window.location.origin
: 'https://wagmi.sh',
},
- useDeeplink: parameters.useDeeplink ?? true,
+ useDeeplink: true,
})
const result = await sdk.init()
// On initial load, sometimes `sdk.getProvider` does not return provider.
diff --git a/packages/connectors/src/porto.test.ts b/packages/connectors/src/porto.test.ts
new file mode 100644
index 0000000000..1946aab587
--- /dev/null
+++ b/packages/connectors/src/porto.test.ts
@@ -0,0 +1,10 @@
+import { config } from '@wagmi/test'
+import { expect, test } from 'vitest'
+
+import { porto } from './porto.js'
+
+test('setup', () => {
+ const connectorFn = porto()
+ const connector = config._internal.connectors.setup(connectorFn)
+ expect(connector.name).toEqual('Porto')
+})
diff --git a/packages/connectors/src/porto.ts b/packages/connectors/src/porto.ts
new file mode 100644
index 0000000000..52675701a3
--- /dev/null
+++ b/packages/connectors/src/porto.ts
@@ -0,0 +1,323 @@
+import {
+ ChainNotConfiguredError,
+ type Connector,
+ createConnector,
+} from '@wagmi/core'
+import type { ExactPartial } from '@wagmi/core/internal'
+import type { Porto, RpcSchema } from 'porto'
+import {
+ type Address,
+ getAddress,
+ numberToHex,
+ type ProviderConnectInfo,
+ type RpcError,
+ SwitchChainError,
+ UserRejectedRequestError,
+ withRetry,
+} from 'viem'
+
+export type PortoParameters = ExactPartial
+
+export function porto(parameters: PortoParameters = {}) {
+ type Provider = ReturnType['provider']
+ type Properties = {
+ connect(parameters?: {
+ chainId?: number | undefined
+ capabilities?:
+ | (RpcSchema.wallet_connect.Capabilities & {
+ force?: boolean | undefined
+ })
+ | undefined
+ isReconnecting?: boolean | undefined
+ withCapabilities?: withCapabilities | boolean | undefined
+ }): Promise<{
+ accounts: withCapabilities extends true
+ ? readonly {
+ address: Address
+ capabilities: RpcSchema.wallet_connect.ResponseCapabilities
+ }[]
+ : readonly Address[]
+ chainId: number
+ }>
+ getPortoInstance(): Promise
+ onConnect(connectInfo: ProviderConnectInfo): void
+ }
+
+ return createConnector((wagmiConfig) => {
+ const chains = wagmiConfig.chains ?? parameters.chains ?? []
+
+ const transports = (() => {
+ if (wagmiConfig.transports) return wagmiConfig.transports
+ return parameters.transports
+ })()
+
+ let porto_promise: Promise | undefined
+
+ let accountsChanged: Connector['onAccountsChanged'] | undefined
+ let chainChanged: Connector['onChainChanged'] | undefined
+ let connect: Connector['onConnect'] | undefined
+ let disconnect: Connector['onDisconnect'] | undefined
+
+ return {
+ async connect({ chainId = chains[0].id, ...rest } = {}) {
+ const isReconnecting =
+ ('isReconnecting' in rest && rest.isReconnecting) || false
+ const withCapabilities =
+ ('withCapabilities' in rest && rest.withCapabilities) || false
+
+ let accounts: readonly (Address | { address: Address })[] = []
+ let currentChainId: number | undefined
+
+ if (isReconnecting) {
+ ;[accounts, currentChainId] = await Promise.all([
+ this.getAccounts().catch(() => []),
+ this.getChainId().catch(() => undefined),
+ ])
+ if (chainId && currentChainId !== chainId) {
+ const chain = await this.switchChain!({ chainId }).catch(
+ (error) => {
+ if (error.code === UserRejectedRequestError.code) throw error
+ return { id: currentChainId }
+ },
+ )
+ currentChainId = chain?.id ?? currentChainId
+ }
+ }
+
+ const provider = (await this.getProvider()) as Provider
+
+ try {
+ if (!accounts?.length && !isReconnecting) {
+ const { RpcSchema } = await (() => {
+ // safe webpack optional peer dependency dynamic import
+ try {
+ return import('porto')
+ } catch {
+ throw new Error('dependency "porto" not found')
+ }
+ })()
+ const { z } = await (() => {
+ // safe webpack optional peer dependency dynamic import
+ try {
+ return import('porto/internal')
+ } catch {
+ throw new Error('dependency "porto/internal" not found')
+ }
+ })()
+ const res = await provider.request({
+ method: 'wallet_connect',
+ params: [
+ {
+ ...('capabilities' in rest
+ ? {
+ capabilities: z.encode(
+ RpcSchema.wallet_connect.Capabilities,
+ rest.capabilities ?? {},
+ ),
+ }
+ : {}),
+ chainIds: [
+ numberToHex(chainId),
+ ...chains
+ .filter((x) => x.id !== chainId)
+ .map((x) => numberToHex(x.id)),
+ ],
+ },
+ ],
+ })
+ accounts = res.accounts
+ currentChainId = Number(res.chainIds[0])
+ }
+
+ if (!currentChainId) throw new ChainNotConfiguredError()
+
+ // Manage EIP-1193 event listeners
+ // https://eips.ethereum.org/EIPS/eip-1193#events
+ if (connect) {
+ provider.removeListener('connect', connect)
+ connect = undefined
+ }
+ if (!accountsChanged) {
+ accountsChanged = this.onAccountsChanged.bind(this)
+ // Porto Provider uses Ox, which uses `readonly Address.Address[]` for `accountsChanged`,
+ // while Connector `accountsChanged` is `string[]`
+ provider.on('accountsChanged', accountsChanged as never)
+ }
+ if (!chainChanged) {
+ chainChanged = this.onChainChanged.bind(this)
+ provider.on('chainChanged', chainChanged)
+ }
+ if (!disconnect) {
+ disconnect = this.onDisconnect.bind(this)
+ provider.on('disconnect', disconnect)
+ }
+
+ return {
+ accounts: accounts.map((account) => {
+ if (typeof account === 'object')
+ return withCapabilities ? account : account.address
+ return withCapabilities
+ ? { address: account, capabilities: {} }
+ : account
+ }) as never,
+ chainId: currentChainId,
+ }
+ } catch (err) {
+ const error = err as RpcError
+ if (error.code === UserRejectedRequestError.code)
+ throw new UserRejectedRequestError(error)
+ throw error
+ }
+ },
+ async disconnect() {
+ const provider = await this.getProvider()
+
+ if (chainChanged) {
+ provider.removeListener('chainChanged', chainChanged)
+ chainChanged = undefined
+ }
+ if (disconnect) {
+ provider.removeListener('disconnect', disconnect)
+ disconnect = undefined
+ }
+ if (!connect) {
+ connect = this.onConnect.bind(this)
+ provider.on('connect', connect)
+ }
+
+ await provider.request({ method: 'wallet_disconnect' })
+ },
+ async getAccounts() {
+ const provider = await this.getProvider()
+ const accounts = await provider.request({
+ method: 'eth_accounts',
+ })
+ return accounts.map((x) => getAddress(x))
+ },
+ async getChainId() {
+ const provider = await this.getProvider()
+ const hexChainId = await provider.request({
+ method: 'eth_chainId',
+ })
+ return Number(hexChainId)
+ },
+ async getPortoInstance() {
+ porto_promise ??= (async () => {
+ const { Porto } = await (() => {
+ // safe webpack optional peer dependency dynamic import
+ try {
+ return import('porto')
+ } catch {
+ throw new Error('dependency "porto" not found')
+ }
+ })()
+ return Porto.create({
+ ...parameters,
+ announceProvider: false,
+ // @ts-ignore
+ chains,
+ // @ts-ignore
+ transports,
+ })
+ })()
+ return await porto_promise
+ },
+ async getProvider() {
+ return (await this.getPortoInstance()).provider
+ },
+ icon: 'data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNDIyIiBoZWlnaHQ9IjQyMiIgdmlld0JveD0iMCAwIDQyMiA0MjIiIGZpbGw9Im5vbmUiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+CjxyZWN0IHdpZHRoPSI0MjIiIGhlaWdodD0iNDIyIiBmaWxsPSJibGFjayIvPgo8ZyBjbGlwLXBhdGg9InVybCgjY2xpcDBfMV8xNSkiPgo8cGF0aCBkPSJNODEgMjg2LjM2NkM4MSAyODAuODkzIDg1LjQ1MDUgMjc2LjQ1NSA5MC45NDA0IDI3Ni40NTVIMzI5LjUxMUMzMzUuMDAxIDI3Ni40NTUgMzM5LjQ1MiAyODAuODkzIDMzOS40NTIgMjg2LjM2NlYzMDYuMTg4QzMzOS40NTIgMzExLjY2MiAzMzUuMDAxIDMxNi4wOTkgMzI5LjUxMSAzMTYuMDk5SDkwLjk0MDRDODUuNDUwNSAzMTYuMDk5IDgxIDMxMS42NjIgODEgMzA2LjE4OFYyODYuMzY2WiIgZmlsbD0id2hpdGUiIGZpbGwtb3BhY2l0eT0iMC41Ii8+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNOTAuOTQwNCAyMzQuODI4Qzg1LjQ1MDUgMjM0LjgyOCA4MSAyMzkuMjY2IDgxIDI0NC43MzlWMjcxLjUzMUM4My44NDMyIDI2OS42MzMgODcuMjYyMiAyNjguNTI2IDkwLjk0MDQgMjY4LjUyNkgzMjkuNTExQzMzMy4xODggMjY4LjUyNiAzMzYuNjA4IDI2OS42MzMgMzM5LjQ1MiAyNzEuNTMxVjI0NC43MzlDMzM5LjQ1MiAyMzkuMjY2IDMzNS4wMDEgMjM0LjgyOCAzMjkuNTExIDIzNC44MjhIOTAuOTQwNFpNMzM5LjQ1MiAyODYuMzY2QzMzOS40NTIgMjgwLjg5MyAzMzUuMDAxIDI3Ni40NTUgMzI5LjUxMSAyNzYuNDU1SDkwLjk0MDRDODUuNDUwNSAyNzYuNDU1IDgxIDI4MC44OTMgODEgMjg2LjM2NlYzMDYuMTlDODEgMzExLjY2NCA4NS40NTA1IDMxNi4xMDEgOTAuOTQwNCAzMTYuMTAxSDMyOS41MTFDMzM1LjAwMSAzMTYuMTAxIDMzOS40NTIgMzExLjY2NCAzMzkuNDUyIDMwNi4xOVYyODYuMzY2WiIgZmlsbD0id2hpdGUiIGZpbGwtb3BhY2l0eT0iMC41Ii8+CjxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNOTAuOTQwNCAxOTMuMjAxQzg1LjQ1MDUgMTkzLjIwMSA4MSAxOTcuNjM4IDgxIDIwMy4xMTJWMjI5LjkwM0M4My44NDMyIDIyOC4wMDYgODcuMjYyMiAyMjYuODk5IDkwLjk0MDQgMjI2Ljg5OUgzMjkuNTExQzMzMy4xODggMjI2Ljg5OSAzMzYuNjA4IDIyOC4wMDYgMzM5LjQ1MiAyMjkuOTAzVjIwMy4xMTJDMzM5LjQ1MiAxOTcuNjM4IDMzNS4wMDEgMTkzLjIwMSAzMjkuNTExIDE5My4yMDFIOTAuOTQwNFpNMzM5LjQ1MiAyNDQuNzM5QzMzOS40NTIgMjM5LjI2NSAzMzUuMDAxIDIzNC44MjggMzI5LjUxMSAyMzQuODI4SDkwLjk0MDRDODUuNDUwNSAyMzQuODI4IDgxIDIzOS4yNjUgODEgMjQ0LjczOVYyNzEuNTNDODEuMjE3NSAyNzEuMzg1IDgxLjQzODMgMjcxLjI0NSA4MS42NjI0IDI3MS4xMDlDODMuODMyNSAyNjkuNzk0IDg2LjMwNTQgMjY4LjkyNyA4OC45NTIzIDI2OC42MzVDODkuNjA1MSAyNjguNTYzIDkwLjI2ODQgMjY4LjUyNiA5MC45NDA0IDI2OC41MjZIMzI5LjUxMUMzMzAuMTgzIDI2OC41MjYgMzMwLjg0NiAyNjguNTYzIDMzMS40OTggMjY4LjYzNUMzMzQuNDE5IDI2OC45NTcgMzM3LjEyOCAyNjkuOTggMzM5LjQ1MiAyNzEuNTNWMjQ0LjczOVpNMzM5LjQ1MiAyODYuMzY2QzMzOS40NTIgMjgxLjAyMSAzMzUuMjA2IDI3Ni42NjMgMzI5Ljg5MyAyNzYuNDYyQzMyOS43NjcgMjc2LjQ1NyAzMjkuNjQgMjc2LjQ1NSAzMjkuNTExIDI3Ni40NTVIOTAuOTQwNEM4NS40NTA1IDI3Ni40NTUgODEgMjgwLjg5MyA4MSAyODYuMzY2VjMwNi4xODhDODEgMzExLjY2MiA4NS40NTA1IDMxNi4xMDEgOTAuOTQwNCAzMTYuMTAxSDMyOS41MTFDMzM1LjAwMSAzMTYuMTAxIDMzOS40NTIgMzExLjY2MiAzMzkuNDUyIDMwNi4xODhWMjg2LjM2NloiIGZpbGw9IndoaXRlIiBmaWxsLW9wYWNpdHk9IjAuNSIvPgo8cGF0aCBvcGFjaXR5PSIwLjMiIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNOTguMDE0NiAxMDRDODguNjE3NyAxMDQgODEgMTExLjU5NSA4MSAxMjAuOTY1VjE4OC4yNzZDODMuODQzMiAxODYuMzc5IDg3LjI2MjIgMTg1LjI3MiA5MC45NDA0IDE4NS4yNzJIMzI5LjUxMUMzMzMuMTg4IDE4NS4yNzIgMzM2LjYwOCAxODYuMzc5IDMzOS40NTIgMTg4LjI3NlYxMjAuOTY1QzMzOS40NTIgMTExLjU5NSAzMzEuODMzIDEwNCAzMjIuNDM3IDEwNEg5OC4wMTQ2Wk0zMzkuNDUyIDIwMy4xMTJDMzM5LjQ1MiAxOTcuNjM4IDMzNS4wMDEgMTkzLjIwMSAzMjkuNTExIDE5My4yMDFIOTAuOTQwNEM4NS40NTA1IDE5My4yMDEgODEgMTk3LjYzOCA4MSAyMDMuMTEyVjIyOS45MDNDODEuMjE3NSAyMjkuNzU4IDgxLjQzODMgMjI5LjYxOCA4MS42NjI0IDIyOS40ODJDODMuODMyNSAyMjguMTY3IDg2LjMwNTQgMjI3LjMgODguOTUyMyAyMjcuMDA4Qzg5LjYwNTEgMjI2LjkzNiA5MC4yNjg0IDIyNi44OTkgOTAuOTQwNCAyMjYuODk5SDMyOS41MTFDMzMwLjE4MyAyMjYuODk5IDMzMC44NDYgMjI2LjkzNiAzMzEuNDk4IDIyNy4wMDhDMzM0LjQxOSAyMjcuMzMgMzM3LjEyOCAyMjguMzUyIDMzOS40NTIgMjI5LjkwM1YyMDMuMTEyWk0zMzkuNDUyIDI0NC43MzlDMzM5LjQ1MiAyMzkuMzkzIDMzNS4yMDYgMjM1LjAzNiAzMjkuODkzIDIzNC44MzVDMzI5Ljc2NyAyMzQuODMgMzI5LjY0IDIzNC44MjggMzI5LjUxMSAyMzQuODI4SDkwLjk0MDRDODUuNDUwNSAyMzQuODI4IDgxIDIzOS4yNjUgODEgMjQ0LjczOVYyNzEuNTNMODEuMDcwNyAyNzEuNDgzQzgxLjI2NTMgMjcxLjM1NSA4MS40NjI1IDI3MS4yMyA4MS42NjI0IDI3MS4xMDlDODEuOTA4MyAyNzAuOTYgODIuMTU4MSAyNzAuODE3IDgyLjQxMTcgMjcwLjY3OUM4NC4zOTUzIDI2OS42MDUgODYuNjA1NCAyNjguODk0IDg4Ljk1MjMgMjY4LjYzNUM4OS4wMDUyIDI2OC42MjkgODkuMDU4IDI2OC42MjQgODkuMTExIDI2OC42MThDODkuNzEyNSAyNjguNTU3IDkwLjMyMjggMjY4LjUyNiA5MC45NDA0IDI2OC41MjZIMzI5LjUxMUMzMjkuNzM4IDI2OC41MjYgMzI5Ljk2NSAyNjguNTMgMzMwLjE5MiAyNjguNTM5QzMzMC42MzEgMjY4LjU1NSAzMzEuMDY3IDI2OC41ODcgMzMxLjQ5OCAyNjguNjM1QzMzNC40MTkgMjY4Ljk1NyAzMzcuMTI4IDI2OS45OCAzMzkuNDUyIDI3MS41M1YyNDQuNzM5Wk0zMzkuNDUyIDI4Ni4zNjZDMzM5LjQ1MiAyODEuMDIxIDMzNS4yMDYgMjc2LjY2MyAzMjkuODkzIDI3Ni40NjJMMzI5Ljg2NSAyNzYuNDYxQzMyOS43NDggMjc2LjQ1NyAzMjkuNjI5IDI3Ni40NTUgMzI5LjUxMSAyNzYuNDU1SDkwLjk0MDRDODUuNDUwNSAyNzYuNDU1IDgxIDI4MC44OTMgODEgMjg2LjM2NlYzMDYuMTg4QzgxIDMxMS42NjIgODUuNDUwNSAzMTYuMTAxIDkwLjk0MDQgMzE2LjEwMUgzMjkuNTExQzMzNS4wMDEgMzE2LjEwMSAzMzkuNDUyIDMxMS42NjIgMzM5LjQ1MiAzMDYuMTg4VjI4Ni4zNjZaIiBmaWxsPSJ3aGl0ZSIvPgo8cGF0aCBkPSJNMjY5Ljg2OCAxMzEuNzUyQzI2OS44NjggMTI2LjI3OCAyNzQuMzE4IDEyMS44NCAyNzkuODA4IDEyMS44NEgzMTEuNjE4QzMxNy4xMDggMTIxLjg0IDMyMS41NTggMTI2LjI3OCAzMjEuNTU4IDEzMS43NTJWMTYxLjQ4NUMzMjEuNTU4IDE2Ni45NTkgMzE3LjEwOCAxNzEuMzk2IDMxMS42MTggMTcxLjM5NkgyNzkuODA4QzI3NC4zMTggMTcxLjM5NiAyNjkuODY4IDE2Ni45NTkgMjY5Ljg2OCAxNjEuNDg1VjEzMS43NTJaIiBmaWxsPSJ3aGl0ZSIvPgo8L2c+CjxkZWZzPgo8Y2xpcFBhdGggaWQ9ImNsaXAwXzFfMTUiPgo8cmVjdCB3aWR0aD0iMjU5IiBoZWlnaHQ9IjIxMyIgZmlsbD0id2hpdGUiIHRyYW5zZm9ybT0idHJhbnNsYXRlKDgxIDEwNCkiLz4KPC9jbGlwUGF0aD4KPC9kZWZzPgo8L3N2Zz4K',
+ id: 'xyz.ithaca.porto',
+ async isAuthorized() {
+ try {
+ // Use retry strategy as some injected wallets (e.g. MetaMask) fail to
+ // immediately resolve JSON-RPC requests on page load.
+ const accounts = await withRetry(() => this.getAccounts())
+ return !!accounts.length
+ } catch {
+ return false
+ }
+ },
+ name: 'Porto',
+ async onAccountsChanged(accounts) {
+ wagmiConfig.emitter.emit('change', {
+ accounts: accounts.map((x) => getAddress(x)),
+ })
+ },
+ onChainChanged(chain) {
+ const chainId = Number(chain)
+ wagmiConfig.emitter.emit('change', { chainId })
+ },
+ async onConnect(connectInfo) {
+ const accounts = await this.getAccounts()
+ if (accounts.length === 0) return
+
+ const chainId = Number(connectInfo.chainId)
+ wagmiConfig.emitter.emit('connect', { accounts, chainId })
+
+ // Manage EIP-1193 event listeners
+ const provider = await this.getProvider()
+ if (provider) {
+ if (connect) {
+ provider.removeListener('connect', connect)
+ connect = undefined
+ }
+ if (!accountsChanged) {
+ accountsChanged = this.onAccountsChanged.bind(this)
+ // Porto Provider uses Ox, which uses `readonly Address.Address[]` for `accountsChanged`,
+ // while Connector `accountsChanged` is `string[]`
+ provider.on('accountsChanged', accountsChanged as never)
+ }
+ if (!chainChanged) {
+ chainChanged = this.onChainChanged.bind(this)
+ provider.on('chainChanged', chainChanged)
+ }
+ if (!disconnect) {
+ disconnect = this.onDisconnect.bind(this)
+ provider.on('disconnect', disconnect)
+ }
+ }
+ },
+ async onDisconnect(_error) {
+ const provider = await this.getProvider()
+
+ wagmiConfig.emitter.emit('disconnect')
+
+ // Manage EIP-1193 event listeners
+ if (provider) {
+ if (chainChanged) {
+ provider.removeListener('chainChanged', chainChanged)
+ chainChanged = undefined
+ }
+ if (disconnect) {
+ provider.removeListener('disconnect', disconnect)
+ disconnect = undefined
+ }
+ if (!connect) {
+ connect = this.onConnect.bind(this)
+ provider.on('connect', connect)
+ }
+ }
+ },
+ async setup() {
+ if (!connect) {
+ const provider = await this.getProvider()
+ connect = this.onConnect.bind(this)
+ provider.on('connect', connect)
+ }
+ },
+ async switchChain({ chainId }) {
+ const chain = chains.find((x) => x.id === chainId)
+ if (!chain) throw new SwitchChainError(new ChainNotConfiguredError())
+
+ const provider = await this.getProvider()
+ await provider.request({
+ method: 'wallet_switchEthereumChain',
+ params: [{ chainId: numberToHex(chainId) }],
+ })
+
+ return chain
+ },
+ type: 'injected',
+ }
+ })
+}
diff --git a/packages/connectors/src/safe.ts b/packages/connectors/src/safe.ts
index 13153e106f..8fd6117d1d 100644
--- a/packages/connectors/src/safe.ts
+++ b/packages/connectors/src/safe.ts
@@ -2,8 +2,8 @@ import type { SafeAppProvider } from '@safe-global/safe-apps-provider'
import type { Opts } from '@safe-global/safe-apps-sdk'
import {
type Connector,
- ProviderNotFoundError,
createConnector,
+ ProviderNotFoundError,
} from '@wagmi/core'
import type { Compute } from '@wagmi/core/internal'
import { getAddress, withTimeout } from 'viem'
@@ -45,7 +45,7 @@ export function safe(parameters: SafeParameters = {}) {
id: 'safe',
name: 'Safe',
type: safe.type,
- async connect() {
+ async connect({ withCapabilities } = {}) {
const provider = await this.getProvider()
if (!provider) throw new ProviderNotFoundError()
@@ -60,7 +60,13 @@ export function safe(parameters: SafeParameters = {}) {
// Remove disconnected shim if it exists
if (shimDisconnect) await config.storage?.removeItem('safe.disconnected')
- return { accounts, chainId }
+ return {
+ // TODO(v3): Make `withCapabilities: true` default behavior
+ accounts: (withCapabilities
+ ? accounts.map((address) => ({ address, capabilities: {} }))
+ : accounts) as never,
+ chainId,
+ }
},
async disconnect() {
const provider = await this.getProvider()
@@ -89,7 +95,14 @@ export function safe(parameters: SafeParameters = {}) {
if (!isIframe) return
if (!provider_) {
- const { default: SDK } = await import('@safe-global/safe-apps-sdk')
+ const { default: SDK } = await (() => {
+ // safe webpack optional peer dependency dynamic import
+ try {
+ return import('@safe-global/safe-apps-sdk')
+ } catch {
+ throw new Error('dependency "@safe-global/safe-apps-sdk" not found')
+ }
+ })()
const sdk = new SDK(parameters)
// `getInfo` hangs when not used in Safe App iFrame
@@ -101,7 +114,16 @@ export function safe(parameters: SafeParameters = {}) {
// Unwrapping import for Vite compatibility.
// See: https://github.com/vitejs/vite/issues/9703
const SafeAppProvider = await (async () => {
- const Provider = await import('@safe-global/safe-apps-provider')
+ const Provider = await (() => {
+ // safe webpack optional peer dependency dynamic import
+ try {
+ return import('@safe-global/safe-apps-provider')
+ } catch {
+ throw new Error(
+ 'dependency "@safe-global/safe-apps-provider" not found',
+ )
+ }
+ })()
if (
typeof Provider.SafeAppProvider !== 'function' &&
typeof Provider.default.SafeAppProvider === 'function'
diff --git a/packages/connectors/src/version.ts b/packages/connectors/src/version.ts
index d44e5a92df..668b35113e 100644
--- a/packages/connectors/src/version.ts
+++ b/packages/connectors/src/version.ts
@@ -1 +1 @@
-export const version = '5.7.12'
+export const version = '7.1.2'
diff --git a/packages/connectors/src/walletConnect.test.ts b/packages/connectors/src/walletConnect.test.ts
index 4e8a74ebfe..960d02a18b 100644
--- a/packages/connectors/src/walletConnect.test.ts
+++ b/packages/connectors/src/walletConnect.test.ts
@@ -1,5 +1,5 @@
import { config, walletConnectProjectId } from '@wagmi/test'
-import { http, HttpResponse } from 'msw'
+import { HttpResponse, http } from 'msw'
import { setupServer } from 'msw/node'
import {
afterAll,
diff --git a/packages/connectors/src/walletConnect.ts b/packages/connectors/src/walletConnect.ts
index fc4f794c1f..d5a3d622df 100644
--- a/packages/connectors/src/walletConnect.ts
+++ b/packages/connectors/src/walletConnect.ts
@@ -1,22 +1,22 @@
import {
ChainNotConfiguredError,
type Connector,
- ProviderNotFoundError,
createConnector,
extractRpcUrls,
+ ProviderNotFoundError,
} from '@wagmi/core'
import type { Compute, ExactPartial, Omit } from '@wagmi/core/internal'
import type { EthereumProvider } from '@walletconnect/ethereum-provider'
import {
type AddEthereumChainParameter,
type Address,
+ getAddress,
+ numberToHex,
type ProviderConnectInfo,
type ProviderRpcError,
type RpcError,
SwitchChainError,
UserRejectedRequestError,
- getAddress,
- numberToHex,
} from 'viem'
type WalletConnectConnector = Connector & {
@@ -78,12 +78,16 @@ export function walletConnect(parameters: WalletConnectParameters) {
type Provider = Awaited>
type Properties = {
- connect(parameters?: {
+ // TODO(v3): Make `withCapabilities: true` default behavior
+ connect(parameters?: {
chainId?: number | undefined
isReconnecting?: boolean | undefined
pairingTopic?: string | undefined
+ withCapabilities?: withCapabilities | boolean | undefined
}): Promise<{
- accounts: readonly Address[]
+ accounts: withCapabilities extends true
+ ? readonly { address: Address }[]
+ : readonly Address[]
chainId: number
}>
getNamespaceChainsIds(): number[]
@@ -126,7 +130,7 @@ export function walletConnect(parameters: WalletConnectParameters) {
provider.on('session_delete', sessionDelete)
}
},
- async connect({ chainId, ...rest } = {}) {
+ async connect({ chainId, withCapabilities, ...rest } = {}) {
try {
const provider = await this.getProvider()
if (!provider) throw new ProviderNotFoundError()
@@ -167,7 +171,23 @@ export function walletConnect(parameters: WalletConnectParameters) {
// If session exists and chains are authorized, enable provider for required chain
const accounts = (await provider.enable()).map((x) => getAddress(x))
- const currentChainId = await this.getChainId()
+
+ // Switch to chain if provided
+ let currentChainId = await this.getChainId()
+ if (chainId && currentChainId !== chainId) {
+ const chain = await this.switchChain!({ chainId }).catch(
+ (error: RpcError) => {
+ if (
+ error.code === UserRejectedRequestError.code &&
+ (error.cause as RpcError | undefined)?.message !==
+ 'Missing or invalid. request() method: wallet_addEthereumChain'
+ )
+ throw error
+ return { id: currentChainId }
+ },
+ )
+ currentChainId = chain?.id ?? currentChainId
+ }
if (displayUri) {
provider.removeListener('display_uri', displayUri)
@@ -194,7 +214,12 @@ export function walletConnect(parameters: WalletConnectParameters) {
provider.on('session_delete', sessionDelete)
}
- return { accounts, chainId: currentChainId }
+ return {
+ accounts: (withCapabilities
+ ? accounts.map((address) => ({ address, capabilities: {} }))
+ : accounts) as never,
+ chainId: currentChainId,
+ }
} catch (error) {
if (
/(user rejected|connection request reset)/i.test(
@@ -245,9 +270,16 @@ export function walletConnect(parameters: WalletConnectParameters) {
async function initProvider() {
const optionalChains = config.chains.map((x) => x.id) as [number]
if (!optionalChains.length) return
- const { EthereumProvider } = await import(
- '@walletconnect/ethereum-provider'
- )
+ const { EthereumProvider } = await (() => {
+ // safe webpack optional peer dependency dynamic import
+ try {
+ return import('@walletconnect/ethereum-provider')
+ } catch {
+ throw new Error(
+ 'dependency "@walletconnect/ethereum-provider" not found',
+ )
+ }
+ })()
return await EthereumProvider.init({
...parameters,
disableProviderPing: true,
@@ -311,7 +343,9 @@ export function walletConnect(parameters: WalletConnectParameters) {
new Promise((resolve) => {
const listener = ({
chainId: currentChainId,
- }: { chainId?: number | undefined }) => {
+ }: {
+ chainId?: number | undefined
+ }) => {
if (currentChainId === chainId) {
config.emitter.off('change', listener)
resolve()
@@ -424,7 +458,7 @@ export function walletConnect(parameters: WalletConnectParameters) {
getNamespaceChainsIds() {
if (!provider_) return []
const chainIds = provider_.session?.namespaces[NAMESPACE]?.accounts?.map(
- (account) => Number.parseInt(account.split(':')[1] || ''),
+ (account) => Number.parseInt(account.split(':')[1] || '', 10),
)
return chainIds ?? []
},
diff --git a/packages/core/CHANGELOG.md b/packages/core/CHANGELOG.md
index 2747e5b253..65aebaeff8 100644
--- a/packages/core/CHANGELOG.md
+++ b/packages/core/CHANGELOG.md
@@ -1,5 +1,217 @@
# @wagmi/core
+## 3.2.2
+
+### Patch Changes
+
+- Updated query internals. ([`4fefa57`](https://github.com/wevm/wagmi/commit/4fefa576014820b454344b579282ddecde5c7994))
+
+## 3.2.1
+
+### Patch Changes
+
+- `wagmi/tempo`: Fixed issue where `webAuthn` connector was not adhering to chain-specific `prepareTransactionRequest` phases. ([#4939](https://github.com/wevm/wagmi/pull/4939))
+
+## 3.2.0
+
+### Minor Changes
+
+- Updated to `viem@2.44.0` with Tempo Moderato support. ([#4940](https://github.com/wevm/wagmi/pull/4940))
+
+ **Breaking Changes (Tempo)**
+
+ - Renamed `reward.start` → `reward.distribute` (no longer supports streaming)
+ - Renamed `reward.startSync` → `reward.distributeSync`
+ - Renamed `reward.getTotalPerSecond` → `reward.getGlobalRewardPerToken`
+ - Renamed `reward.watchRewardScheduled` → `reward.watchRewardDistributed`
+ - Removed `nonce.getNonceKeyCount`
+ - Removed `nonce.watchActiveKeyCountChanged`
+ - Removed `amm.watchFeeSwap` (FeeSwap event no longer emitted by protocol)
+
+ **New Features (Tempo)**
+
+ - Added `dex.cancelStale` action to cancel stale orders from restricted makers
+ - Added `dex.cancelStaleSync` action
+ - Added `salt` parameter to `token.create`
+
+## 3.1.0
+
+### Minor Changes
+
+- Added first-class support and extension for [Tempo](https://docs.tempo.xyz) via `/tempo` entrypoint. ([#4922](https://github.com/wevm/wagmi/pull/4922))
+
+## 3.0.2
+
+### Patch Changes
+
+- Fixed `config.connectors` type inference ([#4923](https://github.com/wevm/wagmi/pull/4923))
+
+## 3.0.1
+
+### Patch Changes
+
+- Fixed `readContract` return type inference for ABI function overloads. ([`058c8c1`](https://github.com/wevm/wagmi/commit/058c8c18459a69a4aa2141e34640273a06a819f4))
+
+## 3.0.0
+
+### Major Changes
+
+- All connector dependencies are now optional peer dependencies. This means that if you want to use a specific connector, you need to install its required dependencies. ([#4857](https://github.com/wevm/wagmi/pull/4857))
+
+ #### baseAccount
+
+ [`baseAccount`](https://wagmi.sh/core/api/connectors/baseAccount) requires `@base-org/account`
+
+ ```
+ pnpm add @base-org/account@~2.4.0
+ ```
+
+ #### coinbaseWallet
+
+ [`coinbaseWallet`](https://wagmi.sh/core/api/connectors/coinbaseWallet) requires `@coinbase/wallet-sdk`
+
+ ```
+ pnpm add @coinbase/wallet-sdk@~4.3.6
+ ```
+
+ #### gemini
+
+ [`gemini`](https://wagmi.sh/core/api/connectors/gemini) requires `@gemini-wallet/core`
+
+ ```
+ pnpm add @gemini-wallet/core@~0.3.1
+ ```
+
+ #### metaMask
+
+ [`metaMask`](https://wagmi.sh/core/api/connectors/metaMask) requires `@metamask/sdk`
+
+ ```
+ pnpm add @metamask/sdk@~0.33.1
+ ```
+
+ #### porto
+
+ [`porto`](https://wagmi.sh/core/api/connectors/porto) requires `porto`
+
+ ```
+ pnpm add porto@~0.2.35
+ ```
+
+ #### safe
+
+ [`safe`](https://wagmi.sh/core/api/connectors/safe) requires `@safe-global/safe-apps-provider` and `@safe-global/safe-apps-sdk`
+
+ ```
+ pnpm add @safe-global/safe-apps-provider@~0.18.6 @safe-global/safe-apps-sdk@~9.1.0
+ ```
+
+ #### walletConnect
+
+ [`walletConnect`](https://wagmi.sh/core/api/connectors/walletConnect) requires `walletconnect/ethereum-provider`
+
+ ```
+ pnpm add @walletconnect/ethereum-provider@~2.21.1
+ ```
+
+## 2.22.1
+
+### Patch Changes
+
+- Fixed passing `account` in `waitForTransactionReceipt` for reverted transaction. ([#4832](https://github.com/wevm/wagmi/pull/4832))
+
+## 2.22.0
+
+### Minor Changes
+
+- Added `sendTransactionSync` and `sendCallsSync` Actions. ([#4823](https://github.com/wevm/wagmi/pull/4823))
+
+## 2.21.2
+
+### Patch Changes
+
+- Added `assertChainId` parameter to `getConnectorClient`. ([`866aeb0`](https://github.com/wevm/wagmi/commit/866aeb0e6361ef9114246e50149c1077bc05bf10))
+
+## 2.21.1
+
+### Patch Changes
+
+- Fixed `getConnectors` comparison ([#4792](https://github.com/wevm/wagmi/pull/4792))
+
+## 2.21.0
+
+### Minor Changes
+
+- [#4784](https://github.com/wevm/wagmi/pull/4784) [`8736133a13eb82099e20468b735525a266fdfd6c`](https://github.com/wevm/wagmi/commit/8736133a13eb82099e20468b735525a266fdfd6c) Thanks [@tmm](https://github.com/tmm)! - Added `withCapabilities` option to `connect` for exposing response capabilities.
+
+## 2.20.3
+
+### Patch Changes
+
+- [#4752](https://github.com/wevm/wagmi/pull/4752) [`ce06e137e7bfaf000464b1cecd6c86e19a66ebcf`](https://github.com/wevm/wagmi/commit/ce06e137e7bfaf000464b1cecd6c86e19a66ebcf) Thanks [@iamakulov](https://github.com/iamakulov)! - Fixed `deepEqual` crashing for objects with no prototype
+
+## 2.20.2
+
+### Patch Changes
+
+- [#4733](https://github.com/wevm/wagmi/pull/4733) [`986b96427a4bb743d2673dfbc7e8cb5041316db3`](https://github.com/wevm/wagmi/commit/986b96427a4bb743d2673dfbc7e8cb5041316db3) Thanks [@effie-ms](https://github.com/effie-ms)! - Fixed `getConnectorClient` chain ID race condition.
+
+## 2.20.1
+
+### Patch Changes
+
+- [#4773](https://github.com/wevm/wagmi/pull/4773) [`d4c367ca46c508598c997cf229a31593a1e2b8b8`](https://github.com/wevm/wagmi/commit/d4c367ca46c508598c997cf229a31593a1e2b8b8) Thanks [@tmm](https://github.com/tmm)! - Fixed issue with codegen actions/hooks, where `syncConnectedChain: false` did not work as intended.
+
+## 2.20.0
+
+### Minor Changes
+
+- [#4770](https://github.com/wevm/wagmi/pull/4770) [`a13aa2b68890f180f6ac3f741cbb9817494cb66c`](https://github.com/wevm/wagmi/commit/a13aa2b68890f180f6ac3f741cbb9817494cb66c) Thanks [@tmm](https://github.com/tmm)! - Added internal `revalidate` function.
+
+## 2.19.0
+
+### Minor Changes
+
+- [#4756](https://github.com/wevm/wagmi/pull/4756) [`b5f017dbc707729eb0b36d617352be224d1139d4`](https://github.com/wevm/wagmi/commit/b5f017dbc707729eb0b36d617352be224d1139d4) Thanks [@plusminushalf](https://github.com/plusminushalf)! - Added `getAction` to `sendCalls` and `getCallsStatus`
+
+## 2.18.1
+
+### Patch Changes
+
+- [#4704](https://github.com/wevm/wagmi/pull/4704) [`6514ba29a5acb918773235fed0238d7d679d06d5`](https://github.com/wevm/wagmi/commit/6514ba29a5acb918773235fed0238d7d679d06d5) Thanks [@iceanddust](https://github.com/iceanddust)! - Added missing `from` address to the `wallet_sendCalls` handler in the `mock` connector
+
+## 2.18.0
+
+### Minor Changes
+
+- [#4734](https://github.com/wevm/wagmi/pull/4734) [`eac550ae5b49f96a7e3404a6d88adc62d3889013`](https://github.com/wevm/wagmi/commit/eac550ae5b49f96a7e3404a6d88adc62d3889013) Thanks [@jxom](https://github.com/jxom)! - Added `baseAccount` connector.
+
+## 2.17.3
+
+### Patch Changes
+
+- [#4700](https://github.com/wevm/wagmi/pull/4700) [`7ce242b549d8cc78e6c319d9ee419693da36704c`](https://github.com/wevm/wagmi/commit/7ce242b549d8cc78e6c319d9ee419693da36704c) Thanks [@jade-u410](https://github.com/jade-u410)! - Updated `@coinbase/wallet-sdk` to 4.3.3
+
+## 2.17.2
+
+### Patch Changes
+
+- [`29297a48af72b537173d948ccd2fe37d39914c66`](https://github.com/wevm/wagmi/commit/29297a48af72b537173d948ccd2fe37d39914c66) Thanks [@jxom](https://github.com/jxom)! - Fixed `sendCalls` generics.
+
+- [`07370106d5fb6b8fe300992d93abf25b3d0eaf57`](https://github.com/wevm/wagmi/commit/07370106d5fb6b8fe300992d93abf25b3d0eaf57) Thanks [@jxom](https://github.com/jxom)! - Fixed propagation of `waitForCallsStatus` parameters.
+
+## 2.17.1
+
+### Patch Changes
+
+- [#4649](https://github.com/wevm/wagmi/pull/4649) [`01f64e64fa4f85cdd30023903f972f4f9023681f`](https://github.com/wevm/wagmi/commit/01f64e64fa4f85cdd30023903f972f4f9023681f) Thanks [@jxom](https://github.com/jxom)! - Added `chainId` parameter to `getCapabilities`/`useCapabilities`.
+
+## 2.17.0
+
+### Minor Changes
+
+- [#4638](https://github.com/wevm/wagmi/pull/4638) [`799ee4d4b23c2ecd64e3f3668e67634e81939719`](https://github.com/wevm/wagmi/commit/799ee4d4b23c2ecd64e3f3668e67634e81939719) Thanks [@jxom](https://github.com/jxom)! - Stabilized EIP-5792 Actions & Hooks.
+
## 2.16.7
### Patch Changes
diff --git a/packages/core/package.json b/packages/core/package.json
index a63d491953..ef21b86308 100644
--- a/packages/core/package.json
+++ b/packages/core/package.json
@@ -1,7 +1,7 @@
{
"name": "@wagmi/core",
"description": "VanillaJS library for Ethereum",
- "version": "2.16.7",
+ "version": "3.2.2",
"license": "MIT",
"repository": {
"type": "git",
@@ -9,10 +9,10 @@
"directory": "packages/core"
},
"scripts": {
- "build": "pnpm run clean && pnpm run build:esm+types",
+ "build": "pnpm run build:esm+types",
"build:esm+types": "tsc --project tsconfig.build.json --outDir ./dist/esm --declaration --declarationMap --declarationDir ./dist/types",
"check:types": "tsc --noEmit",
- "clean": "rm -rf dist tsconfig.tsbuildinfo actions chains codegen experimental internal query",
+ "clean": "rm -rf dist tsconfig.tsbuildinfo actions chains codegen internal query tempo",
"test:build": "publint --strict && attw --pack --ignore-rules cjs-resolves-to-esm"
},
"files": [
@@ -23,9 +23,9 @@
"!src/**/*.test-d.ts",
"/actions",
"/chains",
- "/experimental",
"/internal",
- "/query"
+ "/query",
+ "/tempo"
],
"sideEffects": false,
"type": "module",
@@ -49,10 +49,6 @@
"types": "./dist/types/exports/codegen.d.ts",
"default": "./dist/esm/exports/codegen.js"
},
- "./experimental": {
- "types": "./dist/types/exports/experimental.d.ts",
- "default": "./dist/esm/exports/experimental.js"
- },
"./internal": {
"types": "./dist/types/exports/internal.d.ts",
"default": "./dist/esm/exports/internal.js"
@@ -61,27 +57,47 @@
"types": "./dist/types/exports/query.d.ts",
"default": "./dist/esm/exports/query.js"
},
+ "./tempo": {
+ "types": "./dist/types/exports/tempo.d.ts",
+ "default": "./dist/esm/exports/tempo.js"
+ },
"./package.json": "./package.json"
},
"typesVersions": {
"*": {
- "actions": ["./dist/types/exports/actions.d.ts"],
- "chains": ["./dist/types/exports/chains.d.ts"],
- "codegen": ["./dist/types/exports/codegen.d.ts"],
- "experimental": ["./dist/types/exports/experimental.d.ts"],
- "internal": ["./dist/types/exports/internal.d.ts"],
- "query": ["./dist/types/exports/query.d.ts"]
+ "actions": [
+ "./dist/types/exports/actions.d.ts"
+ ],
+ "chains": [
+ "./dist/types/exports/chains.d.ts"
+ ],
+ "codegen": [
+ "./dist/types/exports/codegen.d.ts"
+ ],
+ "internal": [
+ "./dist/types/exports/internal.d.ts"
+ ],
+ "query": [
+ "./dist/types/exports/query.d.ts"
+ ],
+ "tempo": [
+ "./dist/types/exports/tempo.d.ts"
+ ]
}
},
"peerDependencies": {
"@tanstack/query-core": ">=5.0.0",
- "typescript": ">=5.0.4",
+ "ox": ">=0.11.1",
+ "typescript": ">=5.7.3",
"viem": "2.x"
},
"peerDependenciesMeta": {
"@tanstack/query-core": {
"optional": true
},
+ "ox": {
+ "optional": true
+ },
"typescript": {
"optional": true
}
@@ -92,9 +108,20 @@
"zustand": "5.0.0"
},
"devDependencies": {
- "@tanstack/query-core": "catalog:"
+ "@tanstack/query-core": "catalog:",
+ "ox": "catalog:"
},
- "contributors": ["awkweb.eth ", "jxom.eth "],
+ "contributors": [
+ "awkweb.eth ",
+ "jxom.eth "
+ ],
"funding": "https://github.com/sponsors/wevm",
- "keywords": ["wagmi", "eth", "ethereum", "dapps", "wallet", "web3"]
+ "keywords": [
+ "wagmi",
+ "eth",
+ "ethereum",
+ "dapps",
+ "wallet",
+ "web3"
+ ]
}
diff --git a/packages/core/src/actions/call.test.ts b/packages/core/src/actions/call.test.ts
index fb8cfc9030..c0024c90d6 100644
--- a/packages/core/src/actions/call.test.ts
+++ b/packages/core/src/actions/call.test.ts
@@ -76,12 +76,12 @@ test('insufficient funds', async () => {
- \`value\` is the amount of ether to send to the recipient.
Raw Call Arguments:
- from: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
- to: 0x70997970c51812dc3a010c7d01b50e0d17dc79c8
+ from: 0x95132632579b073D12a6673e18Ab05777a6B86f8
+ to: 0x1D5D7e139A994CeE7f360be398Ef032fE5D74fce
value: 100000 ETH
Details: Insufficient funds for gas * price + value
- Version: viem@2.23.12]
+ Version: viem@2.44.0]
`)
})
@@ -98,13 +98,13 @@ test('maxFeePerGas less than maxPriorityFeePerGas', async () => {
[CallExecutionError: The provided tip (\`maxPriorityFeePerGas\` = 22 gwei) cannot be higher than the fee cap (\`maxFeePerGas\` = 20 gwei).
Raw Call Arguments:
- from: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
+ from: 0x95132632579b073D12a6673e18Ab05777a6B86f8
to: 0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2
data: 0x06fdde03
maxFeePerGas: 20 gwei
maxPriorityFeePerGas: 22 gwei
- Version: viem@2.23.12]
+ Version: viem@2.44.0]
`)
})
@@ -116,15 +116,15 @@ test('contract revert (contract error)', async () => {
to: address.wagmiMintExample,
}),
).rejects.toThrowErrorMatchingInlineSnapshot(`
- [CallExecutionError: Execution reverted with reason: revert: Token ID is taken.
+ [CallExecutionError: Execution reverted with reason: Token ID is taken.
Raw Call Arguments:
- from: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
+ from: 0x95132632579b073D12a6673e18Ab05777a6B86f8
to: 0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2
data: 0xa0712d6800000000000000000000000000000000000000000000000000000000000001a4
- Details: execution reverted: revert: Token ID is taken
- Version: viem@2.23.12]
+ Details: execution reverted: Token ID is taken
+ Version: viem@2.44.0]
`)
})
@@ -139,11 +139,11 @@ test('contract revert (insufficient params)', async () => {
[CallExecutionError: Execution reverted for an unknown reason.
Raw Call Arguments:
- from: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
+ from: 0x95132632579b073D12a6673e18Ab05777a6B86f8
to: 0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2
data: 0xa0712d68
Details: execution reverted
- Version: viem@2.23.12]
+ Version: viem@2.44.0]
`)
})
diff --git a/packages/core/src/actions/codegen/createReadContract.test.ts b/packages/core/src/actions/codegen/createReadContract.test.ts
index 9de7ae718f..d43856e936 100644
--- a/packages/core/src/actions/codegen/createReadContract.test.ts
+++ b/packages/core/src/actions/codegen/createReadContract.test.ts
@@ -14,7 +14,7 @@ test('default', async () => {
functionName: 'balanceOf',
args: ['0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC'],
}),
- ).resolves.toMatchInlineSnapshot('4n')
+ ).resolves.toMatchInlineSnapshot('10n')
})
test('multichain', async () => {
@@ -32,7 +32,7 @@ test('multichain', async () => {
args: ['0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC'],
chainId: chain.mainnet2.id,
}),
- ).resolves.toMatchInlineSnapshot('4n')
+ ).resolves.toMatchInlineSnapshot('10n')
})
test('functionName', async () => {
@@ -46,5 +46,5 @@ test('functionName', async () => {
readWagmiMintExampleBalanceOf(config, {
args: ['0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC'],
}),
- ).resolves.toMatchInlineSnapshot('4n')
+ ).resolves.toMatchInlineSnapshot('10n')
})
diff --git a/packages/core/src/actions/codegen/createReadContract.ts b/packages/core/src/actions/codegen/createReadContract.ts
index f7dbfbed45..32c14da4bb 100644
--- a/packages/core/src/actions/codegen/createReadContract.ts
+++ b/packages/core/src/actions/codegen/createReadContract.ts
@@ -7,7 +7,6 @@ import type {
import type { Config } from '../../createConfig.js'
import type { UnionCompute, UnionStrictOmit } from '../../types/utils.js'
-import { getAccount } from '../getAccount.js'
import { getChainId } from '../getChainId.js'
import {
type ReadContractParameters,
@@ -76,11 +75,8 @@ export function createReadContract<
if (c.address !== undefined && typeof c.address === 'object')
return (config, parameters) => {
const configChainId = getChainId(config)
- const account = getAccount(config)
const chainId =
- (parameters as { chainId?: number })?.chainId ??
- account.chainId ??
- configChainId
+ (parameters as { chainId?: number })?.chainId ?? configChainId
return readContract(config, {
...(parameters as any),
...(c.functionName ? { functionName: c.functionName } : {}),
diff --git a/packages/core/src/actions/codegen/createSimulateContract.test-d.ts b/packages/core/src/actions/codegen/createSimulateContract.test-d.ts
index 91e5998977..764d3075f9 100644
--- a/packages/core/src/actions/codegen/createSimulateContract.test-d.ts
+++ b/packages/core/src/actions/codegen/createSimulateContract.test-d.ts
@@ -1,5 +1,5 @@
import { abi, config, mainnet, optimism } from '@wagmi/test'
-import { http, type Address } from 'viem'
+import { type Address, http } from 'viem'
import { celo } from 'viem/chains'
import { assertType, expectTypeOf, test } from 'vitest'
diff --git a/packages/core/src/actions/codegen/createSimulateContract.test.ts b/packages/core/src/actions/codegen/createSimulateContract.test.ts
index bd37d13770..94fc041d30 100644
--- a/packages/core/src/actions/codegen/createSimulateContract.test.ts
+++ b/packages/core/src/actions/codegen/createSimulateContract.test.ts
@@ -3,6 +3,7 @@ import { expect, test } from 'vitest'
import { connect } from '../connect.js'
import { disconnect } from '../disconnect.js'
+import { switchChain } from '../switchChain.js'
import { createSimulateContract } from './createSimulateContract.js'
const connector = config.connectors[0]!
@@ -33,7 +34,7 @@ test('default', async () => {
},
],
"account": {
- "address": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
+ "address": "0x95132632579b073D12a6673e18Ab05777a6B86f8",
"type": "json-rpc",
},
"address": "0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2",
@@ -60,6 +61,15 @@ test('multichain', async () => {
abi: abi.wagmiMintExample,
})
+ await expect(
+ simulateWagmiMintExample(config, {
+ functionName: 'mint',
+ }),
+ ).resolves.toMatchObject({
+ chainId: 1,
+ })
+
+ await switchChain(config, { chainId: chain.mainnet2.id })
await expect(
simulateWagmiMintExample(config, {
functionName: 'mint',
@@ -79,7 +89,7 @@ test('multichain', async () => {
},
],
"account": {
- "address": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
+ "address": "0x95132632579b073D12a6673e18Ab05777a6B86f8",
"type": "json-rpc",
},
"address": "0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2",
@@ -92,6 +102,7 @@ test('multichain', async () => {
}
`)
+ await switchChain(config, { chainId: chain.mainnet.id })
await disconnect(config, { connector })
})
@@ -120,7 +131,7 @@ test('functionName', async () => {
},
],
"account": {
- "address": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
+ "address": "0x95132632579b073D12a6673e18Ab05777a6B86f8",
"type": "json-rpc",
},
"address": "0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2",
diff --git a/packages/core/src/actions/codegen/createSimulateContract.ts b/packages/core/src/actions/codegen/createSimulateContract.ts
index 016384e245..efdbe0cd39 100644
--- a/packages/core/src/actions/codegen/createSimulateContract.ts
+++ b/packages/core/src/actions/codegen/createSimulateContract.ts
@@ -15,7 +15,6 @@ import type {
ConnectorParameter,
} from '../../types/properties.js'
import type { UnionCompute, UnionStrictOmit } from '../../types/utils.js'
-import { getAccount } from '../getAccount.js'
import { getChainId } from '../getChainId.js'
import {
type SimulateContractReturnType,
@@ -98,11 +97,8 @@ export function createSimulateContract<
if (c.address !== undefined && typeof c.address === 'object')
return (config, parameters) => {
const configChainId = getChainId(config)
- const account = getAccount(config)
const chainId =
- (parameters as { chainId?: number })?.chainId ??
- account.chainId ??
- configChainId
+ (parameters as { chainId?: number })?.chainId ?? configChainId
return simulateContract(config, {
...(parameters as any),
...(c.functionName ? { functionName: c.functionName } : {}),
diff --git a/packages/core/src/actions/codegen/createWatchContractEvent.test.ts b/packages/core/src/actions/codegen/createWatchContractEvent.test.ts
index 19ba09b2a2..9dd13bafbb 100644
--- a/packages/core/src/actions/codegen/createWatchContractEvent.test.ts
+++ b/packages/core/src/actions/codegen/createWatchContractEvent.test.ts
@@ -1,4 +1,4 @@
-import { abi, address, chain, config } from '@wagmi/test'
+import { abi, address, chain, config, wait } from '@wagmi/test'
import type { WatchEventOnLogsParameter } from 'viem'
import { test } from 'vitest'
@@ -17,7 +17,9 @@ test('default', async () => {
logs = logs.concat(next)
},
})
+ await wait(500)
unwatch()
+ await wait(500)
})
test('multichain', async () => {
@@ -37,5 +39,7 @@ test('multichain', async () => {
logs = logs.concat(next)
},
})
+ await wait(500)
unwatch()
+ await wait(500)
})
diff --git a/packages/core/src/actions/codegen/createWatchContractEvent.ts b/packages/core/src/actions/codegen/createWatchContractEvent.ts
index 2817efc704..f9c701018c 100644
--- a/packages/core/src/actions/codegen/createWatchContractEvent.ts
+++ b/packages/core/src/actions/codegen/createWatchContractEvent.ts
@@ -2,7 +2,6 @@ import type { Abi, Address, ContractEventName } from 'viem'
import type { Config } from '../../createConfig.js'
import type { UnionCompute, UnionStrictOmit } from '../../types/utils.js'
-import { getAccount } from '../getAccount.js'
import { getChainId } from '../getChainId.js'
import {
type WatchContractEventParameters,
@@ -64,11 +63,8 @@ export function createWatchContractEvent<
if (c.address !== undefined && typeof c.address === 'object')
return (config, parameters) => {
const configChainId = getChainId(config)
- const account = getAccount(config)
const chainId =
- (parameters as { chainId?: number })?.chainId ??
- account.chainId ??
- configChainId
+ (parameters as { chainId?: number })?.chainId ?? configChainId
return watchContractEvent(config, {
...(parameters as any),
...(c.eventName ? { eventName: c.eventName } : {}),
diff --git a/packages/core/src/actions/codegen/createWriteContract.ts b/packages/core/src/actions/codegen/createWriteContract.ts
index 6c1d891a3f..e02b51db94 100644
--- a/packages/core/src/actions/codegen/createWriteContract.ts
+++ b/packages/core/src/actions/codegen/createWriteContract.ts
@@ -19,7 +19,6 @@ import type {
UnionCompute,
UnionStrictOmit,
} from '../../types/utils.js'
-import { getAccount } from '../getAccount.js'
import { getChainId } from '../getChainId.js'
import {
type WriteContractReturnType,
@@ -86,10 +85,7 @@ export type CreateWriteContractReturnType<
| undefined
}
: Compute>) &
- ConnectorParameter & {
- /** @deprecated */
- __mode?: 'prepared'
- }
+ ConnectorParameter
>,
) => Promise
@@ -107,25 +103,10 @@ export function createWriteContract<
): CreateWriteContractReturnType {
if (c.address !== undefined && typeof c.address === 'object')
return (config, parameters) => {
- const configChainId = getChainId(config)
- const account = getAccount(config)
-
- let chainId: number | undefined
- if (parameters.chainId) chainId = parameters.chainId
- else if (
- (parameters as unknown as { account: Address | Account | undefined })
- .account &&
- (parameters as unknown as { account: Address | Account | undefined })
- .account === account.address
- )
- chainId = account.chainId
- else if (
- (parameters as unknown as { account: Address | Account | undefined })
- .account === undefined
- )
- chainId = account.chainId
- else chainId = configChainId
-
+ const chainId = (() => {
+ if (parameters.chainId) return parameters.chainId
+ return getChainId(config)
+ })()
return writeContract(config, {
...(parameters as any),
...(c.functionName ? { functionName: c.functionName } : {}),
diff --git a/packages/core/src/actions/connect.test-d.ts b/packages/core/src/actions/connect.test-d.ts
index ad790b1209..00ff13b76c 100644
--- a/packages/core/src/actions/connect.test-d.ts
+++ b/packages/core/src/actions/connect.test-d.ts
@@ -1,5 +1,5 @@
-import { accounts } from '@wagmi/test'
-import { http } from 'viem'
+import { accounts, config as testConfig } from '@wagmi/test'
+import { type Address, type Hex, http } from 'viem'
import { mainnet } from 'viem/chains'
import { expectTypeOf, test } from 'vitest'
@@ -46,3 +46,46 @@ test('parameters: connector (Connector)', () => {
>
expectTypeOf().toEqualTypeOf()
})
+
+test('parameters: withCapabilities', async () => {
+ const connectorFn = mock({ accounts })
+
+ const res0 = await connect(config, { connector: connectorFn })
+ expectTypeOf(res0.accounts).toEqualTypeOf()
+
+ const res1 = await connect(config, {
+ connector: connectorFn,
+ withCapabilities: false,
+ })
+ expectTypeOf(res1.accounts).toEqualTypeOf()
+
+ const res2 = await connect(config, {
+ connector: connectorFn,
+ withCapabilities: true,
+ })
+ expectTypeOf(res2.accounts).toEqualTypeOf<
+ readonly [
+ {
+ address: Address
+ capabilities: {
+ foo: { bar: Hex }
+ }
+ },
+ ...{
+ address: Address
+ capabilities: {
+ foo: { bar: Hex }
+ }
+ }[],
+ ]
+ >()
+})
+
+test('behavior: with config', () => {
+ connect(testConfig, {
+ connector: testConfig.connectors[0]!,
+ foo: 'bar',
+ })
+ // @ts-expect-error
+ testConfig.connectors[4]
+})
diff --git a/packages/core/src/actions/connect.test.ts b/packages/core/src/actions/connect.test.ts
index a9c591895a..810a9a85c5 100644
--- a/packages/core/src/actions/connect.test.ts
+++ b/packages/core/src/actions/connect.test.ts
@@ -15,7 +15,7 @@ beforeEach(async () => {
test('default', async () => {
await expect(connect(config, { connector })).resolves.toMatchObject(
expect.objectContaining({
- accounts: expect.any(Array),
+ accounts: expect.arrayContaining([expect.any(String)]),
chainId: expect.any(Number),
}),
)
@@ -25,7 +25,7 @@ test('parameters: chainId', async () => {
const chainId = chain.mainnet2.id
await expect(connect(config, { connector, chainId })).resolves.toMatchObject(
expect.objectContaining({
- accounts: expect.any(Array),
+ accounts: expect.arrayContaining([expect.any(String)]),
chainId,
}),
)
@@ -37,13 +37,30 @@ test('parameters: connector', async () => {
connect(config, { connector: connector_ }),
).resolves.toMatchObject(
expect.objectContaining({
- accounts: expect.any(Array),
+ accounts: expect.arrayContaining([expect.any(String)]),
chainId: expect.any(Number),
}),
)
await disconnect(config, { connector: connector_ })
})
+test('parameters: withCapabilities', async () => {
+ await expect(
+ connect(config, { connector, withCapabilities: true }),
+ ).resolves.toMatchObject(
+ expect.objectContaining({
+ accounts: expect.arrayContaining([
+ expect.objectContaining({
+ address: expect.any(String),
+ capabilities: expect.objectContaining({
+ foo: expect.objectContaining({ bar: expect.any(String) }),
+ }),
+ }),
+ ]),
+ }),
+ )
+})
+
test('behavior: user rejected request', async () => {
const connector_ = config._internal.connectors.setup(
mock({
@@ -57,7 +74,7 @@ test('behavior: user rejected request', async () => {
[UserRejectedRequestError: User rejected the request.
Details: Failed to connect.
- Version: viem@2.23.12]
+ Version: viem@2.44.0]
`)
})
diff --git a/packages/core/src/actions/connect.ts b/packages/core/src/actions/connect.ts
index f69809e504..ae9bf93a5c 100644
--- a/packages/core/src/actions/connect.ts
+++ b/packages/core/src/actions/connect.ts
@@ -19,6 +19,7 @@ export type ConnectParameters<
connector extends Connector | CreateConnectorFn =
| Connector
| CreateConnectorFn,
+ withCapabilities extends boolean = false,
///
parameters extends unknown | undefined =
| (connector extends CreateConnectorFn
@@ -36,12 +37,46 @@ export type ConnectParameters<
> = Compute<
ChainIdParameter & {
connector: connector | CreateConnectorFn
+ withCapabilities?: withCapabilities | boolean | undefined
}
> &
parameters
-export type ConnectReturnType = {
- accounts: readonly [Address, ...Address[]]
+export type ConnectReturnType<
+ config extends Config = Config,
+ connector extends Connector | CreateConnectorFn =
+ | Connector
+ | CreateConnectorFn,
+ withCapabilities extends boolean = false,
+ ///
+ capabilities extends unknown | undefined =
+ | (connector extends CreateConnectorFn
+ ? Awaited<
+ ReturnType['connect']>
+ >['accounts'] extends
+ | readonly Address[]
+ | readonly {
+ capabilities: infer capabilities
+ }[]
+ ? capabilities
+ : Record
+ : never)
+ | (connector extends Connector
+ ? Awaited>['accounts'] extends
+ | readonly Address[]
+ | readonly {
+ capabilities: infer capabilities
+ }[]
+ ? capabilities
+ : Record
+ : never),
+> = {
+ accounts: withCapabilities extends true
+ ? readonly [
+ { address: Address; capabilities: capabilities },
+ ...{ address: Address; capabilities: capabilities }[],
+ ]
+ : readonly [Address, ...Address[]]
chainId:
| config['chains'][number]['id']
| (number extends config['chains'][number]['id'] ? number : number & {})
@@ -60,10 +95,11 @@ export type ConnectErrorType =
export async function connect<
config extends Config,
connector extends Connector | CreateConnectorFn,
+ withCapabilities extends boolean = false,
>(
config: config,
- parameters: ConnectParameters,
-): Promise> {
+ parameters: ConnectParameters,
+): Promise> {
// "Register" connector if not already created
let connector: Connector
if (typeof parameters.connector === 'function') {
@@ -80,7 +116,6 @@ export async function connect<
const { connector: _, ...rest } = parameters
const data = await connector.connect(rest)
- const accounts = data.accounts as readonly [Address, ...Address[]]
connector.emitter.off('connect', config._internal.events.connect)
connector.emitter.on('change', config._internal.events.change)
@@ -90,7 +125,11 @@ export async function connect<
config.setState((x) => ({
...x,
connections: new Map(x.connections).set(connector.uid, {
- accounts,
+ accounts: (rest.withCapabilities
+ ? data.accounts.map((account) =>
+ typeof account === 'object' ? account.address : account,
+ )
+ : data.accounts) as readonly [Address, ...Address[]],
chainId: data.chainId,
connector: connector,
}),
@@ -98,7 +137,18 @@ export async function connect<
status: 'connected',
}))
- return { accounts, chainId: data.chainId }
+ return {
+ // TODO(v3): Remove `withCapabilities: true` default behavior so remove compat marshalling
+ // Workaround so downstream connectors work with `withCapabilities` without any changes required
+ accounts: (rest.withCapabilities
+ ? data.accounts.map((address) =>
+ typeof address === 'object'
+ ? address
+ : { address, capabilities: {} },
+ )
+ : data.accounts) as never,
+ chainId: data.chainId,
+ }
} catch (error) {
config.setState((x) => ({
...x,
diff --git a/packages/core/src/actions/deployContract.test.ts b/packages/core/src/actions/deployContract.test.ts
index 06b545a77e..9a97f1394b 100644
--- a/packages/core/src/actions/deployContract.test.ts
+++ b/packages/core/src/actions/deployContract.test.ts
@@ -56,11 +56,11 @@ test('behavior: no funds', async () => {
Request Arguments:
chain: undefined (id: 1)
- from: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
+ from: 0x95132632579b073D12a6673e18Ab05777a6B86f8
data: 0x608060405260405180602001604052806000815250600b90805190602001906200002b92919062000484565b506000600f60006101000a81548160ff0219169083151502179055503480156200005457600080fd5b50604051620046d0380380620046d0833981810160405260808110156200007a57600080fd5b81019080805160405193929190846401000000008211156200009b57600080fd5b83820191506020820185811115620000b257600080fd5b8251866001820283011164010000000082111715620000d057600080fd5b8083526020830192505050908051906020019080838360005b8381101562000106578082015181840152602081019050620000e9565b50505050905090810190601f168015620001345780820380516001836020036101000a031916815260200191505b50604052602001805160405193929190846401000000008211156200015857600080fd5b838201915060208201858111156200016f57600080fd5b82518660018202830111640100000000821117156200018d57600080fd5b8083526020830192505050908051906020019080838360005b83811015620001c3578082015181840152602081019050620001a6565b50505050905090810190601f168015620001f15780820380516001836020036101000a031916815260200191505b5060405260200180519060200190929190805190602001909291905050508383620002296301ffc9a760e01b6200037360201b60201c565b81600690805190602001906200024192919062000484565b5080600790805190602001906200025a92919062000484565b50620002736380ac58cd60e01b6200037360201b60201c565b6200028b635b5e139f60e01b6200037360201b60201c565b620002a363780e9d6360e01b6200037360201b60201c565b50506000620002b76200047c60201b60201c565b905080600a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff1602179055508073ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a35081600e81905550620bdd808101601081905550505050506200052a565b63ffffffff60e01b817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916141562000410576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f4552433136353a20696e76616c696420696e746572666163652069640000000081525060200191505060405180910390fd5b6001600080837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060006101000a81548160ff02191690831515021790555050565b600033905090565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10620004c757805160ff1916838001178555620004f8565b82800160010185558215620004f8579182015b82811115620004f7578251825591602001919060010190620004da565b5b5090506200050791906200050b565b5090565b5b80821115620005265760008160009055506001016200050c565b5090565b614196806200053a6000396000f3fe60806040526004361061021a5760003560e01c80636c0360eb11610123578063b0f67427116100ab578063e36d64981161006f578063e36d649814610ddf578063e985e9c514610e0a578063e986655014610e91578063eb8d244414610ea8578063f2fde38b14610ed55761021a565b8063b0f6742714610bac578063b88d4fde14610bc3578063bb8a16bd14610cd5578063c87b56dd14610d00578063cb774d4714610db45761021a565b80637d17fcbe116100f25780637d17fcbe14610a395780638da5cb5b14610a5057806395d89b4114610a91578063a22cb46514610b21578063a723533e14610b7e5761021a565b80636c0360eb1461090257806370a0823114610992578063715018a6146109f75780637a3f451e14610a0e5761021a565b80632f745c59116101a65780634f6ccce7116101755780634f6ccce7146106cb57806355f804b31461071a578063571dff3b146107e2578063607e20e31461080d5780636352211e1461089d5761021a565b80632f745c59146105b357806334918dfd146106225780633ccfd60b1461063957806342842e0e146106505761021a565b8063095ea7b3116101ed578063095ea7b3146103bf578063109695231461041a57806318160ddd146104e257806318e20a381461050d57806323b872dd146105385761021a565b8063018a2c371461021f57806301ffc9a71461025a57806306fdde03146102ca578063081812fc1461035a575b600080fd5b34801561022b57600080fd5b506102586004803603602081101561024257600080fd5b8101908080359060200190929190505050610f26565b005b34801561026657600080fd5b506102b26004803603602081101561027d57600080fd5b8101908080357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19169060200190929190505050610fdf565b60405180821515815260200191505060405180910390f35b3480156102d657600080fd5b506102df611046565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561031f578082015181840152602081019050610304565b50505050905090810190601f16801561034c5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561036657600080fd5b506103936004803603602081101561037d57600080fd5b81019080803590602001909291905050506110e8565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b3480156103cb57600080fd5b50610418600480360360408110156103e257600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050611183565b005b34801561042657600080fd5b506104e06004803603602081101561043d57600080fd5b810190808035906020019064010000000081111561045a57600080fd5b82018360208201111561046c57600080fd5b8035906020019184600183028401116401000000008311171561048e57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f8201169050808301925050505050505091929192905050506112c7565b005b3480156104ee57600080fd5b506104f7611390565b6040518082815260200191505060405180910390f35b34801561051957600080fd5b506105226113a1565b6040518082815260200191505060405180910390f35b34801561054457600080fd5b506105b16004803603606081101561055b57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803590602001909291905050506113a7565b005b3480156105bf57600080fd5b5061060c600480360360408110156105d657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919050505061141d565b6040518082815260200191505060405180910390f35b34801561062e57600080fd5b50610637611478565b005b34801561064557600080fd5b5061064e611553565b005b34801561065c57600080fd5b506106c96004803603606081101561067357600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff16906020019092919080359060200190929190505050611651565b005b3480156106d757600080fd5b50610704600480360360208110156106ee57600080fd5b8101908080359060200190929190505050611671565b6040518082815260200191505060405180910390f35b34801561072657600080fd5b506107e06004803603602081101561073d57600080fd5b810190808035906020019064010000000081111561075a57600080fd5b82018360208201111561076c57600080fd5b8035906020019184600183028401116401000000008311171561078e57600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f820116905080830192505050505050509192919290505050611694565b005b3480156107ee57600080fd5b506107f761174f565b6040518082815260200191505060405180910390f35b34801561081957600080fd5b50610822611754565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610862578082015181840152602081019050610847565b50505050905090810190601f16801561088f5780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b3480156108a957600080fd5b506108d6600480360360208110156108c057600080fd5b81019080803590602001909291905050506117f2565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b34801561090e57600080fd5b50610917611829565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561095757808201518184015260208101905061093c565b50505050905090810190601f1680156109845780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561099e57600080fd5b506109e1600480360360208110156109b557600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff1690602001909291905050506118cb565b6040518082815260200191505060405180910390f35b348015610a0357600080fd5b50610a0c6119a0565b005b348015610a1a57600080fd5b50610a23611b10565b6040518082815260200191505060405180910390f35b348015610a4557600080fd5b50610a4e611b1c565b005b348015610a5c57600080fd5b50610a65611c4c565b604051808273ffffffffffffffffffffffffffffffffffffffff16815260200191505060405180910390f35b348015610a9d57600080fd5b50610aa6611c76565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610ae6578082015181840152602081019050610acb565b50505050905090810190601f168015610b135780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b348015610b2d57600080fd5b50610b7c60048036036040811015610b4457600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803515159060200190929190505050611d18565b005b610baa60048036036020811015610b9457600080fd5b8101908080359060200190929190505050611ece565b005b348015610bb857600080fd5b50610bc1612127565b005b348015610bcf57600080fd5b50610cd360048036036080811015610be657600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff1690602001909291908035906020019092919080359060200190640100000000811115610c4d57600080fd5b820183602082011115610c5f57600080fd5b80359060200191846001830284011164010000000083111715610c8157600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600081840152601f19601f82011690508083019250505050505050919291929050505061220b565b005b348015610ce157600080fd5b50610cea612283565b6040518082815260200191505060405180910390f35b348015610d0c57600080fd5b50610d3960048036036020811015610d2357600080fd5b8101908080359060200190929190505050612289565b6040518080602001828103825283818151815260200191508051906020019080838360005b83811015610d79578082015181840152602081019050610d5e565b50505050905090810190601f168015610da65780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b348015610dc057600080fd5b50610dc961255a565b6040518082815260200191505060405180910390f35b348015610deb57600080fd5b50610df4612560565b6040518082815260200191505060405180910390f35b348015610e1657600080fd5b50610e7960048036036040811015610e2d57600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612566565b60405180821515815260200191505060405180910390f35b348015610e9d57600080fd5b50610ea66125fa565b005b348015610eb457600080fd5b50610ebd612764565b60405180821515815260200191505060405180910390f35b348015610ee157600080fd5b50610f2460048036036020811015610ef857600080fd5b81019080803573ffffffffffffffffffffffffffffffffffffffff169060200190929190505050612777565b005b610f2e61296c565b73ffffffffffffffffffffffffffffffffffffffff16610f4c611c4c565b73ffffffffffffffffffffffffffffffffffffffff1614610fd5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b8060108190555050565b6000806000837bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19167bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916815260200190815260200160002060009054906101000a900460ff169050919050565b606060068054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156110de5780601f106110b3576101008083540402835291602001916110de565b820191906000526020600020905b8154815290600101906020018083116110c157829003601f168201915b5050505050905090565b60006110f382612974565b611148576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c81526020018061408b602c913960400191505060405180910390fd5b6004600083815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050919050565b600061118e826117f2565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff161415611215576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602181526020018061410f6021913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff1661123461296c565b73ffffffffffffffffffffffffffffffffffffffff16148061126357506112628161125d61296c565b612566565b5b6112b8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526038815260200180613f956038913960400191505060405180910390fd5b6112c28383612991565b505050565b6112cf61296c565b73ffffffffffffffffffffffffffffffffffffffff166112ed611c4c565b73ffffffffffffffffffffffffffffffffffffffff1614611376576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b80600b908051906020019061138c929190613de6565b5050565b600061139c6002612a4a565b905090565b60105481565b6113b86113b261296c565b82612a5f565b61140d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260318152602001806141306031913960400191505060405180910390fd5b611418838383612b53565b505050565b600061147082600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020612d9690919063ffffffff16565b905092915050565b61148061296c565b73ffffffffffffffffffffffffffffffffffffffff1661149e611c4c565b73ffffffffffffffffffffffffffffffffffffffff1614611527576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600f60009054906101000a900460ff1615600f60006101000a81548160ff021916908315150217905550565b61155b61296c565b73ffffffffffffffffffffffffffffffffffffffff16611579611c4c565b73ffffffffffffffffffffffffffffffffffffffff1614611602576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b60004790503373ffffffffffffffffffffffffffffffffffffffff166108fc829081150290604051600060405180830381858888f1935050505015801561164d573d6000803e3d6000fd5b5050565b61166c8383836040518060200160405280600081525061220b565b505050565b600080611688836002612db090919063ffffffff16565b50905080915050919050565b61169c61296c565b73ffffffffffffffffffffffffffffffffffffffff166116ba611c4c565b73ffffffffffffffffffffffffffffffffffffffff1614611743576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b61174c81612ddc565b50565b601481565b600b8054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156117ea5780601f106117bf576101008083540402835291602001916117ea565b820191906000526020600020905b8154815290600101906020018083116117cd57829003601f168201915b505050505081565b600061182282604051806060016040528060298152602001613ff7602991396002612df69092919063ffffffff16565b9050919050565b606060098054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156118c15780601f10611896576101008083540402835291602001916118c1565b820191906000526020600020905b8154815290600101906020018083116118a457829003601f168201915b5050505050905090565b60008073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611952576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602a815260200180613fcd602a913960400191505060405180910390fd5b611999600160008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020612e15565b9050919050565b6119a861296c565b73ffffffffffffffffffffffffffffffffffffffff166119c6611c4c565b73ffffffffffffffffffffffffffffffffffffffff1614611a4f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff16600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a36000600a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550565b67011c37937e08000081565b611b2461296c565b73ffffffffffffffffffffffffffffffffffffffff16611b42611c4c565b73ffffffffffffffffffffffffffffffffffffffff1614611bcb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b6000600d5414611c43576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f5374617274696e6720696e64657820697320616c72656164792073657400000081525060200191505060405180910390fd5b43600c81905550565b6000600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905090565b606060078054600181600116156101000203166002900480601f016020809104026020016040519081016040528092919081815260200182805460018160011615610100020316600290048015611d0e5780601f10611ce357610100808354040283529160200191611d0e565b820191906000526020600020905b815481529060010190602001808311611cf157829003601f168201915b5050505050905090565b611d2061296c565b73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415611dc1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260198152602001807f4552433732313a20617070726f766520746f2063616c6c65720000000000000081525060200191505060405180910390fd5b8060056000611dce61296c565b73ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055508173ffffffffffffffffffffffffffffffffffffffff16611e7b61296c565b73ffffffffffffffffffffffffffffffffffffffff167f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c318360405180821515815260200191505060405180910390a35050565b600f60009054906101000a900460ff16611f50576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f53616c65206d7573742062652061637469766520746f206d696e74204170650081525060200191505060405180910390fd5b6014811115611faa576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526021815260200180613f746021913960400191505060405180910390fd5b600e54611fc782611fb9611390565b612e2a90919063ffffffff16565b111561201e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260288152602001806140426028913960400191505060405180910390fd5b3461203a8267011c37937e080000612eb290919063ffffffff16565b11156120ae576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601f8152602001807f45746865722076616c75652073656e74206973206e6f7420636f72726563740081525060200191505060405180910390fd5b60005b818110156120ef5760006120c3611390565b9050600e546120d0611390565b10156120e1576120e03382612f38565b5b5080806001019150506120b1565b506000600c541480156121175750600e54612108611390565b148061211657506010544210155b5b156121245743600c819055505b50565b61212f61296c565b73ffffffffffffffffffffffffffffffffffffffff1661214d611c4c565b73ffffffffffffffffffffffffffffffffffffffff16146121d6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b60006121e0611390565b905060005b601e811015612207576121fa33828401612f38565b80806001019150506121e5565b5050565b61221c61221661296c565b83612a5f565b612271576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260318152602001806141306031913960400191505060405180910390fd5b61227d84848484612f56565b50505050565b600e5481565b606061229482612974565b6122e9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602f8152602001806140e0602f913960400191505060405180910390fd5b6060600860008481526020019081526020016000208054600181600116156101000203166002900480601f0160208091040260200160405190810160405280929190818152602001828054600181600116156101000203166002900480156123925780601f1061236757610100808354040283529160200191612392565b820191906000526020600020905b81548152906001019060200180831161237557829003601f168201915b5050505050905060606123a3611829565b90506000815114156123b9578192505050612555565b60008251111561248a5780826040516020018083805190602001908083835b602083106123fb57805182526020820191506020810190506020830392506123d8565b6001836020036101000a03801982511681845116808217855250505050505090500182805190602001908083835b6020831061244c5780518252602082019150602081019050602083039250612429565b6001836020036101000a0380198251168184511680821785525050505050509050019250505060405160208183030381529060405292505050612555565b8061249485612fc8565b6040516020018083805190602001908083835b602083106124ca57805182526020820191506020810190506020830392506124a7565b6001836020036101000a03801982511681845116808217855250505050505090500182805190602001908083835b6020831061251b57805182526020820191506020810190506020830392506124f8565b6001836020036101000a03801982511681845116808217855250505050505090500192505050604051602081830303815290604052925050505b919050565b600d5481565b600c5481565b6000600560008473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16905092915050565b6000600d5414612672576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f5374617274696e6720696e64657820697320616c72656164792073657400000081525060200191505060405180910390fd5b6000600c5414156126eb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f5374617274696e6720696e64657820626c6f636b206d7573742062652073657481525060200191505060405180910390fd5b600e54600c544060001c816126fc57fe5b06600d8190555060ff61271a600c544361310f90919063ffffffff16565b111561273a57600e54600143034060001c8161273257fe5b06600d819055505b6000600d5414156127625761275b6001600d54612e2a90919063ffffffff16565b600d819055505b565b600f60009054906101000a900460ff1681565b61277f61296c565b73ffffffffffffffffffffffffffffffffffffffff1661279d611c4c565b73ffffffffffffffffffffffffffffffffffffffff1614612826576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e657281525060200191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168173ffffffffffffffffffffffffffffffffffffffff1614156128ac576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180613ed86026913960400191505060405180910390fd5b8073ffffffffffffffffffffffffffffffffffffffff16600a60009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e060405160405180910390a380600a60006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555050565b600033905090565b600061298a82600261319290919063ffffffff16565b9050919050565b816004600083815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff160217905550808273ffffffffffffffffffffffffffffffffffffffff16612a04836117f2565b73ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b6000612a58826000016131ac565b9050919050565b6000612a6a82612974565b612abf576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602c815260200180613f48602c913960400191505060405180910390fd5b6000612aca836117f2565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161480612b3957508373ffffffffffffffffffffffffffffffffffffffff16612b21846110e8565b73ffffffffffffffffffffffffffffffffffffffff16145b80612b4a5750612b498185612566565b5b91505092915050565b8273ffffffffffffffffffffffffffffffffffffffff16612b73826117f2565b73ffffffffffffffffffffffffffffffffffffffff1614612bdf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260298152602001806140b76029913960400191505060405180910390fd5b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff161415612c65576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526024815260200180613efe6024913960400191505060405180910390fd5b612c708383836131bd565b612c7b600082612991565b612ccc81600160008673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206131c290919063ffffffff16565b50612d1e81600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206131dc90919063ffffffff16565b50612d35818360026131f69092919063ffffffff16565b50808273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a4505050565b6000612da5836000018361322b565b60001c905092915050565b600080600080612dc386600001866132ae565b915091508160001c8160001c9350935050509250929050565b8060099080519060200190612df2929190613de6565b5050565b6000612e09846000018460001b84613347565b60001c90509392505050565b6000612e238260000161343d565b9050919050565b600080828401905083811015612ea8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601b8152602001807f536166654d6174683a206164646974696f6e206f766572666c6f77000000000081525060200191505060405180910390fd5b8091505092915050565b600080831415612ec55760009050612f32565b6000828402905082848281612ed657fe5b0414612f2d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602181526020018061406a6021913960400191505060405180910390fd5b809150505b92915050565b612f5282826040518060200160405280600081525061344e565b5050565b612f61848484612b53565b612f6d848484846134bf565b612fc2576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526032815260200180613ea66032913960400191505060405180910390fd5b50505050565b60606000821415613010576040518060400160405280600181526020017f3000000000000000000000000000000000000000000000000000000000000000815250905061310a565b600082905060005b6000821461303a578080600101915050600a828161303257fe5b049150613018565b60608167ffffffffffffffff8111801561305357600080fd5b506040519080825280601f01601f1916602001820160405280156130865781602001600182028036833780820191505090505b50905060006001830390508593505b6000841461310257600a84816130a757fe5b0660300160f81b828280600190039350815181106130c157fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600a84816130fa57fe5b049350613095565b819450505050505b919050565b600082821115613187576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601e8152602001807f536166654d6174683a207375627472616374696f6e206f766572666c6f77000081525060200191505060405180910390fd5b818303905092915050565b60006131a4836000018360001b6136d8565b905092915050565b600081600001805490509050919050565b505050565b60006131d4836000018360001b6136fb565b905092915050565b60006131ee836000018360001b6137e3565b905092915050565b6000613222846000018460001b8473ffffffffffffffffffffffffffffffffffffffff1660001b613853565b90509392505050565b60008183600001805490501161328c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526022815260200180613e846022913960400191505060405180910390fd5b82600001828154811061329b57fe5b9060005260206000200154905092915050565b60008082846000018054905011613310576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260228152602001806140206022913960400191505060405180910390fd5b600084600001848154811061332157fe5b906000526020600020906002020190508060000154816001015492509250509250929050565b6000808460010160008581526020019081526020016000205490506000811415839061340e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b838110156133d35780820151818401526020810190506133b8565b50505050905090810190601f1680156134005780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b5084600001600182038154811061342157fe5b9060005260206000209060020201600101549150509392505050565b600081600001805490509050919050565b613458838361392f565b61346560008484846134bf565b6134ba576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526032815260200180613ea66032913960400191505060405180910390fd5b505050565b60006134e08473ffffffffffffffffffffffffffffffffffffffff16613b23565b6134ed57600190506136d0565b606061365763150b7a0260e01b61350261296c565b888787604051602401808573ffffffffffffffffffffffffffffffffffffffff1681526020018473ffffffffffffffffffffffffffffffffffffffff16815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561358657808201518184015260208101905061356b565b50505050905090810190601f1680156135b35780820380516001836020036101000a031916815260200191505b5095505050505050604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff8381831617835250505050604051806060016040528060328152602001613ea6603291398773ffffffffffffffffffffffffffffffffffffffff16613b369092919063ffffffff16565b9050600081806020019051602081101561367057600080fd5b8101908080519060200190929190505050905063150b7a0260e01b7bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff191614925050505b949350505050565b600080836001016000848152602001908152602001600020541415905092915050565b600080836001016000848152602001908152602001600020549050600081146137d7576000600182039050600060018660000180549050039050600086600001828154811061374657fe5b906000526020600020015490508087600001848154811061376357fe5b906000526020600020018190555060018301876001016000838152602001908152602001600020819055508660000180548061379b57fe5b600190038181906000526020600020016000905590558660010160008781526020019081526020016000206000905560019450505050506137dd565b60009150505b92915050565b60006137ef8383613b4e565b61384857826000018290806001815401808255809150506001900390600052602060002001600090919091909150558260000180549050836001016000848152602001908152602001600020819055506001905061384d565b600090505b92915050565b60008084600101600085815260200190815260200160002054905060008114156138fa57846000016040518060400160405280868152602001858152509080600181540180825580915050600190039060005260206000209060020201600090919091909150600082015181600001556020820151816001015550508460000180549050856001016000868152602001908152602001600020819055506001915050613928565b8285600001600183038154811061390d57fe5b90600052602060002090600202016001018190555060009150505b9392505050565b600073ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1614156139d2576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260208152602001807f4552433732313a206d696e7420746f20746865207a65726f206164647265737381525060200191505060405180910390fd5b6139db81612974565b15613a4e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601c8152602001807f4552433732313a20746f6b656e20616c7265616479206d696e7465640000000081525060200191505060405180910390fd5b613a5a600083836131bd565b613aab81600160008573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020016000206131dc90919063ffffffff16565b50613ac2818360026131f69092919063ffffffff16565b50808273ffffffffffffffffffffffffffffffffffffffff16600073ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef60405160405180910390a45050565b600080823b905060008111915050919050565b6060613b458484600085613b71565b90509392505050565b600080836001016000848152602001908152602001600020541415905092915050565b606082471015613bcc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401808060200182810382526026815260200180613f226026913960400191505060405180910390fd5b613bd585613b23565b613c47576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252601d8152602001807f416464726573733a2063616c6c20746f206e6f6e2d636f6e747261637400000081525060200191505060405180910390fd5b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040518082805190602001908083835b60208310613c975780518252602082019150602081019050602083039250613c74565b6001836020036101000a03801982511681845116808217855250505050505090500191505060006040518083038185875af1925050503d8060008114613cf9576040519150601f19603f3d011682016040523d82523d6000602084013e613cfe565b606091505b5091509150613d0e828286613d1a565b92505050949350505050565b60608315613d2a57829050613ddf565b600083511115613d3d5782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825283818151815260200191508051906020019080838360005b83811015613da4578082015181840152602081019050613d89565b50505050905090810190601f168015613dd15780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b9392505050565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f10613e2757805160ff1916838001178555613e55565b82800160010185558215613e55579182015b82811115613e54578251825591602001919060010190613e39565b5b509050613e629190613e66565b5090565b5b80821115613e7f576000816000905550600101613e67565b509056fe456e756d657261626c655365743a20696e646578206f7574206f6620626f756e64734552433732313a207472616e7366657220746f206e6f6e20455243373231526563656976657220696d706c656d656e7465724f776e61626c653a206e6577206f776e657220697320746865207a65726f20616464726573734552433732313a207472616e7366657220746f20746865207a65726f2061646472657373416464726573733a20696e73756666696369656e742062616c616e636520666f722063616c6c4552433732313a206f70657261746f7220717565727920666f72206e6f6e6578697374656e7420746f6b656e43616e206f6e6c79206d696e7420323020746f6b656e7320617420612074696d654552433732313a20617070726f76652063616c6c6572206973206e6f74206f776e6572206e6f7220617070726f76656420666f7220616c6c4552433732313a2062616c616e636520717565727920666f7220746865207a65726f20616464726573734552433732313a206f776e657220717565727920666f72206e6f6e6578697374656e7420746f6b656e456e756d657261626c654d61703a20696e646578206f7574206f6620626f756e6473507572636861736520776f756c6420657863656564206d617820737570706c79206f662041706573536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f774552433732313a20617070726f76656420717565727920666f72206e6f6e6578697374656e7420746f6b656e4552433732313a207472616e73666572206f6620746f6b656e2074686174206973206e6f74206f776e4552433732314d657461646174613a2055524920717565727920666f72206e6f6e6578697374656e7420746f6b656e4552433732313a20617070726f76616c20746f2063757272656e74206f776e65724552433732313a207472616e736665722063616c6c6572206973206e6f74206f776e6572206e6f7220617070726f766564a2646970667358221220b0e64d1fa6c4dbeb9c6f54607d7e1996943fe27624a80652f57b53fda084621b64736f6c63430007000033000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000002710000000000000000000000000000000000000000000000000000000006080e6d70000000000000000000000000000000000000000000000000000000000000011426f7265644170655961636874436c756200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000044241594300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000c00000000000000000000000000000000000000000000000000000000000010f2c00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000014426f72656420417065205761676d6920436c756200000000000000000000000000000000000000000000000000000000000000000000000000000000000000044241594300000000000000000000000000000000000000000000000000000000
Details: Insufficient funds for gas * price + value
- Version: viem@2.23.12]
+ Version: viem@2.44.0]
`)
await disconnect(config, { connector })
diff --git a/packages/core/src/actions/deployContract.ts b/packages/core/src/actions/deployContract.ts
index a688dd7cfd..34e476b098 100644
--- a/packages/core/src/actions/deployContract.ts
+++ b/packages/core/src/actions/deployContract.ts
@@ -72,6 +72,7 @@ export async function deployContract<
else
client = await getConnectorClient(config, {
account: account ?? undefined,
+ assertChainId: false,
chainId,
connector,
})
diff --git a/packages/core/src/actions/estimateFeesPerGas.test-d.ts b/packages/core/src/actions/estimateFeesPerGas.test-d.ts
index dada2ea311..ad1f12e9aa 100644
--- a/packages/core/src/actions/estimateFeesPerGas.test-d.ts
+++ b/packages/core/src/actions/estimateFeesPerGas.test-d.ts
@@ -3,39 +3,36 @@ import { expectTypeOf, test } from 'vitest'
import { estimateFeesPerGas } from './estimateFeesPerGas.js'
test('types', async () => {
- const default_ = await estimateFeesPerGas(config)
- expectTypeOf(default_).toMatchTypeOf<{
- gasPrice?: undefined
- maxFeePerGas: bigint
- maxPriorityFeePerGas: bigint
- formatted: {
+ // default
+ {
+ const result = await estimateFeesPerGas(config, {})
+ expectTypeOf(result).toEqualTypeOf<{
gasPrice?: undefined
- maxFeePerGas: string
- maxPriorityFeePerGas: string
- }
- }>()
+ maxFeePerBlobGas?: undefined
+ maxFeePerGas: bigint
+ maxPriorityFeePerGas: bigint
+ }>()
+ }
- const legacy = await estimateFeesPerGas(config, { type: 'legacy' })
- expectTypeOf(legacy).toMatchTypeOf<{
- gasPrice: bigint
- maxFeePerGas?: undefined
- maxPriorityFeePerGas?: undefined
- formatted: {
- gasPrice: string
+ // legacy
+ {
+ const result = await estimateFeesPerGas(config, { type: 'legacy' })
+ expectTypeOf(result).toEqualTypeOf<{
+ gasPrice: bigint
+ maxFeePerBlobGas?: undefined
maxFeePerGas?: undefined
maxPriorityFeePerGas?: undefined
- }
- }>()
+ }>()
+ }
- const eip1559 = await estimateFeesPerGas(config, { type: 'eip1559' })
- expectTypeOf(eip1559).toMatchTypeOf<{
- gasPrice?: undefined
- maxFeePerGas: bigint
- maxPriorityFeePerGas: bigint
- formatted: {
+ // eip1559
+ {
+ const result = await estimateFeesPerGas(config, { type: 'eip1559' })
+ expectTypeOf(result).toEqualTypeOf<{
gasPrice?: undefined
- maxFeePerGas: string
- maxPriorityFeePerGas: string
- }
- }>()
+ maxFeePerBlobGas?: undefined
+ maxFeePerGas: bigint
+ maxPriorityFeePerGas: bigint
+ }>()
+ }
})
diff --git a/packages/core/src/actions/estimateFeesPerGas.test.ts b/packages/core/src/actions/estimateFeesPerGas.test.ts
index 4c5d668b83..318cbec16c 100644
--- a/packages/core/src/actions/estimateFeesPerGas.test.ts
+++ b/packages/core/src/actions/estimateFeesPerGas.test.ts
@@ -7,7 +7,6 @@ test('default', async () => {
const result = await estimateFeesPerGas(config)
expect(Object.keys(result)).toMatchInlineSnapshot(`
[
- "formatted",
"gasPrice",
"maxFeePerGas",
"maxPriorityFeePerGas",
diff --git a/packages/core/src/actions/estimateFeesPerGas.ts b/packages/core/src/actions/estimateFeesPerGas.ts
index 66915f010a..cfe7119114 100644
--- a/packages/core/src/actions/estimateFeesPerGas.ts
+++ b/packages/core/src/actions/estimateFeesPerGas.ts
@@ -1,10 +1,4 @@
-import {
- type Chain,
- type FeeValuesEIP1559,
- type FeeValuesLegacy,
- type FeeValuesType,
- formatUnits,
-} from 'viem'
+import type { Chain, FeeValuesType } from 'viem'
import {
type EstimateFeesPerGasErrorType as viem_EstimateFeesPerGasErrorType,
type EstimateFeesPerGasParameters as viem_EstimateFeesPerGasParameters,
@@ -14,11 +8,8 @@ import {
import type { Config } from '../createConfig.js'
import type { ChainIdParameter } from '../types/properties.js'
-import type { Unit } from '../types/unit.js'
-import type { Compute } from '../types/utils.js'
-import type { UnionCompute, UnionLooseOmit } from '../types/utils.js'
+import type { Compute, UnionCompute, UnionLooseOmit } from '../types/utils.js'
import { getAction } from '../utils/getAction.js'
-import { getUnit } from '../utils/getUnit.js'
export type EstimateFeesPerGasParameters<
type extends FeeValuesType = FeeValuesType,
@@ -28,23 +19,12 @@ export type EstimateFeesPerGasParameters<
viem_EstimateFeesPerGasParameters,
'chain'
> &
- ChainIdParameter & {
- /** @deprecated */
- formatUnits?: Unit | undefined
- }
+ ChainIdParameter
>
export type EstimateFeesPerGasReturnType<
type extends FeeValuesType = FeeValuesType,
-> = Compute<
- viem_EstimateFeesPerGasReturnType & {
- /** @deprecated */
- formatted: UnionCompute<
- | (type extends 'legacy' ? FeeValuesLegacy : never)
- | (type extends 'eip1559' ? FeeValuesEIP1559 : never)
- >
- }
->
+> = Compute>
export type EstimateFeesPerGasErrorType = viem_EstimateFeesPerGasErrorType
@@ -55,7 +35,7 @@ export async function estimateFeesPerGas<
config: config,
parameters: EstimateFeesPerGasParameters = {},
): Promise> {
- const { chainId, formatUnits: units = 'gwei', ...rest } = parameters
+ const { chainId, ...rest } = parameters
const client = config.getClient({ chainId })
const action = getAction(
@@ -69,17 +49,7 @@ export async function estimateFeesPerGas<
chain: client.chain,
})
- const unit = getUnit(units)
- const formatted = {
- gasPrice: gasPrice ? formatUnits(gasPrice, unit) : undefined,
- maxFeePerGas: maxFeePerGas ? formatUnits(maxFeePerGas, unit) : undefined,
- maxPriorityFeePerGas: maxPriorityFeePerGas
- ? formatUnits(maxPriorityFeePerGas, unit)
- : undefined,
- }
-
return {
- formatted,
gasPrice,
maxFeePerGas,
maxPriorityFeePerGas,
diff --git a/packages/core/src/actions/estimateGas.ts b/packages/core/src/actions/estimateGas.ts
index c049fa42f8..391e84bc0d 100644
--- a/packages/core/src/actions/estimateGas.ts
+++ b/packages/core/src/actions/estimateGas.ts
@@ -61,6 +61,7 @@ export async function estimateGas<
else {
const connectorClient = await getConnectorClient(config, {
account: parameters.account,
+ assertChainId: false,
chainId,
connector,
})
diff --git a/packages/core/src/actions/getBalance.test.ts b/packages/core/src/actions/getBalance.test.ts
index 954c09c2e6..df6c0632c1 100644
--- a/packages/core/src/actions/getBalance.test.ts
+++ b/packages/core/src/actions/getBalance.test.ts
@@ -21,82 +21,34 @@ beforeEach(async () => {
test('default', async () => {
await expect(getBalance(config, { address })).resolves.toMatchInlineSnapshot(`
- {
- "decimals": 18,
- "formatted": "10000",
- "symbol": "ETH",
- "value": 10000000000000000000000n,
- }
- `)
+ {
+ "decimals": 18,
+ "symbol": "ETH",
+ "value": 10000000000000000000000n,
+ }
+ `)
await testClient.mainnet.setBalance({
address,
value: parseEther('6969.12222215666'),
})
await expect(getBalance(config, { address })).resolves.toMatchInlineSnapshot(`
- {
- "decimals": 18,
- "formatted": "6969.12222215666",
- "symbol": "ETH",
- "value": 6969122222156660000000n,
- }
- `)
+ {
+ "decimals": 18,
+ "symbol": "ETH",
+ "value": 6969122222156660000000n,
+ }
+ `)
})
test('parameters: chainId', async () => {
await expect(
getBalance(config, { address, chainId: chain.mainnet2.id }),
- ).resolves.toMatchInlineSnapshot(`
- {
- "decimals": 18,
- "formatted": "420",
- "symbol": "WAG",
- "value": 420000000000000000000n,
- }
- `)
-})
-
-test('parameters: token', async () => {
- await expect(
- getBalance(config, {
- address: '0x4557B18E779944BFE9d78A672452331C186a9f48',
- token: '0x6B175474E89094C44Da98b954EedeAC495271d0F',
- }),
- ).resolves.toMatchInlineSnapshot(`
- {
- "decimals": 18,
- "formatted": "0.559062564299199392",
- "symbol": "DAI",
- "value": 559062564299199392n,
- }
- `)
-})
-
-test('parameters: token (bytes32 symbol)', async () => {
- await expect(
- getBalance(config, {
- address: '0x4557B18E779944BFE9d78A672452331C186a9f48',
- token: '0x9f8f72aa9304c8b593d555f12ef6589cc3a579a2',
- }),
).resolves.toMatchInlineSnapshot(`
{
"decimals": 18,
- "formatted": "0",
- "symbol": "MKR",
- "value": 0n,
+ "symbol": "WAG",
+ "value": 420000000000000000000n,
}
`)
})
-
-test('parameters: unit', async () => {
- await expect(
- getBalance(config, { address, unit: 'wei' }),
- ).resolves.toMatchInlineSnapshot(`
- {
- "decimals": 18,
- "formatted": "10000000000000000000000",
- "symbol": "ETH",
- "value": 10000000000000000000000n,
- }
- `)
-})
diff --git a/packages/core/src/actions/getBalance.ts b/packages/core/src/actions/getBalance.ts
index 1aae5667b1..ff1e79c6c0 100644
--- a/packages/core/src/actions/getBalance.ts
+++ b/packages/core/src/actions/getBalance.ts
@@ -1,4 +1,3 @@
-import { type Address, type Hex, formatUnits, hexToString, trim } from 'viem'
import {
type GetBalanceErrorType as viem_GetBalanceErrorType,
type GetBalanceParameters as viem_GetBalanceParameters,
@@ -7,26 +6,15 @@ import {
import type { Config } from '../createConfig.js'
import type { ChainIdParameter } from '../types/properties.js'
-import type { Unit } from '../types/unit.js'
import type { Compute } from '../types/utils.js'
import { getAction } from '../utils/getAction.js'
-import { getUnit } from '../utils/getUnit.js'
-import { type ReadContractsErrorType, readContracts } from './readContracts.js'
export type GetBalanceParameters = Compute<
- ChainIdParameter &
- viem_GetBalanceParameters & {
- /** @deprecated */
- token?: Address | undefined
- /** @deprecated */
- unit?: Unit | undefined
- }
+ ChainIdParameter & viem_GetBalanceParameters
>
export type GetBalanceReturnType = {
decimals: number
- /** @deprecated */
- formatted: string
symbol: string
value: bigint
}
@@ -38,45 +26,7 @@ export async function getBalance(
config: config,
parameters: GetBalanceParameters,
): Promise {
- const {
- address,
- blockNumber,
- blockTag,
- chainId,
- token: tokenAddress,
- unit = 'ether',
- } = parameters
-
- if (tokenAddress) {
- try {
- return await getTokenBalance(config, {
- balanceAddress: address,
- chainId,
- symbolType: 'string',
- tokenAddress,
- })
- } catch (error) {
- // In the chance that there is an error upon decoding the contract result,
- // it could be likely that the contract data is represented as bytes32 instead
- // of a string.
- if (
- (error as ReadContractsErrorType).name ===
- 'ContractFunctionExecutionError'
- ) {
- const balance = await getTokenBalance(config, {
- balanceAddress: address,
- chainId,
- symbolType: 'bytes32',
- tokenAddress,
- })
- const symbol = hexToString(
- trim(balance.symbol as Hex, { dir: 'right' }),
- )
- return { ...balance, symbol }
- }
- throw error
- }
- }
+ const { address, blockNumber, blockTag, chainId } = parameters
const client = config.getClient({ chainId })
const action = getAction(client, viem_getBalance, 'getBalance')
@@ -86,64 +36,7 @@ export async function getBalance(
const chain = config.chains.find((x) => x.id === chainId) ?? client.chain!
return {
decimals: chain.nativeCurrency.decimals,
- formatted: formatUnits(value, getUnit(unit)),
symbol: chain.nativeCurrency.symbol,
value,
}
}
-
-type GetTokenBalanceParameters = {
- balanceAddress: Address
- chainId?: number | undefined
- symbolType: 'bytes32' | 'string'
- tokenAddress: Address
- unit?: Unit | undefined
-}
-
-async function getTokenBalance(
- config: Config,
- parameters: GetTokenBalanceParameters,
-) {
- const { balanceAddress, chainId, symbolType, tokenAddress, unit } = parameters
- const contract = {
- abi: [
- {
- type: 'function',
- name: 'balanceOf',
- stateMutability: 'view',
- inputs: [{ type: 'address' }],
- outputs: [{ type: 'uint256' }],
- },
- {
- type: 'function',
- name: 'decimals',
- stateMutability: 'view',
- inputs: [],
- outputs: [{ type: 'uint8' }],
- },
- {
- type: 'function',
- name: 'symbol',
- stateMutability: 'view',
- inputs: [],
- outputs: [{ type: symbolType }],
- },
- ],
- address: tokenAddress,
- } as const
- const [value, decimals, symbol] = await readContracts(config, {
- allowFailure: false,
- contracts: [
- {
- ...contract,
- functionName: 'balanceOf',
- args: [balanceAddress],
- chainId,
- },
- { ...contract, functionName: 'decimals', chainId },
- { ...contract, functionName: 'symbol', chainId },
- ] as const,
- })
- const formatted = formatUnits(value ?? '0', getUnit(unit ?? decimals))
- return { decimals, formatted, symbol, value }
-}
diff --git a/packages/core/src/actions/getBlock.test-d.ts b/packages/core/src/actions/getBlock.test-d.ts
index 8c59f6e277..4041c841af 100644
--- a/packages/core/src/actions/getBlock.test-d.ts
+++ b/packages/core/src/actions/getBlock.test-d.ts
@@ -1,4 +1,4 @@
-import { http } from 'viem'
+import { type Hex, http } from 'viem'
import { celo, mainnet } from 'viem/chains'
import { expectTypeOf, test } from 'vitest'
@@ -12,18 +12,11 @@ test('chain formatters', async () => {
})
const result = await getBlock(config)
if (result.chainId === celo.id) {
- expectTypeOf(result.difficulty).toEqualTypeOf()
- expectTypeOf(result.gasLimit).toEqualTypeOf()
- expectTypeOf(result.mixHash).toEqualTypeOf()
+ expectTypeOf(result.difficulty).toEqualTypeOf()
+ expectTypeOf(result.gasLimit).toEqualTypeOf()
+ expectTypeOf(result.mixHash).toEqualTypeOf()
expectTypeOf(result.nonce).toEqualTypeOf<`0x${string}`>()
- expectTypeOf(result.uncles).toEqualTypeOf()
- expectTypeOf(result.randomness).toEqualTypeOf<
- | {
- committed: `0x${string}`
- revealed: `0x${string}`
- }
- | undefined
- >()
+ expectTypeOf(result.uncles).toEqualTypeOf()
}
})
@@ -35,16 +28,8 @@ test('chainId', async () => {
const result = await getBlock(config, {
chainId: celo.id,
})
- expectTypeOf(result.difficulty).toEqualTypeOf()
- expectTypeOf(result.gasLimit).toEqualTypeOf()
- expectTypeOf(result.mixHash).toEqualTypeOf()
+ expectTypeOf(result.difficulty).toEqualTypeOf()
+ expectTypeOf(result.gasLimit).toEqualTypeOf()
+ expectTypeOf(result.mixHash).toEqualTypeOf()
expectTypeOf(result.nonce).toEqualTypeOf<`0x${string}`>()
- expectTypeOf(result.uncles).toEqualTypeOf()
- expectTypeOf(result.randomness).toEqualTypeOf<
- | {
- committed: `0x${string}`
- revealed: `0x${string}`
- }
- | undefined
- >()
})
diff --git a/packages/core/src/actions/getBlock.test.ts b/packages/core/src/actions/getBlock.test.ts
index b1e92ba364..da8b6a361b 100644
--- a/packages/core/src/actions/getBlock.test.ts
+++ b/packages/core/src/actions/getBlock.test.ts
@@ -16,128 +16,130 @@ test('args: blockNumber', async () => {
)
expect(block).toMatchInlineSnapshot(`
{
- "baseFeePerGas": 24076814055n,
- "blobGasUsed": undefined,
+ "baseFeePerGas": 194923488n,
+ "blobGasUsed": 786432n,
"chainId": 1,
"difficulty": 0n,
- "excessBlobGas": undefined,
+ "excessBlobGas": 0n,
"extraData": "0x546974616e2028746974616e6275696c6465722e78797a29",
- "gasLimit": 30000000n,
- "gasUsed": 26325393n,
- "hash": "0xcfa5df46abf1521f68ae72a7f7c4661949f4fb08a3d1296fe8082f6580a414e0",
- "logsBloom": "0x2df3b5a24d2d57e7d73f96dbfea3577b1d5fbaacfcb9b5fb86db74d2e4ffd1e48bba050c33edada84fe477213937158c1e95d3da9f457f6f36e3ff0afdffcb667c5ee5f9e3ddffa9db1af6bbf15fcbbca5139717d5eedab4daa63cd8bb7dfa3e976b1e7023e2dc4586cef3caa0b73d6ff2ba3afb989c9f58f6b67bb4ed596c5aeb78cef51f69ad3675df70ffbd2aa6576d7c9e3debd00cccec3b69fc617b8568bfe588f7e126ef591f34ddd0d8b68c28b7ed45b46af3a7bb75c0e2fe4bec54fb772c87ae6f7efcdfb13139b758cfda4d98dffe426fef6d1c2e55f36b5bb1f0a2aef7bcbdf83d31ea646cf6ef3fe9d8b9af2ad4197f7ea2de462bd029fdef7e6f",
+ "gasLimit": 45000000n,
+ "gasUsed": 30531630n,
+ "hash": "0xe38d4bb2060a54519508612f40ef737a09c5b20488c12b0bec2d4f5ea7073c15",
+ "logsBloom": "0x3effc77fb16497fa74fffeb6ef65dfbd7b97f8dd7f198ff37abfcf5fdeb329e7bdbc9d8caffdf765f7b75df9e737eff773fbf639ff9ffb376fb726a7ff2f68dffea0de7fafd3f7fbff8d5fdff57becf3e76f3f73fefc1ff9bbf9df7fb3fffff13f577b7fdffeb7f7ffb8cd71ff93fff3bfffd7e3bfbe576daefdfff6fb5afedf8ffbbd7d7baf977f46fbffceebfbe86fc6ffb6f1eff3fbbfbeb9eefbf954ffe3fbff9d73b8f9ecfdcfdf7df3fdd9ff3bbfdfe9efe8ffee6ff7fe4a3ff7a5fefbfffffcffcd7f2bc04bdf7c52d3fdfeff3f7dfe7b4fefa9f46edb53c2de9ffb7f3ffdff6fefa67f64f6e7f7bff5af1dffffeff9b99ff86fef589e3bbfffdfffb7",
"miner": "0x4838b106fce9647bdf1e7877bf73ce8b0bad5f97",
- "mixHash": "0x92ac9cd6e57bacd7c7d3e9b087c3907b1c085e284eec2dce7379a847cb4c9940",
+ "mixHash": "0x15350a0cad9bc5cb1298b3710db038850f1df5d8ac00c4ca3b03fb64c7e8ab78",
"nonce": "0x0000000000000000",
- "number": 19258213n,
- "parentHash": "0x40cb7885ad596d0397d664a4dc9ef5c2011c09e9a62b386f838f5f5362582ebb",
- "receiptsRoot": "0x910a69ba396ab4f59c2c77aa413e941fc4da97a021b8d8bbf12c125bfc42d9d3",
+ "number": 23535880n,
+ "parentBeaconBlockRoot": "0x2bd55d2f0e1a3d3e181659ebc21bb167527e517de88b39b0d7ebbeeb3e28eebc",
+ "parentHash": "0x1fab238a9630a2e95c8b735ebc63bc2751bc6492f409ee16a7b5a532985196eb",
+ "receiptsRoot": "0x01d0a60dd8fd8de710a191aba91f82e2a437ac21a6e77b21b2f745809e7feadf",
+ "requestsHash": "0x965c860907968cab126093a785436ad747495ae45b21dac1b6a92ae0f4866ce0",
"sha3Uncles": "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
- "size": 158252n,
- "stateRoot": "0x6e27207d219b0251dbc2fde71f3cde8e33703261f032056453c27275500dddbc",
- "timestamp": 1708302299n,
+ "size": 155442n,
+ "stateRoot": "0xd3c86549e5d57f14bd0b28630b70cb68038ac3334251bd194c93a18d96492f39",
+ "timestamp": 1759960991n,
"totalDifficulty": null,
- "transactionsRoot": "0x897dba26a3a940b62f86da6e5fec5f71312ad7c871a4031db79dee67442c9d1e",
+ "transactionsRoot": "0x9da0226f723a9da4b8df8782930c0e83bd73c4a393069ee7861465188eed989b",
"uncles": [],
"withdrawals": [
{
"address": "0xb9d7934878b5fb9610b3fe8a5e441e8fad7e293f",
- "amount": "0x112da72",
- "index": "0x21ec946",
- "validatorIndex": "0x5cd8e",
+ "amount": "0x11a6bd6",
+ "index": "0x633236b",
+ "validatorIndex": "0xb8688",
},
{
"address": "0xb9d7934878b5fb9610b3fe8a5e441e8fad7e293f",
- "amount": "0x1119345",
- "index": "0x21ec947",
- "validatorIndex": "0x5cd8f",
+ "amount": "0x119ebba",
+ "index": "0x633236c",
+ "validatorIndex": "0xb8689",
},
{
"address": "0xb9d7934878b5fb9610b3fe8a5e441e8fad7e293f",
- "amount": "0x110e2ca",
- "index": "0x21ec948",
- "validatorIndex": "0x5cd90",
+ "amount": "0x11a167c",
+ "index": "0x633236d",
+ "validatorIndex": "0xb868a",
},
{
"address": "0xb9d7934878b5fb9610b3fe8a5e441e8fad7e293f",
- "amount": "0x1119245",
- "index": "0x21ec949",
- "validatorIndex": "0x5cd91",
+ "amount": "0x11a2017",
+ "index": "0x633236e",
+ "validatorIndex": "0xb868b",
},
{
"address": "0xb9d7934878b5fb9610b3fe8a5e441e8fad7e293f",
- "amount": "0x1115a03",
- "index": "0x21ec94a",
- "validatorIndex": "0x5cd92",
+ "amount": "0x11a5b81",
+ "index": "0x633236f",
+ "validatorIndex": "0xb868c",
},
{
"address": "0xb9d7934878b5fb9610b3fe8a5e441e8fad7e293f",
- "amount": "0x111cf3f",
- "index": "0x21ec94b",
- "validatorIndex": "0x5cd93",
+ "amount": "0x11a4908",
+ "index": "0x6332370",
+ "validatorIndex": "0xb868d",
},
{
"address": "0xb9d7934878b5fb9610b3fe8a5e441e8fad7e293f",
- "amount": "0x1106006",
- "index": "0x21ec94c",
- "validatorIndex": "0x5cd94",
+ "amount": "0x11a74ca",
+ "index": "0x6332371",
+ "validatorIndex": "0xb868e",
},
{
"address": "0xb9d7934878b5fb9610b3fe8a5e441e8fad7e293f",
- "amount": "0x1115bb3",
- "index": "0x21ec94d",
- "validatorIndex": "0x5cd95",
+ "amount": "0x11a5a90",
+ "index": "0x6332372",
+ "validatorIndex": "0xb868f",
},
{
"address": "0xb9d7934878b5fb9610b3fe8a5e441e8fad7e293f",
- "amount": "0x111e0d9",
- "index": "0x21ec94e",
- "validatorIndex": "0x5cd96",
+ "amount": "0x11a512b",
+ "index": "0x6332373",
+ "validatorIndex": "0xb8690",
},
{
"address": "0xb9d7934878b5fb9610b3fe8a5e441e8fad7e293f",
- "amount": "0x110829f",
- "index": "0x21ec94f",
- "validatorIndex": "0x5cd97",
+ "amount": "0x11a0ba7",
+ "index": "0x6332374",
+ "validatorIndex": "0xb8691",
},
{
"address": "0xb9d7934878b5fb9610b3fe8a5e441e8fad7e293f",
- "amount": "0x11029ab",
- "index": "0x21ec950",
- "validatorIndex": "0x5cd98",
+ "amount": "0x11a313b",
+ "index": "0x6332375",
+ "validatorIndex": "0xb8692",
},
{
"address": "0xb9d7934878b5fb9610b3fe8a5e441e8fad7e293f",
- "amount": "0x11140a6",
- "index": "0x21ec951",
- "validatorIndex": "0x5cd99",
+ "amount": "0x3e72765",
+ "index": "0x6332376",
+ "validatorIndex": "0xb8693",
},
{
"address": "0xb9d7934878b5fb9610b3fe8a5e441e8fad7e293f",
- "amount": "0x111396c",
- "index": "0x21ec952",
- "validatorIndex": "0x5cd9a",
+ "amount": "0x119c821",
+ "index": "0x6332377",
+ "validatorIndex": "0xb8694",
},
{
"address": "0xb9d7934878b5fb9610b3fe8a5e441e8fad7e293f",
- "amount": "0x110de16",
- "index": "0x21ec953",
- "validatorIndex": "0x5cd9b",
+ "amount": "0x119e921",
+ "index": "0x6332378",
+ "validatorIndex": "0xb8695",
},
{
"address": "0xb9d7934878b5fb9610b3fe8a5e441e8fad7e293f",
- "amount": "0x1121062",
- "index": "0x21ec954",
- "validatorIndex": "0x5cd9c",
+ "amount": "0x119f302",
+ "index": "0x6332379",
+ "validatorIndex": "0xb8696",
},
{
"address": "0xb9d7934878b5fb9610b3fe8a5e441e8fad7e293f",
- "amount": "0x11188bc",
- "index": "0x21ec955",
- "validatorIndex": "0x5cd9d",
+ "amount": "0x11a38a8",
+ "index": "0x633237a",
+ "validatorIndex": "0xb8697",
},
],
- "withdrawalsRoot": "0x26638497bd55075025ac2362d92bd789ac1232fd50c4b3866565280318027950",
+ "withdrawalsRoot": "0x0740ba007069960b2d60f77b0ce2648cffa3573accd055d4803eb771e32903e7",
}
`)
})
diff --git a/packages/core/src/actions/getBytecode.test.ts b/packages/core/src/actions/getBytecode.test.ts
index 4fdeb4ef17..1d5b6bdff9 100644
--- a/packages/core/src/actions/getBytecode.test.ts
+++ b/packages/core/src/actions/getBytecode.test.ts
@@ -14,9 +14,7 @@ test('default', async () => {
getBytecode(config, {
address: address.wagmiMintExample,
}),
- ).resolves.toBe(
- '0x608060405234801561001057600080fd5b50600436106101005760003560e01c80636352211e11610097578063a22cb46511610066578063a22cb46514610215578063b88d4fde14610228578063c87b56dd1461023b578063e985e9c51461024e57600080fd5b80636352211e146101d457806370a08231146101e757806395d89b41146101fa578063a0712d681461020257600080fd5b80631249c58b116100d35780631249c58b1461018f57806318160ddd1461019757806323b872dd146101ae57806342842e0e146101c157600080fd5b806301ffc9a71461010557806306fdde031461012d578063081812fc14610142578063095ea7b31461017a575b600080fd5b61011861011336600461178f565b610297565b60405190151581526020015b60405180910390f35b61013561037c565b6040516101249190611829565b61015561015036600461183c565b61040e565b60405173ffffffffffffffffffffffffffffffffffffffff9091168152602001610124565b61018d61018836600461187e565b6104d3565b005b61018d61062b565b6101a060065481565b604051908152602001610124565b61018d6101bc3660046118a8565b61067d565b61018d6101cf3660046118a8565b610704565b6101556101e236600461183c565b61071f565b6101a06101f53660046118e4565b6107b7565b61013561086b565b61018d61021036600461183c565b61087a565b61018d6102233660046118ff565b610902565b61018d61023636600461196a565b610911565b61013561024936600461183c565b61099f565b61011861025c366004611a64565b73ffffffffffffffffffffffffffffffffffffffff918216600090815260056020908152604080832093909416825291909152205460ff1690565b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f80ac58cd00000000000000000000000000000000000000000000000000000000148061032a57507fffffffff0000000000000000000000000000000000000000000000000000000082167f5b5e139f00000000000000000000000000000000000000000000000000000000145b8061037657507f01ffc9a7000000000000000000000000000000000000000000000000000000007fffffffff000000000000000000000000000000000000000000000000000000008316145b92915050565b60606000805461038b90611a97565b80601f01602080910402602001604051908101604052809291908181526020018280546103b790611a97565b80156104045780601f106103d957610100808354040283529160200191610404565b820191906000526020600020905b8154815290600101906020018083116103e757829003601f168201915b5050505050905090565b60008181526002602052604081205473ffffffffffffffffffffffffffffffffffffffff166104aa5760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a20617070726f76656420717565727920666f72206e6f6e657860448201527f697374656e7420746f6b656e000000000000000000000000000000000000000060648201526084015b60405180910390fd5b5060009081526004602052604090205473ffffffffffffffffffffffffffffffffffffffff1690565b60006104de8261071f565b90508073ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff16036105815760405162461bcd60e51b815260206004820152602160248201527f4552433732313a20617070726f76616c20746f2063757272656e74206f776e6560448201527f720000000000000000000000000000000000000000000000000000000000000060648201526084016104a1565b3373ffffffffffffffffffffffffffffffffffffffff821614806105aa57506105aa813361025c565b61061c5760405162461bcd60e51b815260206004820152603860248201527f4552433732313a20617070726f76652063616c6c6572206973206e6f74206f7760448201527f6e6572206e6f7220617070726f76656420666f7220616c6c000000000000000060648201526084016104a1565b6106268383610b07565b505050565b6007545b60008181526002602052604090205473ffffffffffffffffffffffffffffffffffffffff16156106615760010161062f565b61066b3382610ba7565b60068054600190810190915501600755565b6106873382610bc1565b6106f95760405162461bcd60e51b815260206004820152603160248201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60448201527f776e6572206e6f7220617070726f76656400000000000000000000000000000060648201526084016104a1565b610626838383610d17565b61062683838360405180602001604052806000815250610911565b60008181526002602052604081205473ffffffffffffffffffffffffffffffffffffffff16806103765760405162461bcd60e51b815260206004820152602960248201527f4552433732313a206f776e657220717565727920666f72206e6f6e657869737460448201527f656e7420746f6b656e000000000000000000000000000000000000000000000060648201526084016104a1565b600073ffffffffffffffffffffffffffffffffffffffff82166108425760405162461bcd60e51b815260206004820152602a60248201527f4552433732313a2062616c616e636520717565727920666f7220746865207a6560448201527f726f20616464726573730000000000000000000000000000000000000000000060648201526084016104a1565b5073ffffffffffffffffffffffffffffffffffffffff1660009081526003602052604090205490565b60606001805461038b90611a97565b60008181526002602052604090205473ffffffffffffffffffffffffffffffffffffffff16156108ec5760405162461bcd60e51b815260206004820152601160248201527f546f6b656e2049442069732074616b656e00000000000000000000000000000060448201526064016104a1565b6108f63382610ba7565b50600680546001019055565b61090d338383610f4a565b5050565b61091b3383610bc1565b61098d5760405162461bcd60e51b815260206004820152603160248201527f4552433732313a207472616e736665722063616c6c6572206973206e6f74206f60448201527f776e6572206e6f7220617070726f76656400000000000000000000000000000060648201526084016104a1565b6109998484848461105d565b50505050565b6040517f666f726567726f756e64000000000000000000000000000000000000000000006020820152602a810182905260609060009061016890604a016040516020818303038152906040528051906020012060001c6109ff9190611b19565b6040517f6261636b67726f756e64000000000000000000000000000000000000000000006020820152602a810185905290915060009061016890604a016040516020818303038152906040528051906020012060001c610a5f9190611b19565b90506000610aba610a6f866110e6565b610aa9610a7b866110e6565b610a84866110e6565b604051602001610a95929190611b2d565b60405160208183030381529060405261121b565b604051602001610a959291906125ba565b9050600081604051602001610acf919061268b565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190529695505050505050565b600081815260046020526040902080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff84169081179091558190610b618261071f565b73ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92560405160405180910390a45050565b61090d82826040518060200160405280600081525061136e565b60008181526002602052604081205473ffffffffffffffffffffffffffffffffffffffff16610c585760405162461bcd60e51b815260206004820152602c60248201527f4552433732313a206f70657261746f7220717565727920666f72206e6f6e657860448201527f697374656e7420746f6b656e000000000000000000000000000000000000000060648201526084016104a1565b6000610c638361071f565b90508073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff161480610cd1575073ffffffffffffffffffffffffffffffffffffffff80821660009081526005602090815260408083209388168352929052205460ff165b80610d0f57508373ffffffffffffffffffffffffffffffffffffffff16610cf78461040e565b73ffffffffffffffffffffffffffffffffffffffff16145b949350505050565b8273ffffffffffffffffffffffffffffffffffffffff16610d378261071f565b73ffffffffffffffffffffffffffffffffffffffff1614610dc05760405162461bcd60e51b815260206004820152602560248201527f4552433732313a207472616e736665722066726f6d20696e636f72726563742060448201527f6f776e657200000000000000000000000000000000000000000000000000000060648201526084016104a1565b73ffffffffffffffffffffffffffffffffffffffff8216610e485760405162461bcd60e51b8152602060048201526024808201527f4552433732313a207472616e7366657220746f20746865207a65726f2061646460448201527f726573730000000000000000000000000000000000000000000000000000000060648201526084016104a1565b610e53600082610b07565b73ffffffffffffffffffffffffffffffffffffffff83166000908152600360205260408120805460019290610e899084906126ff565b909155505073ffffffffffffffffffffffffffffffffffffffff82166000908152600360205260408120805460019290610ec4908490612716565b909155505060008181526002602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff86811691821790925591518493918716917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91a4505050565b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610fc55760405162461bcd60e51b815260206004820152601960248201527f4552433732313a20617070726f766520746f2063616c6c65720000000000000060448201526064016104a1565b73ffffffffffffffffffffffffffffffffffffffff83811660008181526005602090815260408083209487168084529482529182902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff001686151590811790915591519182527f17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31910160405180910390a3505050565b611068848484610d17565b611074848484846113f7565b6109995760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e746572000000000000000000000000000060648201526084016104a1565b60608160000361112957505060408051808201909152600181527f3000000000000000000000000000000000000000000000000000000000000000602082015290565b8160005b8115611153578061113d8161272e565b915061114c9050600a83612766565b915061112d565b60008167ffffffffffffffff81111561116e5761116e61193b565b6040519080825280601f01601f191660200182016040528015611198576020820181803683370190505b5090505b8415610d0f576111ad6001836126ff565b91506111ba600a86611b19565b6111c5906030612716565b60f81b8183815181106111da576111da61277a565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350611214600a86612766565b945061119c565b6060815160000361123a57505060408051602081019091526000815290565b600060405180606001604052806040815260200161284d60409139905060006003845160026112699190612716565b6112739190612766565b61127e9060046127a9565b67ffffffffffffffff8111156112965761129661193b565b6040519080825280601f01601f1916602001820160405280156112c0576020820181803683370190505b509050600182016020820185865187015b8082101561132c576003820191508151603f8160121c168501518453600184019350603f81600c1c168501518453600184019350603f8160061c168501518453600184019350603f81168501518453506001830192506112d1565b5050600386510660018114611348576002811461135b57611363565b603d6001830353603d6002830353611363565b603d60018303535b509195945050505050565b61137883836115d0565b61138560008484846113f7565b6106265760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e746572000000000000000000000000000060648201526084016104a1565b600073ffffffffffffffffffffffffffffffffffffffff84163b156115c5576040517f150b7a0200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85169063150b7a029061146e9033908990889088906004016127e6565b6020604051808303816000875af19250505080156114c7575060408051601f3d9081017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01682019092526114c49181019061282f565b60015b61157a573d8080156114f5576040519150601f19603f3d011682016040523d82523d6000602084013e6114fa565b606091505b5080516000036115725760405162461bcd60e51b815260206004820152603260248201527f4552433732313a207472616e7366657220746f206e6f6e20455243373231526560448201527f63656976657220696d706c656d656e746572000000000000000000000000000060648201526084016104a1565b805181602001fd5b7fffffffff00000000000000000000000000000000000000000000000000000000167f150b7a0200000000000000000000000000000000000000000000000000000000149050610d0f565b506001949350505050565b73ffffffffffffffffffffffffffffffffffffffff82166116335760405162461bcd60e51b815260206004820181905260248201527f4552433732313a206d696e7420746f20746865207a65726f206164647265737360448201526064016104a1565b60008181526002602052604090205473ffffffffffffffffffffffffffffffffffffffff16156116a55760405162461bcd60e51b815260206004820152601c60248201527f4552433732313a20746f6b656e20616c7265616479206d696e7465640000000060448201526064016104a1565b73ffffffffffffffffffffffffffffffffffffffff821660009081526003602052604081208054600192906116db908490612716565b909155505060008181526002602052604080822080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff861690811790915590518392907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef908290a45050565b7fffffffff000000000000000000000000000000000000000000000000000000008116811461178c57600080fd5b50565b6000602082840312156117a157600080fd5b81356117ac8161175e565b9392505050565b60005b838110156117ce5781810151838201526020016117b6565b838111156109995750506000910152565b600081518084526117f78160208601602086016117b3565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b6020815260006117ac60208301846117df565b60006020828403121561184e57600080fd5b5035919050565b803573ffffffffffffffffffffffffffffffffffffffff8116811461187957600080fd5b919050565b6000806040838503121561189157600080fd5b61189a83611855565b946020939093013593505050565b6000806000606084860312156118bd57600080fd5b6118c684611855565b92506118d460208501611855565b9150604084013590509250925092565b6000602082840312156118f657600080fd5b6117ac82611855565b6000806040838503121561191257600080fd5b61191b83611855565b91506020830135801515811461193057600080fd5b809150509250929050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6000806000806080858703121561198057600080fd5b61198985611855565b935061199760208601611855565b925060408501359150606085013567ffffffffffffffff808211156119bb57600080fd5b818701915087601f8301126119cf57600080fd5b8135818111156119e1576119e161193b565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0908116603f01168101908382118183101715611a2757611a2761193b565b816040528281528a6020848701011115611a4057600080fd5b82602086016020830137600060208483010152809550505050505092959194509250565b60008060408385031215611a7757600080fd5b611a8083611855565b9150611a8e60208401611855565b90509250929050565b600181811c90821680611aab57607f821691505b602082108103611ae4577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b50919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b600082611b2857611b28611aea565b500690565b7f3c73766720786d6c6e733d22687474703a2f2f7777772e77332e6f72672f323081527f30302f737667222077696474683d223130323422206865696768743d2231303260208201527f34222066696c6c3d226e6f6e65223e3c706174682066696c6c3d2268736c2800604082015260008351611bb181605f8501602088016117b3565b7f2c20313030252c20313025292220643d224d3020306831303234763130323448605f918401918201527f307a22202f3e3c672066696c6c3d2268736c2800000000000000000000000000607f8201528351611c148160928401602088016117b3565b7f2c20313030252c2039302529223e3c7061746820643d224d393033203433372e609292909101918201527f35633020392e3131332d372e3338382031362e352d31362e352031362e35732d60b28201527f31362e352d372e3338372d31362e352d31362e3520372e3338382d31362e352060d28201527f31362e352d31362e352031362e3520372e3338372031362e352031362e357a4d60f28201527f3639382e3532392035363663362e39323120302031322e35332d352e353936206101128201527f31322e35332d31322e35762d353063302d362e39303420352e3630392d31322e6101328201527f352031322e3532392d31322e356832352e30353963362e393220302031322e356101528201527f323920352e3539362031322e3532392031322e35763530633020362e393034206101728201527f352e3630392031322e352031322e35332031322e357331322e3532392d352e356101928201527f39362031322e3532392d31322e35762d353063302d362e39303420352e3630396101b28201527f2d31322e352031322e35332d31322e356832352e30353963362e3932203020316101d28201527f322e35323920352e3539362031322e3532392031322e35763530633020362e396101f28201527f303420352e3630392031322e352031322e3532392031322e356833372e3538396102128201527f63362e393220302031322e3532392d352e3539362031322e3532392d31322e356102328201527f762d373563302d362e3930342d352e3630392d31322e352d31322e3532392d316102528201527f322e35732d31322e353320352e3539362d31322e35332031322e357635362e326102728201527f3561362e32363420362e3236342030203120312d31322e3532392030563437386102928201527f2e3563302d362e3930342d352e3630392d31322e352d31322e35332d31322e356102b28201527f483639382e353239632d362e393220302d31322e35323920352e3539362d31326102d28201527f2e3532392031322e35763735633020362e39303420352e3630392031322e35206102f28201527f31322e3532392031322e357a22202f3e3c7061746820643d224d3135372e36356103128201527f3520353431632d362e39333220302d31322e3535322d352e3539362d31322e356103328201527f35322d31322e35762d353063302d362e3930342d352e3631392d31322e352d316103528201527f322e3535312d31322e3553313230203437312e35393620313230203437382e356103728201527f763735633020362e39303420352e36322031322e352031322e3535322031322e6103928201527f35683135302e363263362e39333320302031322e3535322d352e3539362031326103b28201527f2e3535322d31322e35762d353063302d362e39303420352e3631392d31322e356103d28201527f2031322e3535322d31322e35683134342e33343563332e343635203020362e326103f28201527f373620322e37393820362e32373620362e3235732d322e38313120362e32352d6104128201527f362e32373620362e3235483332302e383238632d362e39333320302d31322e356104328201527f353220352e3539362d31322e3535322031322e357633372e35633020362e39306104528201527f3420352e3631392031322e352031322e3535322031322e35683135302e3632636104728201527f362e39333320302031322e3535322d352e3539362031322e3535322d31322e356104928201527f762d373563302d362e3930342d352e3631392d31322e352d31322e3535322d316104b28201527f322e35483238332e313732632d362e39333220302d31322e35353120352e35396104d28201527f362d31322e3535312031322e35763530633020362e3930342d352e36313920316104f28201527f322e352d31322e3535322031322e35682d32352e313033632d362e39333320306105128201527f2d31322e3535322d352e3539362d31322e3535322d31322e35762d353063302d6105328201527f362e3930342d352e36322d31322e352d31322e3535322d31322e35732d31322e6105528201527f35353220352e3539362d31322e3535322031322e35763530633020362e3930346105728201527f2d352e3631392031322e352d31322e3535312031322e35682d32352e3130347a6105928201527f6d3330312e3234322d362e3235633020332e3435322d322e38313120362e32356105b28201527f2d362e32373620362e3235483333392e363535632d332e34363520302d362e326105d28201527f37362d322e3739382d362e3237362d362e323573322e3831312d362e323520366105f28201527f2e3237362d362e3235683131322e39363663332e343635203020362e323736206106128201527f322e37393820362e32373620362e32357a4d343937203535332e3831386330206106328201527f362e39323920352e3632382031322e3534362031322e3537312031322e3534366106528201527f6831333261362e323820362e323820302030203120362e32383620362e3237326106728201527f20362e323820362e32382030203020312d362e32383620362e323733682d31336106928201527f32632d362e39343320302d31322e35373120352e3631362d31322e35373120316106b28201527f322e3534364131322e35362031322e3536203020302030203530392e353731206106d28201527f363034683135302e38353863362e39343320302031322e3537312d352e3631366106f28201527f2031322e3537312d31322e353435762d3131322e393163302d362e3932382d356107128201527f2e3632382d31322e3534352d31322e3537312d31322e353435483530392e35376107328201527f31632d362e39343320302d31322e35373120352e3631372d31322e35373120316107528201527f322e3534357637352e3237337a6d33372e3731342d36322e373237632d362e396107728201527f343320302d31322e35373120352e3631372d31322e3537312031322e353435766107928201527f32352e303931633020362e39323920352e3632382031322e3534362031322e356107b28201527f37312031322e353436683130302e35373263362e39343320302031322e3537316107d28201527f2d352e3631372031322e3537312d31322e353436762d32352e30393163302d366107f28201527f2e3932382d352e3632382d31322e3534352d31322e3537312d31322e353435486108128201527f3533342e3731347a222066696c6c2d72756c653d226576656e6f646422202f3e6108328201527f3c2f673e3c2f7376673e0000000000000000000000000000000000000000000061085282015261085c01949350505050565b7f7b226e616d65223a20227761676d6920230000000000000000000000000000008152600083516125f28160118501602088016117b3565b7f222c2022696d616765223a2022646174613a696d6167652f7376672b786d6c3b6011918401918201527f6261736536342c00000000000000000000000000000000000000000000000000603182015283516126558160388401602088016117b3565b7f227d00000000000000000000000000000000000000000000000000000000000060389290910191820152603a01949350505050565b7f646174613a6170706c69636174696f6e2f6a736f6e3b6261736536342c0000008152600082516126c381601d8501602087016117b3565b91909101601d0192915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b600082821015612711576127116126d0565b500390565b60008219821115612729576127296126d0565b500190565b60007fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff820361275f5761275f6126d0565b5060010190565b60008261277557612775611aea565b500490565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6000817fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff04831182151516156127e1576127e16126d0565b500290565b600073ffffffffffffffffffffffffffffffffffffffff80871683528086166020840152508360408301526080606083015261282560808301846117df565b9695505050505050565b60006020828403121561284157600080fd5b81516117ac8161175e56fe4142434445464748494a4b4c4d4e4f505152535455565758595a6162636465666768696a6b6c6d6e6f707172737475767778797a303132333435363738392b2fa26469706673582212201665a4f9111990d7529375848d3fd02c0121091a940da59e763eba826e7b077064736f6c634300080d0033',
- )
+ ).resolves.toMatch(/^0x.*/)
})
test('parameters: blockNumber', async () => {
diff --git a/packages/core/src/experimental/actions/getCallsStatus.test.ts b/packages/core/src/actions/getCallsStatus.test.ts
similarity index 67%
rename from packages/core/src/experimental/actions/getCallsStatus.test.ts
rename to packages/core/src/actions/getCallsStatus.test.ts
index 367c33c303..badd3478ee 100644
--- a/packages/core/src/experimental/actions/getCallsStatus.test.ts
+++ b/packages/core/src/actions/getCallsStatus.test.ts
@@ -2,8 +2,8 @@ import { accounts, config, testClient } from '@wagmi/test'
import { parseEther } from 'viem'
import { expect, test } from 'vitest'
-import { connect } from '../../actions/connect.js'
-import { disconnect } from '../../actions/disconnect.js'
+import { connect } from './connect.js'
+import { disconnect } from './disconnect.js'
import { getCallsStatus } from './getCallsStatus.js'
import { sendCalls } from './sendCalls.js'
@@ -11,7 +11,7 @@ const connector = config.connectors[0]!
test('default', async () => {
await connect(config, { connector })
- const id = await sendCalls(config, {
+ const { id } = await sendCalls(config, {
calls: [
{
data: '0xdeadbeef',
@@ -33,7 +33,7 @@ test('default', async () => {
id,
})
- expect(status).toBe('CONFIRMED')
+ expect(status).toBe('success')
expect(
receipts?.map((x) => ({ ...x, blockHash: undefined })),
).toMatchInlineSnapshot(
@@ -41,27 +41,27 @@ test('default', async () => {
[
{
"blockHash": undefined,
- "blockNumber": 19258214n,
- "gasUsed": 21064n,
+ "blockNumber": 23535881n,
+ "gasUsed": 21160n,
"logs": [],
"status": "success",
- "transactionHash": "0x13c53b2d4d9da424835525349cd66e553330f323d6fb19458b801ae1f7989a41",
+ "transactionHash": "0x7add018cb41f4b86d793758248d20cb8394364d9379d201cb7747db29c4aac18",
},
{
"blockHash": undefined,
- "blockNumber": 19258214n,
+ "blockNumber": 23535881n,
"gasUsed": 21000n,
"logs": [],
"status": "success",
- "transactionHash": "0xd8397b3e82b061c26a0c2093f1ceca0c3662a512614f7d6370349e89d0eea007",
+ "transactionHash": "0x5019ef03b9ee83c6398d1a68490b56878300c1f83697c3b3eeaf666baf63abff",
},
{
"blockHash": undefined,
- "blockNumber": 19258214n,
+ "blockNumber": 23535881n,
"gasUsed": 21000n,
"logs": [],
"status": "success",
- "transactionHash": "0x4d26e346593d9ea265bb164b115e89aa92df43b0b8778ac75d4ad28e2a22b101",
+ "transactionHash": "0xe61204827da836e4bc51fbfe15f04e5b1307c50f160d1add15675c8654663f20",
},
]
`,
diff --git a/packages/core/src/experimental/actions/getCallsStatus.ts b/packages/core/src/actions/getCallsStatus.ts
similarity index 69%
rename from packages/core/src/experimental/actions/getCallsStatus.ts
rename to packages/core/src/actions/getCallsStatus.ts
index 214a6c8cae..0d560421b7 100644
--- a/packages/core/src/experimental/actions/getCallsStatus.ts
+++ b/packages/core/src/actions/getCallsStatus.ts
@@ -3,11 +3,12 @@ import {
type GetCallsStatusParameters as viem_GetCallsStatusParameters,
type GetCallsStatusReturnType as viem_GetCallsStatusReturnType,
getCallsStatus as viem_getCallsStatus,
-} from 'viem/experimental'
+} from 'viem/actions'
-import { getConnectorClient } from '../../actions/getConnectorClient.js'
-import type { Config } from '../../createConfig.js'
-import type { ConnectorParameter } from '../../types/properties.js'
+import type { Config } from '../createConfig.js'
+import type { ConnectorParameter } from '../types/properties.js'
+import { getAction } from '../utils/getAction.js'
+import { getConnectorClient } from './getConnectorClient.js'
export type GetCallsStatusParameters = viem_GetCallsStatusParameters &
ConnectorParameter
@@ -23,5 +24,6 @@ export async function getCallsStatus(
): Promise {
const { connector, id } = parameters
const client = await getConnectorClient(config, { connector })
- return viem_getCallsStatus(client, { id })
+ const action = getAction(client, viem_getCallsStatus, 'getCallsStatus')
+ return action({ id })
}
diff --git a/packages/core/src/experimental/actions/getCapabilities.test.ts b/packages/core/src/actions/getCapabilities.test.ts
similarity index 92%
rename from packages/core/src/experimental/actions/getCapabilities.test.ts
rename to packages/core/src/actions/getCapabilities.test.ts
index 2946e27a5c..e7c02ec444 100644
--- a/packages/core/src/experimental/actions/getCapabilities.test.ts
+++ b/packages/core/src/actions/getCapabilities.test.ts
@@ -1,8 +1,8 @@
import { accounts, config } from '@wagmi/test'
import { expect, test } from 'vitest'
-import { connect } from '../../actions/connect.js'
-import { disconnect } from '../../actions/disconnect.js'
+import { connect } from './connect.js'
+import { disconnect } from './disconnect.js'
import { getCapabilities } from './getCapabilities.js'
const connector = config.connectors[0]!
diff --git a/packages/core/src/actions/getCapabilities.ts b/packages/core/src/actions/getCapabilities.ts
new file mode 100644
index 0000000000..ab8ea82bfb
--- /dev/null
+++ b/packages/core/src/actions/getCapabilities.ts
@@ -0,0 +1,39 @@
+import type { Account } from 'viem'
+import {
+ type GetCapabilitiesErrorType as viem_GetCapabilitiesErrorType,
+ type GetCapabilitiesParameters as viem_GetCapabilitiesParameters,
+ type GetCapabilitiesReturnType as viem_GetCapabilitiesReturnType,
+ getCapabilities as viem_getCapabilities,
+} from 'viem/actions'
+
+import type { Config } from '../createConfig.js'
+import type { ConnectorParameter } from '../types/properties.js'
+import { getConnectorClient } from './getConnectorClient.js'
+
+export type GetCapabilitiesParameters<
+ config extends Config = Config,
+ chainId extends config['chains'][number]['id'] | undefined = undefined,
+> = viem_GetCapabilitiesParameters & ConnectorParameter
+
+export type GetCapabilitiesReturnType<
+ config extends Config = Config,
+ chainId extends config['chains'][number]['id'] | undefined = undefined,
+> = viem_GetCapabilitiesReturnType
+
+export type GetCapabilitiesErrorType = viem_GetCapabilitiesErrorType
+
+/** https://wagmi.sh/core/api/actions/getCapabilities */
+export async function getCapabilities<
+ config extends Config,
+ chainId extends config['chains'][number]['id'] | undefined = undefined,
+>(
+ config: config,
+ parameters: GetCapabilitiesParameters = {},
+): Promise> {
+ const { account, chainId, connector } = parameters
+ const client = await getConnectorClient(config, { account, connector })
+ return viem_getCapabilities(client as any, {
+ account: account as Account,
+ chainId,
+ })
+}
diff --git a/packages/core/src/actions/getChains.test-d.ts b/packages/core/src/actions/getChains.test-d.ts
index cd5f04c9c5..56e33f9955 100644
--- a/packages/core/src/actions/getChains.test-d.ts
+++ b/packages/core/src/actions/getChains.test-d.ts
@@ -1,5 +1,4 @@
import { type chain, config } from '@wagmi/test'
-import type { Chain } from 'viem'
import { expectTypeOf, test } from 'vitest'
import { getChains } from './getChains.js'
@@ -8,5 +7,4 @@ test('default', async () => {
const chains = getChains(config)
expectTypeOf(chains[0]).toEqualTypeOf()
expectTypeOf(chains[2]).toEqualTypeOf()
- expectTypeOf(chains[3]).toEqualTypeOf()
})
diff --git a/packages/core/src/actions/getChains.ts b/packages/core/src/actions/getChains.ts
index a91e6e89b4..bd9ba468a5 100644
--- a/packages/core/src/actions/getChains.ts
+++ b/packages/core/src/actions/getChains.ts
@@ -2,10 +2,8 @@ import type { Chain } from 'viem'
import type { Config } from '../createConfig.js'
import { deepEqual } from '../utils/deepEqual.js'
-export type GetChainsReturnType = readonly [
- ...config['chains'],
- ...Chain[],
-]
+export type GetChainsReturnType =
+ config['chains']
let previousChains: readonly Chain[] = []
diff --git a/packages/core/src/actions/getClient.ts b/packages/core/src/actions/getClient.ts
index 82f1c6c171..ba78cafa34 100644
--- a/packages/core/src/actions/getClient.ts
+++ b/packages/core/src/actions/getClient.ts
@@ -44,9 +44,9 @@ export function getClient<
config: config,
parameters: GetClientParameters = {},
): GetClientReturnType {
- let client = undefined
try {
- client = config.getClient(parameters)
- } catch {}
- return client as GetClientReturnType
+ return config.getClient(parameters) as GetClientReturnType
+ } catch {
+ return undefined as never
+ }
}
diff --git a/packages/core/src/actions/getAccount.test-d.ts b/packages/core/src/actions/getConnection.test-d.ts
similarity index 95%
rename from packages/core/src/actions/getAccount.test-d.ts
rename to packages/core/src/actions/getConnection.test-d.ts
index 728468039b..9c7540a6ac 100644
--- a/packages/core/src/actions/getAccount.test-d.ts
+++ b/packages/core/src/actions/getConnection.test-d.ts
@@ -3,10 +3,10 @@ import type { Address } from 'viem'
import { expectTypeOf, test } from 'vitest'
import type { Connector } from '../createConfig.js'
-import { getAccount } from './getAccount.js'
+import { getConnection } from './getConnection.js'
test('states', () => {
- const result = getAccount(config)
+ const result = getConnection(config)
switch (result.status) {
case 'reconnecting': {
diff --git a/packages/core/src/actions/getAccount.test.ts b/packages/core/src/actions/getConnection.test.ts
similarity index 79%
rename from packages/core/src/actions/getAccount.test.ts
rename to packages/core/src/actions/getConnection.test.ts
index a538357875..d49f831054 100644
--- a/packages/core/src/actions/getAccount.test.ts
+++ b/packages/core/src/actions/getConnection.test.ts
@@ -3,10 +3,10 @@ import { expect, test } from 'vitest'
import { connect } from './connect.js'
import { disconnect } from './disconnect.js'
-import { getAccount } from './getAccount.js'
+import { getConnection } from './getConnection.js'
test('default', () => {
- expect(getAccount(config)).toMatchInlineSnapshot(`
+ expect(getConnection(config)).toMatchInlineSnapshot(`
{
"address": undefined,
"addresses": undefined,
@@ -23,15 +23,15 @@ test('default', () => {
})
test('behavior: connected', async () => {
- let result = getAccount(config)
+ let result = getConnection(config)
expect(result.status).toEqual('disconnected')
await connect(config, { connector: config.connectors[0]! })
- result = getAccount(config)
+ result = getConnection(config)
expect(result.address).toBeDefined()
expect(result.status).toEqual('connected')
await disconnect(config)
- result = getAccount(config)
+ result = getConnection(config)
expect(result.status).toEqual('disconnected')
})
diff --git a/packages/core/src/actions/getAccount.ts b/packages/core/src/actions/getConnection.ts
similarity index 93%
rename from packages/core/src/actions/getAccount.ts
rename to packages/core/src/actions/getConnection.ts
index af5daea028..f7dc4d0600 100644
--- a/packages/core/src/actions/getAccount.ts
+++ b/packages/core/src/actions/getConnection.ts
@@ -2,7 +2,7 @@ import type { Address, Chain } from 'viem'
import type { Config, Connector } from '../createConfig.js'
-export type GetAccountReturnType<
+export type GetConnectionReturnType<
config extends Config = Config,
///
chain = Config extends config ? Chain : config['chains'][number],
@@ -56,17 +56,17 @@ export type GetAccountReturnType<
status: 'disconnected'
}
-/** https://wagmi.sh/core/api/actions/getAccount */
-export function getAccount(
+/** https://wagmi.sh/core/api/actions/getConnection */
+export function getConnection(
config: config,
-): GetAccountReturnType {
+): GetConnectionReturnType {
const uid = config.state.current!
const connection = config.state.connections.get(uid)
const addresses = connection?.accounts
const address = addresses?.[0]
const chain = config.chains.find(
(chain) => chain.id === connection?.chainId,
- ) as GetAccountReturnType['chain']
+ ) as GetConnectionReturnType['chain']
const status = config.state.status
switch (status) {
diff --git a/packages/core/src/actions/getConnectorClient.test.ts b/packages/core/src/actions/getConnectorClient.test.ts
index a9d60f5142..465db5d8ce 100644
--- a/packages/core/src/actions/getConnectorClient.test.ts
+++ b/packages/core/src/actions/getConnectorClient.test.ts
@@ -1,6 +1,6 @@
import { address, config } from '@wagmi/test'
+import type { Address } from 'viem'
import { expect, test } from 'vitest'
-
import type { Connector } from '../createConfig.js'
import { connect } from './connect.js'
import { disconnect } from './disconnect.js'
@@ -27,10 +27,11 @@ test.todo('custom connector client')
test('behavior: account address is checksummed', async () => {
await connect(config, { connector })
- const account = '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266'
+ const account =
+ '0x95132632579b073D12a6673e18Ab05777a6B86f8'.toLowerCase() as Address
const client = await getConnectorClient(config, { account })
expect(client.account.address).toMatchInlineSnapshot(
- '"0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"',
+ '"0x95132632579b073D12a6673e18Ab05777a6B86f8"',
)
expect(client.account.address).not.toBe(account)
await disconnect(config, { connector })
diff --git a/packages/core/src/actions/getConnectorClient.ts b/packages/core/src/actions/getConnectorClient.ts
index 534ba76bc6..913cbb53f5 100644
--- a/packages/core/src/actions/getConnectorClient.ts
+++ b/packages/core/src/actions/getConnectorClient.ts
@@ -43,6 +43,10 @@ export type GetConnectorClientParameters<
* an account within the wallet).
*/
account?: Address | Account | null | undefined
+ /**
+ * Assert that the current chain ID matches the connector's chain ID.
+ */
+ assertChainId?: boolean | undefined
}
>
@@ -75,6 +79,8 @@ export async function getConnectorClient<
config: config,
parameters: GetConnectorClientParameters = {},
): Promise> {
+ const { assertChainId = true } = parameters
+
// Get connection
let connection: Connection | undefined
if (parameters.connector) {
@@ -105,9 +111,9 @@ export async function getConnectorClient<
// Check connector using same chainId as connection
const connectorChainId = await connection.connector.getChainId()
- if (connectorChainId !== connection.chainId)
+ if (assertChainId && connectorChainId !== chainId)
throw new ConnectorChainMismatchError({
- connectionChainId: connection.chainId,
+ connectionChainId: chainId,
connectorChainId,
})
diff --git a/packages/core/src/actions/getConnectors.test.ts b/packages/core/src/actions/getConnectors.test.ts
index d15f5fbb08..9a568668f6 100644
--- a/packages/core/src/actions/getConnectors.test.ts
+++ b/packages/core/src/actions/getConnectors.test.ts
@@ -5,4 +5,5 @@ import { getConnectors } from './getConnectors.js'
test('default', () => {
expect(getConnectors(config)).toEqual(config.connectors)
+ expect(getConnectors(config)).toEqual(config.connectors)
})
diff --git a/packages/core/src/actions/getConnectors.ts b/packages/core/src/actions/getConnectors.ts
index 439362d3f4..d4786484ed 100644
--- a/packages/core/src/actions/getConnectors.ts
+++ b/packages/core/src/actions/getConnectors.ts
@@ -1,5 +1,4 @@
import type { Config, Connector } from '../createConfig.js'
-import { deepEqual } from '../utils/deepEqual.js'
export type GetConnectorsReturnType =
config['connectors']
@@ -11,7 +10,13 @@ export function getConnectors(
config: config,
): GetConnectorsReturnType {
const connectors = config.connectors
- if (deepEqual(previousConnectors, connectors)) return previousConnectors
+ if (
+ previousConnectors.length === connectors.length &&
+ previousConnectors.every(
+ (connector, index) => connector === connectors[index],
+ )
+ )
+ return previousConnectors
previousConnectors = connectors
return connectors
}
diff --git a/packages/core/src/actions/getEnsAvatar.test.ts b/packages/core/src/actions/getEnsAvatar.test.ts
index ed1e830481..790c6a8a46 100644
--- a/packages/core/src/actions/getEnsAvatar.test.ts
+++ b/packages/core/src/actions/getEnsAvatar.test.ts
@@ -3,7 +3,7 @@ import { expect, test } from 'vitest'
import { getEnsAvatar } from './getEnsAvatar.js'
-test('default', async () => {
+test.skip('default', async () => {
await expect(
getEnsAvatar(config, {
name: 'wevm.eth',
diff --git a/packages/core/src/actions/getProof.test.ts b/packages/core/src/actions/getProof.test.ts
index 5ff0af2828..49fff585d7 100644
--- a/packages/core/src/actions/getProof.test.ts
+++ b/packages/core/src/actions/getProof.test.ts
@@ -3,7 +3,7 @@ import { expect, test } from 'vitest'
import { getProof } from './getProof.js'
-test('default', async () => {
+test.skip('default', async () => {
await expect(
getProof(config, {
chainId: chain.optimism.id,
diff --git a/packages/core/src/actions/getToken.test.ts b/packages/core/src/actions/getToken.test.ts
deleted file mode 100644
index 8af08736a7..0000000000
--- a/packages/core/src/actions/getToken.test.ts
+++ /dev/null
@@ -1,84 +0,0 @@
-import { config } from '@wagmi/test'
-import { expect, test } from 'vitest'
-
-import { getToken } from './getToken.js'
-
-test('default', async () => {
- await expect(
- getToken(config, {
- address: '0x1f9840a85d5af5bf1d1762f925bdaddc4201f984',
- }),
- ).resolves.toMatchInlineSnapshot(`
- {
- "address": "0x1f9840a85d5af5bf1d1762f925bdaddc4201f984",
- "decimals": 18,
- "name": "Uniswap",
- "symbol": "UNI",
- "totalSupply": {
- "formatted": "1000000000",
- "value": 1000000000000000000000000000n,
- },
- }
- `)
-})
-
-test('parameters: formatUnits', async () => {
- await expect(
- getToken(config, {
- address: '0x1f9840a85d5af5bf1d1762f925bdaddc4201f984',
- formatUnits: 'gwei',
- }),
- ).resolves.toMatchInlineSnapshot(`
- {
- "address": "0x1f9840a85d5af5bf1d1762f925bdaddc4201f984",
- "decimals": 18,
- "name": "Uniswap",
- "symbol": "UNI",
- "totalSupply": {
- "formatted": "1000000000000000000",
- "value": 1000000000000000000000000000n,
- },
- }
- `)
-})
-
-test('behavior: bytes32 token', async () => {
- await expect(
- getToken(config, {
- address: '0x9f8f72aa9304c8b593d555f12ef6589cc3a579a2',
- }),
- ).resolves.toMatchInlineSnapshot(`
- {
- "address": "0x9f8f72aa9304c8b593d555f12ef6589cc3a579a2",
- "decimals": 18,
- "name": "Maker",
- "symbol": "MKR",
- "totalSupply": {
- "formatted": "977631.036950888222010062",
- "value": 977631036950888222010062n,
- },
- }
- `)
-})
-
-test('behavior: bogus token', async () => {
- await expect(
- getToken(config, {
- address: '0xa0cf798816d4b9b9866b5330eea46a18382f251e',
- }),
- ).rejects.toThrowErrorMatchingInlineSnapshot(`
- [ContractFunctionExecutionError: The contract function "decimals" returned no data ("0x").
-
- This could be due to any of the following:
- - The contract does not have the function "decimals",
- - The parameters passed to the contract function may be invalid, or
- - The address is not a contract.
-
- Contract Call:
- address: 0xa0cf798816d4b9b9866b5330eea46a18382f251e
- function: decimals()
-
- Docs: https://viem.sh/docs/contract/multicall
- Version: viem@2.23.12]
- `)
-})
diff --git a/packages/core/src/actions/getToken.ts b/packages/core/src/actions/getToken.ts
deleted file mode 100644
index 480a742820..0000000000
--- a/packages/core/src/actions/getToken.ts
+++ /dev/null
@@ -1,141 +0,0 @@
-import type { Address, Hex } from 'viem'
-import {
- ContractFunctionExecutionError,
- formatUnits,
- hexToString,
- trim,
-} from 'viem'
-
-import type { Config } from '../createConfig.js'
-import type { ChainIdParameter } from '../types/properties.js'
-import type { Unit } from '../types/unit.js'
-import type { Compute } from '../types/utils.js'
-import { getUnit } from '../utils/getUnit.js'
-import { type ReadContractsErrorType, readContracts } from './readContracts.js'
-
-export type GetTokenParameters = Compute<
- ChainIdParameter & {
- address: Address
- formatUnits?: Unit | undefined
- }
->
-
-export type GetTokenReturnType = {
- address: Address
- decimals: number
- name: string | undefined
- symbol: string | undefined
- totalSupply: {
- formatted: string
- value: bigint
- }
-}
-
-export type GetTokenErrorType = ReadContractsErrorType
-
-/** @deprecated */
-export async function getToken(
- config: config,
- parameters: GetTokenParameters,
-): Promise {
- const { address, chainId, formatUnits: unit = 18 } = parameters
-
- function getAbi(type: type) {
- return [
- {
- type: 'function',
- name: 'decimals',
- stateMutability: 'view',
- inputs: [],
- outputs: [{ type: 'uint8' }],
- },
- {
- type: 'function',
- name: 'name',
- stateMutability: 'view',
- inputs: [],
- outputs: [{ type }],
- },
- {
- type: 'function',
- name: 'symbol',
- stateMutability: 'view',
- inputs: [],
- outputs: [{ type }],
- },
- {
- type: 'function',
- name: 'totalSupply',
- stateMutability: 'view',
- inputs: [],
- outputs: [{ type: 'uint256' }],
- },
- ] as const
- }
-
- try {
- const abi = getAbi('string')
- const contractConfig = { address, abi, chainId } as const
- const [decimals, name, symbol, totalSupply] = await readContracts(config, {
- allowFailure: true,
- contracts: [
- { ...contractConfig, functionName: 'decimals' },
- { ...contractConfig, functionName: 'name' },
- { ...contractConfig, functionName: 'symbol' },
- { ...contractConfig, functionName: 'totalSupply' },
- ] as const,
- })
-
- // throw if `name` or `symbol` failed
- if (name.error instanceof ContractFunctionExecutionError) throw name.error
- if (symbol.error instanceof ContractFunctionExecutionError)
- throw symbol.error
-
- // `decimals` and `totalSupply` are required
- if (decimals.error) throw decimals.error
- if (totalSupply.error) throw totalSupply.error
-
- return {
- address,
- decimals: decimals.result,
- name: name.result,
- symbol: symbol.result,
- totalSupply: {
- formatted: formatUnits(totalSupply.result!, getUnit(unit)),
- value: totalSupply.result,
- },
- }
- } catch (error) {
- // In the chance that there is an error upon decoding the contract result,
- // it could be likely that the contract data is represented as bytes32 instead
- // of a string.
- if (error instanceof ContractFunctionExecutionError) {
- const abi = getAbi('bytes32')
- const contractConfig = { address, abi, chainId } as const
- const [decimals, name, symbol, totalSupply] = await readContracts(
- config,
- {
- allowFailure: false,
- contracts: [
- { ...contractConfig, functionName: 'decimals' },
- { ...contractConfig, functionName: 'name' },
- { ...contractConfig, functionName: 'symbol' },
- { ...contractConfig, functionName: 'totalSupply' },
- ] as const,
- },
- )
- return {
- address,
- decimals,
- name: hexToString(trim(name as Hex, { dir: 'right' })),
- symbol: hexToString(trim(symbol as Hex, { dir: 'right' })),
- totalSupply: {
- formatted: formatUnits(totalSupply, getUnit(unit)),
- value: totalSupply,
- },
- }
- }
-
- throw error
- }
-}
diff --git a/packages/core/src/actions/getTransaction.test-d.ts b/packages/core/src/actions/getTransaction.test-d.ts
index 9476b781c1..c5ab9b37c3 100644
--- a/packages/core/src/actions/getTransaction.test-d.ts
+++ b/packages/core/src/actions/getTransaction.test-d.ts
@@ -11,6 +11,8 @@ test('chain formatters', async () => {
transports: { [celo.id]: http(), [mainnet.id]: http() },
})
const result = await getTransaction(config, { hash: '0x123' })
+ // @ts-expect-error
+ result.feeCurrency
if (result.chainId === celo.id) {
expectTypeOf(result.feeCurrency).toEqualTypeOf<`0x${string}` | null>()
}
diff --git a/packages/core/src/actions/getTransactionConfirmations.test-d.ts b/packages/core/src/actions/getTransactionConfirmations.test-d.ts
index fd9168dfa2..42474ca6c7 100644
--- a/packages/core/src/actions/getTransactionConfirmations.test-d.ts
+++ b/packages/core/src/actions/getTransactionConfirmations.test-d.ts
@@ -1,8 +1,7 @@
import { config } from '@wagmi/test'
+import { http } from 'viem'
import { mainnet, zkSync } from 'viem/chains'
import { test } from 'vitest'
-
-import { http } from 'viem'
import { createConfig } from '../createConfig.js'
import { getTransactionConfirmations } from './getTransactionConfirmations.js'
diff --git a/packages/core/src/actions/getTransactionCount.test.ts b/packages/core/src/actions/getTransactionCount.test.ts
index 95f0e6ddee..7f4561571e 100644
--- a/packages/core/src/actions/getTransactionCount.test.ts
+++ b/packages/core/src/actions/getTransactionCount.test.ts
@@ -1,7 +1,6 @@
import { accounts, chain, config, testClient } from '@wagmi/test'
-import { expect, test } from 'vitest'
-
import type { BlockTag } from 'viem'
+import { expect, test } from 'vitest'
import { getTransactionCount } from './getTransactionCount.js'
const address = accounts[0]
diff --git a/packages/core/src/actions/getWalletClient.test-d.ts b/packages/core/src/actions/getWalletClient.test-d.ts
index d1d87f5e97..8f1d20ebba 100644
--- a/packages/core/src/actions/getWalletClient.test-d.ts
+++ b/packages/core/src/actions/getWalletClient.test-d.ts
@@ -1,7 +1,6 @@
import { chain, config } from '@wagmi/test'
-import { expectTypeOf, test } from 'vitest'
-
import type { Account } from 'viem'
+import { expectTypeOf, test } from 'vitest'
import { getWalletClient } from './getWalletClient.js'
test('default', async () => {
diff --git a/packages/core/src/actions/multicall.bench-d.ts b/packages/core/src/actions/multicall.bench-d.ts
new file mode 100644
index 0000000000..000efc9e27
--- /dev/null
+++ b/packages/core/src/actions/multicall.bench-d.ts
@@ -0,0 +1,76 @@
+import { attest } from '@ark/attest'
+import { abi, config } from '@wagmi/test'
+import { test } from 'vitest'
+import { multicall } from './multicall.js'
+
+test('default', () => {
+ multicall(config, {
+ chainId: 1,
+ contracts: [
+ {
+ address: '0x',
+ abi: abi.erc20,
+ functionName: 'balanceOf',
+ args: ['0x'],
+ },
+ {
+ address: '0x',
+ abi: abi.wagmiMintExample,
+ functionName: 'tokenURI',
+ args: [123n],
+ },
+ {
+ address: '0x',
+ abi: abi.viewOverloads,
+ functionName: 'foo',
+ },
+ {
+ address: '0x',
+ abi: abi.viewOverloads,
+ functionName: 'foo',
+ args: ['0x'],
+ },
+ {
+ address: '0x',
+ abi: abi.viewOverloads,
+ functionName: 'foo',
+ args: ['0x', '0x'],
+ },
+ {
+ abi: abi.wagmigotchi,
+ address: '0x',
+ functionName: 'love',
+ args: ['0x'],
+ },
+ {
+ abi: abi.wagmigotchi,
+ address: '0x',
+ functionName: 'love',
+ args: ['0x'],
+ },
+ {
+ abi: abi.wagmigotchi,
+ address: '0x',
+ functionName: 'getAlive',
+ },
+ {
+ abi: abi.mloot,
+ address: '0x',
+ functionName: 'tokenOfOwnerByIndex',
+ args: ['0x', 0n],
+ },
+ {
+ abi: abi.erc20,
+ address: '0x',
+ functionName: 'symbol',
+ },
+ {
+ abi: abi.erc20,
+ address: '0x',
+ functionName: 'balanceOf',
+ args: ['0x'],
+ },
+ ],
+ })
+ attest.instantiations([523679, 'instantiations'])
+})
diff --git a/packages/core/src/actions/multicall.test.ts b/packages/core/src/actions/multicall.test.ts
index cf2d7c0ddf..a4cca18f60 100644
--- a/packages/core/src/actions/multicall.test.ts
+++ b/packages/core/src/actions/multicall.test.ts
@@ -18,7 +18,7 @@ test('default', async () => {
).resolves.toMatchInlineSnapshot(`
[
{
- "result": 4n,
+ "result": 10n,
"status": "success",
},
]
@@ -40,7 +40,7 @@ test('allowFailure', async () => {
}),
).resolves.toMatchInlineSnapshot(`
[
- 4n,
+ 10n,
]
`)
})
diff --git a/packages/core/src/actions/prepareTransactionRequest.test.ts b/packages/core/src/actions/prepareTransactionRequest.test.ts
index 1411011e3e..bc4a9befc9 100644
--- a/packages/core/src/actions/prepareTransactionRequest.test.ts
+++ b/packages/core/src/actions/prepareTransactionRequest.test.ts
@@ -1,8 +1,7 @@
import { accounts, config, privateKey } from '@wagmi/test'
-import { expect, test } from 'vitest'
-
import { parseEther } from 'viem'
import { privateKeyToAccount } from 'viem/accounts'
+import { expect, test } from 'vitest'
import { connect } from './connect.js'
import { disconnect } from './disconnect.js'
import { prepareTransactionRequest } from './prepareTransactionRequest.js'
@@ -19,6 +18,7 @@ test('default', async () => {
const {
gas: _gas,
+ gasPrice: _gasPrice,
maxFeePerGas: _mfpg,
maxPriorityFeePerGas: _mpfpg,
nonce: _nonce,
@@ -26,9 +26,9 @@ test('default', async () => {
} = request
expect(rest).toMatchInlineSnapshot(`
{
- "account": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
+ "account": "0x95132632579b073D12a6673e18Ab05777a6B86f8",
"chainId": 1,
- "from": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
+ "from": "0x95132632579b073D12a6673e18Ab05777a6B86f8",
"to": "0x70997970c51812dc3a010c7d01b50e0d17dc79c8",
"type": "eip1559",
"value": 1000000000000000000n,
@@ -49,6 +49,7 @@ test('parameters: account', async () => {
const {
gas: _gas,
+ gasPrice: _gasPrice,
maxFeePerGas: _mfpg,
maxPriorityFeePerGas: _mpfpg,
nonce: _nonce,
@@ -56,9 +57,9 @@ test('parameters: account', async () => {
} = request
expect(rest).toMatchInlineSnapshot(`
{
- "account": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
+ "account": "0x95132632579b073D12a6673e18Ab05777a6B86f8",
"chainId": 1,
- "from": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
+ "from": "0x95132632579b073D12a6673e18Ab05777a6B86f8",
"to": "0x70997970c51812dc3a010c7d01b50e0d17dc79c8",
"type": "eip1559",
"value": 1000000000000000000n,
@@ -79,6 +80,7 @@ test('behavior: local account', async () => {
const {
gas: _gas,
+ gasPrice: _gasPrice,
maxFeePerGas: _mfpg,
maxPriorityFeePerGas: _mpfpg,
nonce: _nonce,
@@ -87,11 +89,11 @@ test('behavior: local account', async () => {
expect(rest).toMatchInlineSnapshot(`
{
"account": {
- "address": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
- "experimental_signAuthorization": [Function],
+ "address": "0x95132632579b073D12a6673e18Ab05777a6B86f8",
"nonceManager": undefined,
- "publicKey": "0x048318535b54105d4a7aae60c08fc45f9687181b4fdfc625bd1a753fa7397fed753547f11ca8696646f2f3acb08e31016afac23e630c5d11f59f61fef57b0d2aa5",
+ "publicKey": "0x04e997cee8adb07b5269f375399109f53c94ddb7ac9cdb9252b74ba33fd471392fc563102ff7b38c85ee9d0a88c8819e6c97ea8b0db791d59c89086f62f5516863",
"sign": [Function],
+ "signAuthorization": [Function],
"signMessage": [Function],
"signTransaction": [Function],
"signTypedData": [Function],
@@ -99,7 +101,7 @@ test('behavior: local account', async () => {
"type": "local",
},
"chainId": 1,
- "from": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
+ "from": "0x95132632579b073D12a6673e18Ab05777a6B86f8",
"to": "0x70997970c51812dc3a010c7d01b50e0d17dc79c8",
"type": "eip1559",
"value": 1000000000000000000n,
diff --git a/packages/core/src/actions/prepareTransactionRequest.ts b/packages/core/src/actions/prepareTransactionRequest.ts
index 36ed81f774..3f62f73e72 100644
--- a/packages/core/src/actions/prepareTransactionRequest.ts
+++ b/packages/core/src/actions/prepareTransactionRequest.ts
@@ -13,13 +13,12 @@ import type { Config } from '../createConfig.js'
import type { SelectChains } from '../types/chain.js'
import type { ChainIdParameter } from '../types/properties.js'
import type {
- Compute,
IsNarrowable,
UnionCompute,
UnionStrictOmit,
} from '../types/utils.js'
import { getAction } from '../utils/getAction.js'
-import { getAccount } from './getAccount.js'
+import { getConnection } from './getConnection.js'
export type PrepareTransactionRequestParameters<
config extends Config = Config,
@@ -73,19 +72,17 @@ export type PrepareTransactionRequestReturnType<
///
chains extends readonly Chain[] = SelectChains,
> = {
- [key in keyof chains]: Compute<
- viem_PrepareTransactionRequestReturnType<
+ [key in keyof chains]: viem_PrepareTransactionRequestReturnType<
+ IsNarrowable extends true ? chains[key] : undefined,
+ Account,
+ chains[key],
+ Account,
+ request extends viem_PrepareTransactionRequestRequest<
IsNarrowable extends true ? chains[key] : undefined,
- Account,
- chains[key],
- Account,
- request extends viem_PrepareTransactionRequestRequest<
- IsNarrowable extends true ? chains[key] : undefined,
- chains[key]
- >
- ? request
- : never
+ chains[key]
>
+ ? request
+ : never
> & {
chainId: chains[key]['id']
}
@@ -108,7 +105,7 @@ export async function prepareTransactionRequest<
): Promise> {
const { account: account_, chainId, ...rest } = parameters
- const account = account_ ?? getAccount(config).address
+ const account = account_ ?? getConnection(config).address
const client = config.getClient({ chainId })
const action = getAction(
diff --git a/packages/core/src/actions/readContract.bench-d.ts b/packages/core/src/actions/readContract.bench-d.ts
new file mode 100644
index 0000000000..11f899abd6
--- /dev/null
+++ b/packages/core/src/actions/readContract.bench-d.ts
@@ -0,0 +1,41 @@
+import { attest } from '@ark/attest'
+import type { abi } from '@wagmi/test'
+import { parseAbi } from 'viem'
+import viemPackageJson from 'viem/package.json' with { type: 'json' }
+import { test } from 'vitest'
+import type { ReadContractParameters } from './readContract.js'
+
+test('default', () => {
+ type Result = ReadContractParameters<(typeof abi)['erc20'], 'balanceOf'>
+ const res = {} as Result
+ attest.instantiations([132033, 'instantiations'])
+ attest(res.args)
+ if (viemPackageJson.version.startsWith('2.43'))
+ attest(res.args).type.toString.snap(
+ // biome-ignore lint/style/noUnusedTemplateLiteral: stable
+ `readonly [account: \`0x\${string}\`]`,
+ )
+})
+
+const abiOverload = parseAbi([
+ 'function foo() view returns (int8)',
+ 'function foo(address account) view returns (string)',
+ 'function foo(address sender, address account) view returns ((address foo, address bar))',
+ 'function bar() view returns (int8)',
+])
+test('overloads', () => {
+ type Result = ReadContractParameters
+ const res = {} as Result
+ attest.instantiations([12984, 'instantiations'])
+ attest<
+ | readonly []
+ | readonly [account: `0x${string}`]
+ | readonly [sender: `0x${string}`, account: `0x${string}`]
+ | undefined
+ >(res.args)
+ if (viemPackageJson.version.startsWith('2.43'))
+ attest(res.args).type.toString.snap(` | readonly []
+ | readonly [account: \`0x\${string}\`]
+ | readonly [sender: \`0x\${string}\`, account: \`0x\${string}\`]
+ | undefined`)
+})
diff --git a/packages/core/src/actions/readContract.test-d.ts b/packages/core/src/actions/readContract.test-d.ts
index a667ec03e8..99c6c2f2d9 100644
--- a/packages/core/src/actions/readContract.test-d.ts
+++ b/packages/core/src/actions/readContract.test-d.ts
@@ -35,7 +35,6 @@ test('overloads', async () => {
functionName: 'foo',
args: ['0x'],
})
- // @ts-ignore – TODO: Fix https://github.com/wevm/viem/issues/1916
assertType(result3)
const result4 = await readContract(config, {
@@ -47,7 +46,6 @@ test('overloads', async () => {
assertType<{
foo: `0x${string}`
bar: `0x${string}`
- // @ts-ignore – TODO: Fix https://github.com/wevm/viem/issues/1916
}>(result4)
})
diff --git a/packages/core/src/actions/readContract.test.ts b/packages/core/src/actions/readContract.test.ts
index 37f0db7e0c..c121070e31 100644
--- a/packages/core/src/actions/readContract.test.ts
+++ b/packages/core/src/actions/readContract.test.ts
@@ -11,7 +11,7 @@ test('default', async () => {
functionName: 'balanceOf',
args: ['0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC'],
}),
- ).resolves.toMatchInlineSnapshot('4n')
+ ).resolves.toMatchInlineSnapshot('10n')
})
test('parameters: chainId', async () => {
@@ -23,7 +23,7 @@ test('parameters: chainId', async () => {
args: ['0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC'],
chainId: chain.mainnet2.id,
}),
- ).resolves.toMatchInlineSnapshot('4n')
+ ).resolves.toMatchInlineSnapshot('10n')
})
test('parameters: deployless read (bytecode)', async () => {
diff --git a/packages/core/src/actions/readContract.ts b/packages/core/src/actions/readContract.ts
index e01e74e9f2..9fce8fd899 100644
--- a/packages/core/src/actions/readContract.ts
+++ b/packages/core/src/actions/readContract.ts
@@ -1,5 +1,4 @@
-import type { Abi } from 'viem'
-import type { ContractFunctionArgs, ContractFunctionName } from 'viem'
+import type { Abi, ContractFunctionArgs, ContractFunctionName } from 'viem'
import {
type ReadContractErrorType as viem_ReadContractErrorType,
type ReadContractParameters as viem_ReadContractParameters,
@@ -46,7 +45,7 @@ export function readContract<
config extends Config,
const abi extends Abi | readonly unknown[],
functionName extends ContractFunctionName,
- args extends ContractFunctionArgs,
+ const args extends ContractFunctionArgs,
>(
config: config,
parameters: ReadContractParameters,
diff --git a/packages/core/src/actions/readContracts.test.ts b/packages/core/src/actions/readContracts.test.ts
index c5e85ff3a8..b7da42c0b6 100644
--- a/packages/core/src/actions/readContracts.test.ts
+++ b/packages/core/src/actions/readContracts.test.ts
@@ -84,7 +84,7 @@ test('default', async () => {
`)
})
-test.skip('falls back to readContract if multicall is not available', async () => {
+test('falls back to readContract if multicall is not available', async () => {
const spy = vi.spyOn(readContract, 'readContract')
const config = createConfig({
chains: [mainnet, { ...mainnet2, contracts: { multicall3: undefined } }],
@@ -158,7 +158,7 @@ test.skip('falls back to readContract if multicall is not available', async () =
`)
})
-test.skip('multichain', async () => {
+test('multichain', async () => {
const config = createConfig({
chains: [mainnet, mainnet2, optimism],
transports: {
@@ -207,28 +207,28 @@ test.skip('multichain', async () => {
args: ['0xA0Cf798816D4b9b9866b5330EEa46a18382f251e', 0n],
},
] as const
- const optimismContracts = [
- {
- abi: abi.erc20,
- address: address.optimism.usdc,
- chainId: optimism.id,
- functionName: 'symbol',
- },
- {
- abi: abi.erc20,
- address: address.optimism.usdc,
- chainId: optimism.id,
- functionName: 'balanceOf',
- args: ['0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC'],
- },
- ] as const
+ // const optimismContracts = [
+ // {
+ // abi: abi.erc20,
+ // address: address.optimism.usdc,
+ // chainId: optimism.id,
+ // functionName: 'symbol',
+ // },
+ // {
+ // abi: abi.erc20,
+ // address: address.optimism.usdc,
+ // chainId: optimism.id,
+ // functionName: 'balanceOf',
+ // args: ['0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC'],
+ // },
+ // ] as const
const results = await readContracts(config, {
contracts: [
mainnetContracts[0]!,
- optimismContracts[0]!,
+ // optimismContracts[0]!,
mainnetContracts[1]!,
mainnet2Contracts[0]!,
- optimismContracts[1]!,
+ // optimismContracts[1]!,
mainnet2Contracts[1]!,
mainnetContracts[2]!,
],
@@ -236,10 +236,10 @@ test.skip('multichain', async () => {
expectTypeOf(results).toEqualTypeOf<
[
MulticallResponse,
- MulticallResponse,
+ // MulticallResponse,
MulticallResponse,
MulticallResponse,
- MulticallResponse,
+ // MulticallResponse,
MulticallResponse,
MulticallResponse,
]
@@ -263,10 +263,6 @@ test.skip('multichain', async () => {
"result": 2n,
"status": "success",
},
- {
- "result": "USDC",
- "status": "success",
- },
{
"result": 1n,
"status": "success",
@@ -275,10 +271,6 @@ test.skip('multichain', async () => {
"result": false,
"status": "success",
},
- {
- "result": 10959340n,
- "status": "success",
- },
{
"result": 370395n,
"status": "success",
@@ -289,11 +281,11 @@ test.skip('multichain', async () => {
},
]
`)
-})
+}, 60_000)
-test('multi-chain: falls back to readContract if multicall is not available', async () => {
+test('multichain: falls back to readContract if multicall is not available', async () => {
const config = createConfig({
- chains: [mainnet, { ...optimism, contracts: { multicall3: undefined } }],
+ chains: [{ ...mainnet, contracts: { multicall3: undefined } }, optimism],
transports: {
[mainnet.id]: http(),
[optimism.id]: http(),
@@ -317,39 +309,39 @@ test('multi-chain: falls back to readContract if multicall is not available', as
args: ['0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC'],
},
] as const
- const optimismContracts = [
- {
- abi: abi.erc20,
- address: address.optimism.usdc,
- chainId: optimism.id,
- functionName: 'symbol',
- },
- {
- abi: abi.erc20,
- address: address.optimism.usdc,
- chainId: optimism.id,
- functionName: 'balanceOf',
- args: ['0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC'],
- },
- ] as const
+ // const optimismContracts = [
+ // {
+ // abi: abi.erc20,
+ // address: address.optimism.usdc,
+ // chainId: optimism.id,
+ // functionName: 'symbol',
+ // },
+ // {
+ // abi: abi.erc20,
+ // address: address.optimism.usdc,
+ // chainId: optimism.id,
+ // functionName: 'balanceOf',
+ // args: ['0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC'],
+ // },
+ // ] as const
const results = await readContracts(config, {
- contracts: [...mainnetContracts, ...optimismContracts],
+ contracts: [...mainnetContracts /** ...optimismContracts */],
})
expectTypeOf(results).toEqualTypeOf<
[
MulticallResponse,
MulticallResponse,
- MulticallResponse,
- MulticallResponse,
+ // MulticallResponse,
+ // MulticallResponse,
]
>()
for (const contract of mainnetContracts) {
expect(spy).toBeCalledWith(config, { ...contract, chainId: mainnet.id })
}
- for (const contract of optimismContracts) {
- expect(spy).toBeCalledWith(config, { ...contract, chainId: optimism.id })
- }
+ // for (const contract of optimismContracts) {
+ // expect(spy).toBeCalledWith(config, { ...contract, chainId: optimism.id })
+ // }
expect(results).toMatchInlineSnapshot(`
[
{
@@ -360,17 +352,9 @@ test('multi-chain: falls back to readContract if multicall is not available', as
"result": 1n,
"status": "success",
},
- {
- "result": "USDC",
- "status": "success",
- },
- {
- "result": 10959340n,
- "status": "success",
- },
]
`)
-})
+}, 15_000)
test('throws if allowFailure=false & a contract method fails', async () => {
await expect(
@@ -397,7 +381,7 @@ test('throws if allowFailure=false & a contract method fails', async () => {
args: (0xA0Cf798816D4b9b9866b5330EEa46a18382f251e, 69420)
Docs: https://viem.sh/docs/contract/readContract
- Version: viem@2.23.12]
+ Version: viem@2.44.0]
`,
)
})
@@ -450,7 +434,7 @@ test('allowFailure=true & a contract method fails', async () => {
args: (0xA0Cf798816D4b9b9866b5330EEa46a18382f251e, 69420)
Docs: https://viem.sh/docs/contract/readContract
- Version: viem@2.23.12],
+ Version: viem@2.44.0],
"result": undefined,
"status": "failure",
},
@@ -464,7 +448,7 @@ test('allowFailure=true & a contract method fails', async () => {
args: (0xA0Cf798816D4b9b9866b5330EEa46a18382f251e, 69421)
Docs: https://viem.sh/docs/contract/readContract
- Version: viem@2.23.12],
+ Version: viem@2.44.0],
"result": undefined,
"status": "failure",
},
@@ -502,7 +486,7 @@ test('throws if allowFailure=false & encoding contract function data fails', asy
args: (1e+31)
Docs: https://viem.sh/docs/contract/readContract
- Version: viem@2.23.12]
+ Version: viem@2.44.0]
`,
)
})
@@ -561,7 +545,7 @@ test('allowFailure=true & encoding contract function data fails', async () => {
args: (1e+31)
Docs: https://viem.sh/docs/contract/readContract
- Version: viem@2.23.12],
+ Version: viem@2.44.0],
"result": undefined,
"status": "failure",
},
@@ -579,7 +563,7 @@ test('allowFailure=true & encoding contract function data fails', async () => {
args: (1e+31)
Docs: https://viem.sh/docs/contract/readContract
- Version: viem@2.23.12],
+ Version: viem@2.44.0],
"result": undefined,
"status": "failure",
},
@@ -617,7 +601,7 @@ test('should throw if allowFailure=false & a contract has no response', async ()
args: (0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC)
Docs: https://viem.sh/docs/contract/readContract
- Version: viem@2.23.12]
+ Version: viem@2.44.0]
`,
)
})
@@ -669,7 +653,7 @@ test('allowFailure=true & a contract has no response', async () => {
args: (0xa5cc3c03994DB5b0d9A5eEdD10CabaB0813678AC)
Docs: https://viem.sh/docs/contract/readContract
- Version: viem@2.23.12],
+ Version: viem@2.44.0],
"result": undefined,
"status": "failure",
},
diff --git a/packages/core/src/actions/readContracts.ts b/packages/core/src/actions/readContracts.ts
index 45f2a0cef4..4f433df513 100644
--- a/packages/core/src/actions/readContracts.ts
+++ b/packages/core/src/actions/readContracts.ts
@@ -59,7 +59,7 @@ export async function readContracts<
allowFailure,
blockNumber,
blockTag,
- chainId: Number.parseInt(chainId),
+ chainId: Number.parseInt(chainId, 10),
contracts: contracts.map(({ contract }) => contract),
}),
)
diff --git a/packages/core/src/experimental/actions/sendCalls.test.ts b/packages/core/src/actions/sendCalls.test.ts
similarity index 89%
rename from packages/core/src/experimental/actions/sendCalls.test.ts
rename to packages/core/src/actions/sendCalls.test.ts
index 34e0db028e..54dd2b9d7f 100644
--- a/packages/core/src/experimental/actions/sendCalls.test.ts
+++ b/packages/core/src/actions/sendCalls.test.ts
@@ -2,8 +2,8 @@ import { accounts, config } from '@wagmi/test'
import { parseEther } from 'viem'
import { expect, test } from 'vitest'
-import { connect } from '../../actions/connect.js'
-import { disconnect } from '../../actions/disconnect.js'
+import { connect } from './connect.js'
+import { disconnect } from './disconnect.js'
import { sendCalls } from './sendCalls.js'
const connector = config.connectors[0]!
@@ -29,7 +29,11 @@ test('default', async () => {
],
}),
).resolves.toMatchInlineSnapshot(
- `"0x5dedb5a4ff8968db37459b52b83cbdc92b01c9c709c9cff26e345ef5cf27f92e"`,
+ `
+ {
+ "id": "0xb24b52a86aa2b0bae6f1e44868c3a13d2572e766a1f6364afd93d1757839b8a1",
+ }
+ `,
)
await disconnect(config, { connector })
})
@@ -80,7 +84,11 @@ test('behavior: nullish account (account filled by wallet)', async () => {
],
}),
).resolves.toMatchInlineSnapshot(
- `"0x035b56a56a5b2fea10e194bae4c846b415de48a8288c7eb704ba7880edcc29a0"`,
+ `
+ {
+ "id": "0x0a8b20024fae14dd9e854accfc8496b9d18c291206647c842a96a954133401f3",
+ }
+ `,
)
})
diff --git a/packages/core/src/experimental/actions/sendCalls.ts b/packages/core/src/actions/sendCalls.ts
similarity index 67%
rename from packages/core/src/experimental/actions/sendCalls.ts
rename to packages/core/src/actions/sendCalls.ts
index cabce545d9..456eb96532 100644
--- a/packages/core/src/experimental/actions/sendCalls.ts
+++ b/packages/core/src/actions/sendCalls.ts
@@ -4,30 +4,35 @@ import {
type SendCallsParameters as viem_SendCallsParameters,
type SendCallsReturnType as viem_SendCallsReturnType,
sendCalls as viem_sendCalls,
-} from 'viem/experimental'
+} from 'viem/actions'
-import {
- type GetConnectorClientErrorType,
- getConnectorClient,
-} from '../../actions/getConnectorClient.js'
-import type { Config } from '../../createConfig.js'
-import type { BaseErrorType, ErrorType } from '../../errors/base.js'
-import type { SelectChains } from '../../types/chain.js'
+import type { Config } from '../createConfig.js'
+import type { BaseErrorType, ErrorType } from '../errors/base.js'
+import type { SelectChains } from '../types/chain.js'
import type {
ChainIdParameter,
ConnectorParameter,
-} from '../../types/properties.js'
-import type { Compute } from '../../types/utils.js'
+} from '../types/properties.js'
+import type { Compute } from '../types/utils.js'
+import { getAction } from '../utils/getAction.js'
+import {
+ type GetConnectorClientErrorType,
+ getConnectorClient,
+} from './getConnectorClient.js'
export type SendCallsParameters<
config extends Config = Config,
chainId extends
config['chains'][number]['id'] = config['chains'][number]['id'],
+ calls extends readonly unknown[] = readonly unknown[],
///
chains extends readonly Chain[] = SelectChains,
> = {
[key in keyof chains]: Compute<
- Omit, 'chain'> &
+ Omit<
+ viem_SendCallsParameters,
+ 'chain'
+ > &
ChainIdParameter &
ConnectorParameter
>
@@ -46,21 +51,24 @@ export type SendCallsErrorType =
/** https://wagmi.sh/core/api/actions/sendCalls */
export async function sendCalls<
+ const calls extends readonly unknown[],
config extends Config,
chainId extends config['chains'][number]['id'],
>(
config: config,
- parameters: SendCallsParameters,
+ parameters: SendCallsParameters,
): Promise {
const { account, chainId, connector, calls, ...rest } = parameters
const client = await getConnectorClient(config, {
account,
+ assertChainId: false,
chainId,
connector,
})
- return viem_sendCalls(client, {
+ const action = getAction(client, viem_sendCalls, 'sendCalls')
+ return action({
...(rest as any),
...(typeof account !== 'undefined' ? { account } : {}),
calls,
diff --git a/packages/core/src/actions/sendCallsSync.test.ts b/packages/core/src/actions/sendCallsSync.test.ts
new file mode 100644
index 0000000000..9ff1c727d0
--- /dev/null
+++ b/packages/core/src/actions/sendCallsSync.test.ts
@@ -0,0 +1,95 @@
+import { accounts, config, testClient, wait } from '@wagmi/test'
+import { parseEther } from 'viem'
+import { beforeEach, expect, test } from 'vitest'
+
+import { connect } from './connect.js'
+import { disconnect } from './disconnect.js'
+import { sendCallsSync } from './sendCallsSync.js'
+
+const connector = config.connectors[0]!
+
+beforeEach(async () => {
+ await disconnect(config).catch(() => {})
+})
+
+test('default', async () => {
+ await connect(config, { connector })
+ const [status] = await Promise.all([
+ sendCallsSync(config, {
+ calls: [
+ {
+ data: '0xdeadbeef',
+ to: accounts[1],
+ value: parseEther('1'),
+ },
+ {
+ to: accounts[2],
+ value: parseEther('2'),
+ },
+ {
+ to: accounts[3],
+ value: parseEther('3'),
+ },
+ ],
+ }),
+ (async () => {
+ await wait(1000)
+ await testClient.mainnet.mine({ blocks: 1 })
+ })(),
+ ])
+ expect(status).toBeDefined()
+ await disconnect(config, { connector })
+})
+
+test('behavior: not connected', async () => {
+ await expect(
+ sendCallsSync(config, {
+ calls: [
+ {
+ to: accounts[1],
+ value: parseEther('1'),
+ },
+ {
+ to: accounts[2],
+ value: parseEther('2'),
+ },
+ {
+ to: accounts[3],
+ value: parseEther('3'),
+ },
+ ],
+ }),
+ ).rejects.toThrowErrorMatchingInlineSnapshot(`
+ [ConnectorNotConnectedError: Connector not connected.
+
+ Version: @wagmi/core@x.y.z]
+ `)
+})
+
+test('behavior: account does not exist on connector', async () => {
+ await connect(config, { connector })
+ await expect(
+ sendCallsSync(config, {
+ account: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
+ calls: [
+ {
+ to: accounts[1],
+ value: parseEther('1'),
+ },
+ {
+ to: accounts[2],
+ value: parseEther('2'),
+ },
+ {
+ to: accounts[3],
+ value: parseEther('3'),
+ },
+ ],
+ }),
+ ).rejects.toThrowErrorMatchingInlineSnapshot(`
+ [ConnectorAccountNotFoundError: Account "0xA0Cf798816D4b9b9866b5330EEa46a18382f251e" not found for connector "Mock Connector".
+
+ Version: @wagmi/core@x.y.z]
+ `)
+ await disconnect(config, { connector })
+})
diff --git a/packages/core/src/actions/sendCallsSync.ts b/packages/core/src/actions/sendCallsSync.ts
new file mode 100644
index 0000000000..6ec708c8fb
--- /dev/null
+++ b/packages/core/src/actions/sendCallsSync.ts
@@ -0,0 +1,77 @@
+import type { Account, Chain } from 'viem'
+import {
+ type SendCallsSyncErrorType as viem_SendCallsSyncErrorType,
+ type SendCallsSyncParameters as viem_SendCallsSyncParameters,
+ type SendCallsSyncReturnType as viem_SendCallsSyncReturnType,
+ sendCallsSync as viem_sendCallsSync,
+} from 'viem/actions'
+
+import type { Config } from '../createConfig.js'
+import type { BaseErrorType, ErrorType } from '../errors/base.js'
+import type { SelectChains } from '../types/chain.js'
+import type {
+ ChainIdParameter,
+ ConnectorParameter,
+} from '../types/properties.js'
+import type { Compute } from '../types/utils.js'
+import { getAction } from '../utils/getAction.js'
+import {
+ type GetConnectorClientErrorType,
+ getConnectorClient,
+} from './getConnectorClient.js'
+
+export type SendCallsSyncParameters<
+ config extends Config = Config,
+ chainId extends
+ config['chains'][number]['id'] = config['chains'][number]['id'],
+ calls extends readonly unknown[] = readonly unknown[],
+ ///
+ chains extends readonly Chain[] = SelectChains,
+> = {
+ [key in keyof chains]: Compute<
+ Omit<
+ viem_SendCallsSyncParameters,
+ 'chain'
+ > &
+ ChainIdParameter &
+ ConnectorParameter
+ >
+}[number]
+
+export type SendCallsSyncReturnType = viem_SendCallsSyncReturnType
+
+export type SendCallsSyncErrorType =
+ // getConnectorClient()
+ | GetConnectorClientErrorType
+ // base
+ | BaseErrorType
+ | ErrorType
+ // viem
+ | viem_SendCallsSyncErrorType
+
+/** https://wagmi.sh/core/api/actions/sendCallsSync */
+export async function sendCallsSync<
+ const calls extends readonly unknown[],
+ config extends Config,
+ chainId extends config['chains'][number]['id'],
+>(
+ config: config,
+ parameters: SendCallsSyncParameters,
+): Promise {
+ const { account, chainId, connector, calls, ...rest } = parameters
+
+ const client = await getConnectorClient(config, {
+ account,
+ assertChainId: false,
+ chainId,
+ connector,
+ })
+
+ const action = getAction(client, viem_sendCallsSync, 'sendCallsSync')
+ return action({
+ ...(rest as any),
+ ...(typeof account !== 'undefined' ? { account } : {}),
+ calls,
+ chain: chainId ? { id: chainId } : undefined,
+ })
+}
diff --git a/packages/core/src/actions/sendTransaction.test.ts b/packages/core/src/actions/sendTransaction.test.ts
index 627d29b8fd..da1bf9eded 100644
--- a/packages/core/src/actions/sendTransaction.test.ts
+++ b/packages/core/src/actions/sendTransaction.test.ts
@@ -1,8 +1,7 @@
import { config, privateKey, transactionHashRegex } from '@wagmi/test'
import { parseEther } from 'viem'
-import { beforeEach, expect, test } from 'vitest'
-
import { privateKeyToAccount } from 'viem/accounts'
+import { beforeEach, expect, test } from 'vitest'
import { connect } from './connect.js'
import { disconnect } from './disconnect.js'
import { sendTransaction } from './sendTransaction.js'
@@ -83,12 +82,12 @@ test('behavior: value exceeds balance', async () => {
- \`value\` is the amount of ether to send to the recipient.
Request Arguments:
- from: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
+ from: 0x95132632579b073D12a6673e18Ab05777a6B86f8
to: 0xd2135CfB216b74109775236E36d4b433F1DF507B
value: 99999 ETH
Details: Insufficient funds for gas * price + value
- Version: viem@2.23.12]
+ Version: viem@2.44.0]
`)
await disconnect(config, { connector })
})
diff --git a/packages/core/src/actions/sendTransaction.ts b/packages/core/src/actions/sendTransaction.ts
index 76bc3a420a..56f6d43e4f 100644
--- a/packages/core/src/actions/sendTransaction.ts
+++ b/packages/core/src/actions/sendTransaction.ts
@@ -70,6 +70,7 @@ export async function sendTransaction<
else
client = await getConnectorClient(config, {
account: account ?? undefined,
+ assertChainId: false,
chainId,
connector,
})
diff --git a/packages/core/src/actions/sendTransactionSync.test.ts b/packages/core/src/actions/sendTransactionSync.test.ts
new file mode 100644
index 0000000000..ab40f10165
--- /dev/null
+++ b/packages/core/src/actions/sendTransactionSync.test.ts
@@ -0,0 +1,97 @@
+import { config, testClient, wait } from '@wagmi/test'
+import { parseEther } from 'viem'
+import { beforeEach, expect, test } from 'vitest'
+import { connect } from './connect.js'
+import { disconnect } from './disconnect.js'
+import { sendTransactionSync } from './sendTransactionSync.js'
+
+const connector = config.connectors[0]!
+
+beforeEach(async () => {
+ if (config.state.current === connector.uid)
+ await disconnect(config, { connector })
+})
+
+test('default', async () => {
+ const result = await connect(config, { connector })
+ config.state.connections.set(connector.uid, {
+ ...result,
+ // Switch up the current account because the default one is running out of funds somewhere
+ accounts: result.accounts.slice(1) as unknown as typeof result.accounts,
+ connector,
+ })
+ const [receipt] = await Promise.all([
+ sendTransactionSync(config, {
+ to: '0xd2135CfB216b74109775236E36d4b433F1DF507B',
+ value: parseEther('0.0001'),
+ }),
+ (async () => {
+ await wait(1000)
+ await testClient.mainnet.mine({ blocks: 1 })
+ })(),
+ ])
+ expect(receipt).toBeDefined()
+ await disconnect(config, { connector })
+})
+
+test('behavior: connector not connected', async () => {
+ await connect(config, { connector })
+ await expect(
+ sendTransactionSync(config, {
+ connector: config.connectors[1],
+ to: '0xd2135CfB216b74109775236E36d4b433F1DF507B',
+ value: parseEther('0.0001'),
+ }),
+ ).rejects.toThrowErrorMatchingInlineSnapshot(`
+ [ConnectorNotConnectedError: Connector not connected.
+
+ Version: @wagmi/core@x.y.z]
+ `)
+ await disconnect(config, { connector })
+})
+
+test('behavior: account does not exist on connector', async () => {
+ await connect(config, { connector })
+ await expect(
+ sendTransactionSync(config, {
+ account: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
+ to: '0xd2135CfB216b74109775236E36d4b433F1DF507B',
+ value: parseEther('0.0001'),
+ }),
+ ).rejects.toThrowErrorMatchingInlineSnapshot(`
+ [ConnectorAccountNotFoundError: Account "0xA0Cf798816D4b9b9866b5330EEa46a18382f251e" not found for connector "Mock Connector".
+
+ Version: @wagmi/core@x.y.z]
+ `)
+ await disconnect(config, { connector })
+})
+
+test('behavior: value exceeds balance', async () => {
+ await connect(config, { connector })
+ await expect(
+ sendTransactionSync(config, {
+ to: '0xd2135CfB216b74109775236E36d4b433F1DF507B',
+ value: parseEther('99999'),
+ }),
+ ).rejects.toThrowErrorMatchingInlineSnapshot(`
+ [TransactionExecutionError: The total cost (gas * gas fee + value) of executing this transaction exceeds the balance of the account.
+
+ This error could arise when the account does not have enough funds to:
+ - pay for the total gas fee,
+ - pay for the value to send.
+
+ The cost of the transaction is calculated as \`gas * gas fee + value\`, where:
+ - \`gas\` is the amount of gas needed for transaction to execute,
+ - \`gas fee\` is the gas fee,
+ - \`value\` is the amount of ether to send to the recipient.
+
+ Request Arguments:
+ from: 0x95132632579b073D12a6673e18Ab05777a6B86f8
+ to: 0xd2135CfB216b74109775236E36d4b433F1DF507B
+ value: 99999 ETH
+
+ Details: Insufficient funds for gas * price + value
+ Version: viem@2.44.0]
+ `)
+ await disconnect(config, { connector })
+})
diff --git a/packages/core/src/actions/sendTransactionSync.ts b/packages/core/src/actions/sendTransactionSync.ts
new file mode 100644
index 0000000000..4f9c648083
--- /dev/null
+++ b/packages/core/src/actions/sendTransactionSync.ts
@@ -0,0 +1,91 @@
+import type {
+ Account,
+ Chain,
+ Client,
+ TransactionRequest,
+ SendTransactionSyncErrorType as viem_SendTransactionSyncErrorType,
+ SendTransactionSyncParameters as viem_SendTransactionSyncParameters,
+ SendTransactionSyncReturnType as viem_SendTransactionSyncReturnType,
+} from 'viem'
+import { sendTransactionSync as viem_sendTransactionSync } from 'viem/actions'
+
+import type { Config } from '../createConfig.js'
+import type { BaseErrorType, ErrorType } from '../errors/base.js'
+import type { SelectChains } from '../types/chain.js'
+import type {
+ ChainIdParameter,
+ ConnectorParameter,
+} from '../types/properties.js'
+import type { Compute } from '../types/utils.js'
+import { getAction } from '../utils/getAction.js'
+import {
+ type GetConnectorClientErrorType,
+ getConnectorClient,
+} from './getConnectorClient.js'
+
+export type SendTransactionSyncParameters<
+ config extends Config = Config,
+ chainId extends
+ config['chains'][number]['id'] = config['chains'][number]['id'],
+ ///
+ chains extends readonly Chain[] = SelectChains,
+> = {
+ [key in keyof chains]: Compute<
+ Omit<
+ viem_SendTransactionSyncParameters,
+ 'chain' | 'gas'
+ > &
+ ChainIdParameter &
+ ConnectorParameter
+ >
+}[number] & {
+ /** Gas provided for transaction execution. */
+ gas?: TransactionRequest['gas'] | null
+}
+
+export type SendTransactionSyncReturnType = viem_SendTransactionSyncReturnType
+
+export type SendTransactionSyncErrorType =
+ // getConnectorClient()
+ | GetConnectorClientErrorType
+ // base
+ | BaseErrorType
+ | ErrorType
+ // viem
+ | viem_SendTransactionSyncErrorType
+
+/** https://wagmi.sh/core/api/actions/sendTransactionSync */
+export async function sendTransactionSync<
+ config extends Config,
+ chainId extends config['chains'][number]['id'],
+>(
+ config: config,
+ parameters: SendTransactionSyncParameters,
+): Promise {
+ const { account, chainId, connector, ...rest } = parameters
+
+ let client: Client
+ if (typeof account === 'object' && account?.type === 'local')
+ client = config.getClient({ chainId })
+ else
+ client = await getConnectorClient(config, {
+ account: account ?? undefined,
+ assertChainId: false,
+ chainId,
+ connector,
+ })
+
+ const action = getAction(
+ client,
+ viem_sendTransactionSync,
+ 'sendTransactionSync',
+ )
+ const hash = await action({
+ ...(rest as any),
+ ...(account ? { account } : {}),
+ chain: chainId ? { id: chainId } : null,
+ gas: rest.gas ?? undefined,
+ })
+
+ return hash
+}
diff --git a/packages/core/src/experimental/actions/showCallsStatus.test.ts b/packages/core/src/actions/showCallsStatus.test.ts
similarity index 83%
rename from packages/core/src/experimental/actions/showCallsStatus.test.ts
rename to packages/core/src/actions/showCallsStatus.test.ts
index d397886e05..5822242382 100644
--- a/packages/core/src/experimental/actions/showCallsStatus.test.ts
+++ b/packages/core/src/actions/showCallsStatus.test.ts
@@ -2,8 +2,8 @@ import { accounts, config, testClient } from '@wagmi/test'
import { parseEther } from 'viem'
import { test } from 'vitest'
-import { connect } from '../../actions/connect.js'
-import { disconnect } from '../../actions/disconnect.js'
+import { connect } from './connect.js'
+import { disconnect } from './disconnect.js'
import { sendCalls } from './sendCalls.js'
import { showCallsStatus } from './showCallsStatus.js'
@@ -11,7 +11,7 @@ const connector = config.connectors[0]!
test('default', async () => {
await connect(config, { connector })
- const id = await sendCalls(config, {
+ const { id } = await sendCalls(config, {
calls: [
{
data: '0xdeadbeef',
diff --git a/packages/core/src/experimental/actions/showCallsStatus.ts b/packages/core/src/actions/showCallsStatus.ts
similarity index 79%
rename from packages/core/src/experimental/actions/showCallsStatus.ts
rename to packages/core/src/actions/showCallsStatus.ts
index a170ffe163..e3c6ae067d 100644
--- a/packages/core/src/experimental/actions/showCallsStatus.ts
+++ b/packages/core/src/actions/showCallsStatus.ts
@@ -3,11 +3,11 @@ import {
type ShowCallsStatusParameters as viem_ShowCallsStatusParameters,
type ShowCallsStatusReturnType as viem_ShowCallsStatusReturnType,
showCallsStatus as viem_showCallsStatus,
-} from 'viem/experimental'
+} from 'viem/actions'
-import { getConnectorClient } from '../../actions/getConnectorClient.js'
-import type { Config } from '../../createConfig.js'
-import type { ConnectorParameter } from '../../types/properties.js'
+import type { Config } from '../createConfig.js'
+import type { ConnectorParameter } from '../types/properties.js'
+import { getConnectorClient } from './getConnectorClient.js'
export type ShowCallsStatusParameters = viem_ShowCallsStatusParameters &
ConnectorParameter
diff --git a/packages/core/src/actions/signMessage.test.ts b/packages/core/src/actions/signMessage.test.ts
index 62e0abfa3d..cc319dc72f 100644
--- a/packages/core/src/actions/signMessage.test.ts
+++ b/packages/core/src/actions/signMessage.test.ts
@@ -6,7 +6,7 @@ import { expect, test } from 'vitest'
import { mock } from '../connectors/mock.js'
import { connect } from './connect.js'
import { disconnect } from './disconnect.js'
-import { getAccount } from './getAccount.js'
+import { getConnection } from './getConnection.js'
import { signMessage } from './signMessage.js'
const connector = config.connectors[0]!
@@ -19,7 +19,7 @@ test('default', async () => {
message: 'foo bar baz',
signature,
}),
- ).resolves.toEqual(getAccount(config).address)
+ ).resolves.toEqual(getConnection(config).address)
await disconnect(config, { connector })
})
@@ -51,7 +51,7 @@ test('behavior: user rejected request', async () => {
[UserRejectedRequestError: User rejected the request.
Details: Failed to sign message.
- Version: viem@2.23.12]
+ Version: viem@2.44.0]
`)
await disconnect(config, { connector: connector_ })
})
diff --git a/packages/core/src/actions/signTypedData.test.ts b/packages/core/src/actions/signTypedData.test.ts
index 68a0eca25a..199d1a90eb 100644
--- a/packages/core/src/actions/signTypedData.test.ts
+++ b/packages/core/src/actions/signTypedData.test.ts
@@ -1,12 +1,11 @@
import { accounts, config, privateKey, typedData } from '@wagmi/test'
import { recoverTypedDataAddress } from 'viem'
-import { expect, test } from 'vitest'
-
import { privateKeyToAccount } from 'viem/accounts'
+import { expect, test } from 'vitest'
import { mock } from '../connectors/mock.js'
import { connect } from './connect.js'
import { disconnect } from './disconnect.js'
-import { getAccount } from './getAccount.js'
+import { getConnection } from './getConnection.js'
import { signTypedData } from './signTypedData.js'
const connector = config.connectors[0]!
@@ -25,7 +24,7 @@ test('default', async () => {
message: typedData.basic.message,
signature,
}),
- ).resolves.toBe(getAccount(config).address)
+ ).resolves.toBe(getConnection(config).address)
await disconnect(config, { connector })
})
@@ -47,7 +46,7 @@ test('behavior: user rejected request', async () => {
[UserRejectedRequestError: User rejected the request.
Details: Failed to sign typed data.
- Version: viem@2.23.12]
+ Version: viem@2.44.0]
`)
await disconnect(config, { connector: connector_ })
})
diff --git a/packages/core/src/actions/simulateContract.test-d.ts b/packages/core/src/actions/simulateContract.test-d.ts
index 3f893ff8f8..bb274fdec3 100644
--- a/packages/core/src/actions/simulateContract.test-d.ts
+++ b/packages/core/src/actions/simulateContract.test-d.ts
@@ -1,7 +1,7 @@
import { abi, config } from '@wagmi/test'
-import { http, type Address } from 'viem'
+import { type Address, http } from 'viem'
import { celo, mainnet } from 'viem/chains'
-import { expectTypeOf, test } from 'vitest'
+import { assertType, expectTypeOf, test } from 'vitest'
import { createConfig } from '../createConfig.js'
import {
@@ -158,3 +158,39 @@ test('SimulateContractReturnType', () => {
}
}>()
})
+
+test('overloads', async () => {
+ const result1 = await simulateContract(config, {
+ address: '0x',
+ abi: abi.writeOverloads,
+ functionName: 'foo',
+ })
+ assertType(result1.result)
+
+ const result2 = await simulateContract(config, {
+ address: '0x',
+ abi: abi.writeOverloads,
+ functionName: 'foo',
+ args: [],
+ })
+ assertType(result2.result)
+
+ const result3 = await simulateContract(config, {
+ address: '0x',
+ abi: abi.writeOverloads,
+ functionName: 'foo',
+ args: ['0x'],
+ })
+ assertType(result3.result)
+
+ const result4 = await simulateContract(config, {
+ address: '0x',
+ abi: abi.writeOverloads,
+ functionName: 'foo',
+ args: ['0x', '0x'],
+ })
+ assertType<{
+ foo: `0x${string}`
+ bar: `0x${string}`
+ }>(result4.result)
+})
diff --git a/packages/core/src/actions/simulateContract.test.ts b/packages/core/src/actions/simulateContract.test.ts
index a52cbd5568..35bd17423b 100644
--- a/packages/core/src/actions/simulateContract.test.ts
+++ b/packages/core/src/actions/simulateContract.test.ts
@@ -29,7 +29,7 @@ test('parameters: account', async () => {
},
],
"account": {
- "address": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
+ "address": "0x95132632579b073D12a6673e18Ab05777a6B86f8",
"type": "json-rpc",
},
"address": "0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2",
@@ -67,7 +67,7 @@ test('parameters: connector', async () => {
},
],
"account": {
- "address": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
+ "address": "0x95132632579b073D12a6673e18Ab05777a6B86f8",
"type": "json-rpc",
},
"address": "0xFBA3912Ca04dd458c843e2EE08967fC04f3579c2",
diff --git a/packages/core/src/actions/simulateContract.ts b/packages/core/src/actions/simulateContract.ts
index e5fe5655ff..7cd5598f95 100644
--- a/packages/core/src/actions/simulateContract.ts
+++ b/packages/core/src/actions/simulateContract.ts
@@ -20,12 +20,7 @@ import type {
ChainIdParameter,
ConnectorParameter,
} from '../types/properties.js'
-import type {
- Compute,
- PartialBy,
- UnionCompute,
- UnionStrictOmit,
-} from '../types/utils.js'
+import type { Compute, PartialBy, UnionCompute } from '../types/utils.js'
import { getAction } from '../utils/getAction.js'
import {
type GetConnectorClientErrorType,
@@ -51,19 +46,16 @@ export type SimulateContractParameters<
chains extends readonly Chain[] = SelectChains,
> = {
[key in keyof chains]: UnionCompute<
- UnionStrictOmit<
- viem_SimulateContractParameters<
- abi,
- functionName,
- args,
- chains[key],
- chains[key],
- Account | Address
- >,
- 'chain'
+ // TODO: Should use `UnionStrictOmit<..., 'chain'>` on `viem_SimulateContractParameters` result instead, but it knocks out inference for overloads
+ viem_SimulateContractParameters<
+ abi,
+ functionName,
+ args,
+ chains[key],
+ chains[key],
+ Account | Address
>
- > &
- ChainIdParameter &
+ > & { chain?: never } & ChainIdParameter &
ConnectorParameter
}[number]
@@ -117,7 +109,7 @@ export async function simulateContract<
config extends Config,
const abi extends Abi | readonly unknown[],
functionName extends ContractFunctionName,
- args extends ContractFunctionArgs<
+ const args extends ContractFunctionArgs<
abi,
'nonpayable' | 'payable',
functionName
@@ -142,6 +134,7 @@ export async function simulateContract<
if (parameters.account) account = parameters.account
else {
const connectorClient = await getConnectorClient(config, {
+ assertChainId: false,
chainId,
connector,
})
diff --git a/packages/core/src/actions/switchChain.test.ts b/packages/core/src/actions/switchChain.test.ts
index 807b443a94..8d7b438a5e 100644
--- a/packages/core/src/actions/switchChain.test.ts
+++ b/packages/core/src/actions/switchChain.test.ts
@@ -4,7 +4,7 @@ import { expect, test } from 'vitest'
import { mock } from '../connectors/mock.js'
import { connect } from './connect.js'
import { disconnect } from './disconnect.js'
-import { getAccount } from './getAccount.js'
+import { getConnection } from './getConnection.js'
import { switchChain } from './switchChain.js'
const connector = config.connectors[0]!
@@ -12,17 +12,17 @@ const connector = config.connectors[0]!
test('default', async () => {
await connect(config, { connector })
- const chainId1 = getAccount(config).chainId
+ const chainId1 = getConnection(config).chainId
await switchChain(config, { chainId: chain.mainnet2.id })
- const chainId2 = getAccount(config).chainId
+ const chainId2 = getConnection(config).chainId
expect(chainId2).toBeDefined()
expect(chainId1).not.toBe(chainId2)
await switchChain(config, { chainId: chain.mainnet.id })
- const chainId3 = getAccount(config).chainId
+ const chainId3 = getConnection(config).chainId
expect(chainId3).toBeDefined()
expect(chainId1).toBe(chainId3)
@@ -43,7 +43,7 @@ test('behavior: user rejected request', async () => {
[UserRejectedRequestError: User rejected the request.
Details: Failed to switch chain.
- Version: viem@2.23.12]
+ Version: viem@2.44.0]
`)
await disconnect(config, { connector: connector_ })
})
diff --git a/packages/core/src/actions/switchAccount.test.ts b/packages/core/src/actions/switchConnection.test.ts
similarity index 62%
rename from packages/core/src/actions/switchAccount.test.ts
rename to packages/core/src/actions/switchConnection.test.ts
index 97d0e84b37..733b582e39 100644
--- a/packages/core/src/actions/switchAccount.test.ts
+++ b/packages/core/src/actions/switchConnection.test.ts
@@ -3,8 +3,8 @@ import { expect, test } from 'vitest'
import { connect } from './connect.js'
import { disconnect } from './disconnect.js'
-import { getAccount } from './getAccount.js'
-import { switchAccount } from './switchAccount.js'
+import { getConnection } from './getConnection.js'
+import { switchConnection } from './switchConnection.js'
const connector1 = config.connectors[0]!
const connector2 = config.connectors[1]!
@@ -13,17 +13,17 @@ test('default', async () => {
await connect(config, { connector: connector2 })
await connect(config, { connector: connector1 })
- const address1 = getAccount(config).address
+ const address1 = getConnection(config).address
- await switchAccount(config, { connector: connector2 })
+ await switchConnection(config, { connector: connector2 })
- const address2 = getAccount(config).address
+ const address2 = getConnection(config).address
expect(address2).toBeDefined()
expect(address1).not.toBe(address2)
- await switchAccount(config, { connector: connector1 })
+ await switchConnection(config, { connector: connector1 })
- const address3 = getAccount(config).address
+ const address3 = getConnection(config).address
expect(address3).toBeDefined()
expect(address1).toBe(address3)
diff --git a/packages/core/src/actions/switchAccount.ts b/packages/core/src/actions/switchConnection.ts
similarity index 71%
rename from packages/core/src/actions/switchAccount.ts
rename to packages/core/src/actions/switchConnection.ts
index ec577a57c7..6cec5c809f 100644
--- a/packages/core/src/actions/switchAccount.ts
+++ b/packages/core/src/actions/switchConnection.ts
@@ -7,27 +7,27 @@ import {
type ConnectorNotConnectedErrorType,
} from '../errors/config.js'
-export type SwitchAccountParameters = {
+export type SwitchConnectionParameters = {
connector: Connector
}
-export type SwitchAccountReturnType = {
+export type SwitchConnectionReturnType = {
accounts: readonly [Address, ...Address[]]
chainId:
| config['chains'][number]['id']
| (number extends config['chains'][number]['id'] ? number : number & {})
}
-export type SwitchAccountErrorType =
+export type SwitchConnectionErrorType =
| ConnectorNotConnectedErrorType
| BaseError
| ErrorType
-/** https://wagmi.sh/core/api/actions/switchAccount */
-export async function switchAccount(
+/** https://wagmi.sh/core/api/actions/switchConnection */
+export async function switchConnection(
config: config,
- parameters: SwitchAccountParameters,
-): Promise> {
+ parameters: SwitchConnectionParameters,
+): Promise> {
const { connector } = parameters
const connection = config.state.connections.get(connector.uid)
diff --git a/packages/core/src/actions/verifyMessage.test.ts b/packages/core/src/actions/verifyMessage.test.ts
index f2766cbea4..281a4aa23f 100644
--- a/packages/core/src/actions/verifyMessage.test.ts
+++ b/packages/core/src/actions/verifyMessage.test.ts
@@ -1,9 +1,9 @@
-import { accounts, config } from '@wagmi/test'
+import { config } from '@wagmi/test'
import { expect, test } from 'vitest'
import { verifyMessage } from './verifyMessage.js'
-const eoaAddress = accounts[0]
+const eoaAddress = '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266'
const smartAccountAddress = '0x3FCf42e10CC70Fe75A62EB3aDD6D305Aa840d145'
test('smart account: valid signature', async () => {
diff --git a/packages/core/src/actions/verifyTypedData.test-d.ts b/packages/core/src/actions/verifyTypedData.test-d.ts
new file mode 100644
index 0000000000..df51cdb861
--- /dev/null
+++ b/packages/core/src/actions/verifyTypedData.test-d.ts
@@ -0,0 +1,20 @@
+import { config, typedData } from '@wagmi/test'
+import { test } from 'vitest'
+
+import { verifyTypedData } from './verifyTypedData.js'
+
+test('default', async () => {
+ verifyTypedData(config, {
+ ...typedData.basic,
+ primaryType: 'Mail',
+ address: '0x',
+ signature: '0x',
+ })
+ verifyTypedData(config, {
+ ...typedData.basic,
+ // @ts-expect-error
+ primaryType: 'foobarbaz',
+ address: '0x',
+ signature: '0x',
+ })
+})
diff --git a/packages/core/src/actions/verifyTypedData.ts b/packages/core/src/actions/verifyTypedData.ts
index 4fac5463f5..cba510e058 100644
--- a/packages/core/src/actions/verifyTypedData.ts
+++ b/packages/core/src/actions/verifyTypedData.ts
@@ -8,14 +8,14 @@ import {
import type { Config } from '../createConfig.js'
import type { ChainIdParameter } from '../types/properties.js'
-import type { Compute } from '../types/utils.js'
+import type { UnionCompute } from '../types/utils.js'
import { getAction } from '../utils/getAction.js'
export type VerifyTypedDataParameters<
typedData extends TypedData | Record = TypedData,
primaryType extends keyof typedData | 'EIP712Domain' = keyof typedData,
config extends Config = Config,
-> = Compute<
+> = UnionCompute<
viem_VerifyTypedDataParameters &
ChainIdParameter
>
diff --git a/packages/core/src/experimental/actions/waitForCallsStatus.test.ts b/packages/core/src/actions/waitForCallsStatus.test.ts
similarity index 69%
rename from packages/core/src/experimental/actions/waitForCallsStatus.test.ts
rename to packages/core/src/actions/waitForCallsStatus.test.ts
index 0d3ce44998..381362d84c 100644
--- a/packages/core/src/experimental/actions/waitForCallsStatus.test.ts
+++ b/packages/core/src/actions/waitForCallsStatus.test.ts
@@ -2,8 +2,8 @@ import { accounts, config, testClient, wait } from '@wagmi/test'
import { parseEther } from 'viem'
import { expect, test } from 'vitest'
-import { connect } from '../../actions/connect.js'
-import { disconnect } from '../../actions/disconnect.js'
+import { connect } from './connect.js'
+import { disconnect } from './disconnect.js'
import { sendCalls } from './sendCalls.js'
import { waitForCallsStatus } from './waitForCallsStatus.js'
@@ -12,7 +12,7 @@ const connector = config.connectors[0]!
test('default', async () => {
await connect(config, { connector })
- const id = await sendCalls(config, {
+ const { id } = await sendCalls(config, {
calls: [
{
data: '0xdeadbeef',
@@ -40,7 +40,7 @@ test('default', async () => {
})(),
])
- expect(status).toBe('CONFIRMED')
+ expect(status).toBe('success')
expect(
receipts?.map((x) => ({ ...x, blockHash: undefined })),
).toMatchInlineSnapshot(
@@ -48,27 +48,27 @@ test('default', async () => {
[
{
"blockHash": undefined,
- "blockNumber": 19258214n,
- "gasUsed": 21064n,
+ "blockNumber": 23535881n,
+ "gasUsed": 21160n,
"logs": [],
"status": "success",
- "transactionHash": "0x13c53b2d4d9da424835525349cd66e553330f323d6fb19458b801ae1f7989a41",
+ "transactionHash": "0x7add018cb41f4b86d793758248d20cb8394364d9379d201cb7747db29c4aac18",
},
{
"blockHash": undefined,
- "blockNumber": 19258214n,
+ "blockNumber": 23535881n,
"gasUsed": 21000n,
"logs": [],
"status": "success",
- "transactionHash": "0xd8397b3e82b061c26a0c2093f1ceca0c3662a512614f7d6370349e89d0eea007",
+ "transactionHash": "0x5019ef03b9ee83c6398d1a68490b56878300c1f83697c3b3eeaf666baf63abff",
},
{
"blockHash": undefined,
- "blockNumber": 19258214n,
+ "blockNumber": 23535881n,
"gasUsed": 21000n,
"logs": [],
"status": "success",
- "transactionHash": "0x4d26e346593d9ea265bb164b115e89aa92df43b0b8778ac75d4ad28e2a22b101",
+ "transactionHash": "0xe61204827da836e4bc51fbfe15f04e5b1307c50f160d1add15675c8654663f20",
},
]
`,
diff --git a/packages/core/src/experimental/actions/waitForCallsStatus.ts b/packages/core/src/actions/waitForCallsStatus.ts
similarity index 72%
rename from packages/core/src/experimental/actions/waitForCallsStatus.ts
rename to packages/core/src/actions/waitForCallsStatus.ts
index 2a02df2f48..a1c5764d32 100644
--- a/packages/core/src/experimental/actions/waitForCallsStatus.ts
+++ b/packages/core/src/actions/waitForCallsStatus.ts
@@ -3,11 +3,11 @@ import {
type WaitForCallsStatusParameters as viem_WaitForCallsStatusParameters,
type WaitForCallsStatusReturnType as viem_WaitForCallsStatusReturnType,
waitForCallsStatus as viem_waitForCallsStatus,
-} from 'viem/experimental'
+} from 'viem/actions'
-import { getConnectorClient } from '../../actions/getConnectorClient.js'
-import type { Config } from '../../createConfig.js'
-import type { ConnectorParameter } from '../../types/properties.js'
+import type { Config } from '../createConfig.js'
+import type { ConnectorParameter } from '../types/properties.js'
+import { getConnectorClient } from './getConnectorClient.js'
export type WaitForCallsStatusParameters = viem_WaitForCallsStatusParameters &
ConnectorParameter
@@ -21,7 +21,7 @@ export async function waitForCallsStatus(
config: config,
parameters: WaitForCallsStatusParameters,
): Promise {
- const { connector, id } = parameters
+ const { connector } = parameters
const client = await getConnectorClient(config, { connector })
- return viem_waitForCallsStatus(client, { id })
+ return viem_waitForCallsStatus(client, parameters)
}
diff --git a/packages/core/src/actions/waitForTransactionReceipt.test.ts b/packages/core/src/actions/waitForTransactionReceipt.test.ts
index 2a5146d8b1..ee0e7f488f 100644
--- a/packages/core/src/actions/waitForTransactionReceipt.test.ts
+++ b/packages/core/src/actions/waitForTransactionReceipt.test.ts
@@ -44,6 +44,7 @@ test('behavior: transaction reverted', async () => {
[CallExecutionError: Execution reverted with reason: PartyBid::claim: contribution already claimed.
Raw Call Arguments:
+ from: 0xa0cf798816d4b9b9866b5330eea46a18382f251e
to: 0xf1332f21487e74612ed3a0fb36da729b73f1ae19
value: 0 ETH
data: 0x1e83409a000000000000000000000000a0cf798816d4b9b9866b5330eea46a18382f251e
@@ -53,6 +54,6 @@ test('behavior: transaction reverted', async () => {
nonce: 43
Details: execution reverted: PartyBid::claim: contribution already claimed
- Version: viem@2.23.12]
+ Version: viem@2.44.0]
`)
})
diff --git a/packages/core/src/actions/waitForTransactionReceipt.ts b/packages/core/src/actions/waitForTransactionReceipt.ts
index 5ac8fcdb20..4efa69d27d 100644
--- a/packages/core/src/actions/waitForTransactionReceipt.ts
+++ b/packages/core/src/actions/waitForTransactionReceipt.ts
@@ -63,10 +63,13 @@ export async function waitForTransactionReceipt<
getTransaction,
'getTransaction',
)
- const txn = await action_getTransaction({ hash: receipt.transactionHash })
+ const { from: account, ...txn } = await action_getTransaction({
+ hash: receipt.transactionHash,
+ })
const action_call = getAction(client, call, 'call')
const code = await action_call({
...(txn as any),
+ account,
data: txn.input,
gasPrice: txn.type !== 'eip1559' ? txn.gasPrice : undefined,
maxFeePerGas: txn.type === 'eip1559' ? txn.maxFeePerGas : undefined,
diff --git a/packages/core/src/actions/watchAccount.ts b/packages/core/src/actions/watchAccount.ts
deleted file mode 100644
index dfa8ae4908..0000000000
--- a/packages/core/src/actions/watchAccount.ts
+++ /dev/null
@@ -1,33 +0,0 @@
-import type { Config } from '../createConfig.js'
-import { deepEqual } from '../utils/deepEqual.js'
-import { type GetAccountReturnType, getAccount } from './getAccount.js'
-
-export type WatchAccountParameters = {
- onChange(
- account: GetAccountReturnType,
- prevAccount: GetAccountReturnType,
- ): void
-}
-
-export type WatchAccountReturnType = () => void
-
-/** https://wagmi.sh/core/api/actions/watchAccount */
-export function watchAccount(
- config: config,
- parameters: WatchAccountParameters,
-): WatchAccountReturnType {
- const { onChange } = parameters
-
- return config.subscribe(() => getAccount(config), onChange, {
- equalityFn(a, b) {
- const { connector: aConnector, ...aRest } = a
- const { connector: bConnector, ...bRest } = b
- return (
- deepEqual(aRest, bRest) &&
- // check connector separately
- aConnector?.id === bConnector?.id &&
- aConnector?.uid === bConnector?.uid
- )
- },
- })
-}
diff --git a/packages/core/src/actions/watchBlockNumber.test.ts b/packages/core/src/actions/watchBlockNumber.test.ts
index 0a4299db58..636d723c20 100644
--- a/packages/core/src/actions/watchBlockNumber.test.ts
+++ b/packages/core/src/actions/watchBlockNumber.test.ts
@@ -1,5 +1,5 @@
import { config, testClient, wait } from '@wagmi/test'
-import { expect, test } from 'vitest'
+import { expect, test, vi } from 'vitest'
import { watchBlockNumber } from './watchBlockNumber.js'
@@ -16,12 +16,10 @@ test('default', async () => {
await testClient.mainnet.mine({ blocks: 1 })
await wait(100)
await testClient.mainnet.mine({ blocks: 1 })
- await wait(100)
+ await vi.waitUntil(() => blockNumbers.length === 3, { timeout: 5_000 })
expect(blockNumbers.length).toBe(3)
- expect(
- blockNumbers.map((blockNumber) => blockNumber - blockNumbers[0]!),
- ).toEqual([0n, 1n, 2n])
unwatch()
+ await wait(100)
})
diff --git a/packages/core/src/actions/watchBlockNumber.ts b/packages/core/src/actions/watchBlockNumber.ts
index 712849080a..75379a6927 100644
--- a/packages/core/src/actions/watchBlockNumber.ts
+++ b/packages/core/src/actions/watchBlockNumber.ts
@@ -1,10 +1,9 @@
+import type { Chain, Transport, WebSocketTransport } from 'viem'
import {
type WatchBlockNumberParameters as viem_WatchBlockNumberParameters,
type WatchBlockNumberReturnType as viem_WatchBlockNumberReturnType,
watchBlockNumber as viem_watchBlockNumber,
} from 'viem/actions'
-
-import type { Chain, Transport, WebSocketTransport } from 'viem'
import type { Config } from '../createConfig.js'
import type { SelectChains } from '../types/chain.js'
import type {
diff --git a/packages/core/src/actions/watchBlocks.test.ts b/packages/core/src/actions/watchBlocks.test.ts
index caf4c0dc61..62b2629586 100644
--- a/packages/core/src/actions/watchBlocks.test.ts
+++ b/packages/core/src/actions/watchBlocks.test.ts
@@ -1,7 +1,6 @@
import { config, testClient, wait } from '@wagmi/test'
-import { expect, test } from 'vitest'
-
import type { Block } from 'viem'
+import { expect, test, vi } from 'vitest'
import { watchBlocks } from './watchBlocks.js'
test('default', async () => {
@@ -13,18 +12,14 @@ test('default', async () => {
})
await testClient.mainnet.mine({ blocks: 1 })
- await wait(100)
+ await wait(500)
await testClient.mainnet.mine({ blocks: 1 })
- await wait(100)
+ await wait(500)
await testClient.mainnet.mine({ blocks: 1 })
- await wait(100)
+ await vi.waitUntil(() => blocks.length === 3, { timeout: 5_000 })
expect(blocks.length).toBe(3)
- expect(blocks.map((block) => block.number! - blocks[0]?.number!)).toEqual([
- 0n,
- 1n,
- 2n,
- ])
unwatch()
+ await wait(100)
})
diff --git a/packages/core/src/actions/watchBlocks.ts b/packages/core/src/actions/watchBlocks.ts
index c6f3225dc9..cd2dcf0676 100644
--- a/packages/core/src/actions/watchBlocks.ts
+++ b/packages/core/src/actions/watchBlocks.ts
@@ -1,10 +1,9 @@
+import type { BlockTag, Chain, Transport, WebSocketTransport } from 'viem'
import {
type WatchBlocksParameters as viem_WatchBlocksParameters,
type WatchBlocksReturnType as viem_WatchBlocksReturnType,
watchBlocks as viem_watchBlocks,
} from 'viem/actions'
-
-import type { BlockTag, Chain, Transport, WebSocketTransport } from 'viem'
import type { Config } from '../createConfig.js'
import type { SelectChains } from '../types/chain.js'
import type {
diff --git a/packages/core/src/actions/watchAccount.test.ts b/packages/core/src/actions/watchConnection.test.ts
similarity index 63%
rename from packages/core/src/actions/watchAccount.test.ts
rename to packages/core/src/actions/watchConnection.test.ts
index c803165888..26de7a6f9f 100644
--- a/packages/core/src/actions/watchAccount.test.ts
+++ b/packages/core/src/actions/watchConnection.test.ts
@@ -4,27 +4,27 @@ import { expect, test } from 'vitest'
import { connect } from './connect.js'
import { disconnect } from './disconnect.js'
-import { watchAccount } from './watchAccount.js'
+import { watchConnection } from './watchConnection.js'
test('default', async () => {
- const accounts: { address: Address | undefined; status: string }[] = []
- const unwatch = watchAccount(config, {
+ const connections: { address: Address | undefined; status: string }[] = []
+ const unwatch = watchConnection(config, {
onChange(data) {
- accounts.push({ address: data.address, status: data.status })
+ connections.push({ address: data.address, status: data.status })
},
})
await connect(config, { connector: config.connectors[0]! })
await disconnect(config)
- expect(accounts).toMatchInlineSnapshot(`
+ expect(connections).toMatchInlineSnapshot(`
[
{
"address": undefined,
"status": "connecting",
},
{
- "address": "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266",
+ "address": "0x95132632579b073D12a6673e18Ab05777a6B86f8",
"status": "connected",
},
{
diff --git a/packages/core/src/actions/watchConnection.ts b/packages/core/src/actions/watchConnection.ts
new file mode 100644
index 0000000000..a1b6b22e19
--- /dev/null
+++ b/packages/core/src/actions/watchConnection.ts
@@ -0,0 +1,33 @@
+import type { Config } from '../createConfig.js'
+import { deepEqual } from '../utils/deepEqual.js'
+import { type GetConnectionReturnType, getConnection } from './getConnection.js'
+
+export type WatchConnectionParameters = {
+ onChange(
+ connection: GetConnectionReturnType,
+ prevConnection: GetConnectionReturnType,
+ ): void
+}
+
+export type WatchConnectionReturnType = () => void
+
+/** https://wagmi.sh/core/api/actions/watchConnection */
+export function watchConnection(
+ config: config,
+ parameters: WatchConnectionParameters,
+): WatchConnectionReturnType {
+ const { onChange } = parameters
+
+ return config.subscribe(() => getConnection(config), onChange, {
+ equalityFn(a, b) {
+ const { connector: aConnector, ...aRest } = a
+ const { connector: bConnector, ...bRest } = b
+ return (
+ deepEqual(aRest, bRest) &&
+ // check connector separately
+ aConnector?.id === bConnector?.id &&
+ aConnector?.uid === bConnector?.uid
+ )
+ },
+ })
+}
diff --git a/packages/core/src/actions/watchContractEvent.test-d.ts b/packages/core/src/actions/watchContractEvent.test-d.ts
index e6624fff57..00ae6f4a23 100644
--- a/packages/core/src/actions/watchContractEvent.test-d.ts
+++ b/packages/core/src/actions/watchContractEvent.test-d.ts
@@ -60,8 +60,6 @@ test('behavior: no eventName', () => {
onLogs(logs) {
expectTypeOf(logs[0]!.eventName).toEqualTypeOf<'Transfer' | 'Approval'>()
expectTypeOf(logs[0]!.args).toEqualTypeOf<
- | Record
- | readonly unknown[]
| {
from?: `0x${string}` | undefined
to?: `0x${string}` | undefined
diff --git a/packages/core/src/actions/watchContractEvent.test.ts b/packages/core/src/actions/watchContractEvent.test.ts
index 759a21dd19..72486ed59d 100644
--- a/packages/core/src/actions/watchContractEvent.test.ts
+++ b/packages/core/src/actions/watchContractEvent.test.ts
@@ -7,13 +7,13 @@ import {
transactionHashRegex,
wait,
} from '@wagmi/test'
-import { http, createWalletClient, parseEther } from 'viem'
+import { createWalletClient, erc20Abi, http, parseEther } from 'viem'
import type { WatchEventOnLogsParameter } from 'viem/actions'
import { beforeEach, expect, test } from 'vitest'
import { connect } from './connect.js'
import { disconnect } from './disconnect.js'
-import { getBalance } from './getBalance.js'
+import { readContract } from './readContract.js'
import { watchContractEvent } from './watchContractEvent.js'
import { writeContract } from './writeContract.js'
@@ -53,11 +53,13 @@ test('default', async () => {
address: address.usdcHolder,
})
- const balance = await getBalance(config, {
- address: connectedAddress,
- token: address.usdc,
+ const balance = await readContract(config, {
+ address: address.usdc,
+ abi: erc20Abi,
+ functionName: 'balanceOf',
+ args: [connectedAddress],
})
- expect(balance.value).toBeGreaterThan(0n)
+ expect(balance).toBeGreaterThan(0n)
// start watching transfer events
let logs: WatchEventOnLogsParameter = []
@@ -89,6 +91,7 @@ test('default', async () => {
await wait(1000) // wait for events to be emitted
unwatch()
+ await wait(100)
expect(logs.length).toBe(2)
expect(logs[0]?.transactionHash).toMatch(transactionHashRegex)
diff --git a/packages/core/src/actions/watchPendingTransactions.test.ts b/packages/core/src/actions/watchPendingTransactions.test.ts
index 510b9acce3..6ddd3a0778 100644
--- a/packages/core/src/actions/watchPendingTransactions.test.ts
+++ b/packages/core/src/actions/watchPendingTransactions.test.ts
@@ -42,6 +42,7 @@ test('default', async () => {
await testClient.mainnet.mine({ blocks: 1 })
unwatch()
+ await wait(100)
expect(transactions.length).toBe(2)
expect(transactions[0]).toMatch(transactionHashRegex)
diff --git a/packages/core/src/actions/writeContract.bench-d.ts b/packages/core/src/actions/writeContract.bench-d.ts
new file mode 100644
index 0000000000..e84114089c
--- /dev/null
+++ b/packages/core/src/actions/writeContract.bench-d.ts
@@ -0,0 +1,41 @@
+import { attest } from '@ark/attest'
+import type { abi } from '@wagmi/test'
+import { parseAbi } from 'viem'
+import viemPackageJson from 'viem/package.json' with { type: 'json' }
+import { test } from 'vitest'
+import type { WriteContractParameters } from './writeContract.js'
+
+test('default', () => {
+ type Result = WriteContractParameters<(typeof abi)['erc20'], 'approve'>
+ const res = {} as Result
+ attest.instantiations([143162, 'instantiations'])
+ attest(res.args)
+ if (viemPackageJson.version.startsWith('2.43'))
+ attest(res.args).type.toString.snap(
+ // biome-ignore lint/style/noUnusedTemplateLiteral: stable
+ `readonly [spender: \`0x\${string}\`, amount: bigint]`,
+ )
+})
+
+const abiOverload = parseAbi([
+ 'function foo() returns (int8)',
+ 'function foo(address account) returns (string)',
+ 'function foo(address sender, address account) returns ((address foo, address bar))',
+ 'function bar() returns (int8)',
+])
+test('overloads', () => {
+ type Result = WriteContractParameters
+ const res = {} as Result
+ attest.instantiations([21691, 'instantiations'])
+ attest<
+ | readonly []
+ | readonly [account: `0x${string}`]
+ | readonly [sender: `0x${string}`, account: `0x${string}`]
+ | undefined
+ >(res.args)
+ if (viemPackageJson.version.startsWith('2.43'))
+ attest(res.args).type.toString.snap(` | readonly []
+ | readonly [account: \`0x\${string}\`]
+ | readonly [sender: \`0x\${string}\`, account: \`0x\${string}\`]
+ | undefined`)
+})
diff --git a/packages/core/src/actions/writeContract.test-d.ts b/packages/core/src/actions/writeContract.test-d.ts
index 68009a3773..29098787d5 100644
--- a/packages/core/src/actions/writeContract.test-d.ts
+++ b/packages/core/src/actions/writeContract.test-d.ts
@@ -1,5 +1,5 @@
import { abi, config } from '@wagmi/test'
-import { http, type Address, parseAbi } from 'viem'
+import { type Address, http, parseAbi } from 'viem'
import { celo, mainnet } from 'viem/chains'
import { expectTypeOf, test } from 'vitest'
diff --git a/packages/core/src/actions/writeContract.ts b/packages/core/src/actions/writeContract.ts
index 5fb6d87104..63377e5331 100644
--- a/packages/core/src/actions/writeContract.ts
+++ b/packages/core/src/actions/writeContract.ts
@@ -47,7 +47,7 @@ export type WriteContractParameters<
> = UnionCompute<
{
// TODO: Should use `UnionStrictOmit<..., 'chain'>` on `viem_WriteContractParameters` result instead
- // temp workaround that doesn't affect runtime behavior for for https://github.com/wevm/wagmi/issues/3981
+ // temp workaround that doesn't affect runtime behavior for https://github.com/wevm/wagmi/issues/3981
[key in keyof chains]: viem_WriteContractParameters<
abi,
functionName,
@@ -59,10 +59,7 @@ export type WriteContractParameters<
>
}[number] &
Compute> &
- ConnectorParameter & {
- /** @deprecated */
- __mode?: 'prepared'
- }
+ ConnectorParameter
>
export type WriteContractReturnType = viem_WriteContractReturnType
@@ -99,6 +96,7 @@ export async function writeContract<
else
client = await getConnectorClient(config, {
account: account ?? undefined,
+ assertChainId: false,
chainId,
connector,
})
diff --git a/packages/core/src/connectors/createConnector.test.ts b/packages/core/src/connectors/createConnector.test.ts
index d1ff9f20af..8ce1468738 100644
--- a/packages/core/src/connectors/createConnector.test.ts
+++ b/packages/core/src/connectors/createConnector.test.ts
@@ -1,4 +1,3 @@
-import type { Address } from 'viem'
import { test } from 'vitest'
import { createConnector } from './createConnector.js'
@@ -10,7 +9,7 @@ test('default', () => {
type: 'test',
async setup() {},
async connect() {
- return { accounts: [] as Address[], chainId: 123 }
+ return { accounts: [] as never, chainId: 123 }
},
async disconnect() {},
async getAccounts() {
diff --git a/packages/core/src/connectors/createConnector.ts b/packages/core/src/connectors/createConnector.ts
index 54b4d9955c..bf2d05e21b 100644
--- a/packages/core/src/connectors/createConnector.ts
+++ b/packages/core/src/connectors/createConnector.ts
@@ -38,17 +38,23 @@ export type CreateConnectorFn<
readonly id: string
readonly name: string
readonly rdns?: string | readonly string[] | undefined
- /** @deprecated */
- readonly supportsSimulation?: boolean | undefined
readonly type: string
setup?(): Promise
- connect(
+ // TODO(v3): Make `withCapabilities: true` default behavior
+ connect(
parameters?:
- | { chainId?: number | undefined; isReconnecting?: boolean | undefined }
+ | {
+ chainId?: number | undefined
+ isReconnecting?: boolean | undefined
+ withCapabilities?: withCapabilities | boolean | undefined
+ }
| undefined,
): Promise<{
- accounts: readonly Address[]
+ // TODO(v3): Add `capabilities` (e.g. `readonly { address: Address; capabilities: Record | undefined }`)
+ accounts: withCapabilities extends true
+ ? readonly { address: Address; capabilities: Record }[]
+ : readonly Address[]
chainId: number
}>
disconnect(): Promise
diff --git a/packages/core/src/connectors/injected.ts b/packages/core/src/connectors/injected.ts
index d686d0aa29..99444164b7 100644
--- a/packages/core/src/connectors/injected.ts
+++ b/packages/core/src/connectors/injected.ts
@@ -2,14 +2,14 @@ import {
type AddEthereumChainParameter,
type Address,
type EIP1193Provider,
+ getAddress,
+ numberToHex,
type ProviderConnectInfo,
type ProviderRpcError,
ResourceUnavailableRpcError,
type RpcError,
SwitchChainError,
UserRejectedRequestError,
- getAddress,
- numberToHex,
withRetry,
withTimeout,
} from 'viem'
@@ -88,10 +88,6 @@ export function injected(parameters: InjectedParameters = {}) {
get name() {
return getTarget().name
},
- /** @deprecated */
- get supportsSimulation() {
- return true
- },
type: injected.type,
async setup() {
const provider = await this.getProvider()
@@ -110,7 +106,7 @@ export function injected(parameters: InjectedParameters = {}) {
}
}
},
- async connect({ chainId, isReconnecting } = {}) {
+ async connect({ chainId, isReconnecting, withCapabilities } = {}) {
const provider = await this.getProvider()
if (!provider) throw new ProviderNotFoundError()
@@ -189,7 +185,12 @@ export function injected(parameters: InjectedParameters = {}) {
if (!parameters.target)
await config.storage?.setItem('injected.connected', true)
- return { accounts, chainId: currentChainId }
+ return {
+ accounts: (withCapabilities
+ ? accounts.map((address) => ({ address, capabilities: {} }))
+ : accounts) as never,
+ chainId: currentChainId,
+ }
} catch (err) {
const error = err as RpcError
if (error.code === UserRejectedRequestError.code)
diff --git a/packages/core/src/connectors/mock.test.ts b/packages/core/src/connectors/mock.test.ts
index 5beef19aa4..9359c1b529 100644
--- a/packages/core/src/connectors/mock.test.ts
+++ b/packages/core/src/connectors/mock.test.ts
@@ -1,6 +1,6 @@
import { accounts, config } from '@wagmi/test'
+import type { Address, Hex } from 'viem'
import { expect, expectTypeOf, test } from 'vitest'
-
import type { Connector } from '../createConfig.js'
import type { CreateConnectorFn } from './createConnector.js'
import { mock } from './mock.js'
@@ -21,16 +21,50 @@ test('setup', () => {
Parameters<(typeof connector)['connect']>[0]
>
expectTypeOf().toMatchTypeOf()
+
+ type ConnectFnReturnType = Awaited>
+ expectTypeOf().toMatchTypeOf<
+ | readonly `0x${string}`[]
+ | readonly {
+ address: Address
+ capabilities: {
+ foo: {
+ bar: Hex
+ }
+ }
+ }[]
+ >()
+})
+
+test('behavior: connect#withCapabilities', async () => {
+ const connectorFn = mock({ accounts })
+ const connector = config._internal.connectors.setup(connectorFn)
+ const res = await connector.connect({ withCapabilities: true })
+ expectTypeOf(res.accounts).toEqualTypeOf<
+ readonly {
+ address: Address
+ capabilities: Record
+ }[]
+ >()
+ expect(res).toMatchObject(
+ expect.objectContaining({
+ accounts: expect.arrayContaining([
+ expect.objectContaining({ address: expect.any(String) }),
+ ]),
+ }),
+ )
})
-test('behavior: features.connectError', () => {
+test('behavior: features.connectError', async () => {
const connectorFn = mock({ accounts, features: { connectError: true } })
const connector = config._internal.connectors.setup(connectorFn)
- expect(() => connector.connect()).rejects.toThrowErrorMatchingInlineSnapshot(`
+ await expect(() =>
+ connector.connect(),
+ ).rejects.toThrowErrorMatchingInlineSnapshot(`
[UserRejectedRequestError: User rejected the request.
Details: Failed to connect.
- Version: viem@2.23.12]
+ Version: viem@2.44.0]
`)
})
@@ -49,7 +83,7 @@ test('behavior: connector.getProvider request errors', async () => {
) as ReturnType
const provider = await connector.getProvider()
- expect(
+ await expect(
provider.request({
method: 'eth_signTypedData_v4',
params: [] as any,
@@ -58,10 +92,10 @@ test('behavior: connector.getProvider request errors', async () => {
[UserRejectedRequestError: User rejected the request.
Details: Failed to sign typed data.
- Version: viem@2.23.12]
+ Version: viem@2.44.0]
`)
- expect(
+ await expect(
provider.request({
method: 'wallet_switchEthereumChain',
params: [] as any,
@@ -70,10 +104,10 @@ test('behavior: connector.getProvider request errors', async () => {
[UserRejectedRequestError: User rejected the request.
Details: Failed to switch chain.
- Version: viem@2.23.12]
+ Version: viem@2.44.0]
`)
- expect(
+ await expect(
provider.request({
method: 'wallet_watchAsset',
params: [] as any,
@@ -82,10 +116,10 @@ test('behavior: connector.getProvider request errors', async () => {
[UserRejectedRequestError: User rejected the request.
Details: Failed to switch chain.
- Version: viem@2.23.12]
+ Version: viem@2.44.0]
`)
- expect(
+ await expect(
provider.request({
method: 'personal_sign',
params: [] as any,
@@ -94,7 +128,7 @@ test('behavior: connector.getProvider request errors', async () => {
[UserRejectedRequestError: User rejected the request.
Details: Failed to sign message.
- Version: viem@2.23.12]
+ Version: viem@2.44.0]
`)
})
diff --git a/packages/core/src/connectors/mock.ts b/packages/core/src/connectors/mock.ts
index 8a2dd8a6e6..141c47b505 100644
--- a/packages/core/src/connectors/mock.ts
+++ b/packages/core/src/connectors/mock.ts
@@ -1,19 +1,20 @@
import {
type Address,
+ custom,
type EIP1193RequestFn,
+ fromHex,
+ getAddress,
type Hex,
+ keccak256,
+ numberToHex,
RpcRequestError,
SwitchChainError,
+ stringToHex,
type Transport,
UserRejectedRequestError,
type WalletCallReceipt,
+ type WalletGetCallsStatusReturnType,
type WalletRpcSchema,
- custom,
- fromHex,
- getAddress,
- keccak256,
- numberToHex,
- stringToHex,
} from 'viem'
import { rpc } from 'viem/utils'
@@ -49,12 +50,23 @@ export function mock(parameters: MockParameters) {
Transport<'custom', unknown, EIP1193RequestFn>
>
type Properties = {
- connect(parameters?: {
+ // TODO(v3): Make `withCapabilities: true` default behavior
+ connect(parameters?: {
chainId?: number | undefined
isReconnecting?: boolean | undefined
foo?: string | undefined
+ withCapabilities?: withCapabilities | boolean | undefined
}): Promise<{
- accounts: readonly Address[]
+ accounts: withCapabilities extends true
+ ? readonly {
+ address: Address
+ capabilities: {
+ foo: {
+ bar: Hex
+ }
+ }
+ }[]
+ : readonly Address[]
chainId: number
}>
}
@@ -68,7 +80,7 @@ export function mock(parameters: MockParameters) {
async setup() {
connectedChainId = config.chains[0].id
},
- async connect({ chainId } = {}) {
+ async connect({ chainId, withCapabilities } = {}) {
if (features.connectError) {
if (typeof features.connectError === 'boolean')
throw new UserRejectedRequestError(new Error('Failed to connect.'))
@@ -89,7 +101,12 @@ export function mock(parameters: MockParameters) {
connected = true
return {
- accounts: accounts.map((x) => getAddress(x)),
+ accounts: (withCapabilities
+ ? accounts.map((x) => ({
+ address: getAddress(x),
+ capabilities: { foo: { bar: x } },
+ }))
+ : accounts.map((x) => getAddress(x))) as never,
chainId: currentChainId,
}
},
@@ -189,7 +206,7 @@ export function mock(parameters: MockParameters) {
paymasterService: {
supported:
(params as [Hex])[0] ===
- '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
+ '0x95132632579b073D12a6673e18Ab05777a6B86f8',
},
sessionKeys: {
supported: true,
@@ -199,7 +216,7 @@ export function mock(parameters: MockParameters) {
paymasterService: {
supported:
(params as [Hex])[0] ===
- '0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266',
+ '0x95132632579b073D12a6673e18Ab05777a6B86f8',
},
},
}
@@ -207,11 +224,17 @@ export function mock(parameters: MockParameters) {
if (method === 'wallet_sendCalls') {
const hashes = []
const calls = (params as any)[0].calls
+ const from = (params as any)[0].from
for (const call of calls) {
const { result, error } = await rpc.http(url, {
body: {
method: 'eth_sendTransaction',
- params: [call],
+ params: [
+ {
+ ...call,
+ ...(typeof from !== 'undefined' ? { from } : {}),
+ },
+ ],
},
})
if (error)
@@ -224,12 +247,21 @@ export function mock(parameters: MockParameters) {
}
const id = keccak256(stringToHex(JSON.stringify(calls)))
transactionCache.set(id, hashes)
- return id
+ return { id }
}
if (method === 'wallet_getCallsStatus') {
const hashes = transactionCache.get((params as any)[0])
- if (!hashes) return null
+ if (!hashes)
+ return {
+ atomic: false,
+ chainId: '0x1',
+ id: (params as any)[0],
+ status: 100,
+ receipts: [],
+ version: '2.0.0',
+ } satisfies WalletGetCallsStatusReturnType
+
const receipts = await Promise.all(
hashes.map(async (hash) => {
const { result, error } = await rpc.http(url, {
@@ -256,9 +288,24 @@ export function mock(parameters: MockParameters) {
} satisfies WalletCallReceipt
}),
)
- if (receipts.some((x) => !x))
- return { status: 'PENDING', receipts: [] }
- return { status: 'CONFIRMED', receipts }
+ const receipts_ = receipts.filter((x) => x !== null)
+ if (receipts_.length === 0)
+ return {
+ atomic: false,
+ chainId: '0x1',
+ id: (params as any)[0],
+ status: 100,
+ receipts: [],
+ version: '2.0.0',
+ } satisfies WalletGetCallsStatusReturnType
+ return {
+ atomic: false,
+ chainId: '0x1',
+ id: (params as any)[0],
+ status: 200,
+ receipts: receipts_,
+ version: '2.0.0',
+ } satisfies WalletGetCallsStatusReturnType
}
if (method === 'wallet_showCallsStatus') return
diff --git a/packages/core/src/createConfig.test-d.ts b/packages/core/src/createConfig.test-d.ts
index 3daa57bd5f..fb693fa594 100644
--- a/packages/core/src/createConfig.test-d.ts
+++ b/packages/core/src/createConfig.test-d.ts
@@ -1,5 +1,5 @@
import { accounts } from '@wagmi/test'
-import { http, createClient, webSocket } from 'viem'
+import { createClient, http, webSocket } from 'viem'
import { mainnet, sepolia } from 'viem/chains'
import { expectTypeOf, test } from 'vitest'
@@ -73,7 +73,7 @@ test('behavior: missing transport for chain', () => {
transports: {
[mainnet.id]: http(),
// @ts-expect-error
- [123]: http(),
+ 123: http(),
},
})
})
diff --git a/packages/core/src/createConfig.test.ts b/packages/core/src/createConfig.test.ts
index a6ae41e280..de3f2160dd 100644
--- a/packages/core/src/createConfig.test.ts
+++ b/packages/core/src/createConfig.test.ts
@@ -1,8 +1,8 @@
import { accounts, chain, wait } from '@wagmi/test'
import {
+ announceProvider,
type EIP1193Provider,
type EIP6963ProviderDetail,
- announceProvider,
} from 'mipd'
import { http } from 'viem'
import { expect, test, vi } from 'vitest'
@@ -12,8 +12,9 @@ import { disconnect } from './actions/disconnect.js'
import { switchChain } from './actions/switchChain.js'
import { createConnector } from './connectors/createConnector.js'
import { mock } from './connectors/mock.js'
-import { createConfig } from './createConfig.js'
+import { type Connection, createConfig } from './createConfig.js'
import { createStorage } from './createStorage.js'
+import { serialize } from './utils/serialize.js'
const { mainnet, optimism } = chain
@@ -426,6 +427,62 @@ test('behavior: eip 6963 providers', async () => {
`)
})
+test('behavior: revalidate connections', async () => {
+ const state = {
+ 'wagmi.store': serialize({
+ state: { chainId: 1 },
+ version: 1,
+ }),
+ } as Record
+ Object.defineProperty(window, 'localStorage', {
+ value: {
+ getItem: vi.fn((key) => state[key] ?? null),
+ removeItem: vi.fn((key) => state.delete?.[key]),
+ setItem: vi.fn((key, value) => {
+ state[key] = value
+ }),
+ },
+ writable: true,
+ })
+
+ const config = createConfig({
+ chains: [mainnet],
+ connectors: [
+ mock({ accounts }),
+ mock({ accounts, features: { defaultConnected: true, reconnect: true } }),
+ mock({ accounts }),
+ ],
+ storage: createStorage<{ store: object }>({
+ storage: window.localStorage,
+ }),
+ transports: {
+ [mainnet.id]: http(),
+ },
+ })
+
+ const connections = new Map()
+ const c1 = config.connectors.at(0)!
+ const c2 = config.connectors.at(1)!
+ const c3 = config.connectors.at(2)!
+ connections.set(c1.uid, { accounts: ['0x'], chainId: 1, connector: c1 })
+ connections.set(c2.uid, { accounts: ['0x'], chainId: 1, connector: c2 })
+ connections.set(c3.uid, { accounts: ['0x'], chainId: 1, connector: c3 })
+ connections.set('foo', {
+ accounts: ['0x'],
+ chainId: 1,
+ connector: {
+ id: 'foo',
+ name: 'foo',
+ type: 'foo',
+ uid: 'foo',
+ } as Connection['connector'],
+ })
+ config.setState((state) => ({ ...state, connections }))
+ await config._internal.revalidate()
+
+ expect([...config.state.connections.keys()]).toEqual([c2.uid])
+})
+
function getProviderDetail(
info: Pick,
): EIP6963ProviderDetail {
diff --git a/packages/core/src/createConfig.ts b/packages/core/src/createConfig.ts
index 154eef5f6d..b64cf305aa 100644
--- a/packages/core/src/createConfig.ts
+++ b/packages/core/src/createConfig.ts
@@ -1,30 +1,30 @@
import {
+ createStore as createMipd,
type EIP6963ProviderDetail,
type Store as MipdStore,
- createStore as createMipd,
} from 'mipd'
import {
type Address,
type Chain,
type Client,
- type EIP1193RequestFn,
createClient,
+ type EIP1193RequestFn,
type ClientConfig as viem_ClientConfig,
type Transport as viem_Transport,
} from 'viem'
import { persist, subscribeWithSelector } from 'zustand/middleware'
-import { type Mutate, type StoreApi, createStore } from 'zustand/vanilla'
+import { createStore, type Mutate, type StoreApi } from 'zustand/vanilla'
import type {
ConnectorEventMap,
CreateConnectorFn,
} from './connectors/createConnector.js'
import { injected } from './connectors/injected.js'
-import { type Emitter, type EventData, createEmitter } from './createEmitter.js'
+import { createEmitter, type Emitter, type EventData } from './createEmitter.js'
import {
- type Storage,
createStorage,
getDefaultStorage,
+ type Storage,
} from './createStorage.js'
import { ChainNotConfiguredError } from './errors/config.js'
import type {
@@ -198,9 +198,9 @@ export function createConfig<
let currentVersion: number
const prefix = '0.0.0-canary-'
if (version.startsWith(prefix))
- currentVersion = Number.parseInt(version.replace(prefix, ''))
+ currentVersion = Number.parseInt(version.replace(prefix, ''), 10)
// use package major version to version store
- else currentVersion = Number.parseInt(version.split('.')[0] ?? '0')
+ else currentVersion = Number.parseInt(version.split('.')[0] ?? '0', 10)
const store = createStore(
subscribeWithSelector(
@@ -414,7 +414,9 @@ export function createConfig<
return chains.getState() as chains
},
get connectors() {
- return connectors.getState() as Connector[]
+ return connectors.getState() as Readonly<{
+ [key in keyof connectorFns]: Connector
+ }>
},
storage,
@@ -451,6 +453,26 @@ export function createConfig<
_internal: {
mipd,
+ async revalidate() {
+ // Check connections to see if they are still active
+ const state = store.getState()
+ const connections = state.connections
+ let current = state.current
+ for (const [, connection] of connections) {
+ const connector = connection.connector
+ // check if `connect.isAuthorized` exists
+ // partial connectors in storage do not have it
+ const isAuthorized = connector.isAuthorized
+ ? await connector.isAuthorized()
+ : false
+ if (isAuthorized) continue
+ // Remove stale connection
+ connections.delete(connector.uid)
+ if (current === connector.uid) current = null
+ }
+ // set connections
+ store.setState((x) => ({ ...x, connections, current }))
+ },
store,
ssr: Boolean(ssr),
syncConnectedChain,
@@ -515,10 +537,9 @@ export type CreateConfigParameters<
| undefined
})
| {
- client(parameters: { chain: chains[number] }): Client<
- transports[chains[number]['id']],
- chains[number]
- >
+ client(parameters: {
+ chain: chains[number]
+ }): Client
}
>
>
@@ -533,7 +554,9 @@ export type Config<
readonly CreateConnectorFn[] = readonly CreateConnectorFn[],
> = {
readonly chains: chains
- readonly connectors: readonly Connector[]
+ readonly connectors: Readonly<{
+ [key in keyof connectorFns]: Connector
+ }>
readonly storage: Storage | null
readonly state: State
@@ -570,6 +593,7 @@ type Internal<
>,
> = {
readonly mipd: MipdStore | undefined
+ revalidate: () => Promise
readonly store: Mutate, [['zustand/persist', any]]>
readonly ssr: boolean
readonly syncConnectedChain: boolean
diff --git a/packages/core/src/createStorage.test-d.ts b/packages/core/src/createStorage.test-d.ts
index 6bb4c7f300..75cd0e7492 100644
--- a/packages/core/src/createStorage.test-d.ts
+++ b/packages/core/src/createStorage.test-d.ts
@@ -1,7 +1,6 @@
import { expectTypeOf, test } from 'vitest'
-import { createStorage } from './createStorage.js'
-
import type { Connection } from './createConfig.js'
+import { createStorage } from './createStorage.js'
test('getItem', () => {
const storage = createStorage({ storage: localStorage })
diff --git a/packages/core/src/createStorage.ts b/packages/core/src/createStorage.ts
index 8995ca3202..d86aef2aca 100644
--- a/packages/core/src/createStorage.ts
+++ b/packages/core/src/createStorage.ts
@@ -91,6 +91,7 @@ export const noopStorage = {
export function getDefaultStorage() {
const storage = (() => {
+ // biome-ignore lint/complexity/useOptionalChain: _
if (typeof window !== 'undefined' && window.localStorage)
return window.localStorage
return noopStorage
diff --git a/packages/core/src/experimental/actions/getCapabilities.ts b/packages/core/src/experimental/actions/getCapabilities.ts
deleted file mode 100644
index 095451081b..0000000000
--- a/packages/core/src/experimental/actions/getCapabilities.ts
+++ /dev/null
@@ -1,28 +0,0 @@
-import type { Account } from 'viem'
-import {
- type GetCapabilitiesErrorType as viem_GetCapabilitiesErrorType,
- type GetCapabilitiesParameters as viem_GetCapabilitiesParameters,
- type GetCapabilitiesReturnType as viem_GetCapabilitiesReturnType,
- getCapabilities as viem_getCapabilities,
-} from 'viem/experimental'
-
-import { getConnectorClient } from '../../actions/getConnectorClient.js'
-import type { Config } from '../../createConfig.js'
-import type { ConnectorParameter } from '../../types/properties.js'
-
-export type GetCapabilitiesParameters = viem_GetCapabilitiesParameters &
- ConnectorParameter
-
-export type GetCapabilitiesReturnType = viem_GetCapabilitiesReturnType
-
-export type GetCapabilitiesErrorType = viem_GetCapabilitiesErrorType
-
-/** https://wagmi.sh/core/api/actions/getCapabilities */
-export async function getCapabilities(
- config: config,
- parameters: GetCapabilitiesParameters = {},
-): Promise {
- const { account, connector } = parameters
- const client = await getConnectorClient(config, { account, connector })
- return viem_getCapabilities(client as any, { account: account as Account })
-}
diff --git a/packages/core/src/experimental/actions/writeContracts.test.ts b/packages/core/src/experimental/actions/writeContracts.test.ts
deleted file mode 100644
index 0f9b1c4211..0000000000
--- a/packages/core/src/experimental/actions/writeContracts.test.ts
+++ /dev/null
@@ -1,95 +0,0 @@
-import { abi, address, config } from '@wagmi/test'
-import { expect, test } from 'vitest'
-
-import { connect } from '../../actions/connect.js'
-import { disconnect } from '../../actions/disconnect.js'
-import { writeContracts } from './writeContracts.js'
-
-const connector = config.connectors[0]!
-
-test('default', async () => {
- await connect(config, { connector })
- await expect(
- writeContracts(config, {
- contracts: [
- {
- abi: abi.wagmiMintExample,
- address: address.wagmiMintExample,
- functionName: 'mint',
- },
- {
- abi: abi.wagmiMintExample,
- address: address.wagmiMintExample,
- functionName: 'mint',
- },
- {
- abi: abi.wagmiMintExample,
- address: address.wagmiMintExample,
- functionName: 'mint',
- },
- ],
- }),
- ).resolves.toMatchInlineSnapshot(
- `"0x8913636bd97cf4bcc0a6343c730905a27ead0f7480ff82190072e916439eb212"`,
- )
- await disconnect(config, { connector })
-})
-
-test('behavior: not connected', async () => {
- await expect(
- writeContracts(config, {
- contracts: [
- {
- abi: abi.wagmiMintExample,
- address: address.wagmiMintExample,
- functionName: 'mint',
- },
- {
- abi: abi.wagmiMintExample,
- address: address.wagmiMintExample,
- functionName: 'mint',
- },
- {
- abi: abi.wagmiMintExample,
- address: address.wagmiMintExample,
- functionName: 'mint',
- },
- ],
- }),
- ).rejects.toThrowErrorMatchingInlineSnapshot(`
- [ConnectorNotConnectedError: Connector not connected.
-
- Version: @wagmi/core@x.y.z]
- `)
-})
-
-test('behavior: account does not exist on connector', async () => {
- await connect(config, { connector })
- await expect(
- writeContracts(config, {
- account: '0xA0Cf798816D4b9b9866b5330EEa46a18382f251e',
- contracts: [
- {
- abi: abi.wagmiMintExample,
- address: address.wagmiMintExample,
- functionName: 'mint',
- },
- {
- abi: abi.wagmiMintExample,
- address: address.wagmiMintExample,
- functionName: 'mint',
- },
- {
- abi: abi.wagmiMintExample,
- address: address.wagmiMintExample,
- functionName: 'mint',
- },
- ],
- }),
- ).rejects.toThrowErrorMatchingInlineSnapshot(`
- [ConnectorAccountNotFoundError: Account "0xA0Cf798816D4b9b9866b5330EEa46a18382f251e" not found for connector "Mock Connector".
-
- Version: @wagmi/core@x.y.z]
- `)
- await disconnect(config, { connector })
-})
diff --git a/packages/core/src/experimental/actions/writeContracts.ts b/packages/core/src/experimental/actions/writeContracts.ts
deleted file mode 100644
index 06e6687592..0000000000
--- a/packages/core/src/experimental/actions/writeContracts.ts
+++ /dev/null
@@ -1,78 +0,0 @@
-import type { Account, Chain, ContractFunctionParameters } from 'viem'
-import {
- type WriteContractsErrorType as viem_WriteContractsErrorType,
- type WriteContractsParameters as viem_WriteContractsParameters,
- type WriteContractsReturnType as viem_WriteContractsReturnType,
- writeContracts as viem_writeContracts,
-} from 'viem/experimental'
-
-import {
- type GetConnectorClientErrorType,
- getConnectorClient,
-} from '../../actions/getConnectorClient.js'
-import type { Config } from '../../createConfig.js'
-import type { BaseErrorType, ErrorType } from '../../errors/base.js'
-import type { SelectChains } from '../../types/chain.js'
-import type {
- ChainIdParameter,
- ConnectorParameter,
-} from '../../types/properties.js'
-import type { Compute } from '../../types/utils.js'
-
-export type WriteContractsParameters<
- contracts extends readonly unknown[] = readonly ContractFunctionParameters[],
- config extends Config = Config,
- chainId extends
- config['chains'][number]['id'] = config['chains'][number]['id'],
- ///
- chains extends readonly Chain[] = SelectChains,
-> = {
- [key in keyof chains]: Compute<
- Omit<
- viem_WriteContractsParameters<
- contracts,
- chains[key],
- Account,
- chains[key]
- >,
- 'chain'
- > &
- ChainIdParameter &
- ConnectorParameter
- >
-}[number]
-
-export type WriteContractsReturnType = viem_WriteContractsReturnType
-
-export type WriteContractsErrorType =
- // getConnectorClient()
- | GetConnectorClientErrorType
- // base
- | BaseErrorType
- | ErrorType
- // viem
- | viem_WriteContractsErrorType
-
-/** https://wagmi.sh/core/api/actions/writeContracts */
-export async function writeContracts<
- const contracts extends readonly unknown[],
- config extends Config,
- chainId extends config['chains'][number]['id'],
->(
- config: config,
- parameters: WriteContractsParameters,
-): Promise {
- const { account, chainId, connector, ...rest } = parameters
-
- const client = await getConnectorClient(config, {
- account,
- chainId,
- connector,
- })
-
- return viem_writeContracts(client, {
- ...(rest as any),
- ...(account ? { account } : {}),
- chain: chainId ? { id: chainId } : undefined,
- })
-}
diff --git a/packages/core/src/experimental/query/getCallsStatus.ts b/packages/core/src/experimental/query/getCallsStatus.ts
deleted file mode 100644
index e520701ad3..0000000000
--- a/packages/core/src/experimental/query/getCallsStatus.ts
+++ /dev/null
@@ -1,50 +0,0 @@
-import type { QueryOptions } from '@tanstack/query-core'
-
-import type { Config } from '../../createConfig.js'
-import { ConnectorNotConnectedError } from '../../errors/config.js'
-import { filterQueryOptions } from '../../query/utils.js'
-import type { ScopeKeyParameter } from '../../types/properties.js'
-import type { Compute } from '../../types/utils.js'
-import {
- type GetCallsStatusErrorType,
- type GetCallsStatusParameters,
- type GetCallsStatusReturnType,
- getCallsStatus,
-} from '../actions/getCallsStatus.js'
-
-export type GetCallsStatusOptions = Compute<
- GetCallsStatusParameters & ScopeKeyParameter
->
-
-export function getCallsStatusQueryOptions(
- config: config,
- options: GetCallsStatusOptions,
-) {
- return {
- async queryFn({ queryKey }) {
- const { scopeKey: _, ...parameters } = queryKey[1]
- const status = await getCallsStatus(config, parameters)
- return status
- },
- queryKey: getCallsStatusQueryKey(options),
- retry(failureCount, error) {
- if (error instanceof ConnectorNotConnectedError) return false
- return failureCount < 3
- },
- } as const satisfies QueryOptions<
- GetCallsStatusQueryFnData,
- GetCallsStatusErrorType,
- GetCallsStatusData,
- GetCallsStatusQueryKey
- >
-}
-
-export type GetCallsStatusQueryFnData = GetCallsStatusReturnType
-
-export type GetCallsStatusData = GetCallsStatusQueryFnData
-
-export function getCallsStatusQueryKey(options: GetCallsStatusOptions) {
- return ['callsStatus', filterQueryOptions(options)] as const
-}
-
-export type GetCallsStatusQueryKey = ReturnType
diff --git a/packages/core/src/experimental/query/getCapabilities.ts b/packages/core/src/experimental/query/getCapabilities.ts
deleted file mode 100644
index 4d21e780db..0000000000
--- a/packages/core/src/experimental/query/getCapabilities.ts
+++ /dev/null
@@ -1,50 +0,0 @@
-import type { QueryOptions } from '@tanstack/query-core'
-
-import type { Config } from '../../createConfig.js'
-import { ConnectorNotConnectedError } from '../../errors/config.js'
-import { filterQueryOptions } from '../../query/utils.js'
-import type { ScopeKeyParameter } from '../../types/properties.js'
-import type { Compute, ExactPartial } from '../../types/utils.js'
-import {
- type GetCapabilitiesErrorType,
- type GetCapabilitiesParameters,
- type GetCapabilitiesReturnType,
- getCapabilities,
-} from '../actions/getCapabilities.js'
-
-export type GetCapabilitiesOptions = Compute<
- ExactPartial